com.offbynull.coroutines.instrumenter.asm.SearchUtilsTest.java Source code

Java tutorial

Introduction

Here is the source code for com.offbynull.coroutines.instrumenter.asm.SearchUtilsTest.java

Source

/*
 * 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);
    }

}