Uploaded image for project: 'Clover'
  1. Clover
  2. CLOV-1339

The <testmethod name=".*> does not match constructors

    • Our product teams collect and evaluate feedback from a number of different sources. To learn more about how we use customer feedback in the planning process, check out our new feature policy.

      Problem:

      If you declare custom test detector, for instance:

      <clover-setup>
        <testsources dir="src/test/java">
          <testclass name=".*">
            <testmethod name=".*"/>
          </testclass>
        </testsources>
      </clover-setup>
      

      Then the test detector does not match constructors. As a consequence, a class like this:

      public class SomeException extends Exception {
        public SomeException(String s) { 
          super(s); 
        }
      } 
      

      will be treated as APPLICATION not as TEST code.

      Background reason:

      public boolean isMethodMatch(SourceContext sourceContext, MethodContext methodContext) {
              final MethodSignature signature = methodContext.getSignature();
              return methodMatches(signature.getName()) &&
                      methodAnnotationMatches(signature.getModifiers()) &&
                      methodReturnPatternMatches(signature.getReturnType()) &&
                      methodTagMatches(signature.getTags());
          }
      
      public boolean methodReturnPatternMatches(String methodReturnType) {
              return methodReturnType != null &&
                      (methodReturnTypePattern == null || methodReturnTypePattern.matcher(methodReturnType).matches());
          }
      

      The methodReturnType==null for constructors, thus constructor do not match the pattern.

      Solution:

      We could rewrite check like this:

      return methodReturnTypePattern == null ||
          (methodReturnType != null && methodReturnTypePattern.matcher(methodReturnType).matches());
      

      However, this would require entirely new handling of code instrumentation for constructors. The reason is that code would be currently rewritten like:

      public SomeException(String s) {
              __CLR3_1_12_100hjv4vvu6.R.globalSliceStart(getClass().getName(), 0);
              int $CLV_p$ = 0;
              java.lang.Throwable $CLV_t$ = null;
              try {
                  __CLR3_1_12_162c4pt0(s); // <<< ORIGINAL CONSTRUCTOR
                  $CLV_p$ = 1;
              } catch (java.lang.Throwable $CLV_t2$) {
                  if ($CLV_p$ == 0 && $CLV_t$ == null) {
                      $CLV_t$ = $CLV_t2$;
                  }
                  __CLR3_1_12_100hjv4vvu6.R.rethrow($CLV_t2$);
              } finally {
                  __CLR3_1_12_100hjv4vvu6.R.globalSliceEnd(getClass().getName(), "SomeException.SomeException", 0, $CLV_p$, $CLV_t$);
              }
          }
      
          private __CLR3_1_12_162c4pt0(String s) { // << COMPILATION FAILURE, MISSING RETURN TYPE
              super(s);
              __CLR3_1_12_100hjv4vvu6.R.inc(1);
              __CLR3_1_12_100hjv4vvu6.R.inc(0);
          }
      

      Problems:

      • call to super() must be first
      • we should not move constructor body into another method

            [CLOV-1339] The <testmethod name=".*> does not match constructors

            Katherine Yabut made changes -
            Workflow Original: JAC Suggestion Workflow [ 3341969 ] New: JAC Suggestion Workflow 3 [ 3584517 ]
            Status Original: RESOLVED [ 5 ] New: Closed [ 6 ]
            Michael Andreacchio made changes -
            Workflow Original: New Clover Workflow [ 897645 ] New: JAC Suggestion Workflow [ 3341969 ]
            Issue Type Original: Improvement [ 4 ] New: Suggestion [ 10000 ]
            Status Original: Closed [ 6 ] New: Resolved [ 5 ]
            Michael Andreacchio made changes -
            Resolution New: Won't Fix [ 2 ]
            Status Original: Open [ 1 ] New: Closed [ 6 ]
            Marek Parfianowicz made changes -
            Assignee Original: Marek Parfianowicz [ mparfianowicz ]
            Piotr Swiecicki made changes -
            Workflow Original: Clover Workflow [ 895408 ] New: New Clover Workflow [ 897645 ]
            Piotr Swiecicki made changes -
            Workflow Original: reviewflow [ 548581 ] New: Clover Workflow [ 895408 ]
            Marek Parfianowicz made changes -
            Fix Version/s New: someday [ 23593 ]
            Marek Parfianowicz made changes -
            Description Original: *Problem:*

            If you declare custom test detector, for instance:

            {code:xml}
            <clover-setup>
              <testsources dir="src/test/java">
                <testclass name=".*">
                  <testmethod name=".*"/>
                </testclass>
              </testsources>
            </clover-setup>
            {code}

            Then the test detector does not match constructors. As a consequence, a class like this:

            {code:java}
            public class SomeException extends Exception {
              public SomeException(String s) {
                super(s);
              }
            }
            {code}

            will be treated as APPLICATION not as TEST code.

            *Background reason:*

            {code:java}
            public boolean isMethodMatch(SourceContext sourceContext, MethodContext methodContext) {
                    final MethodSignature signature = methodContext.getSignature();
                    return methodMatches(signature.getName()) &&
                            methodAnnotationMatches(signature.getModifiers()) &&
                            methodReturnPatternMatches(signature.getReturnType()) &&
                            methodTagMatches(signature.getTags());
                }

            public boolean methodReturnPatternMatches(String methodReturnType) {
                    return methodReturnType != null &&
                            (methodReturnTypePattern == null || methodReturnTypePattern.matcher(methodReturnType).matches());
                }
            {code}

            The methodReturnType==null for constructors, thus constructor do not match the pattern.

            *Solution:*

            We could rewrite check like this:

            {code:java}
            return methodReturnTypePattern == null ||
                (methodReturnType != null && methodReturnTypePattern.matcher(methodReturnType).matches());
            {code}

            However, this would require entirely new handling of code instrumentation for constructors. The reason is that code would be currently rewritten like:

            {code:java}
            public SomeException(String s) {
                    __CLR3_1_12_100hjv4vvu6.R.globalSliceStart(getClass().getName(), 0);
                    int $CLV_p$ = 0;
                    java.lang.Throwable $CLV_t$ = null;
                    try {
                        __CLR3_1_12_162c4pt0(s); // <<< ORIGINAL CONSTRUCTOR
                        $CLV_p$ = 1;
                    } catch (java.lang.Throwable $CLV_t2$) {
                        if ($CLV_p$ == 0 && $CLV_t$ == null) {
                            $CLV_t$ = $CLV_t2$;
                        }
                        __CLR3_1_12_100hjv4vvu6.R.rethrow($CLV_t2$);
                    } finally {
                        __CLR3_1_12_100hjv4vvu6.R.globalSliceEnd(getClass().getName(), "SomeException.SomeException", 0, $CLV_p$, $CLV_t$);
                    }
                }

                private __CLR3_1_12_162c4pt0(String s) { // << COMPILATION FAILURE, MISSING RETURN TYPE
                    super(s);
                    __CLR3_1_12_100hjv4vvu6.R.inc(1);
                    __CLR3_1_12_100hjv4vvu6.R.inc(0);
                }
            {code}
            New: *Problem:*

            If you declare custom test detector, for instance:

            {code:xml}
            <clover-setup>
              <testsources dir="src/test/java">
                <testclass name=".*">
                  <testmethod name=".*"/>
                </testclass>
              </testsources>
            </clover-setup>
            {code}

            Then the test detector does not match constructors. As a consequence, a class like this:

            {code:java}
            public class SomeException extends Exception {
              public SomeException(String s) {
                super(s);
              }
            }
            {code}

            will be treated as APPLICATION not as TEST code.

            *Background reason:*

            {code:java}
            public boolean isMethodMatch(SourceContext sourceContext, MethodContext methodContext) {
                    final MethodSignature signature = methodContext.getSignature();
                    return methodMatches(signature.getName()) &&
                            methodAnnotationMatches(signature.getModifiers()) &&
                            methodReturnPatternMatches(signature.getReturnType()) &&
                            methodTagMatches(signature.getTags());
                }

            public boolean methodReturnPatternMatches(String methodReturnType) {
                    return methodReturnType != null &&
                            (methodReturnTypePattern == null || methodReturnTypePattern.matcher(methodReturnType).matches());
                }
            {code}

            The methodReturnType==null for constructors, thus constructor do not match the pattern.

            *Solution:*

            We could rewrite check like this:

            {code:java}
            return methodReturnTypePattern == null ||
                (methodReturnType != null && methodReturnTypePattern.matcher(methodReturnType).matches());
            {code}

            However, this would require entirely new handling of code instrumentation for constructors. The reason is that code would be currently rewritten like:

            {code:java}
            public SomeException(String s) {
                    __CLR3_1_12_100hjv4vvu6.R.globalSliceStart(getClass().getName(), 0);
                    int $CLV_p$ = 0;
                    java.lang.Throwable $CLV_t$ = null;
                    try {
                        __CLR3_1_12_162c4pt0(s); // <<< ORIGINAL CONSTRUCTOR
                        $CLV_p$ = 1;
                    } catch (java.lang.Throwable $CLV_t2$) {
                        if ($CLV_p$ == 0 && $CLV_t$ == null) {
                            $CLV_t$ = $CLV_t2$;
                        }
                        __CLR3_1_12_100hjv4vvu6.R.rethrow($CLV_t2$);
                    } finally {
                        __CLR3_1_12_100hjv4vvu6.R.globalSliceEnd(getClass().getName(), "SomeException.SomeException", 0, $CLV_p$, $CLV_t$);
                    }
                }

                private __CLR3_1_12_162c4pt0(String s) { // << COMPILATION FAILURE, MISSING RETURN TYPE
                    super(s);
                    __CLR3_1_12_100hjv4vvu6.R.inc(1);
                    __CLR3_1_12_100hjv4vvu6.R.inc(0);
                }
            {code}

            Problems:
             * call to super() must be first
             * we should not move constructor body into another method
            Marek Parfianowicz made changes -
            Description Original: *Problem:*

            If you declare custom test detector, for instance:

            {code:xml}
            <clover-setup>
              <testsources dir="src/test/java">
                <testclass name=".*">
                  <testmethod name=".*"/>
                </testclass>
              </testsources>
            </clover-setup>
            {code}

            Then the test detector does not match constructors. As a consequence, a class like this:

            {code:java}
            public class SomeException extends Exception {
              public SomeException(String s) {
                super(s);
              }
            }
            {code}

            will be treated as APPLICATION not as TEST code.

            *Background reason:*

            {code:java}
            public boolean isMethodMatch(SourceContext sourceContext, MethodContext methodContext) {
                    final MethodSignature signature = methodContext.getSignature();
                    return methodMatches(signature.getName()) &&
                            methodAnnotationMatches(signature.getModifiers()) &&
                            methodReturnPatternMatches(signature.getReturnType()) &&
                            methodTagMatches(signature.getTags());
                }

            public boolean methodReturnPatternMatches(String methodReturnType) {
                    return methodReturnType != null &&
                            (methodReturnTypePattern == null || methodReturnTypePattern.matcher(methodReturnType).matches());
                }
            {code}

            The methodReturnType==null for constructors, thus constructor do not match the pattern.

            *Solution:*

            We could rewrite check like this:

            {code:java}
            return methodReturnTypePattern == null ||
                (methodReturnType != null && methodReturnTypePattern.matcher(methodReturnType).matches());
            {code}

            However, this would require entirely new handling of code instrumentation for constructors. The reason is that code would be currently rewritten like:

            {code:java}
            public NoStateChangeException(String s) {
                    __CLR3_1_12_100hjv4vvu6.R.globalSliceStart(getClass().getName(), 0);
                    int $CLV_p$ = 0;
                    java.lang.Throwable $CLV_t$ = null;
                    try {
                        __CLR3_1_12_162c4pt0(s); // <<< ORGININAL CONSTRUCTOR
                        $CLV_p$ = 1;
                    } catch (java.lang.Throwable $CLV_t2$) {
                        if ($CLV_p$ == 0 && $CLV_t$ == null) {
                            $CLV_t$ = $CLV_t2$;
                        }
                        __CLR3_1_12_100hjv4vvu6.R.rethrow($CLV_t2$);
                    } finally {
                        __CLR3_1_12_100hjv4vvu6.R.globalSliceEnd(getClass().getName(), "NoStateChangeException.NoStateChangeException", 0, $CLV_p$, $CLV_t$);
                    }
                }

                private __CLR3_1_12_162c4pt0(String s) { // << COMPILATION FAILURE, MISSING RETURN TYPE
                    super(s);
                    __CLR3_1_12_100hjv4vvu6.R.inc(1);
                    __CLR3_1_12_100hjv4vvu6.R.inc(0);
                }
            {code}
            New: *Problem:*

            If you declare custom test detector, for instance:

            {code:xml}
            <clover-setup>
              <testsources dir="src/test/java">
                <testclass name=".*">
                  <testmethod name=".*"/>
                </testclass>
              </testsources>
            </clover-setup>
            {code}

            Then the test detector does not match constructors. As a consequence, a class like this:

            {code:java}
            public class SomeException extends Exception {
              public SomeException(String s) {
                super(s);
              }
            }
            {code}

            will be treated as APPLICATION not as TEST code.

            *Background reason:*

            {code:java}
            public boolean isMethodMatch(SourceContext sourceContext, MethodContext methodContext) {
                    final MethodSignature signature = methodContext.getSignature();
                    return methodMatches(signature.getName()) &&
                            methodAnnotationMatches(signature.getModifiers()) &&
                            methodReturnPatternMatches(signature.getReturnType()) &&
                            methodTagMatches(signature.getTags());
                }

            public boolean methodReturnPatternMatches(String methodReturnType) {
                    return methodReturnType != null &&
                            (methodReturnTypePattern == null || methodReturnTypePattern.matcher(methodReturnType).matches());
                }
            {code}

            The methodReturnType==null for constructors, thus constructor do not match the pattern.

            *Solution:*

            We could rewrite check like this:

            {code:java}
            return methodReturnTypePattern == null ||
                (methodReturnType != null && methodReturnTypePattern.matcher(methodReturnType).matches());
            {code}

            However, this would require entirely new handling of code instrumentation for constructors. The reason is that code would be currently rewritten like:

            {code:java}
            public SomeException(String s) {
                    __CLR3_1_12_100hjv4vvu6.R.globalSliceStart(getClass().getName(), 0);
                    int $CLV_p$ = 0;
                    java.lang.Throwable $CLV_t$ = null;
                    try {
                        __CLR3_1_12_162c4pt0(s); // <<< ORIGINAL CONSTRUCTOR
                        $CLV_p$ = 1;
                    } catch (java.lang.Throwable $CLV_t2$) {
                        if ($CLV_p$ == 0 && $CLV_t$ == null) {
                            $CLV_t$ = $CLV_t2$;
                        }
                        __CLR3_1_12_100hjv4vvu6.R.rethrow($CLV_t2$);
                    } finally {
                        __CLR3_1_12_100hjv4vvu6.R.globalSliceEnd(getClass().getName(), "SomeException.SomeException", 0, $CLV_p$, $CLV_t$);
                    }
                }

                private __CLR3_1_12_162c4pt0(String s) { // << COMPILATION FAILURE, MISSING RETURN TYPE
                    super(s);
                    __CLR3_1_12_100hjv4vvu6.R.inc(1);
                    __CLR3_1_12_100hjv4vvu6.R.inc(0);
                }
            {code}
            Marek Parfianowicz created issue -

              Unassigned Unassigned
              mparfianowicz Marek Parfianowicz
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated:
                Resolved: