Added test cases.

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1347 379699f6-c40d-0410-875b-85095c16579e
master
hoenicke 23 years ago
parent 7714d5d503
commit 14b4dd94f8
  1. 214
      jode/test/src/net/sf/jode/bytecode/BasicBlockWriterTest.java
  2. 47
      jode/test/src/net/sf/jode/bytecode/BasicBlocksTest.java
  3. 44
      jode/test/src/net/sf/jode/bytecode/BlockTest.java
  4. 358
      jode/test/src/net/sf/jode/flow/TrExcTest.java
  5. 186
      jode/test/src/net/sf/jode/obfuscator/modules/ConstAnaTest.java

@ -0,0 +1,214 @@
package net.sf.jode.bytecode;
import junit.framework.*;
import java.io.*;
public class BasicBlockWriterTest extends TestCase implements Opcodes {
public BasicBlockWriterTest(String name) {
super(name);
}
GrowableConstantPool gcp = new GrowableConstantPool();
Instruction[] someNops;
Instruction[] manyNops;
Instruction[] whileHead;
Instruction[] whileCond;
Instruction[] whileFoot;
/**
* The whileHead block in bytecode
*/
private final static String whileHeadStr="\3=";
/**
* The whileCond block in bytecode, without the if_icmpeq instruction.
*/
private final static String whileCondStr="\34\33";
/**
* The whileFoot block in bytecode.
*/
private final static String whileFootStr="\204\2\1";
/**
* The someNops block in bytecode, without the if_icmpeq instruction.
*/
private final static String someNopsStr="\0\0";
public void setUp() {
Instruction nop = Instruction.forOpcode(opc_nop);
someNops = new Instruction[] { nop, nop };
manyNops = new Instruction[35000];
for (int i = 0; i < manyNops.length; i++)
manyNops[i] = nop;
whileHead = new Instruction[] {
Instruction.forOpcode(opc_ldc, new Integer(0)),
Instruction.forOpcode(opc_istore, LocalVariableInfo.getInfo(2)),
};
whileCond = new Instruction[] {
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(2)),
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)),
Instruction.forOpcode(opc_if_icmpeq)
};
whileFoot = new Instruction[] {
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(2), 1),
};
}
public byte[] write(BasicBlockWriter bbw) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
bbw.write(gcp, dos);
dos.close();
return baos.toByteArray();
}
public void testEmpty() throws IOException {
BasicBlocks bb = new BasicBlocks(new MethodInfo("foo", "()V", 0));
bb.setBlocks(new Block[0], null, new Handler[0]);
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp);
gcp.write(new DataOutputStream(new ByteArrayOutputStream()));
assertEquals("Code differs",
"\0\0\0\1\0\0\0\1" /* no stack, one local, length 1 */
+"\261" /* opc_return */
+"\0\0" /* no exception handlers */,
new String(write(bbw)));
}
public void testSimple() throws IOException {
Block bb1 = new Block();
Block bb2 = new Block();
bb1.setCode(someNops, new Block[] {bb2});
bb2.setCode(someNops, new Block[] {null});
BasicBlocks bb = new BasicBlocks(new MethodInfo("foo", "()V", 0));
bb.setBlocks(new Block[] { bb1, bb2}, bb1, new Handler[0]);
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp);
gcp.write(new DataOutputStream(new ByteArrayOutputStream()));
assertEquals("Code differs",
"\0\0\0\1\0\0\0\5" /* no stack, one local, length 5 */
+someNopsStr+someNopsStr+"\261"
+"\0\0" /* no exception handlers */,
new String(write(bbw)));
}
public void testWhile() throws IOException {
Block b1 = new Block();
Block b2 = new Block();
Block b3 = new Block();
Block b4 = new Block();
b1.setCode(whileHead, new Block[] { b2 });
b2.setCode(whileCond, new Block[] { null, b3 });
b3.setCode(someNops, new Block[] { b4 });
b4.setCode(whileFoot, new Block[] { b2 });
BasicBlocks bb = new BasicBlocks(new MethodInfo("a", "(I)V", 0));
bb.setBlocks(new Block[] { b1, b2, b3, b4}, b1, new Handler[0]);
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp);
gcp.write(new DataOutputStream(new ByteArrayOutputStream()));
assertEquals(5, bbw.blockAddr.length);
assertEquals(0, bbw.blockAddr[0]);
assertEquals(2, bbw.blockAddr[1]);
assertEquals(7, bbw.blockAddr[2]);
assertEquals(9, bbw.blockAddr[3]);
assertEquals(16, bbw.blockAddr[4]);
assertEquals("Code differs",
"\0\2\0\3\0\0\0\20"
+whileHeadStr+whileCondStr+"\237\0\13"
+someNopsStr+whileFootStr+"\247\377\366"+"\261"+"\0\0",
new String(write(bbw)));
}
public void testTableSwitch() throws IOException {
Block b1 = new Block();
Block b2 = new Block();
Instruction[] switchBlock = new Instruction[] {
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)),
Instruction.forOpcode(opc_lookupswitch, new int[] { 1, 3, 5})
};
b1.setCode(switchBlock, new Block[] { b2, null, b1, null });
b2.setCode(someNops, new Block[] { null });
BasicBlocks bb = new BasicBlocks(new MethodInfo("s", "(I)V", 0));
bb.setBlocks(new Block[] { b1, b2 }, b1, new Handler[0]);
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp);
gcp.write(new DataOutputStream(new ByteArrayOutputStream()));
assertEquals(3, bbw.blockAddr.length);
assertEquals(0, bbw.blockAddr[0]);
assertEquals(36, bbw.blockAddr[1]);
assertEquals(39, bbw.blockAddr[2]);
assertEquals("Code differs",
"\0\1\0\2\0\0\0\47"
+"\33\252\0\0" /*iload_0 + tableswitch + align */
+"\0\0\0\45\0\0\0\1\0\0\0\5" /* def, low, high */
+"\0\0\0\43\0\0\0\45\0\0\0\45\0\0\0\45\377\377\377\377"
+someNopsStr+"\261"+"\0\0",
new String(write(bbw)));
}
public void testLookupSwitch() throws IOException {
Block b1 = new Block();
Block b2 = new Block();
Instruction[] switchBlock = new Instruction[] {
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)),
Instruction.forOpcode(opc_lookupswitch, new int[] { 1, 5, 7})
};
b1.setCode(switchBlock, new Block[] { b2, null, b1, null });
b2.setCode(someNops, new Block[] { null });
BasicBlocks bb = new BasicBlocks(new MethodInfo("s", "(I)V", 0));
bb.setBlocks(new Block[] { b1, b2 }, b1, new Handler[0]);
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp);
gcp.write(new DataOutputStream(new ByteArrayOutputStream()));
assertEquals(3, bbw.blockAddr.length);
assertEquals(0, bbw.blockAddr[0]);
assertEquals(36, bbw.blockAddr[1]);
assertEquals(39, bbw.blockAddr[2]);
assertEquals("Code differs",
"\0\1\0\2\0\0\0\47"
+"\33\253\0\0" /*iload_0 + lookupswitch + align */
+"\0\0\0\45\0\0\0\3" /* def , nitem */
+"\0\0\0\1\0\0\0\43"
+"\0\0\0\5\0\0\0\45"
+"\0\0\0\7\377\377\377\377"
+someNopsStr+"\261"+"\0\0",
new String(write(bbw)));
}
public void testException() throws IOException {
Block b1 = new Block();
Block b2 = new Block();
Instruction[] catchInstrs = new Instruction[] {
Instruction.forOpcode(opc_athrow)
};
b1.setCode(someNops, new Block[] { null });
b2.setCode(catchInstrs, new Block[0]);
BasicBlocks bb = new BasicBlocks(new MethodInfo("e", "()V", 0));
Handler h = new Handler(b1, b1, b2, "java.lang.RuntimeException");
bb.setBlocks(new Block[] { b1, b2 }, b1, new Handler[] {h});
assertEquals(0, b1.blockNr);
assertEquals(1, b2.blockNr);
assertEquals(1, b1.catchers.length);
assertEquals(0, b2.catchers.length);
assertSame(h, b1.catchers[0]);
BasicBlockWriter bbw = new BasicBlockWriter(bb, gcp);
gcp.write(new DataOutputStream(new ByteArrayOutputStream()));
int cpoolEntry = gcp.putClassName("java.lang.RuntimeException");
assertEquals(3, bbw.blockAddr.length);
assertEquals(0, bbw.blockAddr[0]);
assertEquals(3, bbw.blockAddr[1]);
assertEquals(4, bbw.blockAddr[2]);
assertEquals("Code differs",
"\0\1\0\1\0\0\0\4"
+ someNopsStr + "\261" + "\277"
+ "\0\1\0\0\0\3\0\3\0"+(char)cpoolEntry,
new String(write(bbw)));
}
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(new BasicBlockWriterTest("testEmpty"));
suite.addTest(new BasicBlockWriterTest("testSimple"));
suite.addTest(new BasicBlockWriterTest("testWhile"));
suite.addTest(new BasicBlockWriterTest("testTableSwitch"));
suite.addTest(new BasicBlockWriterTest("testLookupSwitch"));
suite.addTest(new BasicBlockWriterTest("testException"));
return suite;
}
}

