Skip to content
This repository has been archived by the owner on Nov 29, 2022. It is now read-only.

Notes #1

Open
bootstraponline opened this issue Sep 10, 2021 · 5 comments
Open

Notes #1

bootstraponline opened this issue Sep 10, 2021 · 5 comments

Comments

@bootstraponline
Copy link

bootstraponline commented Sep 10, 2021

UTP shipping in Android Studio.

  • Understand UTP architecture
  • Build UTP
  • Run test with UTP successfully
  • Refactor/extract UTP for stand alone client

gradlew
-Pandroid.experimental.androidTest.useUnifiedTestPlatform=true
device-nameBuildVariantAndroidTest

image

https://developer.android.com/studio/preview/features/

Android studio ships with utp.jar that defines 5 files

  1. TaskOutputProcessorListener.java
  2. TaskOutputProcessor.java
  3. GradleAndroidProjectResolverExtension.java
  4. TaskOutputLineProcessor.java
  5. TaskOutputProcessorKt.java

Clone repo and checkout the mirror-goog-studio-main branch. Use bfg to remove files larger than the GitHub 100MB limit. Run bfg twice to remove all files.

$ git clone https://android.googlesource.com/platform/tools/base
$ git checkout mirror-goog-studio-main
$ rm profiler/native/trace_processor_daemon/testdata/tank.trace
$ git add profiler/native/trace_processor_daemon/testdata/tank.trac
$ git commit -m "remove file"
$ wget https://repo1.maven.org/maven2/com/madgag/bfg/1.14.0/bfg-1.14.0.jar
$ java -jar bfg-1.14.0.jar --strip-blobs-bigger-than 50M 
$ git reflog expire --expire=now --all && git gc --prune=now --aggressive
$ git push --set-upstream origin mirror-goog-studio-main

prebuilt jars

        "//prebuilts/tools/common/m2/repository/com/google/testing/platform/android-device-provider-gradle/0.0.8-alpha02:jar",
        "//prebuilts/tools/common/m2/repository/com/google/testing/platform/android-device-provider-local/0.0.8-alpha02:jar",
        "//prebuilts/tools/common/m2/repository/com/google/testing/platform/android-driver-instrumentation/0.0.8-alpha02:jar",
        "//prebuilts/tools/common/m2/repository/com/google/testing/platform/android-test-plugin-host-device-info/0.0.8-alpha02:jar",
        "//prebuilts/tools/common/m2/repository/com/google/testing/platform/android-test-plugin-host-retention/0.0.8-alpha02:jar",
        "//prebuilts/tools/common/m2/repository/com/google/testing/platform/android-test-plugin/0.0.8-alpha02:jar",
        "//prebuilts/tools/common/m2/repository/com/google/testing/platform/core-proto/0.0.8-alpha02:jar",
        "//prebuilts/tools/common/m2/repository/com/google/testing/platform/core/0.0.8-alpha02:jar",
        "//prebuilts/tools/common/m2/repository/com/google/testing/platform/launcher/0.0.8-alpha02:jar",

Mirror

git clone --mirror https://android.googlesource.com/platform/tools/base

git remote update

git push --mirror [email protected]:Flank/mirror-goog-studio-main.git
@bootstraponline
Copy link
Author

@bootstraponline
Copy link
Author

/**
 * A work action that runs UTP in an external java process.
 */
abstract class RunUtpWorkAction : WorkAction<RunUtpWorkParameters> {

    private val logger = Logging.getLogger(RunUtpWorkAction::class.java)

    @get:Inject
    abstract val execOperations: ExecOperations

    override fun execute() {
        val javaProcessExecutor = GradleJavaProcessExecutor {
            execOperations.javaexec(it)
        }
        val javaProcessInfo = ProcessInfoBuilder().apply {
            setClasspath(parameters.launcherJar.asFile.get().absolutePath)
            setMain(UtpDependency.LAUNCHER.mainClass)
            addArgs(parameters.coreJar.asFile.get().absolutePath)
            addArgs("--proto_config=${parameters.runnerConfig.asFile.get().absolutePath}")
            addArgs("--proto_server_config=${parameters.serverConfig.asFile.get().absolutePath}")
            addJvmArg("-Djava.util.logging.config.file=${
                parameters.loggingProperties.asFile.get().absolutePath}")
        }.createJavaProcess()

        javaProcessExecutor.execute(
            javaProcessInfo,
            LoggedProcessOutputHandler(LoggerWrapper(logger))).apply {
            rethrowFailure()
        }
    }

@bootstraponline
Copy link
Author

    // A UTP launcher jar file to run.
    val launcherJar: RegularFileProperty

    // A UTP core jar file.
    val coreJar: RegularFileProperty

    // A UTP runner config binary proto file to be passed into the launcher.
    val runnerConfig: RegularFileProperty

    // A UTP server config binary proto file to be passed into the launcher.
    val serverConfig: RegularFileProperty

