forked from elastic/elasticsearch
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Build] Fix Concurrency issue in buildparams access
Also provide caching support for buildparams provider
- Loading branch information
Showing
4 changed files
with
139 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
109 changes: 109 additions & 0 deletions
109
...src/test/groovy/org/elasticsearch/gradle/internal/info/BuildParameterExtensionSpec.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the "Elastic License | ||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side | ||
* Public License v 1"; you may not use this file except in compliance with, at | ||
* your election, the "Elastic License 2.0", the "GNU Affero General Public | ||
* License v3.0 only", or the "Server Side Public License, v 1". | ||
*/ | ||
|
||
package org.elasticsearch.gradle.internal.info | ||
|
||
import spock.lang.Specification | ||
|
||
import org.elasticsearch.gradle.internal.BwcVersions | ||
import org.gradle.api.JavaVersion | ||
import org.gradle.api.Project | ||
import org.gradle.api.provider.Provider | ||
import org.gradle.api.provider.ProviderFactory | ||
import org.gradle.testfixtures.ProjectBuilder | ||
import org.junit.Assert | ||
|
||
import java.util.concurrent.CountDownLatch | ||
import java.util.concurrent.Executors | ||
import java.util.concurrent.Future | ||
import java.util.concurrent.TimeUnit | ||
import java.util.concurrent.atomic.AtomicInteger | ||
|
||
import static org.junit.Assert.fail | ||
|
||
class BuildParameterExtensionSpec extends Specification { | ||
|
||
ProjectBuilder projectBuilder = new ProjectBuilder() | ||
|
||
def "#getterName is cached anc concurrently accessible"() { | ||
given: | ||
def project = projectBuilder.build() | ||
def providers = project.getProviders(); | ||
def buildParams = extension(project, providers) | ||
int numberOfThreads = 10; | ||
when: | ||
var service = Executors.newFixedThreadPool(10) | ||
var latch = new CountDownLatch(numberOfThreads) | ||
def testedProvider = buildParams."$getterName"() | ||
def futures = (1..numberOfThreads).collect { | ||
service.submit( | ||
() -> { | ||
try { | ||
testedProvider.get() | ||
} catch (AssertionError e) { | ||
latch.countDown() | ||
Assert.fail("Accessing cached provider more than once") | ||
} | ||
latch.countDown() | ||
} | ||
) | ||
} | ||
latch.await(10, TimeUnit.SECONDS) | ||
|
||
then: | ||
futures.size() == numberOfThreads | ||
futures.every { it.state() == Future.State.SUCCESS } | ||
|
||
where: | ||
getterName << [ | ||
"getRuntimeJavaHome", | ||
"getJavaToolChainSpec", | ||
"getRuntimeJavaDetails", | ||
"getRuntimeJavaVersion" | ||
] | ||
|
||
} | ||
|
||
private BuildParameterExtension extension(Project project, ProviderFactory providers) { | ||
return project.getExtensions().create( | ||
"buildParameters", BuildParameterExtension.class, | ||
providers, | ||
providerMock(), | ||
providerMock(), | ||
providerMock(), | ||
true, | ||
providerMock(), | ||
[ | ||
Mock(JavaHome), | ||
Mock(JavaHome), | ||
], | ||
JavaVersion.VERSION_11, | ||
JavaVersion.VERSION_11, | ||
JavaVersion.VERSION_11, | ||
"gitRevision", | ||
"gitOrigin", | ||
"testSeed", | ||
false, | ||
5, | ||
true, | ||
// cannot use Mock here because of the way the provider is used by gradle internal property api | ||
providers.provider { Mock(BwcVersions) } | ||
) | ||
} | ||
|
||
private Provider providerMock() { | ||
Provider provider = Mock(Provider) | ||
AtomicInteger counter = new AtomicInteger(0) | ||
provider.getOrNull() >> { | ||
println "accessing provider" | ||
return counter.get() == 1 ? fail("Accessing cached provider more than once") : counter.incrementAndGet() | ||
} | ||
provider | ||
} | ||
} |