blob: a55615afea2946c05ce4a69572fc4e8435c5f9aa [file] [log] [blame]
/*******************************************************************************
* 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:
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
package org.jacoco.core.internal.flow;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
/**
* Unit tests for {@link ClassProbesAdapter}.
*/
public class ClassProbesAdapterTest {
private static class MockMethodVisitor extends MethodProbesVisitor {
boolean frame = false;
@Override
public void visitJumpInsnWithProbe(int opcode, Label label,
int probeId, IFrame frame) {
frame.accept(this);
}
@Override
public void visitTableSwitchInsnWithProbes(int min, int max,
Label dflt, Label[] labels, IFrame frame) {
frame.accept(this);
}
@Override
public void visitLookupSwitchInsnWithProbes(Label dflt, int[] keys,
Label[] labels, IFrame frame) {
frame.accept(this);
}
@Override
public void visitFrame(int type, int nLocal, Object[] local,
int nStack, Object[] stack) {
frame = true;
}
}
private static class MockClassVisitor extends ClassProbesVisitor {
int count;
@Override
public MethodProbesVisitor visitMethod(int access, String name,
String desc, String signature, String[] exceptions) {
return null;
}
@Override
public void visitTotalProbeCount(int count) {
this.count = count;
}
}
@Test
public void testProbeCounter() {
final MockClassVisitor cv = new MockClassVisitor();
final ClassProbesAdapter adapter = new ClassProbesAdapter(cv, false);
assertEquals(0, adapter.nextId());
assertEquals(1, adapter.nextId());
assertEquals(2, adapter.nextId());
adapter.visitEnd();
assertEquals(3, cv.count);
}
@Test
public void testVisitClassMethods() {
final MockClassVisitor cv = new MockClassVisitor() {
@Override
public MethodProbesVisitor visitMethod(int access, String name,
String desc, String signature, String[] exceptions) {
return new MockMethodVisitor();
}
};
final ClassProbesAdapter adapter = new ClassProbesAdapter(cv, false);
adapter.visit(Opcodes.V1_5, 0, "Foo", null, "java/lang/Object", null);
writeMethod(adapter);
writeMethod(adapter);
writeMethod(adapter);
assertEquals(0, cv.count);
adapter.visitEnd();
assertEquals(3, cv.count);
}
@Test
public void testVisitMethodNullMethodVisitor() {
final MockClassVisitor cv = new MockClassVisitor();
final ClassProbesAdapter adapter = new ClassProbesAdapter(cv, false);
writeMethod(adapter); // 1 probe
writeMethodWithBranch(adapter); // 3 probes
writeMethodWithTableSwitch(adapter); // 3 probes
writeMethodWithLookupSwitch(adapter); // 3 probes
adapter.visitEnd();
assertEquals(10, cv.count);
}
@Test
public void testVisitWithFrames() {
final MockMethodVisitor mv = new MockMethodVisitor();
final MockClassVisitor cv = new MockClassVisitor() {
@Override
public MethodProbesVisitor visitMethod(int access, String name,
String desc, String signature, String[] exceptions) {
return mv;
}
};
final ClassProbesAdapter adapter = new ClassProbesAdapter(cv, true);
writeMethodWithBranch(adapter);
adapter.visitEnd();
assertTrue(mv.frame);
}
@Test
public void testVisitWithoutFrames() {
final MockMethodVisitor mv = new MockMethodVisitor();
final MockClassVisitor cv = new MockClassVisitor() {
@Override
public MethodProbesVisitor visitMethod(int access, String name,
String desc, String signature, String[] exceptions) {
return mv;
}
};
final ClassProbesAdapter adapter = new ClassProbesAdapter(cv, false);
writeMethodWithBranch(adapter);
adapter.visitEnd();
assertFalse(mv.frame);
}
private void writeMethod(final ClassVisitor cv) {
MethodVisitor mv = cv.visitMethod(0, "foo", "()V", null, null);
mv.visitCode();
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 1);
mv.visitEnd();
}
private void writeMethodWithBranch(final ClassVisitor cv) {
MethodVisitor mv = cv.visitMethod(0, "foo", "()V", null, null);
mv.visitCode();
mv.visitInsn(Opcodes.ICONST_0);
Label l = new Label();
mv.visitJumpInsn(Opcodes.IFEQ, l);
mv.visitInsn(Opcodes.NOP);
mv.visitLabel(l);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
private void writeMethodWithTableSwitch(final ClassVisitor cv) {
MethodVisitor mv = cv.visitMethod(0, "foo", "()V", null, null);
mv.visitCode();
mv.visitInsn(Opcodes.ICONST_0);
Label l1 = new Label();
Label l2 = new Label();
mv.visitTableSwitchInsn(0, 0, l1, new Label[] { l2 });
mv.visitLabel(l1);
mv.visitInsn(Opcodes.NOP);
mv.visitLabel(l2);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
private void writeMethodWithLookupSwitch(final ClassVisitor cv) {
MethodVisitor mv = cv.visitMethod(0, "foo", "()V", null, null);
mv.visitCode();
mv.visitInsn(Opcodes.ICONST_0);
Label l1 = new Label();
Label l2 = new Label();
mv.visitLookupSwitchInsn(l1, new int[] { 0 }, new Label[] { l2 });
mv.visitLabel(l1);
mv.visitInsn(Opcodes.NOP);
mv.visitLabel(l2);
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
}