@ -0,0 +1,47 @@
package net.sf.jode.bytecode;
import junit.framework.*;
import java.io.*;
public class BasicBlocksTest extends TestCase implements Opcodes {
public BasicBlocksTest(String name) {
super(name);
}
public void testJsr() {
Block b0 = new Block();
Block b1 = new Block();
Block b2 = new Block();
b0.setCode(new Instruction[] {
Instruction.forOpcode(opc_jsr)
}, new Block[] { b1, null });
b1.setCode(new Instruction[] {
Instruction.forOpcode(opc_astore, LocalVariableInfo.getInfo(2)),
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(1), -1),
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)),
Instruction.forOpcode(opc_ifeq)
}, new Block[] { b2, b0 });
b2.setCode(new Instruction[] {
Instruction.forOpcode(opc_ret, LocalVariableInfo.getInfo(0)),
}, new Block[0]);
assertEquals("pop0", 0, b0.maxpop);
assertEquals("push0", 0, b0.maxpush);
assertEquals("delta0", 0, b0.delta);
assertEquals("pop1", 1, b1.maxpop);
assertEquals("push1", 0, b1.maxpush);
assertEquals("delta1", -1, b1.delta);
assertEquals("pop2", 0, b2.maxpop);
assertEquals("push2", 0, b2.maxpush);
assertEquals("delta2", 0, b2.delta);
BasicBlocks bb = new BasicBlocks(new MethodInfo("foo", "(I)V", 0));
bb.setBlocks(new Block[] { b0, b1, b2 }, b0, new Handler[0]);
assertEquals("stack0", 0, b0.stackHeight);
assertEquals("stack1", 1, b1.stackHeight);
assertEquals("stack2", 0, b2.stackHeight);
}
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(new BasicBlocksTest("testJsr"));
return suite;
}
}

