| /******************************************************************************* |
| * Copyright (c) 2009, 2019 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.java5; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNull; |
| |
| import java.io.IOException; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.jacoco.core.internal.instr.InstrSupport; |
| import org.jacoco.core.test.TargetLoader; |
| import org.jacoco.core.test.validation.Source.Line; |
| import org.jacoco.core.test.validation.ValidationTestBase; |
| import org.jacoco.core.test.validation.java5.targets.FinallyTarget; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.objectweb.asm.Opcodes; |
| import org.objectweb.asm.tree.AbstractInsnNode; |
| import org.objectweb.asm.tree.ClassNode; |
| import org.objectweb.asm.tree.LineNumberNode; |
| import org.objectweb.asm.tree.MethodNode; |
| |
| /** |
| * Test of filtering of duplicated bytecode that is generated for finally block. |
| */ |
| public class FinallyTest extends ValidationTestBase { |
| |
| private Map<Integer, String> tags; |
| |
| public FinallyTest() { |
| super(FinallyTarget.class); |
| } |
| |
| @Before |
| @Override |
| public void setup() throws Exception { |
| super.setup(); |
| tags = new HashMap<Integer, String>(); |
| } |
| |
| public void assertFinally(final Line line) { |
| if (isJDKCompiler) { |
| assertEmpty(line); |
| } else { |
| assertFullyCovered(line); |
| } |
| } |
| |
| public void assertTwoRegions1(final Line line) { |
| if (isJDKCompiler && JAVA_VERSION.isBefore("1.8")) { |
| // https://bugs.openjdk.java.net/browse/JDK-7008643 |
| assertPartlyCovered(line); |
| } else { |
| assertFullyCovered(line); |
| } |
| } |
| |
| public void assertTwoRegionsReturn1(final Line line) { |
| if (isJDKCompiler && JAVA_VERSION.isBefore("1.8")) { |
| // https://bugs.openjdk.java.net/browse/JDK-7008643 |
| assertEmpty(line); |
| } else { |
| assertFullyCovered(line); |
| } |
| } |
| |
| public void assertTwoRegionsReturn2(final Line line) { |
| if (isJDKCompiler && JAVA_VERSION.isBefore("1.8")) { |
| // https://bugs.openjdk.java.net/browse/JDK-7008643 |
| assertEmpty(line); |
| } else { |
| assertNotCovered(line); |
| } |
| } |
| |
| public void assertEmptyTry1(final Line line) { |
| if (isJDKCompiler && JAVA_VERSION.isBefore("1.8")) { |
| // compiler bug fixed in javac >= 1.8: |
| assertPartlyCovered(line); |
| } else { |
| assertFullyCovered(line); |
| } |
| } |
| |
| public void assertEmptyTry2(final Line line) { |
| if (isJDKCompiler && JAVA_VERSION.isBefore("1.8")) { |
| // compiler bug fixed in javac >= 1.8: |
| assertFullyCovered(line); |
| } else { |
| assertEmpty(line); |
| } |
| } |
| |
| public void assertAlwaysCompletesAbruptly0(final Line line) { |
| if (isJDKCompiler) { |
| // uncovered case: |
| assertEmpty(line); |
| } else { |
| assertPartlyCovered(line); |
| } |
| } |
| |
| public void assertAlwaysCompletesAbruptly1(final Line line) { |
| if (isJDKCompiler) { |
| // uncovered case: |
| assertPartlyCovered(line); |
| } else { |
| assertFullyCovered(line); |
| } |
| } |
| |
| @Test |
| @Override |
| public void execute_assertions_in_comments() throws IOException { |
| super.execute_assertions_in_comments(); |
| gotos(); |
| } |
| |
| /** |
| * This test studies placement of GOTO instructions. |
| */ |
| private void gotos() throws IOException { |
| |
| final Set<String> expected = new HashSet<String>(); |
| |
| if (isJDKCompiler) { |
| expected.add("example.2"); |
| } else { |
| expected.add("example.0"); |
| } |
| |
| expected.add("breakStatement.for"); |
| if (isJDKCompiler) { |
| if (JAVA_VERSION.isBefore("10")) { |
| // https://bugs.openjdk.java.net/browse/JDK-8180141 |
| expected.add("breakStatement.1"); |
| } else { |
| expected.add("breakStatement"); |
| } |
| expected.add("breakStatement.2"); |
| } else { |
| expected.add("breakStatement"); |
| } |
| |
| if (isJDKCompiler) { |
| expected.add("emptyCatch.2"); |
| } else { |
| expected.add("emptyCatch"); |
| expected.add("emptyCatch.1"); |
| } |
| |
| if (isJDKCompiler) { |
| expected.add("catchNotExecuted.2"); |
| } else { |
| expected.add("catchNotExecuted"); |
| expected.add("catchNotExecuted.1"); |
| } |
| |
| if (isJDKCompiler) { |
| expected.add("nested.5"); |
| expected.add("nested.6"); |
| } else { |
| expected.add("nested.0"); |
| expected.add("nested.3"); |
| } |
| |
| if (isJDKCompiler && JAVA_VERSION.isBefore("1.8")) { |
| expected.add("emptyTry.2"); |
| } |
| |
| if (!isJDKCompiler) { |
| expected.add("alwaysCompletesAbruptly.0"); |
| } |
| |
| assertEquals(expected, getTagsWithGotos()); |
| } |
| |
| private Set<String> getTagsWithGotos() throws IOException { |
| final Set<String> gotoTags = new HashSet<String>(); |
| |
| byte[] b = TargetLoader.getClassDataAsBytes(FinallyTarget.class); |
| |
| final ClassNode classNode = new ClassNode(); |
| InstrSupport.classReaderFor(b).accept(classNode, 0); |
| for (final MethodNode m : classNode.methods) { |
| if ("main".equals(m.name)) { |
| // skip it |
| continue; |
| } |
| int lineNumber = -1; |
| for (AbstractInsnNode i = m.instructions |
| .getFirst(); i != null; i = i.getNext()) { |
| if (AbstractInsnNode.LINE == i.getType()) { |
| lineNumber = ((LineNumberNode) i).line; |
| } |
| if (Opcodes.GOTO == i.getOpcode()) { |
| String tag = tags.get(Integer.valueOf(lineNumber)); |
| if (tag == null) { |
| throw new AssertionError( |
| "No tag at line " + lineNumber); |
| } |
| gotoTags.add(tag); |
| } |
| } |
| } |
| |
| return gotoTags; |
| } |
| |
| public void tag(final Line line, String tag) { |
| assertFalse("duplicate tag " + tag, tags.containsValue(tag)); |
| assertNull("duplicate tag in " + line, |
| tags.put(Integer.valueOf(line.getNr()), tag)); |
| } |
| |
| } |