diff --git a/src/test/java/com/github/copilot/sdk/CapiProxy.java b/src/test/java/com/github/copilot/sdk/CapiProxy.java index 1a7df2d6c..bcd064d94 100644 --- a/src/test/java/com/github/copilot/sdk/CapiProxy.java +++ b/src/test/java/com/github/copilot/sdk/CapiProxy.java @@ -89,7 +89,11 @@ public String start() throws IOException, InterruptedException { } // Start the harness server using npx tsx - var pb = new ProcessBuilder("npx", "tsx", "server.ts"); + // On Windows, npx is installed as npx.cmd which requires cmd /c to launch + boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win"); + var pb = isWindows + ? new ProcessBuilder("cmd", "/c", "npx", "tsx", "server.ts") + : new ProcessBuilder("npx", "tsx", "server.ts"); pb.directory(harnessDir.toFile()); pb.redirectErrorStream(false); diff --git a/src/test/java/com/github/copilot/sdk/CliServerManagerTest.java b/src/test/java/com/github/copilot/sdk/CliServerManagerTest.java index e59d03ae8..e556839cc 100644 --- a/src/test/java/com/github/copilot/sdk/CliServerManagerTest.java +++ b/src/test/java/com/github/copilot/sdk/CliServerManagerTest.java @@ -131,6 +131,14 @@ void processInfoWithNullPort() { // resolveCliCommand is private, so we test indirectly through startCliServer // with specific cliPath values. + // On Windows, "/nonexistent/copilot" is not an absolute path (no drive letter), + // so resolveCliCommand wraps it with "cmd /c" and ProcessBuilder.start() + // succeeds + // (launching cmd.exe). Use a Windows-absolute path to ensure IOException. + private static final String NONEXISTENT_CLI = System.getProperty("os.name").toLowerCase().contains("win") + ? "C:\\nonexistent\\copilot" + : "/nonexistent/copilot"; + @Test void startCliServerWithJsFile() throws Exception { // Using a .js file path causes resolveCliCommand to prepend "node" @@ -152,8 +160,8 @@ void startCliServerWithJsFile() throws Exception { @Test void startCliServerWithCliArgs() throws Exception { // Test that cliArgs are included in the command - var options = new CopilotClientOptions().setCliPath("/nonexistent/copilot") - .setCliArgs(new String[]{"--extra-flag"}).setUseStdio(true); + var options = new CopilotClientOptions().setCliPath(NONEXISTENT_CLI).setCliArgs(new String[]{"--extra-flag"}) + .setUseStdio(true); var manager = new CliServerManager(options); var ex = assertThrows(IOException.class, () -> manager.startCliServer()); @@ -163,7 +171,7 @@ void startCliServerWithCliArgs() throws Exception { @Test void startCliServerWithExplicitPort() throws Exception { // Test the explicit port branch (useStdio=false, port > 0) - var options = new CopilotClientOptions().setCliPath("/nonexistent/copilot").setUseStdio(false).setPort(9999); + var options = new CopilotClientOptions().setCliPath(NONEXISTENT_CLI).setUseStdio(false).setPort(9999); var manager = new CliServerManager(options); var ex = assertThrows(IOException.class, () -> manager.startCliServer()); @@ -173,7 +181,7 @@ void startCliServerWithExplicitPort() throws Exception { @Test void startCliServerWithGitHubToken() throws Exception { // Test the github token branch - var options = new CopilotClientOptions().setCliPath("/nonexistent/copilot").setGitHubToken("ghp_test123") + var options = new CopilotClientOptions().setCliPath(NONEXISTENT_CLI).setGitHubToken("ghp_test123") .setUseStdio(true); var manager = new CliServerManager(options); @@ -184,7 +192,7 @@ void startCliServerWithGitHubToken() throws Exception { @Test void startCliServerWithUseLoggedInUserExplicit() throws Exception { // Test the explicit useLoggedInUser=false branch (adds --no-auto-login) - var options = new CopilotClientOptions().setCliPath("/nonexistent/copilot").setUseLoggedInUser(false) + var options = new CopilotClientOptions().setCliPath(NONEXISTENT_CLI).setUseLoggedInUser(false) .setUseStdio(true); var manager = new CliServerManager(options); @@ -195,7 +203,7 @@ void startCliServerWithUseLoggedInUserExplicit() throws Exception { @Test void startCliServerWithGitHubTokenAndNoExplicitUseLoggedInUser() throws Exception { // When gitHubToken is set and useLoggedInUser is null, defaults to false - var options = new CopilotClientOptions().setCliPath("/nonexistent/copilot").setGitHubToken("ghp_test123") + var options = new CopilotClientOptions().setCliPath(NONEXISTENT_CLI).setGitHubToken("ghp_test123") .setUseStdio(true); var manager = new CliServerManager(options); @@ -225,8 +233,7 @@ void startCliServerWithTelemetryAllOptions() throws Exception { // so even with a nonexistent CLI path, the telemetry code path is exercised var telemetry = new TelemetryConfig().setOtlpEndpoint("http://localhost:4318").setFilePath("/tmp/telemetry.log") .setExporterType("otlp-http").setSourceName("test-app").setCaptureContent(true); - var options = new CopilotClientOptions().setCliPath("/nonexistent/copilot").setTelemetry(telemetry) - .setUseStdio(true); + var options = new CopilotClientOptions().setCliPath(NONEXISTENT_CLI).setTelemetry(telemetry).setUseStdio(true); var manager = new CliServerManager(options); var ex = assertThrows(IOException.class, () -> manager.startCliServer()); @@ -237,8 +244,7 @@ void startCliServerWithTelemetryAllOptions() throws Exception { void startCliServerWithTelemetryCaptureContentFalse() throws Exception { // Test the false branch of getCaptureContent() var telemetry = new TelemetryConfig().setCaptureContent(false); - var options = new CopilotClientOptions().setCliPath("/nonexistent/copilot").setTelemetry(telemetry) - .setUseStdio(true); + var options = new CopilotClientOptions().setCliPath(NONEXISTENT_CLI).setTelemetry(telemetry).setUseStdio(true); var manager = new CliServerManager(options); var ex = assertThrows(IOException.class, () -> manager.startCliServer());