Skip to content

Add smoke test JUnit framework - #12111

Draft
PerfectSlayer wants to merge 1 commit into
masterfrom
bbujon/smoke-tests-junit-framework
Draft

Add smoke test JUnit framework#12111
PerfectSlayer wants to merge 1 commit into
masterfrom
bbujon/smoke-tests-junit-framework

Conversation

@PerfectSlayer

@PerfectSlayer PerfectSlayer commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

What Does This Do

DRAFT. Being refined. Opened for bot review.

This PR adds a JUnit 5 / Java smoke test framework that allows to write smoke tests using Java/JUnit 5 instead of Groovy/Spock.

The framework has four parts:

  • App runners: AbstractSmokeApp with SmokeServerApp (long-running/HTTP) and
    SmokeCliApp (batch) concrete types, registered as a @RegisterExtension.
    Owns the launched app's lifecycle and wires in the agent jar + test agent session token.

  • Backends: a common TraceBackend facade with two interchangeable implementations:
    MockAgentBackend (in-process JavaTestHttpServer, no Docker) and TestAgentBackend
    (a Testcontainers-managed, or external/CI, dd-apm-test-agent, scoped per test via
    X-Datadog-Test-Session-Token).
    A test written against the facade runs unchanged on either backend but the goal is moving toward TestAgentBackend by default.

  • Capture surfaces: Traces (msgpack/JSON decoded through the shared decoder),
    Telemetry (with message-batch flattening), and RemoteConfig (push a config the
    tracer polls for, and read back its /v0.7/config polls, with products/capabilities
    decoders).
    Traces, telemetry, and remote config are all isolated per test.

Motivation

WIP (extracting from one-pager, JIRA cards, and the other PRs)

Additional Notes

Contributor Checklist

Jira ticket: APMLP-1247

@PerfectSlayer PerfectSlayer added type: feature Enhancements and improvements comp: testing Testing tag: ai generated Largely based on code generated by an AI or LLM labels Jul 30, 2026
@dd-octo-sts

dd-octo-sts Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

🟢 Java Benchmark SLOs — All performance SLOs passed

Suite Status
Startup 🟢 pass

SLO thresholds are defined here based on automatically generated metrics. A warning is raised when results are within 5% of the threshold.

PR vs. master results
Scenario Candidate master Δ (95% CI of mean)
startup:insecure-bank:iast:Agent 13.98 s 14.01 s [-1.0%; +0.6%] (no difference)
startup:insecure-bank:tracing:Agent 12.94 s 13.02 s [-1.4%; +0.2%] (no difference)
startup:petclinic:appsec:Agent 16.96 s 16.81 s [+0.1%; +1.7%] (maybe worse)
startup:petclinic:iast:Agent 16.93 s 16.99 s [-1.2%; +0.5%] (no difference)
startup:petclinic:profiling:Agent 16.65 s 16.86 s [-2.4%; -0.1%] (maybe better)
startup:petclinic:sca:Agent 16.64 s 16.73 s [-1.6%; +0.5%] (no difference)
startup:petclinic:tracing:Agent 16.12 s 16.25 s [-1.6%; +0.1%] (no difference)

Commit: b6b0809c · CI Pipeline · Benchmarking Platform UI


Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion.

Base automatically changed from bbujon/smoke-tests-decoded-span-assertions to master July 31, 2026 06:04
@PerfectSlayer
PerfectSlayer force-pushed the bbujon/smoke-tests-junit-framework branch from 4a50f04 to 11530c9 Compare July 31, 2026 08:46
@datadog-datadog-us1-prod

datadog-datadog-us1-prod Bot commented Jul 31, 2026

Copy link
Copy Markdown

Bits has a CI fix ready

🟢 Investigated · 🟢 Fix prepared · ⚪ Validation skipped · 🟠 Ready

spotless failed because the new smoke-test backend sources did not match the repository Java formatter. Reformatted RemoteConfig.java, TelemetryDecoder.java, and TestAgentBackend.java without changing behavior.

Commit fix to this PR


View in Datadog | Reviewed commit 4abdba0 · Any feedback? Reach out in #deveng-pr-agent

@PerfectSlayer
PerfectSlayer force-pushed the bbujon/smoke-tests-junit-framework branch from 11530c9 to 4abdba0 Compare July 31, 2026 08:50
@PerfectSlayer

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4abdba0567

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread dd-smoke-tests/build.gradle Outdated
Comment thread dd-smoke-tests/src/main/java/datadog/smoketest/backend/TraceBackend.java Outdated
Comment thread dd-smoke-tests/src/main/java/datadog/smoketest/SmokeServerApp.java Outdated
Comment on lines +108 to +109
new PollingConditions(timeoutSeconds)
.eventually(() -> SmokeTraceAssertions.assertTraces(getTraces(), options, matchers));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject additional traces that arrive after an early match

