Merge pull request #869 from DataDog/mar-kolya/refactor-smoke-tests

Refactor smoketests setup
This commit is contained in:
Nikolay Martynov 2019-06-11 10:37:14 -04:00 committed by GitHub
commit 6f97243a12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 271 additions and 291 deletions

View File

@ -1,24 +0,0 @@
package datadog.trace.agent.tooling;
import java.lang.reflect.Method;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class DDJavaAgentInfo {
public static final String VERSION;
static {
String v;
try {
Class<?> tracingAgentClass =
ClassLoader.getSystemClassLoader().loadClass("datadog.trace.agent.TracingAgent");
Method getAgentVersionMethod = tracingAgentClass.getMethod("getAgentVersion");
v = (String) getAgentVersionMethod.invoke(null);
} catch (final Exception e) {
log.error("failed to read agent version", e);
v = "unknown";
}
VERSION = v;
log.info("dd-java-agent - version: {}", v);
}
}

View File

@ -102,7 +102,7 @@ dependencies {
testCompile group: 'org.mongodb', name: 'mongo-java-driver', version: '3.4.2'
testCompile group: 'org.mongodb', name: 'mongodb-driver-async', version: '3.4.2'
// run embeded mongodb for integration testing
// run embedded mongodb for integration testing
testCompile group: 'de.flapdoodle.embed', name: 'de.flapdoodle.embed.mongo', version: '1.50.5'
}

View File

