Home | History | Annotate | Download | only in dx
      1 /*
      2  * Copyright (C) 2012 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 package com.android.dx;
     18 
     19 import android.os.Build;
     20 import org.junit.Test;
     21 
     22 import java.io.File;
     23 import java.util.Arrays;
     24 import java.util.HashSet;
     25 import java.util.Set;
     26 
     27 import static org.junit.Assert.assertEquals;
     28 import static org.junit.Assert.assertNotNull;
     29 import static org.junit.Assert.assertTrue;
     30 
     31 public final class AppDataDirGuesserTest {
     32     @Test
     33     public void testGuessCacheDir_SimpleExample() {
     34         guessCacheDirFor("/data/app/a.b.c.apk").shouldGive("/data/data/a.b.c/cache");
     35         guessCacheDirFor("/data/app/a.b.c.tests.apk").shouldGive("/data/data/a.b.c.tests/cache");
     36     }
     37 
     38     @Test
     39     public void testGuessCacheDir_MultipleResultsSeparatedByColon() {
     40         guessCacheDirFor("/data/app/a.b.c.apk:/data/app/d.e.f.apk")
     41                 .shouldGive("/data/data/a.b.c/cache", "/data/data/d.e.f/cache");
     42     }
     43 
     44     @Test
     45     public void testGuessCacheDir_NotWriteableSkipped() {
     46         guessCacheDirFor("/data/app/a.b.c.apk:/data/app/d.e.f.apk")
     47                 .withNonWriteable("/data/data/a.b.c/cache")
     48                 .shouldGive("/data/data/d.e.f/cache");
     49     }
     50 
     51     @Test
     52     public void testGuessCacheDir_StripHyphenatedSuffixes() {
     53         guessCacheDirFor("/data/app/a.b.c-2.apk").shouldGive("/data/data/a.b.c/cache");
     54     }
     55 
     56     @Test
     57     public void testGuessCacheDir_LeadingAndTrailingColonsIgnored() {
     58         guessCacheDirFor("/data/app/a.b.c.apk:asdf:").shouldGive("/data/data/a.b.c/cache");
     59         guessCacheDirFor(":asdf:/data/app/a.b.c.apk").shouldGive("/data/data/a.b.c/cache");
     60     }
     61 
     62     @Test
     63     public void testGuessCacheDir_InvalidInputsGiveEmptyArray() {
     64         guessCacheDirFor("").shouldGive();
     65     }
     66 
     67     @Test
     68     public void testGuessCacheDir_JarsIgnored() {
     69         guessCacheDirFor("/data/app/a.b.c.jar").shouldGive();
     70         guessCacheDirFor("/system/framework/android.test.runner.jar").shouldGive();
     71     }
     72 
     73     @Test
     74     public void testGuessCacheDir_RealWorldExample() {
     75         String realPath = "/system/framework/android.test.runner.jar:" +
     76                 "/data/app/com.google.android.voicesearch.tests-2.apk:" +
     77                 "/data/app/com.google.android.voicesearch-1.apk";
     78         guessCacheDirFor(realPath)
     79                 .withNonWriteable("/data/data/com.google.android.voicesearch.tests/cache")
     80                 .shouldGive("/data/data/com.google.android.voicesearch/cache");
     81     }
     82 
     83     @Test
     84     public void testSplitPathList() {
     85         final String[] expected = { "foo", "bar" };
     86         assertTrue(Arrays.equals(expected, AppDataDirGuesser.splitPathList("foo:bar")));
     87         assertTrue(Arrays.equals(expected,
     88                 AppDataDirGuesser.splitPathList("dexPath=foo:bar")));
     89         assertTrue(Arrays.equals(expected,
     90                 AppDataDirGuesser.splitPathList("dexPath=foo:bar,bazPath=bar:bar2")));
     91     }
     92 
     93     @Test
     94     public void testPre43PathProcessing() {
     95         String input = "dalvik.system.PathClassLoader[dexPath=/data/app/abc-1.apk," +
     96                        "libraryPath=/data/app-lib/abc-1]";
     97         String processed = AppDataDirGuesser.processClassLoaderString(input);
     98         assertTrue("dexPath=/data/app/abc-1.apk,libraryPath=/data/app-lib/abc-1".equals(processed));
     99     }
    100 
    101     @Test
    102     public void test43PathProcessing() {
    103         String input = "dalvik.system.PathClassLoader[DexPathList[[zip file " +
    104                        "\"/data/app/abc-1/base.apk\", zip file \"/data/app/def-1/base.apk\"], " +
    105                        "nativeLibraryDirectories=[/data/app-lib/abc-1]]]";
    106         String processed = AppDataDirGuesser.processClassLoaderString(input);
    107         assertTrue("/data/app/abc-1/base.apk:/data/app/def-1/base.apk".equals(processed));
    108     }
    109 
    110     @Test
    111     public void testApiLevel17PlusPathProcessing() {
    112         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    113             // Our processing should work for anything >= Android 4.2.
    114             String input = getClass().getClassLoader().toString();
    115             String processed = AppDataDirGuesser.processClassLoaderString(input);
    116             // TODO: this comment is no longer true now that we run tests on Android instead of vogar
    117             // A tighter check would be interesting. But vogar doesn't run the tests in a directory
    118             // recognized by the guesser (usually under /data/local/tmp), so we cannot use the
    119             // processed result as input to guessPath.
    120             assertTrue(!input.equals(processed));
    121         }
    122     }
    123 
    124     private interface TestCondition {
    125         TestCondition withNonWriteable(String... files);
    126         void shouldGive(String... files);
    127     }
    128 
    129     private TestCondition guessCacheDirFor(final String path) {
    130         final Set<String> notWriteable = new HashSet<>();
    131         return new TestCondition() {
    132             public void shouldGive(String... files) {
    133                 AppDataDirGuesser guesser = new AppDataDirGuesser() {
    134                     @Override
    135                     public boolean isWriteableDirectory(File file) {
    136                         return !notWriteable.contains(file.getAbsolutePath());
    137                     }
    138                     @Override
    139                     boolean fileOrDirExists(File file) {
    140                         return true;
    141                     }
    142                 };
    143                 File[] results = guesser.guessPath(path);
    144                 assertNotNull("Null results for " + path, results);
    145                 assertEquals("Bad lengths for " + path, files.length, results.length);
    146                 for (int i = 0; i < files.length; ++i) {
    147                     assertEquals("Element " + i, new File(files[i]), results[i]);
    148                 }
    149             }
    150 
    151             public TestCondition withNonWriteable(String... files) {
    152                 notWriteable.addAll(Arrays.asList(files));
    153                 return this;
    154             }
    155         };
    156     }
    157 }
    158