Home | History | Annotate | Download | only in create
      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 
     18 package com.android.tools.layoutlib.create;
     19 
     20 import com.android.tools.layoutlib.create.AsmAnalyzer.DependencyVisitor;
     21 
     22 import org.junit.Before;
     23 import org.junit.Test;
     24 import org.objectweb.asm.ClassReader;
     25 
     26 import java.io.IOException;
     27 import java.io.InputStream;
     28 import java.net.URL;
     29 import java.util.ArrayList;
     30 import java.util.Collections;
     31 import java.util.Map;
     32 import java.util.Set;
     33 import java.util.TreeMap;
     34 
     35 import static org.junit.Assert.assertArrayEquals;
     36 import static org.junit.Assert.assertEquals;
     37 import static org.junit.Assert.assertNotNull;
     38 
     39 /**
     40  * Unit tests for some methods of {@link AsmAnalyzer}.
     41  */
     42 public 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