blob: 91a812476dbb58804ea7822b8ee83ae87dd202a2 [file] [log] [blame]
/*******************************************************************************
* 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));
}
}