aboutsummaryrefslogtreecommitdiff
path: root/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation
diff options
context:
space:
mode:
authorEvgeny Mandrikov <Godin@users.noreply.github.com>2018-07-21 22:47:34 +0200
committerGitHub <noreply@github.com>2018-07-21 22:47:34 +0200
commit88e67b3f121121161f29f15ab8c45e6fc7ecd6d4 (patch)
tree0eb5e7cc76a8cf440f3011daadbbd8a23a6acca1 /org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation
parent753d6532d56892d037ff7958ea30c9bc27f6e8e4 (diff)
downloadjacoco-88e67b3f121121161f29f15ab8c45e6fc7ecd6d4.tar.gz
Extract "validation" tests into separate modules (#711)
Diffstat (limited to 'org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation')
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/AnnotationInitializerTest.java47
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/BadCycleClassTest.java39
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/BooleanExpressionsTest.java79
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ClassFileVersionsTest.java195
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ClassInitializerTest.java44
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ControlStructuresTest.java137
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/CyclomaticComplexityTest.java280
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/EnumImplicitMethodsTest.java41
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ExceptionsTest.java132
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ExplicitInitialFrameTest.java34
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/FieldInitializationInTwoConstructorsTest.java38
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/FramesTest.java179
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ImplicitDefaultConstructorTest.java36
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ImplicitFieldInitializationTest.java38
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/InterfaceClassInitializerTest.java43
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/PrivateEmptyDefaultConstructorTest.java38
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ProbesBeforeSuperConstructorTest.java34
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ResizeInstructionsTest.java171
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/StructuredLockingTest.java202
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/AnnotationInitializer.java23
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/BadCycleClass.java44
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/EnumImplicitMethods.java48
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target01.java293
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target02.java120
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target03.java142
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target04.java33
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target05.java51
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target06.java25
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target07.java27
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target08.java31
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target09.java34
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target10.java33
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target11.java31
-rw-r--r--org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target12.java46
34 files changed, 2788 insertions, 0 deletions
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/AnnotationInitializerTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/AnnotationInitializerTest.java
new file mode 100644
index 00000000..60a38339
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/AnnotationInitializerTest.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.test.validation.targets.AnnotationInitializer;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test of initializer in annotations.
+ */
+public class AnnotationInitializerTest extends ValidationTestBase {
+
+ public AnnotationInitializerTest() {
+ super(AnnotationInitializer.class);
+ }
+
+ @Override
+ protected void run(Class<?> targetClass) throws Exception {
+ // Instrumentation should not add members,
+ // otherwise sun.reflect.annotation.AnnotationInvocationHandler
+ // can throw java.lang.annotation.AnnotationFormatError
+ assertEquals(1, targetClass.getDeclaredFields().length);
+ assertEquals(1, targetClass.getDeclaredMethods().length);
+
+ // Force initialization
+ targetClass.getField("CONST").get(null);
+ }
+
+ @Test
+ public void testCoverageResult() {
+ assertLine("const", ICounter.FULLY_COVERED);
+ assertLine("value", ICounter.EMPTY);
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/BadCycleClassTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/BadCycleClassTest.java
new file mode 100644
index 00000000..aa646ddf
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/BadCycleClassTest.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.test.validation.targets.BadCycleClass;
+import org.junit.Test;
+
+/**
+ * Test of "bad cycles" with classes.
+ */
+public class BadCycleClassTest extends ValidationTestBase {
+
+ public BadCycleClassTest() throws Exception {
+ super(BadCycleClass.class);
+ }
+
+ @Test
+ public void test() throws Exception {
+ assertLine("childinit", ICounter.FULLY_COVERED);
+ assertLine("childsomeMethod", ICounter.FULLY_COVERED);
+ assertLine("childclinit", ICounter.FULLY_COVERED);
+
+ // The cycle causes a constructor and instance method to be called
+ // before the static initializer of a class:
+ assertLogEvents("childinit", "childsomeMethod", "childclinit",
+ "childinit");
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/BooleanExpressionsTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/BooleanExpressionsTest.java
new file mode 100644
index 00000000..64dee474
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/BooleanExpressionsTest.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.test.validation.targets.Target02;
+import org.junit.Test;
+
+/**
+ * Tests of basic Java boolean expressions.
+ */
+public class BooleanExpressionsTest extends ValidationTestBase {
+
+ public BooleanExpressionsTest() {
+ super(Target02.class);
+ }
+
+ @Test
+ public void testCoverageResult() {
+
+ // 1. Boolean comparison result (one case)
+ assertLine("booleancmp1", ICounter.PARTLY_COVERED, 1, 1);
+
+ // 2. Boolean comparison result (both cases)
+ assertLine("booleancmp2", ICounter.FULLY_COVERED, 0, 2);
+
+ // 3. And
+ assertLine("andFF", ICounter.FULLY_COVERED, 1, 1);
+ assertLine("andFT", ICounter.FULLY_COVERED, 1, 1);
+ assertLine("andTF", ICounter.FULLY_COVERED, 1, 1);
+ assertLine("andTT", ICounter.FULLY_COVERED, 1, 1);
+
+ // 4. Conditional And
+ assertLine("conditionalandFF", ICounter.PARTLY_COVERED, 3, 1);
+ assertLine("conditionalandFT", ICounter.PARTLY_COVERED, 3, 1);
+ assertLine("conditionalandTF", ICounter.FULLY_COVERED, 2, 2);
+ assertLine("conditionalandTT", ICounter.FULLY_COVERED, 2, 2);
+
+ // 5. Or
+ assertLine("orFF", ICounter.FULLY_COVERED, 1, 1);
+ assertLine("orFT", ICounter.FULLY_COVERED, 1, 1);
+ assertLine("orTF", ICounter.FULLY_COVERED, 1, 1);
+ assertLine("orTT", ICounter.FULLY_COVERED, 1, 1);
+
+ // 6. Conditional Or
+ assertLine("conditionalorFF", ICounter.FULLY_COVERED, 2, 2);
+ assertLine("conditionalorFT", ICounter.FULLY_COVERED, 2, 2);
+ assertLine("conditionalorTF", ICounter.PARTLY_COVERED, 3, 1);
+ assertLine("conditionalorTT", ICounter.PARTLY_COVERED, 3, 1);
+
+ // 7. Exclusive Or
+ assertLine("xorFF", ICounter.FULLY_COVERED, 1, 1);
+ assertLine("xorFT", ICounter.FULLY_COVERED, 1, 1);
+ assertLine("xorTF", ICounter.FULLY_COVERED, 1, 1);
+ assertLine("xorTT", ICounter.FULLY_COVERED, 1, 1);
+
+ // 8. Conditional Operator
+ assertLine("condT", ICounter.PARTLY_COVERED, 1, 1);
+ assertLine("condF", ICounter.PARTLY_COVERED, 1, 1);
+
+ // 9. Not (one case)
+ assertLine("notT", ICounter.PARTLY_COVERED, 1, 1);
+ assertLine("notF", ICounter.PARTLY_COVERED, 1, 1);
+
+ // 10. Not (both cases)
+ assertLine("notTF", ICounter.FULLY_COVERED, 0, 2);
+
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ClassFileVersionsTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ClassFileVersionsTest.java
new file mode 100644
index 00000000..87d78a21
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ClassFileVersionsTest.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import static org.junit.Assert.assertEquals;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.ACC_SUPER;
+import static org.objectweb.asm.Opcodes.ALOAD;
+import static org.objectweb.asm.Opcodes.F_NEW;
+import static org.objectweb.asm.Opcodes.IFEQ;
+import static org.objectweb.asm.Opcodes.ILOAD;
+import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
+import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
+import static org.objectweb.asm.Opcodes.POP;
+import static org.objectweb.asm.Opcodes.RETURN;
+import static org.objectweb.asm.Opcodes.V1_1;
+import static org.objectweb.asm.Opcodes.V1_2;
+import static org.objectweb.asm.Opcodes.V1_3;
+import static org.objectweb.asm.Opcodes.V1_4;
+import static org.objectweb.asm.Opcodes.V1_5;
+import static org.objectweb.asm.Opcodes.V1_6;
+import static org.objectweb.asm.Opcodes.V1_7;
+import static org.objectweb.asm.Opcodes.V1_8;
+import static org.objectweb.asm.Opcodes.V9;
+
+import java.io.IOException;
+
+import org.jacoco.core.instr.Instrumenter;
+import org.jacoco.core.internal.BytecodeVersion;
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.jacoco.core.runtime.IRuntime;
+import org.jacoco.core.runtime.SystemPropertiesRuntime;
+import org.junit.Test;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * Test class inserted stackmap frames for different class file versions.
+ */
+public class ClassFileVersionsTest {
+
+ @Test
+ public void test_1_1() throws IOException {
+ testVersion(V1_1, false);
+ }
+
+ @Test
+ public void test_1_2() throws IOException {
+ testVersion(V1_2, false);
+ }
+
+ @Test
+ public void test_1_3() throws IOException {
+ testVersion(V1_3, false);
+ }
+
+ @Test
+ public void test_1_4() throws IOException {
+ testVersion(V1_4, false);
+ }
+
+ @Test
+ public void test_1_5() throws IOException {
+ testVersion(V1_5, false);
+ }
+
+ @Test
+ public void test_1_6() throws IOException {
+ testVersion(V1_6, true);
+ }
+
+ @Test
+ public void test_1_7() throws IOException {
+ testVersion(V1_7, true);
+ }
+
+ @Test
+ public void test_1_8() throws IOException {
+ testVersion(V1_8, true);
+ }
+
+ @Test
+ public void test_9() throws IOException {
+ testVersion(V9, true);
+ }
+
+ @Test
+ public void test_10() throws IOException {
+ testVersion(BytecodeVersion.V10, true);
+ }
+
+ private void testVersion(int version, boolean frames) throws IOException {
+ final byte[] original = createClass(version, frames);
+
+ IRuntime runtime = new SystemPropertiesRuntime();
+ Instrumenter instrumenter = new Instrumenter(runtime);
+ byte[] instrumented = instrumenter.instrument(original, "TestTarget");
+
+ assertFrames(instrumented, frames);
+ }
+
+ private void assertFrames(byte[] source, final boolean expected) {
+ int version = BytecodeVersion.get(source);
+ source = BytecodeVersion.downgradeIfNeeded(version, source);
+ new ClassReader(source)
+ .accept(new ClassVisitor(InstrSupport.ASM_API_VERSION) {
+
+ @Override
+ public MethodVisitor visitMethod(int access, String name,
+ String desc, String signature,
+ String[] exceptions) {
+ return new MethodVisitor(InstrSupport.ASM_API_VERSION) {
+ boolean frames = false;
+
+ @Override
+ public void visitFrame(int type, int nLocal,
+ Object[] local, int nStack,
+ Object[] stack) {
+ frames = true;
+ }
+
+ @Override
+ public void visitEnd() {
+ assertEquals(Boolean.valueOf(expected),
+ Boolean.valueOf(frames));
+ }
+ };
+ }
+ }, 0);
+ }
+
+ /**
+ * Creates a class that requires a frame before the return statement. Also
+ * for this class instrumentation should insert another frame.
+ *
+ * <code><pre>
+ * public class Sample {
+ * public Sample(boolean b){
+ * if(b){
+ * toString();
+ * }
+ * return;
+ * }
+ * }
+ * </pre></code>
+ */
+ private byte[] createClass(int version, boolean frames) {
+
+ ClassWriter cw = new ClassWriter(0);
+ MethodVisitor mv;
+
+ cw.visit(version, ACC_PUBLIC + ACC_SUPER, "org/jacoco/test/Sample",
+ null, "java/lang/Object", null);
+
+ mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(Z)V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V",
+ false);
+ mv.visitVarInsn(ILOAD, 1);
+ Label l1 = new Label();
+ mv.visitJumpInsn(IFEQ, l1);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "toString",
+ "()Ljava/lang/String;", false);
+ mv.visitInsn(POP);
+ mv.visitLabel(l1);
+ if (frames) {
+ mv.visitFrame(F_NEW, 2,
+ new Object[] { "org/jacoco/test/Sample", Opcodes.INTEGER },
+ 0, new Object[] {});
+ }
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 2);
+ mv.visitEnd();
+
+ cw.visitEnd();
+
+ return cw.toByteArray();
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ClassInitializerTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ClassInitializerTest.java
new file mode 100644
index 00000000..f87e705c
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ClassInitializerTest.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.test.validation.targets.Target05;
+import org.junit.Test;
+
+/**
+ * Tests of static initializer in classes.
+ */
+public class ClassInitializerTest extends ValidationTestBase {
+
+ public ClassInitializerTest() {
+ super(Target05.class);
+ }
+
+ @Test
+ public void testCoverageResult() {
+
+ assertLine("const1", ICounter.EMPTY);
+ assertLine("const2", ICounter.EMPTY);
+
+ assertLine("const3", ICounter.FULLY_COVERED);
+ assertLine("const4", ICounter.FULLY_COVERED);
+
+ assertLine("field1", ICounter.FULLY_COVERED);
+ assertLine("field2", ICounter.FULLY_COVERED);
+ assertLine("field3", ICounter.FULLY_COVERED);
+ assertLine("field4", ICounter.FULLY_COVERED);
+
+ assertLine("staticblock", ICounter.FULLY_COVERED);
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ControlStructuresTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ControlStructuresTest.java
new file mode 100644
index 00000000..37db4c14
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ControlStructuresTest.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.test.validation.targets.Target01;
+import org.junit.Test;
+
+/**
+ * Tests of basic Java control structures.
+ */
+public class ControlStructuresTest extends ValidationTestBase {
+
+ public ControlStructuresTest() {
+ super(Target01.class);
+ }
+
+ @Test
+ public void testCoverageResult() {
+
+ // 1. Direct unconditional execution
+ assertLine("unconditional", ICounter.FULLY_COVERED);
+
+ // 2. Missed if block
+ assertLine("iffalse", ICounter.FULLY_COVERED, 1, 1);
+ assertLine("missedif", ICounter.NOT_COVERED);
+ assertLine("executedelse", ICounter.FULLY_COVERED);
+
+ // 3. Executed if block
+ assertLine("iftrue", ICounter.FULLY_COVERED, 1, 1);
+ assertLine("executedif", ICounter.FULLY_COVERED);
+ assertLine("missedelse", ICounter.NOT_COVERED);
+
+ // 4. Missed while block
+ assertLine("whilefalse", ICounter.FULLY_COVERED, 1, 1);
+ assertLine("missedwhile", ICounter.NOT_COVERED);
+
+ // 5. Always true while block
+ assertLine("whiletrue", ICounter.FULLY_COVERED, 1, 1);
+
+ // 6. Executed while block
+ assertLine("whiletruefalse", ICounter.FULLY_COVERED, 0, 2);
+ assertLine("executedwhile", ICounter.FULLY_COVERED);
+
+ // 7. Executed do while block
+ assertLine("executeddowhile", ICounter.FULLY_COVERED);
+ assertLine("executeddowhilefalse", ICounter.FULLY_COVERED, 1, 1);
+
+ // 8. Missed for block
+ assertLine("missedforincrementer", ICounter.PARTLY_COVERED, 1, 1);
+ assertLine("missedfor", ICounter.NOT_COVERED);
+
+ // 9. Executed for block
+ assertLine("executedforincrementer", ICounter.FULLY_COVERED, 0, 2);
+ assertLine("executedfor", ICounter.FULLY_COVERED);
+
+ // 10. Missed for each block
+ assertLine("missedforeachincrementer", ICounter.PARTLY_COVERED, 1, 1);
+ assertLine("missedforeach", ICounter.NOT_COVERED);
+
+ // 11. Executed for each block
+ assertLine("executedforeachincrementer", ICounter.FULLY_COVERED, 0, 2);
+ assertLine("executedforeach", ICounter.FULLY_COVERED);
+
+ // 12. Table switch with hit
+ assertLine("tswitch1", ICounter.FULLY_COVERED, 3, 1);
+ assertLine("tswitch1case1", ICounter.NOT_COVERED);
+ assertLine("tswitch1case2", ICounter.FULLY_COVERED);
+ assertLine("tswitch1case3", ICounter.NOT_COVERED);
+ assertLine("tswitch1default", ICounter.NOT_COVERED);
+
+ // 13. Continued table switch with hit
+ assertLine("tswitch2", ICounter.FULLY_COVERED, 3, 1);
+ assertLine("tswitch2case1", ICounter.NOT_COVERED);
+ assertLine("tswitch2case2", ICounter.FULLY_COVERED);
+ assertLine("tswitch2case3", ICounter.FULLY_COVERED);
+ assertLine("tswitch2default", ICounter.FULLY_COVERED);
+
+ // 14. Table switch without hit
+ assertLine("tswitch2", ICounter.FULLY_COVERED, 3, 1);
+ assertLine("tswitch3case1", ICounter.NOT_COVERED);
+ assertLine("tswitch3case2", ICounter.NOT_COVERED);
+ assertLine("tswitch3case3", ICounter.NOT_COVERED);
+ assertLine("tswitch3default", ICounter.FULLY_COVERED);
+
+ // 15. Lookup switch with hit
+ assertLine("lswitch1", ICounter.FULLY_COVERED, 3, 1);
+ assertLine("lswitch1case1", ICounter.NOT_COVERED);
+ assertLine("lswitch1case2", ICounter.FULLY_COVERED);
+ assertLine("lswitch1case3", ICounter.NOT_COVERED);
+ assertLine("lswitch1default", ICounter.NOT_COVERED);
+
+ // 16. Continued lookup switch with hit
+ assertLine("lswitch2", ICounter.FULLY_COVERED, 3, 1);
+ assertLine("lswitch2case1", ICounter.NOT_COVERED);
+ assertLine("lswitch2case2", ICounter.FULLY_COVERED);
+ assertLine("lswitch2case3", ICounter.FULLY_COVERED);
+ assertLine("lswitch2default", ICounter.FULLY_COVERED);
+
+ // 17. Lookup switch without hit
+ assertLine("lswitch3", ICounter.FULLY_COVERED, 3, 1);
+ assertLine("lswitch3case1", ICounter.NOT_COVERED);
+ assertLine("lswitch3case2", ICounter.NOT_COVERED);
+ assertLine("lswitch3case3", ICounter.NOT_COVERED);
+ assertLine("lswitch3default", ICounter.FULLY_COVERED);
+
+ // 18. Break statement
+ assertLine("executedbreak", ICounter.FULLY_COVERED);
+ assertLine("missedafterbreak", ICounter.NOT_COVERED);
+
+ // 19. Continue statement
+ assertLine("executedcontinue", ICounter.FULLY_COVERED);
+ assertLine("missedaftercontinue", ICounter.NOT_COVERED);
+
+ // 20. Conditional return statement
+ assertLine("conditionalreturn", ICounter.FULLY_COVERED);
+ assertLine("afterconditionalreturn", ICounter.NOT_COVERED);
+
+ // 21. Implicit return
+ assertLine("implicitreturn", ICounter.FULLY_COVERED);
+
+ // 22. Explicit return
+ assertLine("explicitreturn", ICounter.FULLY_COVERED);
+ assertLine("afterexplicitreturn", ICounter.EMPTY);
+
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/CyclomaticComplexityTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/CyclomaticComplexityTest.java
new file mode 100644
index 00000000..122612ce
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/CyclomaticComplexityTest.java
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import static org.jacoco.core.test.validation.targets.Stubs.nop;
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import org.jacoco.core.analysis.Analyzer;
+import org.jacoco.core.analysis.CoverageBuilder;
+import org.jacoco.core.analysis.IClassCoverage;
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.analysis.IMethodCoverage;
+import org.jacoco.core.data.ExecutionDataStore;
+import org.jacoco.core.data.SessionInfoStore;
+import org.jacoco.core.instr.Instrumenter;
+import org.jacoco.core.internal.analysis.CounterImpl;
+import org.jacoco.core.runtime.IRuntime;
+import org.jacoco.core.runtime.RuntimeData;
+import org.jacoco.core.runtime.SystemPropertiesRuntime;
+import org.jacoco.core.test.TargetLoader;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Various tests for cyclomatic complexity of methods.
+ */
+public class CyclomaticComplexityTest {
+
+ public interface Target {
+ public void test(int arg);
+ }
+
+ private RuntimeData data;
+ private IRuntime runtime;
+ private byte[] bytes;
+ private Target target;
+
+ @Before
+ public void setup() throws Exception {
+ data = new RuntimeData();
+ runtime = new SystemPropertiesRuntime();
+ runtime.startup(data);
+ }
+
+ @After
+ public void teardown() {
+ runtime.shutdown();
+ }
+
+ public static class Simple implements Target {
+ public void test(int arg) {
+ nop();
+ nop();
+ nop();
+ }
+ }
+
+ @Test
+ public void testSimple1() throws Exception {
+ instrument(Simple.class);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(1, 0), complexity);
+ }
+
+ @Test
+ public void testSimple2() throws Exception {
+ instrument(Simple.class);
+ target.test(0);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(0, 1), complexity);
+ }
+
+ public static class If implements Target {
+ public void test(int arg) {
+ if (arg == 0) {
+ nop();
+ }
+ }
+ }
+
+ @Test
+ public void testIf1() throws Exception {
+ instrument(If.class);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(2, 0), complexity);
+ }
+
+ @Test
+ public void testIf2() throws Exception {
+ instrument(If.class);
+ target.test(0);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(1, 1), complexity);
+ }
+
+ @Test
+ public void testIf3() throws Exception {
+ instrument(If.class);
+ target.test(0);
+ target.test(1);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(0, 2), complexity);
+ }
+
+ public static class TwoIf implements Target {
+ public void test(int arg) {
+ if (arg < 0) {
+ nop();
+ }
+ if (arg > 0) {
+ nop();
+ }
+ }
+ }
+
+ @Test
+ public void testTwoIf1() throws Exception {
+ instrument(TwoIf.class);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(3, 0), complexity);
+ }
+
+ @Test
+ public void testTwoIf2() throws Exception {
+ instrument(TwoIf.class);
+ target.test(-1);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(2, 1), complexity);
+ }
+
+ @Test
+ public void testTwoIf3() throws Exception {
+ instrument(TwoIf.class);
+ target.test(-1);
+ target.test(0);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(1, 2), complexity);
+ }
+
+ @Test
+ public void testTwoIf4() throws Exception {
+ instrument(TwoIf.class);
+ target.test(-1);
+ target.test(+1);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(0, 3), complexity);
+ }
+
+ public static class NestedIf implements Target {
+ public void test(int arg) {
+ if (arg >= 0) {
+ if (arg == 0) {
+ nop();
+ }
+ nop();
+ }
+ }
+ }
+
+ @Test
+ public void testNestedIf1() throws Exception {
+ instrument(NestedIf.class);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(3, 0), complexity);
+ }
+
+ @Test
+ public void testNestedIf2() throws Exception {
+ instrument(NestedIf.class);
+ target.test(-1);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(2, 1), complexity);
+ }
+
+ @Test
+ public void testNestedIf3() throws Exception {
+ instrument(NestedIf.class);
+ target.test(-1);
+ target.test(0);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(1, 2), complexity);
+ }
+
+ @Test
+ public void testNestedIf4() throws Exception {
+ instrument(NestedIf.class);
+ target.test(-1);
+ target.test(0);
+ target.test(+1);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(0, 3), complexity);
+ }
+
+ public static class Switch implements Target {
+ public void test(int arg) {
+ switch (arg) {
+ case 1:
+ nop();
+ break;
+ case 2:
+ nop();
+ break;
+ }
+ }
+ }
+
+ @Test
+ public void testSwitch1() throws Exception {
+ instrument(Switch.class);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(3, 0), complexity);
+ }
+
+ @Test
+ public void testSwitch2() throws Exception {
+ instrument(Switch.class);
+ target.test(0);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(2, 1), complexity);
+ }
+
+ @Test
+ public void testSwitch3() throws Exception {
+ instrument(Switch.class);
+ target.test(0);
+ target.test(1);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(1, 2), complexity);
+ }
+
+ @Test
+ public void testSwitch4() throws Exception {
+ instrument(Switch.class);
+ target.test(0);
+ target.test(1);
+ target.test(2);
+ final ICounter complexity = analyze();
+ assertEquals(CounterImpl.getInstance(0, 3), complexity);
+ }
+
+ private void instrument(final Class<? extends Target> clazz)
+ throws Exception {
+ bytes = TargetLoader.getClassDataAsBytes(clazz);
+ final byte[] instrumented = new Instrumenter(runtime).instrument(bytes,
+ "TestTarget");
+ final TargetLoader loader = new TargetLoader();
+ target = (Target) loader.add(clazz, instrumented).newInstance();
+ }
+
+ private ICounter analyze() throws IOException {
+ final CoverageBuilder builder = new CoverageBuilder();
+ final ExecutionDataStore store = new ExecutionDataStore();
+ data.collect(store, new SessionInfoStore(), false);
+ final Analyzer analyzer = new Analyzer(store, builder);
+ analyzer.analyzeClass(bytes, "TestTarget");
+ final Collection<IClassCoverage> classes = builder.getClasses();
+ assertEquals(1, classes.size(), 0.0);
+ final IClassCoverage classCoverage = classes.iterator().next();
+ for (final IMethodCoverage m : classCoverage.getMethods()) {
+ if (m.getName().equals("test")) {
+ return m.getComplexityCounter();
+ }
+ }
+ throw new AssertionError("No test() method.");
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/EnumImplicitMethodsTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/EnumImplicitMethodsTest.java
new file mode 100644
index 00000000..fbd9e540
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/EnumImplicitMethodsTest.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.test.validation.targets.EnumImplicitMethods;
+import org.junit.Test;
+
+/**
+ * Test of an implicit methods and static initializer in enums.
+ */
+public class EnumImplicitMethodsTest extends ValidationTestBase {
+
+ public EnumImplicitMethodsTest() {
+ super(EnumImplicitMethods.class);
+ }
+
+ @Test
+ public void testCoverageResult() {
+ assertMethodCount(5);
+
+ assertLine("classdef", ICounter.FULLY_COVERED);
+ assertLine("customValueOfMethod", ICounter.NOT_COVERED);
+ assertLine("customValuesMethod", ICounter.NOT_COVERED);
+
+ assertLine("const", ICounter.PARTLY_COVERED);
+ assertLine("staticblock", ICounter.FULLY_COVERED);
+ assertLine("super", ICounter.FULLY_COVERED);
+ assertLine("constructor", ICounter.FULLY_COVERED);
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ExceptionsTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ExceptionsTest.java
new file mode 100644
index 00000000..c68bd374
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ExceptionsTest.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.test.validation.targets.Target03;
+import org.junit.Test;
+
+/**
+ * Tests of exception based control flow.
+ */
+public class ExceptionsTest extends ValidationTestBase {
+
+ public ExceptionsTest() {
+ super(Target03.class);
+ }
+
+ @Test
+ public void testCoverageResult() {
+
+ // 0. Implicit NullPointerException
+ // Currently no coverage at all, as we don't see when a block aborts
+ // somewhere in the middle.
+ assertLine("implicitNullPointerException.before", ICounter.NOT_COVERED);
+ assertLine("implicitNullPointerException.exception",
+ ICounter.NOT_COVERED);
+ assertLine("implicitNullPointerException.after", ICounter.NOT_COVERED);
+
+ // 1. Implicit Exception
+ assertLine("implicitException.before", ICounter.FULLY_COVERED);
+ assertLine("implicitException.exception", ICounter.NOT_COVERED);
+ assertLine("implicitException.after", ICounter.NOT_COVERED);
+
+ // 2. Explicit Exception
+ // Full coverage, as we recognize throw statements as block boundaries.
+ assertLine("explicitException.before", ICounter.FULLY_COVERED);
+ assertLine("explicitException.throw", ICounter.FULLY_COVERED);
+
+ // 3. Try/Catch Block Without Exception Thrown
+ assertLine("noExceptionTryCatch.beforeBlock", ICounter.FULLY_COVERED);
+ assertLine("noExceptionTryCatch.tryBlock", ICounter.FULLY_COVERED);
+ assertLine("noExceptionTryCatch.catch",
+ isJDKCompiler ? ICounter.NOT_COVERED : ICounter.PARTLY_COVERED);
+ assertLine("noExceptionTryCatch.catchBlock", ICounter.NOT_COVERED);
+ assertLine("noExceptionTryCatch.catchBlockEnd",
+ isJDKCompiler ? ICounter.FULLY_COVERED : ICounter.EMPTY);
+ assertLine("noExceptionTryCatch.afterBlock", ICounter.FULLY_COVERED);
+
+ // 4. Try/Catch Block With Exception Thrown Implicitly
+ assertLine("implicitExceptionTryCatch.beforeBlock",
+ ICounter.FULLY_COVERED);
+ assertLine("implicitExceptionTryCatch.before", ICounter.FULLY_COVERED);
+ assertLine("implicitExceptionTryCatch.exception", ICounter.NOT_COVERED);
+ assertLine("implicitExceptionTryCatch.after", ICounter.NOT_COVERED);
+ assertLine("implicitExceptionTryCatch.catch", isJDKCompiler
+ ? ICounter.FULLY_COVERED : ICounter.PARTLY_COVERED);
+ assertLine("implicitExceptionTryCatch.catchBlock",
+ ICounter.FULLY_COVERED);
+ assertLine("implicitExceptionTryCatch.catchBlockEnd",
+ isJDKCompiler ? ICounter.NOT_COVERED : ICounter.EMPTY);
+ assertLine("implicitExceptionTryCatch.afterBlock",
+ ICounter.FULLY_COVERED);
+
+ // 5. Try/Catch Block With Exception Thrown Implicitly After Condition
+ // As the try/catch block is entered at one branch of the condition
+ // should be marked as executed
+ assertLine("implicitExceptionTryCatchAfterCondition.condition",
+ ICounter.FULLY_COVERED, 1, 1);
+ assertLine("implicitExceptionTryCatchAfterCondition.exception",
+ ICounter.NOT_COVERED);
+ assertLine("implicitExceptionTryCatchAfterCondition.catchBlock",
+ ICounter.FULLY_COVERED);
+
+ // 6. Try/Catch Block With Exception Thrown Explicitly
+ assertLine("explicitExceptionTryCatch.beforeBlock",
+ ICounter.FULLY_COVERED);
+ assertLine("explicitExceptionTryCatch.before", ICounter.FULLY_COVERED);
+ assertLine("explicitExceptionTryCatch.throw", ICounter.FULLY_COVERED);
+ assertLine("explicitExceptionTryCatch.catch", ICounter.FULLY_COVERED);
+ assertLine("explicitExceptionTryCatch.catchBlock",
+ ICounter.FULLY_COVERED);
+ assertLine("explicitExceptionTryCatch.catchBlockEnd", ICounter.EMPTY);
+ assertLine("explicitExceptionTryCatch.afterBlock",
+ ICounter.FULLY_COVERED);
+
+ // 7. Finally Block Without Exception Thrown
+ assertLine("noExceptionFinally.beforeBlock", ICounter.FULLY_COVERED);
+ assertLine("noExceptionFinally.tryBlock", ICounter.FULLY_COVERED);
+ assertLine("noExceptionFinally.finally",
+ isJDKCompiler ? ICounter.EMPTY : ICounter.FULLY_COVERED);
+ assertLine("noExceptionFinally.finallyBlock", ICounter.FULLY_COVERED);
+ assertLine("noExceptionFinally.finallyBlockEnd", ICounter.EMPTY);
+ assertLine("noExceptionFinally.afterBlock", ICounter.FULLY_COVERED);
+
+ // 8. Finally Block With Implicit Exception
+ assertLine("implicitExceptionFinally.beforeBlock",
+ ICounter.FULLY_COVERED);
+ assertLine("implicitExceptionFinally.before", ICounter.FULLY_COVERED);
+ assertLine("implicitExceptionFinally.exception", ICounter.NOT_COVERED);
+ assertLine("implicitExceptionFinally.after", ICounter.NOT_COVERED);
+ assertLine("implicitExceptionFinally.finally",
+ isJDKCompiler ? ICounter.EMPTY : ICounter.NOT_COVERED);
+ assertLine("implicitExceptionFinally.finallyBlock",
+ ICounter.FULLY_COVERED);
+ assertLine("implicitExceptionFinally.finallyBlockEnd", ICounter.EMPTY);
+ assertLine("implicitExceptionFinally.afterBlock", ICounter.NOT_COVERED);
+
+ // 9. Finally Block With Exception Thrown Explicitly
+ assertLine("explicitExceptionFinally.beforeBlock",
+ ICounter.FULLY_COVERED);
+ assertLine("explicitExceptionFinally.before", ICounter.FULLY_COVERED);
+ assertLine("explicitExceptionFinally.throw", ICounter.FULLY_COVERED);
+ assertLine("explicitExceptionFinally.finally",
+ isJDKCompiler ? ICounter.EMPTY : ICounter.FULLY_COVERED);
+ assertLine("explicitExceptionFinally.finallyBlock",
+ ICounter.FULLY_COVERED);
+ assertLine("explicitExceptionFinally.finallyBlockEnd",
+ isJDKCompiler ? ICounter.EMPTY : ICounter.FULLY_COVERED);
+ assertLine("explicitExceptionFinally.afterBlock", ICounter.EMPTY);
+
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ExplicitInitialFrameTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ExplicitInitialFrameTest.java
new file mode 100644
index 00000000..1c0a02f1
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ExplicitInitialFrameTest.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.test.validation.targets.Target11;
+import org.junit.Test;
+
+/**
+ * Test for a methods having a explicit initial frame.
+ */
+public class ExplicitInitialFrameTest extends ValidationTestBase {
+
+ public ExplicitInitialFrameTest() {
+ super(Target11.class);
+ }
+
+ @Test
+ public void testCoverageResult() {
+
+ assertLine("dowhilebody", ICounter.FULLY_COVERED);
+
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/FieldInitializationInTwoConstructorsTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/FieldInitializationInTwoConstructorsTest.java
new file mode 100644
index 00000000..6896bf6d
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/FieldInitializationInTwoConstructorsTest.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.test.validation.targets.Target09;
+import org.junit.Test;
+
+/**
+ * Test of field initialization in two constructors.
+ */
+public class FieldInitializationInTwoConstructorsTest extends
+ ValidationTestBase {
+
+ public FieldInitializationInTwoConstructorsTest() {
+ super(Target09.class);
+ }
+
+ @Test
+ public void testCoverageResult() {
+
+ assertLine("field1", ICounter.PARTLY_COVERED);
+ assertLine("field2", ICounter.PARTLY_COVERED);
+ assertLine("constr1", ICounter.FULLY_COVERED);
+ assertLine("constr2", ICounter.NOT_COVERED);
+
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/FramesTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/FramesTest.java
new file mode 100644
index 00000000..9ab062b6
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/FramesTest.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import org.jacoco.core.instr.Instrumenter;
+import org.jacoco.core.internal.BytecodeVersion;
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.jacoco.core.runtime.IRuntime;
+import org.jacoco.core.runtime.SystemPropertiesRuntime;
+import org.jacoco.core.test.TargetLoader;
+import org.jacoco.core.test.validation.targets.Target01;
+import org.jacoco.core.test.validation.targets.Target02;
+import org.jacoco.core.test.validation.targets.Target03;
+import org.jacoco.core.test.validation.targets.Target04;
+import org.jacoco.core.test.validation.targets.Target05;
+import org.jacoco.core.test.validation.targets.Target06;
+import org.jacoco.core.test.validation.targets.Target07;
+import org.jacoco.core.test.validation.targets.Target08;
+import org.jacoco.core.test.validation.targets.Target09;
+import org.jacoco.core.test.validation.targets.Target10;
+import org.jacoco.core.test.validation.targets.Target11;
+import org.jacoco.core.test.validation.targets.Target12;
+import org.junit.Test;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.util.TraceClassVisitor;
+
+/**
+ * Tests whether stackmap frames are correctly adjusted.
+ */
+public class FramesTest {
+
+ /**
+ * Stack sizes calculated for instrumented classes might be sometimes bigger
+ * than actually needed. This is an acceptable tradeoff in favor of keeping
+ * track of the actual stack sizes. For test assertions we need to replace
+ * max stack sizes with constant value.
+ */
+ private static class MaxStackEliminator extends ClassVisitor {
+ public MaxStackEliminator(ClassVisitor cv) {
+ super(InstrSupport.ASM_API_VERSION, cv);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String desc,
+ String signature, String[] exceptions) {
+ final MethodVisitor mv = super.visitMethod(access, name, desc,
+ signature, exceptions);
+ return new MethodVisitor(InstrSupport.ASM_API_VERSION, mv) {
+ @Override
+ public void visitMaxs(int maxStack, int maxLocals) {
+ super.visitMaxs(-1, maxLocals);
+ }
+ };
+ }
+ }
+
+ private void testFrames(Class<?> target) throws IOException {
+ testFrames(TargetLoader.getClassDataAsBytes(target));
+ }
+
+ private void testFrames(byte[] source) throws IOException {
+ IRuntime runtime = new SystemPropertiesRuntime();
+ Instrumenter instrumenter = new Instrumenter(runtime);
+ source = calculateFrames(source);
+ byte[] actual = instrumenter.instrument(source, "TestTarget");
+ byte[] expected = calculateFrames(actual);
+
+ assertEquals(dump(expected), dump(actual));
+ }
+
+ private byte[] calculateFrames(byte[] source) {
+ source = BytecodeVersion.downgradeIfNeeded(BytecodeVersion.get(source),
+ source);
+
+ ClassReader rc = new ClassReader(source);
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+
+ // Adjust Version to 1.6 to enable frames:
+ rc.accept(new ClassVisitor(InstrSupport.ASM_API_VERSION, cw) {
+
+ @Override
+ public void visit(int version, int access, String name,
+ String signature, String superName, String[] interfaces) {
+ super.visit(Opcodes.V1_6, access, name, signature, superName,
+ interfaces);
+ }
+ }, 0);
+ return cw.toByteArray();
+ }
+
+ private String dump(byte[] bytes) {
+ final StringWriter buffer = new StringWriter();
+ final PrintWriter writer = new PrintWriter(buffer);
+ new ClassReader(bytes).accept(
+ new MaxStackEliminator(new TraceClassVisitor(writer)),
+ ClassReader.EXPAND_FRAMES);
+ return buffer.toString();
+ }
+
+ @Test
+ public void testTarget01() throws IOException {
+ testFrames(Target01.class);
+ }
+
+ @Test
+ public void testTarget02() throws IOException {
+ testFrames(Target02.class);
+ }
+
+ @Test
+ public void testTarget03() throws IOException {
+ testFrames(Target03.class);
+ }
+
+ @Test
+ public void testTarget04() throws IOException {
+ testFrames(Target04.class);
+ }
+
+ @Test
+ public void testTarget05() throws IOException {
+ testFrames(Target05.class);
+ }
+
+ @Test
+ public void testTarget06() throws IOException {
+ testFrames(Target06.class);
+ }
+
+ @Test
+ public void testTarget07() throws IOException {
+ testFrames(Target07.class);
+ }
+
+ @Test
+ public void testTarget08() throws IOException {
+ testFrames(Target08.class);
+ }
+
+ @Test
+ public void testTarget09() throws IOException {
+ testFrames(Target09.class);
+ }
+
+ @Test
+ public void testTarget10() throws IOException {
+ testFrames(Target10.class);
+ }
+
+ @Test
+ public void testTarget11() throws IOException {
+ testFrames(Target11.class);
+ }
+
+ @Test
+ public void testTarget12() throws IOException {
+ testFrames(Target12.class);
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ImplicitDefaultConstructorTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ImplicitDefaultConstructorTest.java
new file mode 100644
index 00000000..09872e8d
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ImplicitDefaultConstructorTest.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.test.validation.targets.Target06;
+import org.junit.Test;
+
+/**
+ * Test of a implicit default constructor.
+ *
+ * @see PrivateEmptyDefaultConstructorTest
+ */
+public class ImplicitDefaultConstructorTest extends ValidationTestBase {
+
+ public ImplicitDefaultConstructorTest() {
+ super(Target06.class);
+ }
+
+ @Test
+ public void testCoverageResult() {
+
+ assertLine("classdef", ICounter.FULLY_COVERED);
+
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ImplicitFieldInitializationTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ImplicitFieldInitializationTest.java
new file mode 100644
index 00000000..769593d7
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ImplicitFieldInitializationTest.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.test.validation.targets.Target08;
+import org.junit.Test;
+
+/**
+ * Test of a implicit field initialization.
+ */
+public class ImplicitFieldInitializationTest extends ValidationTestBase {
+
+ public ImplicitFieldInitializationTest() {
+ super(Target08.class);
+ }
+
+ @Test
+ public void testCoverageResult() {
+
+ assertLine("classdef", ICounter.FULLY_COVERED);
+ assertLine("field1", ICounter.EMPTY);
+ assertLine("field2", ICounter.FULLY_COVERED);
+ assertLine("field3", ICounter.EMPTY);
+ assertLine("field4", ICounter.FULLY_COVERED);
+
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/InterfaceClassInitializerTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/InterfaceClassInitializerTest.java
new file mode 100644
index 00000000..5675dbb0
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/InterfaceClassInitializerTest.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.test.validation.targets.Target04;
+import org.junit.Test;
+
+/**
+ * Tests of static initializer in interfaces.
+ */
+public class InterfaceClassInitializerTest extends ValidationTestBase {
+
+ public InterfaceClassInitializerTest() {
+ super(Target04.class);
+ }
+
+ @Override
+ protected void run(final Class<?> targetClass) throws Exception {
+ // Force class initialization
+ targetClass.getField("CONST1").get(null);
+ }
+
+ @Test
+ public void testCoverageResult() {
+
+ assertLine("const1", ICounter.EMPTY);
+ assertLine("const2", ICounter.EMPTY);
+
+ assertLine("const3", ICounter.FULLY_COVERED);
+ assertLine("const4", ICounter.FULLY_COVERED);
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/PrivateEmptyDefaultConstructorTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/PrivateEmptyDefaultConstructorTest.java
new file mode 100644
index 00000000..1d144b7d
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/PrivateEmptyDefaultConstructorTest.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.test.validation.targets.Target07;
+import org.junit.Test;
+
+/**
+ * Test of a private empty default constructor.
+ *
+ * @see ImplicitDefaultConstructorTest
+ */
+public class PrivateEmptyDefaultConstructorTest extends ValidationTestBase {
+
+ public PrivateEmptyDefaultConstructorTest() {
+ super(Target07.class);
+ }
+
+ @Test
+ public void testCoverageResult() {
+
+ assertLine("classdef", ICounter.EMPTY);
+ assertLine("super", ICounter.EMPTY);
+ assertLine("constructor", ICounter.EMPTY);
+
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ProbesBeforeSuperConstructorTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ProbesBeforeSuperConstructorTest.java
new file mode 100644
index 00000000..88b1ae54
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ProbesBeforeSuperConstructorTest.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import org.jacoco.core.analysis.ICounter;
+import org.jacoco.core.test.validation.targets.Target10;
+import org.junit.Test;
+
+/**
+ * Test of probes before the super constructor call.
+ */
+public class ProbesBeforeSuperConstructorTest extends ValidationTestBase {
+
+ public ProbesBeforeSuperConstructorTest() {
+ super(Target10.class);
+ }
+
+ @Test
+ public void testCoverageResult() {
+
+ assertLine("super", ICounter.PARTLY_COVERED, 3, 1);
+
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ResizeInstructionsTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ResizeInstructionsTest.java
new file mode 100644
index 00000000..fe6d134a
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/ResizeInstructionsTest.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import org.jacoco.core.instr.Instrumenter;
+import org.jacoco.core.internal.BytecodeVersion;
+import org.jacoco.core.internal.instr.InstrSupport;
+import org.jacoco.core.runtime.IRuntime;
+import org.jacoco.core.runtime.RuntimeData;
+import org.jacoco.core.runtime.SystemPropertiesRuntime;
+import org.jacoco.core.test.TargetLoader;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+public class ResizeInstructionsTest {
+
+ private final IRuntime runtime = new SystemPropertiesRuntime();
+ private final Instrumenter instrumenter = new Instrumenter(runtime);
+
+ private boolean computedCommonSuperClass = false;
+
+ @Before
+ public void setup() throws Exception {
+ runtime.startup(new RuntimeData());
+ }
+
+ @After
+ public void teardown() {
+ runtime.shutdown();
+ }
+
+ private class Inner {
+ }
+
+ /**
+ * Test of ASM bug
+ * <a href="https://gitlab.ow2.org/asm/asm/issues/317792">#317792</a>.
+ */
+ @Test
+ public void should_not_loose_InnerClasses_attribute() throws Exception {
+ byte[] source = TargetLoader.getClassDataAsBytes(Inner.class);
+ final int version = BytecodeVersion.get(source);
+ source = BytecodeVersion.downgradeIfNeeded(version, source);
+
+ final ClassReader cr = new ClassReader(source);
+ final ClassWriter cw = new ClassWriter(0);
+ cr.accept(new ClassVisitor(InstrSupport.ASM_API_VERSION, cw) {
+ @Override
+ public void visitEnd() {
+ final MethodVisitor mv = cv.visitMethod(0, "m", "()V", null,
+ null);
+ mv.visitCode();
+ addCauseOfResizeInstructions(mv);
+ mv.visitInsn(Opcodes.NOP);
+ mv.visitMaxs(2, 1);
+ mv.visitEnd();
+ super.visitEnd();
+ }
+ }, 0);
+ source = cw.toByteArray();
+ BytecodeVersion.set(source, version);
+
+ final byte[] bytes = instrumenter.instrument(source, "");
+
+ final TargetLoader targetLoader = new TargetLoader();
+ final Class<?> outer = targetLoader.add(ResizeInstructionsTest.class,
+ TargetLoader.getClassDataAsBytes(ResizeInstructionsTest.class));
+ final Class<?> inner = targetLoader.add(Inner.class, bytes);
+ assertSame(outer, inner.getEnclosingClass());
+ assertNotNull(inner.getEnclosingClass());
+ assertSame(outer, inner.getDeclaringClass());
+ assertNotNull(inner.getDeclaringClass());
+ }
+
+ /**
+ * Test of ASM bug
+ * <a href= "https://gitlab.ow2.org/asm/asm/issues/317630">#317630</a> that
+ * caused {@code java.lang.ClassNotFoundException}.
+ */
+ @Test
+ public void should_not_require_computation_of_common_superclass()
+ throws Exception {
+ final String className = "Example";
+
+ final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES) {
+ @Override
+ protected String getCommonSuperClass(final String type1,
+ final String type2) {
+ computedCommonSuperClass |= className.equals(type1)
+ || className.equals(type2);
+ return "java/lang/Object";
+ }
+ };
+ cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, className, null,
+ "java/lang/Object", null);
+ final MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "m", "()V",
+ null, null);
+ mv.visitCode();
+ addCauseOfResizeInstructions(mv);
+ addCauseOfGetCommonSuperClass(mv);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ cw.visitEnd();
+ final byte[] original = cw.toByteArray();
+ assertTrue(computedCommonSuperClass);
+ new TargetLoader().add(className, original);
+
+ final byte[] instrumented = instrumenter.instrument(original,
+ className);
+ new TargetLoader().add(className, instrumented);
+ }
+
+ /**
+ * Adds code that requires
+ * {@link ClassWriter#getCommonSuperClass(String, String)}.
+ *
+ * <pre>
+ * Object o = this;
+ * while (true) {
+ * o = (Integer) null;
+ * }
+ * </pre>
+ */
+ private static void addCauseOfGetCommonSuperClass(final MethodVisitor mv) {
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ mv.visitVarInsn(Opcodes.ASTORE, 1);
+ Label label = new Label();
+ mv.visitLabel(label);
+ mv.visitInsn(Opcodes.ACONST_NULL);
+ mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Integer");
+ mv.visitVarInsn(Opcodes.ASTORE, 1);
+ mv.visitJumpInsn(Opcodes.GOTO, label);
+ }
+
+ /**
+ * Adds code that triggers usage of
+ * {@link org.objectweb.asm.MethodWriter#COMPUTE_INSERTED_FRAMES} during
+ * instrumentation.
+ */
+ private static void addCauseOfResizeInstructions(final MethodVisitor mv) {
+ mv.visitInsn(Opcodes.ICONST_0);
+ mv.visitInsn(Opcodes.ICONST_1);
+ final Label target = new Label();
+ mv.visitJumpInsn(Opcodes.IFLE, target);
+ for (int i = 0; i < Short.MAX_VALUE; i++) {
+ mv.visitInsn(Opcodes.NOP);
+ }
+ mv.visitLabel(target);
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/StructuredLockingTest.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/StructuredLockingTest.java
new file mode 100644
index 00000000..823ab787
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/StructuredLockingTest.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.jacoco.core.instr.Instrumenter;
+import org.jacoco.core.internal.BytecodeVersion;
+import org.jacoco.core.runtime.IRuntime;
+import org.jacoco.core.runtime.SystemPropertiesRuntime;
+import org.jacoco.core.test.TargetLoader;
+import org.jacoco.core.test.validation.targets.Target12;
+import org.junit.Test;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.TryCatchBlockNode;
+import org.objectweb.asm.tree.VarInsnNode;
+import org.objectweb.asm.tree.analysis.Analyzer;
+import org.objectweb.asm.tree.analysis.AnalyzerException;
+import org.objectweb.asm.tree.analysis.BasicInterpreter;
+import org.objectweb.asm.tree.analysis.BasicValue;
+import org.objectweb.asm.tree.analysis.Frame;
+import org.objectweb.asm.tree.analysis.Interpreter;
+
+/**
+ * Tests that the invariants specified in <a href=
+ * "https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-2.html#jvms-2.11.10">chapter
+ * 2.11.10 of the JVM Spec</a> do also hold for instrumented classes.
+ *
+ * This is important because JIT compiler in HotSpot JVM ignores methods with
+ * unstructured locking, so that they executed by interpreter. Android Runtime
+ * also doesn't optimize such methods.
+ *
+ * TODO verification implemented here is incomplete - in particular it is unable
+ * to catch problem described in https://github.com/jacoco/jacoco/issues/626
+ */
+public class StructuredLockingTest {
+
+ @Test
+ public void testTarget12() throws Exception {
+ testMonitorExit(Target12.class);
+ }
+
+ private void testMonitorExit(Class<?> target) throws Exception {
+ assertStructuredLocking(TargetLoader.getClassDataAsBytes(target));
+ }
+
+ private void assertStructuredLocking(byte[] source) throws Exception {
+ IRuntime runtime = new SystemPropertiesRuntime();
+ Instrumenter instrumenter = new Instrumenter(runtime);
+ byte[] instrumented = instrumenter.instrument(source, "TestTarget");
+
+ final int version = BytecodeVersion.get(instrumented);
+ instrumented = BytecodeVersion.downgradeIfNeeded(version, instrumented);
+
+ ClassNode cn = new ClassNode();
+ new ClassReader(instrumented).accept(cn, 0);
+ for (MethodNode mn : cn.methods) {
+ assertStructuredLocking(cn.name, mn);
+ }
+ }
+
+ private void assertStructuredLocking(String owner, MethodNode mn)
+ throws Exception {
+ Analyzer<BasicValue> analyzer = new Analyzer<BasicValue>(
+ new BasicInterpreter()) {
+
+ @Override
+ protected Frame<BasicValue> newFrame(int nLocals, int nStack) {
+ return new LockFrame(nLocals, nStack);
+ }
+
+ @Override
+ protected Frame<BasicValue> newFrame(Frame<? extends BasicValue> src) {
+ return new LockFrame(src);
+ }
+ };
+
+ Frame<BasicValue>[] frames = analyzer.analyze(owner, mn);
+
+ // Make sure no locks are left when method exits:
+ for (int i = 0; i < frames.length; i++) {
+ AbstractInsnNode insn = mn.instructions.get(i);
+ switch (insn.getOpcode()) {
+ case Opcodes.IRETURN:
+ case Opcodes.LRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.DRETURN:
+ case Opcodes.ARETURN:
+ case Opcodes.RETURN:
+ ((LockFrame) frames[i]).assertNoLock("Exit with lock");
+ break;
+ case Opcodes.ATHROW:
+ List<TryCatchBlockNode> handlers = analyzer.getHandlers(i);
+ if (handlers == null || handlers.isEmpty()) {
+ ((LockFrame) frames[i]).assertNoLock("Exit with lock");
+ }
+ break;
+ }
+ }
+
+ // Only instructions protected by a catch-all handler can hold locks:
+ for (int i = 0; i < frames.length; i++) {
+ AbstractInsnNode insn = mn.instructions.get(i);
+ if (insn.getOpcode() > 0) {
+ boolean catchAll = false;
+ List<TryCatchBlockNode> handlers = analyzer.getHandlers(i);
+ if (handlers != null) {
+ for (TryCatchBlockNode node : handlers) {
+ catchAll |= node.type == null;
+ }
+ }
+ if (!catchAll) {
+ ((LockFrame) frames[i])
+ .assertNoLock("No handlers for insn with lock");
+ }
+ }
+ }
+
+ }
+
+ /**
+ * A Frame implementation that keeps track of the locking state. It is
+ * assumed that the monitor objects are stored in local variables.
+ */
+ private static class LockFrame extends Frame<BasicValue> {
+
+ Set<Integer> locks;
+
+ public LockFrame(final int nLocals, final int nStack) {
+ super(nLocals, nStack);
+ locks = new HashSet<Integer>();
+ }
+
+ public LockFrame(Frame<? extends BasicValue> src) {
+ super(src);
+ }
+
+ @Override
+ public Frame<BasicValue> init(Frame<? extends BasicValue> src) {
+ locks = new HashSet<Integer>(((LockFrame) src).locks);
+ return super.init(src);
+ }
+
+ @Override
+ public void execute(AbstractInsnNode insn,
+ Interpreter<BasicValue> interpreter) throws AnalyzerException {
+ super.execute(insn, interpreter);
+ switch (insn.getOpcode()) {
+ case Opcodes.MONITORENTER:
+ // Lock is stored in a local variable:
+ enter(((VarInsnNode) insn.getPrevious()).var);
+ break;
+ case Opcodes.MONITOREXIT:
+ // Lock is stored in a local variable:
+ exit(((VarInsnNode) insn.getPrevious()).var);
+ break;
+ }
+ }
+
+ void enter(int lock) {
+ assertTrue("multiple ENTER for lock " + lock,
+ locks.add(Integer.valueOf(lock)));
+ }
+
+ void exit(int lock) {
+ assertTrue("invalid EXIT for lock " + lock,
+ locks.remove(Integer.valueOf(lock)));
+ }
+
+ @Override
+ public boolean merge(Frame<? extends BasicValue> frame,
+ Interpreter<BasicValue> interpreter) throws AnalyzerException {
+ this.locks.addAll(((LockFrame) frame).locks);
+ return super.merge(frame, interpreter);
+ }
+
+ void assertNoLock(String message) {
+ assertEquals(message, Collections.emptySet(), locks);
+
+ }
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/AnnotationInitializer.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/AnnotationInitializer.java
new file mode 100644
index 00000000..f7b9e0af
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/AnnotationInitializer.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.targets;
+
+/**
+ * This test target is an annotation with an initializer.
+ */
+public @interface AnnotationInitializer {
+
+ Object CONST = new Object(); // $line-const$
+
+ int value() default 0; // $line-value$
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/BadCycleClass.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/BadCycleClass.java
new file mode 100644
index 00000000..c1826646
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/BadCycleClass.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.targets;
+
+public class BadCycleClass {
+
+ public static class Base {
+ static final Child b = new Child();
+
+ static {
+ b.someMethod();
+ }
+ }
+
+ public static class Child extends Base {
+
+ static {
+ Stubs.logEvent("childclinit"); // $line-childclinit$
+ }
+
+ public Child() {
+ Stubs.logEvent("childinit"); // $line-childinit$
+ }
+
+ void someMethod() {
+ Stubs.logEvent("childsomeMethod"); // $line-childsomeMethod$
+ }
+
+ }
+
+ public static void main(String[] args) {
+ new Child();
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/EnumImplicitMethods.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/EnumImplicitMethods.java
new file mode 100644
index 00000000..afbc46fd
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/EnumImplicitMethods.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.targets;
+
+public enum EnumImplicitMethods { // $line-classdef$
+
+ CONST(Stubs.f() ? new Object() : new Object()); // $line-const$
+
+ static {
+ } // $line-staticblock$
+
+ /**
+ * Unlike in {@link Target07 regular classes}, even if enum has explicit
+ * constructor, {@code clinit} method in any case has a reference to the
+ * line of enum definition.
+ */
+ EnumImplicitMethods(Object o) { // $line-super$
+ } // $line-constructor$
+
+ /**
+ * This method should not be excluded from analysis unlike implicitly
+ * created {@link #valueOf(String)} method that refers to the line of enum
+ * definition in case of javac and to the first line in case of ECJ.
+ */
+ public void valueOf() {
+ } // $line-customValueOfMethod$
+
+ /**
+ * This method should not be excluded from analysis unlike implicitly
+ * created {@link #values()} method that refers to the line of enum
+ * definition in case of javac and to the first line in case of ECJ.
+ */
+ public void values(Object o) {
+ } // $line-customValuesMethod$
+
+ public static void main(String[] args) {
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target01.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target01.java
new file mode 100644
index 00000000..81d00fa5
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target01.java
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.f;
+import static org.jacoco.core.test.validation.targets.Stubs.i2;
+import static org.jacoco.core.test.validation.targets.Stubs.nop;
+import static org.jacoco.core.test.validation.targets.Stubs.t;
+
+import java.util.Collections;
+
+/**
+ * This target exercises a set of common Java control structures.
+ */
+public class Target01 {
+
+ public static void main(String[] args) {
+
+ unconditionalExecution();
+ missedIfBlock();
+ executedIfBlock();
+ missedWhileBlock();
+ alwaysExecutedWhileBlock();
+ executedWhileBlock();
+ executedDoWhileBlock();
+ missedForBlock();
+ executedForBlock();
+ missedForEachBlock();
+ executedForEachBlock();
+ tableSwitchWithHit();
+ continuedTableSwitchWithHit();
+ tableSwitchWithoutHit();
+ lookupSwitchWithHit();
+ continuedLookupSwitchWithHit();
+ lookupSwitchWithoutHit();
+ breakStatement();
+ continueStatement();
+ conditionalReturn();
+ implicitReturn();
+ explicitReturn();
+
+ }
+
+ private static void unconditionalExecution() {
+
+ nop(); // $line-unconditional$
+
+ }
+
+ private static void missedIfBlock() {
+
+ if (f()) { // $line-iffalse$
+ nop(); // $line-missedif$
+ } else {
+ nop(); // $line-executedelse$
+ }
+
+ }
+
+ private static void executedIfBlock() {
+
+ if (t()) { // $line-iftrue$
+ nop(); // $line-executedif$
+ } else {
+ nop(); // $line-missedelse$
+ }
+
+ }
+
+ private static void missedWhileBlock() {
+
+ while (f()) { // $line-whilefalse$
+ nop(); // $line-missedwhile$
+ }
+
+ }
+
+ private static void alwaysExecutedWhileBlock() {
+
+ while (t()) { // $line-whiletrue$
+ if (t()) {
+ break;
+ }
+ }
+
+ }
+
+ private static void executedWhileBlock() {
+
+ int i = 0;
+ while (i++ < 3) { // $line-whiletruefalse$
+ nop(); // $line-executedwhile$
+ }
+
+ }
+
+ private static void executedDoWhileBlock() {
+
+ do {
+ nop(); // $line-executeddowhile$
+ } while (f()); // $line-executeddowhilefalse$
+
+ }
+
+ private static void missedForBlock() {
+
+ for (nop(); f(); nop()) { // $line-missedforincrementer$
+ nop(); // $line-missedfor$
+ }
+
+ }
+
+ private static void executedForBlock() {
+
+ for (int j = 0; j < 1; j++) { // $line-executedforincrementer$
+ nop(); // $line-executedfor$
+ }
+
+ }
+
+ private static void missedForEachBlock() {
+
+ for (Object o : Collections.emptyList()) { // $line-missedforeachincrementer$
+ nop(o); // $line-missedforeach$
+ }
+
+ }
+
+ private static void executedForEachBlock() {
+
+ for (Object o : Collections.singleton(new Object())) { // $line-executedforeachincrementer$
+ nop(o); // $line-executedforeach$
+ }
+
+ }
+
+ private static void tableSwitchWithHit() {
+
+ switch (i2()) { // $line-tswitch1$
+ case 1:
+ nop(); // $line-tswitch1case1$
+ break;
+ case 2:
+ nop(); // $line-tswitch1case2$
+ break;
+ case 3:
+ nop(); // $line-tswitch1case3$
+ break;
+ default:
+ nop(); // $line-tswitch1default$
+ break;
+ }
+
+ }
+
+ private static void continuedTableSwitchWithHit() {
+
+ switch (i2()) { // $line-tswitch2$
+ case 1:
+ nop(); // $line-tswitch2case1$
+ case 2:
+ nop(); // $line-tswitch2case2$
+ case 3:
+ nop(); // $line-tswitch2case3$
+ default:
+ nop(); // $line-tswitch2default$
+ }
+
+ }
+
+ private static void tableSwitchWithoutHit() {
+
+ switch (i2()) { // $line-tswitch3$
+ case 3:
+ nop(); // $line-tswitch3case1$
+ break;
+ case 4:
+ nop(); // $line-tswitch3case2$
+ break;
+ case 5:
+ nop(); // $line-tswitch3case3$
+ break;
+ default:
+ nop(); // $line-tswitch3default$
+ break;
+ }
+
+ }
+
+ private static void lookupSwitchWithHit() {
+
+ switch (i2()) { // $line-lswitch1$
+ case -123:
+ nop(); // $line-lswitch1case1$
+ break;
+ case 2:
+ nop(); // $line-lswitch1case2$
+ break;
+ case 456:
+ nop(); // $line-lswitch1case3$
+ break;
+ default:
+ nop(); // $line-lswitch1default$
+ break;
+ }
+
+ }
+
+ private static void continuedLookupSwitchWithHit() {
+
+ switch (i2()) { // $line-lswitch2$
+ case -123:
+ nop(); // $line-lswitch2case1$
+ case 2:
+ nop(); // $line-lswitch2case2$
+ case 456:
+ nop(); // $line-lswitch2case3$
+ default:
+ nop(); // $line-lswitch2default$
+ }
+
+ }
+
+ private static void lookupSwitchWithoutHit() {
+
+ switch (i2()) { // $line-lswitch3$
+ case -123:
+ nop(); // $line-lswitch3case1$
+ break;
+ case 456:
+ nop(); // $line-lswitch3case2$
+ break;
+ case 789:
+ nop(); // $line-lswitch3case3$
+ break;
+ default:
+ nop(); // $line-lswitch3default$
+ break;
+ }
+
+ }
+
+ private static void breakStatement() {
+
+ while (true) {
+ if (t()) {
+ break; // $line-executedbreak$
+ }
+ nop(); // $line-missedafterbreak$
+ }
+
+ }
+
+ private static void continueStatement() {
+
+ for (int j = 0; j < 1; j++) {
+ if (t()) {
+ continue; // $line-executedcontinue$
+ }
+ nop(); // $line-missedaftercontinue$
+ }
+
+ }
+
+ private static void conditionalReturn() {
+
+ if (t()) {
+ return; // $line-conditionalreturn$
+ }
+ nop(); // $line-afterconditionalreturn$
+
+ }
+
+ private static void implicitReturn() {
+
+ } // $line-implicitreturn$
+
+ private static void explicitReturn() {
+
+ return; // $line-explicitreturn$
+
+ } // $line-afterexplicitreturn$
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target02.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target02.java
new file mode 100644
index 00000000..62e22ef9
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target02.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.f;
+import static org.jacoco.core.test.validation.targets.Stubs.i1;
+import static org.jacoco.core.test.validation.targets.Stubs.i2;
+import static org.jacoco.core.test.validation.targets.Stubs.nop;
+import static org.jacoco.core.test.validation.targets.Stubs.t;
+
+/**
+ * This target exercises boolean expressions.
+ */
+public class Target02 {
+
+ public static void main(String[] args) {
+
+ // 1. Boolean comparison result (one case)
+ nop(i2() > 3); // $line-booleancmp1$
+
+ // 2. Boolean comparison result (both cases)
+ for (int i = 0; i < 2; i++) {
+ nop(i < 1); // $line-booleancmp2$
+ }
+
+ // 3. And
+ if (f() & f()) { // $line-andFF$
+ nop();
+ }
+ if (f() & t()) { // $line-andFT$
+ nop();
+ }
+ if (t() & f()) { // $line-andTF$
+ nop();
+ }
+ if (t() & t()) { // $line-andTT$
+ nop();
+ }
+
+ // 4. Conditional And
+ if (f() && f()) { // $line-conditionalandFF$
+ nop();
+ }
+ if (f() && t()) { // $line-conditionalandFT$
+ nop();
+ }
+ if (t() && f()) { // $line-conditionalandTF$
+ nop();
+ }
+ if (t() && t()) { // $line-conditionalandTT$
+ nop();
+ }
+
+ // 5. Or
+ if (f() | f()) { // $line-orFF$
+ nop();
+ }
+ if (f() | t()) { // $line-orFT$
+ nop();
+ }
+ if (t() | f()) { // $line-orTF$
+ nop();
+ }
+ if (t() | t()) { // $line-orTT$
+ nop();
+ }
+
+ // 6. Conditional Or
+ if (f() || f()) { // $line-conditionalorFF$
+ nop();
+ }
+ if (f() || t()) { // $line-conditionalorFT$
+ nop();
+ }
+ if (t() || f()) { // $line-conditionalorTF$
+ nop();
+ }
+ if (t() || t()) { // $line-conditionalorTT$
+ nop();
+ }
+
+ // 7. Exclusive Or
+ if (f() ^ f()) { // $line-xorFF$
+ nop();
+ }
+ if (f() ^ t()) { // $line-xorFT$
+ nop();
+ }
+ if (t() ^ f()) { // $line-xorTF$
+ nop();
+ }
+ if (t() ^ t()) { // $line-xorTT$
+ nop();
+ }
+
+ // 8. Conditional Operator
+ nop(t() ? i1() : i2()); // $line-condT$
+ nop(f() ? i1() : i2()); // $line-condF$
+
+ // 9. Not (one case)
+ nop(!t()); // $line-notT$
+ nop(!f()); // $line-notF$
+
+ // 10. Not (both cases)
+ for (boolean b : new boolean[] { true, false }) {
+ nop(!b); // $line-notTF$
+ }
+
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target03.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target03.java
new file mode 100644
index 00000000..b4418edd
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target03.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.ex;
+import static org.jacoco.core.test.validation.targets.Stubs.f;
+import static org.jacoco.core.test.validation.targets.Stubs.nop;
+
+import org.jacoco.core.test.validation.targets.Stubs.StubException;
+
+/**
+ * This target produces exception based control flow examples.
+ */
+public class Target03 {
+
+ public static void main(String[] args) {
+
+ try {
+ implicitNullPointerException(null);
+ } catch (NullPointerException e) {
+ }
+ try {
+ implicitException();
+ } catch (StubException e) {
+ }
+ try {
+ explicitException();
+ } catch (StubException e) {
+ }
+ noExceptionTryCatch();
+ implicitExceptionTryCatch();
+ implicitExceptionTryCatchAfterCondition();
+ explicitExceptionTryCatch();
+ noExceptionFinally();
+ try {
+ explicitExceptionFinally();
+ } catch (StubException e) {
+ }
+ try {
+ implicitExceptionFinally();
+ } catch (StubException e) {
+ }
+ }
+
+ private static void implicitNullPointerException(int[] a) {
+ nop(); // $line-implicitNullPointerException.before$
+ a[0] = 0; // $line-implicitNullPointerException.exception$
+ nop(); // $line-implicitNullPointerException.after$
+ }
+
+ private static void implicitException() {
+ nop(); // $line-implicitException.before$
+ ex(); // $line-implicitException.exception$
+ nop(); // $line-implicitException.after$
+ }
+
+ private static void explicitException() {
+ nop(); // $line-explicitException.before$
+ throw new StubException(); // $line-explicitException.throw$
+ }
+
+ private static void noExceptionTryCatch() {
+ nop(); // $line-noExceptionTryCatch.beforeBlock$
+ try {
+ nop(); // $line-noExceptionTryCatch.tryBlock$
+ } catch (StubException e) { // $line-noExceptionTryCatch.catch$
+ nop(); // $line-noExceptionTryCatch.catchBlock$
+ } // $line-noExceptionTryCatch.catchBlockEnd$
+ } // $line-noExceptionTryCatch.afterBlock$
+
+ private static void implicitExceptionTryCatch() {
+ nop(); // $line-implicitExceptionTryCatch.beforeBlock$
+ try {
+ nop(); // $line-implicitExceptionTryCatch.before$
+ ex(); // $line-implicitExceptionTryCatch.exception$
+ nop(); // $line-implicitExceptionTryCatch.after$
+ } catch (StubException e) { // $line-implicitExceptionTryCatch.catch$
+ nop(); // $line-implicitExceptionTryCatch.catchBlock$
+ } // $line-implicitExceptionTryCatch.catchBlockEnd$
+ } // $line-implicitExceptionTryCatch.afterBlock$
+
+ private static void implicitExceptionTryCatchAfterCondition() {
+ if (f()) { // $line-implicitExceptionTryCatchAfterCondition.condition$
+ return;
+ }
+ try {
+ ex(); // $line-implicitExceptionTryCatchAfterCondition.exception$
+ } catch (StubException e) {
+ nop(); // $line-implicitExceptionTryCatchAfterCondition.catchBlock$
+ }
+ }
+
+ private static void explicitExceptionTryCatch() {
+ nop(); // $line-explicitExceptionTryCatch.beforeBlock$
+ try {
+ nop(); // $line-explicitExceptionTryCatch.before$
+ throw new StubException(); // $line-explicitExceptionTryCatch.throw$
+ } catch (StubException e) { // $line-explicitExceptionTryCatch.catch$
+ nop(); // $line-explicitExceptionTryCatch.catchBlock$
+ } // $line-explicitExceptionTryCatch.catchBlockEnd$
+ } // $line-explicitExceptionTryCatch.afterBlock$
+
+ private static void noExceptionFinally() {
+ nop(); // $line-noExceptionFinally.beforeBlock$
+ try {
+ nop(); // $line-noExceptionFinally.tryBlock$
+ } finally { // $line-noExceptionFinally.finally$
+ nop(); // $line-noExceptionFinally.finallyBlock$
+ } // $line-noExceptionFinally.finallyBlockEnd$
+ } // $line-noExceptionFinally.afterBlock$
+
+ private static void implicitExceptionFinally() {
+ nop(); // $line-implicitExceptionFinally.beforeBlock$
+ try {
+ nop(); // $line-implicitExceptionFinally.before$
+ ex(); // $line-implicitExceptionFinally.exception$
+ nop(); // $line-implicitExceptionFinally.after$
+ } finally { // $line-implicitExceptionFinally.finally$
+ nop(); // $line-implicitExceptionFinally.finallyBlock$
+ } // $line-implicitExceptionFinally.finallyBlockEnd$
+ } // $line-implicitExceptionFinally.afterBlock$
+
+ private static void explicitExceptionFinally() {
+ nop(); // $line-explicitExceptionFinally.beforeBlock$
+ try {
+ nop(); // $line-explicitExceptionFinally.before$
+ throw new StubException(); // $line-explicitExceptionFinally.throw$
+ } finally { // $line-explicitExceptionFinally.finally$
+ nop(); // $line-explicitExceptionFinally.finallyBlock$
+ } // $line-explicitExceptionFinally.finallyBlockEnd$
+ } // $line-explicitExceptionFinally.afterBlock$
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target04.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target04.java
new file mode 100644
index 00000000..8384744b
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target04.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.i1;
+
+/**
+ * This test target is an interface with a class initializer.
+ */
+public interface Target04 {
+
+ // No code required to initialize these fields:
+
+ static final int CONST1 = 12345; // $line-const1$
+
+ static final String CONST2 = "const"; // $line-const2$
+
+ // These fields are initialized within <clinit>
+
+ static final int CONST3 = i1(); // $line-const3$
+
+ static final Object CONST4 = new Object(); // $line-const4$
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target05.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target05.java
new file mode 100644
index 00000000..ef5c3989
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target05.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.i1;
+
+/**
+ * This test target is a class with a static initializer.
+ */
+public class Target05 {
+
+ // No code required to initialize these fields:
+
+ public static final int CONST1 = 3; // $line-const1$
+
+ public static final String CONST2 = "Hello"; // $line-const2$
+
+ // These fields are initialized within <clinit>
+
+ public static final int CONST3 = i1(); // $line-const3$
+
+ public static final Object CONST4 = new Object(); // $line-const4$
+
+ public static int field1 = 3; // $line-field1$
+
+ public static String field2 = "Hello"; // $line-field2$
+
+ public static int field3 = i1(); // $line-field3$
+
+ public static Object field4 = new Object(); // $line-field4$
+
+ static {
+ Stubs.nop(); // $line-staticblock$
+ }
+
+ private Target05() {
+ }
+
+ public static void main(String[] args) {
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target06.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target06.java
new file mode 100644
index 00000000..f6bc75e8
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target06.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.targets;
+
+/**
+ * This test target is a class with a implicit default constructor.
+ *
+ * @see Target07 explicit constructor
+ */
+public class Target06 { // $line-classdef$
+
+ public static void main(String[] args) {
+ new Target06();
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target07.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target07.java
new file mode 100644
index 00000000..18c3ba52
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target07.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.targets;
+
+/**
+ * This test target is a private empty default constructor.
+ *
+ * @see Target06 implicit constructor
+ */
+public class Target07 { // $line-classdef$
+
+ private Target07() { // $line-super$
+ } // $line-constructor$
+
+ public static void main(String[] args) {
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target08.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target08.java
new file mode 100644
index 00000000..1fe938aa
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target08.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.targets;
+
+/**
+ * This test target has instance members with implicit initializers.
+ */
+public class Target08 { // $line-classdef$
+
+ Object field1; // $line-field1$
+
+ Object field2 = this; // $line-field2$
+
+ int field3; // $line-field3$
+
+ int field4 = 2000; // $line-field4$
+
+ public static void main(String[] args) {
+ new Target08();
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target09.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target09.java
new file mode 100644
index 00000000..a8589d1d
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target09.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.targets;
+
+/**
+ * This test target has instance members with initialization in two
+ * constructors.
+ */
+public class Target09 {
+
+ Object field1 = null; // $line-field1$
+
+ int field2 = 123; // $line-field2$
+
+ public Target09() {
+ } // $line-constr1$
+
+ public Target09(String arg) {
+ } // $line-constr2$
+
+ public static void main(String[] args) {
+ new Target09();
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target10.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target10.java
new file mode 100644
index 00000000..bb4496e9
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target10.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.f;
+import static org.jacoco.core.test.validation.targets.Stubs.t;
+
+import org.jacoco.core.test.validation.targets.Stubs.SuperClass;
+
+/**
+ * This test target has a constructor containing control structures before the
+ * superclass constructor is called.
+ */
+public class Target10 extends SuperClass {
+
+ public Target10() {
+ super(t() || f()); // $line-super$
+ }
+
+ public static void main(String[] args) {
+ new Target10();
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target11.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target11.java
new file mode 100644
index 00000000..d393cb7f
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target11.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.f;
+import static org.jacoco.core.test.validation.targets.Stubs.nop;
+
+/**
+ * This test target needs an explicit initial frame as the first instruction
+ * already is a jump target.
+ */
+public class Target11 {
+
+ public static void main(String[] args) {
+
+ do {
+ nop(); // $line-dowhilebody$
+ } while (f());
+
+ }
+
+}
diff --git a/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target12.java b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target12.java
new file mode 100644
index 00000000..5ee2e324
--- /dev/null
+++ b/org.jacoco.core.test.validation.java5/src/org/jacoco/core/test/validation/targets/Target12.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc R. Hoffmann - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.test.validation.targets;
+
+import static org.jacoco.core.test.validation.targets.Stubs.nop;
+
+/**
+ * This target uses synchronized blocks which compile to try/catch statements.
+ */
+public class Target12 {
+
+ static void simple() {
+ Object lock1 = new Object();
+ synchronized (lock1) {
+ nop();
+ }
+ }
+
+ static void nested() {
+ Object lock1 = new Object();
+ synchronized (lock1) {
+ nop();
+ Object lock2 = new Object();
+ synchronized (lock2) {
+ nop();
+ }
+ nop();
+ }
+
+ }
+
+ public static void main(String[] args) {
+ simple();
+ nested();
+ }
+
+}