[ 
https://issues.apache.org/jira/browse/GROOVY-10878?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17650924#comment-17650924
 ] 

Eric Milles commented on GROOVY-10878:
--------------------------------------

I think the uncovered instructions are here after {{athrow}} of the assert 
error.  I should be able to see where these are being added.  However, 4.0.7 RC 
is out for evaluation.  If you want this addressed, you'll need to open a new 
ticket with 4.0.7 as the affected release.
{code}
    47  nop
    48  nop
    49  athrow
{code}

{code:groovy}
@groovy.transform.CompileStatic
String asString(obj) {
  assert obj != null
  obj.toString()
}
{code}

{code}
  // Method descriptor #56 (Ljava/lang/Object;)Ljava/lang/String;
  // Stack: 4, Locals: 3
  public java.lang.String asString(java.lang.Object obj);
     0  new org.codehaus.groovy.runtime.powerassert.ValueRecorder [59]
     3  dup
     4  invokespecial org.codehaus.groovy.runtime.powerassert.ValueRecorder() 
[60]
     7  astore_2
     8  aload_1 [obj]
     9  dup
    10  aload_2
    11  swap
    12  ldc <Integer 8> [61]
    14  invokevirtual 
org.codehaus.groovy.runtime.powerassert.ValueRecorder.record(java.lang.Object, 
int) : java.lang.Object [65]
    17  pop
    18  ifnull 25
    21  iconst_1
    22  goto 26
    25  iconst_0
    26  ifeq 36
    29  aload_2
    30  invokevirtual 
org.codehaus.groovy.runtime.powerassert.ValueRecorder.clear() : void [68]
    33  goto 55
    36  ldc <String "assert obj != null"> [70]
    38  aload_2
    39  invokestatic 
org.codehaus.groovy.runtime.powerassert.AssertionRenderer.render(java.lang.String,
 org.codehaus.groovy.runtime.powerassert.ValueRecorder) : java.lang.String [76]
    42  aconst_null
    43  invokestatic 
org.codehaus.groovy.runtime.InvokerHelper.createAssertError(java.lang.Object, 
java.lang.Object) : java.lang.AssertionError [80]
    46  athrow
    47  nop
    48  nop
    49  athrow
    50  aload_2
    51  invokevirtual 
org.codehaus.groovy.runtime.powerassert.ValueRecorder.clear() : void [68]
    54  athrow
    55  aload_1 [obj]
    56  invokestatic 
org.codehaus.groovy.runtime.DefaultGroovyMethods.toString(java.lang.Object) : 
java.lang.String [85]
    59  areturn
      Exception Table:
        [pc: 8, pc: 47] -> 50 when : any
      Line numbers:
        [pc: 0, line: 3]
        [pc: 55, line: 4]
      Local variable table:
        [pc: 0, pc: 60] local: this index: 0 type: Scratch
        [pc: 0, pc: 60] local: obj index: 1 type: java.lang.Object
      Stack map table: number of frames 6
        [pc: 25, append: 
{org.codehaus.groovy.runtime.powerassert.ValueRecorder}]
        [pc: 26, same_locals_1_stack_item, stack: {int}]
        [pc: 36, same]
        [pc: 47, full, stack: {java.lang.Throwable}, locals: {}]
        [pc: 50, full, stack: {java.lang.Throwable}, locals: {Scratch, 
java.lang.Object, org.codehaus.groovy.runtime.powerassert.ValueRecorder}]
        [pc: 55, same]
{code}

> Improve JaCoCo's branch code coverage of a Groovy assert statement
> ------------------------------------------------------------------
>
>                 Key: GROOVY-10878
>                 URL: https://issues.apache.org/jira/browse/GROOVY-10878
>             Project: Groovy
>          Issue Type: Improvement
>    Affects Versions: 4.0.6
>            Reporter: Damir Murat
>            Assignee: Eric Milles
>            Priority: Major
>             Fix For: 4.0.7
>
>         Attachments: screenshot-1.png
>
>
> At the moment, there is no way to have full branch coverage for Groovy 
> {{assert}} statements. In a larger project, this is very distractive when 
> trying to find the pieces of actual logic that should be better covered with 
> tests. I believe a slight change in {{assert}} statement code generation can 
> significantly improve the situation.
> JaCoCo has long-standing issues with covering calls of methods that throw 
> exceptions. When such methods are called inside of, {{if/else}} branches, for 
> example, the result is partial coverage reported for those branches.
> However, there is a JaCoCo idiom 
> ([https://github.com/jacoco/jacoco/issues/370#issuecomment-267854179|https://github.com/jacoco/jacoco/issues/370#issuecomment-267854179])
>  that can be used to avoid uncovered code in those cases. The basic idea is 
> to create and return an exception from a called method and throw that 
> exception from a caller, like in:
> {code:java}
> void fail() {
>   throw create();
> }
> RuntimeException create() {
>   return new RuntimeException();
> }
> {code}
> How this relates to the Groovy {{assert}} statement? For example, for a 
> simple {{assert}} statement like
> {code:java}
> assert firstName != null
> {code}
> Groovy generates something like
> {code:java}
> ValueRecorder var1 = new ValueRecorder();
> try {
>   String var10000 = this.firstName;
>   var1.record(var10000, 8);
>   var1.record(var10000, 8);
>   if (var10000 != null) {
>     var1.clear();
>   } else {
>     ScriptBytecodeAdapter.assertFailed(AssertionRenderer.render("assert 
> firstName != null", var1), (Object)null);
>   }
> } catch (Throwable var3) {
>   var1.clear();
>   throw var3;
> }
> {code}
> The problem with generated code is a
> {code:java}
> ScriptBytecodeAdapter.assertFailed(AssertionRenderer.render("assert firstName 
> != null", var1), (Object)null);
> {code}
> method call. Inside that method, an exception is created and thrown. Since 
> JaCoCo cannot cover that line completely, the branch
> {code:java}
> if (var10000 != null)
> {code}
> will be reported as partially covered.
> To avoid those issues, {{ScriptBytecodeAdapter.assertFailed()}} can be 
> adapted (or a new method can be introduced like in the example below) to 
> return the exception instead of throwing it. And then, the calling generated 
> code can throw that returned exception:
> {code:java}
> try {
>   ...
>   if (var10000 != null) {
>     ...
>   } else {
>     Throwable throwable = 
> ScriptBytecodeAdapter.createAssertionError(AssertionRenderer.render("assert 
> firstName != null", var1), (Object)null);
>     throw throwable
>   }
> } catch (Throwable var3) {
>   ...
> }
> {code}
> I have a small project demonstrating the issue and a possible solution here: 
> [https://github.com/dmurat/groovy-assert-jacoco-coverage-problem|https://github.com/dmurat/groovy-assert-jacoco-coverage-problem|]
> Tnx



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to