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

Add filter for Java assert statement #1196

Merged
merged 5 commits into from Jun 10, 2021
Merged

Add filter for Java assert statement #1196

merged 5 commits into from Jun 10, 2021

Conversation

Godin
Copy link
Member

@Godin Godin commented Jun 5, 2021

For Example.java

//
class Example {

    void example(boolean b) {
        assert(b);
    }

    public static void main(String[] args) {
        new Example().example(true);
    }

}

execution of

javac Example.java
java -ea -javaagent:jacoco/lib/jacocoagent.jar Example
java -jar jacoco/lib/jacococli.jar report jacoco.exec --classfiles Example.class --sourcefiles . --html report

before this change produces

and after

@Godin Godin added this to the 0.8.8 milestone Jun 5, 2021
@Godin Godin self-assigned this Jun 5, 2021
@Godin Godin added this to Implementation in Current work items via automation Jun 5, 2021
@Godin Godin force-pushed the filter_assert branch 2 times, most recently from 83120a4 to ea6f39f Compare June 5, 2021 07:36
@Godin Godin marked this pull request as ready for review June 5, 2021 20:44
@Godin Godin moved this from Implementation to Review in Current work items Jun 5, 2021
@Godin Godin requested a review from marchof June 5, 2021 20:44
/**
* This target exercises assert statement.
*/
public class AssertTarget { // assertFullyCovered()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What instructions are left on this line? Shouldn't it be empty?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marchof we ignore only part of static initializer that corresponds to initialization of field $assertionsDisabled, so in this case there is also return with line number of class:

  static {};
    descriptor: ()V
    flags: (0x0008) ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: ldc           #7                  // class org/jacoco/core/test/validation/java5/targets/AssertTarget
         2: invokevirtual #8                  // Method java/lang/Class.desiredAssertionStatus:()Z
         5: ifne          12
         8: iconst_1
         9: goto          13
        12: iconst_0
        13: putstatic     #2                  // Field $assertionsDisabled:Z
        16: return
      LineNumberTable:
        line 20: 0

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether we should also ignore the return if there is no other code. Otherwise we have this line highlighted only if there is a assertion statement in this class.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also if I add a static initializer the return is accounted to that line and the highlighting of the class definition disappears. I think it is more consistent if we ignore the return statement if there is no other code:

static Object C = new Object();

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line highlighted only if there is a assertion statement

Also at least default constructor has line of class declaration and part of static initializer generated for enums.

if we ignore the return statement if there is no other code

This will also exclude line of explicitly written empty static initializer in class with assert statements:

//
class Example { // line 2
    static {
    } // line 4

    void example(boolean b) {
        assert(b);
    }
}
  Example();
    descriptor: ()V
    flags: (0x0000)
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 2: 0

  static {};
    descriptor: ()V
    flags: (0x0008) ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: ldc           #5                  // class Example
         2: invokevirtual #6                  // Method java/lang/Class.desiredAssertionStatus:()Z
         5: ifne          12
         8: iconst_1
         9: goto          13
        12: iconst_0
        13: putstatic     #2                  // Field $assertionsDisabled:Z
        16: return
      LineNumberTable:
        line 2: 0
        line 4: 16

I believe that our users are more concerned about branch that without this change is displayed on a line of class declaration. And not sure whether they will be concerned about just highlighting of this line or about absense of highlighting for explicitly written empty static initializers.

Should we then also for consistency also filter explicitly written empty static initializers in absence of assert statements? Is it worth it? I'm not against both, just wondering how deep this rabbit hole can go to not overlook something - wondering if there might be other cases that we currently overlooking?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, looks like we will end up with too many corner cases. We leave it like it is!

@marchof marchof merged commit 5d24b06 into master Jun 10, 2021
Current work items automation moved this from Review to Done Jun 10, 2021
@marchof marchof deleted the filter_assert branch June 10, 2021 08:45
@Godin Godin added this to To Do in Filtering via automation Jun 10, 2021
@Godin Godin moved this from To Do to Done in Filtering Jun 10, 2021
mirabilos added a commit to qvest-digital/maven-parent that referenced this pull request Apr 19, 2022
jacoco/jacoco#1063 (which
  jacoco/jacoco#613 and/or
  jacoco/jacoco#1196 were supposed to fix)
  is still open, so the code coverage is still off
• projectlombok/lombok.patcher#10
  latest lombok source not published
• maven-release-plugin 3.0.0 still not available, need to bump the
  date manually or force oneself to not care about reproducible builds
• antrun plugin, which we don’t use, uses insecure versions of ant
  by default; unsure if continuously bumping it will be worth the
  hassle? does anyone use any even?
• maven-release-plugin 2.5.3 also uses insecure jdom (3.x doesn’t
  but is still in early beta)
"Z");
nextIs(Opcodes.IFNE);
if (cursor != null) {
output.ignore(cursor, cursor);
Copy link

@morganga morganga Oct 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be ignoring the entire assert test here?
output.ignore(cursor, cursor) it's only ignoring the branch instruction, not the assert test.

I still get a "1 of 2 branches missed" for my assert statements. The only way to cover both branches is to run the test twice, once with assertions disabled, then again with assertions enabled, all in the same test suite.

How about output.ignore(cursor, ((JumpInsnNode) cursor).label);

I've tested the above code fragment and it marks the assert line as green, without complaining about 1 of 2 branches missed. (it also doesn't think the line has multiple branches either)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Filtering
  
Done
Development

Successfully merging this pull request may close these issues.

None yet

3 participants