aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-06-15 21:47:09 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-06-15 21:47:09 +0000
commitb04bfb42b99744eeecad46c0f56e37a01f543edd (patch)
treec17317e718ada6f5cc43e86d859522c5bcda6fd5
parent728069a04599352d12c89c61c91d757c0ffb607c (diff)
parentcf50f7f9bfae65aab4d924d17dec99be5a922999 (diff)
downloadvogar-aml_tz3_314012010.tar.gz
Change-Id: I6963d3f476b26fc8e93c994bbf8ef2c95c39a837
-rw-r--r--Android.mk1
-rw-r--r--OWNERS7
-rw-r--r--src/vogar/ModeId.java16
-rw-r--r--src/vogar/Run.java2
-rw-r--r--src/vogar/RunnerType.java23
-rw-r--r--src/vogar/Vogar.java22
-rw-r--r--src/vogar/android/AndroidSdk.java215
-rw-r--r--src/vogar/android/InstallApkTask.java7
-rw-r--r--src/vogar/commands/Command.java4
-rw-r--r--src/vogar/target/TestRunner.java5
-rw-r--r--src/vogar/target/testng/TestEnvironmentListener.java54
-rw-r--r--src/vogar/target/testng/TestNg.java48
-rw-r--r--src/vogar/target/testng/TestNgAnnotationTransformer.java98
-rw-r--r--src/vogar/target/testng/TestNgListenerAdapter.java72
-rw-r--r--src/vogar/target/testng/TestNgRunnerFactory.java56
-rw-r--r--src/vogar/target/testng/TestNgTargetRunner.java86
-rw-r--r--test/vogar/target/AllTargetTests.java2
-rw-r--r--test/vogar/target/testng/AllTestNgTests.java31
-rw-r--r--test/vogar/target/testng/ChangeDefaultLocaleTest.java43
-rw-r--r--test/vogar/target/testng/SimpleTest.java33
-rw-r--r--test/vogar/target/testng/TestRunnerTestNgTest.java80
21 files changed, 144 insertions, 761 deletions
diff --git a/Android.mk b/Android.mk
index 51e3464..1472829 100644
--- a/Android.mk
+++ b/Android.mk
@@ -33,7 +33,6 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
caliper-gson \
guavalib \
junit \
- testng \
vogar-jsr305 \
vogar-kxml-libcore-20110123
diff --git a/OWNERS b/OWNERS
index 2d36574..2b36b97 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,2 +1,5 @@
-# Bug component: 24949
-include platform/libcore:/OWNERS
+android-libcore-team+review@google.com
+dsrbecky@google.com
+ngeoffray@google.com
+paulduffin@google.com
+rpl@google.com
diff --git a/src/vogar/ModeId.java b/src/vogar/ModeId.java
index c918104..613722a 100644
--- a/src/vogar/ModeId.java
+++ b/src/vogar/ModeId.java
@@ -35,35 +35,31 @@ public enum ModeId {
/**
* $BOOTCLASSPATH for art+libcore only.
* (Intended for use with dalvikvm only.)
+ * See TARGET_TEST_CORE_JARS in android/art/build/Android.common_path.mk
*/
private static final String[] DEVICE_JARS = new String[] {
- // ART module BCP libraries. See CORE_IMG_JARS in art/build/Android.common_path.mk.
"core-oj",
"core-libart",
+ "core-icu4j",
+ "conscrypt",
"okhttp",
"bouncycastle",
"apache-xml",
- // Stubs for dependencies from other APEX modules. If tests require it, this could use
- // platform (xxx.module.platform.api.stubs) or even intra-core
- // (xxx.module.intra.core.api.stubs) API stubs. However it's currently not necessary, so
- // let's stick to public APIs for hygiene.
- "i18n.module.public.api.stubs",
- "conscrypt.module.public.api.stubs",
};
/**
* $BOOTCLASSPATH for art+libcore only (host version).
* (Intended for use with dalvikvm only.)
- * See HOST_TEST_CORE_JARS in art/build/Android.common_path.mk
+ * See HOST_TEST_CORE_JARS in android/art/build/Android.common_path.mk
*/
private static final String[] HOST_JARS = new String[] {
"core-oj-hostdex",
"core-libart-hostdex",
+ "core-icu4j-hostdex",
+ "conscrypt-hostdex",
"okhttp-hostdex",
"bouncycastle-hostdex",
"apache-xml-hostdex",
- "core-icu4j-hostdex",
- "conscrypt-hostdex",
};
/**
diff --git a/src/vogar/Run.java b/src/vogar/Run.java
index ba36594..4a61a76 100644
--- a/src/vogar/Run.java
+++ b/src/vogar/Run.java
@@ -105,7 +105,6 @@ public final class Run {
public final Toolchain toolchain;
public final boolean checkJni;
public final boolean debugging;
- public final Integer sdkVersion;
public Run(Vogar vogar, Toolchain toolchain, Console console, Mkdir mkdir,
AndroidSdk androidSdk, Rm rm, Target target, File runnerDir)
@@ -185,7 +184,6 @@ public final class Run {
this.taskQueue = new TaskQueue(console, maxConcurrentActions);
this.checkJni = vogar.checkJni;
this.debugging = (vogar.debugPort != null) || vogar.debugApp;
- this.sdkVersion = vogar.sdkVersion;
}
private Mode createMode(ModeId modeId, Variant variant) {
diff --git a/src/vogar/RunnerType.java b/src/vogar/RunnerType.java
index 938898a..dfc8c5a 100644
--- a/src/vogar/RunnerType.java
+++ b/src/vogar/RunnerType.java
@@ -21,40 +21,33 @@ package vogar;
*/
public enum RunnerType {
/**
- * Runs JUnit classes, TestNG classes and classes with a main(String[] args) method.
+ * Runs both JUnit classes and classes with a main(String[] args) method.
*/
- DEFAULT(false, true, true, true),
+ DEFAULT(false, true, true),
/**
* Runs only Caliper benchmarks.
*/
- CALIPER(true, false, false, false),
+ CALIPER(true, false, false),
/**
* Runs only JUnit classes.
*/
- JUNIT(false, true, false, false),
+ JUNIT(false, true, false),
/**
* Runs only classes with a main(String[] args) method.
*/
- MAIN(false, false, true, false),
-
- /**
- * Runs only TestNG classes.
- */
- TESTNG(false, false, false, true);
+ MAIN(false, false, true);
private final boolean supportsCaliper;
private final boolean supportsJUnit;
private final boolean supportsMain;
- private final boolean supportsTestNg;
- RunnerType(boolean supportsCaliper, boolean supportsJUnit, boolean supportsMain, boolean supportsTestNg) {
+ RunnerType(boolean supportsCaliper, boolean supportsJUnit, boolean supportsMain) {
this.supportsCaliper = supportsCaliper;
this.supportsJUnit = supportsJUnit;
this.supportsMain = supportsMain;
- this.supportsTestNg = supportsTestNg;
}
public boolean supportsCaliper() {
@@ -68,8 +61,4 @@ public enum RunnerType {
public boolean supportsMain() {
return supportsMain;
}
-
- public boolean supportsTestNg() {
- return supportsTestNg;
- }
}
diff --git a/src/vogar/Vogar.java b/src/vogar/Vogar.java
index 59a0616..a7f3272 100644
--- a/src/vogar/Vogar.java
+++ b/src/vogar/Vogar.java
@@ -40,7 +40,7 @@ import vogar.util.Strings;
* Command line interface for running benchmarks and tests on dalvik.
*/
public final class Vogar {
- static final int LARGE_TIMEOUT_MULTIPLIER = 20;
+ static final int LARGE_TIMEOUT_MULTIPLIER = 10;
public static final int NUM_PROCESSORS = Runtime.getRuntime().availableProcessors();
private final List<File> actionFiles = new ArrayList<File>();
@@ -218,9 +218,6 @@ public final class Vogar {
@Option(names = {"--runner-type"})
RunnerType runnerType;
- @Option(names = {"--sdk-version"})
- Integer sdkVersion = 28;
-
@VisibleForTesting public Vogar() {}
private void printUsage() {
@@ -230,10 +227,10 @@ public final class Vogar {
System.out.println("Usage: Vogar [options]... <actions>... [-- target args]...");
System.out.println();
System.out.println(" <actions>: .java files, directories, or class names.");
- System.out.println(" These should be JUnit tests, TestNG tests, jtreg tests, Caliper benchmarks");
+ System.out.println(" These should be JUnit tests, jtreg tests, Caliper benchmarks");
System.out.println(" or executable Java classes.");
System.out.println();
- System.out.println(" When passing in a JUnit or TestNG test class, it may have \"#method_name\"");
+ System.out.println(" When passing in a JUnit test class, it may have \"#method_name\"");
System.out.println(" appended to it, to specify a single test method.");
System.out.println();
System.out.println(" [target args]: arguments passed to the target process. This is only useful when");
@@ -311,12 +308,11 @@ public final class Vogar {
System.out.println(" --results-dir <directory>: read and write (if --record-results used)");
System.out.println(" results from and to this directory.");
System.out.println();
- System.out.println(" --runner-type <default|caliper|main|junit|testng>: specify which runner to use.");
- System.out.println(" default: runs JUnit tests, TestNG tests and main() classes");
+ System.out.println(" --runner-type <default|caliper|main|junit>: specify which runner to use.");
+ System.out.println(" default: runs both JUnit tests and main() classes");
System.out.println(" caliper: runs Caliper benchmarks only");
System.out.println(" main: runs main() classes only");
System.out.println(" junit: runs JUnit tests only");
- System.out.println(" testng: runs TestNG tests only");
System.out.println(" Default is determined by --benchmark and --testonly, if they are");
System.out.println(" not specified then defaults to: default");
System.out.println();
@@ -407,11 +403,6 @@ public final class Vogar {
System.out.println(" Disable with --no-multidex.");
System.out.println(" Default is: " + multidex);
System.out.println();
- System.out.println(" --sdk-version <argument>: min and target sdk version.");
- System.out.println(" Used in the app manifest for ACTIVITY mode");
- System.out.println(" to prevent warning popups about old applications");
- System.out.println(" Default is: " + sdkVersion);
- System.out.println();
System.out.println(" --dalvik-cache <argument>: override default dalvik-cache location.");
System.out.println(" Default is: " + dalvikCache);
System.out.println();
@@ -665,8 +656,7 @@ public final class Vogar {
AndroidSdk androidSdk = null;
if (modeId.requiresAndroidSdk()) {
- androidSdk = AndroidSdk.createAndroidSdk(console, mkdir, modeId, language,
- !actionFiles.isEmpty());
+ androidSdk = AndroidSdk.createAndroidSdk(console, mkdir, modeId, language);
}
if (runnerType == null) {
diff --git a/src/vogar/android/AndroidSdk.java b/src/vogar/android/AndroidSdk.java
index 15c936d..45f11bb 100644
--- a/src/vogar/android/AndroidSdk.java
+++ b/src/vogar/android/AndroidSdk.java
@@ -70,8 +70,7 @@ public class AndroidSdk {
* compilation class path and android jar path.
*/
public static AndroidSdk createAndroidSdk(
- Log log, Mkdir mkdir, ModeId modeId, Language language,
- boolean supportBuildFromSource) {
+ Log log, Mkdir mkdir, ModeId modeId, Language language) {
List<String> path = new Command.Builder(log).args("which", ARBITRARY_BUILD_TOOL_NAME)
.permitNonZeroExitStatus(true)
.execute();
@@ -176,43 +175,47 @@ public class AndroidSdk {
desugarJarPath = desugarJar.getPath();
- if (!supportBuildFromSource) {
- compilationClasspath = new File[]{};
- } else {
- String pattern = outDir +
- "target/common/obj/JAVA_LIBRARIES/%s_intermediates/classes";
+ String pattern = outDir +
+ "target/common/obj/JAVA_LIBRARIES/%s_intermediates/classes";
+ if (modeId.isHost()) {
+ pattern = outDir + "host/common/obj/JAVA_LIBRARIES/%s_intermediates/classes";
+ }
+ pattern += ".jar";
+
+ String[] jarNames = modeId.getJarNames();
+ compilationClasspath = new File[jarNames.length];
+ for (int i = 0; i < jarNames.length; i++) {
+ String jar = jarNames[i];
+ File file;
if (modeId.isHost()) {
- pattern = outDir + "host/common/obj/JAVA_LIBRARIES/%s_intermediates/classes";
- }
- pattern += ".jar";
-
- String[] jarNames = modeId.getJarNames();
- compilationClasspath = new File[jarNames.length];
- List<String> missingJars = new ArrayList<>();
- for (int i = 0; i < jarNames.length; i++) {
- String jar = jarNames[i];
- File file;
- if (modeId.isHost()) {
- if ("conscrypt-hostdex".equals(jar)) {
- jar = "conscrypt-host-hostdex";
- } else if ("core-icu4j-hostdex".equals(jar)) {
- jar = "core-icu4j-host-hostdex";
- }
- file = new File(String.format(pattern, jar));
+ if ("conscrypt-hostdex".equals(jar)) {
+ jar = "conscrypt-host-hostdex";
+ } else if ("core-icu4j-hostdex".equals(jar)) {
+ jar = "core-icu4j-host-hostdex";
+ }
+ file = new File(String.format(pattern, jar));
+ } else {
+ final String apexPackage;
+ // With unbundled ART, the intermediate directory storing the jar file
+ // outside ART APEX doesn't contain the apex package name.
+ final boolean tryNonApexIntermediate;
+ if ("conscrypt".equals(jar)) {
+ apexPackage = "com.android.conscrypt";
+ tryNonApexIntermediate = true;
+ } else if ("core-icu4j".equals(jar)) {
+ apexPackage = "com.android.i18n";
+ tryNonApexIntermediate = true;
} else {
- file = findApexJar(jar, pattern);
- if (file.exists()) {
- log.verbose("Using jar " + jar + " from " + file);
- } else {
- missingJars.add(jar);
- }
+ apexPackage = "com.android.art.testing";
+ tryNonApexIntermediate = false;
+ }
+
+ file = new File(String.format(pattern, jar + "." + apexPackage));
+ if (tryNonApexIntermediate && !file.exists()) {
+ file = new File(String.format(pattern, jar));
}
- compilationClasspath[i] = file;
- }
- if (!missingJars.isEmpty()) {
- logMissingJars(log, missingJars);
- throw new RuntimeException("Unable to locate all jars needed for compilation");
}
+ compilationClasspath[i] = file;
}
} else {
throw new RuntimeException("Couldn't derive Android home from "
@@ -223,42 +226,6 @@ public class AndroidSdk {
new HostFileCache(log, mkdir), language);
}
- /** Logs jars that couldn't be found ands suggests a command for building them */
- private static void logMissingJars(Log log, List<String> missingJars) {
- StringBuilder makeCommand = new StringBuilder().append("m ");
- for (String jarName : missingJars) {
- String apex = apexForJar(jarName);
- log.warn("Missing compilation jar " + jarName +
- (apex != null ? " from APEX " + apex : ""));
- makeCommand.append(jarName).append(" ");
- }
- log.info("Suggested make command: " + makeCommand);
- }
-
- /** Returns the name of the APEX a particular jar might be located in */
- private static String apexForJar(String jar) {
- if (jar.endsWith(".api.stubs")) {
- return null; // API stubs aren't in any APEX.
- }
- return "com.android.art.testing";
- }
-
- /**
- * Depending on the build setup, jars might be located in the intermediates directory
- * for their APEX or not, so look in both places. Returns the last path searched, so
- * always non-null but possibly non-existent and so the caller should check.
- */
- private static File findApexJar(String jar, String filePattern) {
- String apex = apexForJar(jar);
- if (apex != null) {
- File file = new File(String.format(filePattern, jar + "." + apex));
- if (file.exists()) {
- return file;
- }
- }
- return new File(String.format(filePattern, jar));
- }
-
@VisibleForTesting
AndroidSdk(Log log, Mkdir mkdir, File[] compilationClasspath, String androidJarPath,
String desugarJarPath, HostFileCache hostFileCache, Language language) {
@@ -364,10 +331,9 @@ public class AndroidSdk {
}
}
- List<String> filePaths = new ArrayList<String>();
- for (File file : classpath.getElements()) {
- filePaths.add(file.getPath());
- }
+ // Call desugar first to remove invoke-dynamic LambdaMetaFactory usage,
+ // which ART doesn't support.
+ List<String> desugarOutputFilePaths = desugar(outputTempDir, classpath, dependentCp);
/*
* We pass --core-library so that we can write tests in the
@@ -393,42 +359,26 @@ public class AndroidSdk {
builder.args("--dex")
.args("--output=" + output)
.args("--core-library")
- .args(filePaths);
+ .args(desugarOutputFilePaths);
builder.execute();
break;
case D8:
- List<String> sanitizedOutputFilePaths;
+ List<String> sanitizedDesugarOutputFilePaths;
try {
- sanitizedOutputFilePaths = removeDexFilesForD8(filePaths);
+ sanitizedDesugarOutputFilePaths = removeDexFilesForD8(desugarOutputFilePaths);
} catch (IOException e) {
throw new RuntimeException("Error while removing dex files from archive", e);
}
builder.args(D8_COMMAND_NAME);
builder.args("-JXms16M").args("-JXmx1536M");
-
- // 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
- // multiple dex files. See b/189327238
- String outputPath = output.toString();
- String dexOverflowPath = null;
- if (outputPath.endsWith("/classes.dex")) {
- dexOverflowPath = outputPath.replace("classes.dex", "classes2.dex");
- outputPath = output.getParentFile().toString();
- }
builder
.args("--min-api").args(language.getMinApiLevel())
- .args("--output").args(outputPath)
- .args(sanitizedOutputFilePaths);
+ .args("--output").args(output)
+ .args(sanitizedDesugarOutputFilePaths);
builder.execute();
- if (dexOverflowPath != null && new File(dexOverflowPath).exists()) {
- // If we were expecting a single dex file and d8 overflows into two
- // or more files than fail.
- throw new RuntimeException("Dex file overflow " + dexOverflowPath
- + ", try --multidex");
- }
if (output.toString().endsWith(".jar")) {
try {
- fixD8JarOutput(output, filePaths);
+ fixD8JarOutput(output, desugarOutputFilePaths);
} catch (IOException e) {
throw new RuntimeException("Error while fixing d8 output", e);
}
@@ -473,7 +423,7 @@ public class AndroidSdk {
}
/**
- * Removes DEX files from an archive and preserves the rest.
+ * Removes DEX files from an archive and preserve the rest.
*/
private List<String> removeDexFilesForD8(List<String> fileNames) throws IOException {
byte[] buffer = new byte[4096];
@@ -486,7 +436,7 @@ public class AndroidSdk {
inputFileName.substring(0, inputFileName.length() - jarExtension.length())
+ "-d8" + jarExtension;
} else {
- outputFileName = inputFileName + "-d8" + jarExtension;
+ outputFileName = inputFileName + "-d8" + jarExtension;
}
try (JarOutputStream outputJar =
new JarOutputStream(new FileOutputStream(outputFileName))) {
@@ -531,6 +481,73 @@ public class AndroidSdk {
}
}
+ // Runs desugar on classpath as the input with dependentCp as the classpath_entry.
+ // Returns the generated output list of files.
+ private List<String> desugar(File outputTempDir, Classpath classpath, Classpath dependentCp) {
+ Command.Builder builder = new Command.Builder(log)
+ .args("java", "-jar", desugarJarPath);
+
+ // Ensure that libcore is on the bootclasspath for desugar,
+ // otherwise it tries to use the java command's bootclasspath.
+ for (File f : compilationClasspath) {
+ builder.args("--bootclasspath_entry", f.getPath());
+ }
+
+ // Desugar needs to actively resolve classes that the original inputs
+ // were compiled against. Dx does not; so it doesn't use dependentCp.
+ for (File f : dependentCp.getElements()) {
+ builder.args("--classpath_entry", f.getPath());
+ }
+
+ builder.args("--core_library")
+ .args("--min_sdk_version", language.getMinApiLevel());
+
+ // Build the -i (input) and -o (output) arguments.
+ // Every input from classpath corresponds to a new output temp file into
+ // desugarTempDir.
+ File desugarTempDir;
+ {
+ // Generate a temporary list of files that correspond to the 'classpath';
+ // desugar will then convert the files in 'classpath' into 'desugarClasspath'.
+ if (!outputTempDir.isDirectory()) {
+ throw new AssertionError(
+ "outputTempDir must be a directory: " + outputTempDir.getPath());
+ }
+
+ String desugarTempDirPath = outputTempDir.getPath() + "/desugar";
+ desugarTempDir = new File(desugarTempDirPath);
+ desugarTempDir.mkdirs();
+ if (!desugarTempDir.exists()) {
+ throw new AssertionError(
+ "desugarTempDir; failed to create " + desugarTempDirPath);
+ }
+ }
+
+ // Create unique file names to support non-unique classpath base names.
+ //
+ // For example:
+ //
+ // Classpath("/x/y.jar:/z/y.jar:/a/b.jar") ->
+ // Output Files("${tmp}/0y.jar:${tmp}/1y.jar:${tmp}/2b.jar")
+ int uniqueCounter = 0;
+ List<String> desugarOutputFilePaths = new ArrayList<String>();
+
+ for (File desugarInput : classpath.getElements()) {
+ String tmpName = uniqueCounter + desugarInput.getName();
+ ++uniqueCounter;
+
+ String desugarOutputPath = desugarTempDir.getPath() + "/" + tmpName;
+ desugarOutputFilePaths.add(desugarOutputPath);
+
+ builder.args("-i", desugarInput.getPath())
+ .args("-o", desugarOutputPath);
+ }
+
+ builder.execute();
+
+ return desugarOutputFilePaths;
+ }
+
public void packageApk(File apk, File manifest) {
new Command(log, "aapt",
"package",
diff --git a/src/vogar/android/InstallApkTask.java b/src/vogar/android/InstallApkTask.java
index a62e85a..8e2479d 100644
--- a/src/vogar/android/InstallApkTask.java
+++ b/src/vogar/android/InstallApkTask.java
@@ -83,8 +83,6 @@ public final class InstallApkTask extends Task {
"<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
" package=\"" + packageName(action) + "\">\n" +
" <uses-permission android:name=\"android.permission.INTERNET\" />\n" +
- " <uses-sdk android:minSdkVersion=\"" + run.sdkVersion + "\"\n" +
- " android:targetSdkVersion=\"" + run.sdkVersion + "\" />\n" +
" <application" +
((run.debugging) ? " android:debuggable=\"true\"" : "") + ">\n" +
" <activity android:name=\"" + ACTIVITY_CLASS + "\">\n" +
@@ -116,11 +114,10 @@ public final class InstallApkTask extends Task {
* According to android.content.pm.PackageParser, package name
* "must have at least one '.' separator" Since the qualified name
* may not contain a dot, we prefix containing one to ensure we
- * are compliant. Also transform any hyphens to underscores as they
- * are illegal in package names.
+ * are compliant.
*/
public static String packageName(Action action) {
- return "vogar.test." + action.getName().replaceAll("-", "_");
+ return "vogar.test." + action.getName();
}
private void signApk(File apkUnsigned) {
diff --git a/src/vogar/commands/Command.java b/src/vogar/commands/Command.java
index 38fdf24..60c30b7 100644
--- a/src/vogar/commands/Command.java
+++ b/src/vogar/commands/Command.java
@@ -205,8 +205,8 @@ public final class Command {
log.verbose("sending quit signal to command " + Command.this);
sendQuitSignal(process);
- // hard kill in 1 minute
- timeoutNanoTime = System.nanoTime() + TimeUnit.SECONDS.toNanos(60);
+ // hard kill in 2 seconds
+ timeoutNanoTime = System.nanoTime() + TimeUnit.SECONDS.toNanos(2);
new TimeoutTask() {
@Override protected void onTimeout(Process process) {
log.verbose("killing timed out command " + Command.this);
diff --git a/src/vogar/target/TestRunner.java b/src/vogar/target/TestRunner.java
index 7edc5b5..58137fd 100644
--- a/src/vogar/target/TestRunner.java
+++ b/src/vogar/target/TestRunner.java
@@ -17,6 +17,7 @@
package vogar.target;
import com.google.common.annotations.VisibleForTesting;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
@@ -34,7 +35,6 @@ import vogar.RunnerType;
import vogar.TestProperties;
import vogar.monitor.TargetMonitor;
import vogar.target.junit.JUnitRunnerFactory;
-import vogar.target.testng.TestNgRunnerFactory;
/**
* Runs an action, in process on the target.
@@ -88,9 +88,6 @@ public final class TestRunner {
if (runnerType.supportsMain()) {
runnerFactories.add(new MainRunnerFactory());
}
- if (runnerType.supportsTestNg()) {
- runnerFactories.add(new TestNgRunnerFactory());
- }
runnerFactory = new CompositeRunnerFactory(runnerFactories);
this.monitorPort = monitorPort;
diff --git a/src/vogar/target/testng/TestEnvironmentListener.java b/src/vogar/target/testng/TestEnvironmentListener.java
deleted file mode 100644
index 7ae9088..0000000
--- a/src/vogar/target/testng/TestEnvironmentListener.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.ITestContext;
-import org.testng.ITestListener;
-import org.testng.ITestResult;
-
-import vogar.target.TestEnvironment;
-
-public class TestEnvironmentListener implements ITestListener {
-
- private final TestEnvironment environment;
-
- public TestEnvironmentListener(TestEnvironment environment) {
- this.environment = environment;
- }
-
- @Override
- public void onTestStart(ITestResult result) {
- environment.reset();
- }
-
- @Override
- public void onTestSuccess(ITestResult result) {}
-
- @Override
- public void onTestFailure(ITestResult result) {}
-
- @Override
- public void onTestSkipped(ITestResult result) {}
-
- @Override
- public void onTestFailedButWithinSuccessPercentage(ITestResult result) {}
-
- @Override
- public void onStart(ITestContext context) {}
-
- @Override
- public void onFinish(ITestContext context) {}
-}
diff --git a/src/vogar/target/testng/TestNg.java b/src/vogar/target/testng/TestNg.java
deleted file mode 100644
index f2dbd43..0000000
--- a/src/vogar/target/testng/TestNg.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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 java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-
-public final class TestNg {
- private TestNg() {}
-
- public static boolean isTestNgTest(Class<?> klass) {
- // Classes annotated with @Test
- for (Annotation a : klass.getAnnotations()) {
- Class<?> annotationClass = a.annotationType();
-
- if (org.testng.annotations.Test.class.isAssignableFrom(annotationClass)) {
- return true;
- }
- }
-
- // Methods annotated with @Test
- for (Method m : klass.getMethods()) {
- for (Annotation a : m.getAnnotations()) {
- Class<?> annotationClass = a.annotationType();
-
- if (org.testng.annotations.Test.class.isAssignableFrom(annotationClass)) {
- return true;
- }
- }
- }
-
- return false;
- }
-}
diff --git a/src/vogar/target/testng/TestNgAnnotationTransformer.java b/src/vogar/target/testng/TestNgAnnotationTransformer.java
deleted file mode 100644
index a0e9862..0000000
--- a/src/vogar/target/testng/TestNgAnnotationTransformer.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.IAnnotationTransformer;
-import org.testng.annotations.ITestAnnotation;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.util.HashSet;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * A {@link IAnnotationTransformer} that:
- *
- * <ul>
- * <li>Handles vogar {@code --timeout} option and overrides test run timeout if necessary.
- * <li>Skips past (discards) all tests up to and including one that failed previously causing the
- * process to exit.
- * <p>If {@link #skipReference} has a null value then this lets all tests run. Otherwise, this
- * filters out all tests up to and including the one whose name matches the value in the
- * reference at which point the reference is set to null, so all following tests are kept.
- * This class is a TestNG-version of {@link vogar.target.SkipPastFilter} which handles {@code
- * --skipPast} VM flag the same way.
- * </ul>
- *
- * @see vogar.Vogar
- */
-public class TestNgAnnotationTransformer implements IAnnotationTransformer {
-
- private final long timeoutMillis;
- private final AtomicReference<String> skipReference;
- private final String qualification;
- private final HashSet<String> args;
-
- public TestNgAnnotationTransformer(
- int timeoutSeconds,
- AtomicReference<String> skipReference,
- String qualification,
- String[] vogarArgs) {
- this.timeoutMillis = 1000L * timeoutSeconds;
- this.skipReference = skipReference;
- this.qualification = qualification;
- this.args = new HashSet<>();
- this.args.addAll(List.of(vogarArgs));
- }
-
- @Override
- public void transform(
- ITestAnnotation annotation,
- Class testClass,
- Constructor testConstructor,
- Method testMethod) {
- // Use the least timeout between vogar --timeout and @Test(timeout = N) annotation.
- if (timeoutMillis > 0) {
- long testTimeout = annotation.getTimeOut();
- if (testTimeout > timeoutMillis) {
- annotation.setTimeOut(timeoutMillis);
- }
- }
-
- // Skip up to and including given test name if --skipPast provided.
- final String skipPast = skipReference.get();
- if (skipPast != null && testClass == null && testMethod != null) {
- String name = testMethod.getName();
- if (skipPast.equals(name)) {
- skipReference.set(null);
- }
- annotation.setEnabled(false);
- }
-
- // Disable all but specified tests if qualified test name provided (package.class#method).
- if (qualification != null && testMethod != null) {
- if (!qualification.equals(testMethod.getName())) {
- annotation.setEnabled(false);
- }
- }
- if (!args.isEmpty() && testMethod != null) {
- if (!args.contains(testMethod.getName())) {
- annotation.setEnabled(false);
- }
- }
- }
-}
diff --git a/src/vogar/target/testng/TestNgListenerAdapter.java b/src/vogar/target/testng/TestNgListenerAdapter.java
deleted file mode 100644
index 6f02c20..0000000
--- a/src/vogar/target/testng/TestNgListenerAdapter.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.ITestContext;
-import org.testng.ITestListener;
-import org.testng.ITestResult;
-
-import vogar.Result;
-import vogar.monitor.TargetMonitor;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-
-public class TestNgListenerAdapter implements ITestListener {
-
- private final TargetMonitor monitor;
-
- public TestNgListenerAdapter(TargetMonitor monitor) {
- this.monitor = monitor;
- }
-
- @Override
- public void onTestStart(ITestResult result) {
- StringBuilder sb = new StringBuilder();
- sb.append(result.getTestClass().getName());
- if (result.getName() != null) {
- sb.append('#').append(result.getName());
- }
- monitor.outcomeStarted(sb.toString());
- }
-
- @Override
- public void onTestSuccess(ITestResult result) {
- monitor.outcomeFinished(Result.SUCCESS);
- }
-
- @Override
- public void onTestFailure(ITestResult result) {
- Throwable thrown = result.getThrowable();
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- PrintStream stackTrace = new PrintStream(out);
- thrown.printStackTrace(stackTrace);
- monitor.output(out.toString());
- monitor.outcomeFinished(Result.ERROR);
- }
-
- @Override
- public void onTestSkipped(ITestResult result) {}
-
- @Override
- public void onTestFailedButWithinSuccessPercentage(ITestResult result) {}
-
- @Override
- public void onStart(ITestContext context) {}
-
- @Override
- public void onFinish(ITestContext context) {}
-}
diff --git a/src/vogar/target/testng/TestNgRunnerFactory.java b/src/vogar/target/testng/TestNgRunnerFactory.java
deleted file mode 100644
index 2e214fd..0000000
--- a/src/vogar/target/testng/TestNgRunnerFactory.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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 vogar.monitor.TargetMonitor;
-import vogar.target.RunnerFactory;
-import vogar.target.TargetRunner;
-import vogar.target.TestEnvironment;
-
-import java.util.concurrent.atomic.AtomicReference;
-
-import javax.annotation.Nullable;
-
-public class TestNgRunnerFactory implements RunnerFactory {
-
- @Nullable
- @Override
- public TargetRunner newRunner(
- TargetMonitor monitor,
- String qualification,
- Class<?> klass,
- AtomicReference<String> skipPastReference,
- TestEnvironment testEnvironment,
- int timeoutSeconds,
- String[] args) {
- if (supports(klass)) {
- return new TestNgTargetRunner(
- monitor,
- skipPastReference,
- testEnvironment,
- timeoutSeconds,
- klass,
- qualification,
- args);
- } else {
- return null;
- }
- }
-
- private static boolean supports(Class<?> klass) {
- return TestNg.isTestNgTest(klass);
- }
-}
diff --git a/src/vogar/target/testng/TestNgTargetRunner.java b/src/vogar/target/testng/TestNgTargetRunner.java
deleted file mode 100644
index 6b10509..0000000
--- a/src/vogar/target/testng/TestNgTargetRunner.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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.TestNG;
-
-import vogar.monitor.TargetMonitor;
-import vogar.target.TargetRunner;
-import vogar.target.TestEnvironment;
-
-import java.util.concurrent.atomic.AtomicReference;
-
-public class TestNgTargetRunner implements TargetRunner {
-
- private final TargetMonitor monitor;
- private final Class<?> testClass;
- private final TestEnvironment testEnvironment;
- private final String qualification;
- private final TestNgAnnotationTransformer transformer;
- private final String[] args;
-
- public TestNgTargetRunner(
- TargetMonitor monitor,
- AtomicReference<String> skipPastReference,
- TestEnvironment testEnvironment,
- int timeoutSeconds,
- Class<?> testClass,
- String qualification,
- String[] args) {
- this.monitor = monitor;
- this.testClass = testClass;
- this.testEnvironment = testEnvironment;
- this.qualification = qualification;
- this.args = args;
- this.transformer =
- new TestNgAnnotationTransformer(
- timeoutSeconds, skipPastReference, qualification, args);
- }
-
- @Override
- public boolean run() {
- // Set up TestNg core infrastructure.
- TestNG testng = new TestNG(false);
-
- // This transformer handles test timeout and overrides it if vogar was run
- // with specific timeout parameter (see --timeout option).
- testng.setAnnotationTransformer(transformer);
-
- // Disable parallel execution of tests using @DataProvider's.
- // If parallel execution is enabled with @DataProvider(..., parallel = true) then it
- // would break vogar.monitor.HostMonitor#followProcess protocol which relies on receiving
- // control messages in specific order. It expects "{outcome: ...}" json-object
- // followed by another "{result: ...}" json-object for each test run; whereas with parallel
- // execution enabled for @DataProvider, HostMonitor#followProcess would receive all
- // "outcome" objects, and then all "result" objects, in random order.
- // The easiest way of preventing this behavior would be to disable parallel execution
- // for data providers.
- testng.setDataProviderThreadCount(1);
-
- // Make TestNG less noisy.
- testng.setVerbose(0);
- // Proxy to pass TestNg test lifecycle calls to vogar.
- TestNgListenerAdapter adapter = new TestNgListenerAdapter(monitor);
- testng.addListener(adapter);
- // Listener that resets environment for each test.
- testng.addListener(new TestEnvironmentListener(testEnvironment));
-
- testng.setTestClasses(new Class[] {testClass});
-
- testng.run();
- return true;
- }
-}
diff --git a/test/vogar/target/AllTargetTests.java b/test/vogar/target/AllTargetTests.java
index e687c1b..113cb72 100644
--- a/test/vogar/target/AllTargetTests.java
+++ b/test/vogar/target/AllTargetTests.java
@@ -22,7 +22,6 @@ import org.junit.runners.Suite.SuiteClasses;
import vogar.target.caliper.AllCaliperTests;
import vogar.target.junit.AllJUnitTests;
import vogar.target.main.AllMainTests;
-import vogar.target.testng.AllTestNgTests;
/**
* Run the tests in this package.
@@ -33,7 +32,6 @@ import vogar.target.testng.AllTestNgTests;
AllCaliperTests.class,
AllJUnitTests.class,
AllMainTests.class,
- AllTestNgTests.class,
})
@RunWith(Suite.class)
public class AllTargetTests {
diff --git a/test/vogar/target/testng/AllTestNgTests.java b/test/vogar/target/testng/AllTestNgTests.java
deleted file mode 100644
index 70caab9..0000000
--- a/test/vogar/target/testng/AllTestNgTests.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.junit.runner.RunWith;
-import org.junit.runners.Suite;
-import org.junit.runners.Suite.SuiteClasses;
-
-/**
- * Run the tests in this package.
- */
-@SuiteClasses({
- TestRunnerTestNgTest.class,
-})
-@RunWith(Suite.class)
-public class AllTestNgTests {
-}
diff --git a/test/vogar/target/testng/ChangeDefaultLocaleTest.java b/test/vogar/target/testng/ChangeDefaultLocaleTest.java
deleted file mode 100644
index 1833ff2..0000000
--- a/test/vogar/target/testng/ChangeDefaultLocaleTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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 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.
- *
- * <p>This ensures that the {@link vogar.target.TestEnvironment} class is used correctly.
- */
-public class ChangeDefaultLocaleTest {
-
- @Test
- public void testDefault_Locale_CANADA() {
- assertEquals(Locale.getDefault(), Locale.US);
- Locale.setDefault(Locale.CANADA);
- }
-
- @Test
- public void testDefault_Locale_CHINA() {
- assertEquals(Locale.getDefault(), Locale.US);
- Locale.setDefault(Locale.CHINA);
- }
-}
diff --git a/test/vogar/target/testng/SimpleTest.java b/test/vogar/target/testng/SimpleTest.java
deleted file mode 100644
index ab9603c..0000000
--- a/test/vogar/target/testng/SimpleTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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;
-
-public class SimpleTest {
- @Test
- public void simple1() {
- }
-
- @Test
- public void simple2() {
- }
-
- @Test
- public void Simple3() {
- }
-}
diff --git a/test/vogar/target/testng/TestRunnerTestNgTest.java b/test/vogar/target/testng/TestRunnerTestNgTest.java
deleted file mode 100644
index 060244e..0000000
--- a/test/vogar/target/testng/TestRunnerTestNgTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-import vogar.target.AbstractTestRunnerTest;
-import vogar.target.TestRunner;
-import vogar.target.TestRunnerProperties;
-
-/**
- * Tests for using TestRunner to run TestNG classes.
- */
-@RunWith(JUnit4.class)
-public class TestRunnerTestNgTest extends AbstractTestRunnerTest {
-
- @TestRunnerProperties(testClass = ChangeDefaultLocaleTest.class)
- @Test
- public void testRunner_ChangeDefaultLocaleTest() throws Exception {
- TestRunner runner = testRunnerRule.createTestRunner();
- runner.run();
-
- expectedResults()
- .success("testDefault_Locale_CANADA")
- .success("testDefault_Locale_CHINA")
- .completedNormally();
- }
-
- @TestRunnerProperties(testClass = SimpleTest.class)
- @Test
- public void testRunner_SkipPastAll() throws Exception {
- Class<?> testClass = testRunnerRule.testClass();
- String failingTestName = testClass.getName() + "#other";
- TestRunner runner = testRunnerRule.createTestRunner("--skipPast", failingTestName);
-
- runner.run();
- expectedResults().completedNormally();
- }
-
- @TestRunnerProperties(testClass = SimpleTest.class)
- @Test
- public void testRunner_SimpleTest2_OneMethod() throws Exception {
- String[] args = {"simple2"};
- TestRunner runner = testRunnerRule.createTestRunner(args);
- runner.run();
-
- expectedResults()
- .success("simple2")
- .completedNormally();
- }
-
- @TestRunnerProperties(testClass = SimpleTest.class)
- @Test
- public void testRunner_SimpleTest2_TwoMethod() throws Exception {
- String[] args = {"simple1", "Simple3"};
- TestRunner runner = testRunnerRule.createTestRunner(args);
- runner.run();
-
- expectedResults()
- .success("Simple3")
- .success("simple1")
- .completedNormally();
- }
-
-}