1/* 2 * Copyright (C) 2008 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 17 18package com.android.tools.layoutlib.create; 19 20import static org.junit.Assert.assertArrayEquals; 21import static org.junit.Assert.assertEquals; 22import static org.junit.Assert.assertNotNull; 23 24import com.android.tools.layoutlib.create.AsmAnalyzer.DependencyVisitor; 25 26import org.junit.After; 27import org.junit.Before; 28import org.junit.Test; 29import org.objectweb.asm.ClassReader; 30 31import java.io.IOException; 32import java.net.URL; 33import java.util.ArrayList; 34import java.util.HashSet; 35import java.util.Map; 36import java.util.Set; 37import java.util.TreeMap; 38 39/** 40 * Unit tests for some methods of {@link AsmAnalyzer}. 41 */ 42public class AsmAnalyzerTest { 43 44 private MockLog mLog; 45 private ArrayList<String> mOsJarPath; 46 private AsmAnalyzer mAa; 47 48 @Before 49 public void setUp() throws Exception { 50 mLog = new MockLog(); 51 URL url = this.getClass().getClassLoader().getResource("data/mock_android.jar"); 52 53 mOsJarPath = new ArrayList<String>(); 54 mOsJarPath.add(url.getFile()); 55 56 Set<String> excludeClasses = new HashSet<String>(1); 57 excludeClasses.add("java.lang.JavaClass"); 58 mAa = new AsmAnalyzer(mLog, mOsJarPath, null /* gen */, 59 null /* deriveFrom */, null /* includeGlobs */, excludeClasses); 60 } 61 62 @After 63 public void tearDown() throws Exception { 64 } 65 66 @Test 67 public void testParseZip() throws IOException { 68 Map<String, ClassReader> map = mAa.parseZip(mOsJarPath); 69 70 assertArrayEquals(new String[] { 71 "java.lang.JavaClass", 72 "mock_android.dummy.InnerTest", 73 "mock_android.dummy.InnerTest$DerivingClass", 74 "mock_android.dummy.InnerTest$MyGenerics1", 75 "mock_android.dummy.InnerTest$MyIntEnum", 76 "mock_android.dummy.InnerTest$MyStaticInnerClass", 77 "mock_android.dummy.InnerTest$NotStaticInner1", 78 "mock_android.dummy.InnerTest$NotStaticInner2", 79 "mock_android.view.View", 80 "mock_android.view.ViewGroup", 81 "mock_android.view.ViewGroup$LayoutParams", 82 "mock_android.view.ViewGroup$MarginLayoutParams", 83 "mock_android.widget.LinearLayout", 84 "mock_android.widget.LinearLayout$LayoutParams", 85 "mock_android.widget.TableLayout", 86 "mock_android.widget.TableLayout$LayoutParams" 87 }, 88 map.keySet().toArray()); 89 } 90 91 @Test 92 public void testFindClass() throws IOException, LogAbortException { 93 Map<String, ClassReader> zipClasses = mAa.parseZip(mOsJarPath); 94 TreeMap<String, ClassReader> found = new TreeMap<String, ClassReader>(); 95 96 ClassReader cr = mAa.findClass("mock_android.view.ViewGroup$LayoutParams", 97 zipClasses, found); 98 99 assertNotNull(cr); 100 assertEquals("mock_android/view/ViewGroup$LayoutParams", cr.getClassName()); 101 assertArrayEquals(new String[] { "mock_android.view.ViewGroup$LayoutParams" }, 102 found.keySet().toArray()); 103 assertArrayEquals(new ClassReader[] { cr }, found.values().toArray()); 104 } 105 106 @Test 107 public void testFindGlobs() throws IOException, LogAbortException { 108 Map<String, ClassReader> zipClasses = mAa.parseZip(mOsJarPath); 109 TreeMap<String, ClassReader> found = new TreeMap<String, ClassReader>(); 110 111 // this matches classes, a package match returns nothing 112 found.clear(); 113 mAa.findGlobs("mock_android.view", zipClasses, found); 114 115 assertArrayEquals(new String[] { }, 116 found.keySet().toArray()); 117 118 // a complex glob search. * is a search pattern that matches names, not dots 119 mAa.findGlobs("mock_android.*.*Group$*Layout*", zipClasses, found); 120 121 assertArrayEquals(new String[] { 122 "mock_android.view.ViewGroup$LayoutParams", 123 "mock_android.view.ViewGroup$MarginLayoutParams" 124 }, 125 found.keySet().toArray()); 126 127 // a complex glob search. ** is a search pattern that matches names including dots 128 mAa.findGlobs("mock_android.**Group*", zipClasses, found); 129 130 assertArrayEquals(new String[] { 131 "mock_android.view.ViewGroup", 132 "mock_android.view.ViewGroup$LayoutParams", 133 "mock_android.view.ViewGroup$MarginLayoutParams" 134 }, 135 found.keySet().toArray()); 136 137 // matches a single class 138 found.clear(); 139 mAa.findGlobs("mock_android.view.View", zipClasses, found); 140 141 assertArrayEquals(new String[] { 142 "mock_android.view.View" 143 }, 144 found.keySet().toArray()); 145 146 // matches everyting inside the given package but not sub-packages 147 found.clear(); 148 mAa.findGlobs("mock_android.view.*", zipClasses, found); 149 150 assertArrayEquals(new String[] { 151 "mock_android.view.View", 152 "mock_android.view.ViewGroup", 153 "mock_android.view.ViewGroup$LayoutParams", 154 "mock_android.view.ViewGroup$MarginLayoutParams" 155 }, 156 found.keySet().toArray()); 157 158 for (String key : found.keySet()) { 159 ClassReader value = found.get(key); 160 assertNotNull("No value for " + key, value); 161 assertEquals(key, AsmAnalyzer.classReaderToClassName(value)); 162 } 163 } 164 165 @Test 166 public void testFindClassesDerivingFrom() throws LogAbortException, IOException { 167 Map<String, ClassReader> zipClasses = mAa.parseZip(mOsJarPath); 168 TreeMap<String, ClassReader> found = new TreeMap<String, ClassReader>(); 169 170 mAa.findClassesDerivingFrom("mock_android.view.View", zipClasses, found); 171 172 assertArrayEquals(new String[] { 173 "mock_android.view.View", 174 "mock_android.view.ViewGroup", 175 "mock_android.widget.LinearLayout", 176 "mock_android.widget.TableLayout", 177 }, 178 found.keySet().toArray()); 179 180 for (String key : found.keySet()) { 181 ClassReader value = found.get(key); 182 assertNotNull("No value for " + key, value); 183 assertEquals(key, AsmAnalyzer.classReaderToClassName(value)); 184 } 185 } 186 187 @Test 188 public void testDependencyVisitor() throws IOException, LogAbortException { 189 Map<String, ClassReader> zipClasses = mAa.parseZip(mOsJarPath); 190 TreeMap<String, ClassReader> keep = new TreeMap<String, ClassReader>(); 191 TreeMap<String, ClassReader> new_keep = new TreeMap<String, ClassReader>(); 192 TreeMap<String, ClassReader> in_deps = new TreeMap<String, ClassReader>(); 193 TreeMap<String, ClassReader> out_deps = new TreeMap<String, ClassReader>(); 194 195 ClassReader cr = mAa.findClass("mock_android.widget.TableLayout", zipClasses, keep); 196 DependencyVisitor visitor = mAa.getVisitor(zipClasses, keep, new_keep, in_deps, out_deps); 197 198 // get first level dependencies 199 cr.accept(visitor, 0 /* flags */); 200 201 assertArrayEquals(new String[] { 202 "mock_android.view.ViewGroup", 203 "mock_android.widget.TableLayout$LayoutParams", 204 }, 205 out_deps.keySet().toArray()); 206 207 in_deps.putAll(out_deps); 208 out_deps.clear(); 209 210 // get second level dependencies 211 for (ClassReader cr2 : in_deps.values()) { 212 cr2.accept(visitor, 0 /* flags */); 213 } 214 215 assertArrayEquals(new String[] { 216 "mock_android.view.View", 217 "mock_android.view.ViewGroup$LayoutParams", 218 "mock_android.view.ViewGroup$MarginLayoutParams", 219 }, 220 out_deps.keySet().toArray()); 221 222 in_deps.putAll(out_deps); 223 out_deps.clear(); 224 225 // get third level dependencies (there are none) 226 for (ClassReader cr2 : in_deps.values()) { 227 cr2.accept(visitor, 0 /* flags */); 228 } 229 keep.putAll(new_keep); 230 231 assertArrayEquals(new String[] { }, out_deps.keySet().toArray()); 232 assertArrayEquals(new String[] { 233 "mock_android.widget.TableLayout", 234 }, keep.keySet().toArray()); 235 } 236} 237