openclover / clover

This repository contains source code of OpenClover Core as well as its integrations: Clover-for-Ant, Clover-for-Eclipse and Clover-for-IDEA plugins. Sources are licensed under Apache 2.0 license.
Other
61 stars 16 forks source link

Incorrect instrumentation of class constructors in test classes #249

Open davidhoyt opened 6 months ago

davidhoyt commented 6 months ago

For the following test source:

public class InnerStaticTest {
  private static abstract class MyInnerClass {
      final String value;

      public MyInnerClass(final String value) {
          super();
          this.value = value;
      }
  }
}

This is resulting in the following instrumented test code:

/* $$ This file has been instrumented by Clover 4.5.2#20240131180750 $$ */
public class InnerStaticTest {
    public static com_atlassian_clover.CoverageRecorder __CLR4_5_200ltourofh=com_atlassian_clover.Clover.getRecorder("...",
            1710277001802L,
            0L,
            3,
            new com_atlassian_clover.CloverProfile[] {},
            new java.lang.String[]{
                    "clover.distributed.coverage",null
        }
    );

    public static final com_atlassian_clover.TestNameSniffer __CLR4_5_2_TEST_NAME_SNIFFER=com_atlassian_clover.TestNameSniffer.NULL_INSTANCE;
    private static abstract class MyInnerClass {
      final String value;

      public MyInnerClass(final String value) {
          __CLR4_5_200ltourofh.globalSliceStart(getClass().getName(), 0);
          int $CLV_p$ = 0;
          java.lang.Throwable $CLV_t$ = null;
          try {
              __CLR4_5_2baad260(value);
              $CLV_p$ = 1;
          } catch (java.lang.Throwable $CLV_t2$) {
              if ($CLV_p$ == 0 && $CLV_t$ == null) {
                  $CLV_t$ = $CLV_t2$;
              }
              __CLR4_5_200ltourofh.rethrow($CLV_t2$);
          } finally {
              __CLR4_5_200ltourofh.globalSliceEnd(getClass().getName(), "InnerStaticTest.MyInnerClass.MyInnerClass", __CLR4_5_2_TEST_NAME_SNIFFER.getTestName(), 0, $CLV_p$, $CLV_t$);
          }
      }

      private __CLR4_5_2baad260(final String value) {
          super();
          __CLR4_5_200ltourofh.inc(1);
          __CLR4_5_200ltourofh.inc(0);
          __CLR4_5_200ltourofh.inc(2);
          this.value = value;
      }
    }
}

It's trying to call a super class constructor from within an injected method (and the constructor itself is now no longer calling its super class constructor).

This results in build errors.

Root cause

In this particular class the code instrumenter treated the constructor of a test class like a regular method and attempted to add per-test instrumentation, rewriting the constructor code to a helper method.

Workaround

Configure proper test patterns for the test detector. For example, to omit all inner classes, or to instrument only methods having given name or annotation. For example:

References: