diff --git a/.circleci/config.yml b/.circleci/config.yml index f72cd345f7..4b3fb07018 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -115,6 +115,11 @@ jobs: environment: - TEST_TASK: testJava11 + test_12: + <<: *default_test_job + environment: + - TEST_TASK: testJava12 + agent_integration_tests: <<: *defaults docker: @@ -268,6 +273,12 @@ workflows: filters: tags: only: /.*/ + - test_12: + requires: + - build + filters: + tags: + only: /.*/ - agent_integration_tests: requires: @@ -298,6 +309,7 @@ workflows: - test_9 - test_10 - test_11 + - test_12 - agent_integration_tests - check filters: @@ -314,6 +326,7 @@ workflows: - test_9 - test_10 - test_11 + - test_12 - agent_integration_tests - check filters: diff --git a/dd-java-agent/agent-tooling/agent-tooling.gradle b/dd-java-agent/agent-tooling/agent-tooling.gradle index 182a5b97a4..50e6ce3b6f 100644 --- a/dd-java-agent/agent-tooling/agent-tooling.gradle +++ b/dd-java-agent/agent-tooling/agent-tooling.gradle @@ -16,7 +16,7 @@ dependencies { annotationProcessor deps.autoservice implementation deps.autoservice - compileOnly project(':dd-trace-ot') + compile project(':dd-trace-ot') testCompile deps.opentracing testCompile project(':dd-java-agent:testing') diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDJavaAgentInfo.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDJavaAgentInfo.java deleted file mode 100644 index c55e1d6e9e..0000000000 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/DDJavaAgentInfo.java +++ /dev/null @@ -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); - } -} diff --git a/dd-java-agent/dd-java-agent.gradle b/dd-java-agent/dd-java-agent.gradle index dda95c047e..81ccc6669a 100644 --- a/dd-java-agent/dd-java-agent.gradle +++ b/dd-java-agent/dd-java-agent.gradle @@ -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' } diff --git a/dd-java-agent/instrumentation/couchbase-2.0/couchbase-2.0.gradle b/dd-java-agent/instrumentation/couchbase-2.0/couchbase-2.0.gradle index 15960d93d8..df0477aed7 100644 --- a/dd-java-agent/instrumentation/couchbase-2.0/couchbase-2.0.gradle +++ b/dd-java-agent/instrumentation/couchbase-2.0/couchbase-2.0.gradle @@ -14,18 +14,22 @@ testSets { } muzzle { - pass { - group = 'com.couchbase.client' - module = 'java-client' - // Looks like 2.7.5 was just released and didn't sync up with mirrors properly causing build failures - // TODO: remove this on a few days. - versions = "[2.0.0,2.7.5)" -// assertInverse = true - } + // Version 2.7.5 was not released properly and muzzle cannot test against it causing failure. + // So we have to skip it resulting in this verbose setup. fail { group = 'com.couchbase.client' module = 'java-client' - versions = "(,2.0.0)" + versions = "[,2.0.0)" + } + pass { + group = 'com.couchbase.client' + module = 'java-client' + versions = "[2.0.0,2.7.5)" + } + pass { + group = 'com.couchbase.client' + module = 'java-client' + versions = "[2.7.6,)" } fail { group = 'com.couchbase.client' @@ -53,8 +57,6 @@ dependencies { testCompile group: 'com.couchbase.client', name: 'java-client', version: '2.5.0' latestDepTestCompile group: 'org.springframework.data', name: 'spring-data-couchbase', version: '3.+' - // Looks like 2.7.5 was just released and didn't sync up with mirrors properly causing build failures - // TODO: remove this on a few days. - latestDepTestCompile group: 'com.couchbase.client', name: 'java-client', version: '2.7.4' - latestDepTestCompile group: 'com.couchbase.client', name: 'encryption', version: '1.0.0' + latestDepTestCompile group: 'com.couchbase.client', name: 'java-client', version: '2.6+' + latestDepTestCompile group: 'com.couchbase.client', name: 'encryption', version: '+' } diff --git a/dd-java-agent/instrumentation/glassfish/glassfish.gradle b/dd-java-agent/instrumentation/glassfish/glassfish.gradle index f32595c517..d0f4072239 100644 --- a/dd-java-agent/instrumentation/glassfish/glassfish.gradle +++ b/dd-java-agent/instrumentation/glassfish/glassfish.gradle @@ -19,7 +19,6 @@ testSets { dependencies { - compile project(':dd-trace-ot') compile project(':dd-java-agent:agent-tooling') compile deps.bytebuddy diff --git a/dd-java-agent/instrumentation/grpc-1.5/grpc-1.5.gradle b/dd-java-agent/instrumentation/grpc-1.5/grpc-1.5.gradle index 9b426d90e3..cad593931a 100644 --- a/dd-java-agent/instrumentation/grpc-1.5/grpc-1.5.gradle +++ b/dd-java-agent/instrumentation/grpc-1.5/grpc-1.5.gradle @@ -44,7 +44,6 @@ testSets { dependencies { compileOnly group: 'io.grpc', name: 'grpc-core', version: grpcVersion - compile project(':dd-trace-ot') compile project(':dd-java-agent:agent-tooling') compile deps.bytebuddy diff --git a/dd-java-agent/instrumentation/hystrix-1.4/hystrix-1.4.gradle b/dd-java-agent/instrumentation/hystrix-1.4/hystrix-1.4.gradle index faaca0f737..4bf9097b7b 100644 --- a/dd-java-agent/instrumentation/hystrix-1.4/hystrix-1.4.gradle +++ b/dd-java-agent/instrumentation/hystrix-1.4/hystrix-1.4.gradle @@ -20,7 +20,6 @@ dependencies { compileOnly group: 'com.netflix.hystrix', name: 'hystrix-core', version: '1.4.0' compileOnly group: 'io.reactivex', name: 'rxjava', version: '1.0.7' - compile project(':dd-trace-ot') compile project(':dd-java-agent:agent-tooling') compile deps.bytebuddy diff --git a/dd-java-agent/instrumentation/instrumentation.gradle b/dd-java-agent/instrumentation/instrumentation.gradle index 37cf4bfdf5..f0992e8890 100644 --- a/dd-java-agent/instrumentation/instrumentation.gradle +++ b/dd-java-agent/instrumentation/instrumentation.gradle @@ -1,10 +1,10 @@ // this project will run in isolation under the agent's classloader buildscript { - + repositories { mavenCentral() } - + dependencies { classpath "net.bytebuddy:byte-buddy-gradle-plugin:${versions.bytebuddy}" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}" diff --git a/dd-java-agent/instrumentation/java-concurrent/akka-2.5-testing/akka-2.5-testing.gradle b/dd-java-agent/instrumentation/java-concurrent/akka-2.5-testing/akka-2.5-testing.gradle index 0fbe7c0481..f37737124e 100644 --- a/dd-java-agent/instrumentation/java-concurrent/akka-2.5-testing/akka-2.5-testing.gradle +++ b/dd-java-agent/instrumentation/java-concurrent/akka-2.5-testing/akka-2.5-testing.gradle @@ -12,7 +12,6 @@ dependencies { compileOnly deps.scala testCompile project(':dd-trace-api') - testCompile project(':dd-trace-ot') testCompile deps.scala testCompile group: 'com.typesafe.akka', name: 'akka-actor_2.11', version: '2.5.0' diff --git a/dd-java-agent/instrumentation/java-concurrent/akka-testing/akka-testing.gradle b/dd-java-agent/instrumentation/java-concurrent/akka-testing/akka-testing.gradle index d674298eb3..9e2ea34a78 100644 --- a/dd-java-agent/instrumentation/java-concurrent/akka-testing/akka-testing.gradle +++ b/dd-java-agent/instrumentation/java-concurrent/akka-testing/akka-testing.gradle @@ -9,9 +9,8 @@ apply from: "${rootDir}/gradle/test-with-scala.gradle" dependencies { compileOnly deps.scala - + testCompile project(':dd-trace-api') - testCompile project(':dd-trace-ot') testCompile deps.scala testCompile group: 'com.typesafe.akka', name: 'akka-actor_2.11', version: '2.3.16' testCompile group: 'com.typesafe.akka', name: 'akka-testkit_2.11', version: '2.3.16' diff --git a/dd-java-agent/instrumentation/java-concurrent/kotlin-testing/kotlin-testing.gradle b/dd-java-agent/instrumentation/java-concurrent/kotlin-testing/kotlin-testing.gradle index 6492000368..bbb025b62c 100644 --- a/dd-java-agent/instrumentation/java-concurrent/kotlin-testing/kotlin-testing.gradle +++ b/dd-java-agent/instrumentation/java-concurrent/kotlin-testing/kotlin-testing.gradle @@ -3,7 +3,8 @@ apply from: "${rootDir}/gradle/test-with-kotlin.gradle" dependencies { testCompile project(':dd-trace-api') - testCompile project(':dd-trace-ot') + + testCompile deps.kotlin testCompile deps.coroutines diff --git a/dd-java-agent/instrumentation/java-concurrent/scala-testing/scala-testing.gradle b/dd-java-agent/instrumentation/java-concurrent/scala-testing/scala-testing.gradle index 8515c89828..084d541e1b 100644 --- a/dd-java-agent/instrumentation/java-concurrent/scala-testing/scala-testing.gradle +++ b/dd-java-agent/instrumentation/java-concurrent/scala-testing/scala-testing.gradle @@ -11,7 +11,6 @@ dependencies { compileOnly deps.scala testCompile project(':dd-trace-api') - testCompile project(':dd-trace-ot') testCompile deps.scala testCompile project(':dd-java-agent:testing') diff --git a/dd-java-agent/instrumentation/jetty-8/jetty-8.gradle b/dd-java-agent/instrumentation/jetty-8/jetty-8.gradle index ed13d35a2e..be5a2d8373 100644 --- a/dd-java-agent/instrumentation/jetty-8/jetty-8.gradle +++ b/dd-java-agent/instrumentation/jetty-8/jetty-8.gradle @@ -20,7 +20,6 @@ testSets { dependencies { compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '3.0.1' - compile project(':dd-trace-ot') compile project(':dd-java-agent:agent-tooling') compile deps.bytebuddy diff --git a/dd-java-agent/instrumentation/jsp-2.3/jsp-2.3.gradle b/dd-java-agent/instrumentation/jsp-2.3/jsp-2.3.gradle index 20a917fc85..785d7f363a 100644 --- a/dd-java-agent/instrumentation/jsp-2.3/jsp-2.3.gradle +++ b/dd-java-agent/instrumentation/jsp-2.3/jsp-2.3.gradle @@ -23,7 +23,6 @@ dependencies { compileOnly group: 'javax.servlet.jsp', name: 'javax.servlet.jsp-api', version: '2.3.0' compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0' - compile project(':dd-trace-ot') compile project(':dd-java-agent:agent-tooling') compile deps.bytebuddy diff --git a/dd-java-agent/instrumentation/okhttp-3/okhttp-3.gradle b/dd-java-agent/instrumentation/okhttp-3/okhttp-3.gradle index 9689977a12..9ec7e3cee4 100644 --- a/dd-java-agent/instrumentation/okhttp-3/okhttp-3.gradle +++ b/dd-java-agent/instrumentation/okhttp-3/okhttp-3.gradle @@ -17,10 +17,21 @@ testSets { } } +/* +Note: there is a bit of dependency exclusion magic goin on. +We have to exclude all transitive dependencies on 'okhttp' because we would like to force +specific version. We cannot use . Unfortunately we cannot just force version on +a dependency because this doesn't work well with version ranges - it doesn't select latest. +And we cannot use configurations to exclude this dependency from everywhere in one go +because it looks like exclusions using configurations excludes dependency even if it explicit +not transitive. + */ dependencies { - compileOnly group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.0.0' + compileOnly(group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.0.0') - compile project(':dd-java-agent:agent-tooling') + compile(project(':dd-java-agent:agent-tooling')) { + exclude module: 'okhttp' + } compile deps.bytebuddy compile deps.opentracing @@ -30,7 +41,9 @@ dependencies { testCompile(project(':dd-java-agent:testing')) { exclude module: 'okhttp' } - testCompile project(':dd-java-agent:instrumentation:java-concurrent') + testCompile(project(':dd-java-agent:instrumentation:java-concurrent')) { + exclude module: 'okhttp' + } testCompile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.0.0' // 4.x.x-alpha has been released and it looks like there are lots of incompatible changes diff --git a/dd-java-agent/instrumentation/rabbitmq-amqp-2.7/rabbitmq-amqp-2.7.gradle b/dd-java-agent/instrumentation/rabbitmq-amqp-2.7/rabbitmq-amqp-2.7.gradle index df36e2cd19..c0dfeac67c 100644 --- a/dd-java-agent/instrumentation/rabbitmq-amqp-2.7/rabbitmq-amqp-2.7.gradle +++ b/dd-java-agent/instrumentation/rabbitmq-amqp-2.7/rabbitmq-amqp-2.7.gradle @@ -20,7 +20,6 @@ testSets { dependencies { compileOnly group: 'com.rabbitmq', name: 'amqp-client', version: '2.7.0' - compile project(':dd-trace-ot') compile project(':dd-java-agent:agent-tooling') compile deps.bytebuddy diff --git a/dd-java-agent/instrumentation/servlet-3/servlet-3.gradle b/dd-java-agent/instrumentation/servlet-3/servlet-3.gradle index 16f3f0089d..3ce592b6c8 100644 --- a/dd-java-agent/instrumentation/servlet-3/servlet-3.gradle +++ b/dd-java-agent/instrumentation/servlet-3/servlet-3.gradle @@ -25,7 +25,6 @@ testSets { dependencies { compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '3.0.1' - compile project(':dd-trace-ot') compile project(':dd-java-agent:agent-tooling') compile deps.bytebuddy diff --git a/dd-java-agent/src/test/groovy/datadog/trace/agent/DDInfoTest.groovy b/dd-java-agent/src/test/groovy/datadog/trace/agent/DDInfoTest.groovy index 3a571d3bc7..26e465932b 100644 --- a/dd-java-agent/src/test/groovy/datadog/trace/agent/DDInfoTest.groovy +++ b/dd-java-agent/src/test/groovy/datadog/trace/agent/DDInfoTest.groovy @@ -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 - } } diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/utils/PortUtils.java b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/utils/PortUtils.java index 05d0fffac6..354df5799b 100644 --- a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/utils/PortUtils.java +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/utils/PortUtils.java @@ -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"); + } } diff --git a/dd-java-agent/testing/testing.gradle b/dd-java-agent/testing/testing.gradle index ab4818e1f1..4a951232a6 100644 --- a/dd-java-agent/testing/testing.gradle +++ b/dd-java-agent/testing/testing.gradle @@ -22,9 +22,6 @@ dependencies { compile group: 'org.eclipse.jetty', name: 'jetty-server', version: '8.0.0.v20110901' - compile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.11.0' - - compile project(':dd-trace-ot') compile project(':dd-java-agent:agent-tooling') annotationProcessor deps.autoservice diff --git a/dd-smoke-tests/dd-smoke-tests.gradle b/dd-smoke-tests/dd-smoke-tests.gradle index 7a3b0098d1..af0533c378 100644 --- a/dd-smoke-tests/dd-smoke-tests.gradle +++ b/dd-smoke-tests/dd-smoke-tests.gradle @@ -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}" + } +} diff --git a/dd-smoke-tests/play/play.gradle b/dd-smoke-tests/play/play.gradle index 999c8e7c85..2d002be527 100644 --- a/dd-smoke-tests/play/play.gradle +++ b/dd-smoke-tests/play/play.gradle @@ -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' } diff --git a/dd-smoke-tests/play/src/test/groovy/datadog/smoketest/PlaySmokeTest.groovy b/dd-smoke-tests/play/src/test/groovy/datadog/smoketest/PlaySmokeTest.groovy new file mode 100644 index 0000000000..6c22846cbc --- /dev/null +++ b/dd-smoke-tests/play/src/test/groovy/datadog/smoketest/PlaySmokeTest.groovy @@ -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) + } +} diff --git a/dd-smoke-tests/play/src/test/groovy/datadog/trace/agent/PlaySmokeTest.groovy b/dd-smoke-tests/play/src/test/groovy/datadog/trace/agent/PlaySmokeTest.groovy deleted file mode 100644 index c8d7dd2f5e..0000000000 --- a/dd-smoke-tests/play/src/test/groovy/datadog/trace/agent/PlaySmokeTest.groovy +++ /dev/null @@ -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) - } -} diff --git a/dd-smoke-tests/springboot/springboot.gradle b/dd-smoke-tests/springboot/springboot.gradle index c9011fd0c1..e6f504cdfe 100644 --- a/dd-smoke-tests/springboot/springboot.gradle +++ b/dd-smoke-tests/springboot/springboot.gradle @@ -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}" } diff --git a/dd-smoke-tests/springboot/src/test/groovy/datadog/smoketest/SpringBootSmokeTest.groovy b/dd-smoke-tests/springboot/src/test/groovy/datadog/smoketest/SpringBootSmokeTest.groovy new file mode 100644 index 0000000000..4fca377b95 --- /dev/null +++ b/dd-smoke-tests/springboot/src/test/groovy/datadog/smoketest/SpringBootSmokeTest.groovy @@ -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 command = new ArrayList<>() + command.add(javaPath()) + 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) + } +} diff --git a/dd-smoke-tests/springboot/src/test/groovy/datadog/trace/agent/SpringBootSmokeTest.groovy b/dd-smoke-tests/springboot/src/test/groovy/datadog/trace/agent/SpringBootSmokeTest.groovy deleted file mode 100644 index a53052b897..0000000000 --- a/dd-smoke-tests/springboot/src/test/groovy/datadog/trace/agent/SpringBootSmokeTest.groovy +++ /dev/null @@ -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) - } -} diff --git a/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractServerSmokeTest.groovy b/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractServerSmokeTest.groovy new file mode 100644 index 0000000000..60e575aad7 --- /dev/null +++ b/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractServerSmokeTest.groovy @@ -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) + } + +} diff --git a/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy b/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy new file mode 100644 index 0000000000..750b9d7cd3 --- /dev/null +++ b/dd-smoke-tests/src/main/groovy/datadog/smoketest/AbstractSmokeTest.groovy @@ -0,0 +1,55 @@ +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.environment().put("JAVA_HOME", System.getProperty("java.home")) + + processBuilder.redirectErrorStream(true) + File log = new File("${buildDirectory}/reports/serverProcess.log") + processBuilder.redirectOutput(ProcessBuilder.Redirect.to(log)) + + serverProcess = processBuilder.start() + } + + String javaPath() { + final String separator = System.getProperty("file.separator") + return System.getProperty("java.home") + separator + "bin" + separator + "java" + } + + def cleanupSpec() { + serverProcess?.waitForOrKill(1) + } + + abstract ProcessBuilder createProcessBuilder() +} diff --git a/dd-smoke-tests/wildfly/src/test/groovy/datadog/smoketest/WildflySmokeTest.groovy b/dd-smoke-tests/wildfly/src/test/groovy/datadog/smoketest/WildflySmokeTest.groovy new file mode 100644 index 0000000000..695e1c6acb --- /dev/null +++ b/dd-smoke-tests/wildfly/src/test/groovy/datadog/smoketest/WildflySmokeTest.groovy @@ -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) + } +} diff --git a/dd-smoke-tests/wildfly/src/test/groovy/datadog/trace/agent/WildflySmokeTest.groovy b/dd-smoke-tests/wildfly/src/test/groovy/datadog/trace/agent/WildflySmokeTest.groovy deleted file mode 100644 index cea9946ce9..0000000000 --- a/dd-smoke-tests/wildfly/src/test/groovy/datadog/trace/agent/WildflySmokeTest.groovy +++ /dev/null @@ -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) - } -} diff --git a/dd-smoke-tests/wildfly/wildfly.gradle b/dd-smoke-tests/wildfly/wildfly.gradle index d6e7e0e745..c0c058ef9b 100644 --- a/dd-smoke-tests/wildfly/wildfly.gradle +++ b/dd-smoke-tests/wildfly/wildfly.gradle @@ -1,15 +1,10 @@ -// 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 + + minJavaVersionForTests = JavaVersion.VERSION_1_8 } repositories { @@ -30,10 +25,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 +47,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}" - ] - +tasks.withType(Test).configureEach { 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 + jvmArgs "-Ddatadog.smoketest.wildflyDir=${buildDir}/${serverName}-${serverModule}-${serverVersion}" } diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 6dfaf3d7f6..f7b1741862 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -1,4 +1,4 @@ -def groovyVer = "2.5.6" +def groovyVer = "2.5.7" def spockGroovyVer = groovyVer.replaceAll(/\.\d+$/, '') ext { diff --git a/gradle/java.gradle b/gradle/java.gradle index 9f6b50da8f..e83c00b681 100644 --- a/gradle/java.gradle +++ b/gradle/java.gradle @@ -26,7 +26,7 @@ java { doFirst { // We do this specifically for Java7 bytecode generation because we would like to be able to compile // with Java8+ compiler. This likely would require some modifications when we switch to java11 compiler. - // Using proper Java7 bootstrap and extentions allows to be sure our code will run on real Java7. + // Using proper Java7 bootstrap and extensions allows to be sure our code will run on real Java7. if (JavaVersion.toVersion(sourceCompatibility) == JavaVersion.VERSION_1_7 && JavaVersion.current() != JavaVersion.VERSION_1_7 && System.env.JAVA_7_HOME != null) {