diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 01:06:02 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 01:06:02 +0000 |
commit | 2ac96517c414f848053cd6b584052f3b16d02719 (patch) | |
tree | bf1239f221f4c8aab5d33153d9dcff6f142ba90f | |
parent | ab57ac1dd2552b4f026ea6cbf54f5804245bb29d (diff) | |
parent | a499c017dcd2d9ad1a17b263a5e518bf137e3228 (diff) | |
download | vogar-android14-mainline-cellbroadcast-release.tar.gz |
Snap for 10447354 from a499c017dcd2d9ad1a17b263a5e518bf137e3228 to mainline-cellbroadcast-releaseaml_cbr_341710000aml_cbr_341610000aml_cbr_341510010aml_cbr_341410010aml_cbr_341311010aml_cbr_341110000aml_cbr_341011000aml_cbr_340914000android14-mainline-cellbroadcast-release
Change-Id: Id452456e8215d80accccab405676dd551c4153dc
-rw-r--r-- | Android.mk | 3 | ||||
-rw-r--r-- | README.md | 138 | ||||
-rw-r--r-- | src/vogar/Dexer.java | 1 | ||||
-rw-r--r-- | src/vogar/Run.java | 4 | ||||
-rw-r--r-- | src/vogar/Toolchain.java | 6 | ||||
-rw-r--r-- | src/vogar/Vogar.java | 21 | ||||
-rw-r--r-- | src/vogar/android/AndroidSdk.java | 76 | ||||
-rw-r--r-- | src/vogar/android/DeviceRuntime.java | 14 | ||||
-rw-r--r-- | src/vogar/android/InstallApkTask.java | 2 | ||||
-rw-r--r-- | src/vogar/commands/Command.java | 1 | ||||
-rw-r--r-- | src/vogar/tasks/BuildActionTask.java | 10 | ||||
-rw-r--r-- | test/vogar/android/AbstractModeTest.java | 4 | ||||
-rw-r--r-- | test/vogar/android/HostRuntimeLocalTargetTest.java | 8 | ||||
-rw-r--r-- | test/vogar/target/junit3/TestMethodWithParameterTest.java | 2 | ||||
-rw-r--r-- | test/vogar/target/testng/ChangeDefaultLocaleTest.java | 1 | ||||
-rw-r--r-- | test/vogar/target/testng/TestNgAnnotationsClass.java | 45 | ||||
-rw-r--r-- | test/vogar/target/testng/TestNgAnnotationsMethod.java | 45 | ||||
-rw-r--r-- | test/vogar/target/testng/TestRunnerTestNgTest.java | 62 |
18 files changed, 384 insertions, 59 deletions
@@ -31,14 +31,13 @@ LOCAL_JAVA_RESOURCE_DIRS := resources LOCAL_STATIC_JAVA_LIBRARIES := \ caliper \ caliper-gson \ - guavalib \ + guava \ junit \ testng \ vogar-jsr305 \ vogar-kxml-libcore-20110123 LOCAL_ADDITIONAL_DEPENDENCIES := \ - $(HOST_OUT_EXECUTABLES)/dx \ $(HOST_OUT_EXECUTABLES)/d8 \ $(HOST_OUT_JAVA_LIBRARIES)/desugar.jar diff --git a/README.md b/README.md new file mode 100644 index 0000000..8a6ec19 --- /dev/null +++ b/README.md @@ -0,0 +1,138 @@ +# Vogar + +Vogar is a generic code/test/benchmark runner tool for Android. It is +primarily used to run libcore and art tests and benchmarks, however +this tool can also run arbitrary Java files either on host or target +device. + +Vogar supports multiple testing frameworks and configurations: + + * Allows running JUnit tests, TestNG tests, jtreg tests, Caliper + benchmarks or executable Java classes. It supports running + fine-grained tests that can be specified with hash symbol, e.g. + "com.android.Test#test". + + * Allows running tests and benchmarks using five available runtime + modes: `activity`, `app_process`, `device`, `host` or `jvm`. + +## Building and running + +First build it: + +* With a minimal `aosp/master-art` tree: +```bash +export SOONG_ALLOW_MISSING_DEPENDENCIES=true +${ANDROID_BUILD_TOP}/art/tools/buildbot-build.sh --target +``` + +* With a full Android (AOSP) `aosp/master` tree: +```bash +m vogar +``` + +## Features + +Vogar supports running tests and/or benchmarks (called "actions" below in the document) +in five different modes (specified with `--mode` option). An "action" is a `.java` file, +directory or class names: + + 1. Activity (`--mode=activity`) + + Vogar runs given action in the context of an [`android.app.Activity`](https://developer.android.com/reference/android/app/Activity) on a device. + + 2. App (`--mode=app_process`) + + Vogar runs given action in an app_process runtime on a device or emulator. + Used in conjunction with the `--benchmark` option for running Caliper benchmarks. + This is required to benchmark any code relying on the android framework. + + ```bash + Vogar --mode app_process --benchmark frameworks/base/core/tests/benchmarks/src/android/os/ParcelBenchmark.java + ``` + +3. Device (`--mode=device`) + + Vogar runs given action in an ART runtime on a device or emulator. + +4. Host (`--mode=host`) + + Vogar runs in an ART runtime on the local machine built with any lunch combo. + Similar to "Device" mode but running local ART. + +5. JVM (`--mode=jvm`) + + Vogar runs given action in a Java VM on the local machine. + +Most frequently you will use either `--mode=device` or `--mode=host` mode. + +## Testing and debugging + +Vogar has unit test coverage around basic functionality. Most of the coverage +is for [JUnit](https://junit.org/) and [TestNG](https://testng.org/) integration. + +### Building and running + +First, build tests with: +```bash +m vogar-tests +``` + +Run all tests using phony make target with: +```bash +m run-vogar-tests +``` + +Or run manually (if you want to specify a subset of all unit tests, for example): +```bash +java -cp ${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/vogar-tests.jar \ + org.junit.runner.JUnitCore vogar.AllTests +``` + +## Architecture and implementation + +High level model of each Vogar run is: + + 1. Parsing input options. + 2. Creating a list of `Task` objects that encapsulate various steps required. + These `Task` objects can depend on each other, and get executed only if all + dependencies are already executed. + 3. Executing tasks. It include assembling the code, dexing it, packing in + an activity/runnable dex jar, preparing the environment (host or device), + pushing all artifacts, and running it. + +### Classes overview + +The basic building block of Vogar execution is the `Task` class. There are several +sub classes of `Task`, for example: + + * `MkdirTask` + * `RmTask` + * `PrepareTarget` + +The `Target` class encapsulates the runtime environment, for example a +remote device or the local host. There are four available environments: + + * `AdbTarget` is used when `--mode=device` is set. + + It makes sure device is connected, required directories are mount + properly, and all required files are synced to the device. + + * `AdbChrootTarget` is used when `--mode=device --chroot=/data/chroot/` + are set. + + Same as `AdbTarget` but relatively to a specified chroot directory + (instead of the whole system under the root directory on the device). + + * `LocalTarget` is used when `--mode=host` or `--mode=jvm` are set. + + Same as `AdbTarget` but runs on the host machine. + + * `SshTarget` is used when `--ssh <host:port>` is set. + + Same as `LocalTarget` but on a remote machine at the given address. + +After parsing command line options, Vogar builds a list of tasks which +are put in a `TaskQueue`. They are executed using all available cores +except when "Activity" mode is enabled -- in that case it is always one +thread. + diff --git a/src/vogar/Dexer.java b/src/vogar/Dexer.java index 0e38715..3bf50f0 100644 --- a/src/vogar/Dexer.java +++ b/src/vogar/Dexer.java @@ -20,6 +20,5 @@ package vogar; * Available tools for generating dex files */ public enum Dexer { - DX, D8, } diff --git a/src/vogar/Run.java b/src/vogar/Run.java index ba36594..402b1c4 100644 --- a/src/vogar/Run.java +++ b/src/vogar/Run.java @@ -106,6 +106,8 @@ public final class Run { public final boolean checkJni; public final boolean debugging; public final Integer sdkVersion; + public final boolean serialDexing; + public final boolean verboseDexStats; public Run(Vogar vogar, Toolchain toolchain, Console console, Mkdir mkdir, AndroidSdk androidSdk, Rm rm, Target target, File runnerDir) @@ -186,6 +188,8 @@ public final class Run { this.checkJni = vogar.checkJni; this.debugging = (vogar.debugPort != null) || vogar.debugApp; this.sdkVersion = vogar.sdkVersion; + this.serialDexing = vogar.serialDexing; + this.verboseDexStats = vogar.verboseDexStats; } private Mode createMode(ModeId modeId, Variant variant) { diff --git a/src/vogar/Toolchain.java b/src/vogar/Toolchain.java index b19d2cb..1d8189d 100644 --- a/src/vogar/Toolchain.java +++ b/src/vogar/Toolchain.java @@ -19,17 +19,13 @@ package vogar; import vogar.Dexer; public enum Toolchain { - // .dex: desugar + javac + dx - DX, // .dex: desugar + javac + d8 D8, // .class: javac JAVAC; public Dexer getDexer() { - if (this == Toolchain.DX) { - return Dexer.DX; - } else if (this == Toolchain.D8) { + if (this == Toolchain.D8) { return Dexer.D8; } throw new IllegalStateException("No dexer for toolchain " + this); diff --git a/src/vogar/Vogar.java b/src/vogar/Vogar.java index 59a0616..7fba4aa 100644 --- a/src/vogar/Vogar.java +++ b/src/vogar/Vogar.java @@ -221,6 +221,12 @@ public final class Vogar { @Option(names = {"--sdk-version"}) Integer sdkVersion = 28; + @Option(names = {"--serial-dexing"}) + boolean serialDexing = false; + + @Option(names = {"--verbose-dex-stats"}) + boolean verboseDexStats = false; + @VisibleForTesting public Vogar() {} private void printUsage() { @@ -254,7 +260,7 @@ public final class Vogar { System.out.println(" DEFAULT: default (or N/A), X32: 32-bit, X64: 64-bit"); System.out.println(" Default is: " + variant); System.out.println(); - System.out.println(" --toolchain <DX|D8|JAVAC>: Which toolchain to use."); + System.out.println(" --toolchain <D8|JAVAC>: Which toolchain to use."); System.out.println(" Default depends on --mode value (currently " + modeId.defaultToolchain() + " for --mode=" + modeId + ")"); System.out.println(); @@ -327,6 +333,17 @@ public final class Vogar { System.out.println(); System.out.println(" --verbose: turn on persistent verbose output."); System.out.println(); + System.out.println(" --serial-dexing: disallow Vogar spawn multiple simultaneous dex tasks"); + System.out.println(" Enabling this is useful when there is a memory constraint;"); + System.out.println(" and each dex task could easily consume around 1.5G of memory."); + System.out.println(" Default is: " + serialDexing); + System.out.println(); + System.out.println(" --verbose-dex-stats: print verbose stats of used resources by dex tasks"); + System.out.println(" Enabling this wraps each dex task in '/usr/bin/time -v' call"); + System.out.println(" and adds its output to the stdout log. Useful to get a sense of"); + System.out.println(" resource usage such as RSS memory, CPU usage and wall-clock time."); + System.out.println(" Default is: " + verboseDexStats); + System.out.println(); System.out.println(" --check-jni: enable CheckJNI mode."); System.out.println(" See http://developer.android.com/training/articles/perf-jni.html."); System.out.println(" Default is: " + checkJni + ", but disabled for --benchmark."); @@ -666,7 +683,7 @@ public final class Vogar { AndroidSdk androidSdk = null; if (modeId.requiresAndroidSdk()) { androidSdk = AndroidSdk.createAndroidSdk(console, mkdir, modeId, language, - !actionFiles.isEmpty()); + !actionFiles.isEmpty(), serialDexing, verboseDexStats); } if (runnerType == null) { diff --git a/src/vogar/android/AndroidSdk.java b/src/vogar/android/AndroidSdk.java index 15c936d..220e6a6 100644 --- a/src/vogar/android/AndroidSdk.java +++ b/src/vogar/android/AndroidSdk.java @@ -43,12 +43,11 @@ import vogar.util.Strings; /** - * Android SDK commands such as adb, aapt and dx. + * Android SDK commands such as adb, aapt and d8. */ public class AndroidSdk { private static final String D8_COMMAND_NAME = "d8"; - private static final String DX_COMMAND_NAME = "dx"; private static final String ARBITRARY_BUILD_TOOL_NAME = D8_COMMAND_NAME; private final Log log; @@ -58,6 +57,8 @@ public class AndroidSdk { private final String desugarJarPath; private final Md5Cache dexCache; private final Language language; + private final boolean serialDexing; + private final boolean verboseDexStats; public static Collection<File> defaultExpectations() { return Collections.singletonList(new File("libcore/expectations/knownfailures.txt")); @@ -71,7 +72,7 @@ public class AndroidSdk { */ public static AndroidSdk createAndroidSdk( Log log, Mkdir mkdir, ModeId modeId, Language language, - boolean supportBuildFromSource) { + boolean supportBuildFromSource, boolean serialDexing, boolean verboseDexStats) { List<String> path = new Command.Builder(log).args("which", ARBITRARY_BUILD_TOOL_NAME) .permitNonZeroExitStatus(true) .execute(); @@ -99,7 +100,7 @@ public class AndroidSdk { * Android build tree (target): * ${ANDROID_BUILD_TOP}/out/host/linux-x86/bin/aapt * ${ANDROID_BUILD_TOP}/out/host/linux-x86/bin/adb - * ${ANDROID_BUILD_TOP}/out/host/linux-x86/bin/dx + * ${ANDROID_BUILD_TOP}/out/host/linux-x86/bin/d8 * ${ANDROID_BUILD_TOP}/out/host/linux-x86/bin/desugar.jar * ${ANDROID_BUILD_TOP}/out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates * /classes.jar @@ -220,7 +221,7 @@ public class AndroidSdk { } return new AndroidSdk(log, mkdir, compilationClasspath, androidJarPath, desugarJarPath, - new HostFileCache(log, mkdir), language); + new HostFileCache(log, mkdir), language, serialDexing, verboseDexStats); } /** Logs jars that couldn't be found ands suggests a command for building them */ @@ -261,7 +262,8 @@ public class AndroidSdk { @VisibleForTesting AndroidSdk(Log log, Mkdir mkdir, File[] compilationClasspath, String androidJarPath, - String desugarJarPath, HostFileCache hostFileCache, Language language) { + String desugarJarPath, HostFileCache hostFileCache, Language language, + boolean serialDexing, boolean verboseDexStats) { this.log = log; this.mkdir = mkdir; this.compilationClasspath = compilationClasspath; @@ -269,6 +271,8 @@ public class AndroidSdk { this.desugarJarPath = desugarJarPath; this.dexCache = new Md5Cache(log, "dex", hostFileCache); this.language = language; + this.serialDexing = serialDexing; + this.verboseDexStats = verboseDexStats; } // Goes up N levels in the filesystem hierarchy. Return the last file that exists if this goes @@ -374,37 +378,28 @@ public class AndroidSdk { * same package they're testing, even when that's a core * library package. If you're actually just using this tool to * execute arbitrary code, this has the unfortunate - * side-effect of preventing "dx" from protecting you from + * side-effect of preventing "d8" from protecting you from * yourself. - * - * Memory options pulled from build/core/definitions.mk to - * handle large dx input when building dex for APK. */ Command.Builder builder = new Command.Builder(log); + if (verboseDexStats) { + builder.args("/usr/bin/time").args("-v"); + } switch (dexer) { - case DX: - builder.args(DX_COMMAND_NAME); - builder.args("-JXms16M").args("-JXmx1536M"); - builder.args("--min-sdk-version=" + language.getMinApiLevel()); - if (multidex) { - builder.args("--multi-dex"); - } - builder.args("--dex") - .args("--output=" + output) - .args("--core-library") - .args(filePaths); - builder.execute(); - break; case D8: List<String> sanitizedOutputFilePaths; try { - sanitizedOutputFilePaths = removeDexFilesForD8(filePaths); + sanitizedOutputFilePaths = removeDexFilesForD8(filePaths, outputTempDir); } catch (IOException e) { throw new RuntimeException("Error while removing dex files from archive", e); } builder.args(D8_COMMAND_NAME); builder.args("-JXms16M").args("-JXmx1536M"); + builder.args("-JXX:+TieredCompilation").args("-JXX:TieredStopAtLevel=1"); + builder.args("-JDcom.android.tools.r8.emitRecordAnnotationsInDex"); + builder.args("-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex"); + builder.args("--thread-count").args("1"); // d8 will not allow compiling with a single dex file as the target, but if given // a directory name will start its output in classes.dex but may overflow into @@ -473,26 +468,35 @@ public class AndroidSdk { } /** + * Generates a file path for a modified d8 input file. + * @param inputFile the d8 input file. + * @param outputDirectory the directory where the modified file should be written. + * @return the destination for the modified d8 input file. + */ + private static File getModifiedD8Destination(File inputFile, File outputDirectory) { + String name = inputFile.getName(); + int suffixStart = name.lastIndexOf('.'); + if (suffixStart != -1) { + name = name.substring(0, suffixStart); + } + return new File(outputDirectory, name + "-d8.jar"); + } + + /** * Removes DEX files from an archive and preserves the rest. */ - private List<String> removeDexFilesForD8(List<String> fileNames) throws IOException { + private List<String> removeDexFilesForD8(List<String> fileNames, File tempDir) + throws IOException { byte[] buffer = new byte[4096]; List<String> processedFiles = new ArrayList<>(fileNames.size()); for (String inputFileName : fileNames) { - String jarExtension = ".jar"; - String outputFileName; - if (inputFileName.endsWith(jarExtension)) { - outputFileName = - inputFileName.substring(0, inputFileName.length() - jarExtension.length()) - + "-d8" + jarExtension; - } else { - outputFileName = inputFileName + "-d8" + jarExtension; - } + File inputFile = new File(inputFileName); + File outputFile = getModifiedD8Destination(inputFile, tempDir); try (JarOutputStream outputJar = - new JarOutputStream(new FileOutputStream(outputFileName))) { + new JarOutputStream(new FileOutputStream(outputFile))) { copyJarContentExcludingFiles(buffer, inputFileName, outputJar, ".dex"); } - processedFiles.add(outputFileName); + processedFiles.add(outputFile.toString()); } return processedFiles; } diff --git a/src/vogar/android/DeviceRuntime.java b/src/vogar/android/DeviceRuntime.java index 1c85793..2b5f01f 100644 --- a/src/vogar/android/DeviceRuntime.java +++ b/src/vogar/android/DeviceRuntime.java @@ -25,7 +25,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import vogar.Action; -import vogar.Toolchain; import vogar.Variant; import vogar.Classpath; import vogar.Mode; @@ -56,10 +55,18 @@ public final class DeviceRuntime implements Mode { @Override public Set<Task> installTasks() { Set<Task> result = new HashSet<Task>(); + Task lastDexTask = null; // dex everything on the classpath and push it to the device. for (File classpathElement : run.classpath.getElements()) { - addCreateDexJarAndPushTasks(result, run.basenameOfJar(classpathElement), + Task currentDexTask = addCreateDexJarAndPushTasks(result, run.basenameOfJar(classpathElement), classpathElement, null); + // If {@code serialDexing} is enabled, make each subsequent dex task + // depend on previous so any moment of time only one dexer (d8) instance is run + // simultaneously. + if (lastDexTask != null && run.serialDexing) { + currentDexTask.afterSuccess(lastDexTask); + } + lastDexTask = currentDexTask; } return result; } @@ -131,7 +138,7 @@ public final class DeviceRuntime implements Mode { return result; } - private void addCreateDexJarAndPushTasks( + private Task addCreateDexJarAndPushTasks( Set<Task> tasks, String name, File jar, Action action) { File localDex = run.localDexFile(name); File localTempDir = run.localDir(name); @@ -140,6 +147,7 @@ public final class DeviceRuntime implements Mode { localTempDir); tasks.add(createDexJarTask); tasks.add(run.target.pushTask(localDex, deviceDex).afterSuccess(createDexJarTask)); + return createDexJarTask; } private Task newCreateDexJarTask(Classpath classpath, File classpathElement, String name, diff --git a/src/vogar/android/InstallApkTask.java b/src/vogar/android/InstallApkTask.java index a62e85a..7186392 100644 --- a/src/vogar/android/InstallApkTask.java +++ b/src/vogar/android/InstallApkTask.java @@ -47,7 +47,7 @@ public final class InstallApkTask extends Task { // We can't just give dex multiple jars with conflicting class names // With that in mind, the APK packaging strategy is as follows: - // 1. dx to create a dex + // 1. d8 to create a dex // 2. aapt the dex to create apk // 3. sign the apk // 4. install the apk diff --git a/src/vogar/commands/Command.java b/src/vogar/commands/Command.java index 38fdf24..6c5c4b9 100644 --- a/src/vogar/commands/Command.java +++ b/src/vogar/commands/Command.java @@ -131,6 +131,7 @@ public final class Command { int exitValue = process.waitFor(); destroyed = true; if (exitValue != 0 && !permitNonZeroExitStatus) { + outputLines.add("Command exited with code: " + exitValue); throw new CommandFailedException(args, outputLines); } diff --git a/src/vogar/tasks/BuildActionTask.java b/src/vogar/tasks/BuildActionTask.java index fd4c43a..04605fd 100644 --- a/src/vogar/tasks/BuildActionTask.java +++ b/src/vogar/tasks/BuildActionTask.java @@ -17,6 +17,7 @@ package vogar.tasks; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -90,7 +91,14 @@ public final class BuildActionTask extends Task { if (run.debugging) { javac.debug(); } - if (javaFile != null) { + if (javaFile == null) { + if (JAVA_SOURCE_PATTERN.matcher(action.getTargetClass()).find()) { + // This is likely a missing source file rather than a class + // named something.java.... + throw new FileNotFoundException("Unlikely classname, assuming missing source file: " + + action.getTargetClass()); + } + } else { if (!JAVA_SOURCE_PATTERN.matcher(javaFile.toString()).find()) { throw new CommandFailedException(Collections.<String>emptyList(), Collections.singletonList("Cannot compile: " + javaFile)); diff --git a/test/vogar/android/AbstractModeTest.java b/test/vogar/android/AbstractModeTest.java index 225883c..f6f379a 100644 --- a/test/vogar/android/AbstractModeTest.java +++ b/test/vogar/android/AbstractModeTest.java @@ -73,7 +73,7 @@ public abstract class AbstractModeTest { androidSdk = new AndroidSdk(console, mkdir, new File[] {new File("classpath")}, "android.jar", "desugar.jar", new HostFileCache(console, mkdir), - Language.CUR); + Language.CUR, false, false); Target target = createTarget(); final Vogar vogar = new Vogar(); @@ -83,7 +83,7 @@ public abstract class AbstractModeTest { + ". Please check stdout."); } - run = new Run(vogar, Toolchain.DX, console, mkdir, androidSdk, new Rm(console), target, + run = new Run(vogar, Toolchain.D8, console, mkdir, androidSdk, new Rm(console), target, new File("runner/dir")); classpath = new Classpath(); diff --git a/test/vogar/android/HostRuntimeLocalTargetTest.java b/test/vogar/android/HostRuntimeLocalTargetTest.java index 45a147a..a6fbd02 100644 --- a/test/vogar/android/HostRuntimeLocalTargetTest.java +++ b/test/vogar/android/HostRuntimeLocalTargetTest.java @@ -87,11 +87,11 @@ public class HostRuntimeLocalTargetTest extends AbstractModeTest { + " -Xbootclasspath" + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/core-oj-hostdex.jar" + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/core-libart-hostdex.jar" - + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/core-icu4j-hostdex.jar" - + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/conscrypt-hostdex.jar" + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/okhttp-hostdex.jar" + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/bouncycastle-hostdex.jar" + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/apache-xml-hostdex.jar" + + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/core-icu4j-hostdex.jar" + + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/conscrypt-hostdex.jar" + " -Duser.language=en" + " -Duser.region=US" + " -Xcheck:jni" @@ -149,11 +149,11 @@ public class HostRuntimeLocalTargetTest extends AbstractModeTest { + " -Xbootclasspath" + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/core-oj-hostdex.jar" + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/core-libart-hostdex.jar" - + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/core-icu4j-hostdex.jar" - + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/conscrypt-hostdex.jar" + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/okhttp-hostdex.jar" + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/bouncycastle-hostdex.jar" + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/apache-xml-hostdex.jar" + + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/core-icu4j-hostdex.jar" + + ":${ANDROID_BUILD_TOP}/out/host/linux-x86/framework/conscrypt-hostdex.jar" + " -Duser.language=en" + " -Duser.region=US" + " -Xjnigreflimit:2000" diff --git a/test/vogar/target/junit3/TestMethodWithParameterTest.java b/test/vogar/target/junit3/TestMethodWithParameterTest.java index e345e17..28fd255 100644 --- a/test/vogar/target/junit3/TestMethodWithParameterTest.java +++ b/test/vogar/target/junit3/TestMethodWithParameterTest.java @@ -20,7 +20,7 @@ import junit.framework.TestCase; public class TestMethodWithParameterTest extends TestCase { - @SuppressWarnings("unused") + @SuppressWarnings({"unused", "JUnit3TestNotRun"}) public void testParameterized(int i) { } } diff --git a/test/vogar/target/testng/ChangeDefaultLocaleTest.java b/test/vogar/target/testng/ChangeDefaultLocaleTest.java index 1833ff2..1465f33 100644 --- a/test/vogar/target/testng/ChangeDefaultLocaleTest.java +++ b/test/vogar/target/testng/ChangeDefaultLocaleTest.java @@ -20,7 +20,6 @@ import static org.testng.Assert.assertEquals; import java.util.Locale; import org.testng.annotations.Test; -; /** * Verify that the locale is reset to Locale.US before/after each test is run. diff --git a/test/vogar/target/testng/TestNgAnnotationsClass.java b/test/vogar/target/testng/TestNgAnnotationsClass.java new file mode 100644 index 0000000..3a28151 --- /dev/null +++ b/test/vogar/target/testng/TestNgAnnotationsClass.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2022 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 vogar.target.testng; + +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class TestNgAnnotationsClass { + @BeforeClass + public void beforeClass() { + System.out.println("@BeforeClass"); + } + + @AfterClass + public void afterClass() { + System.out.println("@AfterClass"); + } + + @Test + public void test1() { + } + + @Test + public void test2() { + } + + @Test + public void test3() { + } +} diff --git a/test/vogar/target/testng/TestNgAnnotationsMethod.java b/test/vogar/target/testng/TestNgAnnotationsMethod.java new file mode 100644 index 0000000..12840c8 --- /dev/null +++ b/test/vogar/target/testng/TestNgAnnotationsMethod.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2022 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 vogar.target.testng; + +import org.testng.annotations.Test; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.AfterMethod; + +public class TestNgAnnotationsMethod { + @BeforeMethod + public void beforeMethod() { + System.out.println("@BeforeMethod"); + } + + @AfterMethod + public void afterMethod() { + System.out.println("@AfterMethod"); + } + + @Test + public void test1() { + } + + @Test + public void test2() { + } + + @Test + public void test3() { + } +} diff --git a/test/vogar/target/testng/TestRunnerTestNgTest.java b/test/vogar/target/testng/TestRunnerTestNgTest.java index 060244e..c1f1cb1 100644 --- a/test/vogar/target/testng/TestRunnerTestNgTest.java +++ b/test/vogar/target/testng/TestRunnerTestNgTest.java @@ -77,4 +77,66 @@ public class TestRunnerTestNgTest extends AbstractTestRunnerTest { .completedNormally(); } + @TestRunnerProperties(testClass = TestNgAnnotationsMethod.class) + @Test + public void testRunner_TestNgAnnotationsMethod_OneMethod() throws Exception { + String[] args = {"test1"}; + TestRunner runner = testRunnerRule.createTestRunner(args); + runner.run(); + + expectedResults() + .text("@BeforeMethod\n") + .success("test1") + .text("@AfterMethod\n") + .completedNormally(); + } + + @TestRunnerProperties(testClass = TestNgAnnotationsMethod.class) + @Test + public void testRunner_TestNgAnnotationsMethod_AllMethods() throws Exception { + TestRunner runner = testRunnerRule.createTestRunner(); + runner.run(); + + expectedResults() + .text("@BeforeMethod\n") + .success("test1") + .text("@AfterMethod\n") + .text("@BeforeMethod\n") + .success("test2") + .text("@AfterMethod\n") + .text("@BeforeMethod\n") + .success("test3") + .text("@AfterMethod\n") + .completedNormally(); + } + + @TestRunnerProperties(testClass = TestNgAnnotationsClass.class) + @Test + public void testRunner_TestNgAnnotationsClass_OneMethod() throws Exception { + String[] args = {"test1"}; + TestRunner runner = testRunnerRule.createTestRunner(args); + runner.run(); + + expectedResults() + .text("@BeforeClass\n") + .success("test1") + .text("@AfterClass\n") + .completedNormally(); + } + + @TestRunnerProperties(testClass = TestNgAnnotationsClass.class) + @Test + public void testRunner_TestNgAnnotationsClass_AllMethods() throws Exception { + TestRunner runner = testRunnerRule.createTestRunner(); + runner.run(); + + expectedResults() + .text("@BeforeClass\n") + .success("test1") + .success("test2") + .success("test3") + .text("@AfterClass\n") + .completedNormally(); + } + } |