/* * Copyright (C) 2013 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.build.gradle.model; import static com.android.builder.core.BuilderConstants.ANDROID_TEST; import static com.android.builder.core.BuilderConstants.DEBUG; import static com.android.builder.model.AndroidProject.ARTIFACT_ANDROID_TEST; import com.android.SdkConstants; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.build.FilterData; import com.android.build.OutputFile; import com.android.build.tests.AndroidProjectConnector; import com.android.builder.internal.StringHelper; import com.android.builder.model.AndroidArtifact; import com.android.builder.model.AndroidArtifactOutput; import com.android.builder.model.AndroidLibrary; import com.android.builder.model.AndroidProject; import com.android.builder.model.ApiVersion; import com.android.builder.model.ArtifactMetaData; import com.android.builder.model.BuildTypeContainer; import com.android.builder.model.ClassField; import com.android.builder.model.Dependencies; import com.android.builder.model.JavaArtifact; import com.android.builder.model.JavaCompileOptions; import com.android.builder.model.JavaLibrary; import com.android.builder.model.MavenCoordinates; import com.android.builder.model.ProductFlavor; import com.android.builder.model.ProductFlavorContainer; import com.android.builder.model.SigningConfig; import com.android.builder.model.SourceProvider; import com.android.builder.model.SourceProviderContainer; import com.android.builder.model.Variant; import com.android.ide.common.signing.KeystoreHelper; import com.android.io.StreamException; import com.android.prefs.AndroidLocation; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import junit.framework.TestCase; import org.gradle.tooling.GradleConnector; import org.gradle.tooling.ProjectConnection; import org.gradle.tooling.UnknownModelException; import org.gradle.tooling.model.GradleProject; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; import java.security.CodeSource; import java.security.KeyStore; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; public class AndroidProjectTest extends TestCase { private static final String GRADLE_VERSION = "2.1"; private static final String FOLDER_TEST_REGULAR = "regular"; private static final String FOLDER_TEST_MANUAL = "manual"; private static final String MODEL_VERSION = "0.14.1"; private static final Map<String, ProjectData> sProjectModelMap = Maps.newHashMap(); private static final class ProjectData { AndroidProject model; File projectDir; static ProjectData create(File projectDir, AndroidProject model) { ProjectData projectData = new ProjectData(); projectData.model = model; projectData.projectDir = projectDir; return projectData; } } private static final class DefaultApiVersion implements ApiVersion { private final int mApiLevel; @Nullable private final String mCodename; public DefaultApiVersion(int apiLevel, @Nullable String codename) { mApiLevel = apiLevel; mCodename = codename; } public DefaultApiVersion(int apiLevel) { this(apiLevel, null); } public DefaultApiVersion(@NonNull String codename) { this(1, codename); } public static ApiVersion create(@NonNull Object value) { if (value instanceof Integer) { return new DefaultApiVersion((Integer) value, null); } else if (value instanceof String) { return new DefaultApiVersion(1, (String) value); } return null; } @Override public int getApiLevel() { return mApiLevel; } @Nullable @Override public String getCodename() { return mCodename; } @NonNull @Override public String getApiString() { return mCodename != null ? mCodename : Integer.toString(mApiLevel); } @Override public boolean equals(Object o) { /** * Normally equals only test for the same exact class, but here me make it accept * ApiVersion since we're comparing it against implementations that are serialized * across Gradle's tooling api. */ if (this == o) { return true; } if (!(o instanceof ApiVersion)) { return false; } ApiVersion that = (ApiVersion) o; if (mApiLevel != that.getApiLevel()) { return false; } if (mCodename != null ? !mCodename.equals(that.getCodename()) : that.getCodename() != null) { return false; } return true; } } private ProjectData getModelForProject(String testFolder, String projectName) throws IOException, StreamException { return getModelForProject(testFolder, projectName, false); } private ProjectData getModelForProject(String testFolder, String projectName, boolean cleanFirst) throws IOException, StreamException { ProjectData projectData = sProjectModelMap.get(projectName); if (projectData == null || cleanFirst) { File projectDir = new File(getTestDir(testFolder), projectName); if (cleanFirst) { AndroidProjectConnector connector = new AndroidProjectConnector( getSdkDir(), getNdkDir()); connector.runGradleTasks( projectDir, GRADLE_VERSION, Collections.<String>emptyList(), Collections.<String, String>emptyMap(), "clean"); } // Configure the connector and create the connection GradleConnector connector = GradleConnector.newConnector(); connector.forProjectDirectory(projectDir); ProjectConnection connection = connector.connect(); try { // Load the custom model for the project AndroidProject model = connection.getModel(AndroidProject.class); assertNotNull("Model Object null-check", model); assertEquals("Model Name", projectName, model.getName()); assertEquals("Model version", MODEL_VERSION, model.getModelVersion()); projectData = ProjectData.create(projectDir, model); sProjectModelMap.put(projectName, projectData); return projectData; } finally { connection.close(); } } return projectData; } private Map<String, ProjectData> getModelForMultiProject(String testFolder, String projectName) throws Exception { // Configure the connector and create the connection GradleConnector connector = GradleConnector.newConnector(); File projectDir = new File(getTestDir(testFolder), projectName); connector.forProjectDirectory(projectDir); Map<String, ProjectData> map = Maps.newHashMap(); ProjectConnection connection = connector.connect(); try { // Query the default Gradle Model. GradleProject model = connection.getModel(GradleProject.class); assertNotNull("Model Object null-check", model); // Now get the children projects, recursively. for (GradleProject child : model.getChildren()) { String path = child.getPath(); String name = path.substring(1); File childDir = new File(projectDir, name); GradleConnector childConnector = GradleConnector.newConnector(); childConnector.forProjectDirectory(childDir); ProjectConnection childConnection = childConnector.connect(); try { AndroidProject androidProject = childConnection.getModel(AndroidProject.class); assertNotNull("Model Object null-check for " + path, androidProject); assertEquals("Model Name for " + path, name, androidProject.getName()); assertEquals("Model version", MODEL_VERSION, androidProject.getModelVersion()); map.put(path, ProjectData.create(childDir, androidProject)); } catch (UnknownModelException e) { // probably a Java-only project, ignore. } finally { childConnection.close(); } } } finally { connection.close(); } return map; } public void testBasic() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "basic"); AndroidProject model = projectData.model; assertFalse("Library Project", model.isLibrary()); assertEquals("Compile Target", "android-19", model.getCompileTarget()); assertFalse("Non empty bootclasspath", model.getBootClasspath().isEmpty()); assertNotNull("aaptOptions not null", model.getAaptOptions()); assertEquals("aaptOptions noCompress", 1, model.getAaptOptions().getNoCompress().size()); assertTrue("aaptOptions noCompress", model.getAaptOptions().getNoCompress().contains("txt")); assertEquals("aaptOptions ignoreAssetsPattern", "!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~", model.getAaptOptions().getIgnoreAssets()); assertFalse("aaptOptions getFailOnMissingConfigEntry", model.getAaptOptions().getFailOnMissingConfigEntry()); JavaCompileOptions javaCompileOptions = model.getJavaCompileOptions(); assertEquals("1.6", javaCompileOptions.getSourceCompatibility()); assertEquals("1.6", javaCompileOptions.getTargetCompatibility()); } public void testBasicSourceProviders() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "basic"); AndroidProject model = projectData.model; File projectDir = projectData.projectDir; testDefaultSourceSets(model, projectDir); // test the source provider for the artifacts for (Variant variant : model.getVariants()) { AndroidArtifact artifact = variant.getMainArtifact(); assertNull(artifact.getVariantSourceProvider()); assertNull(artifact.getMultiFlavorSourceProvider()); } } public void testBasicMultiFlavorsSourceProviders() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_MANUAL, "basicMultiFlavors"); AndroidProject model = projectData.model; File projectDir = projectData.projectDir; testDefaultSourceSets(model, projectDir); // test the source provider for the flavor Collection<ProductFlavorContainer> productFlavors = model.getProductFlavors(); assertEquals("Product Flavor Count", 4, productFlavors.size()); for (ProductFlavorContainer pfContainer : productFlavors) { String name = pfContainer.getProductFlavor().getName(); new SourceProviderTester( model.getName(), projectDir, name, pfContainer.getSourceProvider()) .test(); assertEquals(1, pfContainer.getExtraSourceProviders().size()); SourceProviderContainer container = getSourceProviderContainer( pfContainer.getExtraSourceProviders(), ARTIFACT_ANDROID_TEST); assertNotNull(container); new SourceProviderTester( model.getName(), projectDir, ANDROID_TEST + StringHelper.capitalize(name), container.getSourceProvider()) .test(); } // test the source provider for the artifacts for (Variant variant : model.getVariants()) { AndroidArtifact artifact = variant.getMainArtifact(); assertNotNull(artifact.getVariantSourceProvider()); assertNotNull(artifact.getMultiFlavorSourceProvider()); } } private static void testDefaultSourceSets(@NonNull AndroidProject model, @NonNull File projectDir) { ProductFlavorContainer defaultConfig = model.getDefaultConfig(); // test the main source provider new SourceProviderTester(model.getName(), projectDir, "main", defaultConfig.getSourceProvider()) .test(); // test the main instrumentTest source provider SourceProviderContainer testSourceProviders = getSourceProviderContainer( defaultConfig.getExtraSourceProviders(), ARTIFACT_ANDROID_TEST); assertNotNull("InstrumentTest source Providers null-check", testSourceProviders); new SourceProviderTester(model.getName(), projectDir, ANDROID_TEST, testSourceProviders.getSourceProvider()) .test(); // test the source provider for the build types Collection<BuildTypeContainer> buildTypes = model.getBuildTypes(); assertEquals("Build Type Count", 2, buildTypes.size()); for (BuildTypeContainer btContainer : model.getBuildTypes()) { new SourceProviderTester( model.getName(), projectDir, btContainer.getBuildType().getName(), btContainer.getSourceProvider()) .test(); assertEquals(0, btContainer.getExtraSourceProviders().size()); } } public void testBasicVariantDetails() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "basic", true /*cleanFirst*/); AndroidProject model = projectData.model; Collection<Variant> variants = model.getVariants(); assertEquals("Variant Count", 2 , variants.size()); // debug variant Variant debugVariant = getVariant(variants, DEBUG); assertNotNull("debug Variant null-check", debugVariant); new ProductFlavorTester(debugVariant.getMergedFlavor(), "Debug Merged Flavor") .setVersionCode(12) .setVersionName("2.0") .setMinSdkVersion(16) .setTargetSdkVersion(16) .setTestInstrumentationRunner("android.test.InstrumentationTestRunner") .setTestHandleProfiling(Boolean.FALSE) .setTestFunctionalTest(null) .test(); // debug variant, tested. AndroidArtifact debugMainInfo = debugVariant.getMainArtifact(); assertNotNull("Debug main info null-check", debugMainInfo); assertEquals("Debug package name", "com.android.tests.basic.debug", debugMainInfo.getApplicationId()); assertTrue("Debug signed check", debugMainInfo.isSigned()); assertEquals("Debug signingConfig name", "myConfig", debugMainInfo.getSigningConfigName()); assertEquals("Debug sourceGenTask", "generateDebugSources", debugMainInfo.getSourceGenTaskName()); assertEquals("Debug compileTask", "compileDebugSources", debugMainInfo.getCompileTaskName()); Collection<AndroidArtifactOutput> debugMainOutputs = debugMainInfo.getOutputs(); assertNotNull("Debug main output null-check", debugMainOutputs); assertEquals("Debug main output size", 1, debugMainOutputs.size()); AndroidArtifactOutput debugMainOutput = debugMainOutputs.iterator().next(); assertNotNull(debugMainOutput); assertNotNull(debugMainOutput.getMainOutputFile()); assertNotNull(debugMainOutput.getAssembleTaskName()); assertNotNull(debugMainOutput.getGeneratedManifest()); assertEquals(12, debugMainOutput.getVersionCode()); // check debug dependencies Dependencies debugDependencies = debugMainInfo.getDependencies(); assertNotNull(debugDependencies); Collection<AndroidLibrary> debugLibraries = debugDependencies.getLibraries(); assertNotNull(debugLibraries); assertEquals(1, debugLibraries.size()); assertTrue(debugDependencies.getProjects().isEmpty()); AndroidLibrary androidLibrary = debugLibraries.iterator().next(); assertNotNull(androidLibrary); assertNotNull(androidLibrary.getBundle()); assertNotNull(androidLibrary.getFolder()); MavenCoordinates coord = androidLibrary.getResolvedCoordinates(); assertNotNull(coord); assertEquals("com.google.android.gms:play-services:3.1.36", coord.getGroupId() + ":" + coord.getArtifactId() + ":" + coord.getVersion()); Collection<JavaLibrary> javaLibraries = debugDependencies.getJavaLibraries(); assertNotNull(javaLibraries); assertEquals(2, javaLibraries.size()); Set<String> javaLibs = Sets.newHashSet( "com.android.support:support-v13:13.0.0", "com.android.support:support-v4:13.0.0" ); for (JavaLibrary javaLib : javaLibraries) { coord = javaLib.getResolvedCoordinates(); assertNotNull(coord); String lib = coord.getGroupId() + ":" + coord.getArtifactId() + ":" + coord.getVersion(); assertTrue(javaLibs.contains(lib)); javaLibs.remove(lib); } // this variant is tested. Collection<AndroidArtifact> debugExtraAndroidArtifacts = debugVariant.getExtraAndroidArtifacts(); AndroidArtifact debugTestInfo = getAndroidArtifact(debugExtraAndroidArtifacts, ARTIFACT_ANDROID_TEST); assertNotNull("Test info null-check", debugTestInfo); assertEquals("Test package name", "com.android.tests.basic.debug.test", debugTestInfo.getApplicationId()); assertTrue("Test signed check", debugTestInfo.isSigned()); assertEquals("Test signingConfig name", "myConfig", debugTestInfo.getSigningConfigName()); assertEquals("Test sourceGenTask", "generateDebugTestSources", debugTestInfo.getSourceGenTaskName()); assertEquals("Test compileTask", "compileDebugTestSources", debugTestInfo.getCompileTaskName()); Collection<File> generatedResFolders = debugTestInfo.getGeneratedResourceFolders(); assertNotNull(generatedResFolders); // size 2 = rs output + resValue output assertEquals(2, generatedResFolders.size()); Collection<AndroidArtifactOutput> debugTestOutputs = debugTestInfo.getOutputs(); assertNotNull("Debug test output null-check", debugTestOutputs); assertEquals("Debug test output size", 1, debugTestOutputs.size()); AndroidArtifactOutput debugTestOutput = debugTestOutputs.iterator().next(); assertNotNull(debugTestOutput); assertNotNull(debugTestOutput.getMainOutputFile()); assertNotNull(debugTestOutput.getAssembleTaskName()); assertNotNull(debugTestOutput.getGeneratedManifest()); // test the resValues and buildConfigFields. ProductFlavor defaultConfig = model.getDefaultConfig().getProductFlavor(); Map<String, ClassField> buildConfigFields = defaultConfig.getBuildConfigFields(); assertNotNull(buildConfigFields); assertEquals(2, buildConfigFields.size()); assertEquals("true", buildConfigFields.get("DEFAULT").getValue()); assertEquals("\"foo2\"", buildConfigFields.get("FOO").getValue()); Map<String, ClassField> resValues = defaultConfig.getResValues(); assertNotNull(resValues); assertEquals(1, resValues.size()); assertEquals("foo", resValues.get("foo").getValue()); // test on the debug build type. Collection<BuildTypeContainer> buildTypes = model.getBuildTypes(); for (BuildTypeContainer buildTypeContainer : buildTypes) { if (buildTypeContainer.getBuildType().getName().equals(DEBUG)) { buildConfigFields = buildTypeContainer.getBuildType().getBuildConfigFields(); assertNotNull(buildConfigFields); assertEquals(1, buildConfigFields.size()); assertEquals("\"bar\"", buildConfigFields.get("FOO").getValue()); resValues = buildTypeContainer.getBuildType().getResValues(); assertNotNull(resValues); assertEquals(1, resValues.size()); assertEquals("foo2", resValues.get("foo").getValue()); } } // now test the merged flavor ProductFlavor mergedFlavor = debugVariant.getMergedFlavor(); buildConfigFields = mergedFlavor.getBuildConfigFields(); assertNotNull(buildConfigFields); assertEquals(2, buildConfigFields.size()); assertEquals("true", buildConfigFields.get("DEFAULT").getValue()); assertEquals("\"foo2\"", buildConfigFields.get("FOO").getValue()); resValues = mergedFlavor.getResValues(); assertNotNull(resValues); assertEquals(1, resValues.size()); assertEquals("foo", resValues.get("foo").getValue()); // release variant, not tested. Variant releaseVariant = getVariant(variants, "release"); assertNotNull("release Variant null-check", releaseVariant); AndroidArtifact relMainInfo = releaseVariant.getMainArtifact(); assertNotNull("Release main info null-check", relMainInfo); assertEquals("Release package name", "com.android.tests.basic", relMainInfo.getApplicationId()); assertFalse("Release signed check", relMainInfo.isSigned()); assertNull("Release signingConfig name", relMainInfo.getSigningConfigName()); assertEquals("Release sourceGenTask", "generateReleaseSources", relMainInfo.getSourceGenTaskName()); assertEquals("Release javaCompileTask", "compileReleaseSources", relMainInfo.getCompileTaskName()); Collection<AndroidArtifactOutput> relMainOutputs = relMainInfo.getOutputs(); assertNotNull("Rel Main output null-check", relMainOutputs); assertEquals("Rel Main output size", 1, relMainOutputs.size()); AndroidArtifactOutput relMainOutput = relMainOutputs.iterator().next(); assertNotNull(relMainOutput); assertNotNull(relMainOutput.getMainOutputFile()); assertNotNull(relMainOutput.getAssembleTaskName()); assertNotNull(relMainOutput.getGeneratedManifest()); assertEquals(13, relMainOutput.getVersionCode()); Collection<AndroidArtifact> releaseExtraAndroidArtifacts = releaseVariant.getExtraAndroidArtifacts(); AndroidArtifact relTestInfo = getAndroidArtifact(releaseExtraAndroidArtifacts, ARTIFACT_ANDROID_TEST); assertNull("Release test info null-check", relTestInfo); // check release dependencies Dependencies releaseDependencies = relMainInfo.getDependencies(); assertNotNull(releaseDependencies); Collection<AndroidLibrary> releaseLibraries = releaseDependencies.getLibraries(); assertNotNull(releaseLibraries); assertEquals(3, releaseLibraries.size()); // map for each aar we expect to find and how many local jars they each have. Map<String, Integer> aarLibs = Maps.newHashMapWithExpectedSize(3); aarLibs.put("com.android.support:support-v13:21.0.0", 1); aarLibs.put("com.android.support:support-v4:21.0.0", 1); aarLibs.put("com.google.android.gms:play-services:3.1.36", 0); for (AndroidLibrary androidLib : releaseLibraries) { assertNotNull(androidLib.getBundle()); assertNotNull(androidLib.getFolder()); coord = androidLib.getResolvedCoordinates(); assertNotNull(coord); String lib = coord.getGroupId() + ":" + coord.getArtifactId() + ":" + coord.getVersion(); Integer localJarCount = aarLibs.get(lib); assertNotNull("Check presense of " + lib, localJarCount); assertEquals("Check local jar count for " + lib, localJarCount.intValue(), androidLib.getLocalJars().size()); System.out.println(">>" + androidLib.getLocalJars()); aarLibs.remove(lib); } assertTrue("check for missing libs", aarLibs.isEmpty()); } public void testBasicSigningConfigs() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "basic"); AndroidProject model = projectData.model; Collection<SigningConfig> signingConfigs = model.getSigningConfigs(); assertNotNull("SigningConfigs null-check", signingConfigs); assertEquals("Number of signingConfig", 2, signingConfigs.size()); SigningConfig debugSigningConfig = getSigningConfig(signingConfigs, DEBUG); assertNotNull("debug signing config null-check", debugSigningConfig); new SigningConfigTester(debugSigningConfig, DEBUG, true).test(); SigningConfig mySigningConfig = getSigningConfig(signingConfigs, "myConfig"); assertNotNull("myConfig signing config null-check", mySigningConfig); new SigningConfigTester(mySigningConfig, "myConfig", true) .setStoreFile(new File(projectData.projectDir, "debug.keystore")) .test(); } public void testDensitySplitOutputs() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "densitySplit"); AndroidProject model = projectData.model; Collection<Variant> variants = model.getVariants(); assertEquals("Variant Count", 2 , variants.size()); // get the main artifact of the debug artifact Variant debugVariant = getVariant(variants, DEBUG); assertNotNull("debug Variant null-check", debugVariant); AndroidArtifact debugMainArficat = debugVariant.getMainArtifact(); assertNotNull("Debug main info null-check", debugMainArficat); // get the outputs. Collection<AndroidArtifactOutput> debugOutputs = debugMainArficat.getOutputs(); assertNotNull(debugOutputs); assertEquals(5, debugOutputs.size()); // build a map of expected outputs and their versionCode Map<String, Integer> expected = Maps.newHashMapWithExpectedSize(5); expected.put(null, 112); expected.put("mdpi", 212); expected.put("hdpi", 312); expected.put("xhdpi", 412); expected.put("xxhdpi", 512); assertEquals(5, debugOutputs.size()); for (AndroidArtifactOutput output : debugOutputs) { assertEquals(OutputFile.FULL_SPLIT, output.getMainOutputFile().getOutputType()); Collection<? extends OutputFile> outputFiles = output.getOutputs(); assertEquals(1, outputFiles.size()); assertNotNull(output.getMainOutputFile()); String densityFilter = getFilter(output.getMainOutputFile(), OutputFile.DENSITY); Integer value = expected.get(densityFilter); // this checks we're not getting an unexpected output. assertNotNull("Check Valid output: " + (densityFilter == null ? "universal" : densityFilter), value); assertEquals(value.intValue(), output.getVersionCode()); expected.remove(densityFilter); } // this checks we didn't miss any expected output. assertTrue(expected.isEmpty()); } @Nullable private static String getFilter(@NonNull OutputFile outputFile, @NonNull String filterType) { for (FilterData filterData : outputFile.getFilters()) { if (filterData.getFilterType().equals(filterType)) { return filterData.getIdentifier(); } } return null; } public void testDensityPureSplitOutputs() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "densitySplitInL"); AndroidProject model = projectData.model; Collection<Variant> variants = model.getVariants(); assertEquals("Variant Count", 2 , variants.size()); // get the main artifact of the debug artifact Variant debugVariant = getVariant(variants, DEBUG); assertNotNull("debug Variant null-check", debugVariant); AndroidArtifact debugMainArtifact = debugVariant.getMainArtifact(); assertNotNull("Debug main info null-check", debugMainArtifact); // get the outputs. Collection<AndroidArtifactOutput> debugOutputs = debugMainArtifact.getOutputs(); assertNotNull(debugOutputs); // build a set of expected outputs Set<String> expected = Sets.newHashSetWithExpectedSize(5); expected.add(null); expected.add("mdpi"); expected.add("hdpi"); expected.add("xhdpi"); expected.add("xxhdpi"); assertEquals(1, debugOutputs.size()); AndroidArtifactOutput output = debugOutputs.iterator().next(); //assertEquals(5, output.getOutputs().size()); for (OutputFile outputFile : output.getOutputs()) { String densityFilter = getFilter(outputFile, OutputFile.DENSITY); assertEquals(densityFilter == null ? OutputFile.MAIN : OutputFile.SPLIT, outputFile.getOutputType()); // with pure splits, all split have the same version code. assertEquals(12, output.getVersionCode()); expected.remove(densityFilter); } // this checks we didn't miss any expected output. //assertTrue(expected.isEmpty()); } public void testAbiSplitOutputs() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "ndkSanAngeles"); AndroidProject model = projectData.model; Collection<Variant> variants = model.getVariants(); assertEquals("Variant Count", 2, variants.size()); // get the main artifact of the debug artifact Variant debugVariant = getVariant(variants, DEBUG); assertNotNull("debug Variant null-check", debugVariant); AndroidArtifact debugMainArficat = debugVariant.getMainArtifact(); assertNotNull("Debug main info null-check", debugMainArficat); // get the outputs. Collection<AndroidArtifactOutput> debugOutputs = debugMainArficat.getOutputs(); assertNotNull(debugOutputs); assertEquals(3, debugOutputs.size()); // build a map of expected outputs and their versionCode Map<String, Integer> expected = Maps.newHashMapWithExpectedSize(5); expected.put("armeabi-v7a", 1000123); expected.put("mips", 2000123); expected.put("x86", 3000123); assertEquals(3, debugOutputs.size()); for (AndroidArtifactOutput output : debugOutputs) { Collection<? extends OutputFile> outputFiles = output.getOutputs(); assertEquals(1, outputFiles.size()); for (FilterData filterData : outputFiles.iterator().next().getFilters()) { if (filterData.getFilterType().equals(OutputFile.ABI)) { String abiFilter = filterData.getIdentifier(); Integer value = expected.get(abiFilter); // this checks we're not getting an unexpected output. assertNotNull("Check Valid output: " + abiFilter, value); assertEquals(value.intValue(), output.getVersionCode()); expected.remove(abiFilter); } } } // this checks we didn't miss any expected output. assertTrue(expected.isEmpty()); } public void testMigrated() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "migrated"); AndroidProject model = projectData.model; File projectDir = projectData.projectDir; assertNotNull("Model Object null-check", model); assertEquals("Model Name", "migrated", model.getName()); assertFalse("Library Project", model.isLibrary()); ProductFlavorContainer defaultConfig = model.getDefaultConfig(); new SourceProviderTester(model.getName(), projectDir, "main", defaultConfig.getSourceProvider()) .setJavaDir("src") .setResourcesDir("src") .setAidlDir("src") .setRenderscriptDir("src") .setResDir("res") .setAssetsDir("assets") .setManifestFile("AndroidManifest.xml") .test(); SourceProviderContainer testSourceProviderContainer = getSourceProviderContainer( defaultConfig.getExtraSourceProviders(), ARTIFACT_ANDROID_TEST); assertNotNull("InstrumentTest source Providers null-check", testSourceProviderContainer); new SourceProviderTester(model.getName(), projectDir, ANDROID_TEST, testSourceProviderContainer.getSourceProvider()) .setJavaDir("tests/java") .setResourcesDir("tests/resources") .setAidlDir("tests/aidl") .setJniDir("tests/jni") .setRenderscriptDir("tests/rs") .setResDir("tests/res") .setAssetsDir("tests/assets") .setManifestFile("tests/AndroidManifest.xml") .test(); } public void testRenamedApk() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "renamedApk"); AndroidProject model = projectData.model; File projectDir = projectData.projectDir; assertNotNull("Model Object null-check", model); assertEquals("Model Name", "renamedApk", model.getName()); Collection<Variant> variants = model.getVariants(); assertEquals("Variant Count", 2 , variants.size()); File buildDir = new File(projectDir, "build"); for (Variant variant : variants) { AndroidArtifact mainInfo = variant.getMainArtifact(); assertNotNull( "Null-check on mainArtifactInfo for " + variant.getDisplayName(), mainInfo); AndroidArtifactOutput output = mainInfo.getOutputs().iterator().next(); assertEquals("Output file for " + variant.getName(), new File(buildDir, variant.getName() + ".apk"), output.getMainOutputFile().getOutputFile()); } } public void testFilteredOutBuildType() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "filteredOutBuildType"); AndroidProject model = projectData.model; assertEquals("Variant Count", 1, model.getVariants().size()); Variant variant = model.getVariants().iterator().next(); assertEquals("Variant name", "release", variant.getBuildType()); } public void testFilteredOutVariants() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "filteredOutVariants"); AndroidProject model = projectData.model; Collection<Variant> variants = model.getVariants(); // check we have the right number of variants: // arm/cupcake, arm/gingerbread, x86/gingerbread, mips/gingerbread // all 4 in release and debug assertEquals("Variant Count", 8, variants.size()); for (Variant variant : variants) { List<String> flavors = variant.getProductFlavors(); assertFalse("check ignored x86/cupcake", flavors.contains("x68") && flavors.contains("cupcake")); assertFalse("check ignored mips/cupcake", flavors.contains("mips") && flavors.contains("cupcake")); } } public void testFlavors() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "flavors"); AndroidProject model = projectData.model; File projectDir = projectData.projectDir; assertNotNull("Model Object null-check", model); assertEquals("Model Name", "flavors", model.getName()); assertFalse("Library Project", model.isLibrary()); ProductFlavorContainer defaultConfig = model.getDefaultConfig(); new SourceProviderTester(model.getName(), projectDir, "main", defaultConfig.getSourceProvider()) .test(); SourceProviderContainer testSourceProviderContainer = getSourceProviderContainer( defaultConfig.getExtraSourceProviders(), ARTIFACT_ANDROID_TEST); assertNotNull("InstrumentTest source Providers null-check", testSourceProviderContainer); new SourceProviderTester(model.getName(), projectDir, ANDROID_TEST, testSourceProviderContainer.getSourceProvider()) .test(); Collection<BuildTypeContainer> buildTypes = model.getBuildTypes(); assertEquals("Build Type Count", 2, buildTypes.size()); Collection<Variant> variants = model.getVariants(); assertEquals("Variant Count", 8, variants.size()); Variant f1faDebugVariant = getVariant(variants, "f1FaDebug"); assertNotNull("f1faDebug Variant null-check", f1faDebugVariant); new ProductFlavorTester(f1faDebugVariant.getMergedFlavor(), "F1faDebug Merged Flavor") .test(); new VariantTester(f1faDebugVariant, projectDir, "flavors-f1-fa-debug.apk").test(); } public void testTicTacToe() throws Exception { Map<String, ProjectData> map = getModelForMultiProject(FOLDER_TEST_REGULAR, "tictactoe"); ProjectData libModelData = map.get(":lib"); assertNotNull("lib module model null-check", libModelData); assertTrue("lib module library flag", libModelData.model.isLibrary()); ProjectData appModelData = map.get(":app"); assertNotNull("app module model null-check", appModelData); Collection<Variant> variants = appModelData.model.getVariants(); Variant debugVariant = getVariant(variants, DEBUG); assertNotNull("debug variant null-check", debugVariant); Dependencies dependencies = debugVariant.getMainArtifact().getDependencies(); assertNotNull(dependencies); Collection<AndroidLibrary> libs = dependencies.getLibraries(); assertNotNull(libs); assertEquals(1, libs.size()); AndroidLibrary androidLibrary = libs.iterator().next(); assertNotNull(androidLibrary); assertEquals("Dependency project path", ":lib", androidLibrary.getProject()); // TODO: right now we can only test the folder name efficiently assertTrue(androidLibrary.getFolder().getPath().endsWith("/tictactoe/lib/unspecified")); } public void testFlavorLib() throws Exception { Map<String, ProjectData> map = getModelForMultiProject(FOLDER_TEST_REGULAR, "flavorlib"); ProjectData appModelData = map.get(":app"); assertNotNull("Module app null-check", appModelData); AndroidProject model = appModelData.model; assertFalse("Library Project", model.isLibrary()); Collection<Variant> variants = model.getVariants(); Collection<ProductFlavorContainer> productFlavors = model.getProductFlavors(); ProductFlavorContainer flavor1 = getProductFlavor(productFlavors, "flavor1"); assertNotNull(flavor1); Variant flavor1Debug = getVariant(variants, "flavor1Debug"); assertNotNull(flavor1Debug); Dependencies dependencies = flavor1Debug.getMainArtifact().getDependencies(); assertNotNull(dependencies); Collection<AndroidLibrary> libs = dependencies.getLibraries(); assertNotNull(libs); assertEquals(1, libs.size()); AndroidLibrary androidLibrary = libs.iterator().next(); assertNotNull(androidLibrary); assertEquals(":lib1", androidLibrary.getProject()); // TODO: right now we can only test the folder name efficiently assertTrue(androidLibrary.getFolder().getPath(), androidLibrary.getFolder().getPath().endsWith("/flavorlib/lib1/unspecified")); ProductFlavorContainer flavor2 = getProductFlavor(productFlavors, "flavor2"); assertNotNull(flavor2); Variant flavor2Debug = getVariant(variants, "flavor2Debug"); assertNotNull(flavor2Debug); dependencies = flavor2Debug.getMainArtifact().getDependencies(); assertNotNull(dependencies); libs = dependencies.getLibraries(); assertNotNull(libs); assertEquals(1, libs.size()); androidLibrary = libs.iterator().next(); assertNotNull(androidLibrary); assertEquals(":lib2", androidLibrary.getProject()); // TODO: right now we can only test the folder name efficiently assertTrue(androidLibrary.getFolder().getPath(), androidLibrary.getFolder().getPath().endsWith("/flavorlib/lib2/unspecified")); } public void testFlavoredLib() throws Exception { Map<String, ProjectData> map = getModelForMultiProject(FOLDER_TEST_REGULAR, "flavoredlib"); ProjectData appModelData = map.get(":app"); assertNotNull("Module app null-check", appModelData); AndroidProject model = appModelData.model; assertFalse("Library Project", model.isLibrary()); Collection<Variant> variants = model.getVariants(); Collection<ProductFlavorContainer> productFlavors = model.getProductFlavors(); ProductFlavorContainer flavor1 = getProductFlavor(productFlavors, "flavor1"); assertNotNull(flavor1); Variant flavor1Debug = getVariant(variants, "flavor1Debug"); assertNotNull(flavor1Debug); Dependencies dependencies = flavor1Debug.getMainArtifact().getDependencies(); assertNotNull(dependencies); Collection<AndroidLibrary> libs = dependencies.getLibraries(); assertNotNull(libs); assertEquals(1, libs.size()); AndroidLibrary androidLibrary = libs.iterator().next(); assertNotNull(androidLibrary); assertEquals(":lib", androidLibrary.getProject()); assertEquals("flavor1Release", androidLibrary.getProjectVariant()); // TODO: right now we can only test the folder name efficiently assertTrue(androidLibrary.getFolder().getPath(), androidLibrary.getFolder().getPath().endsWith("/flavoredlib/lib/unspecified/flavor1Release")); ProductFlavorContainer flavor2 = getProductFlavor(productFlavors, "flavor2"); assertNotNull(flavor2); Variant flavor2Debug = getVariant(variants, "flavor2Debug"); assertNotNull(flavor2Debug); dependencies = flavor2Debug.getMainArtifact().getDependencies(); assertNotNull(dependencies); libs = dependencies.getLibraries(); assertNotNull(libs); assertEquals(1, libs.size()); androidLibrary = libs.iterator().next(); assertNotNull(androidLibrary); assertEquals(":lib", androidLibrary.getProject()); assertEquals("flavor2Release", androidLibrary.getProjectVariant()); // TODO: right now we can only test the folder name efficiently assertTrue(androidLibrary.getFolder().getPath(), androidLibrary.getFolder().getPath().endsWith("/flavoredlib/lib/unspecified/flavor2Release")); } public void testMultiproject() throws Exception { Map<String, ProjectData> map = getModelForMultiProject(FOLDER_TEST_REGULAR, "multiproject"); ProjectData baseLibModelData = map.get(":baseLibrary"); assertNotNull("Module app null-check", baseLibModelData); AndroidProject model = baseLibModelData.model; Collection<Variant> variants = model.getVariants(); assertEquals("Variant count", 2, variants.size()); Variant variant = getVariant(variants, "release"); assertNotNull("release variant null-check", variant); AndroidArtifact mainInfo = variant.getMainArtifact(); assertNotNull("Main Artifact null-check", mainInfo); Dependencies dependencies = mainInfo.getDependencies(); assertNotNull("Dependencies null-check", dependencies); Collection<String> projects = dependencies.getProjects(); assertNotNull("project dep list null-check", projects); assertEquals("project dep count", 1, projects.size()); assertEquals("dep on :util check", ":util", projects.iterator().next()); Collection<JavaLibrary> javaLibraries = dependencies.getJavaLibraries(); assertNotNull("jar dep list null-check", javaLibraries); // TODO these are jars coming from ':util' They shouldn't be there. assertEquals("jar dep count", 2, javaLibraries.size()); } public void testTestWithDep() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "testWithDep"); AndroidProject model = projectData.model; Collection<Variant> variants = model.getVariants(); Variant debugVariant = getVariant(variants, DEBUG); assertNotNull(debugVariant); Collection<AndroidArtifact> extraAndroidArtifact = debugVariant.getExtraAndroidArtifacts(); AndroidArtifact testArtifact = getAndroidArtifact(extraAndroidArtifact, ARTIFACT_ANDROID_TEST); assertNotNull(testArtifact); Dependencies testDependencies = testArtifact.getDependencies(); assertEquals(1, testDependencies.getJavaLibraries().size()); } public void testLibTestDep() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "libTestDep"); AndroidProject model = projectData.model; Collection<Variant> variants = model.getVariants(); Variant debugVariant = getVariant(variants, DEBUG); assertNotNull(debugVariant); Collection<AndroidArtifact> extraAndroidArtifact = debugVariant.getExtraAndroidArtifacts(); AndroidArtifact testArtifact = getAndroidArtifact(extraAndroidArtifact, ARTIFACT_ANDROID_TEST); assertNotNull(testArtifact); Dependencies testDependencies = testArtifact.getDependencies(); Collection<JavaLibrary> javaLibraries = testDependencies.getJavaLibraries(); assertEquals(2, javaLibraries.size()); for (JavaLibrary lib : javaLibraries) { File f = lib.getJarFile(); assertTrue(f.getName().equals("guava-11.0.2.jar") || f.getName().equals("jsr305-1.3.9.jar")); } } public void testRsSupportMode() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "rsSupportMode"); AndroidProject model = projectData.model; File projectDir = projectData.projectDir; Variant debugVariant = getVariant(model.getVariants(), "x86Debug"); assertNotNull("x86Debug variant null-check", debugVariant); AndroidArtifact mainArtifact = debugVariant.getMainArtifact(); Dependencies dependencies = mainArtifact.getDependencies(); assertFalse(dependencies.getJavaLibraries().isEmpty()); boolean foundSupportJar = false; for (JavaLibrary lib : dependencies.getJavaLibraries()) { File file = lib.getJarFile(); if (SdkConstants.FN_RENDERSCRIPT_V8_JAR.equals(file.getName())) { foundSupportJar = true; break; } } assertTrue("Found suppport jar check", foundSupportJar); } public void testGenFolderApi() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "genFolderApi"); AndroidProject model = projectData.model; File projectDir = projectData.projectDir; File buildDir = new File(projectDir, "build"); for (Variant variant : model.getVariants()) { AndroidArtifact mainInfo = variant.getMainArtifact(); assertNotNull( "Null-check on mainArtifactInfo for " + variant.getDisplayName(), mainInfo); // get the generated source folders. Collection<File> genFolder = mainInfo.getGeneratedSourceFolders(); // We're looking for a custom folder String folderStart = new File(buildDir, "customCode").getAbsolutePath() + File.separatorChar; boolean found = false; for (File f : genFolder) { if (f.getAbsolutePath().startsWith(folderStart)) { found = true; break; } } assertTrue("custom generated source folder check", found); } } public void testGenFolderApi2() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_MANUAL, "genFolderApi2"); AndroidProject model = projectData.model; File projectDir = projectData.projectDir; File buildDir = new File(projectDir, "build"); for (Variant variant : model.getVariants()) { AndroidArtifact mainInfo = variant.getMainArtifact(); assertNotNull( "Null-check on mainArtifactInfo for " + variant.getDisplayName(), mainInfo); // get the generated source folders. Collection<File> genFolder = mainInfo.getGeneratedSourceFolders(); // We're looking for a custom folder String folderStart = new File(buildDir, "customCode").getAbsolutePath() + File.separatorChar; boolean found = false; for (File f : genFolder) { if (f.getAbsolutePath().startsWith(folderStart)) { found = true; break; } } assertTrue("custom generated source folder check", found); } } public void testArtifactApi() throws Exception { // Load the custom model for the project ProjectData projectData = getModelForProject(FOLDER_TEST_MANUAL, "artifactApi"); AndroidProject model = projectData.model; // check the Artifact Meta Data Collection<ArtifactMetaData> extraArtifacts = model.getExtraArtifacts(); assertNotNull("Extra artifact collection null-check", extraArtifacts); assertEquals("Extra artifact size check", 2, extraArtifacts.size()); assertNotNull("instrument test metadata null-check", getArtifactMetaData(extraArtifacts, ARTIFACT_ANDROID_TEST)); // get the custom one. ArtifactMetaData extraArtifactMetaData = getArtifactMetaData(extraArtifacts, "__test__"); assertNotNull("custom extra metadata null-check", extraArtifactMetaData); assertFalse("custom extra meta data is Test check", extraArtifactMetaData.isTest()); assertEquals("custom extra meta data type check", ArtifactMetaData.TYPE_JAVA, extraArtifactMetaData.getType()); // check the extra source provider on the build Types. for (BuildTypeContainer btContainer : model.getBuildTypes()) { String name = btContainer.getBuildType().getName(); Collection<SourceProviderContainer> extraSourceProviderContainers = btContainer.getExtraSourceProviders(); assertNotNull( "Extra source provider containers for build type '" + name + "' null-check", extraSourceProviderContainers); assertEquals( "Extra source provider containers for build type size '" + name + "' check", 1, extraSourceProviderContainers.size()); SourceProviderContainer sourceProviderContainer = extraSourceProviderContainers.iterator().next(); assertNotNull( "Extra artifact source provider for " + name + " null check", sourceProviderContainer); assertEquals( "Extra artifact source provider for " + name + " name check", "__test__", sourceProviderContainer.getArtifactName()); assertEquals( "Extra artifact source provider for " + name + " value check", "buildType:" + name, sourceProviderContainer.getSourceProvider().getManifestFile().getPath()); } // check the extra source provider on the product flavors. for (ProductFlavorContainer pfContainer : model.getProductFlavors()) { String name = pfContainer.getProductFlavor().getName(); Collection<SourceProviderContainer> extraSourceProviderContainers = pfContainer.getExtraSourceProviders(); assertNotNull( "Extra source provider container for product flavor '" + name + "' null-check", extraSourceProviderContainers); assertEquals( "Extra artifact source provider container for product flavor size '" + name + "' check", 2, extraSourceProviderContainers.size()); assertNotNull( "Extra source provider container for product flavor '" + name + "': instTest check", getSourceProviderContainer(extraSourceProviderContainers, ARTIFACT_ANDROID_TEST)); SourceProviderContainer sourceProviderContainer = getSourceProviderContainer( extraSourceProviderContainers, "__test__"); assertNotNull( "Custom source provider container for " + name + " null check", sourceProviderContainer); assertEquals( "Custom artifact source provider for " + name + " name check", "__test__", sourceProviderContainer.getArtifactName()); assertEquals( "Extra artifact source provider for " + name + " value check", "productFlavor:" + name, sourceProviderContainer.getSourceProvider().getManifestFile().getPath()); } // check the extra artifacts on the variants for (Variant variant : model.getVariants()) { String name = variant.getName(); Collection<JavaArtifact> javaArtifacts = variant.getExtraJavaArtifacts(); assertEquals(1, javaArtifacts.size()); JavaArtifact javaArtifact = javaArtifacts.iterator().next(); assertEquals("__test__", javaArtifact.getName()); assertEquals("assemble:" + name, javaArtifact.getAssembleTaskName()); assertEquals("compile:" + name, javaArtifact.getJavaCompileTaskName()); assertEquals(new File("classesFolder:" + name), javaArtifact.getClassesFolder()); SourceProvider variantSourceProvider = javaArtifact.getVariantSourceProvider(); assertNotNull(variantSourceProvider); assertEquals("provider:" + name, variantSourceProvider.getManifestFile().getPath()); Dependencies deps = javaArtifact.getDependencies(); assertNotNull("java artifact deps null-check", deps); assertFalse(deps.getJavaLibraries().isEmpty()); } } public void testCustomArtifact() throws Exception { // Load the custom model for the projects Map<String, ProjectData> map = getModelForMultiProject(FOLDER_TEST_MANUAL, "customArtifactDep"); ProjectData appModelData = map.get(":app"); assertNotNull("Module app null-check", appModelData); AndroidProject model = appModelData.model; Collection<Variant> variants = model.getVariants(); assertEquals("Variant count", 2, variants.size()); Variant variant = getVariant(variants, "release"); assertNotNull("release variant null-check", variant); AndroidArtifact mainInfo = variant.getMainArtifact(); assertNotNull("Main Artifact null-check", mainInfo); Dependencies dependencies = mainInfo.getDependencies(); assertNotNull("Dependencies null-check", dependencies); Collection<String> projects = dependencies.getProjects(); assertNotNull("project dep list null-check", projects); assertTrue("project dep empty check", projects.isEmpty()); Collection<JavaLibrary> javaLibraries = dependencies.getJavaLibraries(); assertNotNull("jar dep list null-check", javaLibraries); assertEquals("jar dep count", 1, javaLibraries.size()); } public void testLocalJarInLib() throws Exception { Map<String, ProjectData> map = getModelForMultiProject(FOLDER_TEST_REGULAR, "localJars"); ProjectData libModelData = map.get(":baseLibrary"); assertNotNull("Module app null-check", libModelData); AndroidProject model = libModelData.model; Collection<Variant> variants = model.getVariants(); Variant releaseVariant = getVariant(variants, "release"); assertNotNull(releaseVariant); Dependencies dependencies = releaseVariant.getMainArtifact().getDependencies(); assertNotNull(dependencies); Collection<JavaLibrary> javaLibraries = dependencies.getJavaLibraries(); assertNotNull(javaLibraries); // com.google.guava:guava:11.0.2 // \--- com.google.code.findbugs:jsr305:1.3.9 // + the local jar assertEquals(3, javaLibraries.size()); } public void testOutputFileNameUniquenessInApp() throws Exception { ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "basic"); // make sure that debug and release variant file output have different names. compareDebugAndReleaseOutput(projectData); } public void testOutputFileNameUniquenessInLib() throws Exception { ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "libTestDep"); // make sure that debug and release variant file output have different names. compareDebugAndReleaseOutput(projectData); } private static void compareDebugAndReleaseOutput(ProjectData projectData) { AndroidProject model = projectData.model; Collection<Variant> variants = model.getVariants(); assertEquals("Variant Count", 2, variants.size()); // debug variant Variant debugVariant = getVariant(variants, DEBUG); assertNotNull("debug Variant null-check", debugVariant); // debug artifact AndroidArtifact debugMainInfo = debugVariant.getMainArtifact(); assertNotNull("Debug main info null-check", debugMainInfo); Collection<AndroidArtifactOutput> debugMainOutputs = debugMainInfo.getOutputs(); assertNotNull("Debug main output null-check", debugMainOutputs); // release variant Variant releaseVariant = getVariant(variants, "release"); assertNotNull("release Variant null-check", releaseVariant); AndroidArtifact relMainInfo = releaseVariant.getMainArtifact(); assertNotNull("Release main info null-check", relMainInfo); Collection<AndroidArtifactOutput> relMainOutputs = relMainInfo.getOutputs(); assertNotNull("Rel Main output null-check", relMainOutputs); File debugFile = debugMainOutputs.iterator().next().getMainOutputFile().getOutputFile(); File releaseFile = relMainOutputs.iterator().next().getMainOutputFile().getOutputFile(); assertFalse("debug: " + debugFile + " / release: " + releaseFile, debugFile.equals(releaseFile)); } public void testAbiFilters() throws Exception { ProjectData projectData = getModelForProject(FOLDER_TEST_REGULAR, "ndkPrebuilts"); AndroidProject model = projectData.model; Collection<Variant> variants = model.getVariants(); assertEquals("Variant Count", 6, variants.size()); // flavor names to ABIs // create a temp list to make the compiler happy. generics are fun! List<String> ls1 = ImmutableList.of("x86"); Map<String, List<String>> map = ImmutableMap.of( "x86", ls1, "arm", ImmutableList.of("armeabi-v7a", "armeabi"), "mips", ImmutableList.of("mips")); // loop on the variants for (Variant variant : variants) { String variantName = variant.getName(); // get the flavor name to get the expected ABIs. List<String> flavors = variant.getProductFlavors(); assertNotNull("Null check flavors for " + variantName, flavors); assertEquals("Size check flavors for " + variantName, 1, flavors.size()); List<String> expectedAbis = map.get(flavors.get(0)); Set<String> actualAbis = variant.getMainArtifact().getAbiFilters(); assertNotNull("Null check artifact abi for " + variantName, actualAbis); assertEquals("Size check artifact abis for " + variantName, expectedAbis.size(), actualAbis.size()); for (String abi : expectedAbis) { assertTrue("Check " + abi + " present in artifact abi for " + variantName, actualAbis.contains(abi)); } } } /** * Returns the SDK folder as built from the Android source tree. * @return the SDK */ protected File getSdkDir() { String androidHome = System.getenv("ANDROID_HOME"); if (androidHome != null) { File f = new File(androidHome); if (f.isDirectory()) { return f; } } throw new IllegalStateException("SDK not defined with ANDROID_HOME"); } /** * Returns the SDK folder as built from the Android source tree. */ protected static File getNdkDir() { String androidHome = System.getenv("ANDROID_NDK_HOME"); if (androidHome != null) { File f = new File(androidHome); if (f.isDirectory()) { return f; } else { System.out.println("Failed to find NDK in ANDROID_NDK_HOME=" + androidHome); } } return null; } /** * Returns the root dir for the gradle plugin project */ private File getRootDir() { CodeSource source = getClass().getProtectionDomain().getCodeSource(); if (source != null) { URL location = source.getLocation(); try { File dir = new File(location.toURI()); assertTrue(dir.getPath(), dir.exists()); File f; if (System.getenv("IDE_MODE") != null) { f = dir.getParentFile().getParentFile().getParentFile(); f = new File(f, "build-system"); } else { f = dir.getParentFile().getParentFile().getParentFile().getParentFile().getParentFile().getParentFile().getParentFile(); f = new File(f, "tools" + File.separator + "base" + File.separator + "build-system"); } return f; } catch (URISyntaxException e) { fail(e.getLocalizedMessage()); } } fail("Fail to get the tools/build folder"); return null; } /** * Returns the root folder for the tests projects. */ private File getTestDir(@NonNull String testFolder) { File rootDir = getRootDir(); return new File(new File(rootDir, "tests"), testFolder); } @Nullable private static Variant getVariant( @NonNull Collection<Variant> items, @NonNull String name) { for (Variant item : items) { if (name.equals(item.getName())) { return item; } } return null; } @Nullable private static ProductFlavorContainer getProductFlavor( @NonNull Collection<ProductFlavorContainer> items, @NonNull String name) { for (ProductFlavorContainer item : items) { assertNotNull("ProductFlavorContainer list item null-check:" + name, item); assertNotNull("ProductFlavorContainer.getProductFlavor() list item null-check: " + name, item.getProductFlavor()); assertNotNull("ProductFlavorContainer.getProductFlavor().getName() list item null-check: " + name, item.getProductFlavor().getName()); if (name.equals(item.getProductFlavor().getName())) { return item; } } return null; } @Nullable private static ArtifactMetaData getArtifactMetaData( @NonNull Collection<ArtifactMetaData> items, @NonNull String name) { for (ArtifactMetaData item : items) { assertNotNull("ArtifactMetaData list item null-check:" + name, item); assertNotNull("ArtifactMetaData.getName() list item null-check: " + name, item.getName()); if (name.equals(item.getName())) { return item; } } return null; } @Nullable private static AndroidArtifact getAndroidArtifact( @NonNull Collection<AndroidArtifact> items, @NonNull String name) { for (AndroidArtifact item : items) { assertNotNull("AndroidArtifact list item null-check:" + name, item); assertNotNull("AndroidArtifact.getName() list item null-check: " + name, item.getName()); if (name.equals(item.getName())) { return item; } } return null; } @Nullable private static SigningConfig getSigningConfig( @NonNull Collection<SigningConfig> items, @NonNull String name) { for (SigningConfig item : items) { assertNotNull("SigningConfig list item null-check:" + name, item); assertNotNull("SigningConfig.getName() list item null-check: " + name, item.getName()); if (name.equals(item.getName())) { return item; } } return null; } @Nullable private static SourceProviderContainer getSourceProviderContainer( @NonNull Collection<SourceProviderContainer> items, @NonNull String name) { for (SourceProviderContainer item : items) { assertNotNull("SourceProviderContainer list item null-check:" + name, item); assertNotNull("SourceProviderContainer.getName() list item null-check: " + name, item.getArtifactName()); if (name.equals(item.getArtifactName())) { return item; } } return null; } private static final class ProductFlavorTester { @NonNull private final ProductFlavor productFlavor; @NonNull private final String name; private String applicationId = null; private Integer versionCode = null; private String versionName = null; private ApiVersion minSdkVersion = null; private ApiVersion targetSdkVersion = null; private Integer renderscriptTargetApi = null; private String testApplicationId = null; private String testInstrumentationRunner = null; private Boolean testHandleProfiling = null; private Boolean testFunctionalTest = null; ProductFlavorTester(@NonNull ProductFlavor productFlavor, @NonNull String name) { this.productFlavor = productFlavor; this.name = name; } ProductFlavorTester setApplicationId(String applicationId) { this.applicationId = applicationId; return this; } ProductFlavorTester setVersionCode(Integer versionCode) { this.versionCode = versionCode; return this; } ProductFlavorTester setVersionName(String versionName) { this.versionName = versionName; return this; } ProductFlavorTester setMinSdkVersion(int minSdkVersion) { this.minSdkVersion = new DefaultApiVersion(minSdkVersion); return this; } ProductFlavorTester setTargetSdkVersion(int targetSdkVersion) { this.targetSdkVersion = new DefaultApiVersion(targetSdkVersion); return this; } ProductFlavorTester setRenderscriptTargetApi(Integer renderscriptTargetApi) { this.renderscriptTargetApi = renderscriptTargetApi; return this; } ProductFlavorTester setTestApplicationId(String testApplicationId) { this.testApplicationId = testApplicationId; return this; } ProductFlavorTester setTestInstrumentationRunner(String testInstrumentationRunner) { this.testInstrumentationRunner = testInstrumentationRunner; return this; } ProductFlavorTester setTestHandleProfiling(Boolean testHandleProfiling) { this.testHandleProfiling = testHandleProfiling; return this; } ProductFlavorTester setTestFunctionalTest(Boolean testFunctionalTest) { this.testFunctionalTest = testFunctionalTest; return this; } void test() { assertEquals(name + ":applicationId", applicationId, productFlavor.getApplicationId()); assertEquals(name + ":VersionCode", versionCode, productFlavor.getVersionCode()); assertEquals(name + ":VersionName", versionName, productFlavor.getVersionName()); assertEquals(name + ":minSdkVersion", minSdkVersion, productFlavor.getMinSdkVersion()); assertEquals(name + ":targetSdkVersion", targetSdkVersion, productFlavor.getTargetSdkVersion()); assertEquals(name + ":renderscriptTargetApi", renderscriptTargetApi, productFlavor.getRenderscriptTargetApi()); assertEquals(name + ":testApplicationId", testApplicationId, productFlavor.getTestApplicationId()); assertEquals(name + ":testInstrumentationRunner", testInstrumentationRunner, productFlavor.getTestInstrumentationRunner()); assertEquals(name + ":testHandleProfiling", testHandleProfiling, productFlavor.getTestHandleProfiling()); assertEquals(name + ":testFunctionalTest", testFunctionalTest, productFlavor.getTestFunctionalTest()); } } private static final class SourceProviderTester { @NonNull private final String projectName; @NonNull private final String configName; @NonNull private final SourceProvider sourceProvider; @NonNull private final File projectDir; private String javaDir; private String resourcesDir; private String manifestFile; private String resDir; private String assetsDir; private String aidlDir; private String renderscriptDir; private String jniDir; SourceProviderTester(@NonNull String projectName, @NonNull File projectDir, @NonNull String configName, @NonNull SourceProvider sourceProvider) { this.projectName = projectName; this.projectDir = projectDir; this.configName = configName; this.sourceProvider = sourceProvider; // configure tester with default relative paths setJavaDir("src/" + configName + "/java"); setResourcesDir("src/" + configName + "/resources"); setManifestFile("src/" + configName + "/AndroidManifest.xml"); setResDir("src/" + configName + "/res"); setAssetsDir("src/" + configName + "/assets"); setAidlDir("src/" + configName + "/aidl"); setRenderscriptDir("src/" + configName + "/rs"); setJniDir("src/" + configName + "/jni"); } SourceProviderTester setJavaDir(String javaDir) { this.javaDir = javaDir; return this; } SourceProviderTester setResourcesDir(String resourcesDir) { this.resourcesDir = resourcesDir; return this; } SourceProviderTester setManifestFile(String manifestFile) { this.manifestFile = manifestFile; return this; } SourceProviderTester setResDir(String resDir) { this.resDir = resDir; return this; } SourceProviderTester setAssetsDir(String assetsDir) { this.assetsDir = assetsDir; return this; } SourceProviderTester setAidlDir(String aidlDir) { this.aidlDir = aidlDir; return this; } SourceProviderTester setRenderscriptDir(String renderscriptDir) { this.renderscriptDir = renderscriptDir; return this; } SourceProviderTester setJniDir(String jniDir) { this.jniDir = jniDir; return this; } void test() { testSinglePathCollection("java", javaDir, sourceProvider.getJavaDirectories()); testSinglePathCollection("resources", resourcesDir, sourceProvider.getResourcesDirectories()); testSinglePathCollection("res", resDir, sourceProvider.getResDirectories()); testSinglePathCollection("assets", assetsDir, sourceProvider.getAssetsDirectories()); testSinglePathCollection("aidl", aidlDir, sourceProvider.getAidlDirectories()); testSinglePathCollection("rs", renderscriptDir, sourceProvider.getRenderscriptDirectories()); testSinglePathCollection("jni", jniDir, sourceProvider.getCDirectories()); assertEquals("AndroidManifest", new File(projectDir, manifestFile).getAbsolutePath(), sourceProvider.getManifestFile().getAbsolutePath()); } private void testSinglePathCollection( @NonNull String setName, @NonNull String referencePath, @NonNull Collection<File> pathSet) { assertEquals(1, pathSet.size()); assertEquals(projectName + ": " + configName + "/" + setName, new File(projectDir, referencePath).getAbsolutePath(), pathSet.iterator().next().getAbsolutePath()); } } private static final class VariantTester { private final Variant variant; private final File projectDir; private final String outputFileName; VariantTester(Variant variant, File projectDir, String outputFileName) { this.variant = variant; this.projectDir = projectDir; this.outputFileName = outputFileName; } void test() { AndroidArtifact artifact = variant.getMainArtifact(); assertNotNull("Main Artifact null-check", artifact); String variantName = variant.getName(); File build = new File(projectDir, "build"); File apk = new File(build, "outputs/apk/" + outputFileName); Collection<File> sourceFolders = artifact.getGeneratedSourceFolders(); assertEquals("Gen src Folder count", 4, sourceFolders.size()); Collection<AndroidArtifactOutput> outputs = artifact.getOutputs(); assertNotNull(outputs); assertEquals(1, outputs.size()); AndroidArtifactOutput output = outputs.iterator().next(); assertEquals(variantName + " output", apk, output.getMainOutputFile().getOutputFile()); File manifest = output.getGeneratedManifest(); assertNotNull(manifest); } } private static final class SigningConfigTester { public static final String DEFAULT_PASSWORD = "android"; public static final String DEFAULT_ALIAS = "AndroidDebugKey"; @NonNull private final SigningConfig signingConfig; @NonNull private final String name; private File storeFile = null; private String storePassword = null; private String keyAlias = null; private String keyPassword = null; private String storeType = KeyStore.getDefaultType(); private boolean isSigningReady = false; SigningConfigTester(@NonNull SigningConfig signingConfig, @NonNull String name, boolean isDebug) throws AndroidLocation.AndroidLocationException { assertNotNull(String.format("SigningConfig '%s' null-check", name), signingConfig); this.signingConfig = signingConfig; this.name = name; if (isDebug) { storeFile = new File(KeystoreHelper.defaultDebugKeystoreLocation()); storePassword = DEFAULT_PASSWORD; keyAlias = DEFAULT_ALIAS; keyPassword = DEFAULT_PASSWORD; isSigningReady = true; } } SigningConfigTester setStoreFile(File storeFile) { this.storeFile = storeFile; return this; } SigningConfigTester setStorePassword(String storePassword) { this.storePassword = storePassword; return this; } SigningConfigTester setKeyAlias(String keyAlias) { this.keyAlias = keyAlias; return this; } SigningConfigTester setKeyPassword(String keyPassword) { this.keyPassword = keyPassword; return this; } SigningConfigTester setStoreType(String storeType) { this.storeType = storeType; return this; } SigningConfigTester setSigningReady(boolean isSigningReady) { this.isSigningReady = isSigningReady; return this; } void test() { assertEquals("SigningConfig name", name, signingConfig.getName()); assertEquals(String.format("SigningConfig '%s' storeFile", name), storeFile, signingConfig.getStoreFile()); assertEquals(String.format("SigningConfig '%s' storePassword", name), storePassword, signingConfig.getStorePassword()); String scAlias = signingConfig.getKeyAlias(); assertEquals(String.format("SigningConfig '%s' keyAlias", name), keyAlias != null ? keyAlias.toLowerCase(Locale.getDefault()) : keyAlias, scAlias != null ? scAlias.toLowerCase(Locale.getDefault()) : scAlias); assertEquals(String.format("SigningConfig '%s' keyPassword", name), keyPassword, signingConfig.getKeyPassword()); assertEquals(String.format("SigningConfig '%s' storeType", name), storeType, signingConfig.getStoreType()); assertEquals(String.format("SigningConfig '%s' isSigningReady", name), isSigningReady, signingConfig.isSigningReady()); } } }