org.gradle.resolve.DependencyResolutionStressTest.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-api Show documentation
Show all versions of gradle-api Show documentation
Gradle 6.9.1 API redistribution.
/*
* Copyright 2016 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.resolve
import org.gradle.integtests.fixtures.executer.GradleDistribution
import org.gradle.integtests.fixtures.executer.GradleExecuter
import org.gradle.integtests.fixtures.executer.UnderDevelopmentGradleDistribution
import org.gradle.soak.categories.SoakTest
import org.gradle.test.fixtures.ConcurrentTestUtil
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import org.junit.experimental.categories.Category
import org.junit.rules.ExternalResource
import org.mortbay.jetty.HttpHeaders
import org.mortbay.jetty.Server
import org.mortbay.jetty.bio.SocketConnector
import org.mortbay.jetty.handler.AbstractHandler
import spock.lang.Specification
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
@Category(SoakTest)
class DependencyResolutionStressTest extends Specification {
@Rule TestNameTestDirectoryProvider workspace = new TestNameTestDirectoryProvider()
GradleDistribution distribution = new UnderDevelopmentGradleDistribution()
@Rule StressHttpServer server = new StressHttpServer()
@Rule ConcurrentTestUtil concurrent = new ConcurrentTestUtil()
def setup() {
concurrent.shortTimeout = 180000
}
def "handles concurrent access to changing artifacts"() {
expect:
4.times { count ->
concurrent.start {
def buildDir = workspace.file(count)
buildDir.file('build.gradle') << """
import java.util.zip.*
repositories {
ivy { url '${server.uri}' }
}
configurations {
compile
}
dependencies {
compile 'org.gradle:changing:1.0'
}
task check << {
def file = configurations.compile.singleFile
println "THREAD $count -> checking \$file.name size: \${file.length()}"
file.withInputStream { instr ->
def zipStream = new ZipInputStream(instr)
def entries = []
for (ZipEntry entry = zipStream.nextEntry; entry != null; entry = zipStream.nextEntry) {
entries << entry.name
}
assert entries == ['a', 'b']
}
}
"""
GradleExecuter executer = distribution.executer(workspace).
requireGradleDistribution().
withGradleUserHomeDir(workspace.file("user-home"))
10.times {
executer.inDirectory(buildDir).withArgument("--refresh-dependencies").withTasks('check').run()
}
}
}
concurrent.finished()
}
static class StressHttpServer extends ExternalResource {
final Server server = new Server(0)
final Resources resources = new Resources()
@Override
protected void before() {
server.addConnector(new SocketConnector())
server.addHandler(new AbstractHandler() {
void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) {
println "* Handling $request.method $request.pathInfo"
if (request.method == 'GET' && request.pathInfo == '/org.gradle/changing/1.0/ivy-1.0.xml') {
handleGetIvy(request, response)
request.handled = true
} else if (request.method == 'HEAD' && request.pathInfo == '/org.gradle/changing/1.0/ivy-1.0.xml') {
handleHeadIvy(request, response)
request.handled = true
} else if (request.method == 'GET' && request.pathInfo == '/org.gradle/changing/1.0/changing-1.0.jar') {
handleGetJar(request, response)
request.handled = true
} else if (request.method == 'HEAD' && request.pathInfo == '/org.gradle/changing/1.0/changing-1.0.jar') {
handleHeadJar(request, response)
request.handled = true
}
}
})
server.start()
}
private void handleGetIvy(HttpServletRequest request, HttpServletResponse response) {
println "* GET IVY FILE"
def ivy = resources.ivy
response.setDateHeader(HttpHeaders.LAST_MODIFIED, ivy.lastModified)
response.setContentLength(ivy.contentLength)
response.setContentType(ivy.contentType)
ivy.writeContentTo(response.outputStream)
}
private void handleHeadIvy(HttpServletRequest request, HttpServletResponse response) {
println "* HEAD IVY FILE"
def ivy = resources.ivy
response.setDateHeader(HttpHeaders.LAST_MODIFIED, ivy.lastModified)
response.setContentLength(ivy.contentLength)
response.setContentType(ivy.contentType)
}
private void handleGetJar(HttpServletRequest request, HttpServletResponse response) {
println "* GET JAR"
def jar = resources.jar
response.setDateHeader(HttpHeaders.LAST_MODIFIED, jar.lastModified)
response.setContentLength(jar.contentLength)
response.setContentType(jar.contentType)
jar.writeContentTo(response.outputStream)
}
private void handleHeadJar(HttpServletRequest request, HttpServletResponse response) {
println "* HEAD JAR"
def jar = resources.jar
response.setDateHeader(HttpHeaders.LAST_MODIFIED, jar.lastModified)
response.setContentLength(jar.contentLength)
response.setContentType(jar.contentType)
}
@Override
protected void after() {
server.stop()
}
URI getUri() {
return new URI("http://localhost:${server.connectors[0].localPort}/")
}
}
static class Resources {
private final Object lock = new Object()
private int count
private Resource ivy
private Resource jar
private final IvyFileGenerator ivyGenerator = new IvyFileGenerator()
private final JarFileGenerator jarGenerator = new JarFileGenerator()
Resource getIvy() {
synchronized (lock) {
maybeReset()
if (ivy == null) {
ivy = ivyGenerator.regenerate()
}
return ivy
}
}
Resource getJar() {
synchronized (lock) {
maybeReset()
if (jar == null) {
jar = jarGenerator.regenerate()
}
return jar
}
}
private void maybeReset() {
count++
if (count > 4) {
println "*** RESET"
count = 0
ivy = null
jar = null
}
}
}
static class Resource {
final long lastModified
final byte[] content
final String contentType
Resource(byte[] content, long lastModified, String contentType) {
this.content = content
this.lastModified = lastModified
this.contentType = contentType
}
int getContentLength() {
content.length
}
void writeContentTo(OutputStream outputStream) {
outputStream.write(content)
}
}
static abstract class ResourceGenerator {
private final Random random = new Random();
Resource regenerate() {
def str = new ByteArrayOutputStream()
generateContent(str)
def content = str.toByteArray()
def lastModified = System.currentTimeMillis()
return new Resource(content, lastModified, contentType)
}
// Writes a long string of text encoded with the system encoding to the given output stream
protected void writeLongString(OutputStream outputStream) {
for (int i = 0; i < 25000; i++) {
outputStream.write(String.valueOf(random.nextInt()).bytes)
}
}
protected abstract String getContentType()
protected abstract void generateContent(OutputStream outputStream)
}
static class IvyFileGenerator extends ResourceGenerator {
@Override
String getContentType() {
return "text/xml"
}
@Override
void generateContent(OutputStream outputStream) {
outputStream << '''
'''
}
}
static class JarFileGenerator extends ResourceGenerator {
@Override
String getContentType() {
return "application/java-archive"
}
@Override
void generateContent(OutputStream outputStream) {
def zipStream = new ZipOutputStream(outputStream)
zipStream.putNextEntry(new ZipEntry("a"))
writeLongString(zipStream)
zipStream.putNextEntry(new ZipEntry("b"))
writeLongString(zipStream)
zipStream.finish()
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy