Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore synthetic class created for switch on enum #660

Closed
pbludov opened this issue Mar 16, 2018 · 3 comments
Closed

Ignore synthetic class created for switch on enum #660

pbludov opened this issue Mar 16, 2018 · 3 comments

Comments

@pbludov
Copy link

pbludov commented Mar 16, 2018

Steps to reproduce

JaCoCo version: 0.8.0
Operating system: Ubuntu 16.04/MacOSX 10.12
Tool integration: Maven

TestClass.java

public class TestClass {

    public enum Enum {

        TRUE,
        FALSE,

    }

    public void checkEnum(final Enum value) {
        switch (value) {
            case TRUE:
                break;
            case FALSE:
            default:
                break;
        }
    }

}

TestClassTest.java

import org.junit.Before;
import org.junit.Test;

public class TestClassTest {

    private TestClass testClass;

    @Before
    public void setUp() {
        testClass = new TestClass();
    }

    @Test
    public void testEnum() {
        testClass.checkEnum(TestClass.Enum.TRUE);
        testClass.checkEnum(TestClass.Enum.FALSE);
    }

}

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>test</groupId>
    <artifactId>jacoco</artifactId>
    <packaging>jar</packaging>
    <version>0.1</version>
    <name>Test Coverage with Jacoco</name>
    <build>
        <plugins>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.8.0</version>
                <executions>
                    <execution>
                        <id>unit-test</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>default-check</id>
                        <goals>
                            <goal>check</goal>
                        </goals>
                        <configuration>
                            <rules>
                                <rule>
                                    <element>CLASS</element>
                                    <limits>
                                        <limit>
                                            <counter>LINE</counter>
                                            <value>COVEREDRATIO</value>
                                            <minimum>1.00</minimum>
                                        </limit>
                                        <limit>
                                            <counter>BRANCH</counter>
                                            <value>COVEREDRATIO</value>
                                            <minimum>1.00</minimum>
                                        </limit>
                                    </limits>
                                </rule>
                            </rules>
                        </configuration>
                    </execution>
                    <execution>
                        <id>report</id>
                        <phase>test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.15</version>
                <configuration>
                    <argLine>${argLine}</argLine>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

Expected behaviour

Element Missed Instructions Cov. Missed Branches Cov. Missed Cxty Missed Lines Missed Methods Missed Classes
Total 100% 100% 0 6 0 7 0 5 0 3
TestClass.Enum   100%   n/a 0 2 0 3 0 2 0 1
TestClass   100%   100% 0 3 0 4 0 2 0 1

Actual behaviour

Element Missed Instructions Cov. Missed Branches Cov. Missed Cxty Missed Lines Missed Methods Missed Classes
Total 2 of 58 96% 0 of 2 100% 0 6 0 7 0 5 0 3
TestClass.new Object() {...}   89%   n/a 0 1 0 1 0 1 0 1
TestClass.Enum   100%   n/a 0 2 0 3 0 2 0 1
TestClass   100%   100% 0 3 0 4 0 2 0 1

Extra notes

The command mvn clean verify succeeded, the target level of 100% coverage is achieved.
Only the report says 'there is a missing line'

@marchof
Copy link
Member

marchof commented Mar 20, 2018

@pbludov What you see here is a synthetic class created by the compiler to implement a switch on values. This class should be filtered at all.

We're currently in the process of adding different filters. I add this to our list. Stay tuned.

@marchof marchof changed the title The report shows missed coverage for succeeded build Filter synthetic class created for switch in enum Mar 20, 2018
@marchof marchof changed the title Filter synthetic class created for switch in enum Ignore synthetic class created for switch in enum Mar 20, 2018
@marchof marchof changed the title Ignore synthetic class created for switch in enum Ignore synthetic class created for switch on enum Mar 20, 2018
@Godin Godin self-assigned this Mar 30, 2018
@Godin
Copy link
Member

Godin commented Mar 30, 2018

@marchof do we really want to detect solely

synthetic class created for switch on enum

? To me seems that this will require examination of bytecode pattern in static initialization method of such classes, or ability for filters to detect presence of synthetic field that holds "switch map", while much simpler to detect any synthetic classes.

The only known to me examples of synthetic classes are this one for enums and an empty one which is created in case

class Example {
  class C {
    private C() {
    }
  }

  void fun() {
    new C();
  }
}

to give an access to private constructor:

void fun();
  descriptor: ()V
  flags:
  Code:
    stack=4, locals=1, args_size=1
       0: new           #2                  // class Example$C
       3: dup
       4: aload_0
       5: aconst_null
       6: invokespecial #3                  // Method Example$C."<init>":(LExample;LExample$1;)V
       9: pop
      10: return
private Example$C(Example);
  descriptor: (LExample;)V
  flags: ACC_PRIVATE
  Code:
    stack=2, locals=2, args_size=2
       0: aload_0
       1: aload_1
       2: putfield      #2                  // Field this$0:LExample;
       5: aload_0
       6: invokespecial #3                  // Method java/lang/Object."<init>":()V
       9: return

Example$C(Example, Example$1);
  descriptor: (LExample;LExample$1;)V
  flags: ACC_SYNTHETIC
  Code:
    stack=2, locals=3, args_size=3
       0: aload_0
       1: aload_1
       2: invokespecial #1                  // Method "<init>":(LExample;)V
       5: return
class Example$1
  minor version: 0
  major version: 50
  flags: ACC_SUPER, ACC_SYNTHETIC

While we can do additional tests using big set of classes as before to be sure that those are the only cases, I don't think that this is necessary and strongly believe that we won't find anything else.

Also should be noted that in case of switch on enum javac 1.5.0_22 marks only field with map as synthetic, but not a class. However again I think that we can go ahead by simply filtering synthetic classes for the benefit of users of newer javac versions.

WDYT?

@marchof
Copy link
Member

marchof commented Mar 31, 2018

@Godin I fully agree. Let's filter all synthetic classes in a first step.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Status: Done
Development

No branches or pull requests

3 participants