Ensure gradle runs base mongo test first

Otherwise there is a race condition between the projects initializing the mongo instance.
This commit is contained in:
Tyler Benson 2019-06-12 14:46:11 -07:00
parent d6719ed5cd
commit d26edd6c17
13 changed files with 150 additions and 79 deletions

View File

@ -28,7 +28,7 @@ dependencies {
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')
testCompile project(':dd-java-agent:instrumentation:mongo').sourceSets.test.output
testCompile group: 'de.flapdoodle.embed', name: 'de.flapdoodle.embed.mongo', version: '2.2.0'
testCompile group: 'org.mongodb', name: 'mongo-java-driver', version: '3.1.0'

View File

@ -5,18 +5,8 @@ import com.mongodb.ServerAddress
import com.mongodb.client.MongoCollection
import com.mongodb.client.MongoDatabase
import datadog.opentracing.DDSpan
import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.agent.test.asserts.TraceAssert
import datadog.trace.agent.test.utils.PortUtils
import datadog.trace.api.DDSpanTypes
import de.flapdoodle.embed.mongo.MongodExecutable
import de.flapdoodle.embed.mongo.MongodProcess
import de.flapdoodle.embed.mongo.MongodStarter
import de.flapdoodle.embed.mongo.config.IMongodConfig
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder
import de.flapdoodle.embed.mongo.config.Net
import de.flapdoodle.embed.mongo.distribution.Version
import de.flapdoodle.embed.process.runtime.Network
import io.opentracing.tag.Tags
import org.bson.BsonDocument
import org.bson.BsonString
@ -26,38 +16,18 @@ import spock.lang.Shared
import static datadog.trace.agent.test.utils.PortUtils.UNUSABLE_PORT
import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace
class MongoClientTest extends AgentTestRunner {
abstract class MongoClientTest extends MongoBaseTest {
@Shared
MongoClient client
@Shared
int port = PortUtils.randomOpenPort()
@Shared
MongodExecutable mongodExe
@Shared
MongodProcess mongod
def setup() throws Exception {
final MongodStarter starter = MongodStarter.getDefaultInstance()
final IMongodConfig mongodConfig =
new MongodConfigBuilder()
.version(Version.Main.PRODUCTION)
.net(new Net("localhost", port, Network.localhostIsIPv6()))
.build()
mongodExe = starter.prepare(mongodConfig)
mongod = mongodExe.start()
client = new MongoClient("localhost", port)
}
def cleanup() throws Exception {
client?.close()
client = null
mongod?.stop()
mongod = null
mongodExe?.stop()
mongodExe = null
}
def "test create collection"() {

View File

@ -20,10 +20,9 @@ testSets {
dependencies {
// use mongo listener
compile(project(':dd-java-agent:instrumentation:mongo-3.1')) {
compile(project(':dd-java-agent:instrumentation:mongo:driver-3.1')) {
transitive = false
}
compileOnly group: 'org.mongodb', name: 'mongo-java-driver', version: '3.3.0'
compileOnly group: 'org.mongodb', name: 'mongodb-driver-async', version: '3.3.0'
compile project(':dd-java-agent:agent-tooling')
@ -34,7 +33,7 @@ dependencies {
implementation deps.autoservice
testCompile project(':dd-java-agent:testing')
testCompile project(':dd-java-agent:instrumentation:mongo').sourceSets.test.output
testCompile group: 'de.flapdoodle.embed', name: 'de.flapdoodle.embed.mongo', version: '2.2.0'
testCompile group: 'org.mongodb', name: 'mongodb-driver-async', version: '3.3.0'

View File

@ -6,18 +6,8 @@ import com.mongodb.async.client.MongoDatabase
import com.mongodb.client.result.DeleteResult
import com.mongodb.client.result.UpdateResult
import datadog.opentracing.DDSpan
import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.agent.test.asserts.TraceAssert
import datadog.trace.agent.test.utils.PortUtils
import datadog.trace.api.DDSpanTypes
import de.flapdoodle.embed.mongo.MongodExecutable
import de.flapdoodle.embed.mongo.MongodProcess
import de.flapdoodle.embed.mongo.MongodStarter
import de.flapdoodle.embed.mongo.config.IMongodConfig
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder
import de.flapdoodle.embed.mongo.config.Net
import de.flapdoodle.embed.mongo.distribution.Version
import de.flapdoodle.embed.process.runtime.Network
import io.opentracing.tag.Tags
import org.bson.BsonDocument
import org.bson.BsonString
@ -31,38 +21,18 @@ import java.util.concurrent.CountDownLatch
import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace
@Timeout(10)
class MongoAsyncClientTest extends AgentTestRunner {
class MongoAsyncClientTest extends MongoBaseTest {
@Shared
MongoClient client
@Shared
int port = PortUtils.randomOpenPort()
@Shared
MongodExecutable mongodExe
@Shared
MongodProcess mongod
def setup() throws Exception {
final MongodStarter starter = MongodStarter.getDefaultInstance()
final IMongodConfig mongodConfig =
new MongodConfigBuilder()
.version(Version.Main.PRODUCTION)
.net(new Net("localhost", port, Network.localhostIsIPv6()))
.build()
mongodExe = starter.prepare(mongodConfig)
mongod = mongodExe.start()
client = MongoClients.create("mongodb://localhost:$port")
}
def cleanup() throws Exception {
client?.close()
client = null
mongod?.stop()
mongod = null
mongodExe?.stop()
mongodExe = null
}
def "test create collection"() {
@ -75,7 +45,11 @@ class MongoAsyncClientTest extends AgentTestRunner {
then:
assertTraces(1) {
trace(0, 1) {
mongoSpan(it, 0, "{ \"create\" : \"$collectionName\", \"capped\" : \"?\" }")
mongoSpan(it, 0) {
assert it == "{ \"create\" : \"$collectionName\", \"capped\" : \"?\" }" ||
it == "{\"create\": \"$collectionName\", \"capped\": \"?\", \"\$db\": \"?\", \"\$readPreference\": {\"mode\": \"?\"}}"
true
}
}
}
@ -96,7 +70,11 @@ class MongoAsyncClientTest extends AgentTestRunner {
count.get() == 0
assertTraces(1) {
trace(0, 1) {
mongoSpan(it, 0, "{ \"count\" : \"$collectionName\", \"query\" : { } }")
mongoSpan(it, 0) {
assert it == "{ \"count\" : \"$collectionName\", \"query\" : { } }" ||
it == "{\"count\": \"$collectionName\", \"query\": {}, \"\$db\": \"?\", \"\$readPreference\": {\"mode\": \"?\"}}"
true
}
}
}
@ -127,10 +105,18 @@ class MongoAsyncClientTest extends AgentTestRunner {
count.get() == 1
assertTraces(2) {
trace(0, 1) {
mongoSpan(it, 0, "{ \"insert\" : \"$collectionName\", \"ordered\" : \"?\", \"documents\" : [{ \"_id\" : \"?\", \"password\" : \"?\" }] }")
mongoSpan(it, 0) {
assert it == "{ \"insert\" : \"$collectionName\", \"ordered\" : \"?\", \"documents\" : [{ \"_id\" : \"?\", \"password\" : \"?\" }] }" ||
it == "{\"insert\": \"$collectionName\", \"ordered\": \"?\", \"\$db\": \"?\", \"documents\": [{\"_id\": \"?\", \"password\": \"?\"}]}"
true
}
}
trace(1, 1) {
mongoSpan(it, 0, "{ \"count\" : \"$collectionName\", \"query\" : { } }")
mongoSpan(it, 0) {
assert it == "{ \"count\" : \"$collectionName\", \"query\" : { } }" ||
it == "{\"count\": \"$collectionName\", \"query\": {}, \"\$db\": \"?\", \"\$readPreference\": {\"mode\": \"?\"}}"
true
}
}
}
@ -170,10 +156,18 @@ class MongoAsyncClientTest extends AgentTestRunner {
count.get() == 1
assertTraces(2) {
trace(0, 1) {
mongoSpan(it, 0, "{ \"update\" : \"?\", \"ordered\" : \"?\", \"updates\" : [{ \"q\" : { \"password\" : \"?\" }, \"u\" : { \"\$set\" : { \"password\" : \"?\" } } }] }")
mongoSpan(it, 0) {
assert it == "{ \"update\" : \"?\", \"ordered\" : \"?\", \"updates\" : [{ \"q\" : { \"password\" : \"?\" }, \"u\" : { \"\$set\" : { \"password\" : \"?\" } } }] }" ||
it == "{\"update\": \"?\", \"ordered\": \"?\", \"\$db\": \"?\", \"updates\": [{\"q\": {\"password\": \"?\"}, \"u\": {\"\$set\": {\"password\": \"?\"}}}]}"
true
}
}
trace(1, 1) {
mongoSpan(it, 0, "{ \"count\" : \"$collectionName\", \"query\" : { } }")
mongoSpan(it, 0) {
assert it == "{ \"count\" : \"$collectionName\", \"query\" : { } }" ||
it == "{\"count\": \"$collectionName\", \"query\": {}, \"\$db\": \"?\", \"\$readPreference\": {\"mode\": \"?\"}}"
true
}
}
}
@ -211,10 +205,18 @@ class MongoAsyncClientTest extends AgentTestRunner {
count.get() == 0
assertTraces(2) {
trace(0, 1) {
mongoSpan(it, 0, "{ \"delete\" : \"?\", \"ordered\" : \"?\", \"deletes\" : [{ \"q\" : { \"password\" : \"?\" }, \"limit\" : \"?\" }] }")
mongoSpan(it, 0) {
assert it == "{ \"delete\" : \"?\", \"ordered\" : \"?\", \"deletes\" : [{ \"q\" : { \"password\" : \"?\" }, \"limit\" : \"?\" }] }" ||
it == "{\"delete\": \"?\", \"ordered\": \"?\", \"\$db\": \"?\", \"deletes\": [{\"q\": {\"password\": \"?\"}, \"limit\": \"?\"}]}"
true
}
}
trace(1, 1) {
mongoSpan(it, 0, "{ \"count\" : \"$collectionName\", \"query\" : { } }")
mongoSpan(it, 0) {
assert it == "{ \"count\" : \"$collectionName\", \"query\" : { } }" ||
it == "{\"count\": \"$collectionName\", \"query\": {}, \"\$db\": \"?\", \"\$readPreference\": {\"mode\": \"?\"}}"
true
}
}
}
@ -236,11 +238,11 @@ class MongoAsyncClientTest extends AgentTestRunner {
}
}
def mongoSpan(TraceAssert trace, int index, String statement, Object parentSpan = null, Throwable exception = null) {
def mongoSpan(TraceAssert trace, int index, Closure<Boolean> statementEval, Object parentSpan = null, Throwable exception = null) {
trace.span(index) {
serviceName "mongo"
operationName "mongo.query"
resourceName statement
resourceName statementEval
spanType DDSpanTypes.MONGO
if (parentSpan == null) {
parent()
@ -251,7 +253,7 @@ class MongoAsyncClientTest extends AgentTestRunner {
"$Tags.COMPONENT.key" "java-mongo"
"$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT
"$Tags.DB_INSTANCE.key" "test_db"
"$Tags.DB_STATEMENT.key" statement
"$Tags.DB_STATEMENT.key" statementEval
"$Tags.DB_TYPE.key" "mongo"
"$Tags.PEER_HOSTNAME.key" "localhost"
"$Tags.PEER_HOST_IPV4.key" "127.0.0.1"

View File

@ -0,0 +1,28 @@
apply from: "${rootDir}/gradle/java.gradle"
dependencies {
testAnnotationProcessor deps.autoservice
testImplementation deps.autoservice
testCompile project(':dd-java-agent:testing')
testCompile group: 'de.flapdoodle.embed', name: 'de.flapdoodle.embed.mongo', version: '2.2.0'
}
// Forcing strict test execution order (no parallel execution) to ensure proper mongo executable initialization.
List<Test> testTasks = []
tasks.withType(Test) { Test testTask ->
testTasks.each {
testTask.shouldRunAfter(it)
}
testTasks.add(testTask)
}
subprojects {
afterEvaluate {
tasks.withType(Test) { Test testTask ->
testTasks.each {
testTask.shouldRunAfter(it)
}
testTasks.add(testTask)
}
}
}

View File

@ -0,0 +1,54 @@
import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.agent.test.utils.PortUtils
import de.flapdoodle.embed.mongo.MongodExecutable
import de.flapdoodle.embed.mongo.MongodProcess
import de.flapdoodle.embed.mongo.MongodStarter
import de.flapdoodle.embed.mongo.config.IMongodConfig
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder
import de.flapdoodle.embed.mongo.config.Net
import de.flapdoodle.embed.mongo.distribution.Version
import de.flapdoodle.embed.process.runtime.Network
import spock.lang.Shared
/**
* Testing needs to be in a centralized project.
* If tests in multiple different projects are using embedded mongo,
* they downloader is at risk of a race condition.
*/
class MongoBaseTest extends AgentTestRunner {
// https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo#executable-collision
private static final MongodStarter starter = MongodStarter.getDefaultInstance()
@Shared
int port = PortUtils.randomOpenPort()
@Shared
MongodExecutable mongodExe
@Shared
MongodProcess mongod
def setup() throws Exception {
final IMongodConfig mongodConfig =
new MongodConfigBuilder()
.version(Version.Main.PRODUCTION)
.net(new Net("localhost", port, Network.localhostIsIPv6()))
.build()
mongodExe = starter.prepare(mongodConfig)
mongod = mongodExe.start()
}
def cleanup() throws Exception {
mongod?.stop()
mongod = null
mongodExe?.stop()
mongodExe = null
}
def "test port open"() {
when:
new Socket("localhost", port)
then:
noExceptionThrown()
}
}

View File

@ -0,0 +1,12 @@
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import net.bytebuddy.agent.builder.AgentBuilder;
@AutoService(Instrumenter.class)
public class NoOpInstrumentation implements Instrumenter {
@Override
public AgentBuilder instrument(final AgentBuilder agentBuilder) {
return agentBuilder;
}
}

View File

@ -64,6 +64,11 @@ class SpanAssert {
checked.resourceName = true
}
def resourceName(Closure<Boolean> eval) {
assert eval(span.resourceName)
checked.resourceName = true
}
def resourceNameContains(String... resourceNameParts) {
assertSpanNameContains(span.resourceName, resourceNameParts)
checked.resourceName = true

View File

@ -66,8 +66,9 @@ include ':dd-java-agent:instrumentation:jsp-2.3'
include ':dd-java-agent:instrumentation:kafka-clients-0.11'
include ':dd-java-agent:instrumentation:kafka-streams-0.11'
include ':dd-java-agent:instrumentation:lettuce-5'
include ':dd-java-agent:instrumentation:mongo-3.1'
include ':dd-java-agent:instrumentation:mongo-async-3.3'
include ':dd-java-agent:instrumentation:mongo'
include ':dd-java-agent:instrumentation:mongo:driver-3.1'
include ':dd-java-agent:instrumentation:mongo:driver-async-3.3'
include ':dd-java-agent:instrumentation:netty-4.0'
include ':dd-java-agent:instrumentation:netty-4.1'
include ':dd-java-agent:instrumentation:okhttp-3'