| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.dx; |
| |
| import android.os.Build; |
| import android.os.Process; |
| import org.junit.Test; |
| |
| import java.io.File; |
| import java.util.Arrays; |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertTrue; |
| |
| public final class AppDataDirGuesserTest { |
| @Test |
| public void testGuessCacheDir_SimpleExample() { |
| guessCacheDirFor("/data/app/a.b.c.apk").shouldGive("/data/data/a.b.c/cache"); |
| guessCacheDirFor("/data/app/a.b.c.tests.apk").shouldGive("/data/data/a.b.c.tests/cache"); |
| } |
| |
| @Test |
| public void testGuessCacheDir_MultipleResultsSeparatedByColon() { |
| guessCacheDirFor("/data/app/a.b.c.apk:/data/app/d.e.f.apk") |
| .shouldGive("/data/data/a.b.c/cache", "/data/data/d.e.f/cache"); |
| } |
| |
| @Test |
| public void testGuessCacheDir_NotWriteableSkipped() { |
| guessCacheDirFor("/data/app/a.b.c.apk:/data/app/d.e.f.apk") |
| .withNonWriteable("/data/data/a.b.c/cache") |
| .shouldGive("/data/data/d.e.f/cache"); |
| } |
| |
| @Test |
| public void testGuessCacheDir_ForSecondaryUser() { |
| guessCacheDirFor("/data/app/a.b.c.apk:/data/app/d.e.f.apk") |
| .withNonWriteable("/data/data/a.b.c", "/data/data/d.e.f") |
| .withProcessUid(1110009) |
| .shouldGive("/data/user/11/a.b.c/cache", "/data/user/11/d.e.f/cache"); |
| } |
| |
| @Test |
| public void testGuessCacheDir_StripHyphenatedSuffixes() { |
| guessCacheDirFor("/data/app/a.b.c-2.apk").shouldGive("/data/data/a.b.c/cache"); |
| } |
| |
| @Test |
| public void testGuessCacheDir_LeadingAndTrailingColonsIgnored() { |
| guessCacheDirFor("/data/app/a.b.c.apk:asdf:").shouldGive("/data/data/a.b.c/cache"); |
| guessCacheDirFor(":asdf:/data/app/a.b.c.apk").shouldGive("/data/data/a.b.c/cache"); |
| } |
| |
| @Test |
| public void testGuessCacheDir_InvalidInputsGiveEmptyArray() { |
| guessCacheDirFor("").shouldGive(); |
| } |
| |
| @Test |
| public void testGuessCacheDir_JarsIgnored() { |
| guessCacheDirFor("/data/app/a.b.c.jar").shouldGive(); |
| guessCacheDirFor("/system/framework/android.test.runner.jar").shouldGive(); |
| } |
| |
| @Test |
| public void testGuessCacheDir_RealWorldExample() { |
| String realPath = "/system/framework/android.test.runner.jar:" + |
| "/data/app/com.google.android.voicesearch.tests-2.apk:" + |
| "/data/app/com.google.android.voicesearch-1.apk"; |
| guessCacheDirFor(realPath) |
| .withNonWriteable("/data/data/com.google.android.voicesearch.tests/cache") |
| .shouldGive("/data/data/com.google.android.voicesearch/cache"); |
| } |
| |
| @Test |
| public void testSplitPathList() { |
| final String[] expected = { "foo", "bar" }; |
| assertTrue(Arrays.equals(expected, AppDataDirGuesser.splitPathList("foo:bar"))); |
| assertTrue(Arrays.equals(expected, |
| AppDataDirGuesser.splitPathList("dexPath=foo:bar"))); |
| assertTrue(Arrays.equals(expected, |
| AppDataDirGuesser.splitPathList("dexPath=foo:bar,bazPath=bar:bar2"))); |
| } |
| |
| @Test |
| public void testPre43PathProcessing() { |
| String input = "dalvik.system.PathClassLoader[dexPath=/data/app/abc-1.apk," + |
| "libraryPath=/data/app-lib/abc-1]"; |
| String processed = AppDataDirGuesser.processClassLoaderString(input); |
| assertTrue("dexPath=/data/app/abc-1.apk,libraryPath=/data/app-lib/abc-1".equals(processed)); |
| } |
| |
| @Test |
| public void test43PathProcessing() { |
| String input = "dalvik.system.PathClassLoader[DexPathList[[zip file " + |
| "\"/data/app/abc-1/base.apk\", zip file \"/data/app/def-1/base.apk\"], " + |
| "nativeLibraryDirectories=[/data/app-lib/abc-1]]]"; |
| String processed = AppDataDirGuesser.processClassLoaderString(input); |
| assertTrue("/data/app/abc-1/base.apk:/data/app/def-1/base.apk".equals(processed)); |
| } |
| |
| @Test |
| public void testApiLevel17PlusPathProcessing() { |
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { |
| // Our processing should work for anything >= Android 4.2. |
| String input = getClass().getClassLoader().toString(); |
| String processed = AppDataDirGuesser.processClassLoaderString(input); |
| // TODO: this comment is no longer true now that we run tests on Android instead of vogar |
| // A tighter check would be interesting. But vogar doesn't run the tests in a directory |
| // recognized by the guesser (usually under /data/local/tmp), so we cannot use the |
| // processed result as input to guessPath. |
| assertTrue(!input.equals(processed)); |
| } |
| } |
| |
| @Test |
| public void testGetProcessUid() { |
| AppDataDirGuesser guesser = new AppDataDirGuesser(); |
| assertTrue(guesser.getProcessUid() == Process.myUid()); |
| } |
| |
| private interface TestCondition { |
| TestCondition withNonWriteable(String... files); |
| TestCondition withProcessUid(Integer uid); |
| void shouldGive(String... files); |
| } |
| |
| private TestCondition guessCacheDirFor(final String path) { |
| final Set<String> notWriteable = new HashSet<>(); |
| return new TestCondition() { |
| private Integer processUid; |
| public void shouldGive(String... files) { |
| AppDataDirGuesser guesser = new AppDataDirGuesser() { |
| @Override |
| public boolean isWriteableDirectory(File file) { |
| return !notWriteable.contains(file.getAbsolutePath()); |
| } |
| @Override |
| boolean fileOrDirExists(File file) { |
| return true; |
| } |
| @Override |
| Integer getProcessUid() { |
| return processUid; |
| } |
| }; |
| File[] results = guesser.guessPath(path); |
| assertNotNull("Null results for " + path, results); |
| assertEquals("Bad lengths for " + path, files.length, results.length); |
| for (int i = 0; i < files.length; ++i) { |
| assertEquals("Element " + i, new File(files[i]), results[i]); |
| } |
| } |
| |
| public TestCondition withNonWriteable(String... files) { |
| notWriteable.addAll(Arrays.asList(files)); |
| return this; |
| } |
| |
| @Override |
| public TestCondition withProcessUid(Integer uid) { |
| processUid = uid; |
| return this; |
| } |
| }; |
| } |
| } |