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