1/* 2 * Copyright 2013, Google Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32package org.jf.dexlib2.analysis; 33 34import com.google.common.collect.ImmutableSet; 35import com.google.common.collect.Lists; 36import junit.framework.Assert; 37import org.jf.dexlib2.Opcodes; 38import org.jf.dexlib2.iface.ClassDef; 39import org.jf.dexlib2.immutable.ImmutableDexFile; 40import org.junit.Test; 41 42import java.io.IOException; 43 44public class CommonSuperclassTest { 45 // object tree: 46 // object 47 // one 48 // onetwo 49 // onetwothree 50 // onethree 51 // five (undefined class) 52 // fivetwo 53 // fivetwothree 54 // fivethree 55 56 private final ClassPath oldClassPath; 57 private final ClassPath newClassPath; 58 59 60 public CommonSuperclassTest() throws IOException { 61 ImmutableSet<ClassDef> classes = ImmutableSet.of( 62 TestUtils.makeClassDef("Ljava/lang/Object;", null), 63 TestUtils.makeClassDef("Ltest/one;", "Ljava/lang/Object;"), 64 TestUtils.makeClassDef("Ltest/two;", "Ljava/lang/Object;"), 65 TestUtils.makeClassDef("Ltest/onetwo;", "Ltest/one;"), 66 TestUtils.makeClassDef("Ltest/onetwothree;", "Ltest/onetwo;"), 67 TestUtils.makeClassDef("Ltest/onethree;", "Ltest/one;"), 68 TestUtils.makeClassDef("Ltest/fivetwo;", "Ltest/five;"), 69 TestUtils.makeClassDef("Ltest/fivetwothree;", "Ltest/fivetwo;"), 70 TestUtils.makeClassDef("Ltest/fivethree;", "Ltest/five;"), 71 TestUtils.makeInterfaceDef("Ljava/lang/Cloneable;"), 72 TestUtils.makeInterfaceDef("Ljava/io/Serializable;"), 73 74 // basic class and interface 75 TestUtils.makeClassDef("Liface/classiface1;", "Ljava/lang/Object;", "Liface/iface1;"), 76 TestUtils.makeInterfaceDef("Liface/iface1;"), 77 78 // a more complex interface tree 79 TestUtils.makeInterfaceDef("Liface/base1;"), 80 // implements undefined interface 81 TestUtils.makeInterfaceDef("Liface/sub1;", "Liface/base1;", "Liface/base2;"), 82 // this implements sub1, so that its interfaces can't be fully resolved either 83 TestUtils.makeInterfaceDef("Liface/sub2;", "Liface/base1;", "Liface/sub1;"), 84 TestUtils.makeInterfaceDef("Liface/sub3;", "Liface/base1;"), 85 TestUtils.makeInterfaceDef("Liface/sub4;", "Liface/base1;", "Liface/sub3;"), 86 TestUtils.makeClassDef("Liface/classsub1;", "Ljava/lang/Object;", "Liface/sub1;"), 87 TestUtils.makeClassDef("Liface/classsub2;", "Ljava/lang/Object;", "Liface/sub2;"), 88 TestUtils.makeClassDef("Liface/classsub3;", "Ljava/lang/Object;", "Liface/sub3;", 89 "Liface/base;"), 90 TestUtils.makeClassDef("Liface/classsub4;", "Ljava/lang/Object;", "Liface/sub3;", 91 "Liface/sub4;"), 92 TestUtils.makeClassDef("Liface/classsubsub4;", "Liface/classsub4;"), 93 TestUtils.makeClassDef("Liface/classsub1234;", "Ljava/lang/Object;", "Liface/sub1;", 94 "Liface/sub2;", "Liface/sub3;", "Liface/sub4;")); 95 96 oldClassPath = new ClassPath(new DexClassProvider(new ImmutableDexFile(Opcodes.getDefault(), classes))); 97 newClassPath = new ClassPath(Lists.newArrayList(new DexClassProvider( 98 new ImmutableDexFile(Opcodes.forArtVersion(72), classes))), true, 72); 99 } 100 101 public void superclassTest(ClassPath classPath, String commonSuperclass, 102 String type1, String type2) { 103 TypeProto commonSuperclassProto = classPath.getClass(commonSuperclass); 104 TypeProto type1Proto = classPath.getClass(type1); 105 TypeProto type2Proto = classPath.getClass(type2); 106 107 Assert.assertSame(commonSuperclassProto, type1Proto.getCommonSuperclass(type2Proto)); 108 Assert.assertSame(commonSuperclassProto, type2Proto.getCommonSuperclass(type1Proto)); 109 } 110 111 public void superclassTest(String commonSuperclass, String type1, String type2) { 112 superclassTest(oldClassPath, commonSuperclass, type1, type2); 113 superclassTest(newClassPath, commonSuperclass, type1, type2); 114 } 115 116 @Test 117 public void testGetCommonSuperclass() throws IOException { 118 String object = "Ljava/lang/Object;"; 119 String unknown = "Ujava/lang/Object;"; 120 String one = "Ltest/one;"; 121 String two = "Ltest/two;"; 122 String onetwo = "Ltest/onetwo;"; 123 String onetwothree = "Ltest/onetwothree;"; 124 String onethree = "Ltest/onethree;"; 125 String five = "Ltest/five;"; 126 String fivetwo = "Ltest/fivetwo;"; 127 String fivetwothree = "Ltest/fivetwothree;"; 128 String fivethree = "Ltest/fivethree;"; 129 130 // same object 131 superclassTest(object, object, object); 132 superclassTest(unknown, unknown, unknown); 133 superclassTest(one, one, one); 134 superclassTest(onetwo, onetwo, onetwo); 135 superclassTest(onetwothree, onetwothree, onetwothree); 136 superclassTest(onethree, onethree, onethree); 137 superclassTest(five, five, five); 138 superclassTest(fivetwo, fivetwo, fivetwo); 139 superclassTest(fivetwothree, fivetwothree, fivetwothree); 140 superclassTest(fivethree, fivethree, fivethree); 141 142 // same value, but different object 143 Assert.assertEquals( 144 onetwo, 145 oldClassPath.getClass(onetwo).getCommonSuperclass(new ClassProto(oldClassPath, onetwo)).getType()); 146 147 Assert.assertEquals( 148 onetwo, 149 newClassPath.getClass(onetwo).getCommonSuperclass(new ClassProto(newClassPath, onetwo)).getType()); 150 151 // other object is superclass 152 superclassTest(object, object, one); 153 154 // other object is superclass two levels up 155 superclassTest(object, object, onetwo); 156 157 // unknown and non-object class 158 superclassTest(unknown, one, unknown); 159 160 // unknown and object class 161 superclassTest(object, object, unknown); 162 163 // siblings 164 superclassTest(one, onetwo, onethree); 165 166 // nephew 167 superclassTest(one, onethree, onetwothree); 168 169 // unrelated 170 superclassTest(object, one, two); 171 172 // undefined superclass and object 173 superclassTest(object, fivetwo, object); 174 175 // undefined class and unrelated type 176 superclassTest(unknown, one, five); 177 178 // undefined superclass and unrelated type 179 superclassTest(unknown, one, fivetwo); 180 181 // undefined ancestor and unrelated type 182 superclassTest(unknown, one, fivetwothree); 183 184 // undefined class and direct subclass 185 superclassTest(five, five, fivetwo); 186 187 // undefined class and descendent 188 superclassTest(five, five, fivetwothree); 189 190 // undefined superclass and direct subclass 191 superclassTest(fivetwo, fivetwo, fivetwothree); 192 193 // siblings with undefined superclass 194 superclassTest(five, fivetwo, fivethree); 195 196 // undefined superclass and nephew 197 superclassTest(five, fivethree, fivetwothree); 198 } 199 200 @Test 201 public void testGetCommonSuperclass_interfaces() { 202 String classiface1 = "Liface/classiface1;"; 203 String iface1 = "Liface/iface1;"; 204 String base1 = "Liface/base1;"; 205 String base2 = "Liface/base2;"; 206 String sub1 = "Liface/sub1;"; 207 String sub2 = "Liface/sub2;"; 208 String sub3 = "Liface/sub3;"; 209 String sub4 = "Liface/sub4;"; 210 String classsub1 = "Liface/classsub1;"; 211 String classsub2 = "Liface/classsub2;"; 212 String classsub3 = "Liface/classsub3;"; 213 String classsub4 = "Liface/classsub4;"; 214 String classsubsub4 = "Liface/classsubsub4;"; 215 String classsub1234 = "Liface/classsub1234;"; 216 String object = "Ljava/lang/Object;"; 217 String unknown = "Ujava/lang/Object;"; 218 219 superclassTest(iface1, classiface1, iface1); 220 221 superclassTest(base1, base1, base1); 222 superclassTest(base1, base1, sub1); 223 superclassTest(base1, base1, classsub1); 224 superclassTest(base1, base1, sub2); 225 superclassTest(base1, base1, classsub2); 226 superclassTest(base1, base1, sub3); 227 superclassTest(base1, base1, classsub3); 228 superclassTest(base1, base1, sub4); 229 superclassTest(base1, base1, classsub4); 230 superclassTest(base1, base1, classsubsub4); 231 superclassTest(base1, base1, classsub1234); 232 233 superclassTest(object, sub3, iface1); 234 superclassTest(unknown, sub2, iface1); 235 superclassTest(unknown, sub1, iface1); 236 237 superclassTest(base2, base2, sub1); 238 superclassTest(base2, base2, classsub1); 239 superclassTest(base2, base2, sub2); 240 superclassTest(base2, base2, classsub2); 241 superclassTest(base2, base2, classsub1234); 242 243 superclassTest(unknown, iface1, classsub1234); 244 245 superclassTest(sub1, sub1, classsub1); 246 247 superclassTest(sub2, sub2, classsub2); 248 superclassTest(sub1, sub1, classsub2); 249 250 superclassTest(sub3, sub3, classsub3); 251 252 superclassTest(sub4, sub4, classsub4); 253 superclassTest(sub3, sub3, classsub4); 254 superclassTest(object, sub2, classsub4); 255 superclassTest(object, sub1, classsub4); 256 257 superclassTest(sub1, sub2, sub1); 258 259 superclassTest(sub1, sub1, classsub1234); 260 superclassTest(sub2, sub2, classsub1234); 261 superclassTest(sub3, sub3, classsub1234); 262 superclassTest(sub4, sub4, classsub1234); 263 264 superclassTest(unknown, sub3, classsub1); 265 superclassTest(unknown, sub4, classsub1); 266 superclassTest(unknown, sub3, classsub2); 267 superclassTest(unknown, sub4, classsub2); 268 269 superclassTest(unknown, sub4, base2); 270 superclassTest(unknown, classsub4, base2); 271 } 272 273 @Test 274 public void testGetCommonSuperclass_arrays() throws IOException { 275 String object = "Ljava/lang/Object;"; 276 String one = "Ltest/one;"; 277 String unknown = "Ujava/lang/Object;"; 278 279 String cloneable = "Ljava/lang/Cloneable;"; 280 String serializable = "Ljava/io/Serializable;"; 281 282 String object1 = "[Ljava/lang/Object;"; 283 String one1 = "[Ltest/one;"; 284 String one2 = "[[Ltest/one;"; 285 String two1 = "[Ltest/two;"; 286 String onetwo1 = "[Ltest/onetwo;"; 287 String onetwo2 = "[[Ltest/onetwo;"; 288 String onethree1 = "[Ltest/onethree;"; 289 String onethree2 = "[[Ltest/onethree;"; 290 String five = "Ltest/five;"; 291 String five1 = "[Ltest/five;"; 292 String unknown1 = "[Ujava/lang/Object;"; 293 294 String int1 = "[I"; 295 String int2 = "[[I"; 296 String float1 = "[F"; 297 298 superclassTest(one1, one1, one1); 299 superclassTest(object1, object1, one1); 300 superclassTest(one1, onetwo1, onethree1); 301 superclassTest(one1, one1, onethree1); 302 superclassTest(object1, one1, two1); 303 304 superclassTest(one2, one2, one2); 305 superclassTest(one2, one2, onetwo2); 306 superclassTest(one2, onetwo2, onethree2); 307 superclassTest(object1, one1, one2); 308 superclassTest(object1, two1, one2); 309 310 superclassTest(unknown1, five1, one1); 311 superclassTest(object1, five1, one2); 312 313 superclassTest(unknown1, one1, unknown1); 314 315 superclassTest(object, one1, one); 316 superclassTest(object, object1, one); 317 superclassTest(object, onetwo1, one); 318 superclassTest(object, five1, one); 319 superclassTest(object, one2, one); 320 321 superclassTest(object, one1, unknown); 322 superclassTest(object, unknown1, unknown); 323 324 superclassTest(cloneable, one1, cloneable); 325 superclassTest(serializable, one1, serializable); 326 327 superclassTest(object, one1, five); 328 329 superclassTest(int1, int1, int1); 330 superclassTest(object, int1, float1); 331 superclassTest(object, int1, int2); 332 } 333} 334