@ -2,8 +2,9 @@ package datadog.trace.agent
import datadog.opentracing.DDTraceOTInfo
import datadog.trace.api.DDTraceApiInfo
import spock.lang.Specification
class DDInfoTest {
class DDInfoTest extends Specification {
def "info accessible from api"() {
expect:
DDTraceApiInfo.VERSION == DDTraceOTInfo.VERSION
@ -15,17 +16,4 @@ class DDInfoTest {
DDTraceOTInfo.VERSION != ""
DDTraceOTInfo.VERSION != "unknown"
}
def "info accessible from agent"() {
setup:
def clazz = Class.forName("datadog.trace.agent.tooling.DDJavaAgentInfo")
def versionField = clazz.getDeclaredField("VERSION")
def version = versionField.get(null)
expect:
version != null
version != ""
version != "unknown"
version == DDTraceApiInfo.VERSION
}
}

View File

@ -2,6 +2,8 @@ package datadog.trace.agent.test.utils;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.TimeUnit;
public class PortUtils {
@ -20,4 +22,39 @@ public class PortUtils {
return -1;
}
}
private static boolean isPortOpen(final int port) {
try (final Socket socket = new Socket((String) null, port)) {
return true;
} catch (final IOException e) {
return false;
}
}
public static void waitForPortToOpen(
final int port, final long timeout, final TimeUnit unit, final Process process) {
final long waitUntil = System.currentTimeMillis() + unit.toMillis(timeout);
while (System.currentTimeMillis() < waitUntil) {
try {
Thread.sleep(100);
} catch (final InterruptedException e) {
throw new RuntimeException("Interrupted while waiting for " + port + " to be opened");
}
// Note: we should have used `process.isAlive()` here but it is java8 only
try {
process.exitValue();
throw new RuntimeException("Process died before port " + port + " was opened");
} catch (final IllegalThreadStateException e) {
// process is still alive, things are good.
}
if (isPortOpen(port)) {
return;
}
}
throw new RuntimeException("Timed out waiting for port " + port + " to be opened");
}
}

View File

@ -1 +1,18 @@
apply from: "${rootDir}/gradle/java.gradle"
description = 'dd-smoke-tests'
dependencies {
compile deps.spock
compile project(':dd-java-agent:testing')
}
subprojects { subProject ->
subProject.tasks.withType(Test).configureEach {
dependsOn project(':dd-java-agent').shadowJar
// Tests depend on this to know where to run things and what agent jar to use
jvmArgs "-Ddatadog.smoketest.builddir=${buildDir}"
jvmArgs "-Ddatadog.smoketest.agent.shadowJar.path=${project(':dd-java-agent').tasks.shadowJar.archivePath}"
}
}

View File

@ -1,12 +1,9 @@
plugins {
// using this plugin will launch the server in the background and won't block the tests
id 'com.github.psxpaul.execfork' version '0.1.8'
id 'play'
}
ext {
minJavaVersionForTests = JavaVersion.VERSION_1_8
playHttpPort = 8080
}
def playVersion = "2.6.20"
@ -55,57 +52,9 @@ dependencies {
play project(':dd-trace-api')
play deps.opentracing
testCompile project(':dd-trace-api')
testCompile project(':dd-trace-ot')
testCompile project(':dd-java-agent:testing')
testCompile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.6.0'
}
tasks.register("startServer", com.github.psxpaul.task.ExecFork) {
dependsOn project(':dd-java-agent').shadowJar
playHttpPort = randomOpenPort()
if (playHttpPort == -1) {
throw new GradleException("Failed to get random port to start Play")
}
workingDir = "${buildDir}/stage/playBinary"
commandLine = "${workingDir}/bin/playBinary"
stopAfter = test
standardOutput "${buildDir}/reports/server.log"
// these params tells the ExecFork plugin to block on startServer task until the port is opened or the string is seen in the ouput
waitForPort = playHttpPort
waitForOutput = "Listening for HTTP on /127.0.0.1:${playHttpPort}"
timeout = 240
environment = [
'JAVA_OPTS': "-javaagent:${project(':dd-java-agent').tasks.shadowJar.archivePath}"
+ " -Ddd.writer.type=LoggingWriter" + " -Ddd.service.name=java-app"
+ " -Ddatadog.slf4j.simpleLogger.defaultLogLevel=debug"
+ " -Dorg.slf4j.simpleLogger.defaultLogLevel=debug"
+ " -Dconfig.file=${workingDir}/conf/application.conf -Dhttp.port=${playHttpPort}"
+ " -Dhttp.address=127.0.0.1"
]
dependsOn 'stage'
// When tests are disabled this would still be run, so disable this manually
onlyIf { !project.rootProject.hasProperty("skipTests") }
}
tasks.register("deletePIDFile") {
delete "${buildDir}/stage/playBinary/RUNNING_PID"
testCompile project(':dd-smoke-tests')
}
tasks.withType(Test).configureEach {
// so the test can get this property
jvmArgs "-Ddatadog.smoketest.server.port=${playHttpPort}"
testLogging {
events "started"
}
dependsOn startServer
// clean up the PID file from the server
finalizedBy deletePIDFile
dependsOn 'stage'
}

View File

@ -0,0 +1,39 @@
package datadog.smoketest
import okhttp3.Request
import spock.lang.Shared
class PlaySmokeTest extends AbstractServerSmokeTest {
@Shared
File playDirectory = new File("${buildDirectory}/stage/playBinary")
@Override
ProcessBuilder createProcessBuilder() {
ProcessBuilder processBuilder =
new ProcessBuilder("${playDirectory}/bin/playBinary")
processBuilder.directory(playDirectory)
processBuilder.environment().put("JAVA_OPTS",
defaultJavaProperties.join(" ")
+ " -Dconfig.file=${workingDirectory}/conf/application.conf -Dhttp.port=${httpPort}"
+ " -Dhttp.address=127.0.0.1")
return processBuilder
}
def "welcome endpoint #n th time"() {
setup:
String url = "http://localhost:$httpPort/welcome?id=$n"
def request = new Request.Builder().url(url).get().build()
when:
def response = client.newCall(request).execute()
then:
def responseBodyStr = response.body().string()
responseBodyStr == "Welcome $n."
response.code() == 200
where:
n << (1..200)
}
}

View File

@ -1,29 +0,0 @@
package datadog.trace.agent
import datadog.trace.agent.test.utils.OkHttpUtils
import okhttp3.OkHttpClient
import okhttp3.Request
import spock.lang.Specification
class PlaySmokeTest extends Specification {
OkHttpClient client = OkHttpUtils.client()
private int port = Integer.parseInt(System.getProperty("datadog.smoketest.server.port", "8080"))
def "welcome endpoint #n th time"() {
setup:
String url = "http://localhost:$port/welcome?id=$n"
def request = new Request.Builder().url(url).get().build()
when:
def response = client.newCall(request).execute()
then:
def responseBodyStr = response.body().string()
responseBodyStr == "Welcome $n."
response.code() == 200
where:
n << (1..200)
}
}

View File

@ -1,15 +1,9 @@
plugins {
id "com.github.johnrengelman.shadow" version "4.0.4"
id 'com.github.psxpaul.execfork' version '0.1.8'
}
apply from: "${rootDir}/gradle/java.gradle"
description = 'SpringBoot Smoke Tests.'
ext {
springbootHttpPort = 8080
}
// The standard spring-boot plugin doesn't play nice with our project
// so we'll build a fat jar instead
jar {
@ -23,40 +17,11 @@ jar {
dependencies {
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '1.5.18.RELEASE'
testCompile project(':dd-trace-api')
testCompile project(':dd-trace-ot')
testCompile project(':dd-java-agent:testing')
testCompile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.6.0'
}
tasks.register("startServer", com.github.psxpaul.task.ExecFork) {
springbootHttpPort = randomOpenPort()
dependsOn project(':dd-java-agent').shadowJar, shadowJar
if (springbootHttpPort == -1) {
throw new GradleException("Failed to get random port to start springboot")
}
workingDir = "${buildDir}"
commandLine = "java"
args = ["-javaagent:${project(':dd-java-agent').tasks.shadowJar.archivePath}",
"-Ddd.writer.type=LoggingWriter",
"-Ddd.service.name=java-app",
"-Ddatadog.slf4j.simpleLogger.defaultLogLevel=debug",
"-jar",
"${tasks.shadowJar.archivePath}",
"--server.port=$springbootHttpPort"]
standardOutput "${buildDir}/reports/server.log"
waitForPort = springbootHttpPort
waitForOutput = "datadog.smoketest.springboot.SpringbootApplication - Started SpringbootApplication"
timeout = 240
stopAfter = test
// When tests are disabled this would still be run, so disable this manually
onlyIf { !project.rootProject.hasProperty("skipTests") }
testCompile project(':dd-smoke-tests')
}
tasks.withType(Test).configureEach {
jvmArgs "-Ddatadog.smoketest.server.port=${springbootHttpPort}"
dependsOn shadowJar
dependsOn startServer
jvmArgs "-Ddatadog.smoketest.springboot.shadowJar.path=${tasks.shadowJar.archivePath}"
}

View File

@ -0,0 +1,37 @@
package datadog.smoketest
import okhttp3.Request
class SpringBootSmokeTest extends AbstractServerSmokeTest {
@Override
ProcessBuilder createProcessBuilder() {
String springBootShadowJar = System.getProperty("datadog.smoketest.springboot.shadowJar.path")
List<String> command = new ArrayList<>()
command.add("java")
command.addAll(defaultJavaProperties)
command.addAll((String[]) ["-jar", springBootShadowJar, "--server.port=${httpPort}"])
ProcessBuilder processBuilder = new ProcessBuilder(command)
processBuilder.directory(new File(buildDirectory))
}
def "default home page #n th time"() {
setup:
String url = "http://localhost:${httpPort}/greeting"
def request = new Request.Builder().url(url).get().build()
when:
def response = client.newCall(request).execute()
then:
def responseBodyStr = response.body().string()
responseBodyStr != null
responseBodyStr.contains("Sup Dawg")
response.body().contentType().toString().contains("text/plain")
response.code() == 200
where:
n << (1..200)
}
}

View File

@ -1,31 +0,0 @@
package datadog.trace.agent
import datadog.trace.agent.test.utils.OkHttpUtils
import okhttp3.OkHttpClient
import okhttp3.Request
import spock.lang.Specification
class SpringBootSmokeTest extends Specification {
private OkHttpClient client = OkHttpUtils.client()
private int port = Integer.parseInt(System.getProperty("datadog.smoketest.server.port", "8080"))
def "default home page #n th time"() {
setup:
String url = "http://localhost:$port/greeting"
def request = new Request.Builder().url(url).get().build()
when:
def response = client.newCall(request).execute()
then:
def responseBodyStr = response.body().string()
responseBodyStr != null
responseBodyStr.contains("Sup Dawg")
response.body().contentType().toString().contains("text/plain")
response.code() == 200
where:
n << (1..200)
}
}

View File

@ -0,0 +1,23 @@
package datadog.smoketest
import datadog.trace.agent.test.utils.OkHttpUtils
import datadog.trace.agent.test.utils.PortUtils
import okhttp3.OkHttpClient
import spock.lang.Shared
import java.util.concurrent.TimeUnit
abstract class AbstractServerSmokeTest extends AbstractSmokeTest {
@Shared
int httpPort = PortUtils.randomOpenPort()
protected OkHttpClient client = OkHttpUtils.client()
def setupSpec() {
PortUtils.waitForPortToOpen(httpPort, 240, TimeUnit.SECONDS, serverProcess)
}
}

View File

@ -0,0 +1,48 @@
package datadog.smoketest
import spock.lang.Shared
import spock.lang.Specification
abstract class AbstractSmokeTest extends Specification {
@Shared
protected String workingDirectory = System.getProperty("user.dir")
@Shared
protected String buildDirectory = System.getProperty("datadog.smoketest.builddir")
@Shared
protected String shadowJarPath = System.getProperty("datadog.smoketest.agent.shadowJar.path")
@Shared
protected String[] defaultJavaProperties
@Shared
protected Process serverProcess
def setupSpec() {
if (buildDirectory == null || shadowJarPath == null) {
throw new AssertionError("Expected system properties not found. Smoke tests have to be run from Gradle. Please make sure that is the case.")
}
defaultJavaProperties = [
"-javaagent:${shadowJarPath}",
"-Ddd.writer.type=LoggingWriter",
"-Ddd.service.name=smoke-test-java-app",
"-Ddatadog.slf4j.simpleLogger.defaultLogLevel=debug",
"-Dorg.slf4j.simpleLogger.defaultLogLevel=debug"
]
ProcessBuilder processBuilder = createProcessBuilder()
processBuilder.redirectErrorStream(true)
File log = new File("${buildDirectory}/reports/serverProcess.log")
processBuilder.redirectOutput(ProcessBuilder.Redirect.to(log))
serverProcess = processBuilder.start()
}
def cleanupSpec() {
serverProcess?.waitForOrKill(1)
}
abstract ProcessBuilder createProcessBuilder()
}

View File

@ -0,0 +1,57 @@
package datadog.smoketest
import datadog.trace.agent.test.utils.PortUtils
import okhttp3.Request
import spock.lang.Shared
class WildflySmokeTest extends AbstractServerSmokeTest {
@Shared
File wildflyDirectory = new File(System.getProperty("datadog.smoketest.wildflyDir"))
@Shared
int httpsPort = PortUtils.randomOpenPort()
@Shared
int managementPort = PortUtils.randomOpenPort()
@Override
ProcessBuilder createProcessBuilder() {
ProcessBuilder processBuilder =
new ProcessBuilder("${wildflyDirectory}/bin/standalone.sh")
processBuilder.directory(wildflyDirectory)
processBuilder.environment().put("JAVA_OPTS",
defaultJavaProperties.join(" ")
+ " -Djboss.http.port=${httpPort} -Djboss.https.port=${httpsPort}"
+ " -Djboss.management.http.port=${managementPort}")
return processBuilder
}
def cleanupSpec() {
ProcessBuilder processBuilder = new ProcessBuilder(
"${wildflyDirectory}/bin/jboss-cli.sh",
"--connect",
"--controller=localhost:${managementPort}",
"command=:shutdown")
processBuilder.directory(wildflyDirectory)
Process process = processBuilder.start()
process.waitFor()
}
def "default home page #n th time"() {
setup:
String url = "http://localhost:$httpPort/"
def request = new Request.Builder().url(url).get().build()
when:
def response = client.newCall(request).execute()
then:
def responseBodyStr = response.body().string()
responseBodyStr != null
responseBodyStr.contains("Your WildFly instance is running.")
response.body().contentType().toString().contains("text/html")
response.code() == 200
where:
n << (1..200)
}
}

View File

@ -1,31 +0,0 @@
package datadog.trace.agent
import datadog.trace.agent.test.utils.OkHttpUtils
import okhttp3.OkHttpClient
import okhttp3.Request
import spock.lang.Specification
class WildflySmokeTest extends Specification {
OkHttpClient client = OkHttpUtils.client()
private int port = Integer.parseInt(System.getProperty("datadog.smoketest.server.port", "8080"))
def "default home page #n th time"() {
setup:
String url = "http://localhost:$port/"
def request = new Request.Builder().url(url).get().build()
when:
def response = client.newCall(request).execute()
then:
def responseBodyStr = response.body().string()
responseBodyStr != null
responseBodyStr.contains("Your WildFly instance is running.")
response.body().contentType().toString().contains("text/html")
response.code() == 200
where:
n << (1..200)
}
}

View File

@ -1,15 +1,9 @@
// using this plugin will launch the server in the background and won't block the tests
plugins {
id 'com.github.psxpaul.execfork' version '0.1.8'
}
ext {
serverName = 'wildfly'
serverModule = 'servlet'
serverVersion = '15.0.0.Final'
serverExtension = 'zip'
wildflyHttpPort = 8080
wildflyManagementPort = 9990
}
repositories {
@ -30,10 +24,7 @@ dependencies {
// organisation = serverName, revision = serverVersion, module = serverModule, ext = serverExtension
compile "${serverName}:${serverModule}:${serverVersion}@${serverExtension}"
testCompile project(':dd-trace-api')
testCompile project(':dd-trace-ot')
testCompile project(':dd-java-agent:testing')
testCompile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.6.0'
testCompile project(':dd-smoke-tests')
}
tasks.register("unzip", Copy) {
@ -55,64 +46,8 @@ tasks.register("unzip", Copy) {
onlyIf { !project.rootProject.hasProperty("skipTests") }
}
tasks.register("startServer", com.github.psxpaul.task.ExecFork) {
dependsOn project(':dd-java-agent').shadowJar
wildflyHttpPort = randomOpenPort()
// not used, but to ensure https default port 8443 won't clash
int httpsPort = randomOpenPort()
wildflyManagementPort = randomOpenPort()
if (wildflyHttpPort == -1 || httpsPort == -1 || wildflyManagementPort == -1) {
throw new GradleException("Failed to get random ports to start Wildfly")
}
workingDir = "${buildDir}/wildfly-servlet-15.0.0.Final"
commandLine = "${workingDir}/bin/standalone.sh"
// ideally this should be good enough to use to stop wildfly, but wildfly needs to gracefully shutdown from jboss-cli.sh
// stopAfter = test
standardOutput "${buildDir}/reports/server.log"
// these params tells the ExecFork plugin to block on startServer task until the port is opened or the string is seen in the ouput
waitForPort = wildflyHttpPort
waitForOutput = "Undertow HTTP listener default listening on 127.0.0.1:${wildflyHttpPort}"
timeout = 240
environment = [
'JAVA_OPTS': "-javaagent:${project(':dd-java-agent').tasks.shadowJar.archivePath}"
+ " -Ddd.writer.type=LoggingWriter" + " -Ddd.service.name=java-app"
+ " -Ddatadog.slf4j.simpleLogger.defaultLogLevel=debug"
+ " -Dorg.slf4j.simpleLogger.defaultLogLevel=debug"
+ " -Djboss.http.port=${wildflyHttpPort} -Djboss.https.port=${httpsPort}"
+ " -Djboss.management.http.port=${wildflyManagementPort}"
]
dependsOn unzip
// When tests are disabled this would still be run, so disable this manually
onlyIf { !project.rootProject.hasProperty("skipTests") }
}
tasks.register("stopWildfly", Exec) {
project.getLogger().info("Shutting down Wildfly")
workingDir = "${buildDir}/wildfly-servlet-15.0.0.Final"
commandLine = "${workingDir}/bin/jboss-cli.sh"
args = ["--connect", "--controller=localhost:${wildflyManagementPort}", "command=:shutdown"]
dependsOn startServer
// When tests are disabled this would still be run, so disable this manually
onlyIf { !project.rootProject.hasProperty("skipTests") }
}
tasks.withType(Test).configureEach {
// so the test can get this property
jvmArgs "-Ddatadog.smoketest.server.port=${wildflyHttpPort}"
testLogging {
events "started"
}
dependsOn startServer
// ensure that the wildfly server gets shutdown
finalizedBy stopWildfly
dependsOn unzip
jvmArgs "-Ddatadog.smoketest.wildflyDir=${buildDir}/${serverName}-${serverModule}-${serverVersion}"
}

View File

@ -1,4 +1,4 @@
def groovyVer = "2.5.6"
def groovyVer = "2.5.7"
def spockGroovyVer = groovyVer.replaceAll(/\.\d+$/, '')
ext {