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