package com.mebigfatguy.fbcontrib.utils;
import static org.apache.bcel.Constants.ACC_PUBLIC;
import static org.apache.bcel.Constants.ACC_STATIC;
import static org.apache.bcel.Constants.ALOAD;
import static org.apache.bcel.Constants.ALOAD_0;
import static org.apache.bcel.Constants.ALOAD_1;
import static org.apache.bcel.Constants.ALOAD_2;
import static org.apache.bcel.Constants.ALOAD_3;
import static org.apache.bcel.Constants.ASTORE;
import static org.apache.bcel.Constants.ASTORE_0;
import static org.apache.bcel.Constants.ASTORE_1;
import static org.apache.bcel.Constants.ASTORE_2;
import static org.apache.bcel.Constants.ASTORE_3;
import static org.apache.bcel.Constants.DLOAD;
import static org.apache.bcel.Constants.DLOAD_0;
import static org.apache.bcel.Constants.DLOAD_1;
import static org.apache.bcel.Constants.DLOAD_2;
import static org.apache.bcel.Constants.DLOAD_3;
import static org.apache.bcel.Constants.DSTORE;
import static org.apache.bcel.Constants.DSTORE_0;
import static org.apache.bcel.Constants.DSTORE_1;
import static org.apache.bcel.Constants.DSTORE_2;
import static org.apache.bcel.Constants.DSTORE_3;
import static org.apache.bcel.Constants.FLOAD;
import static org.apache.bcel.Constants.FLOAD_0;
import static org.apache.bcel.Constants.FLOAD_1;
import static org.apache.bcel.Constants.FLOAD_2;
import static org.apache.bcel.Constants.FLOAD_3;
import static org.apache.bcel.Constants.FSTORE;
import static org.apache.bcel.Constants.FSTORE_0;
import static org.apache.bcel.Constants.FSTORE_1;
import static org.apache.bcel.Constants.FSTORE_2;
import static org.apache.bcel.Constants.FSTORE_3;
import static org.apache.bcel.Constants.ILOAD;
import static org.apache.bcel.Constants.ILOAD_0;
import static org.apache.bcel.Constants.ILOAD_1;
import static org.apache.bcel.Constants.ILOAD_2;
import static org.apache.bcel.Constants.ILOAD_3;
import static org.apache.bcel.Constants.ISTORE;
import static org.apache.bcel.Constants.ISTORE_0;
import static org.apache.bcel.Constants.ISTORE_1;
import static org.apache.bcel.Constants.ISTORE_2;
import static org.apache.bcel.Constants.ISTORE_3;
import static org.apache.bcel.Constants.LLOAD;
import static org.apache.bcel.Constants.LLOAD_0;
import static org.apache.bcel.Constants.LLOAD_1;
import static org.apache.bcel.Constants.LLOAD_2;
import static org.apache.bcel.Constants.LLOAD_3;
import static org.apache.bcel.Constants.LSTORE;
import static org.apache.bcel.Constants.LSTORE_0;
import static org.apache.bcel.Constants.LSTORE_1;
import static org.apache.bcel.Constants.LSTORE_2;
import static org.apache.bcel.Constants.LSTORE_3;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import org.apache.bcel.classfile.Constant;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.ConstantUtf8;
import org.apache.bcel.classfile.Method;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import edu.umd.cs.findbugs.FindBugs;
import edu.umd.cs.findbugs.visitclass.DismantleBytecode;
public class RegisterUtilsTest {
private static final int OPERAND = 12345;
@Mock
private DismantleBytecode dbc;
@BeforeSuite
public void setUpClass() {
FindBugs.setHome("target/findbugs-3.0.1.jar");
}
@BeforeMethod
public void setUp() {
MockitoAnnotations.initMocks(this);
when(dbc.getRegisterOperand()).thenReturn(OPERAND);
}
@DataProvider(name = "parameterRegisters")
Object[][] parameterRegisters() {
return new Object[][] {
// access flags, signature, expected registers
{ ACC_PUBLIC | ACC_STATIC, "(JLjava/lang/String;[[I)V", new int[] { 0, 2, 3 } }, { ACC_STATIC, "(Ljava/lang/Object;)Z", new int[] { 0 } },
{ ACC_PUBLIC, "(DJ[D[J)V", new int[] { 1, 3, 5, 6 } }, { 0, "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", new int[] { 1, 2 } }, };
}
@DataProvider(name = "reg_ASTORE")
Object[][] reg_ASTORE() {
return new Object[][] { { ASTORE, OPERAND }, { ASTORE_0, 0 }, { ASTORE_1, 1 }, { ASTORE_2, 2 }, { ASTORE_3, 3 }, { ASTORE_0 - 1, -1 },
{ ASTORE_3 + 1, -1 }, };
}
@DataProvider(name = "reg_ALOAD")
Object[][] reg_ALOAD() {
return new Object[][] { { ALOAD_0, 0 }, { ALOAD_1, 1 }, { ALOAD_2, 2 }, { ALOAD_3, 3 }, { ALOAD_0 - 1, -1 }, { ALOAD_3 + 1, -1 }, };
}
@DataProvider(name = "regStore")
Object[][] regStore() {
return new Object[][] { { ASTORE, OPERAND }, { ISTORE, OPERAND }, { LSTORE, OPERAND }, { FSTORE, OPERAND }, { DSTORE, OPERAND }, { ASTORE_0, 0 },
{ ASTORE_1, 1 }, { ASTORE_2, 2 }, { ASTORE_3, 3 }, { ISTORE_0, 0 }, { ISTORE_1, 1 }, { ISTORE_2, 2 }, { ISTORE_3, 3 }, { LSTORE_0, 0 },
{ LSTORE_1, 1 }, { LSTORE_2, 2 }, { LSTORE_3, 3 }, { FSTORE_0, 0 }, { FSTORE_1, 1 }, { FSTORE_2, 2 }, { FSTORE_3, 3 }, { DSTORE_0, 0 },
{ DSTORE_1, 1 }, { DSTORE_2, 2 }, { DSTORE_3, 3 }, { Integer.MIN_VALUE, -1 }, { Integer.MAX_VALUE, -1 }, };
}
@DataProvider(name = "regLoad")
Object[][] regLoad() {
return new Object[][] { { ALOAD, OPERAND }, { ILOAD, OPERAND }, { LLOAD, OPERAND }, { FLOAD, OPERAND }, { DLOAD, OPERAND }, { ALOAD_0, 0 },
{ ALOAD_1, 1 }, { ALOAD_2, 2 }, { ALOAD_3, 3 }, { ILOAD_0, 0 }, { ILOAD_1, 1 }, { ILOAD_2, 2 }, { ILOAD_3, 3 }, { LLOAD_0, 0 }, { LLOAD_1, 1 },
{ LLOAD_2, 2 }, { LLOAD_3, 3 }, { FLOAD_0, 0 }, { FLOAD_1, 1 }, { FLOAD_2, 2 }, { FLOAD_3, 3 }, { DLOAD_0, 0 }, { DLOAD_1, 1 }, { DLOAD_2, 2 },
{ DLOAD_3, 3 }, { Integer.MIN_VALUE, -1 }, { Integer.MAX_VALUE, -1 }, };
}
@Test(dataProvider = "parameterRegisters")
public void shouldGetParameterRegisters(int accessFlags, String signature, int[] expected) {
Method method = new Method();
method.setAccessFlags(accessFlags);
Constant[] cnst = new Constant[] { new ConstantUtf8(signature) };
ConstantPool cp = new ConstantPool(cnst) {
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
};
method.setConstantPool(cp);
method.setSignatureIndex(0);
int[] regs = RegisterUtils.getParameterRegisters(method);
assertEquals(regs, expected);
}
@Test(dataProvider = "reg_ASTORE")
public void shouldReturnOffsetWhenSeenASTORE(int seen, int expected) {
assertEquals(RegisterUtils.getAStoreReg(dbc, seen), expected);
}
@Test(dataProvider = "reg_ALOAD")
public void shouldReturnOffsetWhenSeenALOAD(int seen, int expected) {
assertEquals(RegisterUtils.getALoadReg(dbc, seen), expected);
}
@Test(dataProvider = "regStore")
public void shouldReturnStoreReg(int seen, int expected) {
assertEquals(RegisterUtils.getStoreReg(dbc, seen), expected);
}
@Test(dataProvider = "regLoad")
public void shouldReturnLoadReg(int seen, int expected) {
assertEquals(RegisterUtils.getLoadReg(dbc, seen), expected);
}
}