diff --git a/build.gradle.kts b/build.gradle.kts index 5023f5043000..e592deac3b1a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,6 +20,7 @@ import org.gradle.gradlebuild.ProjectGroups.javaProjects import org.gradle.gradlebuild.ProjectGroups.kotlinJsProjects import org.gradle.gradlebuild.ProjectGroups.pluginProjects import org.gradle.gradlebuild.ProjectGroups.publicJavaProjects +import org.gradle.gradlebuild.UpdateAgpVersions import org.gradle.gradlebuild.UpdateBranchStatus import org.gradle.gradlebuild.buildquality.incubation.IncubatingApiAggregateReportTask import org.gradle.gradlebuild.buildquality.incubation.IncubatingApiReportTask @@ -390,6 +391,12 @@ tasks.register("installAll") { tasks.register("updateBranchStatus") +tasks.register("updateAgpVersions") { + comment.set(" Generated - Update by running `./gradlew updateAgpVersions`") + minimumSupportedMinor.set("3.4") + propertiesFile.set(layout.projectDirectory.file("gradle/dependency-management/agp-versions.properties")) +} + fun distributionImage(named: String) = project(":distributions").property(named) as CopySpec diff --git a/buildSrc/subprojects/plugins/src/main/kotlin/org/gradle/gradlebuild/UpdateAgpVersions.kt b/buildSrc/subprojects/plugins/src/main/kotlin/org/gradle/gradlebuild/UpdateAgpVersions.kt new file mode 100644 index 000000000000..0d2e7044dfad --- /dev/null +++ b/buildSrc/subprojects/plugins/src/main/kotlin/org/gradle/gradlebuild/UpdateAgpVersions.kt @@ -0,0 +1,86 @@ +/* + * Copyright 2020 the original author or authors. + * + * 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 org.gradle.gradlebuild + +import org.gradle.api.DefaultTask +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.TaskAction +import org.gradle.build.ReproduciblePropertiesWriter +import org.w3c.dom.Element +import java.util.Properties +import javax.xml.parsers.DocumentBuilderFactory + + +/** + * Fetch the latest AGP versions and write a properties file. + * Never up-to-date, non-cacheable. + */ +abstract class UpdateAgpVersions : DefaultTask() { + + @get:Internal + abstract val comment: Property + + @get:Internal + abstract val minimumSupportedMinor: Property + + @get:Internal + abstract val propertiesFile: RegularFileProperty + + @TaskAction + fun fetch() { + + val dbf = DocumentBuilderFactory.newInstance() + val latests = dbf.fetchLatests(minimumSupportedMinor.get()) + val nightly = dbf.fetchNightly() + val properties = Properties().apply { + setProperty("latests", latests.joinToString(",")) + setProperty("nightly", nightly) + } + ReproduciblePropertiesWriter.store( + properties, + propertiesFile.get().asFile, + comment.get() + ) + } + + private + fun DocumentBuilderFactory.fetchLatests(minimumSupported: String): List { + var latests = fetchVersionsFromMavenMetadata("https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/maven-metadata.xml") + .groupBy { it.take(3) } + .map { (_, versions) -> versions.first() } + latests = (latests + minimumSupported).sorted() + latests = latests.subList(latests.indexOf(minimumSupported) + 1, latests.size) + return latests + } + + private + fun DocumentBuilderFactory.fetchNightly(): String = + fetchVersionsFromMavenMetadata("https://repo.gradle.org/gradle/ext-snapshots-local/com/android/tools/build/gradle/maven-metadata.xml") + .first() + + private + fun DocumentBuilderFactory.fetchVersionsFromMavenMetadata(url: String): List = + newDocumentBuilder() + .parse(url) + .getElementsByTagName("version").let { versions -> + (0 until versions.length) + .map { idx -> (versions.item(idx) as Element).textContent } + .reversed() + } +} diff --git a/gradle/dependency-management/agp-versions.properties b/gradle/dependency-management/agp-versions.properties new file mode 100644 index 000000000000..33ed22bbffe9 --- /dev/null +++ b/gradle/dependency-management/agp-versions.properties @@ -0,0 +1,3 @@ +# Generated - Update by running `./gradlew updateAgpVersions` +latests=3.4.2,3.5.3,3.6.0-rc01,4.0.0-alpha09 +nightly=4.0.0-20200121203636+0000 diff --git a/released-versions.json b/released-versions.json index f84fa1d61480..60a2d7776336 100644 --- a/released-versions.json +++ b/released-versions.json @@ -1,7 +1,7 @@ { "latestReleaseSnapshot": { - "version": "6.1.1-20200122000153+0000", - "buildTime": "20200122000153+0000" + "version": "6.1.1-20200124000049+0000", + "buildTime": "20200124000049+0000" }, "latestRc": { "version": "6.1-rc-3", diff --git a/subprojects/core-api/src/main/java/org/gradle/api/provider/Property.java b/subprojects/core-api/src/main/java/org/gradle/api/provider/Property.java index 76194482206c..5e8cb963dfa2 100644 --- a/subprojects/core-api/src/main/java/org/gradle/api/provider/Property.java +++ b/subprojects/core-api/src/main/java/org/gradle/api/provider/Property.java @@ -83,12 +83,12 @@ public interface Property extends Provider, HasConfigurableValue { /** * Specifies the value to use as the convention for this property. The convention is used when no value has been set for this property. * - * @param value The value. + * @param value The value, or null if the convention is that the property should have no value. * @return this * @since 5.1 */ @Incubating - Property convention(T value); + Property convention(@Nullable T value); /** * Specifies the provider of the value to use as the convention for this property. The convention is used when no value has been set for this property. diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalBuildIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalBuildIntegrationTest.groovy index 60619bab242b..d10a7ad99df1 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalBuildIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/IncrementalBuildIntegrationTest.groovy @@ -1392,7 +1392,6 @@ task generate(type: TransformerTask) { outputFile.text == 'second' } - @ToBeImplemented @Issue("https://github.com/gradle/gradle/issues/11805") def "Groovy property annotated as @Internal with differently annotated getter emits warning about conflicting annotations"() { def inputFile = file("input.txt") @@ -1425,21 +1424,24 @@ task generate(type: TransformerTask) { """ when: + executer.expectDeprecationWarning() run "custom" then: executedAndNotSkipped ":custom" + outputContains("Property 'classpath' annotated with @Internal should not be also annotated with @InputFiles, @Classpath. This behaviour has been deprecated and is scheduled to be removed in Gradle 7.0.") when: + executer.expectDeprecationWarning() run "custom" then: skipped ":custom" when: + executer.expectDeprecationWarning() inputFile.text = "changed" run "custom" then: - // FIXME This should execute instead of being skipped, or emit a warning skipped ":custom" } } diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskDependencyInferenceIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskDependencyInferenceIntegrationTest.groovy index 0b3ee572f8e4..41319e038aad 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskDependencyInferenceIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskDependencyInferenceIntegrationTest.groovy @@ -113,7 +113,7 @@ class TaskDependencyInferenceIntegrationTest extends AbstractIntegrationSpec imp buildFile << """ def task = tasks.create("a", FileProducer) { output = file("a.txt") - } + } tasks.register("b") { dependsOn task.output.map { throw new RuntimeException() } } @@ -488,7 +488,7 @@ The following types/formats are supported: then: failure.assertHasDescription("Could not determine the dependencies of task ':a'.") - failure.assertHasCause("No value has been specified for this property.") + failure.assertHasCause("Cannot query the value of this property because it has no value available.") } def "input file collection containing task provider implies dependency on all outputs of the task"() { @@ -563,7 +563,7 @@ The following types/formats are supported: buildFile << """ def taskA = tasks.create("a", FileProducer) { output = file("a.txt") - content = "a" + content = "a" } def taskB = tasks.create("b", FileProducer) { output = file("b.txt") @@ -589,7 +589,7 @@ The following types/formats are supported: buildFile << """ def taskA = tasks.create("a", FileProducer) { output = file("a.txt") - content = "a" + content = "a" } tasks.register("c", InputFileTask) { inFile = taskA.output.orElse(file("b.txt")) @@ -779,7 +779,7 @@ The following types/formats are supported: } configurations { thing } dependencies { thing a.outputs.files } - + tasks.register("b", InputFilesTask) { inFiles.from configurations.named('thing') outFile = file("out.txt") diff --git a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskPropertiesIntegrationTest.groovy b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskPropertiesIntegrationTest.groovy index 7990b18702e3..95458094e59d 100644 --- a/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskPropertiesIntegrationTest.groovy +++ b/subprojects/core/src/integTest/groovy/org/gradle/api/tasks/TaskPropertiesIntegrationTest.groovy @@ -25,13 +25,13 @@ class TaskPropertiesIntegrationTest extends AbstractIntegrationSpec { abstract class MyTask extends DefaultTask { @Internal abstract Property getCount() - + @TaskAction void go() { println("count = \${count.get()}") } } - + tasks.create("thing", MyTask) { println("property = \$count") count = 12 @@ -52,13 +52,13 @@ class TaskPropertiesIntegrationTest extends AbstractIntegrationSpec { abstract class MyTask extends DefaultTask { @Internal abstract Property getCount() - + @TaskAction void go() { println("count = \${count.get()}") } } - + tasks.create("thing", MyTask) { } """ @@ -67,7 +67,7 @@ class TaskPropertiesIntegrationTest extends AbstractIntegrationSpec { fails("thing") then: - failure.assertHasCause("No value has been specified for task ':thing' property 'count'") + failure.assertHasCause("Cannot query the value of task ':thing' property 'count' because it has no value available.") } def "reports failure to query read-only unmanaged Property with final getter"() { @@ -76,13 +76,13 @@ class TaskPropertiesIntegrationTest extends AbstractIntegrationSpec { abstract class MyTask extends DefaultTask { @Internal final Property count = project.objects.property(Integer) - + @TaskAction void go() { println("count = \${count.get()}") } } - + tasks.create("thing", MyTask) { println("property = \$count") } @@ -93,7 +93,7 @@ class TaskPropertiesIntegrationTest extends AbstractIntegrationSpec { then: outputContains("property = task ':thing' property 'count'") - failure.assertHasCause("No value has been specified for task ':thing' property 'count'") + failure.assertHasCause("Cannot query the value of task ':thing' property 'count' because it has no value available.") } def "reports failure to query read-only unmanaged Property"() { @@ -105,7 +105,7 @@ class TaskPropertiesIntegrationTest extends AbstractIntegrationSpec { public abstract class MyTask extends DefaultTask { private final Property count = getProject().getObjects().property(Integer.class); - + @Internal public Property getCount() { return count; @@ -118,7 +118,7 @@ class TaskPropertiesIntegrationTest extends AbstractIntegrationSpec { } """ - buildFile << """ + buildFile << """ tasks.create("thing", MyTask) { println("property = \$count") } @@ -129,7 +129,7 @@ class TaskPropertiesIntegrationTest extends AbstractIntegrationSpec { then: outputContains("property = task ':thing' property 'count'") - failure.assertHasCause("No value has been specified for task ':thing' property 'count'") + failure.assertHasCause("Cannot query the value of task ':thing' property 'count' because it has no value available.") } def "can define task with abstract read-only ConfigurableFileCollection property"() { @@ -138,13 +138,13 @@ class TaskPropertiesIntegrationTest extends AbstractIntegrationSpec { abstract class MyTask extends DefaultTask { @InputFiles abstract ConfigurableFileCollection getSource() - + @TaskAction void go() { println("files = \${source.files.name}") } } - + tasks.create("thing", MyTask) { source.from("a", "b", "c") } @@ -163,13 +163,13 @@ class TaskPropertiesIntegrationTest extends AbstractIntegrationSpec { abstract class MyTask extends DefaultTask { @InputFiles abstract ConfigurableFileTree getSource() - + @TaskAction void go() { println("files = \${source.files.name.sort()}") } } - + tasks.create("thing", MyTask) { source.from("dir") } @@ -197,17 +197,17 @@ class TaskPropertiesIntegrationTest extends AbstractIntegrationSpec { this.name = name } } - + abstract class MyTask extends DefaultTask { @Nested abstract NamedDomainObjectContainer getBeans() - + @TaskAction void go() { println("beans = \${beans.collect { it.prop.get() } }") } } - + tasks.create("thing", MyTask) { beans { one { prop = '1' } @@ -230,17 +230,17 @@ class TaskPropertiesIntegrationTest extends AbstractIntegrationSpec { @Input String prop } - + abstract class MyTask extends DefaultTask { @Nested abstract DomainObjectSet getBeans() - + @TaskAction void go() { println("beans = \${beans.collect { it.prop } }") } } - + tasks.create("thing", MyTask) { beans.add(new Bean(prop: '1')) beans.add(new Bean(prop: '2')) @@ -264,13 +264,13 @@ class TaskPropertiesIntegrationTest extends AbstractIntegrationSpec { abstract class MyTask extends DefaultTask { @Nested abstract Params getParams() - + @TaskAction void go() { println("count = \${params.count.get()}") } } - + tasks.create("thing", MyTask) { println("params = \$params") println("params.count = \$params.count") @@ -293,17 +293,17 @@ class TaskPropertiesIntegrationTest extends AbstractIntegrationSpec { abstract class MyTask extends DefaultTask { @Internal abstract Property getParam() - + MyTask() { param.convention("from convention") } - + @TaskAction void go() { println("param = \${param.get()}") } } - + tasks.create("thing", MyTask) { param.set("from configuration") } diff --git a/subprojects/core/src/main/java/org/gradle/api/internal/DefaultNamedDomainObjectCollection.java b/subprojects/core/src/main/java/org/gradle/api/internal/DefaultNamedDomainObjectCollection.java index 3f80227307f1..8acb8739d4aa 100644 --- a/subprojects/core/src/main/java/org/gradle/api/internal/DefaultNamedDomainObjectCollection.java +++ b/subprojects/core/src/main/java/org/gradle/api/internal/DefaultNamedDomainObjectCollection.java @@ -32,7 +32,7 @@ import org.gradle.api.internal.collections.CollectionFilter; import org.gradle.api.internal.collections.ElementSource; import org.gradle.api.internal.plugins.DslObject; -import org.gradle.api.internal.provider.AbstractReadOnlyProvider; +import org.gradle.api.internal.provider.AbstractMinimalProvider; import org.gradle.api.internal.provider.ProviderInternal; import org.gradle.api.internal.provider.Providers; import org.gradle.api.provider.Provider; @@ -808,7 +808,7 @@ protected NamedDomainObjectProvider createExistingProvider(String n return Cast.uncheckedCast(getInstantiator().newInstance(ExistingNamedDomainObjectProvider.class, this, name, new DslObject(object).getDeclaredType())); } - protected abstract class AbstractNamedDomainObjectProvider extends AbstractReadOnlyProvider implements Named, NamedDomainObjectProvider { + protected abstract class AbstractNamedDomainObjectProvider extends AbstractMinimalProvider implements Named, NamedDomainObjectProvider { private final String name; private final Class type; @@ -865,8 +865,8 @@ public I get() { } @Override - public I getOrNull() { - return Cast.uncheckedCast(findByNameWithoutRules(getName())); + protected Value calculateOwnValue() { + return Value.ofNullable(Cast.uncheckedCast(findByNameWithoutRules(getName()))); } } @@ -914,9 +914,9 @@ public I get() { } @Override - public I getOrNull() { + protected Value calculateOwnValue() { if (wasElementRemoved()) { - return null; + return Value.missing(); } if (failure != null) { throw failure; @@ -927,7 +927,7 @@ public I getOrNull() { tryCreate(); } } - return object; + return Value.of(object); } protected void tryCreate() { diff --git a/subprojects/core/src/main/java/org/gradle/api/services/internal/BuildServiceProvider.java b/subprojects/core/src/main/java/org/gradle/api/services/internal/BuildServiceProvider.java index 2fd50a90cc7f..36a1ec9d9417 100644 --- a/subprojects/core/src/main/java/org/gradle/api/services/internal/BuildServiceProvider.java +++ b/subprojects/core/src/main/java/org/gradle/api/services/internal/BuildServiceProvider.java @@ -16,7 +16,7 @@ package org.gradle.api.services.internal; -import org.gradle.api.internal.provider.AbstractReadOnlyProvider; +import org.gradle.api.internal.provider.AbstractMinimalProvider; import org.gradle.api.services.BuildService; import org.gradle.api.services.BuildServiceParameters; import org.gradle.internal.Try; @@ -30,7 +30,7 @@ import javax.annotation.Nullable; // TODO - complain when used at configuration time, except when opted in to this -public class BuildServiceProvider, P extends BuildServiceParameters> extends AbstractReadOnlyProvider implements Managed { +public class BuildServiceProvider, P extends BuildServiceParameters> extends AbstractMinimalProvider implements Managed { private final String name; private final Class implementationType; private final IsolationScheme isolationScheme; @@ -90,9 +90,8 @@ public boolean isValueProducedByTask() { return true; } - @Nullable @Override - public T getOrNull() { + protected Value calculateOwnValue() { synchronized (this) { if (instance == null) { // TODO - extract some shared infrastructure to take care of instantiation (eg which services are visible, strict vs lenient, decorated or not?) @@ -106,7 +105,7 @@ public T getOrNull() { instance = Try.failure(new ServiceLifecycleException("Failed to create service '" + name + "'.", e)); } } - return instance.get(); + return Value.of(instance.get()); } } diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/AbstractDomainObjectCollectionSpec.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/AbstractDomainObjectCollectionSpec.groovy index 2f59da595747..f9728d4012a7 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/AbstractDomainObjectCollectionSpec.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/AbstractDomainObjectCollectionSpec.groovy @@ -16,11 +16,13 @@ package org.gradle.api.internal + import org.gradle.api.Action import org.gradle.api.DomainObjectCollection import org.gradle.api.internal.plugins.DslObject import org.gradle.api.internal.provider.CollectionProviderInternal import org.gradle.api.internal.provider.ProviderInternal +import org.gradle.api.internal.provider.ValueSupplier import org.gradle.configuration.internal.DefaultUserCodeApplicationContext import org.gradle.configuration.internal.UserCodeApplicationContext import org.gradle.configuration.internal.UserCodeApplicationId @@ -219,7 +221,8 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { !result and: - 1 * provider.get() >> a + 1 * provider.calculateValue() >> ValueSupplier.Value.of(a) + 0 * _ } def "provider for iterable of elements is queried when membership checked"() { @@ -237,7 +240,9 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { !result and: - 1 * provider.get() >> [a, d] + _ * provider.size() >> 2 + 1 * provider.calculateValue() >> ValueSupplier.Value.of([a, d]) + 0 * _ } def "can get all domain objects ordered by order added"() { @@ -283,8 +288,8 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { result == iterationOrder(b, a, d, c) and: - 1 * provider1.get() >> a - 1 * provider2.get() >> d + 1 * provider1.calculateValue() >> ValueSupplier.Value.of(a) + 1 * provider2.calculateValue() >> ValueSupplier.Value.of(d) 0 * _ } @@ -305,7 +310,7 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { and: _ * provider1.size() >> 2 - 1 * provider1.get() >> [a, d] + 1 * provider1.calculateValue() >> ValueSupplier.Value.of([a, d]) 0 * _ } @@ -417,7 +422,7 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { then: 1 * action.execute(c) _ * provider1.type >> type - 1 * provider1.get() >> c + 1 * provider1.calculateValue() >> ValueSupplier.Value.of(c) 0 * _ when: @@ -444,7 +449,7 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { then: 1 * action.execute(c) _ * provider1.elementType >> type - 1 * provider1.get() >> [c] + 1 * provider1.calculateValue() >> ValueSupplier.Value.of([c]) _ * provider1.size() >> 1 0 * _ @@ -489,15 +494,15 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { then: result == iterationOrder(c, a) _ * provider.type >> type - 1 * provider.get() >> a - 0 * provider._ + 1 * provider.calculateValue() >> ValueSupplier.Value.of(a) + 0 * _ when: def result2 = toList(container) then: result2 == iterationOrder(c, a, d) - 0 * provider._ + 0 * _ } def "provider for iterable of elements is queried when filtered collection with matching type created"() { @@ -521,15 +526,15 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { then: result == iterationOrder(c, a, b) _ * provider.size() >> 2 - 1 * provider.get() >> [a, b] - 0 * provider._ + 1 * provider.calculateValue() >> ValueSupplier.Value.of([a, b]) + 0 * _ when: def result2 = toList(container) then: result2 == iterationOrder(c, a, b, d) - 0 * provider._ + 0 * _ } def "provider for element is not queried when filtered collection with non matching type created"() { @@ -545,22 +550,22 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { def filtered = container.withType(otherType) then: - 0 * provider._ + 0 * _ when: def result = toList(filtered) then: result == iterationOrder(d) - 0 * provider._ + 0 * _ when: def result2 = toList(container) then: result2 == iterationOrder(c, a, d) - 1 * provider.get() >> a - 0 * provider._ + 1 * provider.calculateValue() >> ValueSupplier.Value.of(a) + 0 * _ } def "provider for iterable of elements is not queried when filtered collection with non matching type created"() { @@ -592,8 +597,8 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { then: result2 == iterationOrder(c, a, b, d) _ * provider.size() >> 2 - 1 * provider.get() >> [a, b] - 0 * provider._ + 1 * provider.calculateValue() >> ValueSupplier.Value.of([a, b]) + 0 * _ } def "can execute action for all elements in a type filtered collection"() { @@ -670,7 +675,7 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { then: _ * provider1.type >> type - 1 * provider1.get() >> c + 1 * provider1.calculateValue() >> ValueSupplier.Value.of(c) 1 * action.execute(c) 0 * _ @@ -699,7 +704,7 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { then: _ * provider1.elementType >> type _ * provider1.size() >> 1 - 1 * provider1.get() >> [c] + 1 * provider1.calculateValue() >> ValueSupplier.Value.of([c]) 1 * action.execute(c) 0 * _ @@ -785,7 +790,7 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { toList(container) then: - 1 * provider1.get() >> a + 1 * provider1.calculateValue() >> ValueSupplier.Value.of(a) 1 * action.execute(a) 0 * _ @@ -800,7 +805,7 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { toList(container) then: - 1 * provider2.get() >> c + 1 * provider2.calculateValue() >> ValueSupplier.Value.of(c) 1 * action.execute(c) 0 * _ @@ -816,7 +821,7 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { then: _ * provider3.size() >> 2 - 1 * provider3.get() >> [b, d] + 1 * provider3.calculateValue() >> ValueSupplier.Value.of([b, d]) 1 * action.execute(b) 1 * action.execute(d) 0 * _ @@ -829,8 +834,8 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { def providerOfIterable = Mock(CollectionProviderInternal) given: - _ * provider.get() >> a - _ * providerOfIterable.get() >> [b, c] + _ * provider.calculateValue() >> ValueSupplier.Value.of(a) + _ * providerOfIterable.calculateValue() >> ValueSupplier.Value.of([b, c]) container.addLater(provider) container.addAllLater(providerOfIterable) toList(container) @@ -883,10 +888,10 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { then: _ * provider1.type >> type - 1 * provider1.get() >> a + 1 * provider1.calculateValue() >> ValueSupplier.Value.of(a) 1 * action.execute(a) _ * provider2.type >> otherType - 1 * provider2.get() >> d + 1 * provider2.calculateValue() >> ValueSupplier.Value.of(d) 0 * _ when: @@ -920,12 +925,12 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { then: _ * provider1.elementType >> type _ * provider1.size() >> 2 - 1 * provider1.get() >> [a, c] + 1 * provider1.calculateValue() >> ValueSupplier.Value.of([a, c]) 1 * action.execute(a) 1 * action.execute(c) _ * provider2.elementType >> otherType _ * provider2.size() >> 1 - 1 * provider2.get() >> [d] + 1 * provider2.calculateValue() >> ValueSupplier.Value.of([d]) 0 * _ when: @@ -952,16 +957,17 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { filtered.configureEach(action) then: - 0 * provider1.get() - 0 * provider2.get() - 0 * action.execute(_) + 0 * _ when: def result = toList(filtered) then: - 1 * provider1.get() >> a - 1 * provider2.get() >> b + 1 * provider1.calculateValue() >> ValueSupplier.Value.of(a) + 1 * provider2.calculateValue() >> ValueSupplier.Value.of(b) + 0 * _ + + and: result == iterationOrder(a, b) and: @@ -986,9 +992,9 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { filtered.configureEach(action) then: - 0 * provider1.get() - 0 * provider2.get() - 0 * action.execute(_) + _ * provider1.size() >> 1 + _ * provider2.size() >> 2 + 0 * _ when: def result = toList(filtered) @@ -996,8 +1002,11 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { then: _ * provider1.size() >> 1 _ * provider2.size() >> 2 - 1 * provider1.get() >> [a] - 1 * provider2.get() >> [c, b] + 1 * provider1.calculateValue() >> ValueSupplier.Value.of([a]) + 1 * provider2.calculateValue() >> ValueSupplier.Value.of([c, b]) + 0 * _ + + and: result == iterationOrder(a, c, b) and: @@ -1023,16 +1032,17 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { filtered.configureEach(action) then: - 0 * provider1.get() - 0 * provider2.get() - 0 * action.execute(_) + 0 * _ when: def result = toList(filtered) then: 0 * provider1.get() >> a - 1 * provider2.get() >> b + 1 * provider2.calculateValue() >> ValueSupplier.Value.of(b) + 0 * _ + + and: result == iterationOrder(b) and: @@ -1057,9 +1067,9 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { filtered.configureEach(action) then: - 0 * provider1.get() - 0 * provider2.get() - 0 * action.execute(_) + _ * provider1.size() >> 1 + _ * provider2.size() >> 2 + 0 * _ when: def result = toList(filtered) @@ -1067,8 +1077,11 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { then: _ * provider1.size() >> 1 _ * provider2.size() >> 2 - 0 * provider1.get() >> [a] - 1 * provider2.get() >> [b, c] + 0 * provider1.get() + 1 * provider2.calculateValue() >> ValueSupplier.Value.of([b, c]) + 0 * _ + + and: result == iterationOrder(b, c) and: @@ -1094,15 +1107,17 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { filtered.configureEach(action) then: - 0 * provider1.get() - 0 * provider2.get() + 0 * _ when: def result = toList(filtered) then: - 1 * provider1.get() >> a - 1 * provider2.get() >> b + 1 * provider1.calculateValue() >> ValueSupplier.Value.of(a) + 1 * provider2.calculateValue() >> ValueSupplier.Value.of(b) + 0 * _ + + and: result == iterationOrder(b) and: @@ -1128,15 +1143,16 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { didRemoved and: - 0 * provider1.get() - 0 * provider2.get() + 0 * _ when: def result = toList(container) then: - 0 * provider1.get() - 1 * provider2.get() >> b + 1 * provider2.calculateValue() >> ValueSupplier.Value.of(b) + 0 * _ + + and: result == iterationOrder(b) } @@ -1157,7 +1173,8 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { toList(container) == [] and: - 0 * provider1.get() + _ * provider1.type >> type + 0 * _ when: def didRemovedSecondTime = container.remove(provider1) @@ -1167,8 +1184,9 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { toList(container) == [] and: + _ * provider1.type >> type 1 * provider1.present >> false - 0 * provider1.get() + 0 * _ } def "can remove realized external providers without realizing more providers"() { @@ -1179,10 +1197,10 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { given: _ * provider1.type >> type - _ * provider1.get() >> a + _ * provider1.calculateValue() >> ValueSupplier.Value.of(a) _ * provider1.present >> true _ * provider2.type >> type - _ * provider2.get() >> b + _ * provider2.calculateValue() >> ValueSupplier.Value.of(b) _ * provider2.present >> true _ * provider3.type >> otherType container.addLater(provider1) @@ -1199,9 +1217,10 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { didRemoved1 and: + _ * provider1.type >> type + 1 * provider1.present >> true 1 * provider1.get() >> a - 0 * provider2.get() - 0 * provider3.get() + 0 * _ when: def didRemoved2 = container.remove(provider2) @@ -1210,9 +1229,10 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { didRemoved2 and: - 0 * provider1.get() + _ * provider2.type >> type + 1 * provider2.present >> true 1 * provider2.get() >> b - 0 * provider3.get() + 0 * _ } def "can remove realized external elements via instance"() { @@ -1222,7 +1242,7 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { given: _ * provider1.type >> type - _ * provider1.get() >> a + _ * provider1.calculateValue() >> ValueSupplier.Value.of(a) _ * provider2.type >> otherType container.addLater(provider1) container.addLater(provider2) @@ -1237,8 +1257,7 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { didRemoved and: - 0 * provider1.get() - 0 * provider2.get() + 0 * _ } def "will execute remove action when removing external provider only for realized elements"() { @@ -1249,6 +1268,7 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { given: _ * provider1.type >> type + _ * provider1.calculateValue() >> ValueSupplier.Value.of(a) _ * provider1.get() >> a _ * provider1.present >> true _ * provider2.type >> otherType @@ -1265,9 +1285,14 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { then: didRemoved1 + and: + _ * provider1.type >> type + 1 * provider1.present >> true + 1 * provider1.get() >> a + and: 1 * action.execute(a) - 0 * action.execute(_) + 0 * _ when: def didRemoved2 = container.remove(provider2) @@ -1276,7 +1301,7 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { didRemoved2 and: - 0 * action.execute(_) + 0 * _ } def "will execute remove action when clearing the container only for realized external providers"() { @@ -1287,7 +1312,7 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { given: _ * provider1.type >> type - _ * provider1.get() >> a + _ * provider1.calculateValue() >> ValueSupplier.Value.of(a) _ * provider2.type >> otherType container.addLater(provider1) container.addLater(provider2) @@ -1301,7 +1326,7 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { then: 1 * action.execute(a) - 0 * action.execute(_) + 0 * _ when: def result = toList(container) @@ -1325,15 +1350,15 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { container.clear() then: - 0 * provider1.get() - 0 * provider2.get() + 0 * _ when: def result = toList(container) then: - 0 * provider1.get() - 0 * provider2.get() + 0 * _ + + and: result == iterationOrder() } @@ -1345,9 +1370,9 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { given: _ * provider1.type >> type - _ * provider1.get() >> a + _ * provider1.calculateValue() >> ValueSupplier.Value.of(a) _ * provider2.type >> otherType - _ * provider2.get() >> d + _ * provider2.calculateValue() >> ValueSupplier.Value.of(d) container.addLater(provider1) container.addLater(provider2) container.whenObjectRemoved(action) @@ -1362,15 +1387,19 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { didRetained and: + 1 * provider2.calculateValue() >> ValueSupplier.Value.of(d) 1 * action.execute(a) 1 * action.execute(d) - 0 * action.execute(_) + 0 * _ when: def result = toList(container) then: result == iterationOrder() + + and: + 0 * _ } def "will query external providers when not retaining them"() { @@ -1391,15 +1420,17 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { didRetained and: - 1 * provider1.get() >> a - 1 * provider2.get() >> b + 1 * provider1.calculateValue() >> ValueSupplier.Value.of(a) + 1 * provider2.calculateValue() >> ValueSupplier.Value.of(b) + 0 * _ when: def result = toList(container) then: - 0 * provider1.get() - 0 * provider2.get() + 0 * _ + + and: result == iterationOrder(b) } @@ -1410,9 +1441,9 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { given: _ * provider1.type >> type - _ * provider1.get() >> a + _ * provider1.calculateValue() >> ValueSupplier.Value.of(a) _ * provider2.type >> otherType - _ * provider2.get() >> d + _ * provider2.calculateValue() >> ValueSupplier.Value.of(d) container.addLater(provider1) container.addLater(provider2) @@ -1426,13 +1457,16 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { didRetained and: - 0 * provider1.get() - 1 * provider2.get() >> d + 1 * provider2.calculateValue() >> ValueSupplier.Value.of(d) + 0 * _ when: def result = toList(container) then: + 0 * _ + + and: result == iterationOrder(a) } @@ -1453,8 +1487,9 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { filtered.configureEach(action) then: - 0 * provider1.get() - 0 * provider2.get() + _ * provider1.size() >> 1 + _ * provider2.size() >> 2 + 0 * _ when: def result = toList(filtered) @@ -1462,8 +1497,11 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { then: _ * provider1.size() >> 1 _ * provider2.size() >> 2 - 1 * provider1.get() >> [a] - 1 * provider2.get() >> [b, c] + 1 * provider1.calculateValue() >> ValueSupplier.Value.of([a]) + 1 * provider2.calculateValue() >> ValueSupplier.Value.of([b, c]) + 0 * _ + + and: result == iterationOrder(b) and: @@ -1487,15 +1525,18 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { container.withType(type).iterator() then: - 1 * provider1.get() >> a - 0 * provider2.get() + 1 * provider1.calculateValue() >> ValueSupplier.Value.of(a) + 0 * _ when: def result = toList(container) then: 0 * provider1.get() - 1 * provider2.get() >> b + 1 * provider2.calculateValue() >> ValueSupplier.Value.of(b) + 0 * _ + + and: result == iterationOrder(a, b) } @@ -1507,9 +1548,9 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { given: _ * provider1.type >> type - _ * provider1.get() >> a + _ * provider1.calculateValue() >> ValueSupplier.Value.of(a) _ * provider2.type >> type - _ * provider2.get() >> b + _ * provider2.calculateValue() >> ValueSupplier.Value.of(b) container.addLater(provider1) container.addLater(provider2) container.whenObjectRemoved(action) @@ -1524,8 +1565,10 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { result == iterationOrder(b) and: + 1 * provider1.calculateValue() >> ValueSupplier.Value.of(a) + 1 * provider2.calculateValue() >> ValueSupplier.Value.of(b) 1 * action.execute(a) - 0 * action.execute(_) + 0 * _ } def "will execute remove action when removing a collection of external provider only for realized elements"() { @@ -1536,6 +1579,7 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { given: _ * provider1.type >> type + _ * provider1.calculateValue() >> ValueSupplier.Value.of(a) _ * provider1.get() >> a _ * provider1.present >> true _ * provider2.type >> otherType @@ -1554,8 +1598,11 @@ abstract class AbstractDomainObjectCollectionSpec extends Specification { container.empty and: + _ * provider1.type >> type + 1 * provider1.present >> true + 1 * provider1.get() >> a 1 * action.execute(a) - 0 * action.execute(_) + 0 * _ } void setupContainerDefaults() {} diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultDomainObjectCollectionTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultDomainObjectCollectionTest.groovy index 3307831aad11..d1891d47de24 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultDomainObjectCollectionTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultDomainObjectCollectionTest.groovy @@ -19,6 +19,7 @@ package org.gradle.api.internal import org.gradle.api.Action import org.gradle.api.internal.collections.IterationOrderRetainingSetElementSource import org.gradle.api.internal.provider.ProviderInternal +import org.gradle.api.internal.provider.ValueSupplier import org.gradle.api.specs.Spec import static org.gradle.util.WrapUtil.toList @@ -298,7 +299,7 @@ class DefaultDomainObjectCollectionTest extends AbstractDomainObjectCollectionSp def callsRemoveActionWhenObjectRemovedUsingIteratorNoFlushAndLastElementIsUnrealized() { def action = Mock(Action) def provider = Mock(ProviderInternal) - _ * provider.get() >> "c" + _ * provider.calculateValue() >> ValueSupplier.Value.of("c") container.whenObjectRemoved(action) container.add("a") diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultNamedDomainObjectCollectionTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultNamedDomainObjectCollectionTest.groovy index 4fa5a9c8fb35..040f3ba88b0f 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultNamedDomainObjectCollectionTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/DefaultNamedDomainObjectCollectionTest.groovy @@ -30,7 +30,6 @@ class DefaultNamedDomainObjectCollectionTest extends AbstractNamedDomainObjectCo }; Instantiator instantiator = TestUtil.instantiatorFactory().decorateLenient() - Set store final DefaultNamedDomainObjectCollection container = new DefaultNamedDomainObjectCollection(Bean, new IterationOrderRetainingSetElementSource(), instantiator, namer, callbackActionDecorator) final Bean a = new BeanSub1("a") diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/collections/AbstractElementSourceTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/collections/AbstractElementSourceTest.groovy index 16c26d0dc7dd..65425b4c92b1 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/collections/AbstractElementSourceTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/collections/AbstractElementSourceTest.groovy @@ -17,7 +17,7 @@ package org.gradle.api.internal.collections import org.gradle.api.Action -import org.gradle.api.internal.provider.AbstractReadOnlyProvider +import org.gradle.api.internal.provider.AbstractMinimalProvider import org.gradle.api.internal.provider.ChangingValue import org.gradle.api.internal.provider.ChangingValueHandler import org.gradle.api.internal.provider.CollectionProviderInternal @@ -209,7 +209,7 @@ abstract class AbstractElementSourceTest extends Specification { source.iterator().collect() == iterationOrder("foo", "baz", "fooz", "fizz") } - def "comodification with iterator causes an exception" () { + def "comodification with iterator causes an exception"() { given: def provider = provider("baz") def providerOfSet = setProvider("fuzz", "buzz") @@ -275,7 +275,7 @@ abstract class AbstractElementSourceTest extends Specification { return new TypedProviderOfSet(StringBuffer, values as LinkedHashSet) } - private static class TypedProvider extends AbstractReadOnlyProvider implements ChangingValue { + private static class TypedProvider extends AbstractMinimalProvider implements ChangingValue { final Class type T value final ChangingValueHandler changingValue = new ChangingValueHandler() @@ -291,8 +291,8 @@ abstract class AbstractElementSourceTest extends Specification { } @Override - T getOrNull() { - return value + protected Value calculateOwnValue() { + return Value.of(value) } void setValue(T value) { @@ -307,7 +307,7 @@ abstract class AbstractElementSourceTest extends Specification { } } - private static class TypedProviderOfSet extends AbstractReadOnlyProvider> implements CollectionProviderInternal>, ChangingValue> { + private static class TypedProviderOfSet extends AbstractMinimalProvider> implements CollectionProviderInternal>, ChangingValue> { final Class type Set value final ChangingValueHandler> changingValue = new ChangingValueHandler>() @@ -323,8 +323,8 @@ abstract class AbstractElementSourceTest extends Specification { } @Override - Set getOrNull() { - return value + protected Value> calculateOwnValue() { + return Value.of(value) } @Override diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/collections/DefaultPendingSourceTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/collections/DefaultPendingSourceTest.groovy index 0becc0b2d60d..005016457916 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/collections/DefaultPendingSourceTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/collections/DefaultPendingSourceTest.groovy @@ -18,6 +18,7 @@ package org.gradle.api.internal.collections import org.gradle.api.Action import org.gradle.api.internal.provider.ProviderInternal +import org.gradle.api.internal.provider.ValueSupplier import spock.lang.Specification class DefaultPendingSourceTest extends Specification { @@ -29,9 +30,9 @@ class DefaultPendingSourceTest extends Specification { def setup() { pending.onRealize(realize) - _ * provider1.get() >> "provider1" - _ * provider2.get() >> "provider2" - _ * provider3.get() >> "provider3" + _ * provider1.calculateValue() >> ValueSupplier.Value.of("provider1") + _ * provider2.calculateValue() >> ValueSupplier.Value.of("provider2") + _ * provider3.calculateValue() >> ValueSupplier.Value.of("provider3") } def "realizes pending elements on flush"() { diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/collections/ListElementSourceTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/collections/ListElementSourceTest.groovy index 38a36c316c7c..ab6178497e77 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/collections/ListElementSourceTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/collections/ListElementSourceTest.groovy @@ -16,10 +16,9 @@ package org.gradle.api.internal.collections -import org.gradle.api.internal.provider.AbstractReadOnlyProvider +import org.gradle.api.internal.provider.AbstractMinimalProvider import org.gradle.api.internal.provider.CollectionProviderInternal - class ListElementSourceTest extends AbstractIterationOrderRetainingElementSourceTest { ListElementSource source = new ListElementSource<>() @@ -240,7 +239,9 @@ class ListElementSourceTest extends AbstractIterationOrderRetainingElementSource when: iterator = source.listIterator() - while(iterator.hasNext()) { iterator.next() } + while (iterator.hasNext()) { + iterator.next() + } iterator.add("buzz") then: @@ -248,7 +249,9 @@ class ListElementSourceTest extends AbstractIterationOrderRetainingElementSource when: iterator = source.listIterator() - while(iterator.hasNext()) { iterator.next() } + while (iterator.hasNext()) { + iterator.next() + } iterator.previous() iterator.add("bazz") @@ -477,7 +480,7 @@ class ListElementSourceTest extends AbstractIterationOrderRetainingElementSource return new TypedProviderOfList(StringBuffer, values as List) } - private static class TypedProviderOfList extends AbstractReadOnlyProvider> implements CollectionProviderInternal> { + private static class TypedProviderOfList extends AbstractMinimalProvider> implements CollectionProviderInternal> { final Class type final List value @@ -487,13 +490,13 @@ class ListElementSourceTest extends AbstractIterationOrderRetainingElementSource } @Override - Class getElementType() { + Class getElementType() { return type } @Override - List getOrNull() { - return value + protected Value> calculateOwnValue() { + return Value.of(value) } @Override diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DefaultProjectLayoutTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DefaultProjectLayoutTest.groovy index 3114901bf99b..8823d157d7dd 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DefaultProjectLayoutTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/file/DefaultProjectLayoutTest.groovy @@ -16,14 +16,15 @@ package org.gradle.api.internal.file -import org.gradle.api.internal.provider.ProviderInternal + import org.gradle.api.internal.tasks.TaskDependencyFactory -import org.gradle.api.provider.Provider import org.gradle.test.fixtures.file.TestFile import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider import org.junit.Rule import spock.lang.Specification +import static org.gradle.api.internal.provider.ProviderTestUtil.withNoValue +import static org.gradle.api.internal.provider.ProviderTestUtil.withValues import static org.gradle.util.Matchers.strictlyEquals class DefaultProjectLayoutTest extends Specification { @@ -43,9 +44,7 @@ class DefaultProjectLayoutTest extends Specification { } def "can resolve directory relative to project directory"() { - def pathProvider = Stub(ProviderInternal) - _ * pathProvider.get() >>> ["a", "b"] - _ * pathProvider.present >> true + def pathProvider = withValues("a", "b") expect: def dir = layout.projectDirectory.dir("sub-dir") @@ -65,9 +64,7 @@ class DefaultProjectLayoutTest extends Specification { } def "can resolve regular file relative to project directory"() { - def pathProvider = Stub(ProviderInternal) - _ * pathProvider.get() >>> ["a", "b"] - _ * pathProvider.present >> true + def pathProvider = withValues("a", "b") expect: def file = layout.projectDirectory.file("child") @@ -87,9 +84,7 @@ class DefaultProjectLayoutTest extends Specification { } def "directory is not present when path provider is not present"() { - def pathProvider = Stub(ProviderInternal) - _ * pathProvider.present >> false - _ * pathProvider.getOrNull() >> null + def pathProvider = withNoValue() expect: def provider = layout.projectDirectory.dir(pathProvider) @@ -98,9 +93,7 @@ class DefaultProjectLayoutTest extends Specification { } def "regular file is not present when path provider is not present"() { - def pathProvider = Stub(ProviderInternal) - _ * pathProvider.present >> false - _ * pathProvider.getOrNull() >> null + def pathProvider = withNoValue() expect: def provider = layout.projectDirectory.file(pathProvider) @@ -183,9 +176,7 @@ class DefaultProjectLayoutTest extends Specification { } def "can resolve directory relative to build directory"() { - def pathProvider = Stub(Provider) - _ * pathProvider.get() >>> ["a", "b"] - _ * pathProvider.present >> true + def pathProvider = withValues("a", "b") expect: def dir = layout.buildDirectory.dir("sub-dir") @@ -206,9 +197,7 @@ class DefaultProjectLayoutTest extends Specification { } def "can resolve regular file relative to build directory"() { - def pathProvider = Stub(Provider) - _ * pathProvider.get() >>> ["a", "b"] - _ * pathProvider.present >> true + def pathProvider = withValues("a", "b") expect: def file = layout.buildDirectory.file("child") @@ -249,12 +238,9 @@ class DefaultProjectLayoutTest extends Specification { } def "can map File provider to regular file provider"() { - def fileProvider = Stub(ProviderInternal) def file1 = projectDir.file("file1") def file2 = projectDir.file("file2") - - _ * fileProvider.present >> true - _ * fileProvider.get() >>> [file1, file2] + def fileProvider = withValues(file1, file2) expect: def provider = layout.file(fileProvider) @@ -265,12 +251,9 @@ class DefaultProjectLayoutTest extends Specification { } def "can map File provider to directory provider"() { - def fileProvider = Stub(ProviderInternal) def file1 = projectDir.file("file1") def file2 = projectDir.file("file2") - - _ * fileProvider.present >> true - _ * fileProvider.get() >>> [file1, file2] + def fileProvider = withValues(file1, file2) expect: def provider = layout.dir(fileProvider) @@ -281,12 +264,10 @@ class DefaultProjectLayoutTest extends Specification { } def "resolves relative file given by File provider"() { - def fileProvider = Stub(ProviderInternal) def file1 = projectDir.file("file1") def file2 = projectDir.file("file2") - _ * fileProvider.present >> true - _ * fileProvider.get() >>> [new File("file1"), new File("file2")] + def fileProvider = withValues(new File("file1"), new File("file2")) expect: def provider = layout.file(fileProvider) @@ -297,12 +278,10 @@ class DefaultProjectLayoutTest extends Specification { } def "resolves relative dir given by File provider"() { - def dirProvider = Stub(ProviderInternal) def dir1 = projectDir.file("dir1") def dir2 = projectDir.file("dir2") - _ * dirProvider.present >> true - _ * dirProvider.get() >>> [new File("dir1"), new File("dir2")] + def dirProvider = withValues(new File("dir1"), new File("dir2")) expect: def provider = layout.dir(dirProvider) diff --git a/subprojects/core/src/test/groovy/org/gradle/api/internal/model/DefaultObjectFactoryTest.groovy b/subprojects/core/src/test/groovy/org/gradle/api/internal/model/DefaultObjectFactoryTest.groovy index aa8590207fde..ba342e13fc47 100644 --- a/subprojects/core/src/test/groovy/org/gradle/api/internal/model/DefaultObjectFactoryTest.groovy +++ b/subprojects/core/src/test/groovy/org/gradle/api/internal/model/DefaultObjectFactoryTest.groovy @@ -39,7 +39,7 @@ class DefaultObjectFactoryTest extends Specification { then: def e = thrown(IllegalStateException) - e.message == 'No value has been specified for this property.' + e.message == 'Cannot query the value of this property because it has no value available.' } def "cannot create property for null value"() { diff --git a/subprojects/file-collections/src/main/java/org/gradle/api/internal/file/AbstractFileCollection.java b/subprojects/file-collections/src/main/java/org/gradle/api/internal/file/AbstractFileCollection.java index 9a4893d90835..0490212e6d2a 100644 --- a/subprojects/file-collections/src/main/java/org/gradle/api/internal/file/AbstractFileCollection.java +++ b/subprojects/file-collections/src/main/java/org/gradle/api/internal/file/AbstractFileCollection.java @@ -33,10 +33,10 @@ import org.gradle.api.specs.Spec; import org.gradle.api.specs.Specs; import org.gradle.api.tasks.TaskDependency; +import org.gradle.internal.Cast; import org.gradle.util.CollectionUtils; import org.gradle.util.GUtil; -import javax.annotation.Nullable; import java.io.File; import java.util.ArrayList; import java.util.Collection; @@ -115,10 +115,9 @@ public FileCollection plus(FileCollection collection) { @Override public Provider> getElements() { return new AbstractProviderWithValue>() { - @Nullable @Override public Class> getType() { - return null; + return Cast.uncheckedCast(Set.class); } @Override diff --git a/subprojects/file-collections/src/main/java/org/gradle/api/internal/file/DefaultFilePropertyFactory.java b/subprojects/file-collections/src/main/java/org/gradle/api/internal/file/DefaultFilePropertyFactory.java index 30e82fa5f56a..7b495f1801ca 100644 --- a/subprojects/file-collections/src/main/java/org/gradle/api/internal/file/DefaultFilePropertyFactory.java +++ b/subprojects/file-collections/src/main/java/org/gradle/api/internal/file/DefaultFilePropertyFactory.java @@ -26,7 +26,7 @@ import org.gradle.api.file.RegularFileProperty; import org.gradle.api.internal.provider.AbstractCombiningProvider; import org.gradle.api.internal.provider.AbstractMappingProvider; -import org.gradle.api.internal.provider.AbstractReadOnlyProvider; +import org.gradle.api.internal.provider.AbstractMinimalProvider; import org.gradle.api.internal.provider.DefaultProperty; import org.gradle.api.internal.provider.ProviderInternal; import org.gradle.api.internal.provider.Providers; @@ -241,17 +241,16 @@ public THIS convention(Provider valueProvider) { @Override public Provider getLocationOnly() { - return new AbstractReadOnlyProvider() { + return new AbstractMinimalProvider() { @Nullable @Override public Class getType() { return AbstractFileVar.this.getType(); } - @Nullable @Override - public T getOrNull() { - return AbstractFileVar.this.getOrNull(); + protected Value calculateOwnValue() { + return AbstractFileVar.this.calculateOwnValue(); } }; } @@ -356,7 +355,7 @@ protected Directory mapValue(Directory dir) { @Override public Provider dir(final Provider path) { - return new AbstractCombiningProvider(Directory.class, this, path) { + return new AbstractCombiningProvider(Directory.class, this, Providers.internal(path)) { @Override protected Directory map(Directory b, CharSequence v) { return b.dir(v.toString()); @@ -376,7 +375,7 @@ protected RegularFile mapValue(Directory dir) { @Override public Provider file(final Provider path) { - return new AbstractCombiningProvider(RegularFile.class, this, path) { + return new AbstractCombiningProvider(RegularFile.class, this, Providers.internal(path)) { @Override protected RegularFile map(Directory b, CharSequence v) { return b.file(v.toString()); diff --git a/subprojects/file-collections/src/test/groovy/org/gradle/api/internal/file/DefaultFilePropertyFactoryTest.groovy b/subprojects/file-collections/src/test/groovy/org/gradle/api/internal/file/DefaultFilePropertyFactoryTest.groovy index 826c935b6cb7..4c594b27cefe 100644 --- a/subprojects/file-collections/src/test/groovy/org/gradle/api/internal/file/DefaultFilePropertyFactoryTest.groovy +++ b/subprojects/file-collections/src/test/groovy/org/gradle/api/internal/file/DefaultFilePropertyFactoryTest.groovy @@ -205,35 +205,35 @@ class DefaultFilePropertyFactoryTest extends Specification { then: def e = thrown(IllegalStateException) - e.message == 'No value has been specified for this property.' + e.message == 'Cannot query the value of this property because it has no value available.' when: fileProvider.get() then: def e2 = thrown(IllegalStateException) - e2.message == 'No value has been specified for this property.' + e2.message == 'Cannot query the value of this provider because it has no value available.' when: dir.get() then: def e3 = thrown(IllegalStateException) - e3.message == 'No value has been specified for this property.' + e3.message == 'Cannot query the value of this provider because it has no value available.' when: file.get() then: def e4 = thrown(IllegalStateException) - e4.message == 'No value has been specified for this property.' + e4.message == 'Cannot query the value of this provider because it has no value available.' when: tree.files then: def e5 = thrown(IllegalStateException) - e5.message == 'No value has been specified for this property.' + e5.message == 'Cannot query the value of this property because it has no value available.' } @SuppressWarnings("GroovyAssignabilityCheck") diff --git a/subprojects/instant-execution/instant-execution.gradle.kts b/subprojects/instant-execution/instant-execution.gradle.kts index d55f2f094932..cd9d58038798 100644 --- a/subprojects/instant-execution/instant-execution.gradle.kts +++ b/subprojects/instant-execution/instant-execution.gradle.kts @@ -1,8 +1,5 @@ import build.futureKotlin -import org.gradle.gradlebuild.BuildEnvironment -import org.gradle.gradlebuild.test.integrationtests.IntegrationTest import org.gradle.gradlebuild.unittestandcompile.ModuleType -import org.gradle.testing.performance.generator.tasks.RemoteProject plugins { `kotlin-library` @@ -71,44 +68,6 @@ gradlebuildJava { tasks { - - /** - * Santa Tracker git URI. - * - * Note that you can change it to `file:///path/to/your/santa-tracker-clone/.git` - * if you need to iterate quickly on changes to Santa Tracker. - */ - val gitUri = "https://github.com/gradle/santa-tracker-android.git" - - val santaTrackerJava by registering(RemoteProject::class) { - remoteUri.set(gitUri) - // From agp-3.6.0-java branch - ref.set("174705275e434adc843e8e9b28106a5e3ffd6733") - } - - val santaTrackerKotlin by registering(RemoteProject::class) { - remoteUri.set(gitUri) - // From agp-3.6.0 branch - ref.set("3bbbd895de38efafd0dd1789454d4e4cb72d46d5") - } - - if (BuildEnvironment.isCiServer) { - withType().configureEach { - outputs.upToDateWhen { false } - } - } - - withType().configureEach { - dependsOn(santaTrackerJava) - dependsOn(santaTrackerKotlin) - inputs.property("androidHomeIsSet", System.getenv("ANDROID_HOME") != null) - } - - register("cleanRemoteProjects") { - delete(santaTrackerJava.get().outputDirectory) - delete(santaTrackerKotlin.get().outputDirectory) - } - instantIntegTest { enabled = false } diff --git a/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/AbstractInstantExecutionAndroidIntegrationTest.groovy b/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/AbstractInstantExecutionAndroidIntegrationTest.groovy deleted file mode 100644 index 2408a4e980e0..000000000000 --- a/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/AbstractInstantExecutionAndroidIntegrationTest.groovy +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * 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 org.gradle.instantexecution - -import groovy.transform.CompileStatic -import org.gradle.integtests.fixtures.android.AndroidHome -import org.gradle.internal.scan.config.fixtures.GradleEnterprisePluginSettingsFixture -import org.gradle.test.fixtures.file.TestFile - -import static org.gradle.integtests.fixtures.RepoScriptBlockUtil.kotlinEapRepositoryDefinition - -/** - * Base Android / Instant execution integration test. - * - * In order to iterate quickly on changes to AGP: - * - change `AGP_VERSION` to `4.0.0-dev` - * - change the repository url in `AGP_NIGHTLY_REPOSITORY_DECLARATION` to `file:///path/to/agp-src/out/repo` - * - run `./gradlew :publishAndroidGradleLocal` in `/path/to/agp-src/tools` - */ -@CompileStatic -abstract class AbstractInstantExecutionAndroidIntegrationTest extends AbstractInstantExecutionIntegrationTest { - - static final String AGP_VERSION = "4.0.0-20191217200145+0100" - - static final String AGP_NIGHTLY_REPOSITORY_DECLARATION = ''' - maven { - name = 'agp-nightlies' - url = 'https://repo.gradle.org/gradle/ext-snapshots-local/' - } - ''' - - static final String AGP_NIGHTLY_REPOSITORY_INIT_SCRIPT = """ - allprojects { - buildscript { - repositories { - $AGP_NIGHTLY_REPOSITORY_DECLARATION - ${kotlinEapRepositoryDefinition()} - } - } - repositories { - $AGP_NIGHTLY_REPOSITORY_DECLARATION - ${kotlinEapRepositoryDefinition()} - } - } - """ - - def setup() { - AndroidHome.assumeIsSet() - } - - static String replaceAgpVersion(String scriptText, String agpVersion = AGP_VERSION) { - return scriptText.replaceAll( - "(['\"]com.android.tools.build:gradle:).+(['\"])", - "${'$'}1$agpVersion${'$'}2" - ) - } - - void withAgpNightly(String agpVersion = AGP_VERSION) { - withAgpNightly(buildFile, agpVersion) - } - - void withAgpNightly(TestFile buildFile, String agpVersion = AGP_VERSION) { - - println "> Using AGP nightly ${agpVersion}" - - // Inject AGP nightly repository - def init = file("gradle/agp-nightly.init.gradle") << AGP_NIGHTLY_REPOSITORY_INIT_SCRIPT - executer.beforeExecute { - withArgument("-I") - withArgument(init.path) - withArgument("-Pandroid.overrideVersionCheck=true") - } - - // Inject AGP nightly version - buildFile.text = replaceAgpVersion(buildFile.text, agpVersion) - } - - void copyRemoteProject(String remoteProject) { - new TestFile(new File("build/$remoteProject")).copyTo(testDirectory) - GradleEnterprisePluginSettingsFixture.applyEnterprisePlugin(settingsFile) - } -} diff --git a/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/AbstractInstantExecutionIntegrationTest.groovy b/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/AbstractInstantExecutionIntegrationTest.groovy index 13ee77b3d0be..01e3daaa0542 100644 --- a/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/AbstractInstantExecutionIntegrationTest.groovy +++ b/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/AbstractInstantExecutionIntegrationTest.groovy @@ -17,7 +17,9 @@ package org.gradle.instantexecution import org.gradle.integtests.fixtures.AbstractIntegrationSpec +import org.gradle.integtests.fixtures.BuildOperationsFixture import org.gradle.integtests.fixtures.DefaultTestExecutionResult +import org.gradle.integtests.fixtures.instantexecution.InstantExecutionBuildOperationsFixture import org.intellij.lang.annotations.Language @@ -38,7 +40,7 @@ class AbstractInstantExecutionIntegrationTest extends AbstractIntegrationSpec { public static final String INSTANT_EXECUTION_PROPERTY = "-Dorg.gradle.unsafe.instant-execution=true" protected InstantExecutionBuildOperationsFixture newInstantExecutionFixture() { - return new InstantExecutionBuildOperationsFixture(executer, temporaryFolder) + return new InstantExecutionBuildOperationsFixture(new BuildOperationsFixture(executer, temporaryFolder)) } protected void assertTestsExecuted(String testClass, String... testNames) { diff --git a/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/InstantExecutionAndroidIntegrationTest.groovy b/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/InstantExecutionAndroidIntegrationTest.groovy deleted file mode 100644 index b3ae5042abcc..000000000000 --- a/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/InstantExecutionAndroidIntegrationTest.groovy +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * 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 org.gradle.instantexecution - -import org.gradle.integtests.fixtures.TestResources -import org.gradle.test.fixtures.file.LeaksFileHandles -import org.junit.Rule -import spock.lang.Unroll - -@LeaksFileHandles("TODO: AGP (intentionally) does not get a ‘build finished’ event and so does not close some files") -class InstantExecutionAndroidIntegrationTest extends AbstractInstantExecutionAndroidIntegrationTest { - - @Rule - TestResources resources = new TestResources(temporaryFolder, "builds") - - def instantExecution - - def setup() { - executer.noDeprecationChecks() - executer.withRepositoryMirrors() - - def rootDir = file("android-3.6-mini") - executer.beforeExecute { - inDirectory(rootDir) - } - withAgpNightly(rootDir.file("build.gradle")) - - instantExecution = newInstantExecutionFixture() - } - - @Unroll - def "android 3.6 minimal build assembleDebug up-to-date (fromIde=#fromIde)"() { - - when: - instantRun("assembleDebug", "-Pandroid.injected.invoked.from.ide=$fromIde") - - then: - instantExecution.assertStateStored() - - when: - instantRun("assembleDebug", "-Pandroid.injected.invoked.from.ide=$fromIde") - - then: - instantExecution.assertStateLoaded() - - where: - fromIde << [false, true] - } - - @Unroll - def "android 3.6 minimal build clean assembleDebug (fromIde=#fromIde)"() { - - when: - instantRun("assembleDebug", "-Pandroid.injected.invoked.from.ide=$fromIde") - - then: - instantExecution.assertStateStored() - - when: - run 'clean' - instantRun("assembleDebug", "-Pandroid.injected.invoked.from.ide=$fromIde") - - then: - instantExecution.assertStateLoaded() - - where: - fromIde << [false, true] - } -} diff --git a/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/InstantExecutionJavaIntegrationTest.groovy b/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/InstantExecutionJavaIntegrationTest.groovy index 6f972a48f13c..44a62f55a89a 100644 --- a/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/InstantExecutionJavaIntegrationTest.groovy +++ b/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/InstantExecutionJavaIntegrationTest.groovy @@ -16,6 +16,7 @@ package org.gradle.instantexecution +import org.gradle.integtests.fixtures.instantexecution.InstantExecutionBuildOperationsFixture import org.gradle.test.fixtures.archive.ZipTestFixture import org.junit.Test diff --git a/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/InstantExecutionSantaTrackerIntegrationTest.groovy b/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/InstantExecutionSantaTrackerIntegrationTest.groovy deleted file mode 100644 index 4060850368f4..000000000000 --- a/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/InstantExecutionSantaTrackerIntegrationTest.groovy +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * 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 org.gradle.instantexecution - -import org.gradle.test.fixtures.file.LeaksFileHandles -import spock.lang.Unroll - - -/** - * Integration test Santa Tracker android app against AGP nightly. - */ -@LeaksFileHandles("TODO: AGP (intentionally) does not get a ‘build finished’ event and so does not close some files") -class InstantExecutionSantaTrackerIntegrationTest extends AbstractInstantExecutionAndroidIntegrationTest { - - def setup() { - executer.beforeExecute { - executer.noDeprecationChecks() - executer.withRepositoryMirrors() - } - } - - @Unroll - def "assembleDebug up-to-date on Santa Tracker #flavor (fromIde=#fromIde)"() { - - given: - copyRemoteProject(remoteProject) - withAgpNightly() - - when: - instantRun("assembleDebug", "--no-build-cache", "-Pandroid.injected.invoked.from.ide=$fromIde") - - then: - instantRun("assembleDebug", "--no-build-cache", "-Pandroid.injected.invoked.from.ide=$fromIde") - - where: - flavor | remoteProject | fromIde - 'Java' | "santaTrackerJava" | false - 'Java' | "santaTrackerJava" | true - // TODO:instant-execution Kotlin 1.3.70 - // 'Kotlin' | "santaTrackerKotlin" | false - // 'Kotlin' | "santaTrackerKotlin" | true - } - - @Unroll - def "clean assembleDebug on Santa Tracker #flavor (fromIde=#fromIde)"() { - - given: - copyRemoteProject(remoteProject) - withAgpNightly() - - when: - instantRun("assembleDebug", "--no-build-cache", "-Pandroid.injected.invoked.from.ide=$fromIde") - - and: - run 'clean' - - then: - // Instant execution avoid registering the listener inside Android plugin - instantRun("assembleDebug", "--no-build-cache", "-Pandroid.injected.invoked.from.ide=$fromIde") - - where: - flavor | remoteProject | fromIde - 'Java' | "santaTrackerJava" | false - 'Java' | "santaTrackerJava" | true - // TODO:instant-execution Kotlin 1.3.70 - // 'Kotlin' | "santaTrackerKotlin" | false - // 'Kotlin' | "santaTrackerKotlin" | true - } -} diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/build.gradle b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/build.gradle deleted file mode 100644 index 49fdc4bcdcf2..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/build.gradle +++ /dev/null @@ -1,29 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 28 - buildToolsVersion "29.0.2" - defaultConfig { - applicationId "com.example.instantapplication" - minSdkVersion 26 - targetSdkVersion 28 - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } -} - -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'androidx.appcompat:appcompat:1.0.2' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test.ext:junit:1.1.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' -} diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/proguard-rules.pro b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/proguard-rules.pro deleted file mode 100644 index f1b424510da5..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/androidTest/java/com/example/instantapplication/ExampleInstrumentedTest.java b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/androidTest/java/com/example/instantapplication/ExampleInstrumentedTest.java deleted file mode 100644 index 1c1af1fc3354..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/androidTest/java/com/example/instantapplication/ExampleInstrumentedTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.example.instantapplication; - -import android.content.Context; - -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); - - assertEquals("com.example.instantapplication", appContext.getPackageName()); - } -} diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/AndroidManifest.xml b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/AndroidManifest.xml deleted file mode 100644 index 35aa31d8ed1d..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/java/com/example/instantapplication/MainActivity.java b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/java/com/example/instantapplication/MainActivity.java deleted file mode 100644 index 8fe7761be80d..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/java/com/example/instantapplication/MainActivity.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.example.instantapplication; - -import androidx.appcompat.app.AppCompatActivity; - -import android.os.Bundle; - -public class MainActivity extends AppCompatActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - } -} diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index 1f6bb290603d..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/drawable/ic_launcher_background.xml b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 0d025f9bf6b6..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/layout/activity_main.xml b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/layout/activity_main.xml deleted file mode 100644 index 4fc244418b5f..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index eca70cfe52ea..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index eca70cfe52ea..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-hdpi/ic_launcher.png b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 898f3ed59ac9..000000000000 Binary files a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index dffca3601eba..000000000000 Binary files a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-mdpi/ic_launcher.png b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 64ba76f75e9c..000000000000 Binary files a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index dae5e082342f..000000000000 Binary files a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index e5ed46597ea8..000000000000 Binary files a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 14ed0af35023..000000000000 Binary files a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index b0907cac3bfd..000000000000 Binary files a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index d8ae03154975..000000000000 Binary files a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 2c18de9e6610..000000000000 Binary files a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index beed3cdd2c32..000000000000 Binary files a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/values/colors.xml b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/values/colors.xml deleted file mode 100644 index 69b22338c651..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/values/colors.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - #008577 - #00574B - #D81B60 - diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/values/strings.xml b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/values/strings.xml deleted file mode 100644 index 22f17c58dfa4..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - InstantApplication - diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/values/styles.xml b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/values/styles.xml deleted file mode 100644 index 5885930df6d1..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/test/java/com/example/instantapplication/ExampleUnitTest.java b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/test/java/com/example/instantapplication/ExampleUnitTest.java deleted file mode 100644 index 469fbf0616e4..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/app/src/test/java/com/example/instantapplication/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.example.instantapplication; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/build.gradle b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/build.gradle deleted file mode 100644 index ccb7b635afb4..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - repositories { - google() - jcenter() - } - dependencies { - // This version is a placeholder replaced by the integration test - // It denotes the Android Studio version used to generate that build - classpath 'com.android.tools.build:gradle:3.6.0-alpha06' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - google() - jcenter() - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/gradle.properties b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/gradle.properties deleted file mode 100644 index c73d2393ba88..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/gradle.properties +++ /dev/null @@ -1,19 +0,0 @@ -# Project-wide Gradle settings. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx1536m -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true -# AndroidX package structure to make it clearer which packages are bundled with the -# Android operating system, and which are packaged with your app's APK -# https://developer.android.com/topic/libraries/support-library/androidx-rn -android.useAndroidX=true -# Automatically convert third-party libraries to use AndroidX -android.enableJetifier=true diff --git a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/settings.gradle b/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/settings.gradle deleted file mode 100644 index df5cfc3c7f2a..000000000000 --- a/subprojects/instant-execution/src/integTest/resources/org/gradle/instantexecution/builds/android-3.6-mini/settings.gradle +++ /dev/null @@ -1,3 +0,0 @@ -rootProject.name = 'android-3.6-minimal' - -include ':app' diff --git a/subprojects/internal-integ-testing/internal-integ-testing.gradle.kts b/subprojects/internal-integ-testing/internal-integ-testing.gradle.kts index 2fd8549d492e..73eef702e180 100644 --- a/subprojects/internal-integ-testing/internal-integ-testing.gradle.kts +++ b/subprojects/internal-integ-testing/internal-integ-testing.gradle.kts @@ -93,7 +93,15 @@ val prepareVersionsInfo = tasks.register("prepareVersionsIn mostRecentSnapshot = releasedVersions.mostRecentSnapshot } -sourceSets.main { output.dir(mapOf("builtBy" to prepareVersionsInfo), generatedResourcesDir) } +val copyAgpVersionsInfo by tasks.registering(Copy::class) { + from(rootProject.layout.projectDirectory.file("gradle/dependency-management/agp-versions.properties")) + into(temporaryDir) +} + +sourceSets.main { + output.dir(mapOf("builtBy" to prepareVersionsInfo), generatedResourcesDir) + output.dir(copyAgpVersionsInfo) +} @CacheableTask open class PrepareVersionsInfo : DefaultTask() { diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/BuildOperationTreeFixture.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/BuildOperationTreeFixture.groovy new file mode 100644 index 000000000000..07feb884003e --- /dev/null +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/BuildOperationTreeFixture.groovy @@ -0,0 +1,145 @@ +/* + * Copyright 2020 the original author or authors. + * + * 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 org.gradle.integtests.fixtures + +import org.gradle.api.specs.Spec +import org.gradle.api.specs.Specs +import org.gradle.internal.logging.events.StyledTextOutputEvent +import org.gradle.internal.operations.BuildOperationType +import org.gradle.internal.operations.BuildOperationTypes +import org.gradle.internal.operations.trace.BuildOperationRecord +import org.gradle.internal.operations.trace.BuildOperationTree + +import java.util.regex.Pattern + + +class BuildOperationTreeFixture extends BuildOperationTreeQueries { + + private final BuildOperationTree operations + + BuildOperationTreeFixture(BuildOperationTree operations) { + this.operations = operations + } + + @Override + @SuppressWarnings("GrUnnecessaryPublicModifier") + public > BuildOperationRecord root(Class type, Spec predicate = Specs.satisfyAll()) { + def detailsType = BuildOperationTypes.detailsType(type) + def roots = operations.roots.findAll { + it.detailsType && detailsType.isAssignableFrom(it.detailsType) && predicate.isSatisfiedBy(it) + } + assert roots.size() == 1 + return roots[0] + } + + @Override + @SuppressWarnings("GrUnnecessaryPublicModifier") + public > BuildOperationRecord first(Class type, Spec predicate = Specs.satisfyAll()) { + def detailsType = BuildOperationTypes.detailsType(type) + return operations.records.values().find { + it.detailsType && detailsType.isAssignableFrom(it.detailsType) && predicate.isSatisfiedBy(it) + } + } + + @Override + @SuppressWarnings("GrUnnecessaryPublicModifier") + public > boolean isType(BuildOperationRecord record, Class type) { + assert record.detailsType + def detailsType = BuildOperationTypes.detailsType(type) + detailsType.isAssignableFrom(record.detailsType) + } + + @Override + @SuppressWarnings("GrUnnecessaryPublicModifier") + public > List all(Class type, Spec predicate = Specs.satisfyAll()) { + def detailsType = BuildOperationTypes.detailsType(type) + return operations.records.values().findAll { + it.detailsType && detailsType.isAssignableFrom(it.detailsType) && predicate.isSatisfiedBy(it) + }.toList() + } + + @Override + BuildOperationRecord first(Pattern displayName) { + return operations.records.values().find { it.displayName ==~ displayName } + } + + @Override + List all(Pattern displayName) { + return operations.records.values().findAll { it.displayName ==~ displayName } + } + + @Override + BuildOperationRecord only(Pattern displayName) { + def records = all(displayName) + assert records.size() == 1: "Error matching pattern: $displayName" + return records.first() + } + + @Override + List parentsOf(BuildOperationRecord child) { + def parents = [] + def parentId = child.parentId + while (parentId != null) { + def parent = operations.records.get(parentId) + parents.add(0, parent) + parentId = parent.parentId + } + return parents + } + + @Override + void none(Pattern displayName) { + def records = all(displayName) + assert records.size() == 0 + } + + @Override + void debugTree( + Spec predicate = Specs.SATISFIES_ALL, + Spec progressPredicate = Specs.SATISFIES_ALL + ) { + operations.roots.each { debugOpTree(it, 0, predicate, progressPredicate) } + } + + private void debugOpTree( + BuildOperationRecord op, + int level, + Spec predicate, + Spec progressPredicate + ) { + if (predicate.isSatisfiedBy(op)) { + println "${' ' * level}(${op.displayName}, id: $op.id${op.detailsType ? ", details type: ${simpleClassName(op.detailsType)}" : ''})${op.details ? " $op.details" : ''}" + if (progressPredicate.isSatisfiedBy(op)) { + op.progress.each { p -> + def repr = p.hasDetailsOfType(StyledTextOutputEvent) ? p.details.spans*.text.join('') : "$p.detailsType.simpleName ${p.details?.toString() ?: ''}\n" + print "${' ' * (level + 1)} $repr" + } + } + op.children.each { debugOpTree(it, level + 1, predicate, progressPredicate) } + } + } + + private static String simpleClassName(Class detailsType) { + if (!detailsType) { + return null + } else { + // Class.simpleName returns "" for certain anonymous classes and unhelpful things like "Details" for our op interfaces + String clsName = detailsType.interfaces.length == 0 ? detailsType.name : detailsType.interfaces.first().name + clsName.substring(clsName.lastIndexOf('.') + 1) + } + } +} diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/BuildOperationTreeQueries.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/BuildOperationTreeQueries.groovy new file mode 100644 index 000000000000..6d3af66a14a2 --- /dev/null +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/BuildOperationTreeQueries.groovy @@ -0,0 +1,249 @@ +/* + * Copyright 2020 the original author or authors. + * + * 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 org.gradle.integtests.fixtures + +import org.gradle.api.Action +import org.gradle.api.specs.Spec +import org.gradle.api.specs.Specs +import org.gradle.internal.operations.BuildOperationType +import org.gradle.internal.operations.BuildOperationTypes +import org.gradle.internal.operations.trace.BuildOperationRecord + +import java.util.concurrent.ConcurrentLinkedQueue +import java.util.regex.Pattern + +abstract class BuildOperationTreeQueries { + + abstract > BuildOperationRecord root(Class type, Spec predicate = Specs.satisfyAll()) + + abstract > BuildOperationRecord first(Class type, Spec predicate = Specs.satisfyAll()) + + abstract > boolean isType(BuildOperationRecord record, Class type) + + abstract > List all(Class type, Spec predicate = Specs.satisfyAll()) + + @SuppressWarnings("GrUnnecessaryPublicModifier") + public > void none(Class type, Spec predicate = Specs.satisfyAll()) { + assert all(type, predicate).isEmpty() + } + + @SuppressWarnings("GrUnnecessaryPublicModifier") + public > BuildOperationRecord only(Class type, Spec predicate = Specs.satisfyAll()) { + def records = all(type, predicate) + assert records.size() == 1 + return records.first() + } + + BuildOperationRecord first(String displayName) { + first(Pattern.compile(Pattern.quote(displayName))) + } + + abstract BuildOperationRecord first(Pattern displayName) + + List all(String displayName) { + return all(Pattern.compile(Pattern.quote(displayName))) + } + + abstract List all(Pattern displayName) + + BuildOperationRecord only(String displayName) { + return only(Pattern.compile(Pattern.quote(displayName))) + } + + abstract BuildOperationRecord only(Pattern displayName) + + abstract List parentsOf(BuildOperationRecord child) + + void none(String displayName) { + none(Pattern.compile(Pattern.quote(displayName))) + } + + abstract void none(Pattern displayName) + + Map result(String displayName) { + first(displayName).result + } + + String failure(String displayName) { + first(displayName).failure + } + + boolean hasOperation(String displayName) { + first(displayName) != null + } + + @SuppressWarnings("GrUnnecessaryPublicModifier") + public > boolean hasOperation(Class type) { + first(type) != null + } + + @SuppressWarnings(["GrMethodMayBeStatic", "GrUnnecessaryPublicModifier"]) + public > List search(BuildOperationRecord parent, Class type, Spec predicate = Specs.SATISFIES_ALL) { + def detailsType = BuildOperationTypes.detailsType(type) + Spec typeSpec = { + it.detailsType && detailsType.isAssignableFrom(it.detailsType) + } + search(parent, Specs.intersect(typeSpec, predicate)) + } + + @SuppressWarnings(["GrMethodMayBeStatic", "GrUnnecessaryPublicModifier"]) + public > List children(BuildOperationRecord parent, Class type, Spec predicate = Specs.SATISFIES_ALL) { + Spec parentSpec = { + it.parentId == parent.id + } + return search(parent, type, Specs.intersect(parentSpec, predicate)) + } + + @SuppressWarnings("GrMethodMayBeStatic") + List search(BuildOperationRecord parent, Spec predicate = Specs.SATISFIES_ALL) { + def matches = [] + walk(parent) { + if (predicate.isSatisfiedBy(it)) { + matches << it + } + } + matches + } + + @SuppressWarnings("GrMethodMayBeStatic") + void walk(BuildOperationRecord parent, Action action) { + def search = new ConcurrentLinkedQueue(parent.children) + + def operation = search.poll() + while (operation != null) { + action.execute(operation) + search.addAll(operation.children) + operation = search.poll() + } + } + + void orderedSerialSiblings(BuildOperationRecord... expectedOrder) { + def expectedOrderList = expectedOrder.toList() + assert expectedOrder*.parentId.unique().size() == 1 + def startTimeOrdered = expectedOrderList.sort(false) { it.startTime } + assert expectedOrderList == startTimeOrdered + def endTimeOrdered = expectedOrderList.sort(false) { it.endTime } + assert endTimeOrdered == startTimeOrdered + } + + + private static class TimePoint implements Comparable { + private final boolean end + private final long time + private final BuildOperationRecord operation + + TimePoint(BuildOperationRecord operation, long time) { + this(operation, time, false) + } + + TimePoint(BuildOperationRecord operation, long time, boolean end) { + this.operation = operation + this.time = time + this.end = end + } + + @Override + int compareTo(TimePoint o) { + if (o.time > time) { + return -1 + } else if (o.time < time) { + return 1 + } else { + if (end && o.end) { + return 0 + } else if (end) { + return -1 + } else { + return 1 + } + } + } + + @Override + String toString() { + if (end) { + time + "E" + } else { + time + "S" + } + } + } + + /** + * Asserts that no more than maximumConcurrentOperations of the given type of build operation are executing at the same time. + * + * @param type type of build operation + * @param maximumConcurrentOperations maximum concurrent operations allowed + * @param concurrencyExpected whether or not to expect _any_ concurrency + */ + void assertConcurrentOperationsDoNotExceed(Class type, int maximumConcurrentOperations, boolean concurrencyExpected = false) { + int maxConcurrency = getMaximumConcurrentOperations(type) + assert maxConcurrency <= maximumConcurrentOperations + if (concurrencyExpected) { + assert maxConcurrency > 1: "No operations were executed concurrently" + } + } + + void assertConcurrentOperationsExecuted(Class type) { + assert getMaximumConcurrentOperations(type) > 1: "No operations were executed concurrently" + } + + int getMaximumConcurrentOperations(Class type) { + def highWaterPoint = 0 + def allOperations = all(type) + + List points = [] + + allOperations.each { + points.add(new TimePoint(it, it.startTime)) + points.add(new TimePoint(it, it.endTime, true)) + } + + def concurrentOperations = [] + points.sort().each { + if (it.end) { + concurrentOperations.remove(it.operation) + } else { + if ((it.operation.endTime - it.operation.startTime) > 0) { + concurrentOperations.add(it.operation) + } + } + if (concurrentOperations.size() > highWaterPoint) { + highWaterPoint = concurrentOperations.size() + } + } + return highWaterPoint + } + + /** + * Return a list of operations (possibly empty) that executed concurrently with the given operation. + */ + List getOperationsConcurrentWith(Class type, BuildOperationRecord operation) { + def concurrentOperations = [] + all(type).each { candidate -> + if (candidate != operation && candidate.startTime < operation.endTime && candidate.endTime > operation.startTime) { + concurrentOperations << candidate + } + } + return concurrentOperations + } + + abstract void debugTree( + Spec predicate = Specs.SATISFIES_ALL, + Spec progressPredicate = Specs.SATISFIES_ALL + ) +} diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/BuildOperationsFixture.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/BuildOperationsFixture.groovy index 298924e588e2..fbf1997cb918 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/BuildOperationsFixture.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/BuildOperationsFixture.groovy @@ -16,327 +16,86 @@ package org.gradle.integtests.fixtures -import org.gradle.api.Action + import org.gradle.api.specs.Spec import org.gradle.api.specs.Specs import org.gradle.integtests.fixtures.executer.GradleExecuter -import org.gradle.internal.logging.events.StyledTextOutputEvent import org.gradle.internal.operations.BuildOperationType -import org.gradle.internal.operations.BuildOperationTypes import org.gradle.internal.operations.trace.BuildOperationRecord import org.gradle.internal.operations.trace.BuildOperationTrace -import org.gradle.internal.operations.trace.BuildOperationTree import org.gradle.test.fixtures.file.TestDirectoryProvider -import java.util.concurrent.ConcurrentLinkedQueue import java.util.regex.Pattern -class BuildOperationsFixture { - - private final String path +class BuildOperationsFixture extends BuildOperationTreeQueries { - private BuildOperationTree operations + private BuildOperationTreeFixture tree BuildOperationsFixture(GradleExecuter executer, TestDirectoryProvider projectDir) { - this.path = projectDir.testDirectory.file("operations").absolutePath + String path = projectDir.testDirectory.file("operations").absolutePath executer.beforeExecute { executer.withArgument("-D$BuildOperationTrace.SYSPROP=$path") } executer.afterExecute { - operations = BuildOperationTrace.read(path) + tree = new BuildOperationTreeFixture(BuildOperationTrace.read(path)) } } + @Override @SuppressWarnings("GrUnnecessaryPublicModifier") public > BuildOperationRecord root(Class type, Spec predicate = Specs.satisfyAll()) { - def detailsType = BuildOperationTypes.detailsType(type) - def roots = operations.roots.findAll { - it.detailsType && detailsType.isAssignableFrom(it.detailsType) && predicate.isSatisfiedBy(it) - } - assert roots.size() == 1 - return roots[0] + return tree.root(type, predicate) } + @Override @SuppressWarnings("GrUnnecessaryPublicModifier") public > BuildOperationRecord first(Class type, Spec predicate = Specs.satisfyAll()) { - def detailsType = BuildOperationTypes.detailsType(type) - operations.records.values().find { - it.detailsType && detailsType.isAssignableFrom(it.detailsType) && predicate.isSatisfiedBy(it) - } - } - - static > boolean isType(BuildOperationRecord record, Class type) { - assert record.detailsType - def detailsType = BuildOperationTypes.detailsType(type) - detailsType.isAssignableFrom(record.detailsType) - } - - @SuppressWarnings("GrUnnecessaryPublicModifier") - public > List all(Class type, Spec predicate = Specs.satisfyAll()) { - def detailsType = BuildOperationTypes.detailsType(type) - operations.records.values().findAll { - it.detailsType && detailsType.isAssignableFrom(it.detailsType) && predicate.isSatisfiedBy(it) - }.toList() + return tree.first(type, predicate) } + @Override @SuppressWarnings("GrUnnecessaryPublicModifier") - public > void none(Class type, Spec predicate = Specs.satisfyAll()) { - assert all(type, predicate).isEmpty() + public > boolean isType(BuildOperationRecord record, Class type) { + return tree.isType(record, type) } + @Override @SuppressWarnings("GrUnnecessaryPublicModifier") - public > BuildOperationRecord only(Class type, Spec predicate = Specs.satisfyAll()) { - def records = all(type, predicate) - assert records.size() == 1 - records.first() - } - - BuildOperationRecord first(String displayName) { - first(Pattern.compile(Pattern.quote(displayName))) + public > List all(Class type, Spec predicate = Specs.satisfyAll()) { + return tree.all(type, predicate) } + @Override BuildOperationRecord first(Pattern displayName) { - operations.records.values().find { it.displayName ==~ displayName } - } - - List all(String displayName) { - all(Pattern.compile(Pattern.quote(displayName))) + return tree.first(displayName) } + @Override List all(Pattern displayName) { - operations.records.values().findAll { it.displayName ==~ displayName } - } - - BuildOperationRecord only(String displayName) { - only(Pattern.compile(Pattern.quote(displayName))) - } - - List parentsOf(BuildOperationRecord child) { - def parents = [] - def parentId = child.parentId - while (parentId != null) { - def parent = operations.records.get(parentId) - parents.add(0, parent) - parentId = parent.parentId - } - parents + return tree.all(displayName) } + @Override BuildOperationRecord only(Pattern displayName) { - def records = all(displayName) - assert records.size() == 1: "Error matching pattern: $displayName" - records.first() + return tree.only(displayName) } - void none(String displayName) { - none(Pattern.compile(Pattern.quote(displayName))) + @Override + List parentsOf(BuildOperationRecord child) { + return tree.parentsOf(child) } + @Override void none(Pattern displayName) { - def records = all(displayName) - assert records.size() == 0 - } - - Map result(String displayName) { - first(displayName).result - } - - String failure(String displayName) { - first(displayName).failure - } - - boolean hasOperation(String displayName) { - first(displayName) != null - } - - @SuppressWarnings("GrUnnecessaryPublicModifier") - public > boolean hasOperation(Class type) { - first(type) != null - } - - @SuppressWarnings(["GrMethodMayBeStatic", "GrUnnecessaryPublicModifier"]) - public > List search(BuildOperationRecord parent, Class type, Spec predicate = Specs.SATISFIES_ALL) { - def detailsType = BuildOperationTypes.detailsType(type) - Spec typeSpec = { - it.detailsType && detailsType.isAssignableFrom(it.detailsType) - } - search(parent, Specs.intersect(typeSpec, predicate)) - } - - @SuppressWarnings(["GrMethodMayBeStatic", "GrUnnecessaryPublicModifier"]) - public > List children(BuildOperationRecord parent, Class type, Spec predicate = Specs.SATISFIES_ALL) { - Spec parentSpec = { - it.parentId == parent.id - } - return search(parent, type, Specs.intersect(parentSpec, predicate)) - } - - @SuppressWarnings("GrMethodMayBeStatic") - List search(BuildOperationRecord parent, Spec predicate = Specs.SATISFIES_ALL) { - def matches = [] - walk(parent) { - if (predicate.isSatisfiedBy(it)) { - matches << it - } - } - matches - } - - @SuppressWarnings("GrMethodMayBeStatic") - void walk(BuildOperationRecord parent, Action action) { - def search = new ConcurrentLinkedQueue(parent.children) - - def operation = search.poll() - while (operation != null) { - action.execute(operation) - search.addAll(operation.children) - operation = search.poll() - } - } - - void orderedSerialSiblings(BuildOperationRecord... expectedOrder) { - def expectedOrderList = expectedOrder.toList() - assert expectedOrder*.parentId.unique().size() == 1 - def startTimeOrdered = expectedOrderList.sort(false) { it.startTime } - assert expectedOrderList == startTimeOrdered - def endTimeOrdered = expectedOrderList.sort(false) { it.endTime } - assert endTimeOrdered == startTimeOrdered - } - - static class TimePoint implements Comparable { - private final boolean end - private final long time - private final BuildOperationRecord operation - - TimePoint(BuildOperationRecord operation, long time) { - this(operation, time, false) - } - - TimePoint(BuildOperationRecord operation, long time, boolean end) { - this.operation = operation - this.time = time - this.end = end - } - - @Override - int compareTo(TimePoint o) { - if (o.time > time) { - return -1 - } else if (o.time < time) { - return 1 - } else { - if (end && o.end) { - return 0 - } else if (end) { - return -1 - } else { - return 1 - } - } - } - - @Override - String toString() { - if (end) { - time + "E" - } else { - time + "S" - } - } - } - - /** - * Asserts that no more than maximumConcurrentOperations of the given type of build operation are executing at the same time. - * - * @param type type of build operation - * @param maximumConcurrentOperations maximum concurrent operations allowed - * @param concurrencyExpected whether or not to expect _any_ concurrency - */ - void assertConcurrentOperationsDoNotExceed(Class type, int maximumConcurrentOperations, boolean concurrencyExpected = false) { - int maxConcurrency = getMaximumConcurrentOperations(type) - assert maxConcurrency <= maximumConcurrentOperations - if (concurrencyExpected) { - assert maxConcurrency > 1: "No operations were executed concurrently" - } - } - - void assertConcurrentOperationsExecuted(Class type) { - assert getMaximumConcurrentOperations(type) > 1: "No operations were executed concurrently" - } - - int getMaximumConcurrentOperations(Class type) { - def highWaterPoint = 0 - def allOperations = all(type) - - List points = [] - - allOperations.each { - points.add(new TimePoint(it, it.startTime)) - points.add(new TimePoint(it, it.endTime, true)) - } - - def concurrentOperations = [] - points.sort().each { - if (it.end) { - concurrentOperations.remove(it.operation) - } else { - if ((it.operation.endTime - it.operation.startTime) > 0) { - concurrentOperations.add(it.operation) - } - } - if (concurrentOperations.size() > highWaterPoint) { - highWaterPoint = concurrentOperations.size() - } - } - return highWaterPoint - } - - /** - * Return a list of operations (possibly empty) that executed concurrently with the given operation. - */ - List getOperationsConcurrentWith(Class type, BuildOperationRecord operation) { - def concurrentOperations = [] - all(type).each { candidate -> - if (candidate != operation && candidate.startTime < operation.endTime && candidate.endTime > operation.startTime) { - concurrentOperations << candidate - } - } - return concurrentOperations + tree.none(displayName) } + @Override void debugTree( Spec predicate = Specs.SATISFIES_ALL, Spec progressPredicate = Specs.SATISFIES_ALL ) { - operations.roots.each { debugOpTree(it, 0, predicate, progressPredicate) } - } - - private void debugOpTree( - BuildOperationRecord op, - int level, - Spec predicate, - Spec progressPredicate - ) { - if (predicate.isSatisfiedBy(op)) { - println "${' ' * level}(${op.displayName}, id: $op.id${op.detailsType ? ", details type: ${simpleClassName(op.detailsType)}" : ''})${op.details ? " $op.details" : ''}" - if (progressPredicate.isSatisfiedBy(op)) { - op.progress.each { p -> - def repr = p.hasDetailsOfType(StyledTextOutputEvent) ? p.details.spans*.text.join('') : "$p.detailsType.simpleName ${p.details?.toString() ?: ''}\n" - print "${' ' * (level + 1)} $repr" - } - } - op.children.each { debugOpTree(it, level + 1, predicate, progressPredicate) } - } - } - - private static String simpleClassName(Class detailsType) { - if (!detailsType) { - return null - } else { - // Class.simpleName returns "" for certain anonymous classes and unhelpful things like "Details" for our op interfaces - String clsName = detailsType.interfaces.length == 0 ? detailsType.name : detailsType.interfaces.first().name - clsName.substring(clsName.lastIndexOf('.') + 1) - } + tree.debugTree(predicate, progressPredicate) } } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/UnsupportedWithInstantExecution.java b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/UnsupportedWithInstantExecution.java index 7b028bf54453..fe4d57ff4666 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/UnsupportedWithInstantExecution.java +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/UnsupportedWithInstantExecution.java @@ -32,5 +32,12 @@ @Target(ElementType.METHOD) @ExtensionAnnotation(UnsupportedWithInstantExecutionExtension.class) public @interface UnsupportedWithInstantExecution { + String[] bottomSpecs() default {}; + + /** + * Declare regular expressions matching the iteration name. + * Defaults to an empty array, meaning this annotation applies to all iterations of the annotated feature. + */ + String[] iterationMatchers() default {}; } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/UnsupportedWithInstantExecutionExtension.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/UnsupportedWithInstantExecutionExtension.groovy index d3a1a73eca8c..5d8806d7749b 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/UnsupportedWithInstantExecutionExtension.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/UnsupportedWithInstantExecutionExtension.groovy @@ -18,6 +18,8 @@ package org.gradle.integtests.fixtures import org.gradle.integtests.fixtures.executer.GradleContextualExecuter import org.spockframework.runtime.extension.AbstractAnnotationDrivenExtension +import org.spockframework.runtime.extension.IMethodInterceptor +import org.spockframework.runtime.extension.IMethodInvocation import org.spockframework.runtime.model.FeatureInfo import static org.gradle.integtests.fixtures.ToBeFixedForInstantExecutionExtension.isEnabledBottomSpec @@ -28,8 +30,37 @@ class UnsupportedWithInstantExecutionExtension extends AbstractAnnotationDrivenE @Override void visitFeatureAnnotation(UnsupportedWithInstantExecution annotation, FeatureInfo feature) { if (GradleContextualExecuter.isInstant()) { - if (isEnabledBottomSpec(annotation.bottomSpecs(), { feature.parent.bottomSpec.name == it })) { + if (isAllIterations(annotation.iterationMatchers()) && isEnabledBottomSpec(annotation.bottomSpecs(), { feature.parent.bottomSpec.name == it })) { feature.skipped = true + } else { + feature.iterationInterceptors.add(new IterationMatchingMethodInterceptor(annotation.iterationMatchers())) + } + } + } + + static boolean iterationMatches(String[] iterationMatchers, String iterationName) { + return isAllIterations(iterationMatchers) || iterationMatchers.any { iterationName.matches(it) } + } + + private static boolean isAllIterations(String[] iterationMatchers) { + return iterationMatchers.length == 0 + } + + private static class IterationMatchingMethodInterceptor implements IMethodInterceptor { + + private final String[] iterationMatchers + + IterationMatchingMethodInterceptor(String[] iterationMatchers) { + this.iterationMatchers = iterationMatchers + } + + @Override + void intercept(IMethodInvocation invocation) throws Throwable { + if (!iterationMatches(iterationMatchers, invocation.iteration.name)) { + invocation.proceed() + } else { + // This will show up in test reports, necessary because we can't mark the test as skipped + println("Skipping test @${UnsupportedWithInstantExecution.simpleName}") } } } diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/UnsupportedWithInstantExecutionRule.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/UnsupportedWithInstantExecutionRule.groovy index ed88f2d7a2c5..84f35bfef944 100644 --- a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/UnsupportedWithInstantExecutionRule.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/UnsupportedWithInstantExecutionRule.groovy @@ -22,6 +22,7 @@ import org.junit.runner.Description import org.junit.runners.model.Statement import static org.gradle.integtests.fixtures.ToBeFixedForInstantExecutionExtension.isEnabledBottomSpec +import static org.gradle.integtests.fixtures.UnsupportedWithInstantExecutionExtension.iterationMatches import static org.junit.Assume.assumeFalse @@ -33,7 +34,9 @@ class UnsupportedWithInstantExecutionRule implements TestRule { if (!GradleContextualExecuter.isInstant() || annotation == null) { return base } - if (isEnabledBottomSpec(annotation.bottomSpecs(), { description.className.endsWith(".$it") })) { + def enabledBottomSpec = isEnabledBottomSpec(annotation.bottomSpecs(), { description.className.endsWith(".$it") }) + def enabledIteration = iterationMatches(annotation.iterationMatchers(), description.methodName) + if (enabledBottomSpec && enabledIteration) { return new SkippingRuleStatement(base) } return base diff --git a/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/InstantExecutionBuildOperationsFixture.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/instantexecution/InstantExecutionBuildOperationsFixture.groovy similarity index 75% rename from subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/InstantExecutionBuildOperationsFixture.groovy rename to subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/instantexecution/InstantExecutionBuildOperationsFixture.groovy index e90841416ea2..93859f9bed5a 100644 --- a/subprojects/instant-execution/src/integTest/groovy/org/gradle/instantexecution/InstantExecutionBuildOperationsFixture.groovy +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/instantexecution/InstantExecutionBuildOperationsFixture.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,10 @@ * limitations under the License. */ -package org.gradle.instantexecution +package org.gradle.integtests.fixtures.instantexecution -import org.gradle.integtests.fixtures.BuildOperationsFixture -import org.gradle.integtests.fixtures.executer.GradleExecuter +import org.gradle.integtests.fixtures.BuildOperationTreeQueries import org.gradle.internal.operations.trace.BuildOperationRecord -import org.gradle.test.fixtures.file.TestDirectoryProvider import static org.hamcrest.CoreMatchers.notNullValue import static org.hamcrest.CoreMatchers.nullValue @@ -28,10 +26,10 @@ import static org.junit.Assert.assertThat class InstantExecutionBuildOperationsFixture { - final BuildOperationsFixture operations + final BuildOperationTreeQueries operations - InstantExecutionBuildOperationsFixture(GradleExecuter executer, TestDirectoryProvider projectDir) { - operations = new BuildOperationsFixture(executer, projectDir) + InstantExecutionBuildOperationsFixture(BuildOperationTreeQueries operations) { + this.operations = operations } void assertStateLoaded() { diff --git a/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/versions/AndroidGradlePluginVersions.groovy b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/versions/AndroidGradlePluginVersions.groovy new file mode 100644 index 000000000000..d20e36d6ed97 --- /dev/null +++ b/subprojects/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/versions/AndroidGradlePluginVersions.groovy @@ -0,0 +1,138 @@ +/* + * Copyright 2020 the original author or authors. + * + * 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 org.gradle.integtests.fixtures.versions + +import org.gradle.integtests.fixtures.executer.GradleExecuter +import org.gradle.internal.Factory +import org.gradle.test.fixtures.file.TestFile + + +/** + * Android Gradle Plugin Versions. + * + * If you need to iterate locally on changes to AGP sources: + * - hardcode latest nightly to `4.0.0-dev` + * - change the repository url in `AGP_NIGHTLY_REPOSITORY_DECLARATION` to `file:///path/to/agp-src/out/repo` + * - run `./gradlew :publishAndroidGradleLocal` in `/path/to/agp-src/tools` + */ +class AndroidGradlePluginVersions { + + public static final String OVERRIDE_VERSION_CHECK = '-Dcom.android.build.gradle.overrideVersionCheck=true' + + private static final String AGP_NIGHTLY_REPOSITORY_DECLARATION = ''' + maven { + name = 'agp-nightlies' + url = 'https://repo.gradle.org/gradle/ext-snapshots-local/' + } + ''' + + private static final String AGP_NIGHTLY_REPOSITORY_INIT_SCRIPT = """ + allprojects { + buildscript { + repositories { + $AGP_NIGHTLY_REPOSITORY_DECLARATION + } + } + repositories { + $AGP_NIGHTLY_REPOSITORY_DECLARATION + } + } + """ + + static void usingAgpVersion(GradleExecuter executer, TestFile buildFile, String agpVersion) { + println "> Using AGP version ${agpVersion}" + buildFile.text = replaceAgpVersion(buildFile.text, agpVersion) + executer.beforeExecute { + withArgument(OVERRIDE_VERSION_CHECK) + } + if (isAgpNightly(agpVersion)) { + usingAgpNightlyRepository(executer) + } + } + + static boolean isAgpNightly(String agpVersion) { + return agpVersion.contains("-") && agpVersion.substring(agpVersion.indexOf("-") + 1).matches("^[0-9].*") + } + + static void usingAgpNightlyRepository(GradleExecuter executer) { + def init = createAgpNightlyRepositoryInitScript() + executer.beforeExecute { + usingInitScript(init) + } + } + + static File createAgpNightlyRepositoryInitScript() { + File mirrors = File.createTempFile("mirrors", ".gradle") + mirrors.deleteOnExit() + mirrors << AGP_NIGHTLY_REPOSITORY_INIT_SCRIPT + return mirrors + } + + private static String replaceAgpVersion(String scriptText, String agpVersion) { + def regex = "(['\"]com.android.tools.build:gradle:).+(['\"])" + scriptText.readLines().any { it.matches(".*${regex}.*") } + return scriptText.replaceAll(regex, "${'$'}1$agpVersion${'$'}2") + } + + private final Factory propertiesFactory + private Properties properties + + AndroidGradlePluginVersions() { + this(new ClasspathVersionSource("agp-versions.properties", AndroidGradlePluginVersions.classLoader)) + } + + private AndroidGradlePluginVersions(Factory propertiesFactory) { + this.propertiesFactory = propertiesFactory + } + + List getLatests() { + return getVersionList("latests") + } + + String getNightly() { + return getVersion("nightly") + } + + List getLatestsPlusNightly() { + return [latests, [nightly]].flatten() as List + } + + List getLatestsFromMinor(String lowerBound) { + assert lowerBound.matches("^[0-9]+\\.[0-9]+\$") + def withBound = (latests + lowerBound).sort() + return withBound.subList(withBound.indexOf(lowerBound) + 1, withBound.size()) + } + + List getLatestsFromMinorPlusNightly(String lowerBound) { + return [getLatestsFromMinor(lowerBound), [nightly]].flatten() as List + } + + private List getVersionList(String name) { + return loadedProperties().getProperty(name).split(",") + } + + private String getVersion(String name) { + return loadedProperties().getProperty(name) + } + + private Properties loadedProperties() { + if (properties == null) { + properties = propertiesFactory.create() + } + return properties + } +} diff --git a/subprojects/language-jvm/src/main/java/org/gradle/api/tasks/compile/AbstractCompile.java b/subprojects/language-jvm/src/main/java/org/gradle/api/tasks/compile/AbstractCompile.java index ce12b4a5b2fe..fd0d63567b54 100644 --- a/subprojects/language-jvm/src/main/java/org/gradle/api/tasks/compile/AbstractCompile.java +++ b/subprojects/language-jvm/src/main/java/org/gradle/api/tasks/compile/AbstractCompile.java @@ -19,7 +19,7 @@ import org.gradle.api.file.Directory; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.FileCollection; -import org.gradle.api.internal.provider.AbstractReadOnlyProvider; +import org.gradle.api.internal.provider.AbstractMinimalProvider; import org.gradle.api.model.ReplacedBy; import org.gradle.api.provider.Provider; import org.gradle.api.tasks.Classpath; @@ -27,7 +27,6 @@ import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.SourceTask; -import javax.annotation.Nullable; import java.io.File; /** @@ -98,7 +97,6 @@ public void setDestinationDir(File destinationDir) { * Sets the directory to generate the {@code .class} files into. * * @param destinationDir The destination directory. Must not be null. - * * @since 4.0 */ public void setDestinationDir(Provider destinationDir) { @@ -146,7 +144,7 @@ public void setTargetCompatibility(String targetCompatibility) { /** * Convention to fall back to the 'destinationDir' output for backwards compatibility with plugins that extend AbstractCompile and override the deprecated methods. */ - private class BackwardCompatibilityOutputDirectoryConvention extends AbstractReadOnlyProvider { + private class BackwardCompatibilityOutputDirectoryConvention extends AbstractMinimalProvider { private boolean recursiveCall; @Override @@ -154,23 +152,26 @@ public Class getType() { return Directory.class; } - @Nullable @Override - public Directory getOrNull() { + protected Value calculateOwnValue() { if (recursiveCall) { - // getOrNull() was called by AbstractCompile.getDestinationDirectory() and not by a subclass implementation of that method. + // Already quering AbstractCompile.getDestinationDirectory() and not by a subclass implementation of that method. // In that case, this convention should not be used. - return null; + return Value.missing(); } recursiveCall = true; - // If we are not in an error case, this will most likely call a subclass implementation of getDestinationDir(). - // In the Kotlin plugin, the subclass manages it's own field which will be used here. - File legacyValue = getDestinationDir(); - recursiveCall = false; + File legacyValue; + try { + // If we are not in an error case, this will most likely call a subclass implementation of getDestinationDir(). + // In the Kotlin plugin, the subclass manages it's own field which will be used here. + legacyValue = getDestinationDir(); + } finally { + recursiveCall = false; + } if (legacyValue == null) { - return null; + return Value.missing(); } else { - return getProject().getLayout().dir(getProject().provider(() -> legacyValue)).get(); + return Value.of(getProject().getLayout().getProjectDirectory().dir(legacyValue.getAbsolutePath())); } } } diff --git a/subprojects/language-native/src/main/java/org/gradle/language/internal/DefaultBinaryCollection.java b/subprojects/language-native/src/main/java/org/gradle/language/internal/DefaultBinaryCollection.java index e4aa62ac12c7..137c6446b759 100644 --- a/subprojects/language-native/src/main/java/org/gradle/language/internal/DefaultBinaryCollection.java +++ b/subprojects/language-native/src/main/java/org/gradle/language/internal/DefaultBinaryCollection.java @@ -20,8 +20,7 @@ import groovy.lang.Closure; import org.gradle.api.Action; import org.gradle.api.component.SoftwareComponent; -import org.gradle.api.internal.provider.AbstractReadOnlyProvider; -import org.gradle.api.provider.ProviderFactory; +import org.gradle.api.internal.provider.AbstractMinimalProvider; import org.gradle.api.specs.Spec; import org.gradle.internal.ImmutableActionSet; import org.gradle.language.BinaryCollection; @@ -43,23 +42,21 @@ private enum State { } private final Class elementType; - private final ProviderFactory providerFactory; - private final Set elements = new LinkedHashSet(); - private List> pending = new LinkedList>(); + private final Set elements = new LinkedHashSet<>(); + private List> pending = new LinkedList<>(); private State state = State.Collecting; private ImmutableActionSet knownActions = ImmutableActionSet.empty(); private ImmutableActionSet configureActions = ImmutableActionSet.empty(); private ImmutableActionSet finalizeActions = ImmutableActionSet.empty(); @Inject - public DefaultBinaryCollection(Class elementType, ProviderFactory providerFactory) { + public DefaultBinaryCollection(Class elementType) { this.elementType = elementType; - this.providerFactory = providerFactory; } @Override public BinaryProvider get(final Class type, final Spec spec) { - SingleElementProvider provider = new SingleElementProvider(type, spec); + SingleElementProvider provider = new SingleElementProvider<>(type, spec); if (state == State.Collecting) { pending.add(provider); } else { @@ -70,12 +67,7 @@ public BinaryProvider get(final Class type, final Spec spec @Override public BinaryProvider getByName(final String name) { - return get(elementType, new Spec() { - @Override - public boolean isSatisfiedBy(T element) { - return element.getName().equals(name); - } - }); + return get(elementType, element -> element.getName().equals(name)); } @Override @@ -93,7 +85,7 @@ public void whenElementKnown(Action action) { @Override public void whenElementKnown(final Class type, final Action action) { - whenElementKnown(new TypeFilteringAction(type, action)); + whenElementKnown(new TypeFilteringAction<>(type, action)); } @Override @@ -109,7 +101,7 @@ public void whenElementFinalized(Action action) { @Override public void whenElementFinalized(Class type, Action action) { - whenElementFinalized(new TypeFilteringAction(type, action)); + whenElementFinalized(new TypeFilteringAction<>(type, action)); } @Override @@ -122,7 +114,7 @@ public void configureEach(Action action) { @Override public void configureEach(Class type, Action action) { - configureEach(new TypeFilteringAction(type, action)); + configureEach(new TypeFilteringAction<>(type, action)); } public void add(T element) { @@ -170,7 +162,7 @@ public Set get() { return ImmutableSet.copyOf(elements); } - private class SingleElementProvider extends AbstractReadOnlyProvider implements BinaryProvider { + private class SingleElementProvider extends AbstractMinimalProvider implements BinaryProvider { private final Class type; private Spec spec; private S match; @@ -203,40 +195,33 @@ public Class getType() { // Mix in some Groovy DSL support. Should decorate instead public void configure(Closure closure) { - configure(ConfigureUtil.configureUsing(closure)); + configure(ConfigureUtil.configureUsing(closure)); } @Override public void configure(final Action action) { - configureEach(new Action() { - @Override - public void execute(T t) { - if (match == t) { - action.execute(match); - } + configureEach(t -> { + if (match == t) { + action.execute(match); } }); } @Override public void whenFinalized(final Action action) { - whenElementFinalized(new Action() { - @Override - public void execute(T t) { - if (match == t) { - action.execute(match); - } + whenElementFinalized(t -> { + if (match == t) { + action.execute(match); } }); } - @Nullable @Override - public S getOrNull() { + protected Value calculateOwnValue() { if (ambiguous) { throw new IllegalStateException("Found multiple elements"); } - return match; + return Value.ofNullable(match); } } diff --git a/subprojects/language-native/src/test/groovy/org/gradle/language/internal/DefaultBinaryCollectionTest.groovy b/subprojects/language-native/src/test/groovy/org/gradle/language/internal/DefaultBinaryCollectionTest.groovy index 8d885c95d826..0e4d2ff2736d 100644 --- a/subprojects/language-native/src/test/groovy/org/gradle/language/internal/DefaultBinaryCollectionTest.groovy +++ b/subprojects/language-native/src/test/groovy/org/gradle/language/internal/DefaultBinaryCollectionTest.groovy @@ -17,7 +17,6 @@ package org.gradle.language.internal import org.gradle.api.Action -import org.gradle.api.internal.provider.DefaultProviderFactory import org.gradle.api.specs.Spec import org.gradle.language.cpp.CppBinary import org.gradle.language.swift.SwiftBinary @@ -25,7 +24,7 @@ import org.gradle.language.swift.SwiftSharedLibrary import spock.lang.Specification class DefaultBinaryCollectionTest extends Specification { - def container = new DefaultBinaryCollection(SwiftBinary, new DefaultProviderFactory()) + def container = new DefaultBinaryCollection(SwiftBinary) def "can query elements when realized"() { def binary1 = Stub(SwiftBinary) @@ -307,7 +306,7 @@ class DefaultBinaryCollectionTest extends Specification { then: def e = thrown(IllegalStateException) - e.message == 'No value has been specified for this provider.' + e.message == 'Cannot query the value of this provider because it has no value available.' } def "querying the result of get by name fails when no element present"() { @@ -320,7 +319,7 @@ class DefaultBinaryCollectionTest extends Specification { then: def e = thrown(IllegalStateException) - e.message == 'No value has been specified for this provider.' + e.message == 'Cannot query the value of this provider because it has no value available.' } def "querying the result of get by name fails when multiple elements present"() { @@ -601,7 +600,7 @@ class DefaultBinaryCollectionTest extends Specification { then: def e = thrown(IllegalStateException) - e.message == 'No value has been specified for this provider.' + e.message == 'Cannot query the value of this provider because it has no value available.' } def "querying the result of get by spec fails when no matching element present"() { @@ -619,7 +618,7 @@ class DefaultBinaryCollectionTest extends Specification { then: def e = thrown(IllegalStateException) - e.message == 'No value has been specified for this provider.' + e.message == 'Cannot query the value of this provider because it has no value available.' } def "querying the result of get by spec fails when multiple matching elements present"() { diff --git a/subprojects/language-native/src/test/groovy/org/gradle/language/plugins/NativeBasePluginTest.groovy b/subprojects/language-native/src/test/groovy/org/gradle/language/plugins/NativeBasePluginTest.groovy index 1af310484f58..8d32b0088332 100644 --- a/subprojects/language-native/src/test/groovy/org/gradle/language/plugins/NativeBasePluginTest.groovy +++ b/subprojects/language-native/src/test/groovy/org/gradle/language/plugins/NativeBasePluginTest.groovy @@ -69,7 +69,7 @@ class NativeBasePluginTest extends Specification { def b2 = Stub(SoftwareComponent) b2.name >> "b2" def component = Stub(ComponentWithBinaries) - def binaries = new DefaultBinaryCollection(SoftwareComponent, null) + def binaries = new DefaultBinaryCollection(SoftwareComponent) component.binaries >> binaries given: @@ -109,7 +109,7 @@ class NativeBasePluginTest extends Specification { def "assemble task builds outputs of development binary of main component"() { def binary1 = binary('debug', 'debugInstall') def binary2 = binary('release', 'releaseInstall') - def binaries = new DefaultBinaryCollection(SoftwareComponent, null) + def binaries = new DefaultBinaryCollection(SoftwareComponent) binaries.add(binary1) binaries.add(binary2) def component = Stub(TestComponent) @@ -130,7 +130,7 @@ class NativeBasePluginTest extends Specification { def "adds assemble task for each binary of main component"() { def binary1 = binary('debug', 'installDebug') def binary2 = binary('release', 'installRelease') - def binaries = new DefaultBinaryCollection(SoftwareComponent, null) + def binaries = new DefaultBinaryCollection(SoftwareComponent) binaries.add(binary1) binaries.add(binary2) def component = Stub(TestComponent) diff --git a/subprojects/language-native/src/test/groovy/org/gradle/language/swift/internal/DefaultSwiftApplicationTest.groovy b/subprojects/language-native/src/test/groovy/org/gradle/language/swift/internal/DefaultSwiftApplicationTest.groovy index 3f38eaa50304..6eb96ba8dd2d 100644 --- a/subprojects/language-native/src/test/groovy/org/gradle/language/swift/internal/DefaultSwiftApplicationTest.groovy +++ b/subprojects/language-native/src/test/groovy/org/gradle/language/swift/internal/DefaultSwiftApplicationTest.groovy @@ -73,7 +73,7 @@ class DefaultSwiftApplicationTest extends Specification { then: def ex = thrown(IllegalStateException) - ex.message == "No value has been specified for Swift application 'main' property 'developmentBinary'." + ex.message == "Cannot query the value of Swift application 'main' property 'developmentBinary' because it has no value available." } private NativeVariantIdentity getIdentity() { diff --git a/subprojects/language-native/src/test/groovy/org/gradle/language/swift/internal/DefaultSwiftLibraryTest.groovy b/subprojects/language-native/src/test/groovy/org/gradle/language/swift/internal/DefaultSwiftLibraryTest.groovy index 7c42af2fc515..177624948f76 100644 --- a/subprojects/language-native/src/test/groovy/org/gradle/language/swift/internal/DefaultSwiftLibraryTest.groovy +++ b/subprojects/language-native/src/test/groovy/org/gradle/language/swift/internal/DefaultSwiftLibraryTest.groovy @@ -103,7 +103,7 @@ class DefaultSwiftLibraryTest extends Specification { then: def ex = thrown(IllegalStateException) - ex.message == "No value has been specified for Swift library 'main' property 'developmentBinary'." + ex.message == "Cannot query the value of Swift library 'main' property 'developmentBinary' because it has no value available." } private NativeVariantIdentity getIdentity() { diff --git a/subprojects/logging/src/main/java/org/gradle/internal/logging/text/TreeFormatter.java b/subprojects/logging/src/main/java/org/gradle/internal/logging/text/TreeFormatter.java index 2093e37db4e6..976e6de04990 100644 --- a/subprojects/logging/src/main/java/org/gradle/internal/logging/text/TreeFormatter.java +++ b/subprojects/logging/src/main/java/org/gradle/internal/logging/text/TreeFormatter.java @@ -80,7 +80,7 @@ public void blankLine() { /** * Starts a new node with the given type name. */ - public void node(Class type) { + public TreeFormatter node(Class type) { // Implementation is currently dumb, can be made smarter if (type.isInterface()) { node("Interface "); @@ -88,26 +88,28 @@ public void node(Class type) { node("Class "); } appendType(type); + return this; } /** * Appends text to the current node. */ - public void append(CharSequence text) { + public TreeFormatter append(CharSequence text) { if (current.state == State.CollectValue) { current.value.append(text); if (current.valueWritten) { original.append(text); } } else { - throw new IllegalStateException("Cannot append text to node."); + throw new IllegalStateException("Cannot append text as there is no current node."); } + return this; } /** * Appends a type name to the current node. */ - public void appendType(Type type) { + public TreeFormatter appendType(Type type) { // Implementation is currently dumb, can be made smarter if (type instanceof Class) { Class classType = GeneratedSubclasses.unpack((Class) type); @@ -129,6 +131,7 @@ public void appendType(Type type) { } else { append(type.toString()); } + return this; } private void appendOuter(Class type) { @@ -143,25 +146,27 @@ private void appendOuter(Class type) { /** * Appends an annotation name to the current node. */ - public void appendAnnotation(Class type) { + public TreeFormatter appendAnnotation(Class type) { append("@" + type.getSimpleName()); + return this; } /** * Appends a method name to the current node. */ - public void appendMethod(Method method) { + public TreeFormatter appendMethod(Method method) { // Implementation is currently dumb, can be made smarter append(method.getDeclaringClass().getSimpleName()); append("."); append(method.getName()); append("()"); + return this; } /** * Appends some user provided value to the current node. */ - public void appendValue(@Nullable Object value) { + public TreeFormatter appendValue(@Nullable Object value) { // Implementation is currently dumb, can be made smarter if (value == null) { append("null"); @@ -174,12 +179,13 @@ public void appendValue(@Nullable Object value) { } else { append(value.toString()); } + return this; } /** * Appends some user provided values to the current node. */ - public void appendValues(T[] values) { + public TreeFormatter appendValues(T[] values) { // Implementation is currently dumb, can be made smarter append("["); for (int i = 0; i < values.length; i++) { @@ -190,6 +196,7 @@ public void appendValues(T[] values) { appendValue(value); } append("]"); + return this; } @Override diff --git a/subprojects/logging/src/test/groovy/org/gradle/internal/logging/text/TreeFormatterTest.groovy b/subprojects/logging/src/test/groovy/org/gradle/internal/logging/text/TreeFormatterTest.groovy index 8b5f25e2fdf6..4761b92cd9a1 100644 --- a/subprojects/logging/src/test/groovy/org/gradle/internal/logging/text/TreeFormatterTest.groovy +++ b/subprojects/logging/src/test/groovy/org/gradle/internal/logging/text/TreeFormatterTest.groovy @@ -420,7 +420,7 @@ Some thing.''') then: def e = thrown(IllegalStateException) - e.message == 'Cannot append text to node.' + e.message == 'Cannot append text as there is no current node.' } def "cannot append after children finished"() { @@ -433,7 +433,7 @@ Some thing.''') then: def e = thrown(IllegalStateException) - e.message == 'Cannot append text to node.' + e.message == 'Cannot append text as there is no current node.' } interface Thing extends List, Map> { diff --git a/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/CollectionPropertyIntegrationTest.groovy b/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/CollectionPropertyIntegrationTest.groovy index ffaba19e4028..5280f33193c9 100644 --- a/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/CollectionPropertyIntegrationTest.groovy +++ b/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/CollectionPropertyIntegrationTest.groovy @@ -27,7 +27,7 @@ class CollectionPropertyIntegrationTest extends AbstractIntegrationSpec { final ListProperty prop = project.objects.listProperty(String) @Internal List expected = [] - + @TaskAction void validate() { def actual = prop.getOrNull() @@ -37,7 +37,7 @@ class CollectionPropertyIntegrationTest extends AbstractIntegrationSpec { actual.each { assert it instanceof String } } } - + task verify(type: MyTask) """ } @@ -54,13 +54,13 @@ class CollectionPropertyIntegrationTest extends AbstractIntegrationSpec { abstract class ATask extends DefaultTask { @Input abstract ListProperty<$type> getProp() - + @TaskAction void go() { println("prop = \${prop.get()}") } } - + tasks.create("thing", ATask) { prop = $value } @@ -87,8 +87,8 @@ def provider = providers.provider { [++counter, ++counter] } def property = objects.listProperty(Integer) property.set(provider) -assert property.get() == [1, 2] -assert property.get() == [3, 4] +assert property.get() == [1, 2] +assert property.get() == [3, 4] property.finalizeValue() assert property.get() == [5, 6] assert property.get() == [5, 6] @@ -112,8 +112,8 @@ def provider = providers.provider { [++counter, ++counter] } def property = objects.listProperty(Integer) property.set(provider) -assert property.get() == [1, 2] -assert property.get() == [3, 4] +assert property.get() == [1, 2] +assert property.get() == [3, 4] property.disallowChanges() assert property.get() == [5, 6] assert property.get() == [7, 8] @@ -134,10 +134,10 @@ property.set([1]) class SomeTask extends DefaultTask { @Input final ListProperty prop = project.objects.listProperty(String) - + @OutputFile final Property outputFile = project.objects.fileProperty() - + @TaskAction void go() { outputFile.get().asFile.text = prop.get() @@ -453,4 +453,30 @@ task wrongPropertyElementTypeApi { expect: succeeds("verify") } + + def "fails when property with no value is queried"() { + given: + buildFile << """ + abstract class SomeTask extends DefaultTask { + @Internal + abstract ListProperty getProp() + + @TaskAction + def go() { + prop.set((Iterable)null) + prop.get() + } + } + + tasks.register('thing', SomeTask) + """ + + when: + fails("thing") + + then: + failure.assertHasDescription("Execution failed for task ':thing'.") + failure.assertHasCause("Cannot query the value of task ':thing' property 'prop' because it has no value available.") + } + } diff --git a/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/MapPropertyIntegrationTest.groovy b/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/MapPropertyIntegrationTest.groovy index 2915415acc5c..d351a6650ff2 100644 --- a/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/MapPropertyIntegrationTest.groovy +++ b/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/MapPropertyIntegrationTest.groovy @@ -32,13 +32,13 @@ class MapPropertyIntegrationTest extends AbstractIntegrationSpec { final Class keyType @Internal final Class valueType - + AbstractVerificationTask(Class keyType, Class valueType) { this.keyType = keyType this.valueType = valueType prop = project.objects.mapProperty(keyType, valueType) } - + @TaskAction void validate() { def actual = prop.getOrNull() @@ -49,17 +49,17 @@ class MapPropertyIntegrationTest extends AbstractIntegrationSpec { assert keyType.isInstance(it.key) assert valueType.isInstance(it.value) } - } + } } class StringVerificationTask extends AbstractVerificationTask { StringVerificationTask() { super(String, String) } } - + class IntegerVerificationTask extends AbstractVerificationTask { IntegerVerificationTask() { super(Integer, Integer) } } - + task verify(type: StringVerificationTask) task verifyInt(type: IntegerVerificationTask) ''' @@ -77,17 +77,17 @@ class MapPropertyIntegrationTest extends AbstractIntegrationSpec { abstract class MyTask extends DefaultTask { @Input abstract MapProperty<$keyType, $valueType> getProp() - + @TaskAction void go() { println("prop = \${prop.get()}") } } - + def key = new Param(display: 'a') def map = [:] map[key] = new Param(display: 12) - + tasks.create("thing", MyTask) { prop = $value } @@ -110,16 +110,16 @@ class MapPropertyIntegrationTest extends AbstractIntegrationSpec { buildFile << ''' int counter = 0 def provider = providers.provider { [(++counter): ++counter] } - + def property = objects.mapProperty(Integer, Integer) property.set(provider) - + assert property.get() == [1: 2] assert property.get() == [3: 4] property.finalizeValue() assert property.get() == [5: 6] assert property.get() == [5: 6] - + property.set([1: 2]) '''.stripIndent() @@ -135,16 +135,16 @@ class MapPropertyIntegrationTest extends AbstractIntegrationSpec { buildFile << ''' int counter = 0 def provider = providers.provider { [(++counter): ++counter] } - + def property = objects.mapProperty(Integer, Integer) property.set(provider) - + assert property.get() == [1: 2] assert property.get() == [3: 4] property.disallowChanges() assert property.get() == [5: 6] assert property.get() == [7: 8] - + property.set([1: 2]) '''.stripIndent() @@ -161,16 +161,16 @@ class MapPropertyIntegrationTest extends AbstractIntegrationSpec { class SomeTask extends DefaultTask { @Input final MapProperty prop = project.objects.mapProperty(String, String) - + @OutputFile final Property outputFile = project.objects.fileProperty() - + @TaskAction void go() { outputFile.get().asFile.text = prop.get() } } - + task thing(type: SomeTask) { prop = ['key1': 'value1'] outputFile = layout.buildDirectory.file('out.txt') @@ -178,11 +178,11 @@ class MapPropertyIntegrationTest extends AbstractIntegrationSpec { prop.set(['ignoredKey': 'ignoredValue']) } } - + afterEvaluate { thing.prop = ['key2': 'value2'] } - + task before { doLast { thing.prop = providers.provider { ['finalKey': 'finalValue'] } @@ -203,7 +203,7 @@ class MapPropertyIntegrationTest extends AbstractIntegrationSpec { given: buildFile << ''' def prop = project.objects.mapProperty(String, String) - + task thing { inputs.property('prop', prop) prop.set(['key1': 'value1']) @@ -250,7 +250,7 @@ task thing { buildFile << """ verify { prop = ${value} - expected = ['key1': 'value1', 'key2': 'value2'] + expected = ['key1': 'value1', 'key2': 'value2'] } """.stripIndent() @@ -271,7 +271,7 @@ task thing { prop.empty() prop['key1'] = 'value1' prop['key2'] = project.provider { 'value2' } - expected = ['key1': 'value1', 'key2': 'value2'] + expected = ['key1': 'value1', 'key2': 'value2'] } '''.stripIndent() @@ -286,7 +286,7 @@ task thing { prop.empty() prop[1] = 111 prop[2] = project.provider { 222 } - expected = [1: 111, 2: 222] + expected = [1: 111, 2: 222] } '''.stripIndent() @@ -301,7 +301,7 @@ task thing { def str = "aBc" verify { prop = ${value} - expected = ['a': 'b'] + expected = ['a': 'b'] } """.stripIndent() @@ -324,7 +324,7 @@ task thing { prop.putAll(['key4': 'value4']) prop.putAll(project.provider { ['key5': 'value5'] }) expected = ['key1': 'value1', 'key2': 'value2', 'key3': 'value3', 'key4': 'value4', 'key5': 'value5'] - } + } '''.stripIndent() } @@ -338,7 +338,7 @@ task thing { prop.putAll(['key3': 'value3']) prop.putAll(project.provider { ['key4': 'value4'] }) expected = ['key1': 'value1', 'key2': 'value2', 'key3': 'value3', 'key4': 'value4'] - } + } '''.stripIndent() expect: @@ -354,7 +354,7 @@ task thing { prop = ['key': 'value'] prop.putAll(${value}) expected = ['key': 'value', 'b': 'c'] - } + } """.stripIndent() expect: @@ -375,7 +375,7 @@ task thing { prop = ['key': 'value'] prop.put(${key}, ${value}) expected = ['key': 'value', 'a': 'b'] - } + } """.stripIndent() expect: @@ -395,51 +395,51 @@ task thing { verify.prop = 123 } } - + task wrongRuntimeKeyType { doLast { verify.prop = [123: 'value'] verify.prop.get() } } - + task wrongRuntimeValueType { doLast { verify.prop = ['key': 123] verify.prop.get() } } - + task wrongPropertyTypeDsl { doLast { verify.prop = objects.property(Integer) } } - + task wrongPropertyTypeApi { doLast { verify.prop.set(objects.property(Integer)) } } - + task wrongRuntimeKeyTypeDsl { doLast { verify.prop = objects.mapProperty(Integer, String) } } - + task wrongRuntimeValueTypeDsl { doLast { verify.prop = objects.mapProperty(String, Integer) } } - + task wrongRuntimeKeyTypeApi { doLast { verify.prop.set(objects.mapProperty(Integer, String)) } } - + task wrongRuntimeValueTypeApi { doLast { verify.prop.set(objects.mapProperty(String, Integer)) @@ -513,21 +513,21 @@ task thing { verify.expected = ['key': 'newValue'] } } - + task replacingPutWithProvider { doLast { verify.prop.put('key', project.provider { 'newValue' }) verify.expected = ['key': 'newValue'] } } - + task replacingPutAll { doLast { verify.prop.putAll(['key': 'newValue', 'otherKey': 'otherValue']) verify.expected = ['key': 'newValue', 'otherKey': 'otherValue'] } } - + task replacingPutAllWithProvider { doLast { verify.prop.putAll(project.provider { ['key': 'newValue', 'otherKey': 'otherValue'] }) @@ -556,7 +556,7 @@ task thing { prop.putAll(['key3': 'value3']) prop.putAll(project.provider { ['key4': 'value4'] }) expected = null - } + } '''.stripIndent() expect: @@ -595,7 +595,7 @@ task thing { verify { prop.put('key', project.provider { null }) expected = null - } + } '''.stripIndent() expect: @@ -608,10 +608,35 @@ task thing { verify { prop.putAll(project.provider { null }) expected = null - } + } '''.stripIndent() expect: succeeds('verify') } + + def "fails when property with no value is queried"() { + given: + buildFile << """ + abstract class SomeTask extends DefaultTask { + @Internal + abstract MapProperty getProp() + + @TaskAction + def go() { + prop.set((Map)null) + prop.get() + } + } + + tasks.register('thing', SomeTask) + """ + + when: + fails("thing") + + then: + failure.assertHasDescription("Execution failed for task ':thing'.") + failure.assertHasCause("Cannot query the value of task ':thing' property 'prop' because it has no value available.") + } } diff --git a/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/PropertyIntegrationTest.groovy b/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/PropertyIntegrationTest.groovy index 5b71d9e3821b..d58e9e63417c 100644 --- a/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/PropertyIntegrationTest.groovy +++ b/subprojects/model-core/src/integTest/groovy/org/gradle/api/provider/PropertyIntegrationTest.groovy @@ -75,13 +75,13 @@ task thing(type: SomeTask) { abstract class MyTask extends DefaultTask { @Input abstract Property<$type> getProp() - + @TaskAction void go() { println("prop = \${prop.get()}") } } - + tasks.create("thing", MyTask) { prop = $value } @@ -110,17 +110,17 @@ task thing(type: SomeTask) { abstract class MyTask extends DefaultTask { @Nested abstract NestedType getNested() - + void nested(Action action) { action.execute(nested) } - + @TaskAction void go() { println("prop = \${nested.prop.get()}") } } - + tasks.create("thing", MyTask) { nested { prop = "value" @@ -135,6 +135,68 @@ task thing(type: SomeTask) { outputContains("prop = value") } + def "fails when property with no value is queried"() { + given: + buildFile << """ + abstract class SomeTask extends DefaultTask { + @Internal + abstract Property getProp() + + @TaskAction + def go() { + prop.get() + } + } + + tasks.register('thing', SomeTask) + """ + + when: + fails("thing") + + then: + failure.assertHasDescription("Execution failed for task ':thing'.") + failure.assertHasCause("Cannot query the value of task ':thing' property 'prop' because it has no value available.") + } + + def "fails when property with no value because source property has no value is queried"() { + given: + buildFile << """ + interface SomeExtension { + Property getSource() + } + + abstract class SomeTask extends DefaultTask { + @Internal + abstract Property getProp() + + @TaskAction + def go() { + prop.get() + } + } + + def custom1 = extensions.create('custom1', SomeExtension) + + def custom2 = extensions.create('custom2', SomeExtension) + custom2.source = custom1.source + + tasks.register('thing', SomeTask) { + prop = custom2.source + } + """ + + when: + fails("thing") + + then: + failure.assertHasDescription("Execution failed for task ':thing'.") + failure.assertHasCause("""Cannot query the value of task ':thing' property 'prop' because it has no value available. +The value of this property is derived from: + - extension 'custom2' property 'source' + - extension 'custom1' property 'source'""") + } + def "can finalize the value of a property using API"() { given: buildFile << """ @@ -144,16 +206,16 @@ def provider = providers.provider { ++counter } def property = objects.property(Integer) property.set(provider) -assert property.get() == 1 -assert property.get() == 2 +assert property.get() == 1 +assert property.get() == 2 property.finalizeValue() assert counter == 3 // is eager -assert property.get() == 3 +assert property.get() == 3 counter = 45 -assert property.get() == 3 +assert property.get() == 3 property.set(12) """ @@ -174,16 +236,16 @@ def provider = providers.provider { ++counter } def property = objects.property(Integer) property.set(provider) -assert property.get() == 1 -assert property.get() == 2 +assert property.get() == 1 +assert property.get() == 2 property.finalizeValueOnRead() assert counter == 2 // is lazy assert property.get() == 3 - + counter = 45 -assert property.get() == 3 +assert property.get() == 3 property.set(12) """ @@ -204,11 +266,11 @@ def provider = providers.provider { ++counter } def property = objects.property(Integer) property.set(provider) -assert property.get() == 1 -assert property.get() == 2 +assert property.get() == 1 +assert property.get() == 2 property.disallowChanges() assert property.get() == 3 -assert property.get() == 4 +assert property.get() == 4 property.set(12) """ @@ -226,10 +288,10 @@ property.set(12) class SomeTask extends DefaultTask { @Input final Property prop = project.objects.property(String) - + @OutputFile final Property outputFile = project.objects.fileProperty() - + @TaskAction void go() { outputFile.get().asFile.text = prop.get() @@ -318,7 +380,7 @@ task thing(type: SomeTask) { prop = providers.provider { throw new RuntimeException("broken") } outputFile = layout.buildDirectory.file("out.txt") } - + """ when: @@ -335,13 +397,13 @@ task thing(type: SomeTask) { buildFile << """ task thing(type: SomeTask) { - prop = providers.provider { + prop = providers.provider { println("calculating value") return "value" } outputFile = layout.buildDirectory.file("out.txt") } - + """ when: @@ -370,21 +432,21 @@ task thing(type: SomeTask) { class SomeTask extends DefaultTask { @Input final Property prop = project.objects.property(String) - + @InputFiles @SkipWhenEmpty final SetProperty outputFile = project.objects.setProperty(RegularFile) - + @TaskAction void go() { } } task thing(type: SomeTask) { - prop = providers.provider { + prop = providers.provider { throw new RuntimeException("should not be called") } } - + """ when: @@ -399,7 +461,7 @@ task thing(type: SomeTask) { buildFile << """ class SomeExtension { final Property prop - + @javax.inject.Inject SomeExtension(ObjectFactory objects) { prop = objects.property(String) @@ -436,7 +498,7 @@ assert tasks.t.prop.get() == "changed" buildFile << """ class SomeExtension { final Property prop - + @javax.inject.Inject SomeExtension(ObjectFactory objects) { prop = objects.property(String) @@ -467,7 +529,7 @@ assert custom.prop.get() == "value 4" buildFile << """ class SomeExtension { final Property prop - + @javax.inject.Inject SomeExtension(ObjectFactory objects) { prop = objects.property(String) @@ -598,8 +660,8 @@ class SomeExtension { $prop = objects.property($type) } } - -project.extensions.create("some", SomeExtension) + +project.extensions.create("some", SomeExtension) """ when: @@ -622,10 +684,10 @@ project.extensions.create("some", SomeExtension) class SomeTask extends DefaultTask { @Input final Property prop = project.objects.property(String) - + @OutputFile final Property outputFile = project.objects.fileProperty() - + @TaskAction void go() { outputFile.get().asFile.text = prop.get() diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractCollectionProperty.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractCollectionProperty.java index 3156b484ff55..ec74ee4957f7 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractCollectionProperty.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractCollectionProperty.java @@ -29,7 +29,6 @@ import org.gradle.api.internal.tasks.TaskDependencyResolveContext; import org.gradle.api.provider.HasMultipleValues; import org.gradle.api.provider.Provider; -import org.gradle.internal.DisplayName; import javax.annotation.Nullable; import java.util.ArrayList; @@ -144,31 +143,22 @@ public void providers(List>> pr @Override public boolean isPresent() { beforeRead(); - return value.present(); + return value.isPresent(); } @Override - public C get() { + protected Value calculateOwnValue() { beforeRead(); - List values = new ArrayList(); - value.collectInto(getDisplayName(), valueCollector, values); - return fromValue(values); + return doCalculateOwnValue(); } - @Nullable - @Override - public C getOrNull() { - beforeRead(); - return doGetOrNull(); - } - - @Nullable - private C doGetOrNull() { - List values = new ArrayList(); - if (!value.maybeCollectInto(valueCollector, values)) { - return null; + private Value doCalculateOwnValue() { + List values = new ArrayList<>(); + Value result = value.maybeCollectInto(valueCollector, values); + if (result.isMissing()) { + return result.asType(); } - return fromValue(values); + return Value.of(fromValue(values)); } @Override @@ -246,7 +236,7 @@ protected void applyDefaultValue() { @Override protected void makeFinal() { - C collection = doGetOrNull(); + C collection = doCalculateOwnValue().orNull(); if (collection != null) { set(new ElementsFromCollection(collection)); } else { @@ -293,8 +283,8 @@ public PlusCollector(Collector left, Collector right) { } @Override - public boolean present() { - return left.present() && right.present(); + public boolean isPresent() { + return left.isPresent() && right.isPresent(); } @Override @@ -303,17 +293,12 @@ public int size() { } @Override - public void collectInto(DisplayName owner, ValueCollector collector, Collection dest) { - left.collectInto(owner, collector, dest); - right.collectInto(owner, collector, dest); - } - - @Override - public boolean maybeCollectInto(ValueCollector collector, Collection dest) { - if (left.maybeCollectInto(collector, dest)) { - return right.maybeCollectInto(collector, dest); + public Value maybeCollectInto(ValueCollector collector, Collection dest) { + Value value = left.maybeCollectInto(collector, dest); + if (value.isMissing()) { + return value; } - return false; + return right.maybeCollectInto(collector, dest); } @Override diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractCombiningProvider.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractCombiningProvider.java index 2bece24ba530..1eb389cdb2ca 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractCombiningProvider.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractCombiningProvider.java @@ -16,19 +16,17 @@ package org.gradle.api.internal.provider; -import org.gradle.api.provider.Provider; - import javax.annotation.Nullable; -public abstract class AbstractCombiningProvider extends AbstractReadOnlyProvider { +public abstract class AbstractCombiningProvider extends AbstractMinimalProvider { private final Class type; - private final Provider base; - private final Provider provider; + private final ProviderInternal left; + private final ProviderInternal right; - public AbstractCombiningProvider(Class type, Provider base, Provider provider) { + public AbstractCombiningProvider(Class type, ProviderInternal left, ProviderInternal right) { this.type = type; - this.base = base; - this.provider = provider; + this.left = left; + this.right = right; } @Nullable @@ -39,21 +37,26 @@ public Class getType() { @Override public boolean isPresent() { - return base.isPresent() && provider.isPresent(); + return left.isPresent() && right.isPresent(); } @Override - public OUT getOrNull() { - if (base.isPresent() && provider.isPresent()) { - return map(base.get(), provider.get()); + protected Value calculateOwnValue() { + Value leftValue = left.calculateValue(); + if (leftValue.isMissing()) { + return leftValue.asType(); + } + Value rightValue = right.calculateValue(); + if (rightValue.isMissing()) { + return rightValue.asType(); } - return null; + return Value.of(map(leftValue.get(), rightValue.get())); } protected abstract OUT map(BASE b, IN v); @Override public String toString() { - return String.format("combine(%s, %s)", base, provider); + return String.format("combine(%s, %s)", left, right); } } diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractMappingProvider.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractMappingProvider.java index 053454604407..1a956f904c76 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractMappingProvider.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractMappingProvider.java @@ -61,19 +61,13 @@ public boolean isPresent() { } @Override - public OUT get() { + protected Value calculateOwnValue() { beforeRead(); - return mapValue(provider.get()); - } - - @Override - public OUT getOrNull() { - beforeRead(); - IN value = provider.getOrNull(); - if (value != null) { - return mapValue(value); + Value value = provider.calculateValue(); + if (value.isMissing()) { + return value.asType(); } - return null; + return Value.of(mapValue(value.get())); } protected abstract OUT mapValue(IN v); diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractMinimalProvider.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractMinimalProvider.java index 507c963954d1..c35726bf532c 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractMinimalProvider.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractMinimalProvider.java @@ -22,16 +22,20 @@ import org.gradle.api.internal.tasks.TaskDependencyResolveContext; import org.gradle.api.provider.Provider; import org.gradle.internal.Cast; +import org.gradle.internal.Describables; import org.gradle.internal.DisplayName; +import org.gradle.internal.logging.text.TreeFormatter; import org.gradle.internal.state.Managed; import org.gradle.util.GUtil; import javax.annotation.Nullable; /** - * A partial {@link Provider} implementation. + * A partial {@link Provider} implementation. Subclasses need to implement {@link ProviderInternal#getType()} and {@link AbstractMinimalProvider#calculateOwnValue()}. */ public abstract class AbstractMinimalProvider implements ProviderInternal, ScalarSupplier, Managed { + private static final DisplayName DEFAULT_DISPLAY_NAME = Describables.of("this provider"); + @Override public ProviderInternal map(final Transformer transformer) { return new TransformBackedProvider<>(transformer, this); @@ -42,23 +46,68 @@ public Provider flatMap(final Transformer return new FlatMapProvider<>(this, transformer); } + /** + * Returns the human consumable display name for this provider, or null if this is not known. + */ + @Nullable + protected DisplayName getDeclaredDisplayName() { + return null; + } + + /** + * Returns a display name for this provider, using a default if this is not known. + */ + protected DisplayName getDisplayName() { + DisplayName displayName = getDeclaredDisplayName(); + if (displayName == null) { + return DEFAULT_DISPLAY_NAME; + } + return displayName; + } + + protected DisplayName getTypedDisplayName() { + return DEFAULT_DISPLAY_NAME; + } + + protected abstract ScalarSupplier.Value calculateOwnValue(); + @Override public boolean isPresent() { - return getOrNull() != null; + return !calculateOwnValue().isMissing(); + } + + @Override + public T get() { + Value value = calculateOwnValue(); + if (value.isMissing()) { + TreeFormatter formatter = new TreeFormatter(); + formatter.node("Cannot query the value of ").append(getDisplayName().getDisplayName()).append(" because it has no value available."); + if (!value.getPathToOrigin().isEmpty()) { + formatter.node("The value of ").append(getTypedDisplayName().getDisplayName()).append(" is derived from"); + formatter.startChildren(); + for (DisplayName displayName : value.getPathToOrigin()) { + formatter.node(displayName.getDisplayName()); + } + formatter.endChildren(); + } + throw new MissingValueException(formatter.toString()); + } + return value.get(); } @Override - public T get(DisplayName owner) throws IllegalStateException { - return get(); + public T getOrNull() { + return calculateOwnValue().orNull(); } @Override public T getOrElse(T defaultValue) { - T value = getOrNull(); - if (value == null) { - return defaultValue; - } - return value; + return calculateOwnValue().orElse(defaultValue); + } + + @Override + public Value calculateValue() { + return calculateOwnValue().pushWhenMissing(getDeclaredDisplayName()); } @Override @@ -140,7 +189,7 @@ public int getFactoryId() { } private static class FlatMapProvider extends AbstractMinimalProvider { - private final Provider provider; + private final ProviderInternal provider; private final Transformer, ? super T> transformer; FlatMapProvider(ProviderInternal provider, Transformer, ? super T> transformer) { @@ -164,27 +213,20 @@ public boolean isPresent() { } @Override - public S get() { - T value = provider.get(); - return map(value).get(); - } - - @Nullable - @Override - public S getOrNull() { - T value = provider.getOrNull(); - if (value == null) { - return null; + protected Value calculateOwnValue() { + Value value = provider.calculateValue(); + if (value.isMissing()) { + return value.asType(); } - return map(value).getOrNull(); + return map(value.get()).calculateValue(); } - private Provider map(T value) { + private ProviderInternal map(T value) { Provider result = transformer.transform(value); if (result == null) { throw new IllegalStateException(Providers.NULL_TRANSFORMER_RESULT); } - return result; + return Providers.internal(result); } @Override @@ -229,7 +271,7 @@ public T get() { } } - private static class OrElseProvider extends AbstractReadOnlyProvider { + private static class OrElseProvider extends AbstractMinimalProvider { private final ProviderInternal left; private final ProviderInternal right; @@ -258,14 +300,17 @@ public boolean isPresent() { return left.isPresent() || right.isPresent(); } - @Nullable @Override - public T getOrNull() { - T value = left.getOrNull(); - if (value == null) { - value = right.getOrNull(); + protected Value calculateOwnValue() { + Value leftValue = left.calculateValue(); + if (!leftValue.isMissing()) { + return leftValue; + } + Value rightValue = right.calculateValue(); + if (!rightValue.isMissing()) { + return rightValue; } - return value; + return leftValue.addPathsFrom(rightValue); } } diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractProperty.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractProperty.java index 2f474d330260..5eb8dff24366 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractProperty.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractProperty.java @@ -22,6 +22,8 @@ import org.gradle.internal.Describables; import org.gradle.internal.DisplayName; +import javax.annotation.Nullable; + public abstract class AbstractProperty extends AbstractMinimalProvider implements PropertyInternal { private enum State { ImplicitValue, ExplicitValue, Final @@ -41,6 +43,17 @@ public void attachDisplayName(DisplayName displayName) { this.displayName = displayName; } + @Nullable @Override + protected DisplayName getDeclaredDisplayName() { + return displayName; + } + + @Override + protected DisplayName getTypedDisplayName() { + return DEFAULT_DISPLAY_NAME; + } + + @Override protected DisplayName getDisplayName() { if (displayName == null) { return DEFAULT_DISPLAY_NAME; diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractProviderWithValue.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractProviderWithValue.java index 3a70ae413255..5ed7c94dc592 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractProviderWithValue.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractProviderWithValue.java @@ -22,6 +22,14 @@ * A {@link org.gradle.api.provider.Provider} that always has a value defined. The value may not necessarily be final. */ public abstract class AbstractProviderWithValue extends AbstractMinimalProvider { + @Override + protected Value calculateOwnValue() { + return Value.of(get()); + } + + @Override + public abstract T get(); + @Override public T getOrNull() { return get(); diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/Collector.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/Collector.java index 203666aa9057..443ebec50576 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/Collector.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/Collector.java @@ -16,8 +16,6 @@ package org.gradle.api.internal.provider; -import org.gradle.internal.DisplayName; - import java.util.Collection; import java.util.List; @@ -25,11 +23,7 @@ * A supplier of zero or more values of type {@link T}. */ public interface Collector extends ValueSupplier { - boolean present(); - - void collectInto(DisplayName owner, ValueCollector collector, Collection dest); - - boolean maybeCollectInto(ValueCollector collector, Collection dest); + Value maybeCollectInto(ValueCollector collector, Collection dest); int size(); diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/Collectors.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/Collectors.java index 7cb49a949be8..a6ffc7921cea 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/Collectors.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/Collectors.java @@ -23,7 +23,6 @@ import org.gradle.api.Task; import org.gradle.api.internal.tasks.TaskDependencyResolveContext; import org.gradle.api.provider.Provider; -import org.gradle.internal.DisplayName; import javax.annotation.Nullable; import java.util.Collection; @@ -36,17 +35,13 @@ public interface ProvidedCollector extends Collector { public static class EmptyCollection implements Collector { @Override - public boolean present() { + public boolean isPresent() { return true; } @Override - public boolean maybeCollectInto(ValueCollector collector, Collection collection) { - return true; - } - - @Override - public void collectInto(DisplayName owner, ValueCollector collector, Collection dest) { + public Value maybeCollectInto(ValueCollector collector, Collection collection) { + return Value.present(); } @Override @@ -81,19 +76,14 @@ public SingleElement(T element) { } @Override - public boolean present() { + public boolean isPresent() { return true; } @Override - public void collectInto(DisplayName owner, ValueCollector collector, Collection collection) { - collector.add(element, collection); - } - - @Override - public boolean maybeCollectInto(ValueCollector collector, Collection collection) { + public Value maybeCollectInto(ValueCollector collector, Collection collection) { collector.add(element, collection); - return true; + return Value.present(); } @Override @@ -146,24 +136,18 @@ public ElementFromProvider(ProviderInternal providerOfElement) { } @Override - public boolean present() { + public boolean isPresent() { return providerOfElement.isPresent(); } @Override - public void collectInto(DisplayName owner, ValueCollector collector, Collection collection) { - T value = providerOfElement.get(); - collector.add(value, collection); - } - - @Override - public boolean maybeCollectInto(ValueCollector collector, Collection collection) { - T value = providerOfElement.getOrNull(); - if (value == null) { - return false; + public Value maybeCollectInto(ValueCollector collector, Collection collection) { + Value value = providerOfElement.calculateValue(); + if (value.isMissing()) { + return value.asType(); } - collector.add(value, collection); - return true; + collector.add(value.get(), collection); + return Value.present(); } @Override @@ -222,19 +206,14 @@ public ElementsFromCollection(Iterable value) { } @Override - public boolean present() { + public boolean isPresent() { return true; } @Override - public void collectInto(DisplayName owner, ValueCollector collector, Collection collection) { + public Value maybeCollectInto(ValueCollector collector, Collection collection) { collector.addAll(value, collection); - } - - @Override - public boolean maybeCollectInto(ValueCollector collector, Collection collection) { - collector.addAll(value, collection); - return true; + return Value.present(); } @Override @@ -287,24 +266,18 @@ public ElementsFromCollectionProvider(ProviderInternal collector, Collection collection) { - Iterable value = provider.get(); - collector.addAll(value, collection); - } - - @Override - public boolean maybeCollectInto(ValueCollector collector, Collection collection) { - Iterable value = provider.getOrNull(); - if (value == null) { - return false; + public Value maybeCollectInto(ValueCollector collector, Collection collection) { + Value> value = provider.calculateValue(); + if (value.isMissing()) { + return value.asType(); } - collector.addAll(value, collection); - return true; + collector.addAll(value.get(), collection); + return Value.present(); } @Override @@ -361,18 +334,13 @@ public int size() { public static class NoValueCollector implements Collector { @Override - public boolean present() { + public boolean isPresent() { return false; } @Override - public void collectInto(DisplayName owner, ValueCollector collector, Collection dest) { - throw Providers.nullValue(owner); - } - - @Override - public boolean maybeCollectInto(ValueCollector collector, Collection collection) { - return false; + public Value maybeCollectInto(ValueCollector collector, Collection collection) { + return Value.missing(); } @Override @@ -407,21 +375,16 @@ public static class ElementsFromArray implements Collector { } @Override - public boolean present() { + public boolean isPresent() { return true; } @Override - public void collectInto(DisplayName owner, ValueCollector collector, Collection dest) { + public Value maybeCollectInto(ValueCollector collector, Collection dest) { for (T t : value) { collector.add(t, dest); } - } - - @Override - public boolean maybeCollectInto(ValueCollector collector, Collection dest) { - collectInto(null, collector, dest); - return true; + return Value.present(); } @Override @@ -466,21 +429,16 @@ public Class getType() { } @Override - public boolean present() { - return delegate.present(); + public boolean isPresent() { + return delegate.isPresent(); } public void collectInto(Collection collection) { - delegate.collectInto(null, valueCollector, collection); - } - - @Override - public void collectInto(DisplayName owner, ValueCollector collector, Collection dest) { - delegate.collectInto(owner, collector, dest); + maybeCollectInto(valueCollector, collection); } @Override - public boolean maybeCollectInto(ValueCollector collector, Collection dest) { + public Value maybeCollectInto(ValueCollector collector, Collection dest) { return delegate.maybeCollectInto(collector, dest); } diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultMapProperty.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultMapProperty.java index 385814a5f4ef..59f141f22988 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultMapProperty.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultMapProperty.java @@ -25,7 +25,7 @@ import org.gradle.api.provider.MapProperty; import org.gradle.api.provider.Provider; import org.gradle.internal.Cast; -import org.gradle.internal.DisplayName; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; import java.util.ArrayList; @@ -96,31 +96,23 @@ public int getFactoryId() { @Override public boolean isPresent() { beforeRead(); - return value.present(); + return value.isPresent(); } @Override - public Map get() { + protected Value> calculateOwnValue() { beforeRead(); - Map entries = new LinkedHashMap<>(); - value.collectInto(getDisplayName(), entryCollector, entries); - return ImmutableMap.copyOf(entries); - } - - @Nullable - @Override - public Map getOrNull() { - beforeRead(); - return doGetOrNull(); + return doCalculateOwnValue(); } - @Nullable - private Map doGetOrNull() { + @NotNull + private Value> doCalculateOwnValue() { Map entries = new LinkedHashMap<>(); - if (!value.maybeCollectInto(entryCollector, entries)) { - return null; + Value result = value.maybeCollectInto(entryCollector, entries); + if (result.isMissing()) { + return result.asType(); } - return ImmutableMap.copyOf(entries); + return Value.of(ImmutableMap.copyOf(entries)); } @Override @@ -131,10 +123,11 @@ public Provider getting(final K key) { public V call() { beforeRead(); Map dest = new LinkedHashMap<>(); - if (value.maybeCollectInto(entryCollector, dest)) { - return dest.get(key); + Value result = value.maybeCollectInto(entryCollector, dest); + if (result.isMissing()) { + return null; } - return null; + return dest.get(key); } }); } @@ -322,7 +315,7 @@ protected void applyDefaultValue() { @Override @SuppressWarnings("unchecked") protected void makeFinal() { - Map entries = doGetOrNull(); + Map entries = doCalculateOwnValue().orNull(); if (entries != null) { if (entries.isEmpty()) { set((MapCollector) EMPTY_MAP); @@ -334,7 +327,7 @@ protected void makeFinal() { } } - private class KeySetProvider extends AbstractReadOnlyProvider> { + private class KeySetProvider extends AbstractMinimalProvider> { @Nullable @Override @@ -344,22 +337,14 @@ public Class> getType() { } @Override - public Set get() { + protected Value> calculateOwnValue() { beforeRead(); Set keys = new LinkedHashSet<>(); - value.collectKeysInto(keyCollector, keys); - return ImmutableSet.copyOf(keys); - } - - @Nullable - @Override - public Set getOrNull() { - beforeRead(); - Set keys = new LinkedHashSet<>(); - if (!value.maybeCollectKeysInto(keyCollector, keys)) { - return null; + Value result = value.maybeCollectKeysInto(keyCollector, keys); + if (result.isMissing()) { + return result.asType(); } - return ImmutableSet.copyOf(keys); + return Value.of(ImmutableSet.copyOf(keys)); } } @@ -373,36 +358,26 @@ public PlusCollector(MapCollector left, MapCollector right) { } @Override - public boolean present() { - return left.present() && right.present(); - } - - @Override - public void collectInto(DisplayName owner, MapEntryCollector collector, Map dest) { - left.collectInto(owner, collector, dest); - right.collectInto(owner, collector, dest); + public boolean isPresent() { + return left.isPresent() && right.isPresent(); } @Override - public boolean maybeCollectInto(MapEntryCollector collector, Map dest) { - if (left.maybeCollectInto(collector, dest)) { - return right.maybeCollectInto(collector, dest); + public Value maybeCollectInto(MapEntryCollector collector, Map dest) { + Value result = left.maybeCollectInto(collector, dest); + if (result.isMissing()) { + return result; } - return false; + return right.maybeCollectInto(collector, dest); } @Override - public void collectKeysInto(ValueCollector collector, Collection dest) { - left.collectKeysInto(collector, dest); - right.collectKeysInto(collector, dest); - } - - @Override - public boolean maybeCollectKeysInto(ValueCollector collector, Collection dest) { - if (left.maybeCollectKeysInto(collector, dest)) { - return right.maybeCollectKeysInto(collector, dest); + public Value maybeCollectKeysInto(ValueCollector collector, Collection dest) { + Value result = left.maybeCollectKeysInto(collector, dest); + if (result.isMissing()) { + return result; } - return false; + return right.maybeCollectKeysInto(collector, dest); } @Override diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultProperty.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultProperty.java index 05339a4cf0f0..53b6a3621069 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultProperty.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultProperty.java @@ -25,7 +25,7 @@ public class DefaultProperty extends AbstractProperty implements Property< private final Class type; private final ValueSanitizer sanitizer; private ScalarSupplier convention = Providers.noValue(); - private ScalarSupplier value; + private ScalarSupplier valueSupplier; public DefaultProperty(Class type) { applyDefaultValue(); @@ -35,7 +35,7 @@ public DefaultProperty(Class type) { @Override protected ValueSupplier getSupplier() { - return value; + return valueSupplier; } @Override @@ -71,13 +71,13 @@ public void setFromAnyValue(Object object) { public void set(T value) { if (value == null) { if (beforeReset()) { - this.value = convention; + this.valueSupplier = convention; } return; } if (beforeMutate()) { - this.value = Providers.fixedValue(getValidationDisplayName(), value, type, sanitizer); + this.valueSupplier = Providers.fixedValue(getValidationDisplayName(), value, type, sanitizer); } } @@ -94,7 +94,7 @@ public Property value(Provider provider) { } public ProviderInternal getProvider() { - return value.asProvider(); + return valueSupplier.asProvider(); } public DefaultProperty provider(Provider provider) { @@ -111,7 +111,7 @@ public void set(Provider provider) { throw new IllegalArgumentException("Cannot set the value of a property using a null provider."); } ProviderInternal p = Providers.internal(provider); - this.value = p.asSupplier(getValidationDisplayName(), type, sanitizer); + this.valueSupplier = p.asSupplier(getValidationDisplayName(), type, sanitizer); } @Override @@ -134,53 +134,38 @@ public Property convention(Provider valueProvider) { private void applyConvention(ScalarSupplier conventionSupplier) { if (shouldApplyConvention()) { - this.value = conventionSupplier; + this.valueSupplier = conventionSupplier; } this.convention = conventionSupplier; } @Override protected void applyDefaultValue() { - value = Providers.noValue(); + valueSupplier = Providers.noValue(); } @Override protected void makeFinal() { - value = value.withFinalValue(); + valueSupplier = valueSupplier.withFinalValue(); convention = Providers.noValue(); } - @Override - public T get() { - beforeRead(); - return value.get(getDisplayName()); - } - - @Override - public T getOrNull() { - beforeRead(); - return value.getOrNull(); - } @Override - public T getOrElse(T defaultValue) { + protected Value calculateOwnValue() { beforeRead(); - T t = value.getOrNull(); - if (t == null) { - return defaultValue; - } - return t; + return valueSupplier.calculateValue(); } @Override public boolean isPresent() { beforeRead(); - return value.isPresent(); + return valueSupplier.isPresent(); } @Override protected String describeContents() { // NOTE: Do not realize the value of the Provider in toString(). The debugger will try to call this method and make debugging really frustrating. - return String.format("property(%s, %s)", type, value); + return String.format("property(%s, %s)", type, valueSupplier); } } diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultProvider.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultProvider.java index 14742b9015c8..9a3796367c44 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultProvider.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultProvider.java @@ -21,7 +21,7 @@ import javax.annotation.Nullable; import java.util.concurrent.Callable; -public class DefaultProvider extends AbstractReadOnlyProvider { +public class DefaultProvider extends AbstractMinimalProvider { private final Callable value; public DefaultProvider(Callable value) { @@ -36,9 +36,9 @@ public Class getType() { } @Override - public T getOrNull() { + protected Value calculateOwnValue() { try { - return value.call(); + return Value.ofNullable(value.call()); } catch (Exception e) { throw UncheckedException.throwAsUncheckedException(e); } diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultValueSourceProviderFactory.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultValueSourceProviderFactory.java index 23e7434ef041..e82ec86d192a 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultValueSourceProviderFactory.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/DefaultValueSourceProviderFactory.java @@ -137,7 +137,7 @@ public void parameters(Action configureAction) { } } - public class ValueSourceProvider extends AbstractReadOnlyProvider { + public class ValueSourceProvider extends AbstractMinimalProvider { private final Class> valueSourceType; private final Class

parametersType; @@ -189,9 +189,8 @@ public Class getType() { return null; } - @Nullable @Override - public T getOrNull() { + protected Value calculateOwnValue() { synchronized (this) { if (value == null) { @@ -200,7 +199,7 @@ public T getOrNull() { onValueObtained(); } - return value.get(); + return Value.ofNullable(value.get()); } } diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/MapCollector.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/MapCollector.java index fd44dd222398..192175233e75 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/MapCollector.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/MapCollector.java @@ -16,8 +16,6 @@ package org.gradle.api.internal.provider; -import org.gradle.internal.DisplayName; - import java.util.Collection; import java.util.List; import java.util.Map; @@ -27,15 +25,9 @@ */ public interface MapCollector extends ValueSupplier { - boolean present(); - - void collectInto(DisplayName owner, MapEntryCollector collector, Map dest); - - boolean maybeCollectInto(MapEntryCollector collector, Map dest); - - void collectKeysInto(ValueCollector collector, Collection dest); + Value maybeCollectInto(MapEntryCollector collector, Map dest); - boolean maybeCollectKeysInto(ValueCollector collector, Collection dest); + Value maybeCollectKeysInto(ValueCollector collector, Collection dest); void visit(List>> sources); } diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/MapCollectors.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/MapCollectors.java index c82dcb492bd0..f679c2abc4e9 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/MapCollectors.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/MapCollectors.java @@ -21,7 +21,6 @@ import org.gradle.api.Action; import org.gradle.api.Task; import org.gradle.api.internal.tasks.TaskDependencyResolveContext; -import org.gradle.internal.DisplayName; import java.util.Collection; import java.util.List; @@ -32,26 +31,18 @@ public class MapCollectors { public static class EmptyMap implements MapCollector { @Override - public boolean present() { + public boolean isPresent() { return true; } @Override - public void collectInto(DisplayName owner, MapEntryCollector collector, Map dest) { + public Value maybeCollectInto(MapEntryCollector collector, Map dest) { + return Value.present(); } @Override - public boolean maybeCollectInto(MapEntryCollector collector, Map dest) { - return true; - } - - @Override - public void collectKeysInto(ValueCollector collector, Collection dest) { - } - - @Override - public boolean maybeCollectKeysInto(ValueCollector collector, Collection dest) { - return true; + public Value maybeCollectKeysInto(ValueCollector collector, Collection dest) { + return Value.present(); } @Override @@ -84,30 +75,20 @@ public SingleEntry(K key, V value) { } @Override - public boolean present() { + public boolean isPresent() { return true; } @Override - public void collectInto(DisplayName owner, MapEntryCollector collector, Map dest) { - maybeCollectInto(collector, dest); - } - - @Override - public boolean maybeCollectInto(MapEntryCollector collector, Map dest) { + public Value maybeCollectInto(MapEntryCollector collector, Map dest) { collector.add(key, value, dest); - return true; + return Value.present(); } @Override - public void collectKeysInto(ValueCollector collector, Collection dest) { + public Value maybeCollectKeysInto(ValueCollector collector, Collection dest) { collector.add(key, dest); - } - - @Override - public boolean maybeCollectKeysInto(ValueCollector collector, Collection dest) { - collectKeysInto(collector, dest); - return true; + return Value.present(); } @Override @@ -158,42 +139,27 @@ public EntryWithValueFromProvider(K key, ProviderInternal providerO } @Override - public boolean present() { + public boolean isPresent() { return providerOfValue.isPresent(); } @Override - public void collectInto(DisplayName owner, MapEntryCollector collector, Map dest) { - collector.add(key, providerOfValue.get(), dest); - } - - @Override - public boolean maybeCollectInto(MapEntryCollector collector, Map dest) { - V value = providerOfValue.getOrNull(); - if (value != null) { - collector.add(key, value, dest); - return true; - } else { - return false; + public Value maybeCollectInto(MapEntryCollector collector, Map dest) { + Value value = providerOfValue.calculateValue(); + if (value.isMissing()) { + return value.asType(); } + collector.add(key, value.get(), dest); + return Value.present(); } @Override - public void collectKeysInto(ValueCollector collector, Collection dest) { + public Value maybeCollectKeysInto(ValueCollector collector, Collection dest) { if (providerOfValue.isPresent()) { collector.add(key, dest); + return Value.present(); } else { - throw new IllegalStateException(Providers.NULL_VALUE); - } - } - - @Override - public boolean maybeCollectKeysInto(ValueCollector collector, Collection dest) { - if (providerOfValue.isPresent()) { - collector.add(key, dest); - return true; - } else { - return false; + return Value.missing(); } } @@ -227,30 +193,20 @@ public EntriesFromMap(Map entries) { } @Override - public boolean present() { + public boolean isPresent() { return true; } @Override - public void collectInto(DisplayName owner, MapEntryCollector collector, Map dest) { - maybeCollectInto(collector, dest); - } - - @Override - public boolean maybeCollectInto(MapEntryCollector collector, Map dest) { + public Value maybeCollectInto(MapEntryCollector collector, Map dest) { collector.addAll(entries.entrySet(), dest); - return true; + return Value.present(); } @Override - public void collectKeysInto(ValueCollector collector, Collection dest) { + public Value maybeCollectKeysInto(ValueCollector collector, Collection dest) { collector.addAll(entries.keySet(), dest); - } - - @Override - public boolean maybeCollectKeysInto(ValueCollector collector, Collection dest) { - collectKeysInto(collector, dest); - return true; + return Value.present(); } @Override @@ -282,39 +238,28 @@ public EntriesFromMapProvider(ProviderInternal collector, Map dest) { - collector.addAll(providerOfEntries.get().entrySet(), dest); - } - - @Override - public boolean maybeCollectInto(MapEntryCollector collector, Map dest) { - Map entries = providerOfEntries.getOrNull(); - if (entries != null) { - collector.addAll(entries.entrySet(), dest); - return true; - } else { - return false; + public Value maybeCollectInto(MapEntryCollector collector, Map dest) { + Value> value = providerOfEntries.calculateValue(); + if (value.isMissing()) { + return value.asType(); } + collector.addAll(value.get().entrySet(), dest); + return Value.present(); } @Override - public void collectKeysInto(ValueCollector collector, Collection dest) { - collector.addAll(providerOfEntries.get().keySet(), dest); - } - - @Override - public boolean maybeCollectKeysInto(ValueCollector collector, Collection dest) { + public Value maybeCollectKeysInto(ValueCollector collector, Collection dest) { Map entries = providerOfEntries.getOrNull(); if (entries != null) { collector.addAll(entries.keySet(), dest); - return true; + return Value.present(); } else { - return false; + return Value.missing(); } } @@ -342,28 +287,18 @@ public boolean isValueProducedByTask() { public static class NoValue implements MapCollector { @Override - public boolean present() { + public boolean isPresent() { return false; } @Override - public void collectInto(DisplayName owner, MapEntryCollector collector, Map dest) { - throw Providers.nullValue(owner); + public Value maybeCollectInto(MapEntryCollector collector, Map dest) { + return Value.missing(); } @Override - public boolean maybeCollectInto(MapEntryCollector collector, Map dest) { - return false; - } - - @Override - public void collectKeysInto(ValueCollector collector, Collection dest) { - throw new IllegalStateException(Providers.NULL_VALUE); - } - - @Override - public boolean maybeCollectKeysInto(ValueCollector collector, Collection dest) { - return false; + public Value maybeCollectKeysInto(ValueCollector collector, Collection dest) { + return Value.missing(); } @Override diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractReadOnlyProvider.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/MissingValueException.java similarity index 52% rename from subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractReadOnlyProvider.java rename to subprojects/model-core/src/main/java/org/gradle/api/internal/provider/MissingValueException.java index 16efc696a93f..f224e4c82f12 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/AbstractReadOnlyProvider.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/MissingValueException.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 the original author or authors. + * Copyright 2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,18 +16,15 @@ package org.gradle.api.internal.provider; -import static org.gradle.api.internal.provider.Providers.NULL_VALUE; +import org.gradle.internal.exceptions.Contextual; -/** - * A basic {@link org.gradle.api.provider.Provider} implementation. Subclasses need to provide a {@link #getOrNull()} implementation. - */ -public abstract class AbstractReadOnlyProvider extends AbstractMinimalProvider { - @Override - public T get() { - T evaluatedValue = getOrNull(); - if (evaluatedValue == null) { - throw new IllegalStateException(NULL_VALUE); - } - return evaluatedValue; +@Contextual +public class MissingValueException extends IllegalStateException { + public MissingValueException(String message) { + super(message); + } + + public MissingValueException(String message, Throwable cause) { + super(message, cause); } } diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/ProviderInternal.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/ProviderInternal.java index 8d5e72dfb65e..e8eb0fb2de79 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/ProviderInternal.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/ProviderInternal.java @@ -62,6 +62,11 @@ public interface ProviderInternal extends Provider, TaskDependencyContaine @Override ProviderInternal map(Transformer transformer); + /** + * Calculates the value of this supplier. + */ + ValueSupplier.Value calculateValue(); + /** * Returns a view of this provider that can be used to supply a value to a {@link org.gradle.api.provider.Property} instance. */ diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/Providers.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/Providers.java index d335d5a81fca..32e6a49ced0c 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/Providers.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/Providers.java @@ -16,7 +16,6 @@ package org.gradle.api.internal.provider; -import org.gradle.api.Describable; import org.gradle.api.Transformer; import org.gradle.api.provider.Provider; import org.gradle.internal.Cast; @@ -26,7 +25,6 @@ public class Providers { public static final String NULL_TRANSFORMER_RESULT = "Transformer for this provider returned a null value."; - public static final String NULL_VALUE = "No value has been specified for this provider."; private static final NoValueProvider NULL_PROVIDER = new NoValueProvider(); @@ -38,7 +36,7 @@ public static ScalarSupplier noValue() { } public static ScalarSupplier fixedValue(T value) { - return new FixedValueProvider(value); + return new FixedValueProvider<>(value); } public static ScalarSupplier fixedValue(DisplayName owner, T value, Class targetType, ValueSanitizer sanitizer) { @@ -46,7 +44,7 @@ public static ScalarSupplier fixedValue(DisplayName owner, T value, Class if (!targetType.isInstance(value)) { throw new IllegalArgumentException(String.format("Cannot set the value of %s of type %s using an instance of type %s.", owner.getDisplayName(), targetType.getName(), value.getClass().getName())); } - return new FixedValueProvider(value); + return new FixedValueProvider<>(value); } public static ScalarSupplier nullableValue(@Nullable T value) { @@ -62,7 +60,7 @@ public static ProviderInternal notDefined() { } public static ProviderInternal of(T value) { - return new FixedValueProvider(value); + return new FixedValueProvider<>(value); } public static ProviderInternal internal(final Provider value) { @@ -77,10 +75,6 @@ public static ProviderInternal ofNullable(@Nullable T value) { } } - public static IllegalStateException nullValue(Describable owner) { - return new IllegalStateException(String.format("No value has been specified for %s.", owner.getDisplayName())); - } - public static class FixedValueProvider extends AbstractProviderWithValue implements ScalarSupplier { private final T value; @@ -99,11 +93,6 @@ public T get() { return value; } - @Override - public T get(DisplayName owner) throws IllegalStateException { - return value; - } - @Override public ProviderInternal asProvider() { return this; @@ -116,7 +105,7 @@ public ScalarSupplier withFinalValue() { @Override public ProviderInternal map(final Transformer transformer) { - return new MappedFixedValueProvider(transformer, this); + return new MappedFixedValueProvider<>(transformer, this); } @Override @@ -150,14 +139,14 @@ public boolean isPresent() { } @Override - public S get() { + protected Value calculateOwnValue() { if (value == null) { value = transformer.transform(provider.get()); if (value == null) { throw new IllegalStateException(NULL_TRANSFORMER_RESULT); } } - return value; + return Value.of(value); } @Override @@ -173,13 +162,13 @@ public S getOrNull() { @Override public ProviderInternal map(Transformer transformer) { - return new MappedFixedValueProvider(transformer, this); + return new MappedFixedValueProvider<>(transformer, this); } @Override public String toString() { if (value == null) { - return String.format("transform(not calculated)"); + return "transform(not calculated)"; } return String.format("transform(%s, %s)", getType(), value); } @@ -187,13 +176,8 @@ public String toString() { private static class NoValueProvider extends AbstractMinimalProvider implements ScalarSupplier { @Override - public Object get() { - throw new IllegalStateException(NULL_VALUE); - } - - @Override - public Object get(DisplayName owner) throws IllegalStateException { - throw nullValue(owner); + public Value calculateValue() { + return new Missing<>(); } @Override @@ -208,13 +192,8 @@ public Class getType() { } @Override - public Object getOrNull() { - return null; - } - - @Override - public Object getOrElse(Object defaultValue) { - return defaultValue; + protected Value calculateOwnValue() { + return Value.missing(); } @Override diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/ScalarSupplier.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/ScalarSupplier.java index 0a4e73f18b5a..6f0f245d9d9e 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/ScalarSupplier.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/ScalarSupplier.java @@ -16,25 +16,14 @@ package org.gradle.api.internal.provider; -import org.gradle.internal.DisplayName; - -import javax.annotation.Nullable; - /** * Supplies zero or one value of type {@link T}. */ public interface ScalarSupplier extends ValueSupplier { - boolean isPresent(); - /** - * Returns the value of this supplier or fails. - * - * @param owner A display name that can be used in error messages. + * Calculates the value of this supplier. */ - T get(DisplayName owner) throws IllegalStateException; - - @Nullable - T getOrNull(); + Value calculateValue(); ProviderInternal asProvider(); diff --git a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/ValueSupplier.java b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/ValueSupplier.java index 1b19b40e3f7e..aea23ed2575a 100644 --- a/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/ValueSupplier.java +++ b/subprojects/model-core/src/main/java/org/gradle/api/internal/provider/ValueSupplier.java @@ -16,9 +16,15 @@ package org.gradle.api.internal.provider; +import com.google.common.collect.ImmutableList; import org.gradle.api.Action; import org.gradle.api.Task; import org.gradle.api.internal.tasks.TaskDependencyResolveContext; +import org.gradle.internal.Cast; +import org.gradle.internal.DisplayName; + +import javax.annotation.Nullable; +import java.util.List; public interface ValueSupplier { /** @@ -35,4 +41,165 @@ public interface ValueSupplier { * See {@link ProviderInternal#isValueProducedByTask()}. */ boolean isValueProducedByTask(); + + boolean isPresent(); + + interface Value { + Value MISSING = new ScalarSupplier.Missing<>(); + Value SUCCESS = new Present<>(null); + + static Value ofNullable(@Nullable T value) { + if (value == null) { + return MISSING.asType(); + } + return new Present<>(value); + } + + static Value missing() { + return MISSING.asType(); + } + + static Value of(T value) { + assert value != null; + return new Present<>(value); + } + + static Value present() { + return SUCCESS; + } + + T get() throws IllegalStateException; + + @Nullable + T orNull(); + + S orElse(S defaultValue); + + // Only populated when value is missing + List getPathToOrigin(); + + boolean isMissing(); + + Value asType(); + + Value pushWhenMissing(@Nullable DisplayName displayName); + + Value addPathsFrom(Value rightValue); + } + + class Present implements Value { + private final T result; + + public Present(T result) { + this.result = result; + } + + @Override + public boolean isMissing() { + return false; + } + + @Override + public T get() throws IllegalStateException { + return result; + } + + @Override + public T orNull() { + return result; + } + + @Override + public S orElse(S defaultValue) { + return Cast.uncheckedCast(result); + } + + @Override + public Value pushWhenMissing(@Nullable DisplayName displayName) { + return this; + } + + @Override + public Value asType() { + throw new IllegalStateException(); + } + + @Override + public List getPathToOrigin() { + throw new IllegalStateException(); + } + + @Override + public Value addPathsFrom(Value rightValue) { + throw new IllegalStateException(); + } + } + + class Missing implements Value { + private final List path; + + public Missing() { + this.path = ImmutableList.of(); + } + + public Missing(List path) { + this.path = path; + } + + @Override + public boolean isMissing() { + return true; + } + + @Override + public T get() throws IllegalStateException { + throw new IllegalStateException(); + } + + @Override + public T orNull() { + return null; + } + + @Override + public S orElse(S defaultValue) { + return defaultValue; + } + + @Override + public List getPathToOrigin() { + return path; + } + + @Override + public Value asType() { + return Cast.uncheckedCast(this); + } + + @Override + public Value pushWhenMissing(@Nullable DisplayName displayName) { + if (displayName == null) { + return this; + } + ImmutableList.Builder builder = ImmutableList.builderWithExpectedSize(path.size() + 1); + builder.add(displayName); + builder.addAll(path); + return new Missing<>(builder.build()); + } + + @Override + public Value addPathsFrom(Value rightValue) { + if (path.isEmpty()) { + return rightValue.asType(); + } + Missing other = (Missing) rightValue; + if (other.path.isEmpty()) { + return this; + } + ImmutableList.Builder builder = ImmutableList.builderWithExpectedSize(path.size() + other.path.size()); + builder.addAll(path); + builder.addAll(other.path); + return new Missing<>(builder.build()); + } + } } diff --git a/subprojects/model-core/src/main/java/org/gradle/internal/reflect/annotations/impl/DefaultTypeAnnotationMetadataStore.java b/subprojects/model-core/src/main/java/org/gradle/internal/reflect/annotations/impl/DefaultTypeAnnotationMetadataStore.java index d784d477a897..fefb90fe7c1b 100644 --- a/subprojects/model-core/src/main/java/org/gradle/internal/reflect/annotations/impl/DefaultTypeAnnotationMetadataStore.java +++ b/subprojects/model-core/src/main/java/org/gradle/internal/reflect/annotations/impl/DefaultTypeAnnotationMetadataStore.java @@ -381,20 +381,6 @@ private void processMethodAnnotations(Method method, Map 1) { - annotations.keySet().stream() - .filter(ignoredMethodAnnotations::contains) - .findFirst() - .ifPresent(ignoredMethodAnnotation -> metadataBuilder.recordProblem( - String.format("getter '%s()' annotated with @%s should not be also annotated with %s", - method.getName(), - ignoredMethodAnnotation.getSimpleName(), - simpleAnnotationNames(annotations.keySet().stream() - .filter(annotationType -> !annotationType.equals(ignoredMethodAnnotation))) - ) - )); - } - for (Annotation annotation : annotations.values()) { metadataBuilder.declareAnnotation(annotation); } @@ -511,7 +497,16 @@ private ImmutableMap resolveAnnotations() { // If method should be ignored, then ignore all other annotations List declaredTypes = declaredAnnotations.get(TYPE); for (Annotation declaredType : declaredTypes) { - if (ignoredMethodAnnotations.contains(declaredType.annotationType())) { + Class ignoredMethodAnnotation = declaredType.annotationType(); + if (ignoredMethodAnnotations.contains(ignoredMethodAnnotation)) { + if (declaredAnnotations.values().size() > 1) { + recordProblem(String.format("annotated with @%s should not be also annotated with %s", + ignoredMethodAnnotation.getSimpleName(), + simpleAnnotationNames(declaredAnnotations.values().stream() + .>map(Annotation::annotationType) + .filter(annotationType -> !annotationType.equals(ignoredMethodAnnotation))) + )); + } return ImmutableMap.of(TYPE, declaredType); } } diff --git a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/AbstractProviderTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/AbstractProviderTest.groovy index a5aef35656d8..cc17ddfb6a71 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/AbstractProviderTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/AbstractProviderTest.groovy @@ -19,6 +19,8 @@ package org.gradle.api.internal.provider import org.gradle.api.Transformer import org.gradle.internal.state.ManagedFactory +import javax.annotation.Nullable + class AbstractProviderTest extends ProviderSpec { TestProvider provider = new TestProvider() @@ -64,7 +66,7 @@ class AbstractProviderTest extends ProviderSpec { def "mapped provider is live"() { def transformer = Stub(Transformer) - transformer.transform(_) >> {String s -> "[$s]" } + transformer.transform(_) >> { String s -> "[$s]" } expect: def mapped = provider.map(transformer) @@ -86,9 +88,9 @@ class AbstractProviderTest extends ProviderSpec { def "can chain mapped providers"() { def transformer1 = Stub(Transformer) - transformer1.transform(_) >> {String s -> "[$s]" as String } + transformer1.transform(_) >> { String s -> "[$s]" as String } def transformer2 = Stub(Transformer) - transformer2.transform(_) >> {String s -> "-$s-" as String } + transformer2.transform(_) >> { String s -> "-$s-" as String } expect: def mapped = provider.map(transformer1).map(transformer2) @@ -110,10 +112,11 @@ class AbstractProviderTest extends ProviderSpec { then: def e = thrown(IllegalStateException) - e.message == 'No value has been specified for this provider.' + e.message == 'Cannot query the value of this provider because it has no value available.' } - static class TestProvider extends AbstractReadOnlyProvider { + static class TestProvider extends AbstractMinimalProvider { + @Nullable String value void value(String s) { @@ -126,8 +129,8 @@ class AbstractProviderTest extends ProviderSpec { } @Override - Object getOrNull() { - return value + protected Value calculateOwnValue() { + return Value.ofNullable(value) } } } diff --git a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/CollectionPropertySpec.groovy b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/CollectionPropertySpec.groovy index d9c7eb38c168..e08476d243b2 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/CollectionPropertySpec.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/CollectionPropertySpec.groovy @@ -19,6 +19,8 @@ package org.gradle.api.internal.provider import com.google.common.collect.ImmutableCollection import org.gradle.api.Transformer import org.gradle.api.provider.Provider +import org.gradle.internal.Describables +import org.gradle.util.TextUtil import spock.lang.Unroll abstract class CollectionPropertySpec> extends PropertySpec { @@ -87,6 +89,7 @@ abstract class CollectionPropertySpec> extends Prop } def "can change value to empty collection"() { + property.set(["abc"]) property.empty() expect: @@ -144,7 +147,7 @@ abstract class CollectionPropertySpec> extends Prop def "can set untyped from provider"() { def provider = Stub(ProviderInternal) provider.type >> null - provider.get() >>> [["1"], ["2"]] + provider.calculateValue() >>> [["1"], ["2"]].collect { ValueSupplier.Value.of(it) } expect: property.setFromAnyValue(provider) @@ -174,7 +177,7 @@ abstract class CollectionPropertySpec> extends Prop def "queries underlying provider for every call to get()"() { def provider = Stub(ProviderInternal) provider.type >> List - provider.get() >>> [["123"], ["abc"]] + provider.calculateValue() >>> [["123"], ["abc"]].collect { ValueSupplier.Value.of(it) } provider.present >> true expect: @@ -279,7 +282,7 @@ abstract class CollectionPropertySpec> extends Prop def "queries values of provider on every call to get()"() { def provider = Stub(ProviderInternal) _ * provider.present >> true - _ * provider.get() >>> [["abc"], ["def"]] + _ * provider.calculateValue() >>> [["abc"], ["def"]].collect { ValueSupplier.Value.of(it) } expect: property.addAll(provider) @@ -352,18 +355,18 @@ abstract class CollectionPropertySpec> extends Prop property.get() then: - 1 * valueProvider.get() >> ["1"] - 1 * addProvider.get() >> "2" - 1 * addAllProvider.get() >> ["3"] + 1 * valueProvider.calculateValue() >> ValueSupplier.Value.of(["1"]) + 1 * addProvider.calculateValue() >> ValueSupplier.Value.of("2") + 1 * addAllProvider.calculateValue() >> ValueSupplier.Value.of(["3"]) 0 * _ when: property.getOrNull() then: - 1 * valueProvider.getOrNull() >> ["1"] - 1 * addProvider.getOrNull() >> "2" - 1 * addAllProvider.getOrNull() >> ["3"] + 1 * valueProvider.calculateValue() >> ValueSupplier.Value.of(["1"]) + 1 * addProvider.calculateValue() >> ValueSupplier.Value.of("2") + 1 * addAllProvider.calculateValue() >> ValueSupplier.Value.of(["3"]) 0 * _ } @@ -404,8 +407,8 @@ abstract class CollectionPropertySpec> extends Prop property.get() then: - def e = thrown(IllegalStateException) - e.message == "No value has been specified for this property." + def e = thrown(MissingValueException) + e.message == "Cannot query the value of ${displayName} because it has no value available." } def "property has no value when set to provider with no value and other values appended"() { @@ -428,7 +431,7 @@ abstract class CollectionPropertySpec> extends Prop then: def e = thrown(IllegalStateException) - e.message == Providers.NULL_VALUE + e.message == "Cannot query the value of ${displayName} because it has no value available." } def "property has no value when adding an element provider with no value"() { @@ -447,7 +450,22 @@ abstract class CollectionPropertySpec> extends Prop then: def e = thrown(IllegalStateException) - e.message == Providers.NULL_VALUE + e.message == "Cannot query the value of ${displayName} because it has no value available." + } + + def "reports the source of element provider when value is missing and source is known"() { + given: + def elementProvider = supplierWithNoValue(Describables.of("")) + property.set(toMutable(["123"])) + property.add(elementProvider) + + when: + property.get() + + then: + def e = thrown(IllegalStateException) + e.message == TextUtil.toPlatformLineSeparators("""Cannot query the value of ${displayName} because it has no value available. +The value of this property is derived from: """) } def "property has no value when adding an collection provider with no value"() { @@ -466,7 +484,22 @@ abstract class CollectionPropertySpec> extends Prop then: def e = thrown(IllegalStateException) - e.message == Providers.NULL_VALUE + e.message == "Cannot query the value of ${displayName} because it has no value available." + } + + def "reports the source of collection provider when value is missing and source is known"() { + given: + def elementsProvider = supplierWithNoValue(Describables.of("")) + property.set(toMutable(["123"])) + property.addAll(elementsProvider) + + when: + property.get() + + then: + def e = thrown(IllegalStateException) + e.message == TextUtil.toPlatformLineSeparators("""Cannot query the value of ${displayName} because it has no value available. +The value of this property is derived from: """) } def "can set to null value to discard value"() { diff --git a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/DefaultPropertyTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/DefaultPropertyTest.groovy index c53f05b27d79..48d9aa08eba2 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/DefaultPropertyTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/DefaultPropertyTest.groovy @@ -72,15 +72,15 @@ class DefaultPropertyTest extends PropertySpec { property.get() then: - def e = thrown(IllegalStateException) - e.message == "No value has been specified for ${displayName}." + def e = thrown(MissingValueException) + e.message == "Cannot query the value of ${displayName} because it has no value available." } def "toString() does not realize value"() { given: def propertyWithBadValue = property() propertyWithBadValue.set(new DefaultProvider({ - assert false : "never called" + assert false: "never called" })) expect: @@ -136,7 +136,7 @@ class DefaultPropertyTest extends PropertySpec { given: provider.asSupplier(_, _, _) >> supplier - supplier.get(_) >>> [1, 2, 3] + supplier.calculateValue() >>> [1, 2, 3].collect { ValueSupplier.Value.ofNullable(it) } def property = new DefaultProperty(Number) @@ -217,7 +217,7 @@ class DefaultPropertyTest extends PropertySpec { def "mapped provider is live"() { def transformer = Mock(Transformer) - def provider = provider("abc") + def provider = supplierWithValues("abc") def property = new DefaultProperty(String) diff --git a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/DefaultProviderTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/DefaultProviderTest.groovy index 59b174febec3..d24ded0d0f3e 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/DefaultProviderTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/DefaultProviderTest.groovy @@ -64,7 +64,7 @@ class DefaultProviderTest extends ProviderSpec { then: def t = thrown(IllegalStateException) - t.message == "No value has been specified for this provider." + t.message == "Cannot query the value of this provider because it has no value available." when: provider = createProvider(null) @@ -72,7 +72,7 @@ class DefaultProviderTest extends ProviderSpec { then: t = thrown(IllegalStateException) - t.message == "No value has been specified for this provider." + t.message == "Cannot query the value of this provider because it has no value available." when: provider = createProvider(true) diff --git a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/MapPropertySpec.groovy b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/MapPropertySpec.groovy index a6f0b3c44e95..bc3342dd1b59 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/MapPropertySpec.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/api/internal/provider/MapPropertySpec.groovy @@ -17,7 +17,9 @@ package org.gradle.api.internal.provider import com.google.common.collect.ImmutableMap +import org.gradle.internal.Describables import org.gradle.internal.state.ManagedFactory +import org.gradle.util.TextUtil import org.spockframework.util.Assert class MapPropertySpec extends PropertySpec> { @@ -103,7 +105,7 @@ class MapPropertySpec extends PropertySpec> { given: def provider = Stub(ProviderInternal) provider.type >> null - provider.get() >>> [['k1': 'v1'], ['k2': 'v2']] + provider.calculateValue() >>> [['k1': 'v1'], ['k2': 'v2']].collect { ValueSupplier.Value.of(it) } when: property.setFromAnyValue(provider) @@ -132,7 +134,7 @@ class MapPropertySpec extends PropertySpec> { given: def provider = Stub(ProviderInternal) provider.type >> Map - provider.get() >>> [['k1': 'v1'], ['k2': 'v2']] + provider.calculateValue() >>> [['k1': 'v1'], ['k2': 'v2']].collect { ValueSupplier.Value.of(it) } provider.present >> true and: property.set(provider) @@ -229,7 +231,7 @@ class MapPropertySpec extends PropertySpec> { def provider = Stub(ProviderInternal) _ * provider.type >> Map _ * provider.present >> true - _ * provider.get() >>> [['k1': 'v1'], ['k2': 'v2']] + _ * provider.calculateValue() >>> [['k1': 'v1'], ['k2': 'v2']].collect { ValueSupplier.Value.of(it) } and: property.putAll(provider) @@ -274,17 +276,17 @@ class MapPropertySpec extends PropertySpec> { when: property.get() then: - 1 * valueProvider.get() >> ['k1': 'v1'] - 1 * putProvider.get() >> 'v2' - 1 * putAllProvider.get() >> ['k3': 'v3'] + 1 * valueProvider.calculateValue() >> ValueSupplier.Value.of(['k1': 'v1']) + 1 * putProvider.calculateValue() >> ValueSupplier.Value.of('v2') + 1 * putAllProvider.calculateValue() >> ValueSupplier.Value.of(['k3': 'v3']) 0 * _ when: property.getOrNull() then: - 1 * valueProvider.getOrNull() >> ['k1': 'v1'] - 1 * putProvider.getOrNull() >> 'v2' - 1 * putAllProvider.getOrNull() >> ['k3': 'v3'] + 1 * valueProvider.calculateValue() >> ValueSupplier.Value.of(['k1': 'v1']) + 1 * putProvider.calculateValue() >> ValueSupplier.Value.of('v2') + 1 * putAllProvider.calculateValue() >> ValueSupplier.Value.of(['k3': 'v3']) 0 * _ } @@ -317,7 +319,7 @@ class MapPropertySpec extends PropertySpec> { property.get() then: def e = thrown(IllegalStateException) - e.message == Providers.NULL_VALUE + e.message == "Cannot query the value of ${displayName} because it has no value available." } def "property has no value when adding a value provider with no value"() { @@ -335,7 +337,23 @@ class MapPropertySpec extends PropertySpec> { property.get() then: def e = thrown(IllegalStateException) - e.message == Providers.NULL_VALUE + e.message == "Cannot query the value of ${displayName} because it has no value available." + } + + def "reports the source of value provider when value is missing and source is known"() { + given: + def provider = supplierWithNoValue(String, Describables.of("")) + property.set(['k1': 'v1']) + property.put('k2', 'v2') + property.put('k3', provider) + + when: + property.get() + + then: + def e = thrown(IllegalStateException) + e.message == TextUtil.toPlatformLineSeparators("""Cannot query the value of ${displayName} because it has no value available. +The value of this property is derived from: """) } def "property has no value when adding a map provider with no value"() { @@ -353,7 +371,23 @@ class MapPropertySpec extends PropertySpec> { property.get() then: def e = thrown(IllegalStateException) - e.message == Providers.NULL_VALUE + e.message == "Cannot query the value of ${displayName} because it has no value available." + } + + def "reports the source of map provider when value is missing and source is known"() { + given: + def provider = supplierWithNoValue(Describables.of("")) + property.set(['k1': 'v1']) + property.put('k2', 'v2') + property.putAll(provider) + + when: + property.get() + + then: + def e = thrown(IllegalStateException) + e.message == TextUtil.toPlatformLineSeparators("""Cannot query the value of ${displayName} because it has no value available. +The value of this property is derived from: """) } def "can set to null value to discard value"() { @@ -617,8 +651,10 @@ class MapPropertySpec extends PropertySpec> { when: entryProvider.get() + then: - thrown IllegalStateException + def e = thrown(MissingValueException) + e.message == "Cannot query the value of this provider because it has no value available." } def "entry provider has no value when key is not in map"() { @@ -632,8 +668,10 @@ class MapPropertySpec extends PropertySpec> { when: entryProvider.get() + then: - thrown IllegalStateException + def e = thrown(MissingValueException) + e.message == "Cannot query the value of this provider because it has no value available." } def "entry provider tracks value of property"() { @@ -653,6 +691,12 @@ class MapPropertySpec extends PropertySpec> { entryProvider.present entryProvider.get() == 'v2' entryProvider.getOrNull() == 'v2' + + when: + property.set(Providers.of([:])) + then: + !entryProvider.present + entryProvider.getOrNull() == null } def "entry provider tracks value of last added entry"() { @@ -699,8 +743,10 @@ class MapPropertySpec extends PropertySpec> { when: keySetProvider.get() + then: - thrown IllegalStateException + def e = thrown(MissingValueException) + e.message == "Cannot query the value of this provider because it has no value available." } def "keySet provider tracks value of property"() { @@ -772,7 +818,7 @@ class MapPropertySpec extends PropertySpec> { def result2 = property.get() then: - 1 * provider.getOrNull() >> "value" + 1 * provider.calculateValue() >> ValueSupplier.Value.of("value") 0 * _ and: diff --git a/subprojects/model-core/src/test/groovy/org/gradle/internal/reflect/annotations/impl/DefaultTypeAnnotationMetadataStoreTest.groovy b/subprojects/model-core/src/test/groovy/org/gradle/internal/reflect/annotations/impl/DefaultTypeAnnotationMetadataStoreTest.groovy index c64e415993a8..196456976fb1 100644 --- a/subprojects/model-core/src/test/groovy/org/gradle/internal/reflect/annotations/impl/DefaultTypeAnnotationMetadataStoreTest.groovy +++ b/subprojects/model-core/src/test/groovy/org/gradle/internal/reflect/annotations/impl/DefaultTypeAnnotationMetadataStoreTest.groovy @@ -257,7 +257,7 @@ class DefaultTypeAnnotationMetadataStoreTest extends Specification { assertProperties TypeWithIgnoredPropertyWithOtherAnnotations, [ ignoredProperty: [(TYPE): Ignored] ], [ - "Property 'ignoredProperty' getter 'getIgnoredProperty()' annotated with @Ignored should not be also annotated with @Color." + "Property 'ignoredProperty' annotated with @Ignored should not be also annotated with @Color." ] } @@ -272,7 +272,7 @@ class DefaultTypeAnnotationMetadataStoreTest extends Specification { assertProperties TypeWithIgnoredPropertyWithMultipleIgnoreAnnotations, [ twiceIgnoredProperty: [(TYPE): Ignored] ], [ - "Property 'twiceIgnoredProperty' getter 'getTwiceIgnoredProperty()' annotated with @Ignored should not be also annotated with @Ignored2." + "Property 'twiceIgnoredProperty' annotated with @Ignored should not be also annotated with @Ignored2." ] } @@ -282,6 +282,26 @@ class DefaultTypeAnnotationMetadataStoreTest extends Specification { String getTwiceIgnoredProperty() } + def "warns when field is ignored but there is another annotation on the getter"() { + expect: + assertProperties TypeWithIgnoredFieldAndGetterInput, [ + ignoredByField: [(TYPE): Ignored] + ], [ + "Property 'ignoredByField' annotated with @Ignored should not be also annotated with @Small." + ] + } + + @SuppressWarnings("unused") + static class TypeWithIgnoredFieldAndGetterInput { + @Ignored + private String ignoredByField; + + @Small + String getIgnoredByField() { + return ignoredByField + } + } + def "superclass properties are present in subclass"() { expect: assertProperties TypeWithSuperclassProperties, [ diff --git a/subprojects/model-core/src/testFixtures/groovy/org/gradle/api/internal/provider/PropertySpec.groovy b/subprojects/model-core/src/testFixtures/groovy/org/gradle/api/internal/provider/PropertySpec.groovy index 83c246511dea..6e9a78858e89 100644 --- a/subprojects/model-core/src/testFixtures/groovy/org/gradle/api/internal/provider/PropertySpec.groovy +++ b/subprojects/model-core/src/testFixtures/groovy/org/gradle/api/internal/provider/PropertySpec.groovy @@ -16,13 +16,15 @@ package org.gradle.api.internal.provider -import org.gradle.api.Action + import org.gradle.api.Task import org.gradle.api.Transformer import org.gradle.api.internal.tasks.TaskDependencyResolveContext import org.gradle.api.provider.Provider import org.gradle.internal.Describables +import org.gradle.internal.DisplayName import org.gradle.internal.state.Managed +import org.gradle.util.TextUtil import java.util.concurrent.Callable @@ -68,16 +70,16 @@ abstract class PropertySpec extends ProviderSpec { property.get() then: - def t = thrown(IllegalStateException) - t.message == "No value has been specified for ${displayName}." + def t = thrown(MissingValueException) + t.message == "Cannot query the value of ${displayName} because it has no value available." when: property.attachDisplayName(Describables.of("")) property.get() then: - def t2 = thrown(IllegalStateException) - t2.message == "No value has been specified for ." + def t2 = thrown(MissingValueException) + t2.message == "Cannot query the value of because it has no value available." when: property.set(someValue()) @@ -110,7 +112,7 @@ abstract class PropertySpec extends ProviderSpec { } def "can set value using provider"() { - def provider = provider(someValue(), someValue(), someOtherValue(), someValue()) + def provider = supplierWithValues(someValue(), someOtherValue(), someValue()) given: def property = propertyWithNoValue() @@ -124,7 +126,7 @@ abstract class PropertySpec extends ProviderSpec { property.getOrNull() == null } - def "can set value using provider and chaining method"() { + def "can set value using provider with chaining method"() { given: def property = propertyWithNoValue() property.value(Providers.of(someValue())) @@ -181,7 +183,7 @@ abstract class PropertySpec extends ProviderSpec { } def "can set untyped using provider"() { - def provider = provider(someValue(), someValue()) + def provider = supplierWithValues(someValue(), someValue()) given: def property = propertyWithNoValue() @@ -207,7 +209,7 @@ abstract class PropertySpec extends ProviderSpec { } def "convention provider is used before value has been set"() { - def provider = provider(someValue(), someOtherValue(), someValue()) + def provider = supplierWithValues(someOtherValue(), someValue(), someValue()) def property = propertyWithDefaultValue() when: @@ -226,8 +228,42 @@ abstract class PropertySpec extends ProviderSpec { property.get() == someOtherValue() } + def "property has no value when convention provider has no value"() { + def provider = supplierWithNoValue() + def property = propertyWithDefaultValue() + + when: + property.convention(provider) + + then: + !property.present + + when: + property.get() + + then: + def e = thrown(MissingValueException) + e.message == "Cannot query the value of ${displayName} because it has no value available." + } + + def "reports the source of convention provider when value is missing and source is known"() { + def provider = supplierWithNoValue(Describables.of("")) + def property = propertyWithDefaultValue() + + given: + property.convention(provider) + + when: + property.get() + + then: + def e = thrown(IllegalStateException) + e.message == TextUtil.toPlatformLineSeparators("""Cannot query the value of ${displayName} because it has no value available. +The value of this property is derived from: """) + } + def "can replace convention value before value has been set"() { - def provider = provider(someOtherValue()) + def provider = supplierWithValues(someOtherValue()) def property = propertyWithDefaultValue() when: @@ -265,7 +301,7 @@ abstract class PropertySpec extends ProviderSpec { } def "convention provider ignored after value has been set"() { - def provider = broken() + def provider = brokenSupplier() def property = propertyWithDefaultValue() property.set(someValue()) @@ -291,7 +327,7 @@ abstract class PropertySpec extends ProviderSpec { } def "convention provider is used after value has been set to null"() { - def provider = provider(someOtherValue(), someOtherValue()) + def provider = supplierWithValues(someOtherValue(), someOtherValue()) def property = propertyWithDefaultValue() property.convention(provider) @@ -314,7 +350,7 @@ abstract class PropertySpec extends ProviderSpec { } def "convention provider ignored after value has been set using provider with no value"() { - def provider = broken() + def provider = brokenSupplier() def property = propertyWithDefaultValue() property.set(Providers.notDefined()) @@ -427,8 +463,78 @@ abstract class PropertySpec extends ProviderSpec { provider.get() then: - def e = thrown(IllegalStateException) - e.message == "No value has been specified for ${displayName}." + def e = thrown(MissingValueException) + e.message == "Cannot query the value of this provider because it has no value available." + } + + def "reports the source of mapped provider when value is missing and source is known"() { + def transformer = Mock(Transformer) + def property = propertyWithNoValue() + property.attachDisplayName(Describables.of("")) + + def provider = property.map(transformer) + + when: + provider.get() + + then: + def e = thrown(MissingValueException) + e.message == TextUtil.toPlatformLineSeparators("""Cannot query the value of this provider because it has no value available. +The value of this provider is derived from: """) + } + + def "reports the source of flat mapped provider when value is missing and source is known"() { + def transformer = Mock(Transformer) + def property = propertyWithNoValue() + property.attachDisplayName(Describables.of("")) + + def provider = property.flatMap(transformer) + + when: + provider.get() + + then: + def e = thrown(MissingValueException) + e.message == TextUtil.toPlatformLineSeparators("""Cannot query the value of this provider because it has no value available. +The value of this provider is derived from: """) + } + + def "reports the source of flat mapped provider when mapped value is missing and its source is known"() { + def property = propertyWithNoValue() + property.set(someValue()) + + def other = propertyWithNoValue() + other.attachDisplayName(Describables.of("")) + + def provider = property.flatMap { other } + + when: + provider.get() + + then: + def e = thrown(MissingValueException) + e.message == TextUtil.toPlatformLineSeparators("""Cannot query the value of this provider because it has no value available. +The value of this provider is derived from: """) + } + + def "reports the source of orElse provider when both values are missing and its source is known"() { + def property = propertyWithNoValue() + property.attachDisplayName(Describables.of("")) + + def other = propertyWithNoValue() + other.attachDisplayName(Describables.of("")) + + def provider = property.orElse(other) + + when: + provider.get() + + then: + def e = thrown(MissingValueException) + e.message == TextUtil.toPlatformLineSeparators("""Cannot query the value of this provider because it has no value available. +The value of this provider is derived from: + - + - """) } def "can finalize value when no value defined"() { @@ -1547,6 +1653,85 @@ abstract class PropertySpec extends ProviderSpec { e2.message == 'The value for cannot be changed any further.' } + def "reports the source of property value when value is missing and source is known"() { + given: + def a = propertyWithNoValue() + def b = propertyWithNoValue() + def c = propertyWithNoValue() + a.attachDisplayName(Describables.of("")) + a.set(b) + b.set(c) + + when: + a.get() + + then: + def e = thrown(MissingValueException) + e.message == "Cannot query the value of because it has no value available." + + when: + c.attachDisplayName(Describables.of("")) + a.get() + + then: + def e2 = thrown(MissingValueException) + e2.message == TextUtil.toPlatformLineSeparators("""Cannot query the value of because it has no value available. +The value of this property is derived from: """) + + when: + b.attachDisplayName(Describables.of("")) + a.get() + + then: + def e3 = thrown(MissingValueException) + e3.message == TextUtil.toPlatformLineSeparators("""Cannot query the value of because it has no value available. +The value of this property is derived from: + - + - """) + } + + def "reports the source of mapped property value when value is missing and source is known"() { + given: + def a = propertyWithNoValue() + def b = propertyWithNoValue() + def c = propertyWithNoValue() + a.attachDisplayName(Describables.of("")) + a.set(b.map { it }) + b.set(c.map { it }) + def provider = a.map { it } + + when: + provider.get() + + then: + def e = thrown(MissingValueException) + e.message == TextUtil.toPlatformLineSeparators("""Cannot query the value of this provider because it has no value available. +The value of this provider is derived from: """) + + when: + c.attachDisplayName(Describables.of("")) + provider.get() + + then: + def e2 = thrown(MissingValueException) + e2.message == TextUtil.toPlatformLineSeparators("""Cannot query the value of this provider because it has no value available. +The value of this provider is derived from: + - + - """) + + when: + b.attachDisplayName(Describables.of("")) + provider.get() + + then: + def e3 = thrown(MissingValueException) + e3.message == TextUtil.toPlatformLineSeparators("""Cannot query the value of this provider because it has no value available. +The value of this provider is derived from: + - + - + - """) + } + def "producer task for a property is not known by default"() { def context = Mock(TaskDependencyResolveContext) def property = propertyWithNoValue() @@ -1578,7 +1763,7 @@ abstract class PropertySpec extends ProviderSpec { def "has build dependencies when value is provider with producer task"() { def producer = "some task" - def provider = withProducer(producer) + def provider = supplierWithProducer(producer) def context = Mock(TaskDependencyResolveContext) def property = propertyWithNoValue() property.set(provider) @@ -1608,7 +1793,7 @@ abstract class PropertySpec extends ProviderSpec { def "has content producer when value is provider with content producer"() { def task = Mock(Task) - def provider = contentProducedByTask(task) + def provider = supplierWithProducer(task) def property = propertyWithNoValue() property.set(provider) @@ -1650,7 +1835,7 @@ abstract class PropertySpec extends ProviderSpec { def "mapped value has value producer when value is provider with content producer"() { def task = Mock(Task) - def provider = contentProducedByTask(task) + def provider = supplierWithProducer(task) def property = propertyWithNoValue() property.set(provider) @@ -1699,66 +1884,60 @@ abstract class PropertySpec extends ProviderSpec { assert producers == [task] } - ProviderInternal broken() { - return new AbstractReadOnlyProvider() { - @Override - Class getType() { - return PropertySpec.this.type() - } + /** + * A dummy provider with no value. + */ + ProviderInternal supplierWithNoValue() { + return new NoValueProvider(type(), null) + } - @Override - T getOrNull() { - throw new RuntimeException("broken!") - } - } + /** + * A dummy provider with no value and the given display name + */ + ProviderInternal supplierWithNoValue(DisplayName displayName) { + return new NoValueProvider(type(), displayName) } /** - * A provider that provides one of given values each time it is queried, in the order given. + * A dummy provider with no value and the given display name */ - ProviderInternal provider(T... values) { - return new TestProvider(type(), values as List, null) + ProviderInternal supplierWithNoValue(Class type, DisplayName displayName) { + return new NoValueProvider(type, displayName) } - ProviderInternal withProducer(Object value) { - return new TestProvider(type(), [], value) + /** + * A dummy provider that provides one of given values each time it is queried, in the order given. + */ + ProviderInternal supplierWithValues(T... values) { + return ProviderTestUtil.withValues(values) } - ProviderInternal contentProducedByTask(Task producer) { - return new TestProvider(type(), [], producer) + ProviderInternal supplierWithProducer(Object producer) { + return ProviderTestUtil.withProducer(type(), producer) } - class TestProvider extends AbstractReadOnlyProvider { - final Class type - final Iterator values - final Object producer + class NoValueProvider extends AbstractMinimalProvider { + private final Class type + private final DisplayName displayName - TestProvider(Class type, List values, Object producer) { - this.producer = producer - this.values = values.iterator() + NoValueProvider(Class type, DisplayName displayName) { + this.displayName = displayName this.type = type } @Override - void visitProducerTasks(Action visitor) { - if (producer != null) { - visitor.execute(producer) - } + Class getType() { + return type } @Override - boolean maybeVisitBuildDependencies(TaskDependencyResolveContext context) { - if (producer != null) { - context.add(producer) - return true - } else { - return false - } + protected Value calculateOwnValue() { + return Value.missing() } @Override - T getOrNull() { - return values.hasNext() ? values.next() : null + Value calculateValue() { + return Value.missing().pushWhenMissing(displayName) } } diff --git a/subprojects/model-core/src/testFixtures/groovy/org/gradle/api/internal/provider/ProviderSpec.groovy b/subprojects/model-core/src/testFixtures/groovy/org/gradle/api/internal/provider/ProviderSpec.groovy index e251a5df3eb7..934c7772f059 100644 --- a/subprojects/model-core/src/testFixtures/groovy/org/gradle/api/internal/provider/ProviderSpec.groovy +++ b/subprojects/model-core/src/testFixtures/groovy/org/gradle/api/internal/provider/ProviderSpec.groovy @@ -172,8 +172,8 @@ abstract class ProviderSpec extends Specification { provider.get() then: - def t = thrown(IllegalStateException) - t.message == "No value has been specified for ${displayName}." + def t = thrown(MissingValueException) + t.message == "Cannot query the value of ${displayName} because it has no value available." } def "mapped provider with no value does not use transformer"() { @@ -192,8 +192,8 @@ abstract class ProviderSpec extends Specification { mapped.get() then: - def t = thrown(IllegalStateException) - t.message == "No value has been specified for ${displayName}." + def t = thrown(MissingValueException) + t.message == "Cannot query the value of this provider because it has no value available." } def "flat mapped provider with no value does not use transformer"() { @@ -212,8 +212,8 @@ abstract class ProviderSpec extends Specification { mapped.get() then: - def t = thrown(IllegalStateException) - t.message == "No value has been specified for ${displayName}." + def t = thrown(MissingValueException) + t.message == "Cannot query the value of this provider because it has no value available." } def "can map to provider that uses value if present or a default value"() { @@ -231,10 +231,11 @@ abstract class ProviderSpec extends Specification { def "can map to provider that uses value if present or a default value from another provider"() { expect: + def broken = brokenSupplier() def supplier = Providers.of(someOtherValue()) def present = providerWithValue(someValue()) - def usesValue = present.orElse(supplier) + def usesValue = present.orElse(broken) usesValue.present usesValue.get() == someValue() @@ -250,15 +251,17 @@ abstract class ProviderSpec extends Specification { expect: def supplier = Providers.notDefined() - def present = providerWithValue(someValue()) - def usesValue = present.orElse(supplier) - usesValue.present - usesValue.get() == someValue() - def notPresent = providerWithNoValue() def usesDefaultValue = notPresent.orElse(supplier) !usesDefaultValue.present usesDefaultValue.getOrNull() == null + + when: + notPresent.get() + + then: + def e = thrown(MissingValueException) + e.message == "Cannot query the value of ${displayName} because it has no value available." } def "can chain orElse"() { @@ -300,4 +303,22 @@ abstract class ProviderSpec extends Specification { copy.present copy.getOrNull() == someValue() } + + /** + * A test provider that always fails. + */ + ProviderInternal brokenSupplier() { + return new AbstractMinimalProvider() { + @Override + Class getType() { + return ProviderSpec.this.type() + } + + @Override + protected ValueSupplier.Value calculateOwnValue() { + throw new RuntimeException("broken!") + } + } + } + } diff --git a/subprojects/model-core/src/testFixtures/groovy/org/gradle/api/internal/provider/ProviderTestUtil.java b/subprojects/model-core/src/testFixtures/groovy/org/gradle/api/internal/provider/ProviderTestUtil.java new file mode 100644 index 000000000000..22dee001c5a8 --- /dev/null +++ b/subprojects/model-core/src/testFixtures/groovy/org/gradle/api/internal/provider/ProviderTestUtil.java @@ -0,0 +1,85 @@ +/* + * Copyright 2020 the original author or authors. + * + * 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 org.gradle.api.internal.provider; + +import org.gradle.api.Action; +import org.gradle.api.Task; +import org.gradle.api.internal.tasks.TaskDependencyResolveContext; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +public class ProviderTestUtil { + public static ProviderInternal withNoValue() { + return Providers.notDefined(); + } + + public static ProviderInternal withValues(T... values) { + assert values.length > 0; + return new TestProvider<>((Class) values[0].getClass(), Arrays.asList(values), null); + } + + public static ProviderInternal withProducer(Class type, Object producer) { + return new TestProvider<>(type, Collections.emptyList(), producer); + } + + private static class TestProvider extends AbstractMinimalProvider { + final Class type; + final Iterator values; + final Object producer; + + TestProvider(Class type, List values, Object producer) { + this.producer = producer; + this.values = values.iterator(); + this.type = type; + } + + @Override + public Class getType() { + return type; + } + + @Override + public void visitProducerTasks(Action visitor) { + if (producer != null) { + visitor.execute((Task) producer); + } + } + + @Override + public boolean maybeVisitBuildDependencies(TaskDependencyResolveContext context) { + if (producer != null) { + context.add(producer); + return true; + } else { + return false; + } + } + + @Override + public boolean isPresent() { + return values.hasNext(); + } + + @Override + protected Value calculateOwnValue() { + return values.hasNext() ? Value.of(values.next()) : Value.missing(); + } + } +} diff --git a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/FasterIncrementalAndroidBuildsPerformanceTest.groovy b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/FasterIncrementalAndroidBuildsPerformanceTest.groovy index c32834d911aa..ec4d7f4f6d3e 100644 --- a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/FasterIncrementalAndroidBuildsPerformanceTest.groovy +++ b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/FasterIncrementalAndroidBuildsPerformanceTest.groovy @@ -16,6 +16,7 @@ package org.gradle.performance.regression.android +import org.gradle.integtests.fixtures.versions.AndroidGradlePluginVersions import org.gradle.internal.service.scopes.VirtualFileSystemServices import org.gradle.performance.AbstractCrossBuildPerformanceTest import org.gradle.performance.categories.PerformanceExperiment @@ -76,7 +77,7 @@ class FasterIncrementalAndroidBuildsPerformanceTest extends AbstractCrossBuildPe @Override protected void defaultSpec(BuildExperimentSpec.Builder builder) { if (builder instanceof GradleBuildExperimentSpec.GradleBuilder) { - builder.invocation.args('-Dcom.android.build.gradle.overrideVersionCheck=true') + builder.invocation.args(AndroidGradlePluginVersions.OVERRIDE_VERSION_CHECK) } } diff --git a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/RealLifeAndroidBuildPerformanceTest.groovy b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/RealLifeAndroidBuildPerformanceTest.groovy index bfc067d38ab3..2713b927d9bf 100644 --- a/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/RealLifeAndroidBuildPerformanceTest.groovy +++ b/subprojects/performance/src/performanceTest/groovy/org/gradle/performance/regression/android/RealLifeAndroidBuildPerformanceTest.groovy @@ -16,6 +16,7 @@ package org.gradle.performance.regression.android +import org.gradle.integtests.fixtures.versions.AndroidGradlePluginVersions import org.gradle.internal.scan.config.fixtures.GradleEnterprisePluginSettingsFixture import org.gradle.performance.AbstractCrossVersionGradleProfilerPerformanceTest import org.gradle.performance.categories.SlowPerformanceRegressionTest @@ -32,7 +33,7 @@ import static org.gradle.performance.regression.android.IncrementalAndroidTestPr class RealLifeAndroidBuildPerformanceTest extends AbstractCrossVersionGradleProfilerPerformanceTest { def setup() { - runner.args = ['-Dcom.android.build.gradle.overrideVersionCheck=true'] + runner.args = [AndroidGradlePluginVersions.OVERRIDE_VERSION_CHECK] runner.targetVersions = ["6.2-20200108160029+0000"] // AGP 3.6 requires 5.6.1+ // The enterprise plugin requires Gradle 6.0 diff --git a/subprojects/performance/templates.gradle b/subprojects/performance/templates.gradle index d007a4d9903a..2d6d0c2700b7 100644 --- a/subprojects/performance/templates.gradle +++ b/subprojects/performance/templates.gradle @@ -359,9 +359,7 @@ tasks.register("largeAndroidBuild", RemoteProject) { tasks.register("santaTrackerAndroidBuild", RemoteProject) { remoteUri = 'https://github.com/gradle/santa-tracker-android.git' - // branch agp-3.6.0 - // with AGP 3.6.0-beta-04 - // without licenses plugin + // Pinned from branch agp-3.6.0 ref = '3bbbd895de38efafd0dd1789454d4e4cb72d46d5' doLast { addGoogleServicesJson(outputDirectory) diff --git a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/AbstractPluginValidationIntegrationSpec.groovy b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/AbstractPluginValidationIntegrationSpec.groovy index b559203b9423..c46a52063d14 100644 --- a/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/AbstractPluginValidationIntegrationSpec.groovy +++ b/subprojects/plugin-development/src/integTest/groovy/org/gradle/plugin/devel/tasks/AbstractPluginValidationIntegrationSpec.groovy @@ -763,7 +763,7 @@ abstract class AbstractPluginValidationIntegrationSpec extends AbstractIntegrati expect: assertValidationFailsWith( - "Type 'MyTask': property 'oldProperty' getter 'getOldProperty()' annotated with @ReplacedBy should not be also annotated with @Input.": WARNING, + "Type 'MyTask': property 'oldProperty' annotated with @ReplacedBy should not be also annotated with @Input.": WARNING, ) } diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/api/plugins/JavaLibraryDistributionIntegrationTest.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/api/plugins/JavaLibraryDistributionIntegrationTest.groovy index 139833cfb4b6..b97c30ff2414 100755 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/api/plugins/JavaLibraryDistributionIntegrationTest.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/api/plugins/JavaLibraryDistributionIntegrationTest.groovy @@ -139,7 +139,7 @@ class JavaLibraryDistributionIntegrationTest extends WellBehavedPluginTest { expect: executer.noDeprecationChecks() runAndFail 'distZip' - failure.assertHasCause "No value has been specified for property 'distributionBaseName'." + failure.assertHasCause "Cannot query the value of property 'distributionBaseName' because it has no value available." } def "compile only dependencies are not included in distribution"() { diff --git a/subprojects/plugins/src/main/java/org/gradle/api/internal/plugins/DefaultArtifactPublicationSet.java b/subprojects/plugins/src/main/java/org/gradle/api/internal/plugins/DefaultArtifactPublicationSet.java index 3f7d91319721..082d3f033b37 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/internal/plugins/DefaultArtifactPublicationSet.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/internal/plugins/DefaultArtifactPublicationSet.java @@ -19,7 +19,7 @@ import org.gradle.api.Action; import org.gradle.api.artifacts.PublishArtifact; import org.gradle.api.artifacts.PublishArtifactSet; -import org.gradle.api.internal.provider.AbstractReadOnlyProvider; +import org.gradle.api.internal.provider.AbstractMinimalProvider; import org.gradle.api.internal.provider.ChangingValue; import org.gradle.api.internal.provider.ChangingValueHandler; import org.gradle.api.internal.provider.CollectionProviderInternal; @@ -46,7 +46,7 @@ public void addCandidate(PublishArtifact artifact) { defaultArtifactProvider.addArtifact(artifact); } - private static class DefaultArtifactProvider extends AbstractReadOnlyProvider> implements CollectionProviderInternal>, ChangingValue> { + private static class DefaultArtifactProvider extends AbstractMinimalProvider> implements CollectionProviderInternal>, ChangingValue> { private Set defaultArtifacts; private Set artifacts; private PublishArtifact currentDefault; @@ -80,9 +80,8 @@ public Class> getType() { return null; } - @Nullable @Override - public Set getOrNull() { + protected Value> calculateOwnValue() { if (defaultArtifacts == null) { defaultArtifacts = Sets.newLinkedHashSet(); currentDefault = null; @@ -108,7 +107,7 @@ public Set getOrNull() { } } } - return defaultArtifacts; + return Value.of(defaultArtifacts); } void replaceCurrent(PublishArtifact artifact) { diff --git a/subprojects/smoke-test/smoke-test.gradle.kts b/subprojects/smoke-test/smoke-test.gradle.kts index 3bcf99e115cf..eeb91f92fc7b 100644 --- a/subprojects/smoke-test/smoke-test.gradle.kts +++ b/subprojects/smoke-test/smoke-test.gradle.kts @@ -110,15 +110,28 @@ plugins.withType().configureEach { } } -// TODO Copied from instant-execution.gradle.kts, we should have one place to clone this thing and clone it from there locally when needed tasks { - register("santaTracker") { - remoteUri.set("https://github.com/gradle/santa-tracker-android.git") - // From branch agp-3.6.0 + /** + * Santa Tracker git URI. + * + * Note that you can change it to `file:///path/to/your/santa-tracker-clone/.git` + * if you need to iterate quickly on changes to Santa Tracker. + */ + val santaGitUri = "https://github.com/gradle/santa-tracker-android.git" + + register("santaTrackerKotlin") { + remoteUri.set(santaGitUri) + // Pinned from branch agp-3.6.0 ref.set("3bbbd895de38efafd0dd1789454d4e4cb72d46d5") } + register("santaTrackerJava") { + remoteUri.set(santaGitUri) + // Pinned from branch agp-3.6.0-java + ref.set("174705275e434adc843e8e9b28106a5e3ffd6733") + } + register("gradleBuildCurrent") { remoteUri.set(rootDir.absolutePath) ref.set(rootProject.tasks.named("determineCommitId").flatMap { it.determinedCommitId }) diff --git a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AbstractAndroidSantaTrackerSmokeTest.groovy b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AbstractAndroidSantaTrackerSmokeTest.groovy new file mode 100644 index 000000000000..838d81bbffe2 --- /dev/null +++ b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AbstractAndroidSantaTrackerSmokeTest.groovy @@ -0,0 +1,94 @@ +/* + * Copyright 2020 the original author or authors. + * + * 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 org.gradle.smoketests + +import org.gradle.integtests.fixtures.daemon.DaemonLogsAnalyzer +import org.gradle.internal.scan.config.fixtures.GradleEnterprisePluginSettingsFixture +import org.gradle.test.fixtures.file.TestFile +import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider +import org.gradle.testkit.runner.BuildResult +import org.gradle.testkit.runner.TaskOutcome +import org.gradle.testkit.runner.internal.ToolingApiGradleExecutor +import org.junit.Rule + + +class AbstractAndroidSantaTrackerSmokeTest extends AbstractSmokeTest { + + protected static final List TESTED_AGP_VERSIONS = AGP_VERSIONS.getLatestsFromMinorPlusNightly("3.6") + + @Rule + TestNameTestDirectoryProvider temporaryFolder + TestFile homeDir + + def setup() { + homeDir = temporaryFolder.createDir("test-kit-home") + } + + def cleanup() { + // The daemons started by test kit need to be killed, so no locked files are left behind. + DaemonLogsAnalyzer.newAnalyzer(homeDir.file(ToolingApiGradleExecutor.TEST_KIT_DAEMON_DIR_NAME)).killAll() + } + + protected void setupCopyOfSantaTracker(TestFile targetDir, String flavour, String agpVersion = null) { + copyRemoteProject("santaTracker${flavour.capitalize()}", targetDir) + GradleEnterprisePluginSettingsFixture.applyEnterprisePlugin(targetDir.file("settings.gradle")) + if (agpVersion != null) { + def buildFile = targetDir.file("build.gradle") + buildFile.text = AGP_VERSIONS.replaceAgpVersion(buildFile.text, agpVersion) + } + } + + protected BuildResult buildLocation(File projectDir, String agpVersion) { + def runner = runner("assembleDebug") + .withProjectDir(projectDir) + .withTestKitDir(homeDir) + .forwardOutput() + if (AGP_VERSIONS.isAgpNightly(agpVersion)) { + def init = AGP_VERSIONS.createAgpNightlyRepositoryInitScript() + runner.withArguments([runner.arguments, ['-I', init.canonicalPath]].flatten()) + } + runner.build() + } + + protected static boolean verify(BuildResult result, Map outcomes) { + println "> Expecting ${outcomes.size()} tasks with outcomes:" + outcomes.values().groupBy { it }.sort().forEach { outcome, instances -> println "> - $outcome: ${instances.size()}" } + + def outcomesWithMatchingTasks = outcomes.findAll { result.task(it.key) } + def hasMatchingTasks = outcomesWithMatchingTasks.size() == outcomes.size() && outcomesWithMatchingTasks.size() == result.tasks.size() + if (!hasMatchingTasks) { + println "> Tasks missing: " + (outcomes.findAll { !outcomesWithMatchingTasks.keySet().contains(it.key) }) + println "> Tasks in surplus: " + (result.tasks.findAll { !outcomesWithMatchingTasks.keySet().contains(it.path) }) + println "> Updated definitions:" + result.tasks + .toSorted { a, b -> a.path <=> b.path } + .forEach { task -> + println "'${task.path}': ${task.outcome}," + } + } + + boolean allOutcomesMatched = true + outcomesWithMatchingTasks.each { taskName, expectedOutcome -> + def taskOutcome = result.task(taskName)?.outcome + if (taskOutcome != expectedOutcome) { + println "> Task '$taskName' was $taskOutcome but should have been $expectedOutcome" + allOutcomesMatched = false + } + } + return hasMatchingTasks && allOutcomesMatched + } +} diff --git a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AbstractSmokeTest.groovy b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AbstractSmokeTest.groovy index df7f727a97af..9cf8ae81cb6f 100644 --- a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AbstractSmokeTest.groovy +++ b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AbstractSmokeTest.groovy @@ -18,11 +18,15 @@ package org.gradle.smoketests import org.apache.commons.io.FileUtils import org.gradle.cache.internal.DefaultGeneratedGradleJarCache +import org.gradle.integtests.fixtures.instantexecution.InstantExecutionBuildOperationsFixture +import org.gradle.integtests.fixtures.BuildOperationTreeFixture import org.gradle.integtests.fixtures.RepoScriptBlockUtil import org.gradle.integtests.fixtures.executer.GradleContextualExecuter import org.gradle.integtests.fixtures.executer.InstantExecutionGradleExecuter import org.gradle.integtests.fixtures.executer.IntegrationTestBuildContext +import org.gradle.integtests.fixtures.versions.AndroidGradlePluginVersions import org.gradle.internal.featurelifecycle.LoggingDeprecatedFeatureHandler +import org.gradle.internal.operations.trace.BuildOperationTrace import org.gradle.test.fixtures.file.TestFile import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.GradleRunner @@ -37,6 +41,9 @@ import static org.gradle.test.fixtures.server.http.MavenHttpPluginRepository.PLU abstract class AbstractSmokeTest extends Specification { + protected static final AndroidGradlePluginVersions AGP_VERSIONS = new AndroidGradlePluginVersions() + protected static final String AGP_3_ITERATION_MATCHER = ".*agp=3\\..*" + static class TestedVersions { /** * May also need to update @@ -82,7 +89,7 @@ abstract class AbstractSmokeTest extends Specification { // https://developer.android.com/studio/releases/build-tools static androidTools = "29.0.2" // https://developer.android.com/studio/releases/gradle-plugin - static androidGradle = Versions.of("3.4.2", "3.5.3", "3.6.0-rc01", "4.0.0-alpha06") + static androidGradle = Versions.of(*AGP_VERSIONS.latestsPlusNightly) // https://search.maven.org/search?q=g:org.jetbrains.kotlin%20AND%20a:kotlin-project&core=gav static kotlin = Versions.of('1.3.21', '1.3.31', '1.3.41', '1.3.50', '1.3.61') @@ -185,10 +192,11 @@ abstract class AbstractSmokeTest extends Specification { ) } - private static List buildContextParameters() { + private List buildContextParameters() { List parameters = [] if (GradleContextualExecuter.isInstant()) { parameters += InstantExecutionGradleExecuter.INSTANT_EXECUTION_ARGS + parameters += ["-D${BuildOperationTrace.SYSPROP}=${buildOperationTracePath()}".toString()] } def generatedApiJarCacheDir = IntegrationTestBuildContext.INSTANCE.gradleGeneratedApiJarCacheDir if (generatedApiJarCacheDir == null) { @@ -214,11 +222,40 @@ abstract class AbstractSmokeTest extends Specification { ] } + protected void assertInstantExecutionStateStored() { + if (GradleContextualExecuter.isInstant()) { + newInstantExecutionBuildOperationsFixture().assertStateStored() + } + } + + protected void assertInstantExecutionStateLoaded() { + if (GradleContextualExecuter.isInstant()) { + newInstantExecutionBuildOperationsFixture().assertStateLoaded() + } + } + + private InstantExecutionBuildOperationsFixture newInstantExecutionBuildOperationsFixture() { + return new InstantExecutionBuildOperationsFixture(new BuildOperationTreeFixture(BuildOperationTrace.read(buildOperationTracePath()))) + } + + private String buildOperationTracePath() { + return file("operations").absolutePath + } + protected void useSample(String sampleDirectory) { def smokeTestDirectory = new File(this.getClass().getResource(sampleDirectory).toURI()) FileUtils.copyDirectory(smokeTestDirectory, testProjectDir.root) } + protected GradleRunner useAgpVersion(String agpVersion, GradleRunner runner) { + def extraArgs = [AGP_VERSIONS.OVERRIDE_VERSION_CHECK] + if (AGP_VERSIONS.isAgpNightly(agpVersion)) { + def init = AGP_VERSIONS.createAgpNightlyRepositoryInitScript() + extraArgs += ["-I", init.canonicalPath] + } + return runner.withArguments([runner.arguments, extraArgs].flatten()) + } + protected void replaceVariablesInBuildFile(Map binding) { replaceVariablesInFile(binding, buildFile) } diff --git a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AndroidPluginsSmokeTest.groovy b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AndroidPluginsSmokeTest.groovy index 8dba9e7af439..a0fc347bca33 100644 --- a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AndroidPluginsSmokeTest.groovy +++ b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AndroidPluginsSmokeTest.groovy @@ -16,9 +16,11 @@ package org.gradle.smoketests -import org.gradle.integtests.fixtures.ToBeFixedForInstantExecution +import org.gradle.integtests.fixtures.UnsupportedWithInstantExecution import org.gradle.integtests.fixtures.android.AndroidHome import org.gradle.testkit.runner.TaskOutcome +import org.gradle.util.Requires +import org.gradle.util.TestPrecondition import org.gradle.util.VersionNumber import spock.lang.Unroll @@ -30,9 +32,9 @@ import spock.lang.Unroll * https://androidstudio.googleblog.com/ * */ +@Requires(TestPrecondition.JDK11_OR_EARLIER) class AndroidPluginsSmokeTest extends AbstractSmokeTest { - public static final String JAVA_COMPILE_DEPRECATION_MESSAGE = "Extending the JavaCompile task has been deprecated. This is scheduled to be removed in Gradle 7.0. Configure the task instead." def setup() { @@ -40,78 +42,90 @@ class AndroidPluginsSmokeTest extends AbstractSmokeTest { } @Unroll - @ToBeFixedForInstantExecution - def "android application plugin #pluginVersion"(String pluginVersion) { + @UnsupportedWithInstantExecution(iterationMatchers = AGP_3_ITERATION_MATCHER) + def "android library and application APK assembly (agp=#agpVersion, ide=#ide)"( + String agpVersion, boolean ide + ) { + given: + def abiChange = androidLibraryAndApplicationBuild(agpVersion) - def basedir = '.' + and: + def runner = useAgpVersion(agpVersion, runner( + 'assembleDebug', + "-Pandroid.injected.invoked.from.ide=$ide" + )) - def packageName = 'org.gradle.android.example' - def activity = 'MyActivity' - writeActivity(basedir, packageName, activity) + when: 'first build' + def result = runner.build() - file("${basedir}/src/main/res/values/strings.xml") << ''' - - Android Gradle - '''.stripIndent() + then: + result.task(':app:compileDebugJavaWithJavac').outcome == TaskOutcome.SUCCESS + result.task(':library:assembleDebug').outcome == TaskOutcome.SUCCESS + result.task(':app:assembleDebug').outcome == TaskOutcome.SUCCESS + and: + def agpBaseVersion = VersionNumber.parse(agpVersion).baseVersion + def threeDotSixBaseVersion = VersionNumber.parse("3.6.0").baseVersion + if (agpBaseVersion < threeDotSixBaseVersion) { + assert result.output.contains(JAVA_COMPILE_DEPRECATION_MESSAGE) + } else { + assert !result.output.contains(JAVA_COMPILE_DEPRECATION_MESSAGE) + } + if (agpBaseVersion >= threeDotSixBaseVersion) { + expectNoDeprecationWarnings(result) + } - file('src/main/AndroidManifest.xml') << """ - + and: + assertInstantExecutionStateStored() - - - - - - - - + when: 'up-to-date build' + result = runner.build() - """.stripIndent() + then: + result.task(':app:compileDebugJavaWithJavac').outcome == TaskOutcome.UP_TO_DATE + result.task(':library:assembleDebug').outcome == TaskOutcome.UP_TO_DATE + result.task(':app:assembleDebug').outcome == TaskOutcome.UP_TO_DATE - buildFile << buildscript(pluginVersion) << """ - apply plugin: 'com.android.application' + and: + assertInstantExecutionStateLoaded() - ${jcenterRepository()} - ${googleRepository()} + when: 'abi change on library' + abiChange.run() + result = runner.build() - android.defaultConfig.applicationId "org.gradle.android.myapplication" - """.stripIndent() << androidPluginConfiguration() << activityDependency() + then: 'dependent sources are recompiled' + result.task(':library:compileDebugJavaWithJavac').outcome == TaskOutcome.SUCCESS + result.task(':app:compileDebugJavaWithJavac').outcome == TaskOutcome.SUCCESS + result.task(':library:assembleDebug').outcome == TaskOutcome.SUCCESS + result.task(':app:assembleDebug').outcome == TaskOutcome.SUCCESS - when: - def result = runner( - 'androidDependencies', - 'build', - 'connectedAndroidTest', - '-x', 'lint').build() + and: + assertInstantExecutionStateLoaded() + + when: 'clean re-build' + useAgpVersion(agpVersion, this.runner('clean')).build() + result = runner.build() then: - def pluginBaseVersion = VersionNumber.parse(pluginVersion).baseVersion - def threeDotSixBaseVersion = VersionNumber.parse("3.6.0").baseVersion - if (pluginBaseVersion < threeDotSixBaseVersion) { - assert result.output.contains(JAVA_COMPILE_DEPRECATION_MESSAGE) - } else { - assert !result.output.contains(JAVA_COMPILE_DEPRECATION_MESSAGE) - } - result.task(':assemble').outcome == TaskOutcome.SUCCESS - result.task(':compileReleaseJavaWithJavac').outcome == TaskOutcome.SUCCESS + result.task(':app:compileDebugJavaWithJavac').outcome == TaskOutcome.SUCCESS + result.task(':library:assembleDebug').outcome == TaskOutcome.SUCCESS + result.task(':app:assembleDebug').outcome == TaskOutcome.SUCCESS - if (pluginBaseVersion >= threeDotSixBaseVersion) { - expectNoDeprecationWarnings(result) - } + and: + assertInstantExecutionStateLoaded() where: - pluginVersion << TestedVersions.androidGradle + [agpVersion, ide] << [ + TestedVersions.androidGradle.toList(), + [false, true] + ].combinations() } - @Unroll - @ToBeFixedForInstantExecution - def "android library plugin #pluginVersion"(String pluginVersion) { - given: + /** + * @return ABI change runnable + */ + private Runnable androidLibraryAndApplicationBuild(String agpVersion) { def app = 'app' def appPackage = 'org.gradle.android.example.app' @@ -163,7 +177,7 @@ class AndroidPluginsSmokeTest extends AbstractSmokeTest { include ':${library}' """ - file('build.gradle') << buildscript(pluginVersion) << """ + file('build.gradle') << buildscript(agpVersion) << """ subprojects { ${jcenterRepository()} ${googleRepository()} @@ -191,28 +205,9 @@ class AndroidPluginsSmokeTest extends AbstractSmokeTest { libraryBuildFile << androidPluginConfiguration() libraryBuildFile << activityDependency() - when: - def result = runner('build', '-x', 'lint').build() - - then: - result.task(':app:assemble').outcome == TaskOutcome.SUCCESS - result.task(':library:assemble').outcome == TaskOutcome.SUCCESS - result.task(':app:compileReleaseJavaWithJavac').outcome == TaskOutcome.SUCCESS - - if (pluginVersion == TestedVersions.androidGradle.latest()) { - expectNoDeprecationWarnings(result) + return { + writeActivity(library, libPackage, libraryActivity, true) } - - when: 'abi change on library' - writeActivity(library, libPackage, libraryActivity, true) - result = runner('build', '-x', 'lint').build() - - then: 'dependent sources are recompiled' - result.task(':library:compileReleaseJavaWithJavac').outcome == TaskOutcome.SUCCESS - result.task(':app:compileReleaseJavaWithJavac').outcome == TaskOutcome.SUCCESS - - where: - pluginVersion << TestedVersions.androidGradle } private static String activityDependency() { @@ -233,8 +228,6 @@ class AndroidPluginsSmokeTest extends AbstractSmokeTest { classpath 'com.android.tools.build:gradle:${pluginVersion}' } } - - System.properties['com.android.build.gradle.overrideVersionCheck'] = 'true' """.stripIndent() } diff --git a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AndroidSantaTrackerJavaCachingSmokeTest.groovy b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AndroidSantaTrackerJavaCachingSmokeTest.groovy new file mode 100644 index 000000000000..82916f75d48d --- /dev/null +++ b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AndroidSantaTrackerJavaCachingSmokeTest.groovy @@ -0,0 +1,596 @@ +/* + * Copyright 2020 the original author or authors. + * + * 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 org.gradle.smoketests + +import org.gradle.integtests.fixtures.UnsupportedWithInstantExecution +import org.gradle.testkit.runner.BuildResult +import org.gradle.util.Requires +import org.gradle.util.TestPrecondition +import spock.lang.Unroll + +import static org.gradle.testkit.runner.TaskOutcome.FROM_CACHE +import static org.gradle.testkit.runner.TaskOutcome.NO_SOURCE +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS +import static org.gradle.testkit.runner.TaskOutcome.UP_TO_DATE + + +@Requires(TestPrecondition.JDK11_OR_EARLIER) +class AndroidSantaTrackerJavaCachingSmokeTest extends AbstractAndroidSantaTrackerSmokeTest { + + @Unroll + @UnsupportedWithInstantExecution(iterationMatchers = AGP_3_ITERATION_MATCHER) + def "can cache Santa Tracker Java Android application (agp=#agpVersion)"() { + + given: + def originalDir = temporaryFolder.createDir("original") + def relocatedDir = temporaryFolder.createDir("relocated") + + and: + setupCopyOfSantaTracker(originalDir, 'Java', agpVersion) + setupCopyOfSantaTracker(relocatedDir, 'Java', agpVersion) + + when: + buildLocation(originalDir, agpVersion) + + then: + assertInstantExecutionStateStored() + + when: + BuildResult relocatedResult = buildLocation(relocatedDir, agpVersion) + + then: + assertInstantExecutionStateStored() + + and: + def expectedResults = agpVersion.startsWith('3.6') + ? EXPECTED_RESULTS_3_6 + : EXPECTED_RESULTS + verify(relocatedResult, expectedResults) + + where: + agpVersion << TESTED_AGP_VERSIONS + } + + private static final EXPECTED_RESULTS = [ + ':common:assembleDebug': SUCCESS, + ':common:bundleDebugAar': SUCCESS, + ':common:bundleLibCompileToJarDebug': FROM_CACHE, + ':common:bundleLibResDebug': NO_SOURCE, + ':common:bundleLibRuntimeToJarDebug': FROM_CACHE, + ':common:compileDebugAidl': NO_SOURCE, + ':common:compileDebugJavaWithJavac': FROM_CACHE, + ':common:compileDebugLibraryResources': SUCCESS, + ':common:compileDebugRenderscript': NO_SOURCE, + ':common:compileDebugShaders': NO_SOURCE, + ':common:compileDebugSources': UP_TO_DATE, + ':common:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':common:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':common:extractDebugAnnotations': FROM_CACHE, + ':common:extractDeepLinksDebug': FROM_CACHE, + ':common:generateDebugAssets': UP_TO_DATE, + ':common:generateDebugBuildConfig': FROM_CACHE, + ':common:generateDebugRFile': FROM_CACHE, + ':common:generateDebugResValues': FROM_CACHE, + ':common:generateDebugResources': UP_TO_DATE, + ':common:javaPreCompileDebug': FROM_CACHE, + ':common:mergeDebugConsumerProguardFiles': FROM_CACHE, + ':common:mergeDebugGeneratedProguardFiles': FROM_CACHE, + ':common:mergeDebugJavaResource': FROM_CACHE, + ':common:mergeDebugJniLibFolders': FROM_CACHE, + ':common:mergeDebugNativeLibs': FROM_CACHE, + ':common:mergeDebugShaders': FROM_CACHE, + ':common:packageDebugAssets': FROM_CACHE, + ':common:packageDebugRenderscript': NO_SOURCE, + ':common:packageDebugResources': FROM_CACHE, + ':common:parseDebugLocalResources': FROM_CACHE, + ':common:preBuild': UP_TO_DATE, + ':common:preDebugBuild': UP_TO_DATE, + ':common:prepareLintJarForPublish': SUCCESS, + ':common:processDebugJavaRes': NO_SOURCE, + ':common:processDebugManifest': FROM_CACHE, + ':common:stripDebugDebugSymbols': NO_SOURCE, + ':common:syncDebugLibJars': FROM_CACHE, + ':dasherdancer:assembleDebug': SUCCESS, + ':dasherdancer:bundleDebugAar': SUCCESS, + ':dasherdancer:bundleLibCompileToJarDebug': FROM_CACHE, + ':dasherdancer:bundleLibResDebug': NO_SOURCE, + ':dasherdancer:bundleLibRuntimeToJarDebug': FROM_CACHE, + ':dasherdancer:compileDebugAidl': NO_SOURCE, + ':dasherdancer:compileDebugJavaWithJavac': FROM_CACHE, + ':dasherdancer:compileDebugLibraryResources': SUCCESS, + ':dasherdancer:compileDebugRenderscript': NO_SOURCE, + ':dasherdancer:compileDebugShaders': NO_SOURCE, + ':dasherdancer:compileDebugSources': UP_TO_DATE, + ':dasherdancer:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':dasherdancer:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':dasherdancer:extractDebugAnnotations': FROM_CACHE, + ':dasherdancer:extractDeepLinksDebug': FROM_CACHE, + ':dasherdancer:generateDebugAssets': UP_TO_DATE, + ':dasherdancer:generateDebugBuildConfig': FROM_CACHE, + ':dasherdancer:generateDebugRFile': FROM_CACHE, + ':dasherdancer:generateDebugResValues': FROM_CACHE, + ':dasherdancer:generateDebugResources': UP_TO_DATE, + ':dasherdancer:javaPreCompileDebug': FROM_CACHE, + ':dasherdancer:mergeDebugConsumerProguardFiles': FROM_CACHE, + ':dasherdancer:mergeDebugGeneratedProguardFiles': FROM_CACHE, + ':dasherdancer:mergeDebugJavaResource': FROM_CACHE, + ':dasherdancer:mergeDebugJniLibFolders': FROM_CACHE, + ':dasherdancer:mergeDebugNativeLibs': FROM_CACHE, + ':dasherdancer:mergeDebugShaders': FROM_CACHE, + ':dasherdancer:packageDebugAssets': FROM_CACHE, + ':dasherdancer:packageDebugRenderscript': NO_SOURCE, + ':dasherdancer:packageDebugResources': FROM_CACHE, + ':dasherdancer:parseDebugLocalResources': FROM_CACHE, + ':dasherdancer:preBuild': UP_TO_DATE, + ':dasherdancer:preDebugBuild': UP_TO_DATE, + ':dasherdancer:prepareLintJarForPublish': SUCCESS, + ':dasherdancer:processDebugJavaRes': NO_SOURCE, + ':dasherdancer:processDebugManifest': FROM_CACHE, + ':dasherdancer:stripDebugDebugSymbols': NO_SOURCE, + ':dasherdancer:syncDebugLibJars': FROM_CACHE, + ':doodles:assembleDebug': SUCCESS, + ':doodles:bundleDebugAar': SUCCESS, + ':doodles:bundleLibCompileToJarDebug': FROM_CACHE, + ':doodles:bundleLibResDebug': NO_SOURCE, + ':doodles:bundleLibRuntimeToJarDebug': FROM_CACHE, + ':doodles:compileDebugAidl': NO_SOURCE, + ':doodles:compileDebugJavaWithJavac': FROM_CACHE, + ':doodles:compileDebugLibraryResources': SUCCESS, + ':doodles:compileDebugRenderscript': NO_SOURCE, + ':doodles:compileDebugShaders': NO_SOURCE, + ':doodles:compileDebugSources': UP_TO_DATE, + ':doodles:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':doodles:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':doodles:extractDebugAnnotations': FROM_CACHE, + ':doodles:extractDeepLinksDebug': FROM_CACHE, + ':doodles:generateDebugAssets': UP_TO_DATE, + ':doodles:generateDebugBuildConfig': FROM_CACHE, + ':doodles:generateDebugRFile': FROM_CACHE, + ':doodles:generateDebugResValues': FROM_CACHE, + ':doodles:generateDebugResources': UP_TO_DATE, + ':doodles:javaPreCompileDebug': FROM_CACHE, + ':doodles:mergeDebugConsumerProguardFiles': FROM_CACHE, + ':doodles:mergeDebugGeneratedProguardFiles': FROM_CACHE, + ':doodles:mergeDebugJavaResource': FROM_CACHE, + ':doodles:mergeDebugJniLibFolders': FROM_CACHE, + ':doodles:mergeDebugNativeLibs': FROM_CACHE, + ':doodles:mergeDebugShaders': FROM_CACHE, + ':doodles:packageDebugAssets': FROM_CACHE, + ':doodles:packageDebugRenderscript': NO_SOURCE, + ':doodles:packageDebugResources': FROM_CACHE, + ':doodles:parseDebugLocalResources': FROM_CACHE, + ':doodles:preBuild': UP_TO_DATE, + ':doodles:preDebugBuild': UP_TO_DATE, + ':doodles:prepareLintJarForPublish': SUCCESS, + ':doodles:processDebugJavaRes': NO_SOURCE, + ':doodles:processDebugManifest': FROM_CACHE, + ':doodles:stripDebugDebugSymbols': NO_SOURCE, + ':doodles:syncDebugLibJars': FROM_CACHE, + ':presentquest:assembleDebug': SUCCESS, + ':presentquest:bundleDebugAar': SUCCESS, + ':presentquest:bundleLibCompileToJarDebug': FROM_CACHE, + ':presentquest:bundleLibResDebug': NO_SOURCE, + ':presentquest:bundleLibRuntimeToJarDebug': FROM_CACHE, + ':presentquest:compileDebugAidl': NO_SOURCE, + ':presentquest:compileDebugJavaWithJavac': FROM_CACHE, + ':presentquest:compileDebugLibraryResources': SUCCESS, + ':presentquest:compileDebugRenderscript': NO_SOURCE, + ':presentquest:compileDebugShaders': NO_SOURCE, + ':presentquest:compileDebugSources': UP_TO_DATE, + ':presentquest:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':presentquest:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':presentquest:extractDebugAnnotations': FROM_CACHE, + ':presentquest:extractDeepLinksDebug': FROM_CACHE, + ':presentquest:generateDebugAssets': UP_TO_DATE, + ':presentquest:generateDebugBuildConfig': FROM_CACHE, + ':presentquest:generateDebugRFile': FROM_CACHE, + ':presentquest:generateDebugResValues': FROM_CACHE, + ':presentquest:generateDebugResources': UP_TO_DATE, + ':presentquest:javaPreCompileDebug': FROM_CACHE, + ':presentquest:mergeDebugConsumerProguardFiles': FROM_CACHE, + ':presentquest:mergeDebugGeneratedProguardFiles': FROM_CACHE, + ':presentquest:mergeDebugJavaResource': FROM_CACHE, + ':presentquest:mergeDebugJniLibFolders': FROM_CACHE, + ':presentquest:mergeDebugNativeLibs': FROM_CACHE, + ':presentquest:mergeDebugShaders': FROM_CACHE, + ':presentquest:packageDebugAssets': FROM_CACHE, + ':presentquest:packageDebugRenderscript': NO_SOURCE, + ':presentquest:packageDebugResources': FROM_CACHE, + ':presentquest:parseDebugLocalResources': FROM_CACHE, + ':presentquest:preBuild': UP_TO_DATE, + ':presentquest:preDebugBuild': UP_TO_DATE, + ':presentquest:prepareLintJarForPublish': SUCCESS, + ':presentquest:processDebugJavaRes': NO_SOURCE, + ':presentquest:processDebugManifest': FROM_CACHE, + ':presentquest:stripDebugDebugSymbols': NO_SOURCE, + ':presentquest:syncDebugLibJars': FROM_CACHE, + ':rocketsleigh:assembleDebug': SUCCESS, + ':rocketsleigh:bundleDebugAar': SUCCESS, + ':rocketsleigh:bundleLibCompileToJarDebug': FROM_CACHE, + ':rocketsleigh:bundleLibResDebug': NO_SOURCE, + ':rocketsleigh:bundleLibRuntimeToJarDebug': FROM_CACHE, + ':rocketsleigh:compileDebugAidl': NO_SOURCE, + ':rocketsleigh:compileDebugJavaWithJavac': FROM_CACHE, + ':rocketsleigh:compileDebugLibraryResources': SUCCESS, + ':rocketsleigh:compileDebugRenderscript': NO_SOURCE, + ':rocketsleigh:compileDebugShaders': NO_SOURCE, + ':rocketsleigh:compileDebugSources': UP_TO_DATE, + ':rocketsleigh:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':rocketsleigh:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':rocketsleigh:extractDebugAnnotations': FROM_CACHE, + ':rocketsleigh:extractDeepLinksDebug': FROM_CACHE, + ':rocketsleigh:generateDebugAssets': UP_TO_DATE, + ':rocketsleigh:generateDebugBuildConfig': FROM_CACHE, + ':rocketsleigh:generateDebugRFile': FROM_CACHE, + ':rocketsleigh:generateDebugResValues': FROM_CACHE, + ':rocketsleigh:generateDebugResources': UP_TO_DATE, + ':rocketsleigh:javaPreCompileDebug': FROM_CACHE, + ':rocketsleigh:mergeDebugConsumerProguardFiles': FROM_CACHE, + ':rocketsleigh:mergeDebugGeneratedProguardFiles': FROM_CACHE, + ':rocketsleigh:mergeDebugJavaResource': FROM_CACHE, + ':rocketsleigh:mergeDebugJniLibFolders': FROM_CACHE, + ':rocketsleigh:mergeDebugNativeLibs': FROM_CACHE, + ':rocketsleigh:mergeDebugShaders': FROM_CACHE, + ':rocketsleigh:packageDebugAssets': FROM_CACHE, + ':rocketsleigh:packageDebugRenderscript': NO_SOURCE, + ':rocketsleigh:packageDebugResources': FROM_CACHE, + ':rocketsleigh:parseDebugLocalResources': FROM_CACHE, + ':rocketsleigh:preBuild': UP_TO_DATE, + ':rocketsleigh:preDebugBuild': UP_TO_DATE, + ':rocketsleigh:prepareLintJarForPublish': SUCCESS, + ':rocketsleigh:processDebugJavaRes': NO_SOURCE, + ':rocketsleigh:processDebugManifest': FROM_CACHE, + ':rocketsleigh:stripDebugDebugSymbols': NO_SOURCE, + ':rocketsleigh:syncDebugLibJars': FROM_CACHE, + ':santa-tracker:assembleDebug': SUCCESS, + ':santa-tracker:assembleDevelopmentDebug': SUCCESS, + ':santa-tracker:checkDevelopmentDebugDuplicateClasses': FROM_CACHE, + ':santa-tracker:compileDevelopmentDebugAidl': NO_SOURCE, + ':santa-tracker:compileDevelopmentDebugJavaWithJavac': FROM_CACHE, + ':santa-tracker:compileDevelopmentDebugRenderscript': NO_SOURCE, + ':santa-tracker:compileDevelopmentDebugShaders': NO_SOURCE, + ':santa-tracker:compileDevelopmentDebugSources': UP_TO_DATE, + ':santa-tracker:createDevelopmentDebugCompatibleScreenManifests': FROM_CACHE, + ':santa-tracker:dexBuilderDevelopmentDebug': FROM_CACHE, + ':santa-tracker:extractDeepLinksDevelopmentDebug': FROM_CACHE, + ':santa-tracker:generateDevelopmentDebugAssets': UP_TO_DATE, + ':santa-tracker:generateDevelopmentDebugBuildConfig': FROM_CACHE, + ':santa-tracker:generateDevelopmentDebugResValues': FROM_CACHE, + ':santa-tracker:generateDevelopmentDebugResources': UP_TO_DATE, + ':santa-tracker:javaPreCompileDevelopmentDebug': FROM_CACHE, + ':santa-tracker:mergeDevelopmentDebugAssets': FROM_CACHE, + ':santa-tracker:mergeDevelopmentDebugJavaResource': FROM_CACHE, + ':santa-tracker:mergeDevelopmentDebugJniLibFolders': FROM_CACHE, + ':santa-tracker:mergeDevelopmentDebugNativeLibs': FROM_CACHE, + ':santa-tracker:mergeDevelopmentDebugResources': SUCCESS, + ':santa-tracker:mergeDevelopmentDebugShaders': FROM_CACHE, + ':santa-tracker:mergeExtDexDevelopmentDebug': FROM_CACHE, + ':santa-tracker:mergeLibDexDevelopmentDebug': FROM_CACHE, + ':santa-tracker:mergeProjectDexDevelopmentDebug': FROM_CACHE, + ':santa-tracker:packageDevelopmentDebug': SUCCESS, + ':santa-tracker:preBuild': UP_TO_DATE, + ':santa-tracker:preDevelopmentDebugBuild': UP_TO_DATE, + ':santa-tracker:processDevelopmentDebugJavaRes': NO_SOURCE, + ':santa-tracker:processDevelopmentDebugManifest': FROM_CACHE, + ':santa-tracker:processDevelopmentDebugResources': SUCCESS, + ':santa-tracker:stripDevelopmentDebugDebugSymbols': NO_SOURCE, + ':santa-tracker:validateSigningDevelopmentDebug': FROM_CACHE, + ':village:assembleDebug': SUCCESS, + ':village:bundleDebugAar': SUCCESS, + ':village:bundleLibCompileToJarDebug': FROM_CACHE, + ':village:bundleLibResDebug': NO_SOURCE, + ':village:bundleLibRuntimeToJarDebug': FROM_CACHE, + ':village:compileDebugAidl': NO_SOURCE, + ':village:compileDebugJavaWithJavac': FROM_CACHE, + ':village:compileDebugLibraryResources': SUCCESS, + ':village:compileDebugRenderscript': NO_SOURCE, + ':village:compileDebugShaders': NO_SOURCE, + ':village:compileDebugSources': UP_TO_DATE, + ':village:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':village:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':village:extractDebugAnnotations': FROM_CACHE, + ':village:extractDeepLinksDebug': FROM_CACHE, + ':village:generateDebugAssets': UP_TO_DATE, + ':village:generateDebugBuildConfig': FROM_CACHE, + ':village:generateDebugRFile': FROM_CACHE, + ':village:generateDebugResValues': FROM_CACHE, + ':village:generateDebugResources': UP_TO_DATE, + ':village:javaPreCompileDebug': FROM_CACHE, + ':village:mergeDebugConsumerProguardFiles': FROM_CACHE, + ':village:mergeDebugGeneratedProguardFiles': FROM_CACHE, + ':village:mergeDebugJavaResource': FROM_CACHE, + ':village:mergeDebugJniLibFolders': FROM_CACHE, + ':village:mergeDebugNativeLibs': FROM_CACHE, + ':village:mergeDebugShaders': FROM_CACHE, + ':village:packageDebugAssets': FROM_CACHE, + ':village:packageDebugRenderscript': NO_SOURCE, + ':village:packageDebugResources': FROM_CACHE, + ':village:parseDebugLocalResources': FROM_CACHE, + ':village:preBuild': UP_TO_DATE, + ':village:preDebugBuild': UP_TO_DATE, + ':village:prepareLintJarForPublish': SUCCESS, + ':village:processDebugJavaRes': NO_SOURCE, + ':village:processDebugManifest': FROM_CACHE, + ':village:stripDebugDebugSymbols': NO_SOURCE, + ':village:syncDebugLibJars': FROM_CACHE, + ] + + private static final EXPECTED_RESULTS_3_6 = [ + ':common:assembleDebug': SUCCESS, + ':common:bundleDebugAar': SUCCESS, + ':common:bundleLibCompileDebug': SUCCESS, + ':common:bundleLibResDebug': SUCCESS, + ':common:bundleLibRuntimeDebug': SUCCESS, + ':common:compileDebugAidl': NO_SOURCE, + ':common:compileDebugJavaWithJavac': FROM_CACHE, + ':common:compileDebugLibraryResources': FROM_CACHE, + ':common:compileDebugRenderscript': NO_SOURCE, + ':common:compileDebugShaders': FROM_CACHE, + ':common:compileDebugSources': UP_TO_DATE, + ':common:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':common:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':common:extractDebugAnnotations': FROM_CACHE, + ':common:extractDeepLinksDebug': FROM_CACHE, + ':common:generateDebugAssets': UP_TO_DATE, + ':common:generateDebugBuildConfig': FROM_CACHE, + ':common:generateDebugRFile': FROM_CACHE, + ':common:generateDebugResValues': FROM_CACHE, + ':common:generateDebugResources': UP_TO_DATE, + ':common:javaPreCompileDebug': FROM_CACHE, + ':common:mergeDebugConsumerProguardFiles': SUCCESS, + ':common:mergeDebugGeneratedProguardFiles': SUCCESS, + ':common:mergeDebugJavaResource': FROM_CACHE, + ':common:mergeDebugJniLibFolders': FROM_CACHE, + ':common:mergeDebugNativeLibs': FROM_CACHE, + ':common:mergeDebugShaders': FROM_CACHE, + ':common:packageDebugAssets': FROM_CACHE, + ':common:packageDebugRenderscript': NO_SOURCE, + ':common:packageDebugResources': FROM_CACHE, + ':common:parseDebugLocalResources': FROM_CACHE, + ':common:preBuild': UP_TO_DATE, + ':common:preDebugBuild': UP_TO_DATE, + ':common:prepareLintJarForPublish': SUCCESS, + ':common:processDebugJavaRes': NO_SOURCE, + ':common:processDebugManifest': FROM_CACHE, + ':common:stripDebugDebugSymbols': FROM_CACHE, + ':common:syncDebugLibJars': FROM_CACHE, + ':dasherdancer:assembleDebug': SUCCESS, + ':dasherdancer:bundleDebugAar': SUCCESS, + ':dasherdancer:bundleLibCompileDebug': SUCCESS, + ':dasherdancer:bundleLibResDebug': SUCCESS, + ':dasherdancer:bundleLibRuntimeDebug': SUCCESS, + ':dasherdancer:compileDebugAidl': NO_SOURCE, + ':dasherdancer:compileDebugJavaWithJavac': FROM_CACHE, + ':dasherdancer:compileDebugLibraryResources': FROM_CACHE, + ':dasherdancer:compileDebugRenderscript': NO_SOURCE, + ':dasherdancer:compileDebugShaders': FROM_CACHE, + ':dasherdancer:compileDebugSources': UP_TO_DATE, + ':dasherdancer:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':dasherdancer:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':dasherdancer:extractDebugAnnotations': FROM_CACHE, + ':dasherdancer:extractDeepLinksDebug': FROM_CACHE, + ':dasherdancer:generateDebugAssets': UP_TO_DATE, + ':dasherdancer:generateDebugBuildConfig': FROM_CACHE, + ':dasherdancer:generateDebugRFile': FROM_CACHE, + ':dasherdancer:generateDebugResValues': FROM_CACHE, + ':dasherdancer:generateDebugResources': UP_TO_DATE, + ':dasherdancer:javaPreCompileDebug': FROM_CACHE, + ':dasherdancer:mergeDebugConsumerProguardFiles': SUCCESS, + ':dasherdancer:mergeDebugGeneratedProguardFiles': SUCCESS, + ':dasherdancer:mergeDebugJavaResource': FROM_CACHE, + ':dasherdancer:mergeDebugJniLibFolders': FROM_CACHE, + ':dasherdancer:mergeDebugNativeLibs': FROM_CACHE, + ':dasherdancer:mergeDebugShaders': FROM_CACHE, + ':dasherdancer:packageDebugAssets': FROM_CACHE, + ':dasherdancer:packageDebugRenderscript': NO_SOURCE, + ':dasherdancer:packageDebugResources': FROM_CACHE, + ':dasherdancer:parseDebugLocalResources': FROM_CACHE, + ':dasherdancer:preBuild': UP_TO_DATE, + ':dasherdancer:preDebugBuild': UP_TO_DATE, + ':dasherdancer:prepareLintJarForPublish': SUCCESS, + ':dasherdancer:processDebugJavaRes': NO_SOURCE, + ':dasherdancer:processDebugManifest': FROM_CACHE, + ':dasherdancer:stripDebugDebugSymbols': FROM_CACHE, + ':dasherdancer:syncDebugLibJars': FROM_CACHE, + ':doodles:assembleDebug': SUCCESS, + ':doodles:bundleDebugAar': SUCCESS, + ':doodles:bundleLibCompileDebug': SUCCESS, + ':doodles:bundleLibResDebug': SUCCESS, + ':doodles:bundleLibRuntimeDebug': SUCCESS, + ':doodles:compileDebugAidl': NO_SOURCE, + ':doodles:compileDebugJavaWithJavac': FROM_CACHE, + ':doodles:compileDebugLibraryResources': FROM_CACHE, + ':doodles:compileDebugRenderscript': NO_SOURCE, + ':doodles:compileDebugShaders': FROM_CACHE, + ':doodles:compileDebugSources': UP_TO_DATE, + ':doodles:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':doodles:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':doodles:extractDebugAnnotations': FROM_CACHE, + ':doodles:extractDeepLinksDebug': FROM_CACHE, + ':doodles:generateDebugAssets': UP_TO_DATE, + ':doodles:generateDebugBuildConfig': FROM_CACHE, + ':doodles:generateDebugRFile': FROM_CACHE, + ':doodles:generateDebugResValues': FROM_CACHE, + ':doodles:generateDebugResources': UP_TO_DATE, + ':doodles:javaPreCompileDebug': FROM_CACHE, + ':doodles:mergeDebugConsumerProguardFiles': SUCCESS, + ':doodles:mergeDebugGeneratedProguardFiles': SUCCESS, + ':doodles:mergeDebugJavaResource': FROM_CACHE, + ':doodles:mergeDebugJniLibFolders': FROM_CACHE, + ':doodles:mergeDebugNativeLibs': FROM_CACHE, + ':doodles:mergeDebugShaders': FROM_CACHE, + ':doodles:packageDebugAssets': FROM_CACHE, + ':doodles:packageDebugRenderscript': NO_SOURCE, + ':doodles:packageDebugResources': FROM_CACHE, + ':doodles:parseDebugLocalResources': FROM_CACHE, + ':doodles:preBuild': UP_TO_DATE, + ':doodles:preDebugBuild': UP_TO_DATE, + ':doodles:prepareLintJarForPublish': SUCCESS, + ':doodles:processDebugJavaRes': NO_SOURCE, + ':doodles:processDebugManifest': FROM_CACHE, + ':doodles:stripDebugDebugSymbols': FROM_CACHE, + ':doodles:syncDebugLibJars': FROM_CACHE, + ':presentquest:assembleDebug': SUCCESS, + ':presentquest:bundleDebugAar': SUCCESS, + ':presentquest:bundleLibCompileDebug': SUCCESS, + ':presentquest:bundleLibResDebug': SUCCESS, + ':presentquest:bundleLibRuntimeDebug': SUCCESS, + ':presentquest:compileDebugAidl': NO_SOURCE, + ':presentquest:compileDebugJavaWithJavac': FROM_CACHE, + ':presentquest:compileDebugLibraryResources': FROM_CACHE, + ':presentquest:compileDebugRenderscript': NO_SOURCE, + ':presentquest:compileDebugShaders': FROM_CACHE, + ':presentquest:compileDebugSources': UP_TO_DATE, + ':presentquest:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':presentquest:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':presentquest:extractDebugAnnotations': FROM_CACHE, + ':presentquest:extractDeepLinksDebug': FROM_CACHE, + ':presentquest:generateDebugAssets': UP_TO_DATE, + ':presentquest:generateDebugBuildConfig': FROM_CACHE, + ':presentquest:generateDebugRFile': FROM_CACHE, + ':presentquest:generateDebugResValues': FROM_CACHE, + ':presentquest:generateDebugResources': UP_TO_DATE, + ':presentquest:javaPreCompileDebug': FROM_CACHE, + ':presentquest:mergeDebugConsumerProguardFiles': SUCCESS, + ':presentquest:mergeDebugGeneratedProguardFiles': SUCCESS, + ':presentquest:mergeDebugJavaResource': FROM_CACHE, + ':presentquest:mergeDebugJniLibFolders': FROM_CACHE, + ':presentquest:mergeDebugNativeLibs': FROM_CACHE, + ':presentquest:mergeDebugShaders': FROM_CACHE, + ':presentquest:packageDebugAssets': FROM_CACHE, + ':presentquest:packageDebugRenderscript': NO_SOURCE, + ':presentquest:packageDebugResources': FROM_CACHE, + ':presentquest:parseDebugLocalResources': FROM_CACHE, + ':presentquest:preBuild': UP_TO_DATE, + ':presentquest:preDebugBuild': UP_TO_DATE, + ':presentquest:prepareLintJarForPublish': SUCCESS, + ':presentquest:processDebugJavaRes': NO_SOURCE, + ':presentquest:processDebugManifest': FROM_CACHE, + ':presentquest:stripDebugDebugSymbols': FROM_CACHE, + ':presentquest:syncDebugLibJars': FROM_CACHE, + ':rocketsleigh:assembleDebug': SUCCESS, + ':rocketsleigh:bundleDebugAar': SUCCESS, + ':rocketsleigh:bundleLibCompileDebug': SUCCESS, + ':rocketsleigh:bundleLibResDebug': SUCCESS, + ':rocketsleigh:bundleLibRuntimeDebug': SUCCESS, + ':rocketsleigh:compileDebugAidl': NO_SOURCE, + ':rocketsleigh:compileDebugJavaWithJavac': FROM_CACHE, + ':rocketsleigh:compileDebugLibraryResources': FROM_CACHE, + ':rocketsleigh:compileDebugRenderscript': NO_SOURCE, + ':rocketsleigh:compileDebugShaders': FROM_CACHE, + ':rocketsleigh:compileDebugSources': UP_TO_DATE, + ':rocketsleigh:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':rocketsleigh:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':rocketsleigh:extractDebugAnnotations': FROM_CACHE, + ':rocketsleigh:extractDeepLinksDebug': FROM_CACHE, + ':rocketsleigh:generateDebugAssets': UP_TO_DATE, + ':rocketsleigh:generateDebugBuildConfig': FROM_CACHE, + ':rocketsleigh:generateDebugRFile': FROM_CACHE, + ':rocketsleigh:generateDebugResValues': FROM_CACHE, + ':rocketsleigh:generateDebugResources': UP_TO_DATE, + ':rocketsleigh:javaPreCompileDebug': FROM_CACHE, + ':rocketsleigh:mergeDebugConsumerProguardFiles': SUCCESS, + ':rocketsleigh:mergeDebugGeneratedProguardFiles': SUCCESS, + ':rocketsleigh:mergeDebugJavaResource': FROM_CACHE, + ':rocketsleigh:mergeDebugJniLibFolders': FROM_CACHE, + ':rocketsleigh:mergeDebugNativeLibs': FROM_CACHE, + ':rocketsleigh:mergeDebugShaders': FROM_CACHE, + ':rocketsleigh:packageDebugAssets': FROM_CACHE, + ':rocketsleigh:packageDebugRenderscript': NO_SOURCE, + ':rocketsleigh:packageDebugResources': FROM_CACHE, + ':rocketsleigh:parseDebugLocalResources': FROM_CACHE, + ':rocketsleigh:preBuild': UP_TO_DATE, + ':rocketsleigh:preDebugBuild': UP_TO_DATE, + ':rocketsleigh:prepareLintJarForPublish': SUCCESS, + ':rocketsleigh:processDebugJavaRes': NO_SOURCE, + ':rocketsleigh:processDebugManifest': FROM_CACHE, + ':rocketsleigh:stripDebugDebugSymbols': FROM_CACHE, + ':rocketsleigh:syncDebugLibJars': FROM_CACHE, + ':santa-tracker:assembleDebug': SUCCESS, + ':santa-tracker:assembleDevelopmentDebug': SUCCESS, + ':santa-tracker:checkDevelopmentDebugDuplicateClasses': FROM_CACHE, + ':santa-tracker:compileDevelopmentDebugAidl': NO_SOURCE, + ':santa-tracker:compileDevelopmentDebugJavaWithJavac': FROM_CACHE, + ':santa-tracker:compileDevelopmentDebugRenderscript': NO_SOURCE, + ':santa-tracker:compileDevelopmentDebugShaders': FROM_CACHE, + ':santa-tracker:compileDevelopmentDebugSources': UP_TO_DATE, + ':santa-tracker:createDevelopmentDebugCompatibleScreenManifests': FROM_CACHE, + ':santa-tracker:dexBuilderDevelopmentDebug': FROM_CACHE, + ':santa-tracker:extractDeepLinksDevelopmentDebug': FROM_CACHE, + ':santa-tracker:generateDevelopmentDebugAssets': UP_TO_DATE, + ':santa-tracker:generateDevelopmentDebugBuildConfig': FROM_CACHE, + ':santa-tracker:generateDevelopmentDebugResValues': FROM_CACHE, + ':santa-tracker:generateDevelopmentDebugResources': UP_TO_DATE, + ':santa-tracker:javaPreCompileDevelopmentDebug': FROM_CACHE, + ':santa-tracker:mainApkListPersistenceDevelopmentDebug': FROM_CACHE, + ':santa-tracker:mergeDevelopmentDebugAssets': FROM_CACHE, + ':santa-tracker:mergeDevelopmentDebugJavaResource': FROM_CACHE, + ':santa-tracker:mergeDevelopmentDebugJniLibFolders': FROM_CACHE, + ':santa-tracker:mergeDevelopmentDebugNativeLibs': FROM_CACHE, + ':santa-tracker:mergeDevelopmentDebugResources': FROM_CACHE, + ':santa-tracker:mergeDevelopmentDebugShaders': FROM_CACHE, + ':santa-tracker:mergeExtDexDevelopmentDebug': FROM_CACHE, + ':santa-tracker:mergeLibDexDevelopmentDebug': FROM_CACHE, + ':santa-tracker:mergeProjectDexDevelopmentDebug': FROM_CACHE, + ':santa-tracker:packageDevelopmentDebug': SUCCESS, + ':santa-tracker:preBuild': UP_TO_DATE, + ':santa-tracker:preDevelopmentDebugBuild': UP_TO_DATE, + ':santa-tracker:processDevelopmentDebugJavaRes': NO_SOURCE, + ':santa-tracker:processDevelopmentDebugManifest': FROM_CACHE, + ':santa-tracker:processDevelopmentDebugResources': FROM_CACHE, + ':santa-tracker:stripDevelopmentDebugDebugSymbols': FROM_CACHE, + ':santa-tracker:validateSigningDevelopmentDebug': FROM_CACHE, + ':village:assembleDebug': SUCCESS, + ':village:bundleDebugAar': SUCCESS, + ':village:bundleLibCompileDebug': SUCCESS, + ':village:bundleLibResDebug': SUCCESS, + ':village:bundleLibRuntimeDebug': SUCCESS, + ':village:compileDebugAidl': NO_SOURCE, + ':village:compileDebugJavaWithJavac': FROM_CACHE, + ':village:compileDebugLibraryResources': FROM_CACHE, + ':village:compileDebugRenderscript': NO_SOURCE, + ':village:compileDebugShaders': FROM_CACHE, + ':village:compileDebugSources': UP_TO_DATE, + ':village:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':village:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':village:extractDebugAnnotations': FROM_CACHE, + ':village:extractDeepLinksDebug': FROM_CACHE, + ':village:generateDebugAssets': UP_TO_DATE, + ':village:generateDebugBuildConfig': FROM_CACHE, + ':village:generateDebugRFile': FROM_CACHE, + ':village:generateDebugResValues': FROM_CACHE, + ':village:generateDebugResources': UP_TO_DATE, + ':village:javaPreCompileDebug': FROM_CACHE, + ':village:mergeDebugConsumerProguardFiles': SUCCESS, + ':village:mergeDebugGeneratedProguardFiles': SUCCESS, + ':village:mergeDebugJavaResource': FROM_CACHE, + ':village:mergeDebugJniLibFolders': FROM_CACHE, + ':village:mergeDebugNativeLibs': FROM_CACHE, + ':village:mergeDebugShaders': FROM_CACHE, + ':village:packageDebugAssets': FROM_CACHE, + ':village:packageDebugRenderscript': NO_SOURCE, + ':village:packageDebugResources': FROM_CACHE, + ':village:parseDebugLocalResources': FROM_CACHE, + ':village:preBuild': UP_TO_DATE, + ':village:preDebugBuild': UP_TO_DATE, + ':village:prepareLintJarForPublish': SUCCESS, + ':village:processDebugJavaRes': NO_SOURCE, + ':village:processDebugManifest': FROM_CACHE, + ':village:stripDebugDebugSymbols': FROM_CACHE, + ':village:syncDebugLibJars': FROM_CACHE, + ] +} diff --git a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AndroidSantaTrackerKotlinCachingSmokeTest.groovy b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AndroidSantaTrackerKotlinCachingSmokeTest.groovy new file mode 100644 index 000000000000..90d4edaccd06 --- /dev/null +++ b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AndroidSantaTrackerKotlinCachingSmokeTest.groovy @@ -0,0 +1,1158 @@ +/* + * Copyright 2020 the original author or authors. + * + * 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 org.gradle.smoketests + +import org.gradle.integtests.fixtures.ToBeFixedForInstantExecution +import org.gradle.testkit.runner.BuildResult +import org.gradle.util.Requires +import org.gradle.util.TestPrecondition +import spock.lang.Unroll + +import static org.gradle.testkit.runner.TaskOutcome.FROM_CACHE +import static org.gradle.testkit.runner.TaskOutcome.NO_SOURCE +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS +import static org.gradle.testkit.runner.TaskOutcome.UP_TO_DATE + + +@Requires(TestPrecondition.JDK11_OR_EARLIER) +class AndroidSantaTrackerKotlinCachingSmokeTest extends AbstractAndroidSantaTrackerSmokeTest { + + @Unroll + @ToBeFixedForInstantExecution + def "can cache Santa Tracker Kotlin Android application (agp=#agpVersion)"() { + + given: + def originalDir = temporaryFolder.createDir("original") + def relocatedDir = temporaryFolder.createDir("relocated") + + and: + setupCopyOfSantaTracker(originalDir, 'Kotlin', agpVersion) + setupCopyOfSantaTracker(relocatedDir, 'Kotlin', agpVersion) + + when: + buildLocation(originalDir, agpVersion) + + then: + assertInstantExecutionStateStored() + + when: + BuildResult relocatedResult = buildLocation(relocatedDir, agpVersion) + + then: + assertInstantExecutionStateStored() + + and: + def expectedResults = agpVersion.startsWith('3.6') + ? EXPECTED_RESULTS_3_6 + : EXPECTED_RESULTS + verify(relocatedResult, expectedResults) + + where: + agpVersion << TESTED_AGP_VERSIONS + } + + private static final EXPECTED_RESULTS = [ + ':cityquiz:assembleDebug': SUCCESS, + ':cityquiz:checkDebugDuplicateClasses': FROM_CACHE, + ':cityquiz:compileDebugAidl': NO_SOURCE, + ':cityquiz:compileDebugJavaWithJavac': FROM_CACHE, + ':cityquiz:compileDebugKotlin': FROM_CACHE, + ':cityquiz:compileDebugRenderscript': NO_SOURCE, + ':cityquiz:compileDebugShaders': NO_SOURCE, + ':cityquiz:compileDebugSources': UP_TO_DATE, + ':cityquiz:createDebugCompatibleScreenManifests': FROM_CACHE, + ':cityquiz:dexBuilderDebug': FROM_CACHE, + ':cityquiz:extractDeepLinksDebug': FROM_CACHE, + ':cityquiz:featureDebugWriter': SUCCESS, + ':cityquiz:generateDebugAssets': UP_TO_DATE, + ':cityquiz:generateDebugBuildConfig': FROM_CACHE, + ':cityquiz:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':cityquiz:generateDebugResValues': FROM_CACHE, + ':cityquiz:generateDebugResources': UP_TO_DATE, + ':cityquiz:javaPreCompileDebug': FROM_CACHE, + ':cityquiz:mergeDebugAssets': FROM_CACHE, + ':cityquiz:mergeDebugJavaResource': SUCCESS, + ':cityquiz:mergeDebugJniLibFolders': FROM_CACHE, + ':cityquiz:mergeDebugNativeLibs': FROM_CACHE, + ':cityquiz:mergeDebugResources': SUCCESS, + ':cityquiz:mergeDebugShaders': FROM_CACHE, + ':cityquiz:mergeExtDexDebug': FROM_CACHE, + ':cityquiz:mergeLibDexDebug': FROM_CACHE, + ':cityquiz:mergeProjectDexDebug': FROM_CACHE, + ':cityquiz:packageDebug': SUCCESS, + ':cityquiz:preBuild': UP_TO_DATE, + ':cityquiz:preDebugBuild': UP_TO_DATE, + ':cityquiz:processDebugJavaRes': NO_SOURCE, + ':cityquiz:processDebugManifest': FROM_CACHE, + ':cityquiz:processDebugResources': SUCCESS, + ':cityquiz:stripDebugDebugSymbols': NO_SOURCE, + ':common:assembleDebug': SUCCESS, + ':common:bundleDebugAar': SUCCESS, + ':common:bundleLibCompileToJarDebug': FROM_CACHE, + ':common:bundleLibResDebug': FROM_CACHE, + ':common:bundleLibRuntimeToJarDebug': FROM_CACHE, + ':common:compileDebugAidl': NO_SOURCE, + ':common:compileDebugJavaWithJavac': FROM_CACHE, + ':common:compileDebugKotlin': FROM_CACHE, + ':common:compileDebugLibraryResources': SUCCESS, + ':common:compileDebugRenderscript': NO_SOURCE, + ':common:compileDebugShaders': NO_SOURCE, + ':common:compileDebugSources': UP_TO_DATE, + ':common:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':common:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':common:createFullJarDebug': FROM_CACHE, + ':common:extractDebugAnnotations': FROM_CACHE, + ':common:extractDeepLinksDebug': FROM_CACHE, + ':common:generateDebugAssets': UP_TO_DATE, + ':common:generateDebugBuildConfig': FROM_CACHE, + ':common:generateDebugRFile': FROM_CACHE, + ':common:generateDebugResValues': FROM_CACHE, + ':common:generateDebugResources': UP_TO_DATE, + ':common:javaPreCompileDebug': FROM_CACHE, + ':common:mergeDebugConsumerProguardFiles': FROM_CACHE, + ':common:mergeDebugGeneratedProguardFiles': FROM_CACHE, + ':common:mergeDebugJavaResource': SUCCESS, + ':common:mergeDebugJniLibFolders': FROM_CACHE, + ':common:mergeDebugNativeLibs': FROM_CACHE, + ':common:mergeDebugShaders': FROM_CACHE, + ':common:packageDebugAssets': FROM_CACHE, + ':common:packageDebugRenderscript': NO_SOURCE, + ':common:packageDebugResources': FROM_CACHE, + ':common:parseDebugLocalResources': FROM_CACHE, + ':common:preBuild': UP_TO_DATE, + ':common:preDebugBuild': UP_TO_DATE, + ':common:prepareLintJarForPublish': SUCCESS, + ':common:processDebugJavaRes': NO_SOURCE, + ':common:processDebugManifest': FROM_CACHE, + ':common:stripDebugDebugSymbols': NO_SOURCE, + ':common:syncDebugLibJars': SUCCESS, + ':dasherdancer:assembleDebug': SUCCESS, + ':dasherdancer:checkDebugDuplicateClasses': FROM_CACHE, + ':dasherdancer:compileDebugAidl': NO_SOURCE, + ':dasherdancer:compileDebugJavaWithJavac': FROM_CACHE, + ':dasherdancer:compileDebugKotlin': FROM_CACHE, + ':dasherdancer:compileDebugRenderscript': NO_SOURCE, + ':dasherdancer:compileDebugShaders': NO_SOURCE, + ':dasherdancer:compileDebugSources': UP_TO_DATE, + ':dasherdancer:createDebugCompatibleScreenManifests': FROM_CACHE, + ':dasherdancer:dexBuilderDebug': FROM_CACHE, + ':dasherdancer:extractDeepLinksDebug': FROM_CACHE, + ':dasherdancer:featureDebugWriter': SUCCESS, + ':dasherdancer:generateDebugAssets': UP_TO_DATE, + ':dasherdancer:generateDebugBuildConfig': FROM_CACHE, + ':dasherdancer:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':dasherdancer:generateDebugResValues': FROM_CACHE, + ':dasherdancer:generateDebugResources': UP_TO_DATE, + ':dasherdancer:javaPreCompileDebug': FROM_CACHE, + ':dasherdancer:mergeDebugAssets': FROM_CACHE, + ':dasherdancer:mergeDebugJavaResource': SUCCESS, + ':dasherdancer:mergeDebugJniLibFolders': FROM_CACHE, + ':dasherdancer:mergeDebugNativeLibs': FROM_CACHE, + ':dasherdancer:mergeDebugResources': SUCCESS, + ':dasherdancer:mergeDebugShaders': FROM_CACHE, + ':dasherdancer:mergeExtDexDebug': FROM_CACHE, + ':dasherdancer:mergeLibDexDebug': FROM_CACHE, + ':dasherdancer:mergeProjectDexDebug': FROM_CACHE, + ':dasherdancer:packageDebug': SUCCESS, + ':dasherdancer:preBuild': UP_TO_DATE, + ':dasherdancer:preDebugBuild': UP_TO_DATE, + ':dasherdancer:processDebugJavaRes': NO_SOURCE, + ':dasherdancer:processDebugManifest': FROM_CACHE, + ':dasherdancer:processDebugResources': SUCCESS, + ':dasherdancer:stripDebugDebugSymbols': NO_SOURCE, + ':doodles-lib:assembleDebug': SUCCESS, + ':doodles-lib:bundleDebugAar': SUCCESS, + ':doodles-lib:bundleLibCompileToJarDebug': FROM_CACHE, + ':doodles-lib:bundleLibResDebug': NO_SOURCE, + ':doodles-lib:bundleLibRuntimeToJarDebug': FROM_CACHE, + ':doodles-lib:compileDebugAidl': NO_SOURCE, + ':doodles-lib:compileDebugJavaWithJavac': FROM_CACHE, + ':doodles-lib:compileDebugLibraryResources': SUCCESS, + ':doodles-lib:compileDebugRenderscript': NO_SOURCE, + ':doodles-lib:compileDebugShaders': NO_SOURCE, + ':doodles-lib:compileDebugSources': UP_TO_DATE, + ':doodles-lib:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':doodles-lib:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':doodles-lib:createFullJarDebug': FROM_CACHE, + ':doodles-lib:extractDebugAnnotations': FROM_CACHE, + ':doodles-lib:extractDeepLinksDebug': FROM_CACHE, + ':doodles-lib:generateDebugAssets': UP_TO_DATE, + ':doodles-lib:generateDebugBuildConfig': FROM_CACHE, + ':doodles-lib:generateDebugRFile': FROM_CACHE, + ':doodles-lib:generateDebugResValues': FROM_CACHE, + ':doodles-lib:generateDebugResources': UP_TO_DATE, + ':doodles-lib:javaPreCompileDebug': FROM_CACHE, + ':doodles-lib:mergeDebugConsumerProguardFiles': FROM_CACHE, + ':doodles-lib:mergeDebugGeneratedProguardFiles': FROM_CACHE, + ':doodles-lib:mergeDebugJavaResource': FROM_CACHE, + ':doodles-lib:mergeDebugJniLibFolders': FROM_CACHE, + ':doodles-lib:mergeDebugNativeLibs': FROM_CACHE, + ':doodles-lib:mergeDebugShaders': FROM_CACHE, + ':doodles-lib:packageDebugAssets': FROM_CACHE, + ':doodles-lib:packageDebugRenderscript': NO_SOURCE, + ':doodles-lib:packageDebugResources': FROM_CACHE, + ':doodles-lib:parseDebugLocalResources': FROM_CACHE, + ':doodles-lib:preBuild': UP_TO_DATE, + ':doodles-lib:preDebugBuild': UP_TO_DATE, + ':doodles-lib:prepareLintJarForPublish': SUCCESS, + ':doodles-lib:processDebugJavaRes': NO_SOURCE, + ':doodles-lib:processDebugManifest': FROM_CACHE, + ':doodles-lib:stripDebugDebugSymbols': NO_SOURCE, + ':doodles-lib:syncDebugLibJars': FROM_CACHE, + ':gumball:assembleDebug': SUCCESS, + ':gumball:checkDebugDuplicateClasses': FROM_CACHE, + ':gumball:compileDebugAidl': NO_SOURCE, + ':gumball:compileDebugJavaWithJavac': FROM_CACHE, + ':gumball:compileDebugRenderscript': NO_SOURCE, + ':gumball:compileDebugShaders': NO_SOURCE, + ':gumball:compileDebugSources': UP_TO_DATE, + ':gumball:createDebugCompatibleScreenManifests': FROM_CACHE, + ':gumball:dexBuilderDebug': FROM_CACHE, + ':gumball:extractDeepLinksDebug': FROM_CACHE, + ':gumball:featureDebugWriter': SUCCESS, + ':gumball:generateDebugAssets': UP_TO_DATE, + ':gumball:generateDebugBuildConfig': FROM_CACHE, + ':gumball:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':gumball:generateDebugResValues': FROM_CACHE, + ':gumball:generateDebugResources': UP_TO_DATE, + ':gumball:javaPreCompileDebug': FROM_CACHE, + ':gumball:mergeDebugAssets': FROM_CACHE, + ':gumball:mergeDebugJavaResource': FROM_CACHE, + ':gumball:mergeDebugJniLibFolders': FROM_CACHE, + ':gumball:mergeDebugNativeLibs': FROM_CACHE, + ':gumball:mergeDebugResources': SUCCESS, + ':gumball:mergeDebugShaders': FROM_CACHE, + ':gumball:mergeExtDexDebug': FROM_CACHE, + ':gumball:mergeLibDexDebug': FROM_CACHE, + ':gumball:mergeProjectDexDebug': FROM_CACHE, + ':gumball:packageDebug': SUCCESS, + ':gumball:preBuild': UP_TO_DATE, + ':gumball:preDebugBuild': UP_TO_DATE, + ':gumball:processDebugJavaRes': NO_SOURCE, + ':gumball:processDebugManifest': FROM_CACHE, + ':gumball:processDebugResources': SUCCESS, + ':gumball:stripDebugDebugSymbols': NO_SOURCE, + ':jetpack:assembleDebug': SUCCESS, + ':jetpack:checkDebugDuplicateClasses': FROM_CACHE, + ':jetpack:compileDebugAidl': NO_SOURCE, + ':jetpack:compileDebugJavaWithJavac': FROM_CACHE, + ':jetpack:compileDebugKotlin': FROM_CACHE, + ':jetpack:compileDebugRenderscript': NO_SOURCE, + ':jetpack:compileDebugShaders': NO_SOURCE, + ':jetpack:compileDebugSources': UP_TO_DATE, + ':jetpack:createDebugCompatibleScreenManifests': FROM_CACHE, + ':jetpack:dexBuilderDebug': FROM_CACHE, + ':jetpack:extractDeepLinksDebug': FROM_CACHE, + ':jetpack:featureDebugWriter': SUCCESS, + ':jetpack:generateDebugAssets': UP_TO_DATE, + ':jetpack:generateDebugBuildConfig': FROM_CACHE, + ':jetpack:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':jetpack:generateDebugResValues': FROM_CACHE, + ':jetpack:generateDebugResources': UP_TO_DATE, + ':jetpack:javaPreCompileDebug': FROM_CACHE, + ':jetpack:mergeDebugAssets': FROM_CACHE, + ':jetpack:mergeDebugJavaResource': SUCCESS, + ':jetpack:mergeDebugJniLibFolders': FROM_CACHE, + ':jetpack:mergeDebugNativeLibs': FROM_CACHE, + ':jetpack:mergeDebugResources': SUCCESS, + ':jetpack:mergeDebugShaders': FROM_CACHE, + ':jetpack:mergeExtDexDebug': FROM_CACHE, + ':jetpack:mergeLibDexDebug': FROM_CACHE, + ':jetpack:mergeProjectDexDebug': FROM_CACHE, + ':jetpack:packageDebug': SUCCESS, + ':jetpack:preBuild': UP_TO_DATE, + ':jetpack:preDebugBuild': UP_TO_DATE, + ':jetpack:processDebugJavaRes': NO_SOURCE, + ':jetpack:processDebugManifest': FROM_CACHE, + ':jetpack:processDebugResources': SUCCESS, + ':jetpack:stripDebugDebugSymbols': NO_SOURCE, + ':memory:assembleDebug': SUCCESS, + ':memory:checkDebugDuplicateClasses': FROM_CACHE, + ':memory:compileDebugAidl': NO_SOURCE, + ':memory:compileDebugJavaWithJavac': FROM_CACHE, + ':memory:compileDebugRenderscript': NO_SOURCE, + ':memory:compileDebugShaders': NO_SOURCE, + ':memory:compileDebugSources': UP_TO_DATE, + ':memory:createDebugCompatibleScreenManifests': FROM_CACHE, + ':memory:dexBuilderDebug': FROM_CACHE, + ':memory:extractDeepLinksDebug': FROM_CACHE, + ':memory:featureDebugWriter': SUCCESS, + ':memory:generateDebugAssets': UP_TO_DATE, + ':memory:generateDebugBuildConfig': FROM_CACHE, + ':memory:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':memory:generateDebugResValues': FROM_CACHE, + ':memory:generateDebugResources': UP_TO_DATE, + ':memory:javaPreCompileDebug': FROM_CACHE, + ':memory:mergeDebugAssets': FROM_CACHE, + ':memory:mergeDebugJavaResource': FROM_CACHE, + ':memory:mergeDebugJniLibFolders': FROM_CACHE, + ':memory:mergeDebugNativeLibs': FROM_CACHE, + ':memory:mergeDebugResources': SUCCESS, + ':memory:mergeDebugShaders': FROM_CACHE, + ':memory:mergeExtDexDebug': FROM_CACHE, + ':memory:mergeLibDexDebug': FROM_CACHE, + ':memory:mergeProjectDexDebug': FROM_CACHE, + ':memory:packageDebug': SUCCESS, + ':memory:preBuild': UP_TO_DATE, + ':memory:preDebugBuild': UP_TO_DATE, + ':memory:processDebugJavaRes': NO_SOURCE, + ':memory:processDebugManifest': FROM_CACHE, + ':memory:processDebugResources': SUCCESS, + ':memory:stripDebugDebugSymbols': NO_SOURCE, + ':penguinswim:assembleDebug': SUCCESS, + ':penguinswim:checkDebugDuplicateClasses': FROM_CACHE, + ':penguinswim:compileDebugAidl': NO_SOURCE, + ':penguinswim:compileDebugJavaWithJavac': FROM_CACHE, + ':penguinswim:compileDebugRenderscript': NO_SOURCE, + ':penguinswim:compileDebugShaders': NO_SOURCE, + ':penguinswim:compileDebugSources': UP_TO_DATE, + ':penguinswim:createDebugCompatibleScreenManifests': FROM_CACHE, + ':penguinswim:dexBuilderDebug': FROM_CACHE, + ':penguinswim:extractDeepLinksDebug': FROM_CACHE, + ':penguinswim:featureDebugWriter': SUCCESS, + ':penguinswim:generateDebugAssets': UP_TO_DATE, + ':penguinswim:generateDebugBuildConfig': FROM_CACHE, + ':penguinswim:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':penguinswim:generateDebugResValues': FROM_CACHE, + ':penguinswim:generateDebugResources': UP_TO_DATE, + ':penguinswim:javaPreCompileDebug': FROM_CACHE, + ':penguinswim:mergeDebugAssets': FROM_CACHE, + ':penguinswim:mergeDebugJavaResource': FROM_CACHE, + ':penguinswim:mergeDebugJniLibFolders': FROM_CACHE, + ':penguinswim:mergeDebugNativeLibs': FROM_CACHE, + ':penguinswim:mergeDebugResources': SUCCESS, + ':penguinswim:mergeDebugShaders': FROM_CACHE, + ':penguinswim:mergeExtDexDebug': FROM_CACHE, + ':penguinswim:mergeLibDexDebug': FROM_CACHE, + ':penguinswim:mergeProjectDexDebug': FROM_CACHE, + ':penguinswim:packageDebug': SUCCESS, + ':penguinswim:preBuild': UP_TO_DATE, + ':penguinswim:preDebugBuild': UP_TO_DATE, + ':penguinswim:processDebugJavaRes': NO_SOURCE, + ':penguinswim:processDebugManifest': FROM_CACHE, + ':penguinswim:processDebugResources': SUCCESS, + ':penguinswim:stripDebugDebugSymbols': NO_SOURCE, + ':playgames:assembleDebug': SUCCESS, + ':playgames:bundleDebugAar': SUCCESS, + ':playgames:bundleLibCompileToJarDebug': FROM_CACHE, + ':playgames:bundleLibResDebug': NO_SOURCE, + ':playgames:bundleLibRuntimeToJarDebug': FROM_CACHE, + ':playgames:compileDebugAidl': NO_SOURCE, + ':playgames:compileDebugJavaWithJavac': FROM_CACHE, + ':playgames:compileDebugLibraryResources': SUCCESS, + ':playgames:compileDebugRenderscript': NO_SOURCE, + ':playgames:compileDebugShaders': NO_SOURCE, + ':playgames:compileDebugSources': UP_TO_DATE, + ':playgames:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':playgames:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':playgames:createFullJarDebug': FROM_CACHE, + ':playgames:extractDebugAnnotations': FROM_CACHE, + ':playgames:extractDeepLinksDebug': FROM_CACHE, + ':playgames:generateDebugAssets': UP_TO_DATE, + ':playgames:generateDebugBuildConfig': FROM_CACHE, + ':playgames:generateDebugRFile': FROM_CACHE, + ':playgames:generateDebugResValues': FROM_CACHE, + ':playgames:generateDebugResources': UP_TO_DATE, + ':playgames:javaPreCompileDebug': FROM_CACHE, + ':playgames:mergeDebugConsumerProguardFiles': FROM_CACHE, + ':playgames:mergeDebugGeneratedProguardFiles': FROM_CACHE, + ':playgames:mergeDebugJavaResource': FROM_CACHE, + ':playgames:mergeDebugJniLibFolders': FROM_CACHE, + ':playgames:mergeDebugNativeLibs': FROM_CACHE, + ':playgames:mergeDebugShaders': FROM_CACHE, + ':playgames:packageDebugAssets': FROM_CACHE, + ':playgames:packageDebugRenderscript': NO_SOURCE, + ':playgames:packageDebugResources': FROM_CACHE, + ':playgames:parseDebugLocalResources': FROM_CACHE, + ':playgames:preBuild': UP_TO_DATE, + ':playgames:preDebugBuild': UP_TO_DATE, + ':playgames:prepareLintJarForPublish': SUCCESS, + ':playgames:processDebugJavaRes': NO_SOURCE, + ':playgames:processDebugManifest': FROM_CACHE, + ':playgames:stripDebugDebugSymbols': NO_SOURCE, + ':playgames:syncDebugLibJars': FROM_CACHE, + ':presenttoss:assembleDebug': SUCCESS, + ':presenttoss:checkDebugDuplicateClasses': FROM_CACHE, + ':presenttoss:compileDebugAidl': NO_SOURCE, + ':presenttoss:compileDebugJavaWithJavac': FROM_CACHE, + ':presenttoss:compileDebugRenderscript': NO_SOURCE, + ':presenttoss:compileDebugShaders': NO_SOURCE, + ':presenttoss:compileDebugSources': UP_TO_DATE, + ':presenttoss:createDebugCompatibleScreenManifests': FROM_CACHE, + ':presenttoss:dexBuilderDebug': FROM_CACHE, + ':presenttoss:extractDeepLinksDebug': FROM_CACHE, + ':presenttoss:featureDebugWriter': SUCCESS, + ':presenttoss:generateDebugAssets': UP_TO_DATE, + ':presenttoss:generateDebugBuildConfig': FROM_CACHE, + ':presenttoss:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':presenttoss:generateDebugResValues': FROM_CACHE, + ':presenttoss:generateDebugResources': UP_TO_DATE, + ':presenttoss:javaPreCompileDebug': FROM_CACHE, + ':presenttoss:mergeDebugAssets': FROM_CACHE, + ':presenttoss:mergeDebugJavaResource': FROM_CACHE, + ':presenttoss:mergeDebugJniLibFolders': FROM_CACHE, + ':presenttoss:mergeDebugNativeLibs': FROM_CACHE, + ':presenttoss:mergeDebugResources': SUCCESS, + ':presenttoss:mergeDebugShaders': FROM_CACHE, + ':presenttoss:mergeExtDexDebug': FROM_CACHE, + ':presenttoss:mergeLibDexDebug': FROM_CACHE, + ':presenttoss:mergeProjectDexDebug': FROM_CACHE, + ':presenttoss:packageDebug': SUCCESS, + ':presenttoss:preBuild': UP_TO_DATE, + ':presenttoss:preDebugBuild': UP_TO_DATE, + ':presenttoss:processDebugJavaRes': NO_SOURCE, + ':presenttoss:processDebugManifest': FROM_CACHE, + ':presenttoss:processDebugResources': SUCCESS, + ':presenttoss:stripDebugDebugSymbols': NO_SOURCE, + ':rocketsleigh:assembleDebug': SUCCESS, + ':rocketsleigh:checkDebugDuplicateClasses': FROM_CACHE, + ':rocketsleigh:compileDebugAidl': NO_SOURCE, + ':rocketsleigh:compileDebugJavaWithJavac': FROM_CACHE, + ':rocketsleigh:compileDebugKotlin': FROM_CACHE, + ':rocketsleigh:compileDebugRenderscript': NO_SOURCE, + ':rocketsleigh:compileDebugShaders': NO_SOURCE, + ':rocketsleigh:compileDebugSources': UP_TO_DATE, + ':rocketsleigh:createDebugCompatibleScreenManifests': FROM_CACHE, + ':rocketsleigh:dexBuilderDebug': FROM_CACHE, + ':rocketsleigh:extractDeepLinksDebug': FROM_CACHE, + ':rocketsleigh:featureDebugWriter': SUCCESS, + ':rocketsleigh:generateDebugAssets': UP_TO_DATE, + ':rocketsleigh:generateDebugBuildConfig': FROM_CACHE, + ':rocketsleigh:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':rocketsleigh:generateDebugResValues': FROM_CACHE, + ':rocketsleigh:generateDebugResources': UP_TO_DATE, + ':rocketsleigh:javaPreCompileDebug': FROM_CACHE, + ':rocketsleigh:mergeDebugAssets': FROM_CACHE, + ':rocketsleigh:mergeDebugJavaResource': SUCCESS, + ':rocketsleigh:mergeDebugJniLibFolders': FROM_CACHE, + ':rocketsleigh:mergeDebugNativeLibs': FROM_CACHE, + ':rocketsleigh:mergeDebugResources': SUCCESS, + ':rocketsleigh:mergeDebugShaders': FROM_CACHE, + ':rocketsleigh:mergeExtDexDebug': FROM_CACHE, + ':rocketsleigh:mergeLibDexDebug': FROM_CACHE, + ':rocketsleigh:mergeProjectDexDebug': FROM_CACHE, + ':rocketsleigh:packageDebug': SUCCESS, + ':rocketsleigh:preBuild': UP_TO_DATE, + ':rocketsleigh:preDebugBuild': UP_TO_DATE, + ':rocketsleigh:processDebugJavaRes': NO_SOURCE, + ':rocketsleigh:processDebugManifest': FROM_CACHE, + ':rocketsleigh:processDebugResources': SUCCESS, + ':rocketsleigh:stripDebugDebugSymbols': NO_SOURCE, + ':santa-tracker:assembleDebug': SUCCESS, + ':santa-tracker:bundleDebugClasses': FROM_CACHE, + ':santa-tracker:checkDebugDuplicateClasses': FROM_CACHE, + ':santa-tracker:checkDebugLibraries': FROM_CACHE, + ':santa-tracker:compileDebugAidl': NO_SOURCE, + ':santa-tracker:compileDebugJavaWithJavac': FROM_CACHE, + ':santa-tracker:compileDebugKotlin': FROM_CACHE, + ':santa-tracker:compileDebugRenderscript': NO_SOURCE, + ':santa-tracker:compileDebugShaders': NO_SOURCE, + ':santa-tracker:compileDebugSources': UP_TO_DATE, + ':santa-tracker:createDebugCompatibleScreenManifests': FROM_CACHE, + ':santa-tracker:dexBuilderDebug': FROM_CACHE, + ':santa-tracker:extractDeepLinksDebug': FROM_CACHE, + ':santa-tracker:generateDebugAssets': UP_TO_DATE, + ':santa-tracker:generateDebugBuildConfig': FROM_CACHE, + ':santa-tracker:generateDebugFeatureMetadata': FROM_CACHE, + ':santa-tracker:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':santa-tracker:generateDebugResValues': FROM_CACHE, + ':santa-tracker:generateDebugResources': UP_TO_DATE, + ':santa-tracker:handleDebugMicroApk': FROM_CACHE, + ':santa-tracker:javaPreCompileDebug': FROM_CACHE, + ':santa-tracker:kaptDebugKotlin': SUCCESS, + ':santa-tracker:kaptGenerateStubsDebugKotlin': FROM_CACHE, + ':santa-tracker:mergeDebugAssets': FROM_CACHE, + ':santa-tracker:mergeDebugJavaResource': SUCCESS, + ':santa-tracker:mergeDebugJniLibFolders': FROM_CACHE, + ':santa-tracker:mergeDebugNativeLibs': FROM_CACHE, + ':santa-tracker:mergeDebugResources': SUCCESS, + ':santa-tracker:mergeDebugShaders': FROM_CACHE, + ':santa-tracker:mergeExtDexDebug': FROM_CACHE, + ':santa-tracker:mergeLibDexDebug': FROM_CACHE, + ':santa-tracker:mergeProjectDexDebug': FROM_CACHE, + ':santa-tracker:packageDebug': SUCCESS, + ':santa-tracker:preBuild': UP_TO_DATE, + ':santa-tracker:preDebugBuild': FROM_CACHE, + ':santa-tracker:processDebugJavaRes': NO_SOURCE, + ':santa-tracker:processDebugManifest': FROM_CACHE, + ':santa-tracker:processDebugResources': SUCCESS, + ':santa-tracker:signingConfigWriterDebug': FROM_CACHE, + ':santa-tracker:stripDebugDebugSymbols': NO_SOURCE, + ':santa-tracker:validateSigningDebug': FROM_CACHE, + ':santa-tracker:writeDebugModuleMetadata': SUCCESS, + ':snowballrun:assembleDebug': SUCCESS, + ':snowballrun:checkDebugDuplicateClasses': FROM_CACHE, + ':snowballrun:compileDebugAidl': NO_SOURCE, + ':snowballrun:compileDebugJavaWithJavac': FROM_CACHE, + ':snowballrun:compileDebugRenderscript': NO_SOURCE, + ':snowballrun:compileDebugShaders': NO_SOURCE, + ':snowballrun:compileDebugSources': UP_TO_DATE, + ':snowballrun:createDebugCompatibleScreenManifests': FROM_CACHE, + ':snowballrun:dexBuilderDebug': FROM_CACHE, + ':snowballrun:extractDeepLinksDebug': FROM_CACHE, + ':snowballrun:featureDebugWriter': SUCCESS, + ':snowballrun:generateDebugAssets': UP_TO_DATE, + ':snowballrun:generateDebugBuildConfig': FROM_CACHE, + ':snowballrun:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':snowballrun:generateDebugResValues': FROM_CACHE, + ':snowballrun:generateDebugResources': UP_TO_DATE, + ':snowballrun:javaPreCompileDebug': FROM_CACHE, + ':snowballrun:mergeDebugAssets': FROM_CACHE, + ':snowballrun:mergeDebugJavaResource': FROM_CACHE, + ':snowballrun:mergeDebugJniLibFolders': FROM_CACHE, + ':snowballrun:mergeDebugNativeLibs': FROM_CACHE, + ':snowballrun:mergeDebugResources': SUCCESS, + ':snowballrun:mergeDebugShaders': FROM_CACHE, + ':snowballrun:mergeExtDexDebug': FROM_CACHE, + ':snowballrun:mergeLibDexDebug': FROM_CACHE, + ':snowballrun:mergeProjectDexDebug': FROM_CACHE, + ':snowballrun:packageDebug': SUCCESS, + ':snowballrun:preBuild': UP_TO_DATE, + ':snowballrun:preDebugBuild': UP_TO_DATE, + ':snowballrun:processDebugJavaRes': NO_SOURCE, + ':snowballrun:processDebugManifest': FROM_CACHE, + ':snowballrun:processDebugResources': SUCCESS, + ':snowballrun:stripDebugDebugSymbols': NO_SOURCE, + ':tracker:assembleDebug': SUCCESS, + ':tracker:bundleDebugAar': SUCCESS, + ':tracker:bundleLibCompileToJarDebug': FROM_CACHE, + ':tracker:bundleLibResDebug': FROM_CACHE, + ':tracker:bundleLibRuntimeToJarDebug': FROM_CACHE, + ':tracker:compileDebugAidl': NO_SOURCE, + ':tracker:compileDebugJavaWithJavac': SUCCESS, + ':tracker:compileDebugKotlin': FROM_CACHE, + ':tracker:compileDebugLibraryResources': SUCCESS, + ':tracker:compileDebugRenderscript': NO_SOURCE, + ':tracker:compileDebugShaders': NO_SOURCE, + ':tracker:compileDebugSources': SUCCESS, + ':tracker:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':tracker:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':tracker:createFullJarDebug': FROM_CACHE, + ':tracker:extractDebugAnnotations': FROM_CACHE, + ':tracker:extractDeepLinksDebug': FROM_CACHE, + ':tracker:generateDebugAssets': UP_TO_DATE, + ':tracker:generateDebugBuildConfig': FROM_CACHE, + ':tracker:generateDebugRFile': FROM_CACHE, + ':tracker:generateDebugResValues': FROM_CACHE, + ':tracker:generateDebugResources': UP_TO_DATE, + ':tracker:javaPreCompileDebug': FROM_CACHE, + ':tracker:kaptDebugKotlin': SUCCESS, + ':tracker:kaptGenerateStubsDebugKotlin': SUCCESS, + ':tracker:mergeDebugConsumerProguardFiles': FROM_CACHE, + ':tracker:mergeDebugGeneratedProguardFiles': FROM_CACHE, + ':tracker:mergeDebugJavaResource': SUCCESS, + ':tracker:mergeDebugJniLibFolders': FROM_CACHE, + ':tracker:mergeDebugNativeLibs': FROM_CACHE, + ':tracker:mergeDebugResources': FROM_CACHE, + ':tracker:mergeDebugShaders': FROM_CACHE, + ':tracker:packageDebugAssets': FROM_CACHE, + ':tracker:packageDebugRenderscript': NO_SOURCE, + ':tracker:packageDebugResources': FROM_CACHE, + ':tracker:parseDebugLocalResources': FROM_CACHE, + ':tracker:preBuild': UP_TO_DATE, + ':tracker:preDebugBuild': UP_TO_DATE, + ':tracker:prepareLintJarForPublish': SUCCESS, + ':tracker:processDebugJavaRes': NO_SOURCE, + ':tracker:processDebugManifest': FROM_CACHE, + ':tracker:stripDebugDebugSymbols': NO_SOURCE, + ':tracker:syncDebugLibJars': SUCCESS, + ':wearable:assembleDebug': SUCCESS, + ':wearable:checkDebugDuplicateClasses': FROM_CACHE, + ':wearable:compileDebugAidl': NO_SOURCE, + ':wearable:compileDebugJavaWithJavac': FROM_CACHE, + ':wearable:compileDebugKotlin': FROM_CACHE, + ':wearable:compileDebugRenderscript': NO_SOURCE, + ':wearable:compileDebugShaders': NO_SOURCE, + ':wearable:compileDebugSources': UP_TO_DATE, + ':wearable:createDebugCompatibleScreenManifests': FROM_CACHE, + ':wearable:dexBuilderDebug': FROM_CACHE, + ':wearable:extractDeepLinksDebug': FROM_CACHE, + ':wearable:generateDebugAssets': UP_TO_DATE, + ':wearable:generateDebugBuildConfig': FROM_CACHE, + ':wearable:generateDebugResValues': FROM_CACHE, + ':wearable:generateDebugResources': UP_TO_DATE, + ':wearable:javaPreCompileDebug': FROM_CACHE, + ':wearable:kaptDebugKotlin': SUCCESS, + ':wearable:kaptGenerateStubsDebugKotlin': FROM_CACHE, + ':wearable:mergeDebugAssets': FROM_CACHE, + ':wearable:mergeDebugJavaResource': SUCCESS, + ':wearable:mergeDebugJniLibFolders': FROM_CACHE, + ':wearable:mergeDebugNativeLibs': FROM_CACHE, + ':wearable:mergeDebugResources': SUCCESS, + ':wearable:mergeDebugShaders': FROM_CACHE, + ':wearable:mergeExtDexDebug': FROM_CACHE, + ':wearable:mergeLibDexDebug': FROM_CACHE, + ':wearable:mergeProjectDexDebug': FROM_CACHE, + ':wearable:packageDebug': SUCCESS, + ':wearable:preBuild': UP_TO_DATE, + ':wearable:preDebugBuild': UP_TO_DATE, + ':wearable:processDebugJavaRes': NO_SOURCE, + ':wearable:processDebugManifest': FROM_CACHE, + ':wearable:processDebugResources': SUCCESS, + ':wearable:stripDebugDebugSymbols': NO_SOURCE, + ':wearable:validateSigningDebug': FROM_CACHE, + ] + + private static final EXPECTED_RESULTS_3_6 = [ + ':cityquiz:assembleDebug': SUCCESS, + ':cityquiz:checkDebugDuplicateClasses': FROM_CACHE, + ':cityquiz:compileDebugAidl': NO_SOURCE, + ':cityquiz:compileDebugJavaWithJavac': FROM_CACHE, + ':cityquiz:compileDebugKotlin': FROM_CACHE, + ':cityquiz:compileDebugRenderscript': NO_SOURCE, + ':cityquiz:compileDebugShaders': FROM_CACHE, + ':cityquiz:compileDebugSources': UP_TO_DATE, + ':cityquiz:createDebugCompatibleScreenManifests': FROM_CACHE, + ':cityquiz:dexBuilderDebug': FROM_CACHE, + ':cityquiz:extractDeepLinksDebug': FROM_CACHE, + ':cityquiz:featureDebugWriter': SUCCESS, + ':cityquiz:generateDebugAssets': UP_TO_DATE, + ':cityquiz:generateDebugBuildConfig': FROM_CACHE, + ':cityquiz:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':cityquiz:generateDebugResValues': FROM_CACHE, + ':cityquiz:generateDebugResources': UP_TO_DATE, + ':cityquiz:javaPreCompileDebug': FROM_CACHE, + ':cityquiz:mainApkListPersistenceDebug': FROM_CACHE, + ':cityquiz:mergeDebugAssets': FROM_CACHE, + ':cityquiz:mergeDebugJavaResource': SUCCESS, + ':cityquiz:mergeDebugJniLibFolders': FROM_CACHE, + ':cityquiz:mergeDebugNativeLibs': FROM_CACHE, + ':cityquiz:mergeDebugResources': FROM_CACHE, + ':cityquiz:mergeDebugShaders': FROM_CACHE, + ':cityquiz:mergeExtDexDebug': FROM_CACHE, + ':cityquiz:mergeLibDexDebug': FROM_CACHE, + ':cityquiz:mergeProjectDexDebug': FROM_CACHE, + ':cityquiz:packageDebug': SUCCESS, + ':cityquiz:preBuild': UP_TO_DATE, + ':cityquiz:preDebugBuild': UP_TO_DATE, + ':cityquiz:processDebugJavaRes': NO_SOURCE, + ':cityquiz:processDebugManifest': FROM_CACHE, + ':cityquiz:processDebugResources': FROM_CACHE, + ':cityquiz:stripDebugDebugSymbols': FROM_CACHE, + ':common:assembleDebug': SUCCESS, + ':common:bundleDebugAar': SUCCESS, + ':common:bundleLibCompileDebug': SUCCESS, + ':common:bundleLibResDebug': SUCCESS, + ':common:bundleLibRuntimeDebug': SUCCESS, + ':common:compileDebugAidl': NO_SOURCE, + ':common:compileDebugJavaWithJavac': FROM_CACHE, + ':common:compileDebugKotlin': FROM_CACHE, + ':common:compileDebugLibraryResources': FROM_CACHE, + ':common:compileDebugRenderscript': NO_SOURCE, + ':common:compileDebugShaders': FROM_CACHE, + ':common:compileDebugSources': UP_TO_DATE, + ':common:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':common:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':common:extractDebugAnnotations': FROM_CACHE, + ':common:extractDeepLinksDebug': FROM_CACHE, + ':common:generateDebugAssets': UP_TO_DATE, + ':common:generateDebugBuildConfig': FROM_CACHE, + ':common:generateDebugRFile': FROM_CACHE, + ':common:generateDebugResValues': FROM_CACHE, + ':common:generateDebugResources': UP_TO_DATE, + ':common:javaPreCompileDebug': FROM_CACHE, + ':common:mergeDebugConsumerProguardFiles': SUCCESS, + ':common:mergeDebugGeneratedProguardFiles': SUCCESS, + ':common:mergeDebugJavaResource': SUCCESS, + ':common:mergeDebugJniLibFolders': FROM_CACHE, + ':common:mergeDebugNativeLibs': FROM_CACHE, + ':common:mergeDebugShaders': FROM_CACHE, + ':common:packageDebugAssets': FROM_CACHE, + ':common:packageDebugRenderscript': NO_SOURCE, + ':common:packageDebugResources': FROM_CACHE, + ':common:parseDebugLocalResources': FROM_CACHE, + ':common:preBuild': UP_TO_DATE, + ':common:preDebugBuild': UP_TO_DATE, + ':common:prepareLintJarForPublish': SUCCESS, + ':common:processDebugJavaRes': NO_SOURCE, + ':common:processDebugManifest': FROM_CACHE, + ':common:stripDebugDebugSymbols': FROM_CACHE, + ':common:syncDebugLibJars': SUCCESS, + ':dasherdancer:assembleDebug': SUCCESS, + ':dasherdancer:checkDebugDuplicateClasses': FROM_CACHE, + ':dasherdancer:compileDebugAidl': NO_SOURCE, + ':dasherdancer:compileDebugJavaWithJavac': FROM_CACHE, + ':dasherdancer:compileDebugKotlin': FROM_CACHE, + ':dasherdancer:compileDebugRenderscript': NO_SOURCE, + ':dasherdancer:compileDebugShaders': FROM_CACHE, + ':dasherdancer:compileDebugSources': UP_TO_DATE, + ':dasherdancer:createDebugCompatibleScreenManifests': FROM_CACHE, + ':dasherdancer:dexBuilderDebug': FROM_CACHE, + ':dasherdancer:extractDeepLinksDebug': FROM_CACHE, + ':dasherdancer:featureDebugWriter': SUCCESS, + ':dasherdancer:generateDebugAssets': UP_TO_DATE, + ':dasherdancer:generateDebugBuildConfig': FROM_CACHE, + ':dasherdancer:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':dasherdancer:generateDebugResValues': FROM_CACHE, + ':dasherdancer:generateDebugResources': UP_TO_DATE, + ':dasherdancer:javaPreCompileDebug': FROM_CACHE, + ':dasherdancer:mainApkListPersistenceDebug': FROM_CACHE, + ':dasherdancer:mergeDebugAssets': FROM_CACHE, + ':dasherdancer:mergeDebugJavaResource': SUCCESS, + ':dasherdancer:mergeDebugJniLibFolders': FROM_CACHE, + ':dasherdancer:mergeDebugNativeLibs': FROM_CACHE, + ':dasherdancer:mergeDebugResources': FROM_CACHE, + ':dasherdancer:mergeDebugShaders': FROM_CACHE, + ':dasherdancer:mergeExtDexDebug': FROM_CACHE, + ':dasherdancer:mergeLibDexDebug': FROM_CACHE, + ':dasherdancer:mergeProjectDexDebug': FROM_CACHE, + ':dasherdancer:packageDebug': SUCCESS, + ':dasherdancer:preBuild': UP_TO_DATE, + ':dasherdancer:preDebugBuild': UP_TO_DATE, + ':dasherdancer:processDebugJavaRes': NO_SOURCE, + ':dasherdancer:processDebugManifest': FROM_CACHE, + ':dasherdancer:processDebugResources': FROM_CACHE, + ':dasherdancer:stripDebugDebugSymbols': FROM_CACHE, + ':doodles-lib:assembleDebug': SUCCESS, + ':doodles-lib:bundleDebugAar': SUCCESS, + ':doodles-lib:bundleLibCompileDebug': SUCCESS, + ':doodles-lib:bundleLibResDebug': SUCCESS, + ':doodles-lib:bundleLibRuntimeDebug': SUCCESS, + ':doodles-lib:compileDebugAidl': NO_SOURCE, + ':doodles-lib:compileDebugJavaWithJavac': FROM_CACHE, + ':doodles-lib:compileDebugLibraryResources': FROM_CACHE, + ':doodles-lib:compileDebugRenderscript': NO_SOURCE, + ':doodles-lib:compileDebugShaders': FROM_CACHE, + ':doodles-lib:compileDebugSources': UP_TO_DATE, + ':doodles-lib:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':doodles-lib:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':doodles-lib:extractDebugAnnotations': FROM_CACHE, + ':doodles-lib:extractDeepLinksDebug': FROM_CACHE, + ':doodles-lib:generateDebugAssets': UP_TO_DATE, + ':doodles-lib:generateDebugBuildConfig': FROM_CACHE, + ':doodles-lib:generateDebugRFile': FROM_CACHE, + ':doodles-lib:generateDebugResValues': FROM_CACHE, + ':doodles-lib:generateDebugResources': UP_TO_DATE, + ':doodles-lib:javaPreCompileDebug': FROM_CACHE, + ':doodles-lib:mergeDebugConsumerProguardFiles': SUCCESS, + ':doodles-lib:mergeDebugGeneratedProguardFiles': SUCCESS, + ':doodles-lib:mergeDebugJavaResource': FROM_CACHE, + ':doodles-lib:mergeDebugJniLibFolders': FROM_CACHE, + ':doodles-lib:mergeDebugNativeLibs': FROM_CACHE, + ':doodles-lib:mergeDebugShaders': FROM_CACHE, + ':doodles-lib:packageDebugAssets': FROM_CACHE, + ':doodles-lib:packageDebugRenderscript': NO_SOURCE, + ':doodles-lib:packageDebugResources': FROM_CACHE, + ':doodles-lib:parseDebugLocalResources': FROM_CACHE, + ':doodles-lib:preBuild': UP_TO_DATE, + ':doodles-lib:preDebugBuild': UP_TO_DATE, + ':doodles-lib:prepareLintJarForPublish': SUCCESS, + ':doodles-lib:processDebugJavaRes': NO_SOURCE, + ':doodles-lib:processDebugManifest': FROM_CACHE, + ':doodles-lib:stripDebugDebugSymbols': FROM_CACHE, + ':doodles-lib:syncDebugLibJars': FROM_CACHE, + ':gumball:assembleDebug': SUCCESS, + ':gumball:checkDebugDuplicateClasses': FROM_CACHE, + ':gumball:compileDebugAidl': NO_SOURCE, + ':gumball:compileDebugJavaWithJavac': FROM_CACHE, + ':gumball:compileDebugRenderscript': NO_SOURCE, + ':gumball:compileDebugShaders': FROM_CACHE, + ':gumball:compileDebugSources': UP_TO_DATE, + ':gumball:createDebugCompatibleScreenManifests': FROM_CACHE, + ':gumball:dexBuilderDebug': FROM_CACHE, + ':gumball:extractDeepLinksDebug': FROM_CACHE, + ':gumball:featureDebugWriter': SUCCESS, + ':gumball:generateDebugAssets': UP_TO_DATE, + ':gumball:generateDebugBuildConfig': FROM_CACHE, + ':gumball:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':gumball:generateDebugResValues': FROM_CACHE, + ':gumball:generateDebugResources': UP_TO_DATE, + ':gumball:javaPreCompileDebug': FROM_CACHE, + ':gumball:mainApkListPersistenceDebug': FROM_CACHE, + ':gumball:mergeDebugAssets': FROM_CACHE, + ':gumball:mergeDebugJavaResource': FROM_CACHE, + ':gumball:mergeDebugJniLibFolders': FROM_CACHE, + ':gumball:mergeDebugNativeLibs': FROM_CACHE, + ':gumball:mergeDebugResources': FROM_CACHE, + ':gumball:mergeDebugShaders': FROM_CACHE, + ':gumball:mergeExtDexDebug': FROM_CACHE, + ':gumball:mergeLibDexDebug': FROM_CACHE, + ':gumball:mergeProjectDexDebug': FROM_CACHE, + ':gumball:packageDebug': SUCCESS, + ':gumball:preBuild': UP_TO_DATE, + ':gumball:preDebugBuild': UP_TO_DATE, + ':gumball:processDebugJavaRes': NO_SOURCE, + ':gumball:processDebugManifest': FROM_CACHE, + ':gumball:processDebugResources': FROM_CACHE, + ':gumball:stripDebugDebugSymbols': FROM_CACHE, + ':jetpack:assembleDebug': SUCCESS, + ':jetpack:checkDebugDuplicateClasses': FROM_CACHE, + ':jetpack:compileDebugAidl': NO_SOURCE, + ':jetpack:compileDebugJavaWithJavac': FROM_CACHE, + ':jetpack:compileDebugKotlin': FROM_CACHE, + ':jetpack:compileDebugRenderscript': NO_SOURCE, + ':jetpack:compileDebugShaders': FROM_CACHE, + ':jetpack:compileDebugSources': UP_TO_DATE, + ':jetpack:createDebugCompatibleScreenManifests': FROM_CACHE, + ':jetpack:dexBuilderDebug': FROM_CACHE, + ':jetpack:extractDeepLinksDebug': FROM_CACHE, + ':jetpack:featureDebugWriter': SUCCESS, + ':jetpack:generateDebugAssets': UP_TO_DATE, + ':jetpack:generateDebugBuildConfig': FROM_CACHE, + ':jetpack:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':jetpack:generateDebugResValues': FROM_CACHE, + ':jetpack:generateDebugResources': UP_TO_DATE, + ':jetpack:javaPreCompileDebug': FROM_CACHE, + ':jetpack:mainApkListPersistenceDebug': FROM_CACHE, + ':jetpack:mergeDebugAssets': FROM_CACHE, + ':jetpack:mergeDebugJavaResource': SUCCESS, + ':jetpack:mergeDebugJniLibFolders': FROM_CACHE, + ':jetpack:mergeDebugNativeLibs': FROM_CACHE, + ':jetpack:mergeDebugResources': FROM_CACHE, + ':jetpack:mergeDebugShaders': FROM_CACHE, + ':jetpack:mergeExtDexDebug': FROM_CACHE, + ':jetpack:mergeLibDexDebug': FROM_CACHE, + ':jetpack:mergeProjectDexDebug': FROM_CACHE, + ':jetpack:packageDebug': SUCCESS, + ':jetpack:preBuild': UP_TO_DATE, + ':jetpack:preDebugBuild': UP_TO_DATE, + ':jetpack:processDebugJavaRes': NO_SOURCE, + ':jetpack:processDebugManifest': FROM_CACHE, + ':jetpack:processDebugResources': FROM_CACHE, + ':jetpack:stripDebugDebugSymbols': FROM_CACHE, + ':memory:assembleDebug': SUCCESS, + ':memory:checkDebugDuplicateClasses': FROM_CACHE, + ':memory:compileDebugAidl': NO_SOURCE, + ':memory:compileDebugJavaWithJavac': FROM_CACHE, + ':memory:compileDebugRenderscript': NO_SOURCE, + ':memory:compileDebugShaders': FROM_CACHE, + ':memory:compileDebugSources': UP_TO_DATE, + ':memory:createDebugCompatibleScreenManifests': FROM_CACHE, + ':memory:dexBuilderDebug': FROM_CACHE, + ':memory:extractDeepLinksDebug': FROM_CACHE, + ':memory:featureDebugWriter': SUCCESS, + ':memory:generateDebugAssets': UP_TO_DATE, + ':memory:generateDebugBuildConfig': FROM_CACHE, + ':memory:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':memory:generateDebugResValues': FROM_CACHE, + ':memory:generateDebugResources': UP_TO_DATE, + ':memory:javaPreCompileDebug': FROM_CACHE, + ':memory:mainApkListPersistenceDebug': FROM_CACHE, + ':memory:mergeDebugAssets': FROM_CACHE, + ':memory:mergeDebugJavaResource': FROM_CACHE, + ':memory:mergeDebugJniLibFolders': FROM_CACHE, + ':memory:mergeDebugNativeLibs': FROM_CACHE, + ':memory:mergeDebugResources': FROM_CACHE, + ':memory:mergeDebugShaders': FROM_CACHE, + ':memory:mergeExtDexDebug': FROM_CACHE, + ':memory:mergeLibDexDebug': FROM_CACHE, + ':memory:mergeProjectDexDebug': FROM_CACHE, + ':memory:packageDebug': SUCCESS, + ':memory:preBuild': UP_TO_DATE, + ':memory:preDebugBuild': UP_TO_DATE, + ':memory:processDebugJavaRes': NO_SOURCE, + ':memory:processDebugManifest': FROM_CACHE, + ':memory:processDebugResources': FROM_CACHE, + ':memory:stripDebugDebugSymbols': FROM_CACHE, + ':penguinswim:assembleDebug': SUCCESS, + ':penguinswim:checkDebugDuplicateClasses': FROM_CACHE, + ':penguinswim:compileDebugAidl': NO_SOURCE, + ':penguinswim:compileDebugJavaWithJavac': FROM_CACHE, + ':penguinswim:compileDebugRenderscript': NO_SOURCE, + ':penguinswim:compileDebugShaders': FROM_CACHE, + ':penguinswim:compileDebugSources': UP_TO_DATE, + ':penguinswim:createDebugCompatibleScreenManifests': FROM_CACHE, + ':penguinswim:dexBuilderDebug': FROM_CACHE, + ':penguinswim:extractDeepLinksDebug': FROM_CACHE, + ':penguinswim:featureDebugWriter': SUCCESS, + ':penguinswim:generateDebugAssets': UP_TO_DATE, + ':penguinswim:generateDebugBuildConfig': FROM_CACHE, + ':penguinswim:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':penguinswim:generateDebugResValues': FROM_CACHE, + ':penguinswim:generateDebugResources': UP_TO_DATE, + ':penguinswim:javaPreCompileDebug': FROM_CACHE, + ':penguinswim:mainApkListPersistenceDebug': FROM_CACHE, + ':penguinswim:mergeDebugAssets': FROM_CACHE, + ':penguinswim:mergeDebugJavaResource': FROM_CACHE, + ':penguinswim:mergeDebugJniLibFolders': FROM_CACHE, + ':penguinswim:mergeDebugNativeLibs': FROM_CACHE, + ':penguinswim:mergeDebugResources': FROM_CACHE, + ':penguinswim:mergeDebugShaders': FROM_CACHE, + ':penguinswim:mergeExtDexDebug': FROM_CACHE, + ':penguinswim:mergeLibDexDebug': FROM_CACHE, + ':penguinswim:mergeProjectDexDebug': FROM_CACHE, + ':penguinswim:packageDebug': SUCCESS, + ':penguinswim:preBuild': UP_TO_DATE, + ':penguinswim:preDebugBuild': UP_TO_DATE, + ':penguinswim:processDebugJavaRes': NO_SOURCE, + ':penguinswim:processDebugManifest': FROM_CACHE, + ':penguinswim:processDebugResources': FROM_CACHE, + ':penguinswim:stripDebugDebugSymbols': FROM_CACHE, + ':playgames:assembleDebug': SUCCESS, + ':playgames:bundleDebugAar': SUCCESS, + ':playgames:bundleLibCompileDebug': SUCCESS, + ':playgames:bundleLibResDebug': SUCCESS, + ':playgames:bundleLibRuntimeDebug': SUCCESS, + ':playgames:compileDebugAidl': NO_SOURCE, + ':playgames:compileDebugJavaWithJavac': FROM_CACHE, + ':playgames:compileDebugLibraryResources': FROM_CACHE, + ':playgames:compileDebugRenderscript': NO_SOURCE, + ':playgames:compileDebugShaders': FROM_CACHE, + ':playgames:compileDebugSources': UP_TO_DATE, + ':playgames:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':playgames:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':playgames:extractDebugAnnotations': FROM_CACHE, + ':playgames:extractDeepLinksDebug': FROM_CACHE, + ':playgames:generateDebugAssets': UP_TO_DATE, + ':playgames:generateDebugBuildConfig': FROM_CACHE, + ':playgames:generateDebugRFile': FROM_CACHE, + ':playgames:generateDebugResValues': FROM_CACHE, + ':playgames:generateDebugResources': UP_TO_DATE, + ':playgames:javaPreCompileDebug': FROM_CACHE, + ':playgames:mergeDebugConsumerProguardFiles': SUCCESS, + ':playgames:mergeDebugGeneratedProguardFiles': SUCCESS, + ':playgames:mergeDebugJavaResource': FROM_CACHE, + ':playgames:mergeDebugJniLibFolders': FROM_CACHE, + ':playgames:mergeDebugNativeLibs': FROM_CACHE, + ':playgames:mergeDebugShaders': FROM_CACHE, + ':playgames:packageDebugAssets': FROM_CACHE, + ':playgames:packageDebugRenderscript': NO_SOURCE, + ':playgames:packageDebugResources': FROM_CACHE, + ':playgames:parseDebugLocalResources': FROM_CACHE, + ':playgames:preBuild': UP_TO_DATE, + ':playgames:preDebugBuild': UP_TO_DATE, + ':playgames:prepareLintJarForPublish': SUCCESS, + ':playgames:processDebugJavaRes': NO_SOURCE, + ':playgames:processDebugManifest': FROM_CACHE, + ':playgames:stripDebugDebugSymbols': FROM_CACHE, + ':playgames:syncDebugLibJars': FROM_CACHE, + ':presenttoss:assembleDebug': SUCCESS, + ':presenttoss:checkDebugDuplicateClasses': FROM_CACHE, + ':presenttoss:compileDebugAidl': NO_SOURCE, + ':presenttoss:compileDebugJavaWithJavac': FROM_CACHE, + ':presenttoss:compileDebugRenderscript': NO_SOURCE, + ':presenttoss:compileDebugShaders': FROM_CACHE, + ':presenttoss:compileDebugSources': UP_TO_DATE, + ':presenttoss:createDebugCompatibleScreenManifests': FROM_CACHE, + ':presenttoss:dexBuilderDebug': FROM_CACHE, + ':presenttoss:extractDeepLinksDebug': FROM_CACHE, + ':presenttoss:featureDebugWriter': SUCCESS, + ':presenttoss:generateDebugAssets': UP_TO_DATE, + ':presenttoss:generateDebugBuildConfig': FROM_CACHE, + ':presenttoss:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':presenttoss:generateDebugResValues': FROM_CACHE, + ':presenttoss:generateDebugResources': UP_TO_DATE, + ':presenttoss:javaPreCompileDebug': FROM_CACHE, + ':presenttoss:mainApkListPersistenceDebug': FROM_CACHE, + ':presenttoss:mergeDebugAssets': FROM_CACHE, + ':presenttoss:mergeDebugJavaResource': FROM_CACHE, + ':presenttoss:mergeDebugJniLibFolders': FROM_CACHE, + ':presenttoss:mergeDebugNativeLibs': FROM_CACHE, + ':presenttoss:mergeDebugResources': FROM_CACHE, + ':presenttoss:mergeDebugShaders': FROM_CACHE, + ':presenttoss:mergeExtDexDebug': FROM_CACHE, + ':presenttoss:mergeLibDexDebug': FROM_CACHE, + ':presenttoss:mergeProjectDexDebug': FROM_CACHE, + ':presenttoss:packageDebug': SUCCESS, + ':presenttoss:preBuild': UP_TO_DATE, + ':presenttoss:preDebugBuild': UP_TO_DATE, + ':presenttoss:processDebugJavaRes': NO_SOURCE, + ':presenttoss:processDebugManifest': FROM_CACHE, + ':presenttoss:processDebugResources': FROM_CACHE, + ':presenttoss:stripDebugDebugSymbols': FROM_CACHE, + ':rocketsleigh:assembleDebug': SUCCESS, + ':rocketsleigh:checkDebugDuplicateClasses': FROM_CACHE, + ':rocketsleigh:compileDebugAidl': NO_SOURCE, + ':rocketsleigh:compileDebugJavaWithJavac': FROM_CACHE, + ':rocketsleigh:compileDebugKotlin': FROM_CACHE, + ':rocketsleigh:compileDebugRenderscript': NO_SOURCE, + ':rocketsleigh:compileDebugShaders': FROM_CACHE, + ':rocketsleigh:compileDebugSources': UP_TO_DATE, + ':rocketsleigh:createDebugCompatibleScreenManifests': FROM_CACHE, + ':rocketsleigh:dexBuilderDebug': FROM_CACHE, + ':rocketsleigh:extractDeepLinksDebug': FROM_CACHE, + ':rocketsleigh:featureDebugWriter': SUCCESS, + ':rocketsleigh:generateDebugAssets': UP_TO_DATE, + ':rocketsleigh:generateDebugBuildConfig': FROM_CACHE, + ':rocketsleigh:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':rocketsleigh:generateDebugResValues': FROM_CACHE, + ':rocketsleigh:generateDebugResources': UP_TO_DATE, + ':rocketsleigh:javaPreCompileDebug': FROM_CACHE, + ':rocketsleigh:mainApkListPersistenceDebug': FROM_CACHE, + ':rocketsleigh:mergeDebugAssets': FROM_CACHE, + ':rocketsleigh:mergeDebugJavaResource': SUCCESS, + ':rocketsleigh:mergeDebugJniLibFolders': FROM_CACHE, + ':rocketsleigh:mergeDebugNativeLibs': FROM_CACHE, + ':rocketsleigh:mergeDebugResources': FROM_CACHE, + ':rocketsleigh:mergeDebugShaders': FROM_CACHE, + ':rocketsleigh:mergeExtDexDebug': FROM_CACHE, + ':rocketsleigh:mergeLibDexDebug': FROM_CACHE, + ':rocketsleigh:mergeProjectDexDebug': FROM_CACHE, + ':rocketsleigh:packageDebug': SUCCESS, + ':rocketsleigh:preBuild': UP_TO_DATE, + ':rocketsleigh:preDebugBuild': UP_TO_DATE, + ':rocketsleigh:processDebugJavaRes': NO_SOURCE, + ':rocketsleigh:processDebugManifest': FROM_CACHE, + ':rocketsleigh:processDebugResources': FROM_CACHE, + ':rocketsleigh:stripDebugDebugSymbols': FROM_CACHE, + ':santa-tracker:assembleDebug': SUCCESS, + ':santa-tracker:bundleDebugClasses': SUCCESS, + ':santa-tracker:checkDebugDuplicateClasses': FROM_CACHE, + ':santa-tracker:checkDebugLibraries': FROM_CACHE, + ':santa-tracker:compileDebugAidl': NO_SOURCE, + ':santa-tracker:compileDebugJavaWithJavac': FROM_CACHE, + ':santa-tracker:compileDebugKotlin': FROM_CACHE, + ':santa-tracker:compileDebugRenderscript': NO_SOURCE, + ':santa-tracker:compileDebugShaders': FROM_CACHE, + ':santa-tracker:compileDebugSources': UP_TO_DATE, + ':santa-tracker:createDebugCompatibleScreenManifests': FROM_CACHE, + ':santa-tracker:dexBuilderDebug': FROM_CACHE, + ':santa-tracker:extractDeepLinksDebug': FROM_CACHE, + ':santa-tracker:generateDebugAssets': UP_TO_DATE, + ':santa-tracker:generateDebugBuildConfig': FROM_CACHE, + ':santa-tracker:generateDebugFeatureMetadata': FROM_CACHE, + ':santa-tracker:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':santa-tracker:generateDebugResValues': FROM_CACHE, + ':santa-tracker:generateDebugResources': SUCCESS, + ':santa-tracker:handleDebugMicroApk': SUCCESS, + ':santa-tracker:javaPreCompileDebug': FROM_CACHE, + ':santa-tracker:kaptDebugKotlin': SUCCESS, + ':santa-tracker:kaptGenerateStubsDebugKotlin': FROM_CACHE, + ':santa-tracker:mainApkListPersistenceDebug': FROM_CACHE, + ':santa-tracker:mergeDebugAssets': FROM_CACHE, + ':santa-tracker:mergeDebugJavaResource': SUCCESS, + ':santa-tracker:mergeDebugJniLibFolders': FROM_CACHE, + ':santa-tracker:mergeDebugNativeLibs': FROM_CACHE, + ':santa-tracker:mergeDebugResources': FROM_CACHE, + ':santa-tracker:mergeDebugShaders': FROM_CACHE, + ':santa-tracker:mergeExtDexDebug': FROM_CACHE, + ':santa-tracker:mergeLibDexDebug': FROM_CACHE, + ':santa-tracker:mergeProjectDexDebug': FROM_CACHE, + ':santa-tracker:packageDebug': SUCCESS, + ':santa-tracker:preBuild': UP_TO_DATE, + ':santa-tracker:preDebugBuild': FROM_CACHE, + ':santa-tracker:processDebugJavaRes': NO_SOURCE, + ':santa-tracker:processDebugManifest': FROM_CACHE, + ':santa-tracker:processDebugResources': FROM_CACHE, + ':santa-tracker:signingConfigWriterDebug': FROM_CACHE, + ':santa-tracker:stripDebugDebugSymbols': FROM_CACHE, + ':santa-tracker:validateSigningDebug': FROM_CACHE, + ':santa-tracker:writeDebugModuleMetadata': SUCCESS, + ':snowballrun:assembleDebug': SUCCESS, + ':snowballrun:checkDebugDuplicateClasses': FROM_CACHE, + ':snowballrun:compileDebugAidl': NO_SOURCE, + ':snowballrun:compileDebugJavaWithJavac': FROM_CACHE, + ':snowballrun:compileDebugRenderscript': NO_SOURCE, + ':snowballrun:compileDebugShaders': FROM_CACHE, + ':snowballrun:compileDebugSources': UP_TO_DATE, + ':snowballrun:createDebugCompatibleScreenManifests': FROM_CACHE, + ':snowballrun:dexBuilderDebug': FROM_CACHE, + ':snowballrun:extractDeepLinksDebug': FROM_CACHE, + ':snowballrun:featureDebugWriter': SUCCESS, + ':snowballrun:generateDebugAssets': UP_TO_DATE, + ':snowballrun:generateDebugBuildConfig': FROM_CACHE, + ':snowballrun:generateDebugFeatureTransitiveDeps': FROM_CACHE, + ':snowballrun:generateDebugResValues': FROM_CACHE, + ':snowballrun:generateDebugResources': UP_TO_DATE, + ':snowballrun:javaPreCompileDebug': FROM_CACHE, + ':snowballrun:mainApkListPersistenceDebug': FROM_CACHE, + ':snowballrun:mergeDebugAssets': FROM_CACHE, + ':snowballrun:mergeDebugJavaResource': FROM_CACHE, + ':snowballrun:mergeDebugJniLibFolders': FROM_CACHE, + ':snowballrun:mergeDebugNativeLibs': FROM_CACHE, + ':snowballrun:mergeDebugResources': FROM_CACHE, + ':snowballrun:mergeDebugShaders': FROM_CACHE, + ':snowballrun:mergeExtDexDebug': FROM_CACHE, + ':snowballrun:mergeLibDexDebug': FROM_CACHE, + ':snowballrun:mergeProjectDexDebug': FROM_CACHE, + ':snowballrun:packageDebug': SUCCESS, + ':snowballrun:preBuild': UP_TO_DATE, + ':snowballrun:preDebugBuild': UP_TO_DATE, + ':snowballrun:processDebugJavaRes': NO_SOURCE, + ':snowballrun:processDebugManifest': FROM_CACHE, + ':snowballrun:processDebugResources': FROM_CACHE, + ':snowballrun:stripDebugDebugSymbols': FROM_CACHE, + ':tracker:assembleDebug': SUCCESS, + ':tracker:bundleDebugAar': SUCCESS, + ':tracker:bundleLibCompileDebug': SUCCESS, + ':tracker:bundleLibResDebug': SUCCESS, + ':tracker:bundleLibRuntimeDebug': SUCCESS, + ':tracker:compileDebugAidl': NO_SOURCE, + ':tracker:compileDebugJavaWithJavac': SUCCESS, + ':tracker:compileDebugKotlin': FROM_CACHE, + ':tracker:compileDebugLibraryResources': FROM_CACHE, + ':tracker:compileDebugRenderscript': NO_SOURCE, + ':tracker:compileDebugShaders': FROM_CACHE, + ':tracker:compileDebugSources': SUCCESS, + ':tracker:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, + ':tracker:copyDebugJniLibsProjectOnly': FROM_CACHE, + ':tracker:extractDebugAnnotations': FROM_CACHE, + ':tracker:extractDeepLinksDebug': FROM_CACHE, + ':tracker:generateDebugAssets': UP_TO_DATE, + ':tracker:generateDebugBuildConfig': FROM_CACHE, + ':tracker:generateDebugRFile': FROM_CACHE, + ':tracker:generateDebugResValues': FROM_CACHE, + ':tracker:generateDebugResources': UP_TO_DATE, + ':tracker:javaPreCompileDebug': FROM_CACHE, + ':tracker:kaptDebugKotlin': SUCCESS, + ':tracker:kaptGenerateStubsDebugKotlin': SUCCESS, + ':tracker:mergeDebugConsumerProguardFiles': SUCCESS, + ':tracker:mergeDebugGeneratedProguardFiles': SUCCESS, + ':tracker:mergeDebugJavaResource': SUCCESS, + ':tracker:mergeDebugJniLibFolders': FROM_CACHE, + ':tracker:mergeDebugNativeLibs': FROM_CACHE, + ':tracker:mergeDebugResources': FROM_CACHE, + ':tracker:mergeDebugShaders': FROM_CACHE, + ':tracker:packageDebugAssets': FROM_CACHE, + ':tracker:packageDebugRenderscript': NO_SOURCE, + ':tracker:packageDebugResources': FROM_CACHE, + ':tracker:parseDebugLocalResources': FROM_CACHE, + ':tracker:preBuild': UP_TO_DATE, + ':tracker:preDebugBuild': UP_TO_DATE, + ':tracker:prepareLintJarForPublish': SUCCESS, + ':tracker:processDebugJavaRes': NO_SOURCE, + ':tracker:processDebugManifest': FROM_CACHE, + ':tracker:stripDebugDebugSymbols': FROM_CACHE, + ':tracker:syncDebugLibJars': SUCCESS, + ':wearable:assembleDebug': SUCCESS, + ':wearable:checkDebugDuplicateClasses': FROM_CACHE, + ':wearable:compileDebugAidl': NO_SOURCE, + ':wearable:compileDebugJavaWithJavac': FROM_CACHE, + ':wearable:compileDebugKotlin': FROM_CACHE, + ':wearable:compileDebugRenderscript': NO_SOURCE, + ':wearable:compileDebugShaders': FROM_CACHE, + ':wearable:compileDebugSources': UP_TO_DATE, + ':wearable:createDebugCompatibleScreenManifests': FROM_CACHE, + ':wearable:dexBuilderDebug': FROM_CACHE, + ':wearable:extractDeepLinksDebug': FROM_CACHE, + ':wearable:generateDebugAssets': UP_TO_DATE, + ':wearable:generateDebugBuildConfig': FROM_CACHE, + ':wearable:generateDebugResValues': FROM_CACHE, + ':wearable:generateDebugResources': UP_TO_DATE, + ':wearable:javaPreCompileDebug': FROM_CACHE, + ':wearable:kaptDebugKotlin': SUCCESS, + ':wearable:kaptGenerateStubsDebugKotlin': FROM_CACHE, + ':wearable:mainApkListPersistenceDebug': FROM_CACHE, + ':wearable:mergeDebugAssets': FROM_CACHE, + ':wearable:mergeDebugJavaResource': SUCCESS, + ':wearable:mergeDebugJniLibFolders': FROM_CACHE, + ':wearable:mergeDebugNativeLibs': FROM_CACHE, + ':wearable:mergeDebugResources': FROM_CACHE, + ':wearable:mergeDebugShaders': FROM_CACHE, + ':wearable:mergeExtDexDebug': FROM_CACHE, + ':wearable:mergeLibDexDebug': FROM_CACHE, + ':wearable:mergeProjectDexDebug': FROM_CACHE, + ':wearable:packageDebug': SUCCESS, + ':wearable:preBuild': UP_TO_DATE, + ':wearable:preDebugBuild': UP_TO_DATE, + ':wearable:processDebugJavaRes': NO_SOURCE, + ':wearable:processDebugManifest': FROM_CACHE, + ':wearable:processDebugResources': FROM_CACHE, + ':wearable:stripDebugDebugSymbols': FROM_CACHE, + ':wearable:validateSigningDebug': FROM_CACHE, + ] +} diff --git a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AndroidSantaTrackerSmokeTest.groovy b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AndroidSantaTrackerSmokeTest.groovy index 6cd64a803220..fe0c5001e91a 100644 --- a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AndroidSantaTrackerSmokeTest.groovy +++ b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/AndroidSantaTrackerSmokeTest.groovy @@ -16,698 +16,76 @@ package org.gradle.smoketests -import org.gradle.integtests.fixtures.ToBeFixedForInstantExecution -import org.gradle.integtests.fixtures.daemon.DaemonLogsAnalyzer -import org.gradle.internal.scan.config.fixtures.GradleEnterprisePluginSettingsFixture +import org.gradle.integtests.fixtures.UnsupportedWithInstantExecution import org.gradle.profiler.mutations.ApplyNonAbiChangeToJavaSourceFileMutator -import org.gradle.test.fixtures.file.TestFile -import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider -import org.gradle.testkit.runner.BuildResult -import org.gradle.testkit.runner.TaskOutcome -import org.gradle.testkit.runner.internal.ToolingApiGradleExecutor -import org.gradle.util.GradleVersion import org.gradle.util.Requires import org.gradle.util.TestPrecondition -import org.junit.Rule +import spock.lang.Unroll -import static org.gradle.testkit.runner.TaskOutcome.FROM_CACHE -import static org.gradle.testkit.runner.TaskOutcome.NO_SOURCE import static org.gradle.testkit.runner.TaskOutcome.SUCCESS -import static org.gradle.testkit.runner.TaskOutcome.UP_TO_DATE -@Requires(TestPrecondition.JDK11_OR_EARLIER) -class AndroidSantaTrackerSmokeTest extends AbstractSmokeTest { - @Rule - TestNameTestDirectoryProvider temporaryFolder - TestFile homeDir - - def setup() { - homeDir = temporaryFolder.createDir("test-kit-home") - } - @ToBeFixedForInstantExecution - def "check deprecation warnings produced by building Santa Tracker"() { - def checkoutDir = temporaryFolder.createDir ("checkout") - setupCopyOfSantaTracker(checkoutDir) - - def result = buildLocation(checkoutDir) +@Requires(TestPrecondition.JDK11_OR_EARLIER) +class AndroidSantaTrackerSmokeTest extends AbstractAndroidSantaTrackerSmokeTest { - expect: - expectDeprecationWarnings(result, - "The configuration :detachedConfiguration1 was resolved without accessing the project in a safe manner. This may happen when a configuration is resolved from a different project. This behaviour has been deprecated and is scheduled to be removed in Gradle 7.0. See https://docs.gradle.org/${GradleVersion.current().version}/userguide/viewing_debugging_dependencies.html#sub:resolving-unsafe-configuration-resolution-errors for more details.", - "The configuration :detachedConfiguration10 was resolved without accessing the project in a safe manner. This may happen when a configuration is resolved from a different project. This behaviour has been deprecated and is scheduled to be removed in Gradle 7.0. See https://docs.gradle.org/${GradleVersion.current().version}/userguide/viewing_debugging_dependencies.html#sub:resolving-unsafe-configuration-resolution-errors for more details.", - "The configuration :detachedConfiguration11 was resolved without accessing the project in a safe manner. This may happen when a configuration is resolved from a different project. This behaviour has been deprecated and is scheduled to be removed in Gradle 7.0. See https://docs.gradle.org/${GradleVersion.current().version}/userguide/viewing_debugging_dependencies.html#sub:resolving-unsafe-configuration-resolution-errors for more details.", - "The configuration :detachedConfiguration12 was resolved without accessing the project in a safe manner. This may happen when a configuration is resolved from a different project. This behaviour has been deprecated and is scheduled to be removed in Gradle 7.0. See https://docs.gradle.org/${GradleVersion.current().version}/userguide/viewing_debugging_dependencies.html#sub:resolving-unsafe-configuration-resolution-errors for more details.", - "The configuration :detachedConfiguration13 was resolved without accessing the project in a safe manner. This may happen when a configuration is resolved from a different project. This behaviour has been deprecated and is scheduled to be removed in Gradle 7.0. See https://docs.gradle.org/${GradleVersion.current().version}/userguide/viewing_debugging_dependencies.html#sub:resolving-unsafe-configuration-resolution-errors for more details.", - "The configuration :detachedConfiguration14 was resolved without accessing the project in a safe manner. This may happen when a configuration is resolved from a different project. This behaviour has been deprecated and is scheduled to be removed in Gradle 7.0. See https://docs.gradle.org/${GradleVersion.current().version}/userguide/viewing_debugging_dependencies.html#sub:resolving-unsafe-configuration-resolution-errors for more details.", - "The configuration :detachedConfiguration15 was resolved without accessing the project in a safe manner. This may happen when a configuration is resolved from a different project. This behaviour has been deprecated and is scheduled to be removed in Gradle 7.0. See https://docs.gradle.org/${GradleVersion.current().version}/userguide/viewing_debugging_dependencies.html#sub:resolving-unsafe-configuration-resolution-errors for more details.", - "The configuration :detachedConfiguration2 was resolved without accessing the project in a safe manner. This may happen when a configuration is resolved from a different project. This behaviour has been deprecated and is scheduled to be removed in Gradle 7.0. See https://docs.gradle.org/${GradleVersion.current().version}/userguide/viewing_debugging_dependencies.html#sub:resolving-unsafe-configuration-resolution-errors for more details.", - "The configuration :detachedConfiguration3 was resolved without accessing the project in a safe manner. This may happen when a configuration is resolved from a different project. This behaviour has been deprecated and is scheduled to be removed in Gradle 7.0. See https://docs.gradle.org/${GradleVersion.current().version}/userguide/viewing_debugging_dependencies.html#sub:resolving-unsafe-configuration-resolution-errors for more details.", - "The configuration :detachedConfiguration4 was resolved without accessing the project in a safe manner. This may happen when a configuration is resolved from a different project. This behaviour has been deprecated and is scheduled to be removed in Gradle 7.0. See https://docs.gradle.org/${GradleVersion.current().version}/userguide/viewing_debugging_dependencies.html#sub:resolving-unsafe-configuration-resolution-errors for more details.", - "The configuration :detachedConfiguration5 was resolved without accessing the project in a safe manner. This may happen when a configuration is resolved from a different project. This behaviour has been deprecated and is scheduled to be removed in Gradle 7.0. See https://docs.gradle.org/${GradleVersion.current().version}/userguide/viewing_debugging_dependencies.html#sub:resolving-unsafe-configuration-resolution-errors for more details.", - "The configuration :detachedConfiguration6 was resolved without accessing the project in a safe manner. This may happen when a configuration is resolved from a different project. This behaviour has been deprecated and is scheduled to be removed in Gradle 7.0. See https://docs.gradle.org/${GradleVersion.current().version}/userguide/viewing_debugging_dependencies.html#sub:resolving-unsafe-configuration-resolution-errors for more details.", - "The configuration :detachedConfiguration7 was resolved without accessing the project in a safe manner. This may happen when a configuration is resolved from a different project. This behaviour has been deprecated and is scheduled to be removed in Gradle 7.0. See https://docs.gradle.org/${GradleVersion.current().version}/userguide/viewing_debugging_dependencies.html#sub:resolving-unsafe-configuration-resolution-errors for more details.", - "The configuration :detachedConfiguration8 was resolved without accessing the project in a safe manner. This may happen when a configuration is resolved from a different project. This behaviour has been deprecated and is scheduled to be removed in Gradle 7.0. See https://docs.gradle.org/${GradleVersion.current().version}/userguide/viewing_debugging_dependencies.html#sub:resolving-unsafe-configuration-resolution-errors for more details.", - "The configuration :detachedConfiguration9 was resolved without accessing the project in a safe manner. This may happen when a configuration is resolved from a different project. This behaviour has been deprecated and is scheduled to be removed in Gradle 7.0. See https://docs.gradle.org/${GradleVersion.current().version}/userguide/viewing_debugging_dependencies.html#sub:resolving-unsafe-configuration-resolution-errors for more details.", - ) - } + @Unroll + @UnsupportedWithInstantExecution(iterationMatchers = AGP_3_ITERATION_MATCHER) + def "check deprecation warnings produced by building Santa Tracker Java (agp=#agpVersion)"() { - @ToBeFixedForInstantExecution - def "can cache Santa Tracker Android application"() { - def originalDir = temporaryFolder.createDir ("original") - def relocatedDir = temporaryFolder.createDir("relocated") + given: + def checkoutDir = temporaryFolder.createDir("checkout") + setupCopyOfSantaTracker(checkoutDir, 'Java', agpVersion) - setupCopyOfSantaTracker(originalDir) - setupCopyOfSantaTracker(relocatedDir) + when: + def result = buildLocation(checkoutDir, agpVersion) - buildLocation(originalDir) - BuildResult relocatedResult = buildLocation(relocatedDir) + then: + if (agpVersion.startsWith('3.6')) { + expectDeprecationWarnings(result, + "Internal API constructor DefaultDomainObjectSet(Class) has been deprecated. This is scheduled to be removed in Gradle 7.0. Please use ObjectFactory.domainObjectSet(Class) instead." + ) + } else { + expectNoDeprecationWarnings(result) + } + assertInstantExecutionStateStored() - expect: - verify(relocatedResult, EXPECTED_RESULTS) + where: + agpVersion << TESTED_AGP_VERSIONS } - @ToBeFixedForInstantExecution - def "incremental Java compilation works for Santa Tracker"() { - def checkoutDir = temporaryFolder.createDir ("checkout") - setupCopyOfSantaTracker(checkoutDir) + @Unroll + @UnsupportedWithInstantExecution(iterationMatchers = AGP_3_ITERATION_MATCHER) + def "incremental Java compilation works for Santa Tracker Java (agp=#agpVersion)"() { - def pathToClass = "com/google/android/apps/santatracker/tracker/ui/BottomSheetBehavior" - def fileToChange = checkoutDir.file("tracker/src/main/java/${pathToClass}.java") - def compiledClassFile = checkoutDir.file("tracker/build/intermediates/javac/debug/classes/${pathToClass}.class") + given: + def checkoutDir = temporaryFolder.createDir("checkout") + setupCopyOfSantaTracker(checkoutDir, 'Java', agpVersion) + + and: + def pathToClass = "com/google/android/apps/santatracker/map/BottomSheetBehavior" + def fileToChange = checkoutDir.file("santa-tracker/src/main/java/${pathToClass}.java") + def compiledClassFile = checkoutDir.file("santa-tracker/build/intermediates/javac/developmentDebug/classes/${pathToClass}.class") def nonAbiChangeMutator = new ApplyNonAbiChangeToJavaSourceFileMutator(fileToChange) when: - def result = buildLocation(checkoutDir) + def result = buildLocation(checkoutDir, agpVersion) def md5Before = compiledClassFile.md5Hash + then: - result.task(":tracker:compileDebugJavaWithJavac").outcome == SUCCESS + result.task(":santa-tracker:compileDevelopmentDebugJavaWithJavac").outcome == SUCCESS + assertInstantExecutionStateStored() when: nonAbiChangeMutator.beforeBuild() - buildLocation(checkoutDir) + buildLocation(checkoutDir, agpVersion) def md5After = compiledClassFile.md5Hash + then: - result.task(":tracker:compileDebugJavaWithJavac").outcome == SUCCESS + result.task(":santa-tracker:compileDevelopmentDebugJavaWithJavac").outcome == SUCCESS + assertInstantExecutionStateLoaded() md5After != md5Before - } - - private void setupCopyOfSantaTracker(TestFile targetDir) { - copyRemoteProject("santaTracker", targetDir) - GradleEnterprisePluginSettingsFixture.applyEnterprisePlugin(targetDir.file("settings.gradle")) - } - - private BuildResult buildLocation(File projectDir) { - runner("assembleDebug") - .withProjectDir(projectDir) - .withTestKitDir(homeDir) - .forwardOutput() - .build() - } - - private static boolean verify(BuildResult result, Map outcomes) { - println "> Expecting ${outcomes.size()} tasks with outcomes:" - outcomes.values().groupBy { it }.sort().forEach { outcome, instances -> println "> - $outcome: ${instances.size()}" } - - def outcomesWithMatchingTasks = outcomes.findAll { result.task(it.key) } - def hasMatchingTasks = outcomesWithMatchingTasks.size() == outcomes.size() && outcomesWithMatchingTasks.size() == result.tasks.size() - if (!hasMatchingTasks) { - println "> Tasks missing: " + (outcomes.findAll { !outcomesWithMatchingTasks.keySet().contains(it.key) }) - println "> Tasks in surplus: " + (result.tasks.findAll { !outcomesWithMatchingTasks.keySet().contains(it.path) }) - println "> Updated definitions:" - result.tasks - .toSorted { a, b -> a.path <=> b.path } - .forEach { task -> - println "'${task.path}': ${task.outcome}" - } - } - - boolean allOutcomesMatched = true - outcomesWithMatchingTasks.each { taskName, expectedOutcome -> - def taskOutcome = result.task(taskName)?.outcome - if (taskOutcome != expectedOutcome) { - println "> Task '$taskName' was $taskOutcome but should have been $expectedOutcome" - allOutcomesMatched = false - } - } - return hasMatchingTasks && allOutcomesMatched - } - - private static final EXPECTED_RESULTS = [ - ':cityquiz:assembleDebug': SUCCESS, - ':cityquiz:checkDebugDuplicateClasses': FROM_CACHE, - ':cityquiz:compileDebugAidl': NO_SOURCE, - ':cityquiz:compileDebugJavaWithJavac': FROM_CACHE, - ':cityquiz:compileDebugKotlin': FROM_CACHE, - ':cityquiz:compileDebugRenderscript': NO_SOURCE, - ':cityquiz:compileDebugShaders': FROM_CACHE, - ':cityquiz:compileDebugSources': UP_TO_DATE, - ':cityquiz:createDebugCompatibleScreenManifests': FROM_CACHE, - ':cityquiz:dexBuilderDebug': FROM_CACHE, - ':cityquiz:extractDeepLinksDebug': FROM_CACHE, - ':cityquiz:featureDebugWriter': SUCCESS, - ':cityquiz:generateDebugAssets': UP_TO_DATE, - ':cityquiz:generateDebugBuildConfig': FROM_CACHE, - ':cityquiz:generateDebugFeatureTransitiveDeps': FROM_CACHE, - ':cityquiz:generateDebugResValues': FROM_CACHE, - ':cityquiz:generateDebugResources': UP_TO_DATE, - ':cityquiz:javaPreCompileDebug': FROM_CACHE, - ':cityquiz:mainApkListPersistenceDebug': FROM_CACHE, - ':cityquiz:mergeDebugAssets': FROM_CACHE, - ':cityquiz:mergeDebugJavaResource': SUCCESS, - ':cityquiz:mergeDebugJniLibFolders': FROM_CACHE, - ':cityquiz:mergeDebugNativeLibs': FROM_CACHE, - ':cityquiz:mergeDebugResources': FROM_CACHE, - ':cityquiz:mergeDebugShaders': FROM_CACHE, - ':cityquiz:mergeExtDexDebug': FROM_CACHE, - ':cityquiz:mergeLibDexDebug': FROM_CACHE, - ':cityquiz:mergeProjectDexDebug': FROM_CACHE, - ':cityquiz:packageDebug': SUCCESS, - ':cityquiz:preBuild': UP_TO_DATE, - ':cityquiz:preDebugBuild': UP_TO_DATE, - ':cityquiz:processDebugJavaRes': NO_SOURCE, - ':cityquiz:processDebugManifest': FROM_CACHE, - ':cityquiz:processDebugResources': FROM_CACHE, - ':cityquiz:stripDebugDebugSymbols': FROM_CACHE, - ':common:assembleDebug': SUCCESS, - ':common:bundleDebugAar': SUCCESS, - ':common:bundleLibCompileDebug': SUCCESS, - ':common:bundleLibResDebug': SUCCESS, - ':common:bundleLibRuntimeDebug': SUCCESS, - ':common:compileDebugAidl': NO_SOURCE, - ':common:compileDebugJavaWithJavac': FROM_CACHE, - ':common:compileDebugKotlin': FROM_CACHE, - ':common:compileDebugLibraryResources': FROM_CACHE, - ':common:compileDebugRenderscript': NO_SOURCE, - ':common:compileDebugShaders': FROM_CACHE, - ':common:compileDebugSources': UP_TO_DATE, - ':common:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, - ':common:copyDebugJniLibsProjectOnly': FROM_CACHE, - ':common:createFullJarDebug': FROM_CACHE, - ':common:extractDebugAnnotations': FROM_CACHE, - ':common:extractDeepLinksDebug': FROM_CACHE, - ':common:generateDebugAssets': UP_TO_DATE, - ':common:generateDebugBuildConfig': FROM_CACHE, - ':common:generateDebugRFile': FROM_CACHE, - ':common:generateDebugResValues': FROM_CACHE, - ':common:generateDebugResources': UP_TO_DATE, - ':common:javaPreCompileDebug': FROM_CACHE, - ':common:mergeDebugConsumerProguardFiles': SUCCESS, - ':common:mergeDebugGeneratedProguardFiles': SUCCESS, - ':common:mergeDebugJavaResource': SUCCESS, - ':common:mergeDebugJniLibFolders': FROM_CACHE, - ':common:mergeDebugNativeLibs': FROM_CACHE, - ':common:mergeDebugShaders': FROM_CACHE, - ':common:packageDebugAssets': FROM_CACHE, - ':common:packageDebugRenderscript': NO_SOURCE, - ':common:packageDebugResources': FROM_CACHE, - ':common:parseDebugLocalResources': FROM_CACHE, - ':common:preBuild': UP_TO_DATE, - ':common:preDebugBuild': UP_TO_DATE, - ':common:prepareLintJarForPublish': SUCCESS, - ':common:processDebugJavaRes': NO_SOURCE, - ':common:processDebugManifest': FROM_CACHE, - ':common:stripDebugDebugSymbols': FROM_CACHE, - ':common:syncDebugLibJars': SUCCESS, - ':dasherdancer:assembleDebug': SUCCESS, - ':dasherdancer:checkDebugDuplicateClasses': FROM_CACHE, - ':dasherdancer:compileDebugAidl': NO_SOURCE, - ':dasherdancer:compileDebugJavaWithJavac': FROM_CACHE, - ':dasherdancer:compileDebugKotlin': FROM_CACHE, - ':dasherdancer:compileDebugRenderscript': NO_SOURCE, - ':dasherdancer:compileDebugShaders': FROM_CACHE, - ':dasherdancer:compileDebugSources': UP_TO_DATE, - ':dasherdancer:createDebugCompatibleScreenManifests': FROM_CACHE, - ':dasherdancer:dexBuilderDebug': FROM_CACHE, - ':dasherdancer:extractDeepLinksDebug': FROM_CACHE, - ':dasherdancer:featureDebugWriter': SUCCESS, - ':dasherdancer:generateDebugAssets': UP_TO_DATE, - ':dasherdancer:generateDebugBuildConfig': FROM_CACHE, - ':dasherdancer:generateDebugFeatureTransitiveDeps': FROM_CACHE, - ':dasherdancer:generateDebugResValues': FROM_CACHE, - ':dasherdancer:generateDebugResources': UP_TO_DATE, - ':dasherdancer:javaPreCompileDebug': FROM_CACHE, - ':dasherdancer:mainApkListPersistenceDebug': FROM_CACHE, - ':dasherdancer:mergeDebugAssets': FROM_CACHE, - ':dasherdancer:mergeDebugJavaResource': SUCCESS, - ':dasherdancer:mergeDebugJniLibFolders': FROM_CACHE, - ':dasherdancer:mergeDebugNativeLibs': FROM_CACHE, - ':dasherdancer:mergeDebugResources': FROM_CACHE, - ':dasherdancer:mergeDebugShaders': FROM_CACHE, - ':dasherdancer:mergeExtDexDebug': FROM_CACHE, - ':dasherdancer:mergeLibDexDebug': FROM_CACHE, - ':dasherdancer:mergeProjectDexDebug': FROM_CACHE, - ':dasherdancer:packageDebug': SUCCESS, - ':dasherdancer:preBuild': UP_TO_DATE, - ':dasherdancer:preDebugBuild': UP_TO_DATE, - ':dasherdancer:processDebugJavaRes': NO_SOURCE, - ':dasherdancer:processDebugManifest': FROM_CACHE, - ':dasherdancer:processDebugResources': FROM_CACHE, - ':dasherdancer:stripDebugDebugSymbols': FROM_CACHE, - ':doodles-lib:assembleDebug': SUCCESS, - ':doodles-lib:bundleDebugAar': SUCCESS, - ':doodles-lib:bundleLibCompileDebug': SUCCESS, - ':doodles-lib:bundleLibResDebug': SUCCESS, - ':doodles-lib:bundleLibRuntimeDebug': SUCCESS, - ':doodles-lib:compileDebugAidl': NO_SOURCE, - ':doodles-lib:compileDebugJavaWithJavac': FROM_CACHE, - ':doodles-lib:compileDebugLibraryResources': FROM_CACHE, - ':doodles-lib:compileDebugRenderscript': NO_SOURCE, - ':doodles-lib:compileDebugShaders': FROM_CACHE, - ':doodles-lib:compileDebugSources': UP_TO_DATE, - ':doodles-lib:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, - ':doodles-lib:copyDebugJniLibsProjectOnly': FROM_CACHE, - ':doodles-lib:createFullJarDebug': FROM_CACHE, - ':doodles-lib:extractDebugAnnotations': FROM_CACHE, - ':doodles-lib:extractDeepLinksDebug': FROM_CACHE, - ':doodles-lib:generateDebugAssets': UP_TO_DATE, - ':doodles-lib:generateDebugBuildConfig': FROM_CACHE, - ':doodles-lib:generateDebugRFile': FROM_CACHE, - ':doodles-lib:generateDebugResValues': FROM_CACHE, - ':doodles-lib:generateDebugResources': UP_TO_DATE, - ':doodles-lib:javaPreCompileDebug': FROM_CACHE, - ':doodles-lib:mergeDebugConsumerProguardFiles': SUCCESS, - ':doodles-lib:mergeDebugGeneratedProguardFiles': SUCCESS, - ':doodles-lib:mergeDebugJavaResource': FROM_CACHE, - ':doodles-lib:mergeDebugJniLibFolders': FROM_CACHE, - ':doodles-lib:mergeDebugNativeLibs': FROM_CACHE, - ':doodles-lib:mergeDebugShaders': FROM_CACHE, - ':doodles-lib:packageDebugAssets': FROM_CACHE, - ':doodles-lib:packageDebugRenderscript': NO_SOURCE, - ':doodles-lib:packageDebugResources': FROM_CACHE, - ':doodles-lib:parseDebugLocalResources': FROM_CACHE, - ':doodles-lib:preBuild': UP_TO_DATE, - ':doodles-lib:preDebugBuild': UP_TO_DATE, - ':doodles-lib:prepareLintJarForPublish': SUCCESS, - ':doodles-lib:processDebugJavaRes': NO_SOURCE, - ':doodles-lib:processDebugManifest': FROM_CACHE, - ':doodles-lib:stripDebugDebugSymbols': FROM_CACHE, - ':doodles-lib:syncDebugLibJars': FROM_CACHE, - ':gumball:assembleDebug': SUCCESS, - ':gumball:checkDebugDuplicateClasses': FROM_CACHE, - ':gumball:compileDebugAidl': NO_SOURCE, - ':gumball:compileDebugJavaWithJavac': FROM_CACHE, - ':gumball:compileDebugRenderscript': NO_SOURCE, - ':gumball:compileDebugShaders': FROM_CACHE, - ':gumball:compileDebugSources': UP_TO_DATE, - ':gumball:createDebugCompatibleScreenManifests': FROM_CACHE, - ':gumball:dexBuilderDebug': FROM_CACHE, - ':gumball:extractDeepLinksDebug': FROM_CACHE, - ':gumball:featureDebugWriter': SUCCESS, - ':gumball:generateDebugAssets': UP_TO_DATE, - ':gumball:generateDebugBuildConfig': FROM_CACHE, - ':gumball:generateDebugFeatureTransitiveDeps': FROM_CACHE, - ':gumball:generateDebugResValues': FROM_CACHE, - ':gumball:generateDebugResources': UP_TO_DATE, - ':gumball:javaPreCompileDebug': FROM_CACHE, - ':gumball:mainApkListPersistenceDebug': FROM_CACHE, - ':gumball:mergeDebugAssets': FROM_CACHE, - ':gumball:mergeDebugJavaResource': FROM_CACHE, - ':gumball:mergeDebugJniLibFolders': FROM_CACHE, - ':gumball:mergeDebugNativeLibs': FROM_CACHE, - ':gumball:mergeDebugResources': FROM_CACHE, - ':gumball:mergeDebugShaders': FROM_CACHE, - ':gumball:mergeExtDexDebug': FROM_CACHE, - ':gumball:mergeLibDexDebug': FROM_CACHE, - ':gumball:mergeProjectDexDebug': FROM_CACHE, - ':gumball:packageDebug': SUCCESS, - ':gumball:preBuild': UP_TO_DATE, - ':gumball:preDebugBuild': UP_TO_DATE, - ':gumball:processDebugJavaRes': NO_SOURCE, - ':gumball:processDebugManifest': FROM_CACHE, - ':gumball:processDebugResources': FROM_CACHE, - ':gumball:stripDebugDebugSymbols': FROM_CACHE, - ':jetpack:assembleDebug': SUCCESS, - ':jetpack:checkDebugDuplicateClasses': FROM_CACHE, - ':jetpack:compileDebugAidl': NO_SOURCE, - ':jetpack:compileDebugJavaWithJavac': FROM_CACHE, - ':jetpack:compileDebugKotlin': FROM_CACHE, - ':jetpack:compileDebugRenderscript': NO_SOURCE, - ':jetpack:compileDebugShaders': FROM_CACHE, - ':jetpack:compileDebugSources': UP_TO_DATE, - ':jetpack:createDebugCompatibleScreenManifests': FROM_CACHE, - ':jetpack:dexBuilderDebug': FROM_CACHE, - ':jetpack:extractDeepLinksDebug': FROM_CACHE, - ':jetpack:featureDebugWriter': SUCCESS, - ':jetpack:generateDebugAssets': UP_TO_DATE, - ':jetpack:generateDebugBuildConfig': FROM_CACHE, - ':jetpack:generateDebugFeatureTransitiveDeps': FROM_CACHE, - ':jetpack:generateDebugResValues': FROM_CACHE, - ':jetpack:generateDebugResources': UP_TO_DATE, - ':jetpack:javaPreCompileDebug': FROM_CACHE, - ':jetpack:mainApkListPersistenceDebug': FROM_CACHE, - ':jetpack:mergeDebugAssets': FROM_CACHE, - ':jetpack:mergeDebugJavaResource': SUCCESS, - ':jetpack:mergeDebugJniLibFolders': FROM_CACHE, - ':jetpack:mergeDebugNativeLibs': FROM_CACHE, - ':jetpack:mergeDebugResources': FROM_CACHE, - ':jetpack:mergeDebugShaders': FROM_CACHE, - ':jetpack:mergeExtDexDebug': FROM_CACHE, - ':jetpack:mergeLibDexDebug': FROM_CACHE, - ':jetpack:mergeProjectDexDebug': FROM_CACHE, - ':jetpack:packageDebug': SUCCESS, - ':jetpack:preBuild': UP_TO_DATE, - ':jetpack:preDebugBuild': UP_TO_DATE, - ':jetpack:processDebugJavaRes': NO_SOURCE, - ':jetpack:processDebugManifest': FROM_CACHE, - ':jetpack:processDebugResources': FROM_CACHE, - ':jetpack:stripDebugDebugSymbols': FROM_CACHE, - ':memory:assembleDebug': SUCCESS, - ':memory:checkDebugDuplicateClasses': FROM_CACHE, - ':memory:compileDebugAidl': NO_SOURCE, - ':memory:compileDebugJavaWithJavac': FROM_CACHE, - ':memory:compileDebugRenderscript': NO_SOURCE, - ':memory:compileDebugShaders': FROM_CACHE, - ':memory:compileDebugSources': UP_TO_DATE, - ':memory:createDebugCompatibleScreenManifests': FROM_CACHE, - ':memory:dexBuilderDebug': FROM_CACHE, - ':memory:extractDeepLinksDebug': FROM_CACHE, - ':memory:featureDebugWriter': SUCCESS, - ':memory:generateDebugAssets': UP_TO_DATE, - ':memory:generateDebugBuildConfig': FROM_CACHE, - ':memory:generateDebugFeatureTransitiveDeps': FROM_CACHE, - ':memory:generateDebugResValues': FROM_CACHE, - ':memory:generateDebugResources': UP_TO_DATE, - ':memory:javaPreCompileDebug': FROM_CACHE, - ':memory:mainApkListPersistenceDebug': FROM_CACHE, - ':memory:mergeDebugAssets': FROM_CACHE, - ':memory:mergeDebugJavaResource': FROM_CACHE, - ':memory:mergeDebugJniLibFolders': FROM_CACHE, - ':memory:mergeDebugNativeLibs': FROM_CACHE, - ':memory:mergeDebugResources': FROM_CACHE, - ':memory:mergeDebugShaders': FROM_CACHE, - ':memory:mergeExtDexDebug': FROM_CACHE, - ':memory:mergeLibDexDebug': FROM_CACHE, - ':memory:mergeProjectDexDebug': FROM_CACHE, - ':memory:packageDebug': SUCCESS, - ':memory:preBuild': UP_TO_DATE, - ':memory:preDebugBuild': UP_TO_DATE, - ':memory:processDebugJavaRes': NO_SOURCE, - ':memory:processDebugManifest': FROM_CACHE, - ':memory:processDebugResources': FROM_CACHE, - ':memory:stripDebugDebugSymbols': FROM_CACHE, - ':penguinswim:assembleDebug': SUCCESS, - ':penguinswim:checkDebugDuplicateClasses': FROM_CACHE, - ':penguinswim:compileDebugAidl': NO_SOURCE, - ':penguinswim:compileDebugJavaWithJavac': FROM_CACHE, - ':penguinswim:compileDebugRenderscript': NO_SOURCE, - ':penguinswim:compileDebugShaders': FROM_CACHE, - ':penguinswim:compileDebugSources': UP_TO_DATE, - ':penguinswim:createDebugCompatibleScreenManifests': FROM_CACHE, - ':penguinswim:dexBuilderDebug': FROM_CACHE, - ':penguinswim:extractDeepLinksDebug': FROM_CACHE, - ':penguinswim:featureDebugWriter': SUCCESS, - ':penguinswim:generateDebugAssets': UP_TO_DATE, - ':penguinswim:generateDebugBuildConfig': FROM_CACHE, - ':penguinswim:generateDebugFeatureTransitiveDeps': FROM_CACHE, - ':penguinswim:generateDebugResValues': FROM_CACHE, - ':penguinswim:generateDebugResources': UP_TO_DATE, - ':penguinswim:javaPreCompileDebug': FROM_CACHE, - ':penguinswim:mainApkListPersistenceDebug': FROM_CACHE, - ':penguinswim:mergeDebugAssets': FROM_CACHE, - ':penguinswim:mergeDebugJavaResource': FROM_CACHE, - ':penguinswim:mergeDebugJniLibFolders': FROM_CACHE, - ':penguinswim:mergeDebugNativeLibs': FROM_CACHE, - ':penguinswim:mergeDebugResources': FROM_CACHE, - ':penguinswim:mergeDebugShaders': FROM_CACHE, - ':penguinswim:mergeExtDexDebug': FROM_CACHE, - ':penguinswim:mergeLibDexDebug': FROM_CACHE, - ':penguinswim:mergeProjectDexDebug': FROM_CACHE, - ':penguinswim:packageDebug': SUCCESS, - ':penguinswim:preBuild': UP_TO_DATE, - ':penguinswim:preDebugBuild': UP_TO_DATE, - ':penguinswim:processDebugJavaRes': NO_SOURCE, - ':penguinswim:processDebugManifest': FROM_CACHE, - ':penguinswim:processDebugResources': FROM_CACHE, - ':penguinswim:stripDebugDebugSymbols': FROM_CACHE, - ':playgames:assembleDebug': SUCCESS, - ':playgames:bundleDebugAar': SUCCESS, - ':playgames:bundleLibCompileDebug': SUCCESS, - ':playgames:bundleLibResDebug': SUCCESS, - ':playgames:bundleLibRuntimeDebug': SUCCESS, - ':playgames:compileDebugAidl': NO_SOURCE, - ':playgames:compileDebugJavaWithJavac': FROM_CACHE, - ':playgames:compileDebugLibraryResources': FROM_CACHE, - ':playgames:compileDebugRenderscript': NO_SOURCE, - ':playgames:compileDebugShaders': FROM_CACHE, - ':playgames:compileDebugSources': UP_TO_DATE, - ':playgames:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, - ':playgames:copyDebugJniLibsProjectOnly': FROM_CACHE, - ':playgames:createFullJarDebug': FROM_CACHE, - ':playgames:extractDebugAnnotations': FROM_CACHE, - ':playgames:extractDeepLinksDebug': FROM_CACHE, - ':playgames:generateDebugAssets': UP_TO_DATE, - ':playgames:generateDebugBuildConfig': FROM_CACHE, - ':playgames:generateDebugRFile': FROM_CACHE, - ':playgames:generateDebugResValues': FROM_CACHE, - ':playgames:generateDebugResources': UP_TO_DATE, - ':playgames:javaPreCompileDebug': FROM_CACHE, - ':playgames:mergeDebugConsumerProguardFiles': SUCCESS, - ':playgames:mergeDebugGeneratedProguardFiles': SUCCESS, - ':playgames:mergeDebugJavaResource': FROM_CACHE, - ':playgames:mergeDebugJniLibFolders': FROM_CACHE, - ':playgames:mergeDebugNativeLibs': FROM_CACHE, - ':playgames:mergeDebugShaders': FROM_CACHE, - ':playgames:packageDebugAssets': FROM_CACHE, - ':playgames:packageDebugRenderscript': NO_SOURCE, - ':playgames:packageDebugResources': FROM_CACHE, - ':playgames:parseDebugLocalResources': FROM_CACHE, - ':playgames:preBuild': UP_TO_DATE, - ':playgames:preDebugBuild': UP_TO_DATE, - ':playgames:prepareLintJarForPublish': SUCCESS, - ':playgames:processDebugJavaRes': NO_SOURCE, - ':playgames:processDebugManifest': FROM_CACHE, - ':playgames:stripDebugDebugSymbols': FROM_CACHE, - ':playgames:syncDebugLibJars': FROM_CACHE, - ':presenttoss:assembleDebug': SUCCESS, - ':presenttoss:checkDebugDuplicateClasses': FROM_CACHE, - ':presenttoss:compileDebugAidl': NO_SOURCE, - ':presenttoss:compileDebugJavaWithJavac': FROM_CACHE, - ':presenttoss:compileDebugRenderscript': NO_SOURCE, - ':presenttoss:compileDebugShaders': FROM_CACHE, - ':presenttoss:compileDebugSources': UP_TO_DATE, - ':presenttoss:createDebugCompatibleScreenManifests': FROM_CACHE, - ':presenttoss:dexBuilderDebug': FROM_CACHE, - ':presenttoss:extractDeepLinksDebug': FROM_CACHE, - ':presenttoss:featureDebugWriter': SUCCESS, - ':presenttoss:generateDebugAssets': UP_TO_DATE, - ':presenttoss:generateDebugBuildConfig': FROM_CACHE, - ':presenttoss:generateDebugFeatureTransitiveDeps': FROM_CACHE, - ':presenttoss:generateDebugResValues': FROM_CACHE, - ':presenttoss:generateDebugResources': UP_TO_DATE, - ':presenttoss:javaPreCompileDebug': FROM_CACHE, - ':presenttoss:mainApkListPersistenceDebug': FROM_CACHE, - ':presenttoss:mergeDebugAssets': FROM_CACHE, - ':presenttoss:mergeDebugJavaResource': FROM_CACHE, - ':presenttoss:mergeDebugJniLibFolders': FROM_CACHE, - ':presenttoss:mergeDebugNativeLibs': FROM_CACHE, - ':presenttoss:mergeDebugResources': FROM_CACHE, - ':presenttoss:mergeDebugShaders': FROM_CACHE, - ':presenttoss:mergeExtDexDebug': FROM_CACHE, - ':presenttoss:mergeLibDexDebug': FROM_CACHE, - ':presenttoss:mergeProjectDexDebug': FROM_CACHE, - ':presenttoss:packageDebug': SUCCESS, - ':presenttoss:preBuild': UP_TO_DATE, - ':presenttoss:preDebugBuild': UP_TO_DATE, - ':presenttoss:processDebugJavaRes': NO_SOURCE, - ':presenttoss:processDebugManifest': FROM_CACHE, - ':presenttoss:processDebugResources': FROM_CACHE, - ':presenttoss:stripDebugDebugSymbols': FROM_CACHE, - ':rocketsleigh:assembleDebug': SUCCESS, - ':rocketsleigh:checkDebugDuplicateClasses': FROM_CACHE, - ':rocketsleigh:compileDebugAidl': NO_SOURCE, - ':rocketsleigh:compileDebugJavaWithJavac': FROM_CACHE, - ':rocketsleigh:compileDebugKotlin': FROM_CACHE, - ':rocketsleigh:compileDebugRenderscript': NO_SOURCE, - ':rocketsleigh:compileDebugShaders': FROM_CACHE, - ':rocketsleigh:compileDebugSources': UP_TO_DATE, - ':rocketsleigh:createDebugCompatibleScreenManifests': FROM_CACHE, - ':rocketsleigh:dexBuilderDebug': FROM_CACHE, - ':rocketsleigh:extractDeepLinksDebug': FROM_CACHE, - ':rocketsleigh:featureDebugWriter': SUCCESS, - ':rocketsleigh:generateDebugAssets': UP_TO_DATE, - ':rocketsleigh:generateDebugBuildConfig': FROM_CACHE, - ':rocketsleigh:generateDebugFeatureTransitiveDeps': FROM_CACHE, - ':rocketsleigh:generateDebugResValues': FROM_CACHE, - ':rocketsleigh:generateDebugResources': UP_TO_DATE, - ':rocketsleigh:javaPreCompileDebug': FROM_CACHE, - ':rocketsleigh:mainApkListPersistenceDebug': FROM_CACHE, - ':rocketsleigh:mergeDebugAssets': FROM_CACHE, - ':rocketsleigh:mergeDebugJavaResource': SUCCESS, - ':rocketsleigh:mergeDebugJniLibFolders': FROM_CACHE, - ':rocketsleigh:mergeDebugNativeLibs': FROM_CACHE, - ':rocketsleigh:mergeDebugResources': FROM_CACHE, - ':rocketsleigh:mergeDebugShaders': FROM_CACHE, - ':rocketsleigh:mergeExtDexDebug': FROM_CACHE, - ':rocketsleigh:mergeLibDexDebug': FROM_CACHE, - ':rocketsleigh:mergeProjectDexDebug': FROM_CACHE, - ':rocketsleigh:packageDebug': SUCCESS, - ':rocketsleigh:preBuild': UP_TO_DATE, - ':rocketsleigh:preDebugBuild': UP_TO_DATE, - ':rocketsleigh:processDebugJavaRes': NO_SOURCE, - ':rocketsleigh:processDebugManifest': FROM_CACHE, - ':rocketsleigh:processDebugResources': FROM_CACHE, - ':rocketsleigh:stripDebugDebugSymbols': FROM_CACHE, - ':santa-tracker:assembleDebug': SUCCESS, - ':santa-tracker:bundleDebugClasses': SUCCESS, - ':santa-tracker:checkDebugDuplicateClasses': FROM_CACHE, - ':santa-tracker:checkDebugLibraries': FROM_CACHE, - ':santa-tracker:compileDebugAidl': NO_SOURCE, - ':santa-tracker:compileDebugJavaWithJavac': FROM_CACHE, - ':santa-tracker:compileDebugKotlin': FROM_CACHE, - ':santa-tracker:compileDebugRenderscript': NO_SOURCE, - ':santa-tracker:compileDebugShaders': FROM_CACHE, - ':santa-tracker:compileDebugSources': UP_TO_DATE, - ':santa-tracker:createDebugCompatibleScreenManifests': FROM_CACHE, - ':santa-tracker:dexBuilderDebug': FROM_CACHE, - ':santa-tracker:extractDeepLinksDebug': FROM_CACHE, - ':santa-tracker:generateDebugAssets': UP_TO_DATE, - ':santa-tracker:generateDebugBuildConfig': FROM_CACHE, - ':santa-tracker:generateDebugFeatureMetadata': FROM_CACHE, - ':santa-tracker:generateDebugFeatureTransitiveDeps': FROM_CACHE, - ':santa-tracker:generateDebugResValues': FROM_CACHE, - ':santa-tracker:generateDebugResources': SUCCESS, - ':santa-tracker:handleDebugMicroApk': SUCCESS, - ':santa-tracker:javaPreCompileDebug': FROM_CACHE, - ':santa-tracker:kaptDebugKotlin': SUCCESS, - ':santa-tracker:kaptGenerateStubsDebugKotlin': FROM_CACHE, - ':santa-tracker:mainApkListPersistenceDebug': FROM_CACHE, - ':santa-tracker:mergeDebugAssets': FROM_CACHE, - ':santa-tracker:mergeDebugJavaResource': SUCCESS, - ':santa-tracker:mergeDebugJniLibFolders': FROM_CACHE, - ':santa-tracker:mergeDebugNativeLibs': FROM_CACHE, - ':santa-tracker:mergeDebugResources': FROM_CACHE, - ':santa-tracker:mergeDebugShaders': FROM_CACHE, - ':santa-tracker:mergeExtDexDebug': FROM_CACHE, - ':santa-tracker:mergeLibDexDebug': FROM_CACHE, - ':santa-tracker:mergeProjectDexDebug': FROM_CACHE, - ':santa-tracker:packageDebug': SUCCESS, - ':santa-tracker:preBuild': UP_TO_DATE, - ':santa-tracker:preDebugBuild': FROM_CACHE, - ':santa-tracker:processDebugJavaRes': NO_SOURCE, - ':santa-tracker:processDebugManifest': FROM_CACHE, - ':santa-tracker:processDebugResources': FROM_CACHE, - ':santa-tracker:signingConfigWriterDebug': FROM_CACHE, - ':santa-tracker:stripDebugDebugSymbols': FROM_CACHE, - ':santa-tracker:validateSigningDebug': FROM_CACHE, - ':santa-tracker:writeDebugModuleMetadata': SUCCESS, - ':snowballrun:assembleDebug': SUCCESS, - ':snowballrun:checkDebugDuplicateClasses': FROM_CACHE, - ':snowballrun:compileDebugAidl': NO_SOURCE, - ':snowballrun:compileDebugJavaWithJavac': FROM_CACHE, - ':snowballrun:compileDebugRenderscript': NO_SOURCE, - ':snowballrun:compileDebugShaders': FROM_CACHE, - ':snowballrun:compileDebugSources': UP_TO_DATE, - ':snowballrun:createDebugCompatibleScreenManifests': FROM_CACHE, - ':snowballrun:dexBuilderDebug': FROM_CACHE, - ':snowballrun:extractDeepLinksDebug': FROM_CACHE, - ':snowballrun:featureDebugWriter': SUCCESS, - ':snowballrun:generateDebugAssets': UP_TO_DATE, - ':snowballrun:generateDebugBuildConfig': FROM_CACHE, - ':snowballrun:generateDebugFeatureTransitiveDeps': FROM_CACHE, - ':snowballrun:generateDebugResValues': FROM_CACHE, - ':snowballrun:generateDebugResources': UP_TO_DATE, - ':snowballrun:javaPreCompileDebug': FROM_CACHE, - ':snowballrun:mainApkListPersistenceDebug': FROM_CACHE, - ':snowballrun:mergeDebugAssets': FROM_CACHE, - ':snowballrun:mergeDebugJavaResource': FROM_CACHE, - ':snowballrun:mergeDebugJniLibFolders': FROM_CACHE, - ':snowballrun:mergeDebugNativeLibs': FROM_CACHE, - ':snowballrun:mergeDebugResources': FROM_CACHE, - ':snowballrun:mergeDebugShaders': FROM_CACHE, - ':snowballrun:mergeExtDexDebug': FROM_CACHE, - ':snowballrun:mergeLibDexDebug': FROM_CACHE, - ':snowballrun:mergeProjectDexDebug': FROM_CACHE, - ':snowballrun:packageDebug': SUCCESS, - ':snowballrun:preBuild': UP_TO_DATE, - ':snowballrun:preDebugBuild': UP_TO_DATE, - ':snowballrun:processDebugJavaRes': NO_SOURCE, - ':snowballrun:processDebugManifest': FROM_CACHE, - ':snowballrun:processDebugResources': FROM_CACHE, - ':snowballrun:stripDebugDebugSymbols': FROM_CACHE, - ':tracker:assembleDebug': SUCCESS, - ':tracker:bundleDebugAar': SUCCESS, - ':tracker:bundleLibCompileDebug': SUCCESS, - ':tracker:bundleLibResDebug': SUCCESS, - ':tracker:bundleLibRuntimeDebug': SUCCESS, - ':tracker:compileDebugAidl': NO_SOURCE, - ':tracker:compileDebugJavaWithJavac': SUCCESS, - ':tracker:compileDebugKotlin': FROM_CACHE, - ':tracker:compileDebugLibraryResources': FROM_CACHE, - ':tracker:compileDebugRenderscript': NO_SOURCE, - ':tracker:compileDebugShaders': FROM_CACHE, - ':tracker:compileDebugSources': SUCCESS, - ':tracker:copyDebugJniLibsProjectAndLocalJars': FROM_CACHE, - ':tracker:copyDebugJniLibsProjectOnly': FROM_CACHE, - ':tracker:createFullJarDebug': FROM_CACHE, - ':tracker:extractDebugAnnotations': FROM_CACHE, - ':tracker:extractDeepLinksDebug': FROM_CACHE, - ':tracker:generateDebugAssets': UP_TO_DATE, - ':tracker:generateDebugBuildConfig': FROM_CACHE, - ':tracker:generateDebugRFile': FROM_CACHE, - ':tracker:generateDebugResValues': FROM_CACHE, - ':tracker:generateDebugResources': UP_TO_DATE, - ':tracker:javaPreCompileDebug': FROM_CACHE, - ':tracker:kaptDebugKotlin': SUCCESS, - ':tracker:kaptGenerateStubsDebugKotlin': SUCCESS, - ':tracker:mergeDebugConsumerProguardFiles': SUCCESS, - ':tracker:mergeDebugGeneratedProguardFiles': SUCCESS, - ':tracker:mergeDebugJavaResource': SUCCESS, - ':tracker:mergeDebugJniLibFolders': FROM_CACHE, - ':tracker:mergeDebugNativeLibs': FROM_CACHE, - ':tracker:mergeDebugResources': FROM_CACHE, - ':tracker:mergeDebugShaders': FROM_CACHE, - ':tracker:packageDebugAssets': FROM_CACHE, - ':tracker:packageDebugRenderscript': NO_SOURCE, - ':tracker:packageDebugResources': FROM_CACHE, - ':tracker:parseDebugLocalResources': FROM_CACHE, - ':tracker:preBuild': UP_TO_DATE, - ':tracker:preDebugBuild': UP_TO_DATE, - ':tracker:prepareLintJarForPublish': SUCCESS, - ':tracker:processDebugJavaRes': NO_SOURCE, - ':tracker:processDebugManifest': FROM_CACHE, - ':tracker:stripDebugDebugSymbols': FROM_CACHE, - ':tracker:syncDebugLibJars': SUCCESS, - ':wearable:assembleDebug': SUCCESS, - ':wearable:checkDebugDuplicateClasses': FROM_CACHE, - ':wearable:compileDebugAidl': NO_SOURCE, - ':wearable:compileDebugJavaWithJavac': FROM_CACHE, - ':wearable:compileDebugKotlin': FROM_CACHE, - ':wearable:compileDebugRenderscript': NO_SOURCE, - ':wearable:compileDebugShaders': FROM_CACHE, - ':wearable:compileDebugSources': UP_TO_DATE, - ':wearable:createDebugCompatibleScreenManifests': FROM_CACHE, - ':wearable:dexBuilderDebug': FROM_CACHE, - ':wearable:extractDeepLinksDebug': FROM_CACHE, - ':wearable:generateDebugAssets': UP_TO_DATE, - ':wearable:generateDebugBuildConfig': FROM_CACHE, - ':wearable:generateDebugResValues': FROM_CACHE, - ':wearable:generateDebugResources': UP_TO_DATE, - ':wearable:javaPreCompileDebug': FROM_CACHE, - ':wearable:kaptDebugKotlin': SUCCESS, - ':wearable:kaptGenerateStubsDebugKotlin': FROM_CACHE, - ':wearable:mainApkListPersistenceDebug': FROM_CACHE, - ':wearable:mergeDebugAssets': FROM_CACHE, - ':wearable:mergeDebugJavaResource': SUCCESS, - ':wearable:mergeDebugJniLibFolders': FROM_CACHE, - ':wearable:mergeDebugNativeLibs': FROM_CACHE, - ':wearable:mergeDebugResources': FROM_CACHE, - ':wearable:mergeDebugShaders': FROM_CACHE, - ':wearable:mergeExtDexDebug': FROM_CACHE, - ':wearable:mergeLibDexDebug': FROM_CACHE, - ':wearable:mergeProjectDexDebug': FROM_CACHE, - ':wearable:packageDebug': SUCCESS, - ':wearable:preBuild': UP_TO_DATE, - ':wearable:preDebugBuild': UP_TO_DATE, - ':wearable:processDebugJavaRes': NO_SOURCE, - ':wearable:processDebugManifest': FROM_CACHE, - ':wearable:processDebugResources': FROM_CACHE, - ':wearable:stripDebugDebugSymbols': FROM_CACHE, - ':wearable:validateSigningDebug': FROM_CACHE, - ] - def cleanup() { - // The daemons started by test kit need to be killed, so no locked files are left behind. - DaemonLogsAnalyzer.newAnalyzer(homeDir.file(ToolingApiGradleExecutor.TEST_KIT_DAEMON_DIR_NAME)).killAll() + where: + agpVersion << TESTED_AGP_VERSIONS } } diff --git a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/KotlinPluginSmokeTest.groovy b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/KotlinPluginSmokeTest.groovy index 221ab161e6a7..882ba1aac4db 100644 --- a/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/KotlinPluginSmokeTest.groovy +++ b/subprojects/smoke-test/src/smokeTest/groovy/org/gradle/smoketests/KotlinPluginSmokeTest.groovy @@ -19,6 +19,7 @@ package org.gradle.smoketests import org.gradle.integtests.fixtures.ToBeFixedForInstantExecution import org.gradle.integtests.fixtures.android.AndroidHome import org.gradle.testkit.runner.BuildResult +import org.gradle.testkit.runner.GradleRunner import org.gradle.util.Requires import spock.lang.Unroll @@ -53,7 +54,7 @@ class KotlinPluginSmokeTest extends AbstractSmokeTest { @Unroll @ToBeFixedForInstantExecution - def 'kotlin #kotlinPluginVersion android #androidPluginVersion plugins, workers=#workers'() { + def '#sampleName kotlin #kotlinPluginVersion android #androidPluginVersion plugins, workers=#workers'() { given: AndroidHome.assertIsSet() useSample(sampleName) @@ -70,7 +71,7 @@ class KotlinPluginSmokeTest extends AbstractSmokeTest { } when: - def result = build(workers, 'clean', ':app:testDebugUnitTestCoverage') + def result = useAgpVersion(androidPluginVersion, runner(workers, 'clean', ':app:testDebugUnitTestCoverage')).build() then: result.task(':app:testDebugUnitTestCoverage').outcome == SUCCESS @@ -172,8 +173,11 @@ class KotlinPluginSmokeTest extends AbstractSmokeTest { } private BuildResult build(boolean workers, String... tasks) { + return runner(workers, *tasks).build() + } + + private GradleRunner runner(boolean workers, String... tasks) { return runner(tasks + ["--parallel", "-Pkotlin.parallel.tasks.in.project=$workers"] as String[]) .forwardOutput() - .build() } } diff --git a/subprojects/smoke-test/src/smokeTest/resources/org/gradle/smoketests/android-kotlin-example-kotlin-dsl/app/build.gradle.kts b/subprojects/smoke-test/src/smokeTest/resources/org/gradle/smoketests/android-kotlin-example-kotlin-dsl/app/build.gradle.kts index 57da5cc488f2..f1590b307806 100644 --- a/subprojects/smoke-test/src/smokeTest/resources/org/gradle/smoketests/android-kotlin-example-kotlin-dsl/app/build.gradle.kts +++ b/subprojects/smoke-test/src/smokeTest/resources/org/gradle/smoketests/android-kotlin-example-kotlin-dsl/app/build.gradle.kts @@ -21,8 +21,6 @@ plugins { id("jacoco") } -//System.properties["com.android.build.gradle.overrideVersionCheck"] = "true" - android { compileSdkVersion(24) buildToolsVersion("$androidBuildToolsVersion") @@ -46,7 +44,11 @@ android { getByName("androidTest").java.srcDir("src/androidTest/kotlin") } testOptions { - unitTests.isReturnDefaultValues = true + unitTests.withGroovyBuilder { + // AGP >= 4.0.0 exposes `returnDefaultValues` + // AGP < 4.0.0 exposes `isReturnDefaultValues + setProperty("returnDefaultValues", true) + } } kotlinOptions { jvmTarget = "1.8" diff --git a/subprojects/smoke-test/src/smokeTest/resources/org/gradle/smoketests/android-kotlin-example/app/build.gradle b/subprojects/smoke-test/src/smokeTest/resources/org/gradle/smoketests/android-kotlin-example/app/build.gradle index f94c5dbd9f7f..cff982f119c7 100644 --- a/subprojects/smoke-test/src/smokeTest/resources/org/gradle/smoketests/android-kotlin-example/app/build.gradle +++ b/subprojects/smoke-test/src/smokeTest/resources/org/gradle/smoketests/android-kotlin-example/app/build.gradle @@ -5,8 +5,6 @@ plugins { id 'jacoco' } -System.properties['com.android.build.gradle.overrideVersionCheck'] = 'true' - android { compileSdkVersion 24 buildToolsVersion '$androidBuildToolsVersion'