-
Notifications
You must be signed in to change notification settings - Fork 304
Add smoke tests for java's concurrent API #8438
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 22 commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
063e30c
Create initial app and ExecutorService demo.
sarahchen6 84edb2b
Add ForkJoin demo.
sarahchen6 d101383
Start writing tests.
sarahchen6 11758ff
Add simple OTel spans for now.
sarahchen6 2153181
Add FibonacciCalculator interface and adjust tests and demos accordin…
sarahchen6 5ca2aab
Change trace expectations to reality.
sarahchen6 cc4c1a4
Extract calculations to helper function and update tests.
sarahchen6 58b15f1
Check that span name is as expected.
sarahchen6 cfb6aaa
Clean PR.
sarahchen6 02e1922
Update settings.gradle
sarahchen6 ea34748
Update dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/conc…
sarahchen6 3297e0c
Update dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/conc…
sarahchen6 7c62ddd
Update names.
sarahchen6 65411ad
Clean build.gradle.
sarahchen6 b4c1cd3
Format tests.
sarahchen6 ad0693a
Implement close method.
sarahchen6 b255c27
Organize methods in demo classes and add child span tests (but no chi…
sarahchen6 e0d9c91
Edit tests.
sarahchen6 23805ed
feat: Update executor app and checks
PerfectSlayer a9b0970
Propagate changes.
sarahchen6 f454512
Refactor tests.
sarahchen6 0023c3a
Fix variable name.
sarahchen6 6a0fae5
Adjust tests again.
sarahchen6 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
plugins { | ||
id 'java' | ||
id 'application' | ||
id 'com.github.johnrengelman.shadow' | ||
} | ||
|
||
apply from: "$rootDir/gradle/java.gradle" | ||
|
||
description = 'Concurrent Integration Tests.' | ||
|
||
application { | ||
mainClassName = 'datadog.smoketest.concurrent.ConcurrentApp' | ||
} | ||
|
||
dependencies { | ||
implementation('io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations:2.13.1') | ||
implementation project(':dd-trace-api') | ||
testImplementation project(':dd-smoke-tests') | ||
|
||
testImplementation platform('org.junit:junit-bom:5.10.0') | ||
testImplementation 'org.junit.jupiter:junit-jupiter' | ||
} | ||
|
||
test { | ||
useJUnitPlatform() | ||
} | ||
|
||
tasks.withType(Test).configureEach { | ||
dependsOn "shadowJar" | ||
|
||
jvmArgs "-Ddatadog.smoketest.shadowJar.path=${tasks.shadowJar.archiveFile.get()}" | ||
} |
27 changes: 27 additions & 0 deletions
27
dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/ConcurrentApp.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package datadog.smoketest.concurrent; | ||
|
||
import io.opentelemetry.instrumentation.annotations.WithSpan; | ||
import java.util.concurrent.ExecutionException; | ||
|
||
public class ConcurrentApp { | ||
@WithSpan("main") | ||
public static void main(String[] args) { | ||
// Calculate fibonacci using concurrent strategies | ||
for (String arg : args) { | ||
try (FibonacciCalculator calc = getCalculator(arg)) { | ||
calc.computeFibonacci(10); | ||
} catch (ExecutionException | InterruptedException e) { | ||
throw new RuntimeException("Failed to compute fibonacci number.", e); | ||
} | ||
} | ||
} | ||
|
||
private static FibonacciCalculator getCalculator(String name) { | ||
if (name.equalsIgnoreCase("executorService")) { | ||
return new DemoExecutorService(); | ||
} else if (name.equalsIgnoreCase("forkJoin")) { | ||
return new DemoForkJoin(); | ||
} | ||
throw new IllegalArgumentException("Unknown calculator: " + name); | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
...moke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/DemoExecutorService.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package datadog.smoketest.concurrent; | ||
|
||
import static java.util.concurrent.TimeUnit.MILLISECONDS; | ||
|
||
import io.opentelemetry.instrumentation.annotations.WithSpan; | ||
import java.util.concurrent.Callable; | ||
import java.util.concurrent.ExecutionException; | ||
import java.util.concurrent.ExecutorService; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.Future; | ||
|
||
public class DemoExecutorService implements FibonacciCalculator { | ||
private final ExecutorService executorService; | ||
|
||
public DemoExecutorService() { | ||
executorService = Executors.newFixedThreadPool(10); | ||
} | ||
|
||
@WithSpan("compute") | ||
@Override | ||
public long computeFibonacci(int n) throws ExecutionException, InterruptedException { | ||
Future<Long> future = executorService.submit(new FibonacciTask(n)); | ||
return future.get(); | ||
} | ||
|
||
private class FibonacciTask implements Callable<Long> { | ||
private final int n; | ||
|
||
public FibonacciTask(int n) { | ||
this.n = n; | ||
} | ||
|
||
@Override | ||
public Long call() throws ExecutionException, InterruptedException { | ||
if (n <= 1) { | ||
return (long) n; | ||
} | ||
return computeFibonacci(n - 1) + computeFibonacci(n - 2); | ||
} | ||
} | ||
|
||
@Override | ||
public void close() { | ||
executorService.shutdown(); | ||
try { | ||
if (!executorService.awaitTermination(800, MILLISECONDS)) { | ||
executorService.shutdownNow(); | ||
} | ||
} catch (InterruptedException e) { | ||
executorService.shutdownNow(); | ||
} | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
dd-smoke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/DemoForkJoin.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package datadog.smoketest.concurrent; | ||
|
||
import io.opentelemetry.instrumentation.annotations.WithSpan; | ||
import java.util.concurrent.ForkJoinPool; | ||
import java.util.concurrent.RecursiveTask; | ||
|
||
public class DemoForkJoin implements FibonacciCalculator { | ||
private final ForkJoinPool forkJoinPool; | ||
|
||
public DemoForkJoin() { | ||
forkJoinPool = new ForkJoinPool(); | ||
} | ||
|
||
@WithSpan("compute") | ||
@Override | ||
public long computeFibonacci(int n) { | ||
return forkJoinPool.invoke(new FibonacciTask(n)); | ||
} | ||
|
||
private class FibonacciTask extends RecursiveTask<Long> { | ||
private final int n; | ||
|
||
public FibonacciTask(int n) { | ||
this.n = n; | ||
} | ||
|
||
@Override | ||
protected Long compute() { | ||
if (n <= 1) { | ||
return (long) n; | ||
} | ||
FibonacciTask taskOne = new FibonacciTask(n - 1); | ||
taskOne.fork(); | ||
FibonacciTask taskTwo = new FibonacciTask(n - 2); | ||
return taskTwo.compute() + taskOne.join(); | ||
} | ||
} | ||
|
||
@Override | ||
public void close() { | ||
forkJoinPool.shutdown(); | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
...moke-tests/concurrent/src/main/java/datadog/smoketest/concurrent/FibonacciCalculator.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package datadog.smoketest.concurrent; | ||
|
||
import java.util.concurrent.ExecutionException; | ||
|
||
public interface FibonacciCalculator extends AutoCloseable { | ||
long computeFibonacci(int n) throws ExecutionException, InterruptedException; | ||
|
||
@Override | ||
void close(); | ||
} |
61 changes: 61 additions & 0 deletions
61
dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/AbstractDemoTest.groovy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package datadog.smoketest | ||
|
||
import datadog.trace.test.agent.decoder.DecodedTrace | ||
|
||
import java.util.function.Function | ||
|
||
abstract class AbstractDemoTest extends AbstractSmokeTest { | ||
protected static final int TIMEOUT_SECS = 10 | ||
protected abstract List<String> getTestArguments() | ||
|
||
@Override | ||
ProcessBuilder createProcessBuilder() { | ||
def jarPath = System.getProperty("datadog.smoketest.shadowJar.path") | ||
def command = new ArrayList<String>() | ||
command.add(javaPath()) | ||
command.addAll(defaultJavaProperties) | ||
command.add("-Ddd.trace.otel.enabled=true") | ||
command.addAll(["-jar", jarPath]) | ||
command.addAll(getTestArguments()) | ||
|
||
ProcessBuilder processBuilder = new ProcessBuilder(command) | ||
processBuilder.directory(new File(buildDirectory)) | ||
} | ||
|
||
@Override | ||
Closure decodedTracesCallback() { | ||
return {} // force traces decoding | ||
} | ||
|
||
protected static Function<DecodedTrace, Boolean> checkTrace() { | ||
return { | ||
trace -> | ||
// Get root span | ||
def rootSpan = trace.spans.find { it.name == 'main' } | ||
if (!rootSpan) { | ||
return false | ||
} | ||
// Check that there are only 'main' and 'compute' spans | ||
def otherSpans = trace.spans.findAll { it.name != 'main' && it.name != 'compute' } | ||
if (!otherSpans.isEmpty()) { | ||
return false | ||
} | ||
// Check every 'compute' span is either a child of the root span or another 'compute' span | ||
def computeSpans = trace.spans.findAll { it.name == 'compute' } | ||
if (computeSpans.isEmpty()) { | ||
return false | ||
} | ||
return computeSpans.every { | ||
// Check same trace | ||
if (it.traceId != rootSpan.traceId) { | ||
return false | ||
} | ||
// Check parent | ||
if (it.parentId != rootSpan.spanId && trace.spans.find(s -> s.spanId == it.parentId).name != 'compute') { | ||
return false | ||
} | ||
return true | ||
} | ||
} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoExecutorServiceTest.groovy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package datadog.smoketest | ||
|
||
import static java.util.concurrent.TimeUnit.SECONDS | ||
|
||
class DemoExecutorServiceTest extends AbstractDemoTest { | ||
@Override | ||
protected List<String> getTestArguments() { | ||
return ["executorService"] | ||
} | ||
|
||
def 'receive one expected trace for ExecutorService'() { | ||
when: | ||
waitForTrace(defaultPoll, checkTrace()) | ||
|
||
then: | ||
traceCount.get() == 1 | ||
|
||
and: | ||
assert testedProcess.waitFor(TIMEOUT_SECS, SECONDS) | ||
assert testedProcess.exitValue() == 0 | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoForkJoinTest.groovy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package datadog.smoketest | ||
|
||
import static java.util.concurrent.TimeUnit.SECONDS | ||
|
||
class DemoForkJoinTest extends AbstractDemoTest { | ||
@Override | ||
protected List<String> getTestArguments() { | ||
return ["forkJoin"] | ||
} | ||
|
||
def 'receive one expected trace for ExecutorService'() { | ||
sarahchen6 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
when: | ||
waitForTrace(defaultPoll, checkTrace()) | ||
|
||
then: | ||
traceCount.get() == 1 | ||
|
||
and: | ||
assert testedProcess.waitFor(TIMEOUT_SECS, SECONDS) | ||
assert testedProcess.exitValue() == 0 | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
dd-smoke-tests/concurrent/src/test/groovy/datadog/smoketest/DemoMixedConcurrencyTest.groovy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package datadog.smoketest | ||
|
||
import static java.util.concurrent.TimeUnit.SECONDS | ||
|
||
class DemoMixedConcurrencyTest extends AbstractDemoTest { | ||
@Override | ||
protected List<String> getTestArguments() { | ||
return ["executorService", "forkJoin"] | ||
} | ||
|
||
def 'receive one expected trace for ExecutorService'() { | ||
when: | ||
waitForTrace(defaultPoll, checkTrace()) | ||
|
||
then: | ||
traceCount.get() == 1 | ||
|
||
and: | ||
assert testedProcess.waitFor(TIMEOUT_SECS, SECONDS) | ||
assert testedProcess.exitValue() == 0 | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.