blob: 55907f989b6aed8a2c41e4313098618770e00222 [file] [log] [blame]
The Android Open Source Projectf8057102009-03-15 16:47:16 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package dex.reader;
18
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertNotNull;
21import static org.junit.Assert.assertTrue;
22
23import java.io.FileWriter;
24import java.io.IOException;
25import java.lang.reflect.Modifier;
26import java.util.Arrays;
27import java.util.HashSet;
28import java.util.List;
29import java.util.Set;
30
31import org.junit.Test;
32
33import dex.reader.util.JavaSource;
34import dex.structure.DexAnnotation;
35import dex.structure.DexAnnotationAttribute;
36import dex.structure.DexClass;
37import dex.structure.DexEncodedValue;
38import dex.structure.DexField;
39import dex.structure.DexFile;
40import dex.structure.DexMethod;
41import dex.structure.DexParameter;
42
43
44public class DexFileReaderTests extends DexTestsCommon {
45
46 private static final String LDALVIK_ANNOTATION_SIGNATURE = "Ldalvik/annotation/Signature;";
47
48
49 JavaSource A = new JavaSource("a.b.c.A",
50 "package a.b.c; public class A{ public void get() {}}"
51 );
52
53 @Test
54 public void testA() throws IOException {
55 DexFile dexFile = javaToDexUtil.getFrom(A);
56 assertEquals(1, dexFile.getDefinedClasses().size());
57 @SuppressWarnings("unused")
58 DexClass class1 = getClass(dexFile, "La/b/c/A;");
59 System.out.println(dexFile);
60 }
61
62
63 JavaSource T0 = new JavaSource("T0",
64 "public class T0 {" +
65 " public int publicIntField;" +
66 " protected long protectedLongField;" +
67 " short defaultShortField;" +
68 " private double privateDoubleField;" +
69 " " +
70 " public String publicStringMethodInt(int a){ return \"bla\"; }" +
71 " protected String protectedStringMethodInt(int a){ return \"bla\"; }" +
72 " String defaultStringMethodInt(int a){ return \"bla\"; }" +
73 " private String privateStringMethodInt(int a){ return \"bla\"; }" +
74 "}"
75 );
76
77 /**
78 * Tests parsing a simple class.
79 */
80 @Test
81 public void testT0() throws IOException {
82
83 DexFile dexFile = javaToDexUtil.getFrom(T0);
84 assertEquals(1, dexFile.getDefinedClasses().size());
85 DexClass clazz = dexFile.getDefinedClasses().get(0);
86 assertEquals("LT0;", clazz.getName());
87 assertPublic(clazz);
88 //fields
89 assertEquals(4, clazz.getFields().size());
90 DexField field = getField(clazz, "publicIntField");
91 assertPublic(field);
92 field = getField(clazz, "protectedLongField");
93 assertProtected(field);
94 field = getField(clazz, "defaultShortField");
95 assertDefault(field);
96 field = getField(clazz, "privateDoubleField");
97 assertPrivate(field);
98 //methods
99 DexMethod method = getMethod(clazz, "publicStringMethodInt", "I");
100 assertPublic(method);
101 method = getMethod(clazz, "protectedStringMethodInt", "I");/** a.b.C */
102 assertProtected(method);
103 method = getMethod(clazz, "defaultStringMethodInt", "I");
104 assertDefault(method);
105 method = getMethod(clazz, "privateStringMethodInt", "I");
106 assertPrivate(method);
107 }
108
109 JavaSource T1 = new JavaSource( "T1","public class T1 extends T0 {}" );
110
111
112 private static Set<JavaSource> toSet(JavaSource...javaSources){
113 return new HashSet<JavaSource>(Arrays.asList(javaSources));
114 }
115
116 private static Set<String> toStringSet(JavaSource... javaSources) {
117 Set<String> names = new HashSet<String>();
118 for (JavaSource javaSource : javaSources) {
119 names.add(javaSource.getName());
120 }
121
122 return names;
123 }
124
125 private static Set<String> toStringSet(String... javaSourceName) {
126 return new HashSet<String>(Arrays.asList(javaSourceName));
127 }
128
129 /**
130 * Tests parsing a simple sub class.
131 * @throws IOException
132 */
133 @Test
134 public void testT1() throws IOException {
135 DexFile dexFile = javaToDexUtil.getFrom(toSet(T1, T0), toStringSet(T1));
136 assertEquals(1, dexFile.getDefinedClasses().size());
137 DexClass clazz = dexFile.getDefinedClasses().get(0);
138 assertEquals("LT1;", clazz.getName());
139 assertPublic(clazz);
140 assertEquals("LT0;", clazz.getSuperClass());
141 }
142
143 /**
144 * Tests parsing T0 and T1 from same dex file.
145 *
146 * @throws IOException
147 */
148 @Test
149 public void testT0_T1() throws IOException {
150 DexFile dexFile = javaToDexUtil.getFrom(T1, T0);
151 assertEquals(2, dexFile.getDefinedClasses().size());
152
153 DexClass T0 = getClass(dexFile, "LT0;");
154 assertPublic(T0);
155
156 DexClass T1 = getClass(dexFile, "LT1;");
157 assertPublic(T1);
158
159 assertEquals(T1.getSuperClass(), T0.getName());
160 }
161
162 static final JavaSource A0 = new JavaSource("A0",
163 "import java.lang.annotation.*;" +
164 "@Retention(RetentionPolicy.RUNTIME)" +
165 "@Target(ElementType.TYPE)" +
166 "public @interface A0 {}"
167 );
168
169 /**
170 * Tests parsing Annotation Declaration.
171 */
172 @Test
173 public void testA0() throws IOException {
174 DexFile dexFile = javaToDexUtil.getFrom(A0);
175 assertEquals(1, dexFile.getDefinedClasses().size());
176
177 DexClass A0 = getClass(dexFile, "LA0;");
178 assertPublic(A0);
179 assertEquals(2, A0.getAnnotations().size());
180 }
181
182
183 static final JavaSource T3 = new JavaSource("T3",
184 "import java.io.*;" +
185 "@A0 " +
186 "public final class T3 {}"
187 );
188
189
190 /**
191 * Tests parsing Annotated Class.
192 */
193 @Test
194 public void testA0_T3() throws IOException {
195 DexFile dexFile = javaToDexUtil.getFrom(T3, A0);
196 assertEquals(2, dexFile.getDefinedClasses().size());
197
198 DexClass T3 = getClass(dexFile, "LT3;");
199 assertPublic(T3);
200 assertEquals(1, T3.getAnnotations().size());
201
202 DexAnnotation annotation = getAnnotation(T3, "LA0;");
203
204 DexClass A0 = getClass(dexFile, "LA0;");
205
206 assertEquals(A0.getName(), annotation.getTypeName());
207 }
208
209
210 static final JavaSource G0 = new JavaSource("G0","public class G0<T>{}");
211
212 /**
213 * Tests parsing Generic Type.
214 */
215 @Test
216 public void testG0() throws IOException {
217 DexFile dexFile = javaToDexUtil.getFrom(G0);
218 assertEquals(1, dexFile.getDefinedClasses().size());
219 DexClass G0 = getClass(dexFile, "LG0;");
220 assertPublic(G0);
221 DexAnnotation sig = getAnnotation(G0, LDALVIK_ANNOTATION_SIGNATURE);
222 assertEquals(1, sig.getAttributes().size());
223 DexAnnotationAttribute dexAnnotationValue = sig.getAttributes().get(0);
224 assertNotNull(dexAnnotationValue.getEncodedValue());
225 Object value = dexAnnotationValue.getEncodedValue().getValue();
226 assertTrue(value instanceof List);
227 StringBuilder builder = new StringBuilder();
228 for (Object o : (List<?>)value) {
229 builder.append(((DexEncodedValue)o).getValue());
230 }
231 //FIXME verify
232 assertEquals("<T:Ljava/lang/Object;>Ljava/lang/Object;", builder.toString());
233 }
234
235 static final JavaSource G1 = new JavaSource("G1","public class G1<T extends G1>{}");
236
237 /**
238 * Tests parsing Generic Type.
239 */
240 @Test
241 public void testG1() throws IOException {
242 DexFile dexFile = javaToDexUtil.getFrom(G1);
243 assertEquals(1, dexFile.getDefinedClasses().size());
244 DexClass G1 = getClass(dexFile, "LG1;");
245 assertPublic(G1);
246 DexAnnotation sig = getAnnotation(G1, LDALVIK_ANNOTATION_SIGNATURE);
247 assertEquals(1, sig.getAttributes().size());
248 DexAnnotationAttribute dexAnnotationValue = sig.getAttributes().get(0);
249 assertNotNull(dexAnnotationValue.getEncodedValue());
250 Object value = dexAnnotationValue.getEncodedValue().getValue();
251 assertTrue(value instanceof List);
252 StringBuilder builder = new StringBuilder();
253 for (Object o : (List<?>)value) {
254 builder.append(((DexEncodedValue)o).getValue());
255 }
256 //FIXME verify
257 assertEquals("<T:LG1;>Ljava/lang/Object;", builder.toString());
258 }
259
260
261
262 static final JavaSource I0 = new JavaSource("I0",
263 "import java.io.Serializable;" +
264 "public interface I0 extends Serializable {}"
265 );
266
267 /**
268 * Tests parsing Interface Type.
269 */
270 @Test
271 public void testI0() throws IOException {
272 DexFile dexFile = javaToDexUtil.getFrom(I0);
273 assertEquals(1, dexFile.getDefinedClasses().size());
274 DexClass I0 = getClass(dexFile, "LI0;");
275 assertPublic(I0);
276 assertTrue(Modifier.isInterface(I0.getModifiers()));
277 assertEquals(1, I0.getInterfaces().size());
278 assertEquals("Ljava/io/Serializable;", I0.getInterfaces().get(0));
279 }
280
281
282 static final JavaSource Outer0 = new JavaSource("Outer0",
283 "public class Outer0 {" +
284 " static class StaticInner {}" +
285 " class Inner{}" +
286 "}"
287 );
288
289 /**
290 * Tests parsing Interface Type.
291 * @throws IOException
292 */
293 @SuppressWarnings("unchecked")
294 @Test
295 public void testOuter0() throws IOException {
296 DexFile dexFile = javaToDexUtil.getFrom(toSet(Outer0), toStringSet("Outer0", "Outer0$Inner", "Outer0$StaticInner"));
297 assertEquals(3, dexFile.getDefinedClasses().size());
298 DexClass Outer0 = getClass(dexFile, "LOuter0;");
299 DexAnnotation sig = getAnnotation(Outer0, "Ldalvik/annotation/MemberClasses;");
300 assertEquals(1, sig.getAttributes().size());
301 DexAnnotationAttribute dexAnnotationValue = sig.getAttributes().get(0);
302 assertNotNull(dexAnnotationValue.getEncodedValue());
303 List<DexEncodedValue> values = (List<DexEncodedValue>) dexAnnotationValue.getEncodedValue().getValue();
304 Set<String> innerTypeNames = new HashSet<String>();
305 for (DexEncodedValue value : values) {
306 innerTypeNames.add((String) value.getValue());
307 }
308 DexClass inner = getClass(dexFile, "LOuter0$Inner;");
309 DexClass staticInner = getClass(dexFile, "LOuter0$StaticInner;");
310 assertTrue(innerTypeNames.contains(inner.getName()));
311 assertTrue(innerTypeNames.contains(staticInner.getName()));
312 }
313
314 static final JavaSource parameterAnnotation = new JavaSource("A",
315 "public class A {" +
316 " void m(@Deprecated int a) {}" +
317 "}");
318
319 /**
320 * Tests parameter annotation.
321 *
322 * @throws IOException
323 */
324 @Test
325 public void testParameterAnnotation() throws IOException {
326 DexFile dexFile = javaToDexUtil.getFrom(parameterAnnotation);
327 assertEquals(1, dexFile.getDefinedClasses().size());
328 DexClass A = getClass(dexFile, "LA;");
329
330 DexMethod method = getMethod(A, "m", "I");
331 assertEquals(1, method.getParameters().size());
332 DexParameter dexParameter = method.getParameters().get(0);
333 assertEquals("I", dexParameter.getTypeName());
334
335 assertEquals(1, dexParameter.getAnnotations().size());
336 DexAnnotation annotation = dexParameter.getAnnotations().iterator().next();
337 assertEquals("Ljava/lang/Deprecated;", annotation.getTypeName());
338 }
339
340 @Test
341 public void testEnum() throws IOException {
342 JavaSource source = new JavaSource("E", "public enum E { A,B; public static final E C = null; }");
343 DexFile dexFile = javaToDexUtil.getFrom(source);
344 assertEquals(1, dexFile.getDefinedClasses().size());
345 DexClass E = getClass(dexFile, "LE;");
346 System.out.println(E);
347 System.out.println(E.getFields());
348 }
349
350 /**
351 * Tests parsing of huge dex file.
352 * @throws IOException
353 */
354 @Test
355 public void testAllReader() throws IOException {
356 FileWriter w = new FileWriter("dex/classes.out.dex");
357 DexFileReader dexReader = new DexFileReader();
358 DexFile dexFile = dexReader.read(new DexBuffer("dex/classes.dex"));
359 TypeFormatter formatter = new TypeFormatter();
360 w.append(formatter.formatDexFile(dexFile));
361 w.flush();
362 w.close();
363 assertTrue(true);
364 }
365
366 /**
367 * Tests parsing of huge dex file.
368 * @throws IOException
369 */
370 @Test
371 public void testAllReader0() throws IOException {
372 FileWriter w = new FileWriter("dex/classes0.out.dex");
373 DexFileReader dexReader = new DexFileReader();
374 DexFile dexFile = dexReader.read(new DexBuffer("dex/classes0.dex"));
375 TypeFormatter formatter = new TypeFormatter();
376 w.append(formatter.formatDexFile(dexFile));
377 w.flush();
378 w.close();
379 assertTrue(true);
380 }
381
382}