15280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver/* 25280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * Copyright 2014, Google Inc. 35280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * All rights reserved. 45280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * 55280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * Redistribution and use in source and binary forms, with or without 65280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * modification, are permitted provided that the following conditions are 75280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * met: 85280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * 95280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * * Redistributions of source code must retain the above copyright 105280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * notice, this list of conditions and the following disclaimer. 115280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * * Redistributions in binary form must reproduce the above 125280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * copyright notice, this list of conditions and the following disclaimer 135280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * in the documentation and/or other materials provided with the 145280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * distribution. 155280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * * Neither the name of Google Inc. nor the names of its 165280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * contributors may be used to endorse or promote products derived from 175280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * this software without specific prior written permission. 185280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * 195280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 205280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 215280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 225280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 235280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 245280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 255280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 265280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 275280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 285280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 295280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 305280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver */ 315280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver 325280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverpackage org.jf.dexlib2.writer; 335280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver 345280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport com.google.common.collect.ImmutableSet; 355280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport com.google.common.collect.Iterables; 365280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport com.google.common.collect.Lists; 375280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport junit.framework.Assert; 385280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport org.jf.dexlib2.AnnotationVisibility; 395280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport org.jf.dexlib2.Opcodes; 405280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport org.jf.dexlib2.dexbacked.DexBackedDexFile; 415280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport org.jf.dexlib2.iface.Annotation; 425280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport org.jf.dexlib2.iface.AnnotationElement; 435280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport org.jf.dexlib2.iface.ClassDef; 44bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruverimport org.jf.dexlib2.iface.value.AnnotationEncodedValue; 455280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport org.jf.dexlib2.immutable.ImmutableAnnotation; 465280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport org.jf.dexlib2.immutable.ImmutableAnnotationElement; 475280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport org.jf.dexlib2.immutable.ImmutableClassDef; 485280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport org.jf.dexlib2.immutable.ImmutableDexFile; 49bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruverimport org.jf.dexlib2.immutable.value.ImmutableAnnotationEncodedValue; 505280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport org.jf.dexlib2.immutable.value.ImmutableNullEncodedValue; 515280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport org.jf.dexlib2.writer.io.MemoryDataStore; 525280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport org.jf.dexlib2.writer.pool.DexPool; 535280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport org.junit.Test; 545280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver 555280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport java.io.IOException; 565280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverimport java.util.List; 575280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver 585280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruverpublic class DexWriterTest { 595280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver @Test 605280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver public void testAnnotationElementOrder() { 615280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver // Elements are out of order wrt to the element name 625280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver ImmutableSet<ImmutableAnnotationElement> elements = 635280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver ImmutableSet.of(new ImmutableAnnotationElement("zabaglione", ImmutableNullEncodedValue.INSTANCE), 645280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver new ImmutableAnnotationElement("blah", ImmutableNullEncodedValue.INSTANCE)); 655280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver 665280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver ImmutableAnnotation annotation = new ImmutableAnnotation(AnnotationVisibility.RUNTIME, 675280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver "Lorg/test/anno;", elements); 685280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver 695280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver ImmutableClassDef classDef = new ImmutableClassDef("Lorg/test/blah;", 705280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver 0, "Ljava/lang/Object;", null, null, ImmutableSet.of(annotation), null, null); 715280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver 725280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver MemoryDataStore dataStore = new MemoryDataStore(); 735280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver 745280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver try { 75e202aeede5fb5fcc8de22601157b212eabb5f1c6Ben Gruver DexPool.writeTo(dataStore, new ImmutableDexFile(Opcodes.forApi(19), ImmutableSet.of(classDef))); 765280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver } catch (IOException ex) { 775280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver throw new RuntimeException(ex); 785280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver } 795280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver 803ff884b1c345dbd030430e3eecf37e4d409f18b0Ben Gruver DexBackedDexFile dexFile = new DexBackedDexFile(Opcodes.forApi(15), dataStore.getData()); 815280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver ClassDef dbClassDef = Iterables.getFirst(dexFile.getClasses(), null); 825280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver Assert.assertNotNull(dbClassDef); 835280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver Annotation dbAnnotation = Iterables.getFirst(dbClassDef.getAnnotations(), null); 845280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver Assert.assertNotNull(dbAnnotation); 855280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver List<AnnotationElement> dbElements = Lists.newArrayList(dbAnnotation.getElements()); 865280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver 875280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver // Ensure that the elements were written out in sorted order 885280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver Assert.assertEquals(2, dbElements.size()); 895280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver Assert.assertEquals("blah", dbElements.get(0).getName()); 905280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver Assert.assertEquals("zabaglione", dbElements.get(1).getName()); 915280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver } 92bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver 93bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver @Test 94bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver public void testEncodedAnnotationElementOrder() { 95bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver // Elements are out of order wrt to the element name 96bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver ImmutableSet<ImmutableAnnotationElement> encodedElements = 97bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver ImmutableSet.of(new ImmutableAnnotationElement("zabaglione", ImmutableNullEncodedValue.INSTANCE), 98bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver new ImmutableAnnotationElement("blah", ImmutableNullEncodedValue.INSTANCE)); 99bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver 100bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver ImmutableAnnotationEncodedValue encodedAnnotations = 101bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver new ImmutableAnnotationEncodedValue("Lan/encoded/annotation", encodedElements); 102bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver 103bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver ImmutableSet<ImmutableAnnotationElement> elements = 104bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver ImmutableSet.of(new ImmutableAnnotationElement("encoded_annotation", encodedAnnotations)); 105bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver 106bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver ImmutableAnnotation annotation = new ImmutableAnnotation(AnnotationVisibility.RUNTIME, 107bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver "Lorg/test/anno;", elements); 108bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver 109bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver ImmutableClassDef classDef = new ImmutableClassDef("Lorg/test/blah;", 110bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver 0, "Ljava/lang/Object;", null, null, ImmutableSet.of(annotation), null, null); 111bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver 112bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver MemoryDataStore dataStore = new MemoryDataStore(); 113bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver 114bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver try { 115e202aeede5fb5fcc8de22601157b212eabb5f1c6Ben Gruver DexPool.writeTo(dataStore, new ImmutableDexFile(Opcodes.forApi(19), ImmutableSet.of(classDef))); 116bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver } catch (IOException ex) { 117bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver throw new RuntimeException(ex); 118bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver } 119bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver 1203ff884b1c345dbd030430e3eecf37e4d409f18b0Ben Gruver DexBackedDexFile dexFile = new DexBackedDexFile(Opcodes.forApi(15), dataStore.getData()); 121bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver ClassDef dbClassDef = Iterables.getFirst(dexFile.getClasses(), null); 122bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver Assert.assertNotNull(dbClassDef); 123bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver Annotation dbAnnotation = Iterables.getFirst(dbClassDef.getAnnotations(), null); 124bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver Assert.assertNotNull(dbAnnotation); 125bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver 126bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver AnnotationElement element = Iterables.getFirst(dbAnnotation.getElements(), null); 127bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver AnnotationEncodedValue dbAnnotationEncodedValue = (AnnotationEncodedValue)element.getValue(); 128bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver 129bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver List<AnnotationElement> dbElements = Lists.newArrayList(dbAnnotationEncodedValue.getElements()); 130bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver 131bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver // Ensure that the elements were written out in sorted order 132bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver Assert.assertEquals(2, dbElements.size()); 133bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver Assert.assertEquals("blah", dbElements.get(0).getName()); 134bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver Assert.assertEquals("zabaglione", dbElements.get(1).getName()); 135bf167c2f0ed5b9ebde990819554b33373449e39bBen Gruver } 1365280047b4261f5a6619a7a7b64e2666c06e107f6Ben Gruver} 137