Skip to content

Commit

Permalink
Fix NPE in logic that parses flaky tests list (#8070)
Browse files Browse the repository at this point in the history
  • Loading branch information
nikita-tkachenko-datadog authored Dec 9, 2024
1 parent 88c9405 commit 4524f7b
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ public SkippableTests getSkippableTests(TracerEnvironment tracerEnvironment) thr
for (DataDto<TestIdentifierJson> dataDto : response.data) {
TestIdentifierJson testIdentifierJson = dataDto.getAttributes();
Configurations conf = testIdentifierJson.getConfigurations();
String moduleName = (conf != null ? conf : requestConf).getTestBundle();
String moduleName =
(conf != null && conf.getTestBundle() != null ? conf : requestConf).getTestBundle();
testIdentifiersByModule
.computeIfAbsent(moduleName, k -> new HashMap<>())
.put(testIdentifierJson.toTestIdentifier(), testIdentifierJson.toTestMetadata());
Expand Down Expand Up @@ -211,12 +212,15 @@ public Map<String, Collection<TestIdentifier>> getFlakyTestsByModule(

LOGGER.debug("Received {} flaky tests in total", response.size());

Configurations requestConf = tracerEnvironment.getConfigurations();

int flakyTestsCount = 0;
Map<String, Collection<TestIdentifier>> testIdentifiers = new HashMap<>();
for (DataDto<TestIdentifierJson> dataDto : response) {
TestIdentifierJson testIdentifierJson = dataDto.getAttributes();
Configurations configurations = testIdentifierJson.getConfigurations();
String moduleName = configurations.getTestBundle();
Configurations conf = testIdentifierJson.getConfigurations();
String moduleName =
(conf != null && conf.getTestBundle() != null ? conf : requestConf).getTestBundle();
testIdentifiers
.computeIfAbsent(moduleName, k -> new HashSet<>())
.add(testIdentifierJson.toTestIdentifier());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,14 @@ class ConfigurationApiImplTest extends Specification {
return
}

def testBundle = requestConfs['test.bundle']

def moduleATest = """{
"id": "49968354e2091cdb",
"type": "test",
"attributes": {
"configurations": {
"test.bundle": "testBundle-a",
${!testBundle ? '"test.bundle": "testBundle-a",' : ""}
"custom": {
"customTag": "customValue"
}
Expand All @@ -164,7 +166,7 @@ class ConfigurationApiImplTest extends Specification {
"type": "test",
"attributes": {
"configurations": {
"test.bundle": "testBundle-b",
${!testBundle ? '"test.bundle": "testBundle-b",' : ""}
"custom": {
"customTag": "customValue"
}
Expand All @@ -175,8 +177,115 @@ class ConfigurationApiImplTest extends Specification {
}
}"""

def tests = []
if (!testBundle || testBundle == 'testBundle-a') {
tests << moduleATest
}
if (!testBundle || testBundle == 'testBundle-b') {
tests << moduleBTest
}

def response = response
def requestBody = """
{
"data": [
${tests.join(',')}
],
"meta": {
"correlation_id": "11223344",
"coverage": {
"src/main/java/Calculator.java": "/8AA/w==",
"src/main/java/utils/Math.java": "AAAAf+AA/A==",
"src/test/java/CalculatorTest.java": "//AAeAAA/A=="
}
}
}
""".bytes

def header = request.getHeader("Accept-Encoding")
def gzipSupported = header != null && header.contains("gzip")
if (gzipSupported) {
response.addHeader("Content-Encoding", "gzip")
requestBody = gzip(requestBody)
}

response.status(200).send(requestBody)
}

prefix("/api/v2/ci/libraries/tests/flaky") {
def requestJson = moshi.adapter(Map).fromJson(new String(request.body))

// assert request contents
def requestData = requestJson['data']
if (requestData['type'] != "flaky_test_from_libraries_params"
|| requestData['id'] != "1234"
) {
response.status(400).send()
return
}

def requestAttrs = requestData['attributes']
if (requestAttrs['service'] != "foo"
|| requestAttrs['env'] != "foo_env"
|| requestAttrs['repository_url'] != "https://github.com/DataDog/foo"
|| requestAttrs['branch'] != "prod"
|| requestAttrs['sha'] != "d64185e45d1722ab3a53c45be47accae"
|| requestAttrs['test_level'] != "test"
) {
response.status(400).send()
return
}

def requestConfs = requestAttrs['configurations']
if (requestConfs['os.platform'] != "linux"
|| requestConfs['os.architecture'] != "amd64"
|| requestConfs['os.arch'] != "amd64"
|| requestConfs['os.version'] != "bionic"
|| requestConfs['runtime.name'] != "runtimeName"
|| requestConfs['runtime.version'] != "runtimeVersion"
|| requestConfs['runtime.vendor'] != "vendor"
|| requestConfs['runtime.architecture'] != "amd64"
|| requestConfs['custom']['customTag'] != "customValue"
) {
response.status(400).send()
return
}

def testBundle = requestConfs['test.bundle']

def moduleATest = """{
"id": "49968354e2091cdb",
"type": "test",
"attributes": {
"configurations": {
${!testBundle ? '"test.bundle": "testBundle-a",' : ""}
"custom": {
"customTag": "customValue"
}
},
"suite": "suite-a",
"name": "name-a",
"parameters": "parameters-a",
"_missing_line_code_coverage": true
}
}"""

def moduleBTest = """{
"id": "49968354e2091cdc",
"type": "test",
"attributes": {
"configurations": {
${!testBundle ? '"test.bundle": "testBundle-b",' : ""}
"custom": {
"customTag": "customValue"
}
},
"suite": "suite-b",
"name": "name-b",
"parameters": "parameters-b"
}
}"""

def tests = []
if (!testBundle || testBundle == 'testBundle-a') {
tests << moduleATest
Expand Down Expand Up @@ -372,6 +481,45 @@ class ConfigurationApiImplTest extends Specification {
]
}

def "test flaky tests request: #displayName"() {
given:
def tracerEnvironment = givenTracerEnvironment()
def metricCollector = Stub(CiVisibilityMetricCollector)

when:
def configurationApi = new ConfigurationApiImpl(api, metricCollector, () -> "1234")
def flakyTests = configurationApi.getFlakyTestsByModule(tracerEnvironment)

then:
flakyTests == [
"testBundle-a": new HashSet<>([ new TestIdentifier("suite-a", "name-a", "parameters-a") ]),
"testBundle-b": new HashSet<>([ new TestIdentifier("suite-b", "name-b", "parameters-b") ]),
]

where:
api | displayName
givenEvpProxy(false) | "EVP proxy, compression disabled"
givenEvpProxy(true) | "EVP proxy, compression enabled"
givenIntakeApi(false) | "intake, compression disabled"
givenIntakeApi(true) | "intake, compression enabled"
}

def "test flaky tests request with module name"() {
given:
def tracerEnvironment = givenTracerEnvironment("testBundle-a")
def metricCollector = Stub(CiVisibilityMetricCollector)
def api = givenIntakeApi(false)

when:
def configurationApi = new ConfigurationApiImpl(api, metricCollector, () -> "1234")
def flakyTests = configurationApi.getFlakyTestsByModule(tracerEnvironment)

then:
flakyTests == [
"testBundle-a": new HashSet<>([ new TestIdentifier("suite-a", "name-a", "parameters-a") ])
]
}

private static BitSet bits(int... bits) {
BitSet bitSet = new BitSet()
for (int bit : bits) {
Expand Down

0 comments on commit 4524f7b

Please sign in to comment.