Skip to content

Java: Add InProcess FFI transport E2E test (task 4.8) - #2238

Merged
edburns merged 6 commits into
edburns/1917-java-embed-rust-cli-runtime-dd-3039924-agentic-run-02from
copilot/edburns1917-java-embed-rust-cli-runtime-dd-3039924
Aug 4, 2026
Merged

Java: Add InProcess FFI transport E2E test (task 4.8)#2238
edburns merged 6 commits into
edburns/1917-java-embed-rust-cli-runtime-dd-3039924-agentic-run-02from
copilot/edburns1917-java-embed-rust-cli-runtime-dd-3039924

Conversation

Copilot AI commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Task 4.8 of the Java "Embed Rust CLI runtime" plan: an E2E integration test exercising the InProcess FFI transport end-to-end with a real runtime.node binary — client connects, pings, disconnects — via FfiRuntimeHost.

New test infrastructure

  • InProcessEnvGuard — JNA-based utility that mutates the live OS process environment (setenv/SetEnvironmentVariableW) so native code loaded in-process (runtime.node) observes overrides Java's System.getenv() snapshot cannot express. AutoCloseable, restores prior values on close.
  • InProcessTransportIT — Failsafe IT performing a ping round-trip over RuntimeConnection.forInProcess(). No replay proxy needed since ping never reaches the network, mirroring the Go/Node/Python/Rust InProcess smoke tests.
  • SkipInProcess — JUnit 5 condition annotation to exclude tests incompatible with the InProcess transport (e.g. per-client env vars, see [Tracking] In-process (FFI) items to be cleaned up #1934).
  • -Pinprocess Maven profileforkCount=1, parallel=none (InProcess mutates process-global state), COPILOT_SDK_DEFAULT_CONNECTION=inprocess, and a dedicated copilot.inprocess.cli.path pointing at the real platform CLI binary rather than the npm-loader.js dispatcher. Adds a test-scoped dependency on the copilot-sdk-java-runtime:linux-x64 classifier jar as a classpath fallback for runtime.node.

Bug fix: runtime.node resolution

NativeRuntimeLoader.resolveFromCliPath() only checked for a flat runtime.node sibling next to the CLI binary. Real @github/copilot-<platform> npm packages ship it nested under prebuilds/<classifier>/runtime.node, so this path never resolved against actual installed packages:

// Before: only checked <cliDir>/runtime.node
// After: also checks <cliDir>/prebuilds/<classifier>/runtime.node
Path result = NativeRuntimeLoader.resolveFromCliPath(cliPath);

Also discovered along the way: System.getenv() is an immutable JVM-startup snapshot, so native setenv() calls made via InProcessEnvGuard after the JVM starts cannot affect COPILOT_CLI_PATH lookups done in Java code — that must be set before the JVM forks (handled via Surefire/Failsafe's <environmentVariables> in the new profile).

Tests

Added unit test coverage in NativeRuntimeLoaderTest for the new prebuilds/<classifier>/runtime.node resolution, including precedence over the flat layout when both exist.

Co-authored-by: edburns <75821+edburns@users.noreply.github.com>
Copilot AI changed the title [WIP] Create failsafe integration test for InProcess FFI transport Java: Add InProcess FFI transport E2E test (task 4.8) Aug 3, 2026
Copilot AI requested a review from edburns August 3, 2026 23:26
@github-actions

This comment has been minimized.

edburns
edburns previously requested changes Aug 3, 2026

@edburns edburns left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@copilot Please fix the following CI failure:

CI Failure: InProcessTransportIT fails without -Pinprocess profile

The InProcessTransportIT test runs in standard CI (mvn verify without -Pinprocess) and fails because the copilot-sdk-java-runtime:linux-x64 classifier JAR is only added as a dependency in the -Pinprocess profile, so native/linux-x64/runtime.node is not on the classpath.

java.io.FileNotFoundException: Native runtime not found on classpath: native/linux-x64/runtime.node — add the matching classifier JAR to the classpath

Fix: The InProcessTransportIT test should only run when the -Pinprocess profile is active. Add a JUnit 5 condition that checks for COPILOT_SDK_DEFAULT_CONNECTION=inprocess (set by the -Pinprocess profile) and disables the test otherwise. You could:

  1. Add @DisabledIfEnvironmentVariable(named = "COPILOT_SDK_DEFAULT_CONNECTION", matches = "(?!inprocess).*", disabledReason = "Requires -Pinprocess profile") or
  2. Create a custom condition annotation (the inverse of @SkipInProcess) that enables only when COPILOT_SDK_DEFAULT_CONNECTION=inprocess, or
  3. Use org.junit.jupiter.api.Assumptions.assumeTrue("inprocess".equals(System.getenv("COPILOT_SDK_DEFAULT_CONNECTION"))) at the start of the test.

The simplest approach is option 3 with assumeTrue in a @BeforeAll method.

Co-authored-by: edburns <75821+edburns@users.noreply.github.com>

Copilot AI commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please fix the following CI failure:

CI Failure: InProcessTransportIT fails without -Pinprocess profile...

Fixed in d49df45 (pushed as new commit): added a RequireInProcess JUnit 5 condition annotation (inverse of SkipInProcess) that only enables a test when COPILOT_SDK_DEFAULT_CONNECTION=inprocess, and applied it to InProcessTransportIT. Verified mvn -pl sdk verify (no -Pinprocess) now skips the test instead of failing.

Copilot AI requested a review from edburns August 3, 2026 23:41
@github-actions

This comment has been minimized.

edburns
edburns previously requested changes Aug 3, 2026

@edburns edburns left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@copilot Please fix the following CI failure:

CI Failure: Spotless formatting violation in RequireInProcess.java (JDK 25)

[ERROR] Failed to execute goal com.diffplug.spotless:spotless-maven-plugin:2.46.1:check on project copilot-sdk-java:
[ERROR]     src/test/java/com/github/copilot/e2e/RequireInProcess.java

The Javadoc line wrapping does not match the Eclipse formatter output. The formatter wants to reflow some Javadoc lines.

Fix: Run mvn spotless:apply from java/sdk and commit the reformatted RequireInProcess.java.

Co-authored-by: edburns <75821+edburns@users.noreply.github.com>

Copilot AI commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please fix the following CI failure:

CI Failure: Spotless formatting violation in RequireInProcess.java (JDK 25)...

Fixed by running mvn -pl sdk spotless:apply and committing the reformatted files. mvn -pl sdk spotless:check now passes.

Copilot AI requested a review from edburns August 3, 2026 23:52
@github-actions

This comment has been minimized.

@edburns
edburns dismissed stale reviews from themself August 4, 2026 00:00

Issues addressed in latest push

@edburns
edburns marked this pull request as ready for review August 4, 2026 00:01
@edburns
edburns requested a review from a team as a code owner August 4, 2026 00:01
Copilot AI review requested due to automatic review settings August 4, 2026 00:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds Java InProcess FFI test infrastructure and native runtime resolution support.

Changes:

  • Adds InProcess environment guards and test conditions.
  • Adds an InProcess Failsafe integration test and Maven profile.
  • Supports npm prebuilds/<classifier>/runtime.node layouts.
Show a summary per file
File Description
NativeRuntimeLoader.java Resolves nested npm runtime binaries.
NativeRuntimeLoaderTest.java Tests nested resolution and precedence.
InProcessEnvGuard.java Mutates native process environment.
InProcessTransportIT.java Exercises InProcess startup and ping.
SkipInProcess.java Adds an InProcess exclusion annotation.
RequireInProcess.java Adds an InProcess requirement annotation.
pom.xml Adds the InProcess test profile and runtime dependency.

Review details

  • Files reviewed: 7/7 changed files
  • Comments generated: 4
  • Review effort level: Balanced

Comment thread java/sdk/pom.xml
Comment thread java/sdk/src/test/java/com/github/copilot/e2e/InProcessTransportIT.java Outdated
Comment thread java/sdk/src/test/java/com/github/copilot/ffi/InProcessEnvGuard.java Outdated
…cope Surefire in -Pinprocess profile, fix Javadoc

- InProcessEnvGuard now reads previous env values via native getenv/
  GetEnvironmentVariableW instead of System.getenv() JVM snapshot, and
  correctly distinguishes absent variables from empty ones.
- The -Pinprocess Maven profile no longer overrides Surefire configuration,
  leaving existing unit tests on their standard transport.
- Javadoc corrected to point contributors to the java reactor root.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review details

Suppressed comments (1)

java/sdk/src/test/java/com/github/copilot/ffi/InProcessEnvGuard.java:142

  • On Windows, a zero return from GetEnvironmentVariableW also represents a variable that exists with an empty value; only GetLastError()==ERROR_ENVVAR_NOT_FOUND means absent. Treating every zero as null means the guard still restores an originally empty variable as unset, contrary to its save/restore contract. Preserve the Win32 last error through JNA and distinguish ERROR_SUCCESS (empty string) from ERROR_ENVVAR_NOT_FOUND (null).
        int len = kernel32.GetEnvironmentVariableW(new WString(name), buffer, buffer.length);
        if (len == 0) {
            // Variable not set (or error — treat as absent)
            return null;
  • Files reviewed: 7/7 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread java/sdk/pom.xml
Existing ITs set Environment/Cwd options incompatible with InProcess
transport. Restrict the profile to only the in-process smoke test until
the full in-process E2E suite is implemented.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Cross-SDK Consistency Review ✅

This PR brings Java into alignment with all other SDK implementations.

The bug fix in NativeRuntimeLoader.resolveFromCliPath() — adding fallback resolution to prebuilds/<classifier>/runtime.node in addition to the flat layout — mirrors the resolution logic already present in every other SDK:

SDK Flat layout prebuilds/<platform>/runtime.node
Python (_ffi_runtime_host.py:134-136)
Go (go/internal/ffihost/resolve.go:66,82)
.NET (FfiRuntimeHost.cs:92-96)
Rust (ffi.rs:476-481)
Java (this PR) ✅ (now fixed)

No cross-SDK consistency issues found. The changes maintain feature parity across all implementations.

Generated by SDK Consistency Review Agent for #2238 · sonnet46 16.7 AIC · ⌖ 5.38 AIC · ⊞ 6.6K ·

@edburns
edburns merged commit b138ca3 into edburns/1917-java-embed-rust-cli-runtime-dd-3039924-agentic-run-02 Aug 4, 2026
26 checks passed
@edburns
edburns deleted the copilot/edburns1917-java-embed-rust-cli-runtime-dd-3039924 branch August 4, 2026 01:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Java] Embed Rust CLI runtime 4.8: E2E integration test

3 participants