Merge "PreloadCheck: Add support for regex checking"
This commit is contained in:
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 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.preload.check;
|
||||||
|
|
||||||
|
import dalvik.system.DexFile;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class NotInitializedRegex {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Matcher m = Pattern.compile(args[0]).matcher("");
|
||||||
|
boolean requiresMatch = args.length > 1 ? Boolean.parseBoolean(args[1]) : false;
|
||||||
|
|
||||||
|
Collection<DexFile> dexFiles = Util.getBootDexFiles();
|
||||||
|
int matched = 0, notMatched = 0;
|
||||||
|
for (DexFile dexFile : dexFiles) {
|
||||||
|
Enumeration<String> entries = dexFile.entries();
|
||||||
|
while (entries.hasMoreElements()) {
|
||||||
|
String entry = entries.nextElement();
|
||||||
|
m.reset(entry);
|
||||||
|
if (m.matches()) {
|
||||||
|
System.out.println(entry + ": match");
|
||||||
|
matched++;
|
||||||
|
check(entry);
|
||||||
|
} else {
|
||||||
|
System.out.println(entry + ": no match");
|
||||||
|
notMatched++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println("Matched: " + matched + " Not-Matched: " + notMatched);
|
||||||
|
if (requiresMatch && matched == 0) {
|
||||||
|
throw new RuntimeException("Did not find match");
|
||||||
|
}
|
||||||
|
System.out.println("OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void check(String name) {
|
||||||
|
Util.assertNotInitialized(name, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,18 @@
|
|||||||
|
|
||||||
package com.android.preload.check;
|
package com.android.preload.check;
|
||||||
|
|
||||||
|
import dalvik.system.DexFile;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class Util {
|
public class Util {
|
||||||
private static Field statusField;
|
private static Field statusField;
|
||||||
@@ -31,6 +42,49 @@ public class Util {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Collection<DexFile> getBootDexFiles() throws Exception {
|
||||||
|
Class<?> vmClassLoaderClass = Class.forName("java.lang.VMClassLoader");
|
||||||
|
Method getResources = vmClassLoaderClass.getDeclaredMethod("getResources", String.class);
|
||||||
|
getResources.setAccessible(true);
|
||||||
|
LinkedList<DexFile> res = new LinkedList<>();
|
||||||
|
for (int i = 1;; i++) {
|
||||||
|
try {
|
||||||
|
String name = "classes" + (i > 1 ? String.valueOf(i) : "") + ".dex";
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<URL> urls = (List<URL>) getResources.invoke(null, name);
|
||||||
|
if (urls.isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (URL url : urls) {
|
||||||
|
// Make temp copy, so we can use public API. Would be nice to use in-memory, but
|
||||||
|
// those are unstable.
|
||||||
|
String tmp = "/data/local/tmp/tmp.dex";
|
||||||
|
try (BufferedInputStream in = new BufferedInputStream(url.openStream());
|
||||||
|
BufferedOutputStream out = new BufferedOutputStream(
|
||||||
|
new FileOutputStream(tmp))) {
|
||||||
|
byte[] buf = new byte[4096];
|
||||||
|
for (;;) {
|
||||||
|
int r = in.read(buf);
|
||||||
|
if (r == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
out.write(buf, 0, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
res.add(new DexFile(tmp));
|
||||||
|
} catch (Exception dexError) {
|
||||||
|
dexError.printStackTrace(System.out);
|
||||||
|
}
|
||||||
|
new File(tmp).delete();
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isInitialized(Class<?> klass) throws Exception {
|
public static boolean isInitialized(Class<?> klass) throws Exception {
|
||||||
Object val = statusField.get(klass);
|
Object val = statusField.get(klass);
|
||||||
if (val == null || !(val instanceof Integer)) {
|
if (val == null || !(val instanceof Integer)) {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package com.android.preload.check;
|
package com.android.preload.check;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import com.android.tradefed.device.ITestDevice;
|
import com.android.tradefed.device.ITestDevice;
|
||||||
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
|
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
|
||||||
@@ -97,6 +97,14 @@ public class PreloadCheck implements IDeviceTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the classes ending in NoPreloadHolder are not initialized.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testNoPreloadHolder() throws Exception {
|
||||||
|
run("com.android.preload.check.NotInitializedRegex", ".*NoPreloadHolder$", "true");
|
||||||
|
}
|
||||||
|
|
||||||
private void run(String cmd, String... args) throws Exception {
|
private void run(String cmd, String... args) throws Exception {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("app_process ")
|
sb.append("app_process ")
|
||||||
@@ -107,7 +115,7 @@ public class PreloadCheck implements IDeviceTest {
|
|||||||
sb.append(' ').append(escape(arg));
|
sb.append(' ').append(escape(arg));
|
||||||
}
|
}
|
||||||
String res = mTestDevice.executeShellCommand(sb.toString());
|
String res = mTestDevice.executeShellCommand(sb.toString());
|
||||||
assertEquals(sb.toString(), "OK", res.trim());
|
assertTrue(sb.toString() + "\n===\n" + res, res.trim().endsWith("OK"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String escape(String input) {
|
private static String escape(String input) {
|
||||||
|
|||||||
Reference in New Issue
Block a user