@ -0,0 +1,44 @@
package net.sf.jode.bytecode;
import junit.framework.*;
import java.io.*;
public class BlockTest extends TestCase implements Opcodes {
public BlockTest(String name) {
super(name);
}
public void testJsr() {
Block b1 = new Block();
Block b2 = new Block();
Instruction jsr = Instruction.forOpcode(opc_jsr);
b1.setCode(new Instruction[] { jsr }, new Block[] { b2, null } );
assertEquals("pop", 0, b1.maxpop);
assertEquals("push", 0, b1.maxpush);
assertEquals("delta", 0, b1.delta);
try {
b1.setCode(new Instruction[] { jsr }, new Block[] { b2 });
fail("jsr must have two successors");
} catch (IllegalArgumentException ex) {
}
try {
b1.setCode(new Instruction[] { jsr },
new Block[] { null, b2 });
fail("jsr succ mustn't be null");
} catch (IllegalArgumentException ex) {
}
try {
b1.setCode(new Instruction[] { jsr,
Instruction.forOpcode(opc_nop) },
new Block[] { null, b2 });
fail("jsr must be last in block");
} catch (IllegalArgumentException ex) {
}
}
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(new BlockTest("testJsr"));
return suite;
}
}

@ -0,0 +1,358 @@
package net.sf.jode.flow;
import net.sf.jode.decompiler.LocalInfo;
import junit.framework.*;
import net.sf.jode.expr.*;
import net.sf.jode.type.Type;
import net.sf.jode.decompiler.TabbedPrintWriter;
import net.sf.jode.GlobalOptions;
public class TrExcTest extends TestCase {
private static final boolean VERBOSE = false;
public TrExcTest(String name) {
super (name);
}
public void setUp() {
GlobalOptions.debuggingFlags |= GlobalOptions.DEBUG_CHECK;
if (VERBOSE)
GlobalOptions.debuggingFlags
|= GlobalOptions.DEBUG_ANALYZE | GlobalOptions.DEBUG_FLOW;
}
FlowBlock[] createFlowBlocks(int n) {
FlowBlock[] flows = new FlowBlock[n];
for (int i = 0; i < n; i++)
flows[i] = new FlowBlock(null, i, i > 0 ? flows[i-1] : null);
return flows;
}
public void testSynchronized11() throws java.io.IOException {
FlowBlock[] flows = createFlowBlocks(5);
LocalInfo thisLocal = new LocalInfo(null, 0);
LocalInfo tmpLocal = new LocalInfo(null, 1);
LocalInfo tmp2Local = new LocalInfo(null, 2);
/* Monitorenter */
flows[0].appendReadBlock
(new InstructionBlock
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal);
flows[0].appendBlock
(new InstructionBlock(new MonitorEnterOperator()));
flows[0].setSuccessors(new FlowBlock[] { flows[1] });
/* Synchronized Blocks */
flows[1].appendReadBlock
(new InstructionBlock
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal);
flows[1].appendWriteBlock
(new InstructionBlock
(new StoreInstruction
(new LocalStoreOperator(Type.tUObject, tmpLocal))), tmpLocal);
flows[1].appendBlock(new JsrBlock());
flows[1].setSuccessors(new FlowBlock[] { flows[4], flows[2] });
flows[2].appendReadBlock
(new InstructionBlock
(new LocalLoadOperator(Type.tUObject, null, tmpLocal)), tmpLocal);
flows[2].appendBlock
(new ReturnBlock(new NopOperator(Type.tUObject)));
flows[2].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD });
/* Catch Exception Blocks */
flows[3].appendReadBlock
(new InstructionBlock
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal);
flows[3].appendBlock
(new InstructionBlock(new MonitorExitOperator()));
flows[3].appendBlock
(new ThrowBlock(new NopOperator(Type.tUObject)));
flows[3].setSuccessors(new FlowBlock[0]);
/* monitorexit subroutine */
flows[4].appendWriteBlock
(new InstructionBlock
(new StoreInstruction
(new LocalStoreOperator(Type.tUObject, tmp2Local))), tmp2Local);
flows[4].appendReadBlock
(new InstructionBlock
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal);
flows[4].appendBlock
(new InstructionBlock(new MonitorExitOperator()));
flows[4].appendReadBlock
(new RetBlock(tmp2Local), tmp2Local);
flows[4].setSuccessors(new FlowBlock[0]);
flows[0].addStartPred();
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows);
exc.addHandler(flows[1],flows[2],flows[3], null);
exc.analyze();
flows[0].analyze();
flows[0].removeStartPred();
if (VERBOSE)
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err));
assertTrue(flows[0].getBlock() instanceof SynchronizedBlock);
assertTrue(flows[0].getBlock().getSubBlocks()[0]
instanceof ReturnBlock);
}
public void testSynchronized13() throws java.io.IOException {
FlowBlock[] flows = createFlowBlocks(5);
LocalInfo thisLocal = new LocalInfo(null, 0);
LocalInfo tmpLocal = new LocalInfo(null, 1);
LocalInfo tmp2Local = new LocalInfo(null, 2);
/* Monitorenter */
flows[0].appendReadBlock
(new InstructionBlock
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal);
flows[0].appendBlock
(new InstructionBlock(new MonitorEnterOperator()));
flows[0].setSuccessors(new FlowBlock[] { flows[1] });
/* Synchronized Blocks */
flows[1].appendReadBlock
(new InstructionBlock
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal);
flows[1].appendWriteBlock
(new InstructionBlock
(new StoreInstruction
(new LocalStoreOperator(Type.tUObject, tmpLocal))), tmpLocal);
flows[1].appendReadBlock
(new InstructionBlock
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal);
flows[1].appendBlock
(new InstructionBlock(new MonitorExitOperator()));
flows[1].setSuccessors(new FlowBlock[] { flows[2] });
flows[2].appendReadBlock
(new InstructionBlock
(new LocalLoadOperator(Type.tUObject, null, tmpLocal)), tmpLocal);
flows[2].appendBlock
(new ReturnBlock(new NopOperator(Type.tUObject)));
flows[2].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD });
/* Catch Exception Blocks */
flows[3].appendReadBlock
(new InstructionBlock
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal);
flows[3].appendBlock
(new InstructionBlock(new MonitorExitOperator()));
flows[3].appendBlock
(new ThrowBlock(new NopOperator(Type.tUObject)));
flows[3].setSuccessors(new FlowBlock[0]);
/* monitorexit subroutine */
flows[4].appendWriteBlock
(new InstructionBlock
(new StoreInstruction
(new LocalStoreOperator(Type.tUObject, tmp2Local))), tmp2Local);
flows[4].appendReadBlock
(new InstructionBlock
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal);
flows[4].appendBlock
(new InstructionBlock(new MonitorExitOperator()));
flows[4].appendReadBlock
(new RetBlock(tmp2Local), tmp2Local);
flows[4].setSuccessors(new FlowBlock[0]);
flows[0].addStartPred();
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows);
exc.addHandler(flows[1],flows[2],flows[3], null);
exc.analyze();
flows[0].analyze();
flows[0].removeStartPred();
if (VERBOSE)
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err));
assertTrue(flows[0].getBlock() instanceof SynchronizedBlock);
assertTrue(flows[0].getBlock().getSubBlocks()[0]
instanceof ReturnBlock);
}
public void testSpecialFin() throws java.io.IOException {
FlowBlock[] flows = createFlowBlocks(3);
LocalInfo thisLocal = new LocalInfo(null, 0);
LocalInfo tmpLocal = new LocalInfo(null, 1);
LocalInfo tmp2Local = new LocalInfo(null, 2);
/* Try Blocks */
flows[0].setSuccessors(new FlowBlock[] { flows[2] });
/* Catch Exception Blocks */
flows[1].appendBlock(new SpecialBlock(SpecialBlock.POP, 1, 0));
flows[1].setSuccessors(new FlowBlock[] { flows[2] });
/* subroutine */
flows[2].appendBlock(new DescriptionBlock("/*FINALLY*/"));
flows[2].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD });
flows[0].addStartPred();
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows);
exc.addHandler(flows[0],flows[0],flows[1], null);
exc.analyze();
flows[0].analyze();
flows[0].removeStartPred();
if (VERBOSE)
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err));
assertTrue("Try", flows[0].getBlock() instanceof TryBlock);
assertTrue("Empty", flows[0].getBlock().getSubBlocks()[0] instanceof EmptyBlock);
assertTrue("Finally", flows[0].getBlock().getSubBlocks()[1] instanceof FinallyBlock);
assertTrue("Descr", flows[0].getBlock().getSubBlocks()[1].getSubBlocks()[0] instanceof DescriptionBlock);
}
public void testSpecialFinTryLoops() throws java.io.IOException {
FlowBlock[] flows = createFlowBlocks(3);
LocalInfo thisLocal = new LocalInfo(null, 0);
LocalInfo tmpLocal = new LocalInfo(null, 1);
LocalInfo tmp2Local = new LocalInfo(null, 2);
/* Try Blocks */
flows[0].setSuccessors(new FlowBlock[] { flows[0] });
/* Catch Exception Blocks */
flows[1].appendBlock(new SpecialBlock(SpecialBlock.POP, 1, 0));
flows[1].setSuccessors(new FlowBlock[] { flows[2] });
/* subroutine */
flows[2].appendBlock(new DescriptionBlock("/*FINALLY*/"));
flows[2].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD });
flows[0].addStartPred();
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows);
exc.addHandler(flows[0],flows[0],flows[1], null);
exc.analyze();
flows[0].analyze();
flows[0].removeStartPred();
if (VERBOSE)
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err));
assertTrue("Try", flows[0].getBlock() instanceof TryBlock);
assertTrue("Loop", flows[0].getBlock().getSubBlocks()[0] instanceof LoopBlock);
assertTrue("Empty", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0] instanceof EmptyBlock);
assertTrue("Finally", flows[0].getBlock().getSubBlocks()[1] instanceof FinallyBlock);
assertTrue("Descr", flows[0].getBlock().getSubBlocks()[1].getSubBlocks()[0] instanceof DescriptionBlock);
}
public void testFinBreaksJikes() throws java.io.IOException {
FlowBlock[] flows = createFlowBlocks(5);
LocalInfo thisLocal = new LocalInfo(null, 0);
LocalInfo tmpLocal = new LocalInfo(null, 1);
LocalInfo tmp2Local = new LocalInfo(null, 2);
/* Try Blocks */
flows[0].appendBlock(new JsrBlock());
flows[0].setSuccessors(new FlowBlock[] { flows[3], flows[4] });
/* Catch Exception Blocks */
flows[1].appendWriteBlock
(new InstructionBlock
(new StoreInstruction
(new LocalStoreOperator(Type.tUObject, tmpLocal))), tmpLocal);
flows[1].appendBlock(new JsrBlock());
flows[1].setSuccessors(new FlowBlock[] { flows[3], flows[2] });
flows[2].appendReadBlock
(new InstructionBlock
(new LocalLoadOperator(Type.tUObject, null, tmpLocal)), tmpLocal);
flows[2].appendBlock
(new ThrowBlock(new NopOperator(Type.tUObject)));
flows[2].setSuccessors(new FlowBlock[0]);
/* subroutine */
flows[3].appendBlock(new SpecialBlock(SpecialBlock.POP, 1, 0));
flows[3].setSuccessors(new FlowBlock[] { flows[4] });
flows[4].appendBlock(new DescriptionBlock("/*HERE*/"));
flows[4].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD });
flows[0].addStartPred();
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows);
exc.addHandler(flows[0],flows[0],flows[1], null);
exc.analyze();
flows[0].analyze();
flows[0].removeStartPred();
if (VERBOSE)
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err));
assertTrue("Sequ", flows[0].getBlock() instanceof SequentialBlock);
assertTrue("Loop", flows[0].getBlock().getSubBlocks()[0] instanceof LoopBlock);
assertTrue("Try", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0] instanceof TryBlock);
assertTrue("Empty", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[0] instanceof EmptyBlock);
assertTrue("Finally", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[1] instanceof FinallyBlock);
assertTrue("Break", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[1].getSubBlocks()[0] instanceof BreakBlock);
assertTrue("Descr", flows[0].getBlock().getSubBlocks()[1]
instanceof DescriptionBlock);
}
public void testFinCondBreaks() throws java.io.IOException {
FlowBlock[] flows = createFlowBlocks(6);
LocalInfo thisLocal = new LocalInfo(null, 0);
LocalInfo tmpLocal = new LocalInfo(null, 1);
LocalInfo tmp2Local = new LocalInfo(null, 2);
/* Try Blocks */
flows[0].appendBlock(new JsrBlock());
flows[0].setSuccessors(new FlowBlock[] { flows[3], flows[5] });
/* Catch Exception Blocks */
flows[1].appendWriteBlock
(new InstructionBlock
(new StoreInstruction
(new LocalStoreOperator(Type.tUObject, tmpLocal))), tmpLocal);
flows[1].appendBlock(new JsrBlock());
flows[1].setSuccessors(new FlowBlock[] { flows[3], flows[2] });
flows[2].appendReadBlock
(new InstructionBlock
(new LocalLoadOperator(Type.tUObject, null, tmpLocal)), tmpLocal);
flows[2].appendBlock
(new ThrowBlock(new NopOperator(Type.tUObject)));
flows[2].setSuccessors(new FlowBlock[0]);
/* subroutine */
flows[3].appendWriteBlock
(new InstructionBlock
(new StoreInstruction
(new LocalStoreOperator(Type.tUObject, tmp2Local))), tmp2Local);
flows[3].appendReadBlock
(new InstructionBlock
(new LocalLoadOperator(Type.tUObject, null, thisLocal)), thisLocal);
flows[3].appendBlock(new ConditionalBlock
(new CompareUnaryOperator
(Type.tUObject, Operator.EQUALS_OP)));
flows[3].setSuccessors(new FlowBlock[] { flows[4], flows[5] });
flows[4].appendReadBlock
(new RetBlock(tmp2Local), tmp2Local);
flows[4].setSuccessors(new FlowBlock[0]);
flows[5].appendBlock(new DescriptionBlock("/*HERE*/"));
flows[5].setSuccessors(new FlowBlock[] { FlowBlock.END_OF_METHOD });
flows[0].addStartPred();
TransformExceptionHandlers exc = new TransformExceptionHandlers(flows);
exc.addHandler(flows[0],flows[0],flows[1], null);
exc.analyze();
flows[0].analyze();
flows[0].removeStartPred();
if (VERBOSE)
flows[0].dumpSource(new TabbedPrintWriter(GlobalOptions.err));
assertTrue("Sequ", flows[0].getBlock() instanceof SequentialBlock);
assertTrue("Loop", flows[0].getBlock().getSubBlocks()[0] instanceof LoopBlock);
assertTrue("Try", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0] instanceof TryBlock);
assertTrue("Empty", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[0] instanceof EmptyBlock);
assertTrue("Finally", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[1] instanceof FinallyBlock);
assertTrue("If", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[1].getSubBlocks()[0] instanceof IfThenElseBlock);
assertTrue("Break", flows[0].getBlock().getSubBlocks()[0].getSubBlocks()[0].getSubBlocks()[1].getSubBlocks()[0].getSubBlocks()[0] instanceof BreakBlock);
assertTrue("Descr", flows[0].getBlock().getSubBlocks()[1]
instanceof DescriptionBlock);
}
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(new TrExcTest("testSynchronized11"));
suite.addTest(new TrExcTest("testSynchronized13"));
suite.addTest(new TrExcTest("testSpecialFin"));
suite.addTest(new TrExcTest("testSpecialFinTryLoops"));
suite.addTest(new TrExcTest("testFinBreaksJikes"));
suite.addTest(new TrExcTest("testFinCondBreaks"));
return suite;
}
}

@ -0,0 +1,186 @@
package net.sf.jode.obfuscator.modules;
import net.sf.jode.bytecode.*;
import net.sf.jode.GlobalOptions;
import junit.framework.*;
import java.util.BitSet;
import java.io.PrintWriter;
public class ConstAnaTest extends TestCase implements Opcodes {
ConstantAnalyzer ca;
Instruction[] callJsrInstr;
BasicBlocks jsrMethod;
public ConstAnaTest(String name) {
super(name);
}
public void setUp() {
ca = new ConstantAnalyzer();
createJsrMethod();
}
public void createJsrMethod() {
callJsrInstr = new Instruction[] {
Instruction.forOpcode(opc_jsr)
};
Block b0 = new Block();
Block b1 = new Block();
Block b2 = new Block();
b0.setCode(callJsrInstr, new Block[] { b1, null });
b1.setCode(new Instruction[] {
Instruction.forOpcode(opc_astore, LocalVariableInfo.getInfo(2)),
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(1), -1),
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)),
Instruction.forOpcode(opc_ifeq)
}, new Block[] { b2, b0 });
b2.setCode(new Instruction[] {
Instruction.forOpcode(opc_ret, LocalVariableInfo.getInfo(2)),
}, new Block[0]);
jsrMethod = new BasicBlocks(new MethodInfo("foo", "(I)V", 0));
jsrMethod.setBlocks(new Block[] { b0, b1, b2 },
b0, new Handler[0]);
}
public void testSimple() throws Exception {
Block b0 = new Block();
Block b1 = new Block();
Block b2 = new Block();
b0.setCode(new Instruction[] {
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(1), 1),
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(2), 1),
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(3), 1),
}, new Block[] { b1 });
b1.setCode(new Instruction[] {
Instruction.forOpcode(opc_ldc, new Integer(0)),
Instruction.forOpcode(opc_istore, LocalVariableInfo.getInfo(1)),
Instruction.forOpcode(opc_ldc, new Integer(4)),
Instruction.forOpcode(opc_istore, LocalVariableInfo.getInfo(2)),
Instruction.forOpcode(opc_ldc, new Integer(0)),
Instruction.forOpcode(opc_istore, LocalVariableInfo.getInfo(3)),
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)),
Instruction.forOpcode(opc_ifeq)
}, new Block[] { b2, b0 });
b2.setCode(new Instruction[] {
Instruction.forOpcode(opc_iinc, LocalVariableInfo.getInfo(1), 1),
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)),
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(2)),
Instruction.forOpcode(opc_if_icmplt)
}, new Block[] { b2, null });
BasicBlocks bb = new BasicBlocks(new MethodInfo("foo", "()V", 0));
bb.setBlocks(new Block[] { b0, b1, b2 }, b1, new Handler[0]);
ca.analyzeCode(null, bb);
BitSet reachable = (BitSet) ca.bbInfos.get(bb);
assertEquals("Reachable set",
"{1, 2}", reachable.toString());
assertEquals("constant flow",
ca.CONSTANTFLOW,
Class.forName("net.sf.jode.obfuscator.modules.ConstantAnalyzer$ConstantInfo")
.getDeclaredField("flags")
.getInt(ca.constantInfos.get(b1.getInstructions()[7])));
ca.transformCode(bb);
Block[] blocks = bb.getBlocks();
assertEquals(2, blocks.length);
assertEquals(1, blocks[0].getSuccs().length);
assertEquals(blocks[1], blocks[0].getSuccs()[0]);
assertEquals(2, blocks[1].getSuccs().length);
assertEquals(blocks[1], blocks[1].getSuccs()[0]);
assertEquals(null, blocks[1].getSuccs()[1]);
}
public void testJsr() throws Exception {
Block[] blocks = jsrMethod.getBlocks();
ca.analyzeCode(null, jsrMethod);
BitSet reachable = (BitSet) ca.bbInfos.get(jsrMethod);
assertEquals("Reachable set",
"{0, 1, 2}", reachable.toString());
ca.transformCode(jsrMethod);
blocks = jsrMethod.getBlocks();
assertEquals(3, blocks.length);
assertEquals(2, blocks[0].getSuccs().length);
assertEquals(blocks[1], blocks[0].getSuccs()[0]);
assertEquals(null, blocks[0].getSuccs()[1]);
assertEquals(2, blocks[1].getSuccs().length);
assertEquals(0, blocks[2].getSuccs().length);
}
public void testNestedJsr() throws Exception {
Block b0 = new Block();
Block b1 = new Block();
Block b2 = new Block();
Block b3 = new Block();
Block b4 = new Block();
Block b5 = new Block();
Block b6 = new Block();
Block b7 = new Block();
Block b8 = new Block();
Block b9 = new Block();
b0.setCode(new Instruction[] {
Instruction.forOpcode(opc_jsr)
}, new Block[] { b2, b1 });
b1.setCode(new Instruction[] {
Instruction.forOpcode(opc_jsr)
}, new Block[] { b5, null });
b2.setCode(new Instruction[] {
Instruction.forOpcode(opc_astore, LocalVariableInfo.getInfo(2)),
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)),
Instruction.forOpcode(opc_ifeq)
}, new Block[] { b3, b7 });
b3.setCode(new Instruction[] {
Instruction.forOpcode(opc_jsr)
}, new Block[] { b5, b1 });
b4.setCode(new Instruction[] {
Instruction.forOpcode(opc_ret, LocalVariableInfo.getInfo(2)),
}, new Block[0]);
b5.setCode(new Instruction[] {
Instruction.forOpcode(opc_astore, LocalVariableInfo.getInfo(3)),
Instruction.forOpcode(opc_ret, LocalVariableInfo.getInfo(3)),
}, new Block[0]);
b6.setCode(new Instruction[] {
Instruction.forOpcode(opc_astore, LocalVariableInfo.getInfo(3))
}, new Block[] { b4 });
b7.setCode(new Instruction[] {
Instruction.forOpcode(opc_iload, LocalVariableInfo.getInfo(1)),
Instruction.forOpcode(opc_ifeq)
}, new Block[] { b8, b4 });
b8.setCode(new Instruction[] {
Instruction.forOpcode(opc_jsr)
}, new Block[] { b6, b9 });
b9.setCode(new Instruction[0], new Block[] { b7 });
BasicBlocks bb = new BasicBlocks(new MethodInfo("foo", "(I)V", 0));
bb.setBlocks(new Block[] { b0, b1, b2, b3, b4, b5, b6, b7, b8, b9 },
b0, new Handler[0]);
ca.analyzeCode(null, bb);
BitSet reachable = (BitSet) ca.bbInfos.get(bb);
assertEquals("Reachable set",
"{0, 1, 2, 3, 4, 5, 6, 7, 8}", reachable.toString());
assertNotNull("Constant Flow",
ca.constantInfos.get(b8.getInstructions()[0]));
ca.transformCode(bb);
Block[] blocks = bb.getBlocks();
assertEquals(9, blocks.length);
assertEquals(2, blocks[0].getSuccs().length);
assertEquals(2, blocks[1].getSuccs().length);
assertEquals(2, blocks[3].getSuccs().length);
assertEquals(1, blocks[8].getSuccs().length);
}
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(new ConstAnaTest("testSimple"));
suite.addTest(new ConstAnaTest("testJsr"));
suite.addTest(new ConstAnaTest("testNestedJsr"));
return suite;
}
}
Loading…
Cancel
Save