diff options
author | Evgeny Mandrikov <Godin@users.noreply.github.com> | 2017-03-28 19:20:48 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-28 19:20:48 +0200 |
commit | eaef191fe12fc5abc81435016dbbd69cb55d1f68 (patch) | |
tree | f7ea74f56ff9a388e22cb44e5626dd3bcb83f50e /org.jacoco.core.test/src/org/jacoco | |
parent | 38a26f418483fd2053b19bf6b3adb7318c11be3f (diff) | |
download | jacoco-eaef191fe12fc5abc81435016dbbd69cb55d1f68.tar.gz |
Add internal API for filters and filter for synchronized statement (#501)
Diffstat (limited to 'org.jacoco.core.test/src/org/jacoco')
6 files changed, 319 insertions, 7 deletions
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilterTest.java new file mode 100644 index 00000000..b315dda5 --- /dev/null +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilterTest.java @@ -0,0 +1,166 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 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.internal.analysis.filter; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.jacoco.core.internal.instr.InstrSupport; +import org.junit.Test; +import org.objectweb.asm.Label; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.MethodNode; + +public class SynchronizedFilterTest implements IFilterOutput { + + private final SynchronizedFilter filter = new SynchronizedFilter(); + + private final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "name", "()V", null, null); + + private AbstractInsnNode fromInclusive; + private AbstractInsnNode toInclusive; + + @Test + public void javac() { + final Label start = new Label(); + final Label end = new Label(); + final Label handler = new Label(); + final Label handlerEnd = new Label(); + m.visitTryCatchBlock(start, end, handler, null); + m.visitTryCatchBlock(handler, handlerEnd, handler, null); + + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitFieldInsn(Opcodes.GETFIELD, "Fun", "lock", "Ljava/lang/Object;"); + m.visitInsn(Opcodes.DUP); + m.visitVarInsn(Opcodes.ASTORE, 1); + m.visitInsn(Opcodes.MONITORENTER); + m.visitLabel(start); + m.visitInsn(Opcodes.NOP); + m.visitVarInsn(Opcodes.ALOAD, 1); + m.visitInsn(Opcodes.MONITOREXIT); + m.visitLabel(end); + final Label exit = new Label(); + m.visitJumpInsn(Opcodes.GOTO, exit); + m.visitLabel(handler); + m.visitVarInsn(Opcodes.ASTORE, 2); + m.visitVarInsn(Opcodes.ALOAD, 1); + m.visitInsn(Opcodes.MONITOREXIT); + m.visitLabel(handlerEnd); + m.visitVarInsn(Opcodes.ALOAD, 2); + m.visitInsn(Opcodes.ATHROW); + m.visitLabel(exit); + m.visitInsn(Opcodes.RETURN); + + filter.filter(m, this); + assertEquals(handler.info, fromInclusive); + assertEquals(((LabelNode) exit.info).getPrevious(), toInclusive); + } + + /** + * <pre> + * try { + * ... + * } catch (Exception e) { + * ... + * } finally { + * ... + * } + * </pre> + */ + @Test + public void javacTryCatchFinally() { + final Label start = new Label(); + final Label end = new Label(); + final Label catchHandler = new Label(); + final Label finallyHandler = new Label(); + final Label catchHandlerEnd = new Label(); + m.visitTryCatchBlock(start, end, catchHandler, "java/lang/Exception"); + m.visitTryCatchBlock(start, end, finallyHandler, null); + m.visitTryCatchBlock(catchHandler, catchHandlerEnd, finallyHandler, + null); + + m.visitLabel(start); + // body + m.visitInsn(Opcodes.NOP); + m.visitLabel(end); + // finally + m.visitInsn(Opcodes.NOP); + final Label exit = new Label(); + m.visitJumpInsn(Opcodes.GOTO, exit); + m.visitLabel(catchHandler); + m.visitVarInsn(Opcodes.ASTORE, 1); + // catch + m.visitInsn(Opcodes.NOP); + m.visitLabel(catchHandlerEnd); + // finally + m.visitInsn(Opcodes.NOP); + m.visitJumpInsn(Opcodes.GOTO, exit); + m.visitLabel(finallyHandler); + m.visitVarInsn(Opcodes.ASTORE, 2); + // finally + m.visitInsn(Opcodes.NOP); + m.visitVarInsn(Opcodes.ALOAD, 2); + m.visitInsn(Opcodes.ATHROW); + m.visitLabel(exit); + m.visitInsn(Opcodes.RETURN); + + filter.filter(m, this); + assertNull(fromInclusive); + } + + @Test + public void ecj() { + final Label start = new Label(); + final Label end = new Label(); + final Label handler = new Label(); + final Label handlerEnd = new Label(); + m.visitTryCatchBlock(start, end, handler, null); + m.visitTryCatchBlock(handler, handlerEnd, handler, null); + + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitFieldInsn(Opcodes.GETFIELD, "Target", "lock", + "Ljava/lang/Object;"); + m.visitInsn(Opcodes.DUP); + m.visitVarInsn(Opcodes.ASTORE, 1); + m.visitInsn(Opcodes.MONITORENTER); + m.visitLabel(start); + m.visitVarInsn(Opcodes.ALOAD, 0); + m.visitInsn(Opcodes.NOP); + m.visitVarInsn(Opcodes.ALOAD, 1); + m.visitInsn(Opcodes.MONITOREXIT); + m.visitLabel(end); + final Label exit = new Label(); + m.visitJumpInsn(Opcodes.GOTO, exit); + m.visitLabel(handler); + m.visitVarInsn(Opcodes.ALOAD, 1); + m.visitInsn(Opcodes.MONITOREXIT); + m.visitLabel(handlerEnd); + m.visitInsn(Opcodes.ATHROW); + m.visitLabel(exit); + m.visitInsn(Opcodes.RETURN); + + filter.filter(m, this); + assertEquals(handler.info, fromInclusive); + assertEquals(((LabelNode) exit.info).getPrevious(), toInclusive); + } + + public void ignore(AbstractInsnNode fromInclusive, + AbstractInsnNode toInclusive) { + assertNull(this.fromInclusive); + this.fromInclusive = fromInclusive; + this.toInclusive = toInclusive; + } + +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/InstructionTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/InstructionTest.java index 6ce99ed7..1dc5fc2c 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/InstructionTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/InstructionTest.java @@ -12,9 +12,12 @@ package org.jacoco.core.internal.flow; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; import org.junit.Before; import org.junit.Test; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.InsnNode; /** * Unit tests for {@link Instruction}. @@ -25,11 +28,14 @@ public class InstructionTest { @Before public void setup() { - instruction = new Instruction(123); + instruction = new Instruction(new InsnNode(Opcodes.NOP), 123); } @Test public void testInit() { + final InsnNode node = new InsnNode(Opcodes.NOP); + instruction = new Instruction(node, 123); + assertSame(node, instruction.getNode()); assertEquals(123, instruction.getLine()); assertEquals(0, instruction.getBranches()); assertEquals(0, instruction.getCoveredBranches()); @@ -48,14 +54,16 @@ public class InstructionTest { @Test public void testSetPredecessor() { - final Instruction predecessor = new Instruction(122); + final Instruction predecessor = new Instruction( + new InsnNode(Opcodes.NOP), 122); instruction.setPredecessor(predecessor); assertEquals(1, predecessor.getBranches()); } @Test public void testSetCovered() { - final Instruction predecessor = new Instruction(122); + final Instruction predecessor = new Instruction( + new InsnNode(Opcodes.NOP), 122); instruction.setPredecessor(predecessor); instruction.setCovered(); assertEquals(1, instruction.getCoveredBranches()); @@ -68,10 +76,11 @@ public class InstructionTest { @Test public void testSetCoveredOnLongSequence() { - final Instruction first = new Instruction(0); + final Instruction first = new Instruction(new InsnNode(Opcodes.NOP), 0); Instruction next = first; for (int i = 0; i < 0x10000; i++) { - final Instruction insn = new Instruction(i); + final Instruction insn = new Instruction(new InsnNode(Opcodes.NOP), + i); insn.setPredecessor(next); next = insn; } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/LabelInfoTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/LabelInfoTest.java index b412080a..b2fd0b5d 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/LabelInfoTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/LabelInfoTest.java @@ -20,6 +20,8 @@ import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.Test; import org.objectweb.asm.Label; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.InsnNode; /** * Unit tests for {@link LabelInfoTest}. @@ -159,7 +161,8 @@ public class LabelInfoTest { @Test public void testSetInstruction() { - final Instruction instruction = new Instruction(123); + final Instruction instruction = new Instruction( + new InsnNode(Opcodes.NOP), 123); LabelInfo.setInstruction(label, instruction); assertSame(instruction, LabelInfo.getInstruction(label)); } diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/filter/SynchronizedTest.java b/org.jacoco.core.test/src/org/jacoco/core/test/filter/SynchronizedTest.java new file mode 100644 index 00000000..1cfce301 --- /dev/null +++ b/org.jacoco.core.test/src/org/jacoco/core/test/filter/SynchronizedTest.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 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.filter; + +import org.jacoco.core.analysis.ICounter; +import org.jacoco.core.test.filter.targets.Synchronized; +import org.jacoco.core.test.validation.ValidationTestBase; +import org.junit.Test; + +/** + * Test of filtering of a bytecode that is generated for a synchronized + * statement. + */ +public class SynchronizedTest extends ValidationTestBase { + + public SynchronizedTest() { + super(Synchronized.class); + } + + /** + * {@link Synchronized#normal()} + */ + @Test + public void normal() { + assertLine("before", ICounter.FULLY_COVERED); + // when compiled with ECJ next line covered partly without filter: + assertLine("monitorEnter", ICounter.FULLY_COVERED); + assertLine("body", ICounter.FULLY_COVERED); + if (isJDKCompiler) { + // without filter next line covered partly: + assertLine("monitorExit", ICounter.FULLY_COVERED); + } else { + assertLine("monitorExit", ICounter.EMPTY); + } + assertLine("after", ICounter.FULLY_COVERED); + } + + /** + * {@link Synchronized#explicitException()} + */ + @Test + public void explicitException() { + assertLine("explicitException.monitorEnter", ICounter.FULLY_COVERED); + assertLine("explicitException.exception", ICounter.FULLY_COVERED); + // when compiled with javac next line covered fully without filter: + assertLine("explicitException.monitorExit", ICounter.EMPTY); + } + + /** + * {@link Synchronized#implicitException()} + */ + @Test + public void implicitException() { + assertLine("implicitException.monitorEnter", isJDKCompiler + ? ICounter.FULLY_COVERED : ICounter.PARTLY_COVERED); + assertLine("implicitException.exception", ICounter.NOT_COVERED); + if (isJDKCompiler) { + // without filter next line covered partly: + assertLine("implicitException.monitorExit", ICounter.NOT_COVERED); + } else { + assertLine("implicitException.monitorExit", ICounter.EMPTY); + } + } + +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Synchronized.java b/org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Synchronized.java new file mode 100644 index 00000000..94030978 --- /dev/null +++ b/org.jacoco.core.test/src/org/jacoco/core/test/filter/targets/Synchronized.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 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.filter.targets; + +import static org.jacoco.core.test.validation.targets.Stubs.ex; +import static org.jacoco.core.test.validation.targets.Stubs.nop; + +import org.jacoco.core.test.validation.targets.Stubs.StubException; + +/** + * This test target is a synchronized statement. + */ +public class Synchronized { + + private static final Object lock = new Object(); + + private static void normal() { + nop(); // $line-before$ + synchronized (lock) { // $line-monitorEnter$ + nop(); // $line-body$ + } // $line-monitorExit$ + nop(); // $line-after$ + } + + private static void explicitException() { + synchronized (lock) { // $line-explicitException.monitorEnter$ + throw new StubException(); // $line-explicitException.exception$ + } // $line-explicitException.monitorExit$ + } + + private static void implicitException() { + synchronized (lock) { // $line-implicitException.monitorEnter$ + ex(); // $line-implicitException.exception$ + } // $line-implicitException.monitorExit$ + } + + public static void main(String[] args) { + normal(); + + try { + explicitException(); + } catch (StubException e) { + } + + try { + implicitException(); + } catch (StubException e) { + } + } + +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ValidationTestBase.java b/org.jacoco.core.test/src/org/jacoco/core/test/validation/ValidationTestBase.java index aa6b35bd..46a19a5a 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/test/validation/ValidationTestBase.java +++ b/org.jacoco.core.test/src/org/jacoco/core/test/validation/ValidationTestBase.java @@ -37,7 +37,7 @@ import org.junit.Before; */ public abstract class ValidationTestBase { - static final boolean isJDKCompiler = Compiler.DETECT.isJDK(); + protected static final boolean isJDKCompiler = Compiler.DETECT.isJDK(); private static final String[] STATUS_NAME = new String[4]; |