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