Home | History | Annotate | Download | only in flow
      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  *    Marc R. Hoffmann - initial API and implementation
     10  *
     11  *******************************************************************************/
     12 package org.jacoco.core.internal.flow;
     13 
     14 import static org.junit.Assert.assertEquals;
     15 
     16 import java.util.Arrays;
     17 
     18 import org.jacoco.core.instr.MethodRecorder;
     19 import org.junit.After;
     20 import org.junit.Before;
     21 import org.junit.Test;
     22 import org.objectweb.asm.Label;
     23 import org.objectweb.asm.MethodVisitor;
     24 import org.objectweb.asm.Opcodes;
     25 import org.objectweb.asm.commons.AnalyzerAdapter;
     26 import org.objectweb.asm.util.Printer;
     27 
     28 /**
     29  * Unit tests for {@link MethodProbesAdapter}.
     30  */
     31 public class MethodProbesAdapterTest implements IProbeIdGenerator {
     32 
     33 	private Label label;
     34 
     35 	private int id;
     36 
     37 	private MethodRecorder expected, actual;
     38 
     39 	private MethodProbesVisitor expectedVisitor;
     40 
     41 	private MethodVisitor adapter;
     42 
     43 	private IFrame frame;
     44 
     45 	private static class TraceAdapter extends MethodProbesVisitor {
     46 
     47 		private final Printer printer;
     48 
     49 		TraceAdapter(MethodRecorder recorder) {
     50 			super(recorder.getVisitor());
     51 			printer = recorder.getPrinter();
     52 		}
     53 
     54 		@Override
     55 		public void visitProbe(int probeId) {
     56 			rec("visitProbe", Integer.valueOf(probeId));
     57 		}
     58 
     59 		@Override
     60 		public void visitInsnWithProbe(int opcode, int probeId) {
     61 			rec("visitInsnWithProbe", Integer.valueOf(opcode),
     62 					Integer.valueOf(probeId));
     63 		}
     64 
     65 		@Override
     66 		public void visitJumpInsnWithProbe(int opcode, Label label,
     67 				int probeId, IFrame frame) {
     68 			rec("visitJumpInsnWithProbe", Integer.valueOf(opcode), label,
     69 					Integer.valueOf(probeId));
     70 			frame.accept(this);
     71 		}
     72 
     73 		@Override
     74 		public void visitTableSwitchInsnWithProbes(int min, int max,
     75 				Label dflt, Label[] labels, IFrame frame) {
     76 			rec("visitTableSwitchInsnWithProbes", Integer.valueOf(min),
     77 					Integer.valueOf(max), dflt, labels);
     78 			frame.accept(this);
     79 		}
     80 
     81 		@Override
     82 		public void visitLookupSwitchInsnWithProbes(Label dflt, int[] keys,
     83 				Label[] labels, IFrame frame) {
     84 			rec("visitLookupSwitchInsnWithProbes", dflt, keys, labels);
     85 			frame.accept(this);
     86 		}
     87 
     88 		private void rec(String name, Object... args) {
     89 			printer.text.add(name + Arrays.asList(args));
     90 		}
     91 
     92 	}
     93 
     94 	@Before
     95 	public void setup() {
     96 		label = new Label();
     97 		id = 1000;
     98 		expected = new MethodRecorder();
     99 		expectedVisitor = new TraceAdapter(expected);
    100 		actual = new MethodRecorder();
    101 		MethodProbesVisitor actualVisitor = new TraceAdapter(actual);
    102 		MethodProbesAdapter probesAdapter = new MethodProbesAdapter(
    103 				actualVisitor, this);
    104 		final AnalyzerAdapter analyzer = new AnalyzerAdapter("Foo", 0, "doit",
    105 				"()V", probesAdapter);
    106 		probesAdapter.setAnalyzer(analyzer);
    107 		adapter = analyzer;
    108 		frame = new IFrame() {
    109 
    110 			public void accept(MethodVisitor mv) {
    111 			}
    112 		};
    113 	}
    114 
    115 	@After
    116 	public void verify() {
    117 		assertEquals(expected, actual);
    118 	}
    119 
    120 	@Test
    121 	public void testVisitProbe1() {
    122 		LabelInfo.setTarget(label);
    123 		LabelInfo.setSuccessor(label);
    124 
    125 		adapter.visitLabel(label);
    126 
    127 		expectedVisitor.visitProbe(1000);
    128 		expectedVisitor.visitLabel(label);
    129 	}
    130 
    131 	@Test
    132 	public void testVisitProbe2() {
    133 		LabelInfo.setTarget(label);
    134 		LabelInfo.setTarget(label);
    135 
    136 		adapter.visitLabel(label);
    137 
    138 		expectedVisitor.visitLabel(label);
    139 	}
    140 
    141 	@Test
    142 	public void testVisitProbe3() {
    143 		adapter.visitLabel(label);
    144 
    145 		expectedVisitor.visitLabel(label);
    146 	}
    147 
    148 	@Test
    149 	public void testVisitInsn1() {
    150 		adapter.visitInsn(Opcodes.RETURN);
    151 
    152 		expectedVisitor.visitInsnWithProbe(Opcodes.RETURN, 1000);
    153 	}
    154 
    155 	@Test
    156 	public void testVisitInsn2() {
    157 		adapter.visitInsn(Opcodes.ICONST_0);
    158 		adapter.visitInsn(Opcodes.ICONST_0);
    159 		adapter.visitInsn(Opcodes.IADD);
    160 
    161 		expectedVisitor.visitInsn(Opcodes.ICONST_0);
    162 		expectedVisitor.visitInsn(Opcodes.ICONST_0);
    163 		expectedVisitor.visitInsn(Opcodes.IADD);
    164 	}
    165 
    166 	@Test
    167 	public void testVisitJumpInsn1() {
    168 		LabelInfo.setTarget(label);
    169 		LabelInfo.setTarget(label);
    170 
    171 		adapter.visitJumpInsn(Opcodes.GOTO, label);
    172 
    173 		expectedVisitor
    174 				.visitJumpInsnWithProbe(Opcodes.GOTO, label, 1000, frame);
    175 		expectedVisitor.visitFrame(Opcodes.F_FULL, 1, new Object[] { "Foo" },
    176 				0, null);
    177 	}
    178 
    179 	@Test
    180 	public void testVisitJumpInsn2() {
    181 		LabelInfo.setTarget(label);
    182 		LabelInfo.setTarget(label);
    183 
    184 		adapter.visitInsn(Opcodes.ICONST_0);
    185 		adapter.visitJumpInsn(Opcodes.IFLT, label);
    186 
    187 		expectedVisitor.visitInsn(Opcodes.ICONST_0);
    188 		expectedVisitor
    189 				.visitJumpInsnWithProbe(Opcodes.IFLT, label, 1000, frame);
    190 		expectedVisitor.visitFrame(Opcodes.F_FULL, 1, new Object[] { "Foo" },
    191 				0, null);
    192 	}
    193 
    194 	@Test
    195 	public void testVisitJumpInsn3() {
    196 		adapter.visitInsn(Opcodes.ICONST_0);
    197 		adapter.visitJumpInsn(Opcodes.IFLT, label);
    198 
    199 		expectedVisitor.visitInsn(Opcodes.ICONST_0);
    200 		expectedVisitor.visitJumpInsn(Opcodes.IFLT, label);
    201 	}
    202 
    203 	@Test
    204 	public void testVisitJumpInsn4() {
    205 		LabelInfo.setTarget(label);
    206 		LabelInfo.setTarget(label);
    207 
    208 		adapter.visitInsn(Opcodes.ICONST_0);
    209 		adapter.visitInsn(Opcodes.ICONST_0);
    210 		adapter.visitJumpInsn(Opcodes.IF_ICMPEQ, label);
    211 
    212 		expectedVisitor.visitInsn(Opcodes.ICONST_0);
    213 		expectedVisitor.visitInsn(Opcodes.ICONST_0);
    214 		expectedVisitor.visitJumpInsnWithProbe(Opcodes.IF_ICMPEQ, label, 1000,
    215 				frame);
    216 		expectedVisitor.visitFrame(Opcodes.F_FULL, 1, new Object[] { "Foo" },
    217 				0, null);
    218 	}
    219 
    220 	@Test
    221 	public void testVisitLookupSwitchInsn1() {
    222 		LabelInfo.setTarget(label);
    223 		LabelInfo.setTarget(label);
    224 
    225 		final int[] keys = new int[] { 0, 1 };
    226 		final Label[] labels = new Label[] { label, label };
    227 		adapter.visitInsn(Opcodes.ICONST_0);
    228 		adapter.visitLookupSwitchInsn(label, keys, labels);
    229 
    230 		expectedVisitor.visitInsn(Opcodes.ICONST_0);
    231 		expectedVisitor.visitLookupSwitchInsnWithProbes(label, keys, labels,
    232 				frame);
    233 		expectedVisitor.visitFrame(Opcodes.F_FULL, 1, new Object[] { "Foo" },
    234 				0, null);
    235 		assertEquals(1000, LabelInfo.getProbeId(label));
    236 	}
    237 
    238 	@Test
    239 	public void testVisitLookupSwitchInsn2() {
    240 		Label label2 = new Label();
    241 		LabelInfo.setTarget(label2);
    242 		LabelInfo.setTarget(label2);
    243 
    244 		final int[] keys = new int[] { 0, 1 };
    245 		final Label[] labels = new Label[] { label2, label };
    246 		adapter.visitInsn(Opcodes.ICONST_0);
    247 		adapter.visitLookupSwitchInsn(label, keys, labels);
    248 
    249 		expectedVisitor.visitInsn(Opcodes.ICONST_0);
    250 		expectedVisitor.visitLookupSwitchInsnWithProbes(label, keys, labels,
    251 				frame);
    252 		expectedVisitor.visitFrame(Opcodes.F_FULL, 1, new Object[] { "Foo" },
    253 				0, null);
    254 		assertEquals(LabelInfo.NO_PROBE, LabelInfo.getProbeId(label));
    255 		assertEquals(1000, LabelInfo.getProbeId(label2));
    256 	}
    257 
    258 	@Test
    259 	public void testVisitLookupSwitchInsn3() {
    260 		final int[] keys = new int[] { 0, 1 };
    261 		final Label[] labels = new Label[] { label, label };
    262 		adapter.visitInsn(Opcodes.ICONST_0);
    263 		adapter.visitLookupSwitchInsn(label, keys, labels);
    264 
    265 		expectedVisitor.visitInsn(Opcodes.ICONST_0);
    266 		expectedVisitor.visitLookupSwitchInsn(label, keys, labels);
    267 	}
    268 
    269 	@Test
    270 	public void testVisitTableSwitchInsn1() {
    271 		LabelInfo.setTarget(label);
    272 		LabelInfo.setTarget(label);
    273 
    274 		final Label[] labels = new Label[] { label, label };
    275 		adapter.visitInsn(Opcodes.ICONST_0);
    276 		adapter.visitTableSwitchInsn(0, 1, label, labels);
    277 
    278 		expectedVisitor.visitInsn(Opcodes.ICONST_0);
    279 		expectedVisitor.visitTableSwitchInsnWithProbes(0, 1, label, labels,
    280 				frame);
    281 		expectedVisitor.visitFrame(Opcodes.F_FULL, 1, new Object[] { "Foo" },
    282 				0, null);
    283 		assertEquals(1000, LabelInfo.getProbeId(label));
    284 	}
    285 
    286 	@Test
    287 	public void testVisitTableSwitchInsn2() {
    288 		Label label2 = new Label();
    289 		LabelInfo.setTarget(label2);
    290 		LabelInfo.setTarget(label2);
    291 
    292 		final Label[] labels = new Label[] { label2, label };
    293 		adapter.visitInsn(Opcodes.ICONST_0);
    294 		adapter.visitTableSwitchInsn(0, 1, label, labels);
    295 
    296 		expectedVisitor.visitInsn(Opcodes.ICONST_0);
    297 		expectedVisitor.visitTableSwitchInsnWithProbes(0, 1, label, labels,
    298 				frame);
    299 		expectedVisitor.visitFrame(Opcodes.F_FULL, 1, new Object[] { "Foo" },
    300 				0, null);
    301 		assertEquals(LabelInfo.NO_PROBE, LabelInfo.getProbeId(label));
    302 		assertEquals(1000, LabelInfo.getProbeId(label2));
    303 	}
    304 
    305 	@Test
    306 	public void testVisitTableSwitchInsn3() {
    307 		final Label[] labels = new Label[] { label, label };
    308 		adapter.visitInsn(Opcodes.ICONST_0);
    309 		adapter.visitTableSwitchInsn(0, 1, label, labels);
    310 
    311 		expectedVisitor.visitInsn(Opcodes.ICONST_0);
    312 		expectedVisitor.visitTableSwitchInsn(0, 1, label, labels);
    313 	}
    314 
    315 	@Test
    316 	public void testVisitTryCatchBlockNoProbe() {
    317 		Label start = new Label();
    318 		Label end = new Label();
    319 		Label handler = new Label();
    320 
    321 		adapter.visitTryCatchBlock(start, end, handler, "java/lang/Exception");
    322 		adapter.visitLabel(start);
    323 
    324 		expectedVisitor.visitTryCatchBlock(start, end, handler,
    325 				"java/lang/Exception");
    326 		expectedVisitor.visitLabel(start);
    327 	}
    328 
    329 	@Test
    330 	public void testVisitTryCatchBlockWithProbe() {
    331 		Label target = new Label();
    332 		LabelInfo.setSuccessor(target);
    333 		LabelInfo.setTarget(target);
    334 		Label end = new Label();
    335 		Label handler = new Label();
    336 		Label start = new Label();
    337 
    338 		adapter.visitTryCatchBlock(target, end, handler, "java/lang/Exception");
    339 		adapter.visitLabel(target);
    340 
    341 		expectedVisitor.visitTryCatchBlock(start, end, handler,
    342 				"java/lang/Exception");
    343 		expectedVisitor.visitLabel(start);
    344 		expectedVisitor.visitProbe(1000);
    345 		expectedVisitor.visitLabel(target);
    346 	}
    347 
    348 	@Test
    349 	public void testVisitMultipleTryCatchBlocksWithProbe() {
    350 		Label target = new Label();
    351 		LabelInfo.setSuccessor(target);
    352 		LabelInfo.setTarget(target);
    353 		Label end = new Label();
    354 		Label handler1 = new Label();
    355 		Label handler2 = new Label();
    356 		Label start = new Label();
    357 
    358 		adapter.visitTryCatchBlock(target, end, handler1, "java/lang/Exception");
    359 		adapter.visitTryCatchBlock(target, end, handler2, "java/io/IOException");
    360 		adapter.visitLabel(target);
    361 
    362 		expectedVisitor.visitTryCatchBlock(start, end, handler1,
    363 				"java/lang/Exception");
    364 		expectedVisitor.visitTryCatchBlock(start, end, handler2,
    365 				"java/io/IOException");
    366 		expectedVisitor.visitLabel(start);
    367 		expectedVisitor.visitProbe(1000);
    368 		expectedVisitor.visitLabel(target);
    369 	}
    370 
    371 	// === IProbeIdGenerator ===
    372 
    373 	public int nextId() {
    374 		return id++;
    375 	}
    376 
    377 }
    378