package org.kantega.revoc.analysis; import org.junit.Before; import org.junit.Test; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.MethodNode; import java.io.IOException; import java.util.HashMap; import java.util.Map; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** * */ public class OneLineAnalyzeTest { private OneLineAnalyze analyze; private InsnList instructions; @Before public void before() throws IOException { ClassReader reader = new ClassReader(getClass().getResourceAsStream("OneLiner.class")); final Map<String, MethodNode> methods = new HashMap<>(); reader.accept(new ClassVisitor(Opcodes.ASM5) { @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { return new MethodNode(Opcodes.ASM5, access, name, desc , signature, exceptions) { @Override public void visitEnd() { methods.put(name, this); } }; } }, ClassReader.EXPAND_FRAMES); MethodNode run = methods.get("run"); instructions = run.instructions; analyze = OneLineAnalyze.analyze(run); } @Test public void shouldIdentifyOneliners() throws IOException { int exitInstruction = analyze.instructionSize()-2; assertTrue(analyze.mustHaveRunOnce(exitInstruction, 0)); assertTrue(analyze.mustHaveRunOnce(exitInstruction, 1)); assertFalse(analyze.mustHaveRunOnce(exitInstruction, 2));// In a loop assertFalse(analyze.mustHaveRunOnce(exitInstruction, 3)); assertTrue(analyze.mustHaveRunOnce(exitInstruction, 4)); assertFalse(analyze.mustHaveRunOnce(exitInstruction, 5)); assertFalse(analyze.mustHaveRunOnce(exitInstruction, 6)); assertFalse(analyze.mustHaveRunOnce(exitInstruction, 7)); assertFalse(analyze.mustHaveRunOnce(exitInstruction, 8)); assertFalse(analyze.mustHaveRunOnce(exitInstruction, 9)); assertTrue(analyze.mustHaveRunOnce(exitInstruction, 11)); assertTrue(analyze.mustHaveRunOnce(exitInstruction, 12)); } @Test public void shouldIdentifyMustHaveRun() throws IOException { int exitInstruction = analyze.instructionSize()-2; assertTrue(analyze.mustHaveRun(exitInstruction, 0)); assertTrue(analyze.mustHaveRun(exitInstruction, 1)); assertTrue(analyze.mustHaveRun(exitInstruction, 2)); // In a loop assertFalse(analyze.mustHaveRun(exitInstruction, 3)); assertTrue(analyze.mustHaveRun(exitInstruction, 4)); assertFalse(analyze.mustHaveRun(exitInstruction, 5)); assertFalse(analyze.mustHaveRun(exitInstruction, 6)); assertFalse(analyze.mustHaveRun(exitInstruction, 7)); assertFalse(analyze.mustHaveRun(exitInstruction, 8)); assertFalse(analyze.mustHaveRun(exitInstruction, 9)); assertTrue(analyze.mustHaveRun(exitInstruction, 11)); assertTrue(analyze.mustHaveRun(exitInstruction, 12)); } @Test public void shouldIdentifyCantHaveRun() throws IOException { int exitInstruction = 72; for(int i = 0; i < 12; i++) { if(i < 11) { assertFalse("Line index " + i + " should be runnable when exiting from instruction " + exitInstruction, analyze.cantHaveRun(exitInstruction, i)); } else { assertTrue(analyze.cantHaveRun(exitInstruction, i)); } } } }