Skip to content

[Java] Post-agentic 01: Achieve 100% InProcess / out-of-process test parity #2271

Description

@edburns

Overview

Achieve 100% test parity between the InProcess (FFI) transport and the existing out-of-process (stdio/TCP) transport. Every Surefire unit test and Failsafe integration test that runs under the default transport must also run under the InProcess transport, or be explicitly annotated with @SkipInProcess with a documented reason.

Branch: edburns/1917-java-embed-rust-cli-runtime-post-agentic-01-test-parity on upstream

Plan and supporting resources

On the edburns/1917-java-embed-rust-cli-runtime-post-agentic-01-test-parity branch, the directory 1917-java-embed-rust-cli-runtime-remove-before-merge contains the plan (1917-embed-cli-runtime-ignorance-reduction-plan.md) and supporting resources (spikes, prototypes, diagrams).

Read the entire plan before working.

Relevant plan sections to carefully re-read

  • Section 3.11 — E2E testing with InProcess transport — Resolution: Read the full evidence in 1917-java-embed-rust-cli-runtime-remove-before-merge/spike-3-11-replay-proxy-and-in-process/. Key answers:
    1. Replay proxy works with InProcess — the replay proxy intercepts HTTP calls to COPILOT_API_URL. The runtime reads COPILOT_API_URL from the native process environment block.
    2. Use real runtime.node binary — from the copilot-native module.
    3. No mock native library for E2E — only unit tests use mocks.
    4. Reuse existing YAML snapshots — HTTP traffic is identical regardless of transport.
    5. Run full E2E suite under both transports — subprocess (existing job A) and InProcess (new job B with -Pinprocess Maven profile).
  • InProcessEnvGuard requirement — calls SetEnvironmentVariableW (Windows) or setenv() (Linux/macOS) via JNA to mutate process environment before host_start. Restores on close(). Already implemented in com.github.copilot.ffi.InProcessEnvGuard.
  • Concurrency must be 1InProcessEnvGuard mutates process-global state. Use surefire.forkCount=1 or JUnit 5 @ResourceLock.
  • @SkipInProcess annotation — Already implemented in com.github.copilot.e2e.SkipInProcess. JUnit 5 condition annotation for tests incompatible with InProcess transport (e.g., per-client environment variables — see issue [Tracking] In-process (FFI) items to be cleaned up #1934).
  • Section 3.12 — CI/CD workflow changes — Resolution: java-sdk-inprocess job in java-sdk-tests.yml already exists.
  • Hard scope invariant: Linux-x64 only. No other platform E2E tests in this phase.

Current state

The following infrastructure already exists on the branch:

  • InProcessEnvGuard in com.github.copilot.ffi — sets/restores native env vars via JNA.
  • @SkipInProcess annotation in com.github.copilot.e2e — JUnit 5 condition for skipping incompatible tests.
  • @RequireInProcess annotation in com.github.copilot.e2e — JUnit 5 condition for InProcess-only tests.
  • InProcessTransportIT — single Failsafe smoke test that passes under -Pinprocess.
  • -Pinprocess Maven profile — activates InProcess transport for Failsafe.
  • java-sdk-inprocess CI job — runs mvn clean verify -Pinprocess.

Identified gaps

Gap 1: Failsafe IT parity

The -Pinprocess profile failsafe configuration only includes **/InProcessTransportIT.java. The other 6 ITs are excluded:

  • ErgonomicToolDefinitionIT
  • GitHubTelemetryForwardingIT
  • InternalExecutorProviderIT
  • LowLevelToolDefinitionIT
  • SlashCommandsIT
  • SystemMessageSectionsIT

Fix: Remove the <includes> restriction from the inprocess profile failsafe config so all ITs run. Annotate any IT that is inherently incompatible with @SkipInProcess (with reason).

Gap 2: Surefire E2E test parity

Many surefire tests use E2ETestContext and exercise real CLI interactions. These never run under InProcess because:

  1. The CI step no longer sets COPILOT_SDK_DEFAULT_CONNECTION=inprocess (we removed it to fix 195 surefire failures caused by env var leaking into tests that set cliPath/environment/cwd).
  2. E2ETestContext.createClient() unconditionally sets cliPath, environment, and cwd on CopilotClientOptions — all three are rejected by CopilotClient.validateEnvironmentOptions() for InProcess connections.

Fix: Update E2ETestContext.createClient() to detect InProcess mode and:

  • Skip setting cliPath, environment, and cwd on options.
  • Instead, use InProcessEnvGuard to set the required env vars in the native process environment.
  • Re-add COPILOT_SDK_DEFAULT_CONNECTION=inprocess to surefire <environmentVariables> in the inprocess profile (not the CI step env).

Gap 3: Tests with direct client creation

Some tests create CopilotClient directly (not via E2ETestContext) with stdio-specific options (cliPath, cliArgs, cwd). These are inherently incompatible with InProcess transport.

Fix: Annotate each with @SkipInProcess and a reason. Examples:

  • ClientOptionsE2ETest — tests CLI argument forwarding.
  • Tests in CopilotClientTest that set cliArgs or test CLI startup behavior.

Deliverables

Files to modify

  1. java/sdk/pom.xml — Update the -Pinprocess profile:

    • Remove <includes> restriction from failsafe so all ITs run.
    • Add COPILOT_SDK_DEFAULT_CONNECTION=inprocess to surefire <environmentVariables>.
    • Ensure forkCount=1 and parallel=none for both surefire and failsafe.
  2. java/sdk/src/test/java/com/github/copilot/E2ETestContext.java — Update createClient() methods to:

    • Detect InProcess mode (via explicit connection or COPILOT_SDK_DEFAULT_CONNECTION env var).
    • Skip incompatible options (cliPath, environment, cwd).
    • Use InProcessEnvGuard for native env setup.
  3. Various test classes — Add @SkipInProcess("reason") to tests that are inherently incompatible with InProcess transport.

No files to create

All required infrastructure (InProcessEnvGuard, @SkipInProcess, @RequireInProcess) already exists.

Gating tests and criteria

  1. Full parity verified: mvn clean verify -Pinprocess from java/ runs all surefire and failsafe tests under InProcess transport (except those annotated @SkipInProcess).
  2. Same test count: The number of tests run + skipped under -Pinprocess equals the number run + skipped under the default profile.
  3. Standard tests unaffected: mvn clean verify (without -Pinprocess) passes with no regressions.
  4. CI passes: Both java-sdk and java-sdk-inprocess CI jobs pass.
  5. Spotless compliance: mvn spotless:check passes.
  6. Every @SkipInProcess has a reason documenting why the test is incompatible.

Out of scope

  • Testing on any platform other than linux-x64.
  • Adding new test scenarios — this task is about running existing tests under both transports.
  • Changes to production code in src/main/java (except if CopilotClient.validateEnvironmentOptions needs adjustment).

Parent issue: #2268

Activity

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

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions