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