Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for android-test projects for NiA benchmarks #132

Merged
merged 1 commit into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ gradlePlugin {
implementationClass = "org.gradle.api.experimental.android.application.StandaloneAndroidApplicationPlugin"
tags = setOf("declarative-gradle", "android")
}
create("android-test") {
id = "org.gradle.experimental.android-test"
displayName = "Android Test Experimental Declarative Plugin"
description = "Experimental declarative plugin for Android test projects"
implementationClass = "org.gradle.api.experimental.android.application.StandaloneAndroidTestPlugin"
tags = setOf("declarative-gradle", "android")
}
create("android-ecosystem") {
id = "org.gradle.experimental.android-ecosystem"
displayName = "Android Ecosystem Experimental Declarative Plugin"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package org.gradle.api.experimental.android;

import androidx.baselineprofile.gradle.consumer.BaselineProfileConsumerExtension;
import androidx.baselineprofile.gradle.producer.BaselineProfileProducerExtension;
import androidx.room.gradle.RoomExtension;
import com.android.build.api.dsl.BuildType;
import com.android.build.api.dsl.CommonExtension;
import com.android.build.api.dsl.ManagedVirtualDevice;
import com.android.build.api.dsl.UnitTestOptions;
import com.google.android.libraries.mapsplatform.secrets_gradle_plugin.SecretsPluginExtension;
import com.google.devtools.ksp.gradle.KspExtension;
Expand All @@ -12,7 +14,6 @@
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.experimental.android.extensions.BaselineProfile;
import org.gradle.api.experimental.android.extensions.testing.AndroidTestDependencies;
import org.gradle.api.experimental.android.extensions.testing.TestOptions;
import org.gradle.api.experimental.android.extensions.testing.Testing;
Expand All @@ -22,9 +23,11 @@

import static org.gradle.api.experimental.android.AndroidSupport.ifPresent;
import static org.gradle.api.experimental.android.extensions.ComposeSupport.configureCompose;
import static org.gradle.api.experimental.android.nia.NiaSupport.configureBaselineProfile;

@SuppressWarnings("UnstableApiUsage")
public abstract class AbstractAndroidSoftwarePlugin implements Plugin<Project> {
protected static final int DEFAULT_MIN_ANDROID_SDK = 21;
public static final int DEFAULT_MIN_ANDROID_SDK = 21;

protected abstract AndroidSoftware getAndroidSoftware();

Expand Down Expand Up @@ -64,6 +67,7 @@ public void apply(Project project) {
dslModel.getRoom().getVersion().convention("2.6.1");
dslModel.getLicenses().getEnabled().convention(false);
dslModel.getBaselineProfile().getEnabled().convention(false);
dslModel.getBaselineProfile().getUseConnectedDevices().convention(true);
dslModel.getSecrets().getEnabled().convention(false);

// Setup Test Options conventions
Expand Down Expand Up @@ -112,6 +116,9 @@ protected void linkDslModelToPlugin(Project project, AndroidSoftware dslModel, C
android.getCompileOptions().setSourceCompatibility(JavaVersion.toVersion(jdkVersion));
android.getCompileOptions().setTargetCompatibility(JavaVersion.toVersion(jdkVersion));
});
dslModel.getExperimentalProperties().forEach(property -> {
android.getExperimentalProperties().put(property.getName(), property.getValue());
});

// Link build types
AndroidSoftwareBuildTypes modelBuildType = dslModel.getBuildTypes();
Expand All @@ -129,8 +136,9 @@ protected void linkDslModelToPlugin(Project project, AndroidSoftware dslModel, C
configureLicenses(project, dslModel);

if (project.getExtensions().findByName("baselineProfile") != null) {
BaselineProfileConsumerExtension baselineProfileExtension = project.getExtensions().getByType(BaselineProfileConsumerExtension.class);
configureBaselineProfile(project, dslModel.getBaselineProfile(), baselineProfileExtension);
BaselineProfileProducerExtension baselineProfileProducerExtension = project.getExtensions().getByType(BaselineProfileProducerExtension.class);
BaselineProfileConsumerExtension baselineProfileConsumerExtension = project.getExtensions().getByType(BaselineProfileConsumerExtension.class);
configureBaselineProfile(project, dslModel.getBaselineProfile(), baselineProfileProducerExtension, baselineProfileConsumerExtension);
}

configureSecrets(project, dslModel);
Expand Down Expand Up @@ -211,6 +219,12 @@ protected void configureTesting(Project project, AndroidSoftware dslModel, Commo

TestOptions testOptions = testing.getTestOptions();
ifPresent(testOptions.getTestInstrumentationRunner(), android.getDefaultConfig()::setTestInstrumentationRunner);
testOptions.getManagedDevices().forEach(device -> {
ManagedVirtualDevice managedVirtualDevice = android.getTestOptions().getManagedDevices().getDevices().create(device.getName(), ManagedVirtualDevice.class);
ifPresent(device.getDevice(), managedVirtualDevice::setDevice);
ifPresent(device.getApiLevel(), managedVirtualDevice::setApiLevel);
ifPresent(device.getSystemImageSource(), managedVirtualDevice::setSystemImageSource);
});

UnitTestOptions unitTestOptions = android.getTestOptions().getUnitTests();
unitTestOptions.setIncludeAndroidResources(testOptions.getIncludeAndroidResources().get());
Expand Down Expand Up @@ -245,17 +259,6 @@ protected void configureKotlinSerialization(Project project, AndroidSoftware dsl
}
}

@SuppressWarnings("UnstableApiUsage")
private static void configureBaselineProfile(Project project, BaselineProfile baselineProfile, BaselineProfileConsumerExtension baselineProfileExtension) {
if (baselineProfile.getEnabled().get()) {
project.getPlugins().apply("androidx.baselineprofile");

baselineProfileExtension.setAutomaticGenerationDuringBuild(baselineProfile.getAutomaticGenerationDuringBuild().get());

project.getConfigurations().getByName("baselineProfile").fromDependencyCollector(baselineProfile.getDependencies().getProfile());
}
}

/**
* Links build types from the model to the android extension.
*/
Expand All @@ -270,11 +273,6 @@ protected void linkBuildType(Project project, BuildType buildType, AndroidSoftwa
model.getProguardFiles().get().forEach(proguardFile -> {
buildType.proguardFile(proguardFile.getName().get());
});

if (buildType.getExtensions().findByName("baselineProfile") != null) {
BaselineProfileConsumerExtension baselineProfileExtension = buildType.getExtensions().getByType(BaselineProfileConsumerExtension.class);
configureBaselineProfile(project, model.getBaselineProfile(), baselineProfileExtension);
}
}

@SuppressWarnings("UnstableApiUsage")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.gradle.api.Plugin;
import org.gradle.api.experimental.android.application.StandaloneAndroidApplicationPlugin;
import org.gradle.api.experimental.android.library.StandaloneAndroidLibraryPlugin;
import org.gradle.api.experimental.android.test.StandaloneAndroidTestPlugin;
import org.gradle.api.experimental.jvm.JvmEcosystemConventionsPlugin;
import org.gradle.api.initialization.Settings;
import org.gradle.api.internal.plugins.software.RegistersSoftwareTypes;
Expand All @@ -11,7 +12,7 @@
import javax.inject.Inject;

@SuppressWarnings("UnstableApiUsage")
@RegistersSoftwareTypes({StandaloneAndroidApplicationPlugin.class, StandaloneAndroidLibraryPlugin.class})
@RegistersSoftwareTypes({StandaloneAndroidApplicationPlugin.class, StandaloneAndroidLibraryPlugin.class, StandaloneAndroidTestPlugin.class})
public abstract class AndroidEcosystemPlugin implements Plugin<Settings> {
@Override
public void apply(Settings target) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.android.build.api.dsl.BaseFlavor;
import com.android.build.api.dsl.CommonExtension;
import org.gradle.api.Action;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.experimental.android.extensions.BaselineProfile;
import org.gradle.api.experimental.android.extensions.Compose;
import org.gradle.api.experimental.android.extensions.CoreLibraryDesugaring;
Expand Down Expand Up @@ -158,4 +159,7 @@ default void lint(Action<? super Lint> action) {
default void secrets(Action<? super Secrets> action) {
action.execute(getSecrets());
}

@Nested
NamedDomainObjectContainer<ExperimentalProperty> getExperimentalProperties();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.gradle.api.experimental.android;

import org.gradle.api.Named;
import org.gradle.api.provider.Property;
import org.gradle.declarative.dsl.model.annotations.Restricted;

@Restricted
public interface ExperimentalProperty extends Named {
@Restricted
Property<Boolean> getValue();
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.gradle.declarative.dsl.model.annotations.Configuring;
import org.gradle.declarative.dsl.model.annotations.Restricted;

// TODO: This might be better split into separate producer/consumer parts
@Restricted
public interface BaselineProfile {
@Restricted
Expand All @@ -37,4 +38,10 @@ public interface BaselineProfile {
default void dependencies(Action<? super BaselineProfileDependencies> action) {
action.execute(getDependencies());
}

@Restricted
Property<String> getAdditionalManagedDevice();

@Restricted
Property<Boolean> getUseConnectedDevices();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.gradle.api.experimental.android.extensions.testing;

import org.gradle.api.Named;
import org.gradle.api.provider.Property;
import org.gradle.declarative.dsl.model.annotations.Restricted;

@Restricted
public interface ManagedDevice extends Named {
@Restricted
abstract Property<String> getDevice();

@Restricted
abstract Property<Integer> getApiLevel();

@Restricted
abstract Property<String> getSystemImageSource();
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

package org.gradle.api.experimental.android.extensions.testing;

import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Nested;
import org.gradle.declarative.dsl.model.annotations.Restricted;

@Restricted
Expand All @@ -29,4 +31,7 @@ public interface TestOptions {

@Restricted
Property<String> getTestInstrumentationRunner();

@Nested
NamedDomainObjectContainer<ManagedDevice> getManagedDevices();
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
@Restricted
public interface Testing {
/**
* Whether or not to set up Jacoco support.
* Whether to set up Jacoco support.
*/
@Nested
Jacoco getJacoco();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.gradle.api.experimental.android.nia;

import androidx.baselineprofile.gradle.consumer.BaselineProfileConsumerExtension;
import androidx.baselineprofile.gradle.producer.BaselineProfileProducerExtension;
import com.android.SdkConstants;
import com.android.build.api.artifact.SingleArtifact;
import com.android.build.api.dsl.ApplicationExtension;
Expand All @@ -16,15 +18,19 @@
import com.android.build.api.variant.BuiltArtifactsLoader;
import com.android.build.api.variant.HasAndroidTest;
import com.android.build.api.variant.LibraryAndroidComponentsExtension;
import com.android.build.api.variant.TestAndroidComponentsExtension;
import com.android.build.gradle.BaseExtension;
import com.android.build.gradle.TestExtension;
import com.dropbox.gradle.plugins.dependencyguard.DependencyGuardPluginExtension;
import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.text.WordUtils;
import org.gradle.api.*;
import org.gradle.api.experimental.android.AndroidSoftware;
import org.gradle.api.experimental.android.application.AndroidApplication;
import org.gradle.api.experimental.android.extensions.BaselineProfile;
import org.gradle.api.experimental.android.library.AndroidLibrary;
import org.gradle.api.experimental.android.test.AndroidTest;
import org.gradle.api.file.Directory;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Copy;
Expand Down Expand Up @@ -65,11 +71,30 @@ public static boolean isNiaProject(Project project) {
return Objects.equals(project.getRootProject().getName().replace("-", ""), NiaSupport.NIA_PROJECT_NAME);
}

public static void configureNiaTest(Project project, AndroidTest dslModel) {
TestExtension androidTest = project.getExtensions().getByType(TestExtension.class);
TestAndroidComponentsExtension androidTestComponents = project.getExtensions().getByType(TestAndroidComponentsExtension.class);

androidTest.getDefaultConfig().setTargetSdkPreview(dslModel.getTargetSdk().getOrElse(DEFAULT_TARGET_SDK).toString());

configureFlavors(androidTest);

configureKotlin(project);

configureGradleManagedDevices(androidTest);
configurePrintApksTask(project, androidTestComponents);

if (project.getExtensions().findByName("baselineProfile") != null) {
BaselineProfileProducerExtension baselineProfileProducerExtension = project.getExtensions().getByType(BaselineProfileProducerExtension.class);
BaselineProfileConsumerExtension baselineProfileConsumerExtension = project.getExtensions().getByType(BaselineProfileConsumerExtension.class);
configureBaselineProfile(project, dslModel.getBaselineProfile(), baselineProfileProducerExtension, baselineProfileConsumerExtension);
}
}

public static void configureNiaLibrary(Project project, AndroidLibrary dslModel) {
LibraryExtension androidLib = project.getExtensions().getByType(LibraryExtension.class);
LibraryAndroidComponentsExtension androidLibComponents = project.getExtensions().getByType(LibraryAndroidComponentsExtension.class);

// TODO: This might be removable
//noinspection deprecation
androidLib.getDefaultConfig().setTargetSdkPreview(dslModel.getTargetSdk().getOrElse(DEFAULT_TARGET_SDK).toString());

Expand Down Expand Up @@ -430,4 +455,20 @@ private static void configureDependencyGuard(Project project, AndroidApplication
dependencyGuard.configuration(dslModel.getDependencyGuard().getConfigurationName().get());
}
}

@SuppressWarnings("UnstableApiUsage")
public static void configureBaselineProfile(Project project, BaselineProfile baselineProfile, BaselineProfileProducerExtension baselineProfileProducerExtension, BaselineProfileConsumerExtension baselineProfileConsumerExtension) {
if (baselineProfile.getEnabled().get()) {
project.getPlugins().apply("androidx.baselineprofile");

baselineProfileConsumerExtension.setAutomaticGenerationDuringBuild(baselineProfile.getAutomaticGenerationDuringBuild().get());

if (baselineProfile.getAdditionalManagedDevice().isPresent()) {
baselineProfileProducerExtension.getManagedDevices().add(baselineProfile.getAdditionalManagedDevice().get());
}
ifPresent(baselineProfile.getUseConnectedDevices(), baselineProfileProducerExtension::setUseConnectedDevices);

project.getConfigurations().getByName("baselineProfile").fromDependencyCollector(baselineProfile.getDependencies().getProfile());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package org.gradle.api.experimental.android.test;

import com.android.build.api.dsl.BaseFlavor;
import com.android.build.api.dsl.CommonExtension;
import org.gradle.api.Action;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.experimental.android.ExperimentalProperty;
import org.gradle.api.experimental.android.extensions.BaselineProfile;
import org.gradle.api.experimental.android.extensions.testing.AndroidTestDependencies;
import org.gradle.api.experimental.android.extensions.testing.TestOptions;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Nested;
import org.gradle.declarative.dsl.model.annotations.Configuring;
import org.gradle.declarative.dsl.model.annotations.Restricted;

// TODO: This probably shouldn't extend AndroidSoftware, as it does not
// represent a project the produces production software. There should be a
// common AbstractAndroidPlugin that AndroidSoftwarePlugin and this plugin
// both extend that folds these commonalities back into it
public interface AndroidTest {
/**
* @see CommonExtension#getNamespace()
*/
@Restricted
Property<String> getNamespace();

/**
* @see CommonExtension#getCompileSdk()
*/
@Restricted
Property<Integer> getCompileSdk();

/**
* @see BaseFlavor#getMinSdk()
*/
@Restricted
Property<Integer> getMinSdk();

@Restricted
Property<Integer> getTargetSdk();

/**
* Flag to enable/disable generation of the `BuildConfig` class.
*
* Default value is `false`.
*/
@Restricted
Property<Boolean> getBuildConfig();

@Nested
BaselineProfile getBaselineProfile();

@Configuring
default void baselineProfile(Action<? super BaselineProfile> action) {
action.execute(getBaselineProfile());
}

@Nested
NamedDomainObjectContainer<ExperimentalProperty> getExperimentalProperties();

@Nested
AndroidTestDependencies getDependencies();

@Configuring
default void dependencies(Action<? super AndroidTestDependencies> action) {
action.execute(getDependencies());
}

@Nested
TestOptions getTestOptions();

@Configuring
default void testOptions(Action<? super TestOptions> action) {
action.execute(getTestOptions());
}

@Restricted
Property<String> getTargetProjectPath();
}
Loading
Loading