1/*******************************************************************************
2 * Copyright (c) 2009, 2017 Mountainminds GmbH & Co. KG and Contributors
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *    Evgeny Mandrikov - initial API and implementation
10 *
11 *******************************************************************************/
12package org.jacoco.core.internal.analysis.filter;
13
14import static org.junit.Assert.assertEquals;
15import static org.junit.Assert.assertNull;
16
17import org.jacoco.core.internal.instr.InstrSupport;
18import org.junit.Test;
19import org.objectweb.asm.Label;
20import org.objectweb.asm.Opcodes;
21import org.objectweb.asm.tree.AbstractInsnNode;
22import org.objectweb.asm.tree.LabelNode;
23import org.objectweb.asm.tree.MethodNode;
24
25public class SynchronizedFilterTest implements IFilterOutput {
26
27	private final SynchronizedFilter filter = new SynchronizedFilter();
28
29	private final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
30			"name", "()V", null, null);
31
32	private AbstractInsnNode fromInclusive;
33	private AbstractInsnNode toInclusive;
34
35	@Test
36	public void javac() {
37		final Label start = new Label();
38		final Label end = new Label();
39		final Label handler = new Label();
40		final Label handlerEnd = new Label();
41		m.visitTryCatchBlock(start, end, handler, null);
42		m.visitTryCatchBlock(handler, handlerEnd, handler, null);
43
44		m.visitVarInsn(Opcodes.ALOAD, 0);
45		m.visitFieldInsn(Opcodes.GETFIELD, "Fun", "lock", "Ljava/lang/Object;");
46		m.visitInsn(Opcodes.DUP);
47		m.visitVarInsn(Opcodes.ASTORE, 1);
48		m.visitInsn(Opcodes.MONITORENTER);
49		m.visitLabel(start);
50		m.visitInsn(Opcodes.NOP);
51		m.visitVarInsn(Opcodes.ALOAD, 1);
52		m.visitInsn(Opcodes.MONITOREXIT);
53		m.visitLabel(end);
54		final Label exit = new Label();
55		m.visitJumpInsn(Opcodes.GOTO, exit);
56		m.visitLabel(handler);
57		m.visitVarInsn(Opcodes.ASTORE, 2);
58		m.visitVarInsn(Opcodes.ALOAD, 1);
59		m.visitInsn(Opcodes.MONITOREXIT);
60		m.visitLabel(handlerEnd);
61		m.visitVarInsn(Opcodes.ALOAD, 2);
62		m.visitInsn(Opcodes.ATHROW);
63		m.visitLabel(exit);
64		m.visitInsn(Opcodes.RETURN);
65
66		filter.filter("Foo", "java/lang/Object", m, this);
67		assertEquals(handler.info, fromInclusive);
68		assertEquals(((LabelNode) exit.info).getPrevious(), toInclusive);
69	}
70
71	/**
72	 * <pre>
73	 *     try {
74	 *         ...
75	 *     } catch (Exception e) {
76	 *         ...
77	 *     } finally {
78	 *         ...
79	 *     }
80	 * </pre>
81	 */
82	@Test
83	public void javacTryCatchFinally() {
84		final Label start = new Label();
85		final Label end = new Label();
86		final Label catchHandler = new Label();
87		final Label finallyHandler = new Label();
88		final Label catchHandlerEnd = new Label();
89		m.visitTryCatchBlock(start, end, catchHandler, "java/lang/Exception");
90		m.visitTryCatchBlock(start, end, finallyHandler, null);
91		m.visitTryCatchBlock(catchHandler, catchHandlerEnd, finallyHandler,
92				null);
93
94		m.visitLabel(start);
95		// body
96		m.visitInsn(Opcodes.NOP);
97		m.visitLabel(end);
98		// finally
99		m.visitInsn(Opcodes.NOP);
100		final Label exit = new Label();
101		m.visitJumpInsn(Opcodes.GOTO, exit);
102		m.visitLabel(catchHandler);
103		m.visitVarInsn(Opcodes.ASTORE, 1);
104		// catch
105		m.visitInsn(Opcodes.NOP);
106		m.visitLabel(catchHandlerEnd);
107		// finally
108		m.visitInsn(Opcodes.NOP);
109		m.visitJumpInsn(Opcodes.GOTO, exit);
110		m.visitLabel(finallyHandler);
111		m.visitVarInsn(Opcodes.ASTORE, 2);
112		// finally
113		m.visitInsn(Opcodes.NOP);
114		m.visitVarInsn(Opcodes.ALOAD, 2);
115		m.visitInsn(Opcodes.ATHROW);
116		m.visitLabel(exit);
117		m.visitInsn(Opcodes.RETURN);
118
119		filter.filter("Foo", "java/lang/Object", m, this);
120		assertNull(fromInclusive);
121	}
122
123	@Test
124	public void ecj() {
125		final Label start = new Label();
126		final Label end = new Label();
127		final Label handler = new Label();
128		final Label handlerEnd = new Label();
129		m.visitTryCatchBlock(start, end, handler, null);
130		m.visitTryCatchBlock(handler, handlerEnd, handler, null);
131
132		m.visitVarInsn(Opcodes.ALOAD, 0);
133		m.visitFieldInsn(Opcodes.GETFIELD, "Target", "lock",
134				"Ljava/lang/Object;");
135		m.visitInsn(Opcodes.DUP);
136		m.visitVarInsn(Opcodes.ASTORE, 1);
137		m.visitInsn(Opcodes.MONITORENTER);
138		m.visitLabel(start);
139		m.visitVarInsn(Opcodes.ALOAD, 0);
140		m.visitInsn(Opcodes.NOP);
141		m.visitVarInsn(Opcodes.ALOAD, 1);
142		m.visitInsn(Opcodes.MONITOREXIT);
143		m.visitLabel(end);
144		final Label exit = new Label();
145		m.visitJumpInsn(Opcodes.GOTO, exit);
146		m.visitLabel(handler);
147		m.visitVarInsn(Opcodes.ALOAD, 1);
148		m.visitInsn(Opcodes.MONITOREXIT);
149		m.visitLabel(handlerEnd);
150		m.visitInsn(Opcodes.ATHROW);
151		m.visitLabel(exit);
152		m.visitInsn(Opcodes.RETURN);
153
154		filter.filter("Foo", "java/lang/Object", m, this);
155		assertEquals(handler.info, fromInclusive);
156		assertEquals(((LabelNode) exit.info).getPrevious(), toInclusive);
157	}
158
159	public void ignore(AbstractInsnNode fromInclusive,
160			AbstractInsnNode toInclusive) {
161		assertNull(this.fromInclusive);
162		this.fromInclusive = fromInclusive;
163		this.toInclusive = toInclusive;
164	}
165
166}
167