For the default count-exact assertion, PollingConditions returns immediately when one snapshot matches. Because both backends receive traces asynchronously, the expected traces can match first and an additional trace from the same test action can arrive just afterward, causing the test to pass even though the final collection violates the exact-count contract; this also makes IGNORE_ADDITIONAL_TRACES ineffective as the distinction between strict and permissive behavior in that scenario. The strict path needs a stabilization/final-count check rather than accepting the first transient match.

Useful? React with 👍 / 👎.

Comment thread dd-smoke-tests/src/main/java/datadog/smoketest/SmokeCliApp.java Outdated
@PerfectSlayer
PerfectSlayer force-pushed the bbujon/smoke-tests-junit-framework branch 2 times, most recently from b169c19 to 9c11764 Compare July 31, 2026 12:26
@PerfectSlayer

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9c1176468d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +104 to +108
@Override
public void beforeEach(ExtensionContext context) {
if (clearsBetweenTests()) {
clear();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve startup traces for shared CLI backends

When a SmokeCliApp uses a backend that is also registered as a shared extension, the CLI process can finish and emit all of its traces during beforeAll, after which this beforeEach callback clears them before the test body runs. The CLI app's deliberate lack of an owned-backend reset cannot prevent this; TestAgentBackend only works if callers discover and enable retainAcrossTests(), while MockAgentBackend offers no retention mode, so shared CLI trace assertions are otherwise unusable.

Useful? React with 👍 / 👎.

Comment on lines +319 to +321
if (!this.process.waitFor(5, SECONDS)) {
this.process.destroyForcibly();
this.process.waitFor(10, SECONDS);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fail when forced process termination times out

If a child remains alive for ten seconds after destroyForcibly()—for example because process termination is delayed on the host—this ignores the false result from waitFor and lets teardown report success. The orphan can retain its server port and files and interfere with later test classes or Gradle tasks; check the result and surface a cleanup failure, as the existing ProcessManager teardown does.

Useful? React with 👍 / 👎.

Comment thread dd-smoke-tests/src/main/java/datadog/smoketest/backend/TestAgentBackend.java Outdated
@PerfectSlayer
PerfectSlayer force-pushed the bbujon/smoke-tests-junit-framework branch from 9c11764 to b6b0809 Compare July 31, 2026 13:45
@PerfectSlayer

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b6b0809cde

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@Override
public final void beforeEach(ExtensionContext context) {
onBeforeEach();
this.outputThreads.clearMessages();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve startup log messages for CLI apps

When a fast SmokeCliApp emits its output during beforeAll, this unconditional clear can erase those messages before the first test method calls awaitLogLine; whether the output survives depends on the race between the child/output thread and beforeEach. CLI suites that assert diagnostics produced during their one-shot execution therefore become flaky or always time out, so startup messages need the same retention treatment as CLI startup traces.

Useful? React with 👍 / 👎.

Comment on lines +418 to +420
public void assertTelemetryReceived() {
this.backend.telemetry().waitForCount(1, this.startupTimeoutSeconds);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Scope telemetry checks to the owning app

When multiple instrumented apps share one registered backend, every app's afterEach calls this against the same aggregated telemetry session, so a message or repeated heartbeat from app A makes app B's automatic check pass even if B never initialized telemetry. This creates a false negative in the supported shared multi-app composition; the check needs an app-specific identifier such as its runtime ID, or must otherwise avoid treating another app's telemetry as evidence for this app.

Useful? React with 👍 / 👎.

Comment on lines +26 to +27
private static final String INFO_BODY =
"{\"version\":\"7.77.0\",\"endpoints\":[\"/v0.4/traces\",\"/v0.5/traces\",\"/v1.0/traces\"]}";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Advertise client-side dropping in the mock agent

For sampled traces with SAMPLER_DROP or USER_DROP, this /info response omits client_drop_p0s, so DDAgentFeaturesDiscovery leaves its dropping policy inactive and the tracer serializes those traces to the mock backend. A real/test agent advertises this capability, and the existing smoke-test mock does too, so exact trace assertions can pass against one backend and receive additional dropped traces against the other; include the capability in the advertised agent information.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp: testing Testing tag: ai generated Largely based on code generated by an AI or LLM type: feature Enhancements and improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant