diff options
author | Mohannad Farrag <aymanm@google.com> | 2023-05-18 18:57:07 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-05-18 18:57:07 +0000 |
commit | a8ac0d72e10bf67ae38d690a7f795fbf36a72451 (patch) | |
tree | 82acedeb6a8cb5b06e4494f8a0f1069542c4a8f9 | |
parent | f4180a52f489b04de0043097cf0caf53fdb69690 (diff) | |
parent | 505284a12efc34da51f95d0ca73161701e8e3219 (diff) | |
download | cronet-a8ac0d72e10bf67ae38d690a7f795fbf36a72451.tar.gz |
Redesign ChromiumHostDriven test-runner am: d7049ec002 am: 2c69403ca7 am: 505284a12e
Original change: https://android-review.googlesource.com/c/platform/external/cronet/+/2594327
Change-Id: I79b7839625606f864b79985de34c85036f945876
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
5 files changed, 131 insertions, 113 deletions
diff --git a/test_runner/AndroidNetTest.xml b/test_runner/AndroidNetTest.xml index b54b0870c..5d9822350 100644 --- a/test_runner/AndroidNetTest.xml +++ b/test_runner/AndroidNetTest.xml @@ -26,12 +26,6 @@ <option name="teardown-command" value="setenforce 1" /> <option name="throw-if-cmd-fail" value="true" /> </target_preparer> - <!-- This creates the file which gtest redirects its JSON output to --> - <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> - <option name="run-command" value="touch /data/local/tmp/cronet_test_results_output.json"/> - <option name="teardown-command" value="rm /data/local/tmp/cronet_test_results_output.json"/> - <option name="throw-if-cmd-fail" value="true"/> - </target_preparer> <!-- This creates the file which gtest redirects its stdout output to --> <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> <option name="run-command" value="touch /data/local/tmp/cronet_gtest_output.txt"/> @@ -54,5 +48,6 @@ <option name="jar" value="net_unittests_tester.jar"/> <option name="set-option" value="library-to-load:net_unittests__library"/> <option name="set-option" value="dump-native-coverage:true"/> + <option name="enable-pretty-logs" value="false" /> </test> </configuration>
\ No newline at end of file diff --git a/test_runner/AndroidTest.xml b/test_runner/AndroidTest.xml index a4bd777e4..c3ed8ebb0 100644 --- a/test_runner/AndroidTest.xml +++ b/test_runner/AndroidTest.xml @@ -1,5 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- +<?xml version="1.0" encoding="utf-8"?><!-- ~ Copyright (C) 2023 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,12 +24,6 @@ <option name="teardown-command" value="setenforce 1" /> <option name="throw-if-cmd-fail" value="true" /> </target_preparer> - <!-- This creates the file which gtest redirects its JSON output to --> - <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> - <option name="run-command" value="touch /data/local/tmp/cronet_test_results_output.json"/> - <option name="teardown-command" value="rm /data/local/tmp/cronet_test_results_output.json"/> - <option name="throw-if-cmd-fail" value="true"/> - </target_preparer> <!-- This creates the file which gtest redirects its stdout output to --> <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> <option name="run-command" value="touch /data/local/tmp/cronet_gtest_output.txt"/> @@ -44,8 +37,9 @@ </target_preparer> <!-- Runs the test --> <test class="com.android.tradefed.testtype.HostTest"> - <option name="jar" value="cronet_unittests_tester.jar"/> - <option name="set-option" value="library-to-load:cronet_unittests_android__library"/> - <option name="set-option" value="dump-native-coverage:true"/> + <option name="jar" value="cronet_unittests_tester.jar" /> + <option name="set-option" value="library-to-load:cronet_unittests_android__library" /> + <option name="set-option" value="dump-native-coverage:true" /> + <option name="enable-pretty-logs" value="false" /> </test> </configuration>
\ No newline at end of file diff --git a/test_runner/src/com.android.tests.chromium.host/ChromiumHostDrivenTest.java b/test_runner/src/com.android.tests.chromium.host/ChromiumHostDrivenTest.java index a8bd5f2af..6559dbcbc 100644 --- a/test_runner/src/com.android.tests.chromium.host/ChromiumHostDrivenTest.java +++ b/test_runner/src/com.android.tests.chromium.host/ChromiumHostDrivenTest.java @@ -16,83 +16,55 @@ package com.android.tests.chromium.host; +import static com.android.tests.chromium.host.InstrumentationFlags.COMMAND_LINE_FLAGS_KEY; +import static com.android.tests.chromium.host.InstrumentationFlags.DUMP_COVERAGE_KEY; +import static com.android.tests.chromium.host.InstrumentationFlags.EXTRA_SHARD_NANO_TIMEOUT_KEY; +import static com.android.tests.chromium.host.InstrumentationFlags.LIBRARY_TO_LOAD_ACTIVITY_KEY; +import static com.android.tests.chromium.host.InstrumentationFlags.NATIVE_TEST_ACTIVITY_KEY; +import static com.android.tests.chromium.host.InstrumentationFlags.NATIVE_UNIT_TEST_ACTIVITY_KEY; +import static com.android.tests.chromium.host.InstrumentationFlags.RUN_IN_SUBTHREAD_KEY; +import static com.android.tests.chromium.host.InstrumentationFlags.STDOUT_FILE_KEY; +import static com.android.tests.chromium.host.InstrumentationFlags.TEST_RUNNER; + +import com.android.ddmlib.MultiLineReceiver; import com.android.tradefed.config.Option; import com.android.tradefed.device.CollectingOutputReceiver; import com.android.tradefed.device.DeviceNotAvailableException; -import com.android.tradefed.result.FileInputStreamSource; -import com.android.tradefed.result.LogDataType; -import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; -import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; +import com.android.tradefed.invoker.TestInformation; +import com.android.tradefed.log.LogUtil; +import com.android.tradefed.result.ITestInvocationListener; +import com.android.tradefed.testtype.GTest; +import com.android.tradefed.testtype.GTestListTestParser; +import com.android.tradefed.testtype.GTestResultParser; import com.google.common.base.Strings; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.junit.runner.RunWith; - import java.io.File; -import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; import java.time.Duration; import java.util.concurrent.TimeUnit; -@RunWith(DeviceJUnit4ClassRunner.class) -public class ChromiumHostDrivenTest extends BaseHostJUnit4Test { - private static final String CHROMIUM_PACKAGE = "org.chromium.native_test"; - private static final String NATIVE_TEST_ACTIVITY_KEY = String.format("%s.%s", CHROMIUM_PACKAGE, - "NativeTestInstrumentationTestRunner.NativeTestActivity"); - private static final String RUN_IN_SUBTHREAD_KEY = String.format("%s.%s", CHROMIUM_PACKAGE, - "NativeTest.RunInSubThread"); - private static final String NATIVE_UNIT_TEST_ACTIVITY_KEY = String.format("%s.%s", - CHROMIUM_PACKAGE, - "NativeUnitTestActivity"); - private static final String COMMAND_LINE_FLAGS_KEY = String.format("%s.%s", CHROMIUM_PACKAGE, - "NativeTest.CommandLineFlags"); - private static final String EXTRA_SHARD_NANO_TIMEOUT_KEY = String.format("%s.%s", - CHROMIUM_PACKAGE, - "NativeTestInstrumentationTestRunner.ShardNanoTimeout"); - private static final String DUMP_COVERAGE_KEY = String.format("%s.%s", CHROMIUM_PACKAGE, - "NativeTestInstrumentationTestRunner.DumpCoverage"); - private static final String LIBRARY_TO_LOAD_ACTIVITY_KEY = String.format("%s.%s", - CHROMIUM_PACKAGE, - "NativeTestInstrumentationTestRunner.LibraryUnderTest"); - private static final String STDOUT_FILE_KEY = String.format("%s.%s", CHROMIUM_PACKAGE, - "NativeTestInstrumentationTestRunner.StdoutFile"); - private static final String TEST_RUNNER = String.format("%s/%s", CHROMIUM_PACKAGE, - "org.chromium.build.gtest_apk.NativeTestInstrumentationTestRunner"); - private static Duration testsTimeout = Duration.ofMinutes(15); - // This contains the gtest runner result output. - private static final String GTEST_RESULT_OUTPUT_PATH = - "/data/local/tmp/cronet_test_results_output.json"; +public class ChromiumHostDrivenTest extends GTest { + // This counter is used to retry + private static final int retries = 1; + private static final Duration testsTimeout = Duration.ofMinutes(30); // This contains the gtest logs that is printed to stdout. private static final String GTEST_OUTPUT_PATH = "/data/local/tmp/cronet_gtest_output.txt"; private static final String CLEAR_CLANG_COVERAGE_FILES = "find /data/misc/trace -name '*.profraw' -delete"; - @Rule - public DeviceJUnit4ClassRunner.TestLogData logs = new DeviceJUnit4ClassRunner.TestLogData(); - @Rule - public TemporaryFolder folder = new TemporaryFolder(); @Option( name = "dump-native-coverage", description = "Force APK under test to dump native test coverage upon exit" ) private boolean mCoverage = false; - - @Option( - name = "gtest-filter", - description = "Run only tests specified by the filter" - ) - private String gtestFilter = "*"; // Default to run everything - @Option( name = "library-to-load", description = "Name of the .so file under test" ) - private String libraryToLoad; + private String libraryToLoad = ""; - private String createRunAllTestsCommand() { + private String createRunAllTestsCommand() throws DeviceNotAvailableException { InstrumentationCommandBuilder builder = new InstrumentationCommandBuilder(TEST_RUNNER) .addArgument(NATIVE_TEST_ACTIVITY_KEY, NATIVE_UNIT_TEST_ACTIVITY_KEY) .addArgument(RUN_IN_SUBTHREAD_KEY, "1") @@ -100,62 +72,54 @@ public class ChromiumHostDrivenTest extends BaseHostJUnit4Test { .addArgument(LIBRARY_TO_LOAD_ACTIVITY_KEY, libraryToLoad) .addArgument(STDOUT_FILE_KEY, GTEST_OUTPUT_PATH) .addArgument(COMMAND_LINE_FLAGS_KEY, - String.format("'--gtest_filter=%s --gtest_output=json:%s'", - gtestFilter, ChromiumHostDrivenTest.GTEST_RESULT_OUTPUT_PATH)); + String.format("'%s'", getAllGTestFlags(""))); if (mCoverage) { builder.addArgument(DUMP_COVERAGE_KEY, "true"); } return builder.build(); } - private void logFileFromDevice(String filePath) throws DeviceNotAvailableException { - File file = getDevice().pullFile(filePath); - if (file != null) { - logs.addTestLog(filePath, LogDataType.TEXT, - new FileInputStreamSource(file)); - } - } - - @Before - public void setup() throws DeviceNotAvailableException { - if (mCoverage) { - getDevice().executeShellCommand(CLEAR_CLANG_COVERAGE_FILES); - testsTimeout = Duration.ofMinutes(30); - } + private void printHostLogs(String cmd) { + LogUtil.CLog.i(String.format("[Cronet] Library to be loaded: %s\n", libraryToLoad)); + LogUtil.CLog.i(String.format("[Cronet] Command used to run gtests: adb shell %s\n", cmd)); + LogUtil.CLog.i(String.format("[Cronet] Native-Coverage = %b", mCoverage)); } - @Test - public void testRunChromiumTests() throws Exception { + @Override + public void run(TestInformation testInfo, ITestInvocationListener listener) + throws DeviceNotAvailableException { if (Strings.isNullOrEmpty(libraryToLoad)) { throw new IllegalStateException("No library provided to be loaded."); } String cmd = createRunAllTestsCommand(); - CollectingOutputReceiver outputCollector = new CollectingOutputReceiver(); - getDevice().executeShellCommand(cmd, outputCollector, testsTimeout.toSeconds(), - TimeUnit.SECONDS, 1); - File logFile = folder.newFile(); - try (FileWriter fileWriter = new FileWriter(logFile)) { - fileWriter.write(String.format("Library to be loaded: %s\n", libraryToLoad)); - fileWriter.write(String.format("Command used to run gtests: adb shell %s\n", cmd)); - if (mCoverage) { - fileWriter.write("dump-native-coverage enabled!\n"); - } - fileWriter.write( - String.format("Instrumentation Result: %s", outputCollector.getOutput())); + printHostLogs(cmd); + getDevice().executeShellCommand(CLEAR_CLANG_COVERAGE_FILES); + getDevice().executeShellCommand(cmd, new CollectingOutputReceiver(), + testsTimeout.toMinutes(), TimeUnit.MINUTES, /* retryAttempts */ 1); + try { + parseAndReport(getDevice().pullFile(GTEST_OUTPUT_PATH), listener); + } catch (IOException e) { + throw new FailedReportingException("Failed to parse and report test results", + e.getCause()); + } + } + + private void parseAndReport(File testResultsOutput, ITestInvocationListener listener) + throws IOException { + if (testResultsOutput == null) { + throw new IOException( + String.format("Failed to retrieve %s from device", GTEST_OUTPUT_PATH)); } - logs.addTestLog("cronet_extra_logs", LogDataType.TEXT, - new FileInputStreamSource(logFile)); - logFileFromDevice(GTEST_RESULT_OUTPUT_PATH); - logFileFromDevice(GTEST_OUTPUT_PATH); - // The files are included in the test report generated after executing the tests. - File gtestTestResultsJson = getDevice().pullFile(GTEST_RESULT_OUTPUT_PATH); - GTestsMetaData gTestsMetaData = GTestsMetaData.parseFile(gtestTestResultsJson); - Assert.assertFalse(gTestsMetaData.hasAnyFailures()); - if (!gTestsMetaData.isOutputParsedCorrectly()) { - Assert.fail( - "Failed to parse gtests result. Please check the logcat for more information."); - } else if (gTestsMetaData.getTotalTests() == 0) { - Assert.fail("No Test has been executed."); + // Loading all the lines is fine since this is done on the host-machine. + String[] lines = Files.readAllLines(testResultsOutput.toPath()).toArray(String[]::new); + MultiLineReceiver parser; + // the parser automatically reports the test result back to the infra through the listener. + if (isCollectTestsOnly()) { + parser = new GTestListTestParser(libraryToLoad, listener); + } else { + parser = new GTestResultParser(libraryToLoad, listener); } + parser.processNewLines(lines); + parser.done(); } }
\ No newline at end of file diff --git a/test_runner/src/com.android.tests.chromium.host/FailedReportingException.java b/test_runner/src/com.android.tests.chromium.host/FailedReportingException.java new file mode 100644 index 000000000..f9f0fb319 --- /dev/null +++ b/test_runner/src/com.android.tests.chromium.host/FailedReportingException.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 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.tests.chromium.host; + +public class FailedReportingException extends RuntimeException { + public FailedReportingException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/test_runner/src/com.android.tests.chromium.host/InstrumentationFlags.java b/test_runner/src/com.android.tests.chromium.host/InstrumentationFlags.java new file mode 100644 index 000000000..86d7f3ff6 --- /dev/null +++ b/test_runner/src/com.android.tests.chromium.host/InstrumentationFlags.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2023 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.tests.chromium.host; + +public class InstrumentationFlags { + static final String CHROMIUM_PACKAGE = "org.chromium.native_test"; + static final String NATIVE_TEST_ACTIVITY_KEY = String.format("%s.%s", CHROMIUM_PACKAGE, + "NativeTestInstrumentationTestRunner.NativeTestActivity"); + static final String RUN_IN_SUBTHREAD_KEY = String.format("%s.%s", CHROMIUM_PACKAGE, + "NativeTest.RunInSubThread"); + static final String NATIVE_UNIT_TEST_ACTIVITY_KEY = String.format("%s.%s", + CHROMIUM_PACKAGE, + "NativeUnitTestActivity"); + static final String COMMAND_LINE_FLAGS_KEY = String.format("%s.%s", CHROMIUM_PACKAGE, + "NativeTest.CommandLineFlags"); + static final String EXTRA_SHARD_NANO_TIMEOUT_KEY = String.format("%s.%s", + CHROMIUM_PACKAGE, + "NativeTestInstrumentationTestRunner.ShardNanoTimeout"); + static final String DUMP_COVERAGE_KEY = String.format("%s.%s", CHROMIUM_PACKAGE, + "NativeTestInstrumentationTestRunner.DumpCoverage"); + static final String LIBRARY_TO_LOAD_ACTIVITY_KEY = String.format("%s.%s", + CHROMIUM_PACKAGE, + "NativeTestInstrumentationTestRunner.LibraryUnderTest"); + static final String STDOUT_FILE_KEY = String.format("%s.%s", CHROMIUM_PACKAGE, + "NativeTestInstrumentationTestRunner.StdoutFile"); + static final String TEST_RUNNER = String.format("%s/%s", CHROMIUM_PACKAGE, + "org.chromium.build.gtest_apk.NativeTestInstrumentationTestRunner"); +} |