    // A Java logging properties file to be loaded to run a UTP java process.
    val loggingProperties: RegularFileProperty

https://github.com/Flank/mirror-goog-studio-main/blob/ca80154e35b80e5c6757e6575a3e6157ca959c8a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/testing/utp/worker/RunUtpWorkParameters.kt

@bootstraponline
Copy link
Author

bootstraponline commented Sep 12, 2021

https://github.com/Flank/mirror-goog-studio-main/blob/mirror-goog-studio-main/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/testing/utp/UtpTestRunner.kt

/*
 * Runs Android Instrumentation tests using UTP (Unified Test Platform).
 */
class UtpTestRunner @JvmOverloads constructor(
        splitSelectExec: File?,
        processExecutor: ProcessExecutor,
        private val workerExecutor: WorkerExecutor,
        executor: ExecutorServiceAdapter,
        private val utpDependencies: UtpDependencies,
        private val versionedSdkLoader: SdkComponentsBuildService.VersionedSdkLoader,
        private val retentionConfig: RetentionConfig,
        private val useOrchestrator: Boolean,
        private val uninstallIncompatibleApks: Boolean,
        private val utpTestResultListener: UtpTestResultListener?,
        private val configFactory: UtpConfigFactory = UtpConfigFactory(),
        private val runUtpTestSuiteAndWaitFunc: (
            List<UtpRunnerConfig>, String, String, File, ILogger
        ) -> List<Boolean> = { runnerConfigs, projectName, variantName, resultsDir, logger ->
            runUtpTestSuiteAndWait(
                runnerConfigs, workerExecutor, projectName, variantName, resultsDir, logger,
                utpTestResultListener, utpDependencies)
        }
)

@bootstraponline
Copy link
Author

bootstraponline commented Sep 12, 2021

 TestRunner createTestRunner(
                WorkerExecutor workerExecutor,
                ExecutorServiceAdapter executorServiceAdapter,
                @Nullable UtpTestResultListener utpTestResultListener) {
            GradleProcessExecutor gradleProcessExecutor =
                    new GradleProcessExecutor(getExecOperations()::exec);

            if (getUnifiedTestPlatform().get()) {
                boolean useOrchestrator =
                        (getExecutionEnum().get() == ANDROID_TEST_ORCHESTRATOR
                                || getExecutionEnum().get() == ANDROIDX_TEST_ORCHESTRATOR);
                return new UtpTestRunner(
                        getBuildTools().splitSelectExecutable().getOrNull(),
                        gradleProcessExecutor,
                        workerExecutor,
                        executorServiceAdapter,
                        getUtpDependencies(),
                        getSdkBuildService()
                                .get()
                                .sdkLoader(
                                        getBuildTools().getCompileSdkVersion(),
                                        getBuildTools().getBuildToolsRevision()),
                        getRetentionConfig().get(),
                        useOrchestrator,
                        getUninstallIncompatibleApks().get(),
                        utpTestResultListener);
            } else {
                switch (getExecutionEnum().get()) {
                    case ANDROID_TEST_ORCHESTRATOR:
                    case ANDROIDX_TEST_ORCHESTRATOR:
                        Preconditions.checkArgument(
                                !getShardBetweenDevices().get(),
                                "Sharding is not supported with Android Test Orchestrator.");

                        return new OnDeviceOrchestratorTestRunner(
                                getBuildTools().splitSelectExecutable().getOrNull(),
                                gradleProcessExecutor,
                                getExecutionEnum().get(),
                                executorServiceAdapter);
                    case HOST:
                        if (getShardBetweenDevices().get()) {

                            return new ShardedTestRunner(
                                    getBuildTools().splitSelectExecutable().getOrNull(),
                                    gradleProcessExecutor,
                                    getNumShards().getOrNull(),
                                    executorServiceAdapter);
                        } else {

                            return new SimpleTestRunner(
                                    getBuildTools().splitSelectExecutable().getOrNull(),
                                    gradleProcessExecutor,
                                    executorServiceAdapter);
                        }
                    default:
                        throw new AssertionError("Unknown value " + getExecutionEnum().get());
                }
            }
        }
    }

https://github.com/Flank/mirror-goog-studio-main/blob/ca80154e35b80e5c6757e6575a3e6157ca959c8a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/DeviceProviderInstrumentTestTask.java

bootstraponline pushed a commit that referenced this issue Apr 21, 2022
This CL fixes two problems in the lint test infrastructure:

(1) expectInlinedMessages wasn't working right, and was in fact
    not actually checking anything for tests with source
    transforming test modes enabled (which is the default).

(2) Only two of the expect-methods on TestLintResult was looking
    rethrowing exceptions encountered during the lint analysis;
    this CL makes them all do that

(3) When I fixed #1 above a couple of inline-message tests
    failed because they hadn't been kept up to date; for the
    range test, the error messages in the detector were updated
    and the tests need to be adjusted; for the allocation detector
    the fully qualified test mode check actually revealed a bug
    in the detector: exceptions thrown by fully qualified names
    would be flagged as an allocation. This CL fixes these.

Test: Existing and updated unit tests
Bug: None
Change-Id: I43b1693b9e4fb287900e5703fb8bc94dfe7917e1
bootstraponline pushed a commit that referenced this issue Apr 21, 2022
The assumption here is that formc does not generate any new APIs that
would be referenced by downstream Java/Kotlin code. Thus we do not
need to include formc output in ijars.

The benefit of this is that we can produce 'full_ijar' without needing
to wait for the formc action to complete. By producing 'full_ijar'
earlier, we can begin downstream module compilations sooner, thereby
reducing the critical path slightly.

Also, note that formc takes as input the "full" Java jar. So, by
moving formc off the critical path, we no longer need to wait for
the full Javac action either; instead we only need the hjar, which is
produced very quickly by Turbine.

Test scenario: add a new public Java method in android-common, then
build //tools/adt/idea/android/...

Results:

  Before this change:
    trial #1: 338 seconds
    trial #2: 323 seconds
    trial #3: 333 seconds

  After this change:
    trial #1: 316 seconds
    trial #2: 308 seconds
    trial #3: 305 seconds

The improvement is relatively small in practice, it seems. But I did
observe that compilation of downstream modules now starts in parallel
with the "*.pjava.jar" and "*.java.jar" actions, which is good.

Bug: relates to b/200690965
Test: Bazel build
Change-Id: I3051c2328bebacf2f1c3de9af9950c4577388e0b
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant