From bc476ea2bc163c3050a94b03ecc66085d5c890a4 Mon Sep 17 00:00:00 2001 From: Timothy Hoffman <4001421+tim-hoffman@users.noreply.github.com> Date: Wed, 21 Jul 2021 15:23:28 -0500 Subject: [PATCH] Add test cases for current sils issues Issues #1641 and #1699 --- .../scalar/SharedInitLocalSplitterTest.java | 68 ++++++++++ .../SharedInitLocalSplitterTestInput.java | 41 ++++++ ...SharedInitializationLocalSplitterTest.java | 124 ++++++++++++++++++ 3 files changed, 233 insertions(+) create mode 100644 src/systemTest/java/soot/toolkits/scalar/SharedInitLocalSplitterTest.java create mode 100644 src/systemTest/targets/soot/toolkits/scalar/SharedInitLocalSplitterTestInput.java create mode 100644 src/test/java/soot/toolkits/scalar/SharedInitializationLocalSplitterTest.java diff --git a/src/systemTest/java/soot/toolkits/scalar/SharedInitLocalSplitterTest.java b/src/systemTest/java/soot/toolkits/scalar/SharedInitLocalSplitterTest.java new file mode 100644 index 00000000000..f9e51d74ae4 --- /dev/null +++ b/src/systemTest/java/soot/toolkits/scalar/SharedInitLocalSplitterTest.java @@ -0,0 +1,68 @@ +package soot.toolkits.scalar; + +/*- + * #%L + * Soot - a J*va Optimization Framework + * %% + * Copyright (C) 2021 Timothy Hoffman + * %% + * This program 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 2.1 of the + * License, or (at your option) any later version. + * + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + */ + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; +import org.powermock.core.classloader.annotations.PowerMockIgnore; + +import soot.Body; +import soot.SootMethod; +import soot.jimple.JimpleBody; +import soot.options.Options; +import soot.testing.framework.AbstractTestingFramework; + +/** + * @author Timothy Hoffman + */ +@PowerMockIgnore({ "com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "org.w3c.*" }) +public class SharedInitLocalSplitterTest extends AbstractTestingFramework { + + private static final String TEST_TARGET_CLASS = "soot.toolkits.scalar.SharedInitLocalSplitterTestInput"; + + @Override + protected void setupSoot() { + Options.v().setPhaseOption("jb.sils", "enabled:true"); + } + + @Ignore + @Test + public void testCaseA() { + SootMethod target = + prepareTarget(methodSigFromComponents(TEST_TARGET_CLASS, "int", "test", "java.lang.Object"), TEST_TARGET_CLASS); + + Body body = target.retrieveActiveBody(); + Assert.assertTrue(body instanceof JimpleBody); + + // Ensure unused locals are removed before asserting expected count. + UnusedLocalEliminator.v().transform(body); + + // System.out.println("[SharedInitLocalSplitterTest#testCaseA] body = " + body); + + // SharedInitializationLocalSplitter should not have introduced any + // additional locals in this example because all of the integer constant + // values are used only as integers. + Assert.assertEquals(3, body.getLocalCount()); + } +} diff --git a/src/systemTest/targets/soot/toolkits/scalar/SharedInitLocalSplitterTestInput.java b/src/systemTest/targets/soot/toolkits/scalar/SharedInitLocalSplitterTestInput.java new file mode 100644 index 00000000000..e6795961f38 --- /dev/null +++ b/src/systemTest/targets/soot/toolkits/scalar/SharedInitLocalSplitterTestInput.java @@ -0,0 +1,41 @@ +package soot.toolkits.scalar; + +/*- + * #%L + * Soot - a J*va Optimization Framework + * %% + * Copyright (C) 2021 Timothy Hoffman + * %% + * This program 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 2.1 of the + * License, or (at your option) any later version. + * + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + */ + +public class SharedInitLocalSplitterTestInput { + + /* + * SOURCE: https://github.com/soot-oss/soot/issues/1699 + */ + public int test(Object b) { + int x = 100; + while (b != null) { + if (x < 200) { + x = 100; + } else { + x = 200; + } + } + return x; + } +} diff --git a/src/test/java/soot/toolkits/scalar/SharedInitializationLocalSplitterTest.java b/src/test/java/soot/toolkits/scalar/SharedInitializationLocalSplitterTest.java new file mode 100644 index 00000000000..f5814236526 --- /dev/null +++ b/src/test/java/soot/toolkits/scalar/SharedInitializationLocalSplitterTest.java @@ -0,0 +1,124 @@ +package soot.toolkits.scalar; + +/*- + * #%L + * Soot - a J*va Optimization Framework + * %% + * Copyright (C) 2021 Timothy Hoffman + * %% + * This program 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 2.1 of the + * License, or (at your option) any later version. + * + * This program 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 General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + */ + +import java.util.Collections; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import soot.BooleanType; +import soot.G; +import soot.Local; +import soot.Modifier; +import soot.Scene; +import soot.SootClass; +import soot.SootMethod; +import soot.Unit; +import soot.UnitPatchingChain; +import soot.UnknownType; +import soot.VoidType; +import soot.jimple.IntConstant; +import soot.jimple.Jimple; +import soot.jimple.JimpleBody; +import soot.options.Options; +import soot.util.Chain; + +/** + * Tests for the {@link SharedInitializationLocalSplitter}. + * + * @author Timothy Hoffman + */ +public class SharedInitializationLocalSplitterTest { + + @Before + public void initialize() { + // load necessary classes + G.reset(); + final Options opts = Options.v(); + opts.set_whole_program(true); + final Scene sc = Scene.v(); + sc.loadNecessaryClasses(); + } + + @Ignore + @Test + public void testSingleInitUsedAsBoolAndInt() { + // create test method and body + final BooleanType tyBool = BooleanType.v(); + final SootMethod method = new SootMethod("testMethod", Collections.singletonList(tyBool), VoidType.v(), Modifier.PUBLIC); + SootClass cl = new SootClass("TestClass", Modifier.PUBLIC); + cl.addMethod(method); + + final Jimple jimp = Jimple.v(); + final JimpleBody body = jimp.newBody(method); + method.setActiveBody(body); + + final Scene sc = Scene.v(); + final SootClass clPrtStrm = sc.loadClassAndSupport("java.io.PrintStream"); + final SootClass clSystem = sc.loadClassAndSupport("java.lang.System"); + + // create locals + final Chain locals = body.getLocals(); + final Local b = jimp.newLocal("b", UnknownType.v()); + locals.add(b); + final Local s = jimp.newLocal("s", UnknownType.v()); + locals.add(s); + final Local u = jimp.newLocal("u", UnknownType.v()); + locals.add(u); + + // create code + final UnitPatchingChain units = body.getUnits(); + final Unit tgtRet = jimp.newReturnVoidStmt(); + final Unit tgtBranch = jimp.newNopStmt(); + // boolean b = @param0; + units.add(jimp.newIdentityStmt(b, jimp.newParameterRef(tyBool, 0))); + // java.io.PrintStream s = System.out; + units.add(jimp.newAssignStmt(s, jimp.newStaticFieldRef(clSystem.getFieldByName("out").makeRef()))); + // int u = 0; + units.add(jimp.newAssignStmt(u, IntConstant.v(0))); + // if(b==0) goto + units.add(jimp.newIfStmt(jimp.newEqExpr(b, IntConstant.v(0)), tgtBranch)); + // s.println(u); + units.add(jimp.newInvokeStmt(jimp.newVirtualInvokeExpr(s, clPrtStrm.getMethod("void println(boolean)").makeRef(), u))); + // goto + units.add(jimp.newGotoStmt(tgtRet)); + // : nop + units.add(tgtBranch); + // s.println(u); + units.add(jimp.newInvokeStmt(jimp.newVirtualInvokeExpr(s, clPrtStrm.getMethod("void println(int)").makeRef(), u))); + // : return; + units.add(tgtRet); + + // System.out.println("[testSingleInitUsedAsBoolAndInt] before = " + body); + + // execute transform + SharedInitializationLocalSplitter.v().transform(body); + UnusedLocalEliminator.v().transform(body); + + // System.out.println("[testSingleInitUsedAsBoolAndInt] after = " + body); + + // TODO: how to verify that SharedInitializationLocalSplitter did its job? + } +}