/* * This file is part of JOP, the Java Optimized Processor * see <http://www.jopdesign.com/> * * Copyright (C) 2010, Stefan Hepp (stefan@stefant.org). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 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 Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.jopdesign.dfa.analyses; import com.jopdesign.dfa.framework.BoundedSetFactory.BoundedSet; import com.jopdesign.dfa.framework.BoundedSetFactory; import org.junit.After; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; public class SymbolicAddressMapTest { private BoundedSetFactory<SymbolicAddress> bsf2; @Before public void setUp() throws Exception { bsf2 = new BoundedSetFactory<SymbolicAddress>(2); } private BoundedSet<SymbolicAddress> boundedSet(Object... names) { BoundedSet<SymbolicAddress> bs = bsf2.empty(); for(Object s : names) { SymbolicAddress addr = SymbolicAddress.rootAddress(s.toString()); bs.add(addr); } return bs; } @After public void tearDown() throws Exception { } // 0 -> { a,b } // 1 -> { c } // 2 -> { b,c } // f1 -> { a,b } // f2 -> { top } private SymbolicAddressMap map1() { SymbolicAddressMap map1 = new SymbolicAddressMap(bsf2); map1.putStack(0, boundedSet("a","b")); map1.putStack(1, boundedSet("c")); map1.putStack(2, boundedSet("b","c")); map1.put(new Location("f1"), boundedSet("a")); map1.put(new Location("f2"), bsf2.top()); return map1; } // 0 -> { b,c } // 1 -> { a } // f1 -> { a,b } // f3 -> { top } // f4 -> { a,b } private SymbolicAddressMap map2() { SymbolicAddressMap map2 = new SymbolicAddressMap(bsf2); map2.putStack(0, boundedSet("b","c")); map2.putStack(1, boundedSet("c")); map2.put(new Location("f1"), boundedSet("a","b")); map2.put(new Location("f3"), bsf2.top()); map2.put(new Location("f4"), boundedSet("a","b")); return map2; } @Test public void testHashCode() { assert(map1().hashCode() == map1().hashCode()); assert(map1().hashCode() != map2().hashCode()); assert(map1().hashCode() != SymbolicAddressMap.top().hashCode()); assert(map2().hashCode() == map2().hashCode()); assert(map2().hashCode() != SymbolicAddressMap.top().hashCode()); assert(SymbolicAddressMap.top().hashCode() == SymbolicAddressMap.top().hashCode()); } @Test public void testIsTop() { SymbolicAddressMap m1 = map1(); SymbolicAddressMap m2 = map2(); assert(! m1.isTop()); assert(! m2.isTop()); assert(SymbolicAddressMap.top().isTop()); m1.join(SymbolicAddressMap.top()); assert(m1.isTop()); } @Test public void testEqualsObject() { SymbolicAddressMap m1 = map1(); SymbolicAddressMap m2 = map2(); assert(m1.equals(m1)); assert(m1.equals(map1())); assert(m2.equals(map2())); assert(! m1.equals(m2)); m1.join(SymbolicAddressMap.top()); assert(m1.equals(SymbolicAddressMap.top())); m2.join(SymbolicAddressMap.top()); assert(m1.equals(m2)); } @Test public void testIsSubset() { SymbolicAddressMap m1 = map1(); SymbolicAddressMap m2 = map2(); SymbolicAddressMap top = SymbolicAddressMap.top(); assert(! m1.isSubset(m2)); assert(! m2.isSubset(m1)); assert(m1.isSubset(map1())); assert(m2.isSubset(map2())); assert(m1.isSubset(top)); assert(m2.isSubset(top)); assert(! top.isSubset(m1)); assert(! top.isSubset(m2)); SymbolicAddressMap m12 = m1.clone(); m12.join(m2); SymbolicAddressMap m21 = m2.clone(); m21.join(m1); assert(m12.equals(m21)); assert(m1.isSubset(m12)); assert(m1.isSubset(m12)); assert(m2.isSubset(m21)); assert(m2.isSubset(m21)); } @Test public void testClone() { SymbolicAddressMap m1 = map1(); SymbolicAddressMap m2 = map2(); SymbolicAddressMap top = SymbolicAddressMap.top().clone(); assert(m1.equals(m1.clone())); assert(m1.equals(m2.clone())); assert(m1.equals(top.clone())); } @Test public void testCloneFilterStack() { SymbolicAddressMap m1 = map1(); SymbolicAddressMap m2 = map2(); SymbolicAddressMap top = SymbolicAddressMap.top(); SymbolicAddressMap m1a = m1.cloneFilterStack(2); assert(! m1a.equals(m1)); assert(m1a.isSubset(m1)); assert(m1a.getStack(0).equals(m1.getStack(0))); assert(m1a.getStack(1).equals(m1.getStack(1))); assert(!m1a.getStack(2).equals(m1.getStack(2))); m1a.putStack(2, m1.getStack(2)); assert(m1a.equals(m1)); SymbolicAddressMap m2a = m2.cloneFilterStack(2); assert(m2a.equals(m2)); SymbolicAddressMap topa = top.cloneFilterStack(1); assert(topa.equals(top)); } @Test public void testCloneInvoke() { SymbolicAddressMap m1 = map1(); SymbolicAddressMap m2 = map2(); SymbolicAddressMap top = SymbolicAddressMap.top(); // Trivial assertEquals(m1, m1.cloneInvoke(0)); int framePtr = 2; // Stack[2] -> Stack[0] SymbolicAddressMap m1i = m1.cloneInvoke(framePtr); SymbolicAddressMap m1a = new SymbolicAddressMap(bsf2); m1a.addStackUpto(m1, framePtr); // m1i: Stack[0] -> Stack[2] and merge m1a.joinReturned(m1i, framePtr); assertEquals(m1,m1a); framePtr = 1; SymbolicAddressMap m2i = m2.cloneInvoke(framePtr); SymbolicAddressMap m2a = new SymbolicAddressMap(bsf2); m2a.addStackUpto(m2, framePtr); m2a.joinReturned(m2i, framePtr); assertEquals(m2,m2a); try { m1a.joinReturned(null, 0); fail("joinReturned(null) should throw AssertionError"); } catch (AssertionError _) {} assertEquals(m1,m1a); m1a.joinReturned(SymbolicAddressMap.top(), 1); assertEquals(m1a,top); top.joinReturned(m1i, 1); assertEquals(SymbolicAddressMap.top(),top); } @Test public void testAddStackUpto() { // most important functionality has been covered above SymbolicAddressMap m1 = map1(); SymbolicAddressMap m2 = map2(); SymbolicAddressMap top = SymbolicAddressMap.top(); // trivial (bound 0) SymbolicAddressMap m1a = m1.clone(); m1a.addStackUpto(m2, 0); assertEquals(m1,m1a); // add undefined try { m1.addStackUpto(null, 0); fail("addStackUpto(undefined,..) should fail"); } catch(AssertionError _) {} try { top.addStackUpto(null, 0); fail("addStackUpto(undefined,..) should fail"); } catch(AssertionError _) {} // top is handled conservatively m1.addStackUpto(top, 1); assertEquals(m1,top); } @Test public void testJoin() { SymbolicAddressMap m1 = map1(); SymbolicAddressMap m2 = map2(); SymbolicAddressMap top = SymbolicAddressMap.top(); // join with undefined assertEquals(join(m1,null),m1); assertEquals(join(m2,null),m2); assertEquals(join(top,null),top); // join reflexivity assertEquals(join(m1,m2),join(m2,m1)); // join top assertEquals(join(m1,top),top); assertEquals(join(top,m1),top); assertEquals(join(top,top),top); // join subset assert(m1.isSubset(join(m1,m2))); assert(m1.isSubset(join(m2,m1))); assert(m2.isSubset(join(m1,m2))); assert(m2.isSubset(join(m2,m1))); assert(join(m1,m2).isSubset(top)); } private SymbolicAddressMap join(SymbolicAddressMap m1, SymbolicAddressMap m2) { SymbolicAddressMap m12 = m1.clone(); m12.join(m2); return m12; } @Test public void testJoinReturned() { // partly covered above } @Test public void testGetStack() { SymbolicAddressMap m1 = map1(); assertEquals(m1.getStack(0),boundedSet("a","b")); m1.putStack(3,bsf2.top()); assertEquals(m1.getStack(3),SymbolicAddressMap.top().getStack(3)); } @Test public void testPut() { fail("Not yet implemented"); // TODO } @Test public void testPutStack() { fail("Not yet implemented"); // TODO } }