Java tutorial
/* * Copyright (c) 2015, Kasra Faghihi, All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. */ package com.offbynull.coroutines.instrumenter.asm; import static com.offbynull.coroutines.instrumenter.asm.SearchUtils.findInvocationsOf; import static com.offbynull.coroutines.instrumenter.asm.SearchUtils.findInvocationsWithParameter; import static com.offbynull.coroutines.instrumenter.asm.SearchUtils.findMethodsWithName; import static com.offbynull.coroutines.instrumenter.asm.SearchUtils.findMethodsWithParameter; import static com.offbynull.coroutines.instrumenter.asm.SearchUtils.searchForOpcodes; import static com.offbynull.coroutines.instrumenter.testhelpers.TestUtils.readZipResourcesAsClassNodes; import java.io.IOException; import java.io.PrintStream; import java.util.List; import org.apache.commons.lang3.reflect.MethodUtils; import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Test; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; public final class SearchUtilsTest { private ClassNode classNode; @Before public void setUp() throws IOException { classNode = readZipResourcesAsClassNodes("SearchUtilsStubs.zip").get("SearchUtilsStubs.class"); } @Test public void mustFindMethodsWithName() { List<MethodNode> methodNodes = findMethodsWithName(classNode.methods, "syncTest"); assertEquals(1, methodNodes.size()); assertEquals("syncTest", methodNodes.get(0).name); } @Test public void mustFindMethodsWithIntParameters() { List<MethodNode> methodNodes = findMethodsWithParameter(classNode.methods, Type.INT_TYPE); assertEquals(2, methodNodes.size()); assertEquals("method1", methodNodes.get(0).name); assertEquals("method2", methodNodes.get(1).name); } @Test public void mustFindMethodsWithStringParameters() { List<MethodNode> methodNodes = findMethodsWithParameter(classNode.methods, Type.getType(String.class)); assertEquals(1, methodNodes.size()); assertEquals("method2", methodNodes.get(0).name); } @Test public void mustFindOpcodeWithinMethod() { MethodNode methodNode = findMethodsWithName(classNode.methods, "syncTest").get(0); List<AbstractInsnNode> insns = searchForOpcodes(methodNode.instructions, Opcodes.MONITORENTER, Opcodes.MONITOREXIT); assertEquals(3, insns.size()); assertEquals(Opcodes.MONITORENTER, insns.get(0).getOpcode()); assertEquals(Opcodes.MONITOREXIT, insns.get(1).getOpcode()); assertEquals(Opcodes.MONITOREXIT, insns.get(2).getOpcode()); // hidden trycatch block generated by compiler } @Test public void mustFindCallToPrintlnThroughParameterTypeMatching() { MethodNode methodNode = findMethodsWithName(classNode.methods, "syncTest").get(0); List<AbstractInsnNode> insns = findInvocationsWithParameter(methodNode.instructions, Type.getType(String.class)); assertEquals(1, insns.size()); assertEquals("println", ((MethodInsnNode) insns.get(0)).name); } @Test public void mustFindCallToPrintlnThroughMethodMatching() { MethodNode methodNode = findMethodsWithName(classNode.methods, "syncTest").get(0); List<AbstractInsnNode> insns = findInvocationsOf(methodNode.instructions, MethodUtils.getAccessibleMethod(PrintStream.class, "println", String.class)); assertEquals(1, insns.size()); assertEquals("println", ((MethodInsnNode) insns.get(0)).name); } @Test public void mustProperlyDetermineStackSizeForNormalMethod() { Type type = Type.getType(MethodUtils.getAccessibleMethod(Integer.class, "compareTo", Integer.class)); MethodInsnNode methodInsnNode = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/util/Integer", "compareTo", type.getDescriptor(), false); int reqStackCount = SearchUtils.getRequiredStackCountForInvocation(methodInsnNode); assertEquals(2, reqStackCount); } @Test public void mustProperlyDetermineStackSizeForStaticMethod() { Type type = Type.getType(MethodUtils.getAccessibleMethod(Integer.class, "decode", String.class)); MethodInsnNode methodInsnNode = new MethodInsnNode(Opcodes.INVOKESTATIC, "java/util/Integer", "decode", type.getDescriptor(), false); int reqStackCount = SearchUtils.getRequiredStackCountForInvocation(methodInsnNode); assertEquals(1, reqStackCount); } }