Skip to content

Commit 637b51b

Browse files
Copilotedburns
andauthored
Add tests for copilotHome, tcpConnectionToken, and instructionDirectories
Co-authored-by: edburns <75821+edburns@users.noreply.github.com>
1 parent 09425c2 commit 637b51b

3 files changed

Lines changed: 158 additions & 0 deletions

File tree

src/test/java/com/github/copilot/sdk/ConfigCloneTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ void copilotClientOptionsCloneBasic() {
3636
original.setPort(9000);
3737
original.setGitHubToken("ghp_test");
3838
original.setUseLoggedInUser(false);
39+
original.setCopilotHome("/custom/copilot/home");
40+
original.setUseStdio(false);
41+
original.setTcpConnectionToken("my-token-123");
3942

4043
CopilotClientOptions cloned = original.clone();
4144

@@ -44,6 +47,8 @@ void copilotClientOptionsCloneBasic() {
4447
assertEquals(original.getPort(), cloned.getPort());
4548
assertEquals(original.getGitHubToken(), cloned.getGitHubToken());
4649
assertEquals(original.getUseLoggedInUser(), cloned.getUseLoggedInUser());
50+
assertEquals(original.getCopilotHome(), cloned.getCopilotHome());
51+
assertEquals(original.getTcpConnectionToken(), cloned.getTcpConnectionToken());
4752
}
4853

4954
@Test
@@ -120,6 +125,7 @@ void sessionConfigListIndependence() {
120125
toolList.add("grep");
121126
toolList.add("bash");
122127
original.setAvailableTools(toolList);
128+
original.setInstructionDirectories(new ArrayList<>(List.of("/path/a", "/path/b")));
123129

124130
SessionConfig cloned = original.clone();
125131

@@ -129,6 +135,7 @@ void sessionConfigListIndependence() {
129135
// The cloned config should be unaffected by mutations to the original list
130136
assertEquals(2, cloned.getAvailableTools().size());
131137
assertEquals(3, original.getAvailableTools().size());
138+
assertEquals(List.of("/path/a", "/path/b"), cloned.getInstructionDirectories());
132139
}
133140

134141
@Test

src/test/java/com/github/copilot/sdk/CopilotClientTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,30 @@ void testSessionIdleTimeoutSecondsOptionAccepted() {
199199
assertEquals(600, options.getSessionIdleTimeoutSeconds());
200200
}
201201

202+
@Test
203+
void testTcpConnectionTokenWithUseStdioThrows() {
204+
var options = new CopilotClientOptions().setUseStdio(true).setTcpConnectionToken("my-token");
205+
206+
assertThrows(IllegalArgumentException.class, () -> new CopilotClient(options));
207+
}
208+
209+
@Test
210+
void testTcpConnectionTokenAcceptedInTcpMode() {
211+
var options = new CopilotClientOptions().setUseStdio(false).setTcpConnectionToken("my-token");
212+
213+
// Should not throw
214+
try (var client = new CopilotClient(options)) {
215+
assertNotNull(client);
216+
}
217+
}
218+
219+
@Test
220+
void testCopilotHomeOptionSetOnOptions() {
221+
var options = new CopilotClientOptions().setCopilotHome("/custom/home");
222+
223+
assertEquals("/custom/home", options.getCopilotHome());
224+
}
225+
202226
// ===== onLifecycle tests =====
203227

204228
/**
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
*--------------------------------------------------------------------------------------------*/
4+
5+
package com.github.copilot.sdk;
6+
7+
import static org.junit.jupiter.api.Assertions.*;
8+
9+
import java.nio.file.Files;
10+
import java.nio.file.Path;
11+
import java.util.List;
12+
import java.util.Map;
13+
import java.util.concurrent.TimeUnit;
14+
15+
import org.junit.jupiter.api.AfterAll;
16+
import org.junit.jupiter.api.BeforeAll;
17+
import org.junit.jupiter.api.Disabled;
18+
import org.junit.jupiter.api.Test;
19+
20+
import com.github.copilot.sdk.json.MessageOptions;
21+
import com.github.copilot.sdk.json.PermissionHandler;
22+
import com.github.copilot.sdk.json.ResumeSessionConfig;
23+
import com.github.copilot.sdk.json.SessionConfig;
24+
25+
/**
26+
* E2E tests for session configuration features.
27+
*/
28+
public class SessionConfigE2ETest {
29+
30+
private static E2ETestContext ctx;
31+
32+
@BeforeAll
33+
static void setup() throws Exception {
34+
ctx = E2ETestContext.create();
35+
}
36+
37+
@AfterAll
38+
static void teardown() throws Exception {
39+
if (ctx != null) {
40+
ctx.close();
41+
}
42+
}
43+
44+
@Disabled("Requires test harness update with instructionDirectories snapshots - see reference impl PR #1190")
45+
@Test
46+
void testShouldApplyInstructionDirectoriesOnCreate() throws Exception {
47+
ctx.configureForTest("session_config", "should_apply_instructiondirectories_on_create");
48+
49+
// Set up instruction directory with a custom instruction file
50+
Path projectDir = ctx.getWorkDir().resolve("instruction-create-project");
51+
Path instructionDir = ctx.getWorkDir().resolve("extra-create-instructions");
52+
Path instructionFilesDir = instructionDir.resolve(".github").resolve("instructions");
53+
String sentinel = "JAVA_CREATE_INSTRUCTION_DIRECTORIES_SENTINEL";
54+
Files.createDirectories(projectDir);
55+
Files.createDirectories(instructionFilesDir);
56+
Files.writeString(instructionFilesDir.resolve("extra.instructions.md"), "Always include " + sentinel + ".");
57+
58+
try (CopilotClient client = ctx.createClient()) {
59+
CopilotSession session = client.createSession(new SessionConfig().setWorkingDirectory(projectDir.toString())
60+
.setInstructionDirectories(List.of(instructionDir.toString()))
61+
.setOnPermissionRequest(PermissionHandler.APPROVE_ALL)).get();
62+
63+
session.sendAndWait(new MessageOptions().setPrompt("What is 1+1?")).get(60, TimeUnit.SECONDS);
64+
65+
List<Map<String, Object>> exchanges = ctx.getExchanges();
66+
assertFalse(exchanges.isEmpty(), "Should have at least one exchange");
67+
String systemMessage = getSystemMessage(exchanges.get(0));
68+
assertNotNull(systemMessage, "System message should not be null");
69+
assertTrue(systemMessage.contains(sentinel),
70+
"System message should contain the instruction sentinel: " + sentinel);
71+
}
72+
}
73+
74+
@Disabled("Requires test harness update with instructionDirectories snapshots - see reference impl PR #1190")
75+
@Test
76+
void testShouldApplyInstructionDirectoriesOnResume() throws Exception {
77+
ctx.configureForTest("session_config", "should_apply_instructiondirectories_on_resume");
78+
79+
// Set up instruction directory with a custom instruction file
80+
Path projectDir = ctx.getWorkDir().resolve("instruction-resume-project");
81+
Path instructionDir = ctx.getWorkDir().resolve("extra-resume-instructions");
82+
Path instructionFilesDir = instructionDir.resolve(".github").resolve("instructions");
83+
String sentinel = "JAVA_RESUME_INSTRUCTION_DIRECTORIES_SENTINEL";
84+
Files.createDirectories(projectDir);
85+
Files.createDirectories(instructionFilesDir);
86+
Files.writeString(instructionFilesDir.resolve("extra.instructions.md"), "Always include " + sentinel + ".");
87+
88+
try (CopilotClient client = ctx.createClient()) {
89+
// Create a session first
90+
CopilotSession session1 = client.createSession(new SessionConfig()
91+
.setWorkingDirectory(projectDir.toString()).setOnPermissionRequest(PermissionHandler.APPROVE_ALL))
92+
.get();
93+
94+
// Resume with instructionDirectories
95+
CopilotSession session2 = client.resumeSession(session1.getSessionId(),
96+
new ResumeSessionConfig().setWorkingDirectory(projectDir.toString())
97+
.setInstructionDirectories(List.of(instructionDir.toString()))
98+
.setOnPermissionRequest(PermissionHandler.APPROVE_ALL))
99+
.get();
100+
101+
session2.sendAndWait(new MessageOptions().setPrompt("What is 1+1?")).get(60, TimeUnit.SECONDS);
102+
103+
List<Map<String, Object>> exchanges = ctx.getExchanges();
104+
assertFalse(exchanges.isEmpty(), "Should have at least one exchange");
105+
String systemMessage = getSystemMessage(exchanges.get(0));
106+
assertNotNull(systemMessage, "System message should not be null");
107+
assertTrue(systemMessage.contains(sentinel),
108+
"System message should contain the instruction sentinel: " + sentinel);
109+
}
110+
}
111+
112+
@SuppressWarnings("unchecked")
113+
private static String getSystemMessage(Map<String, Object> exchange) {
114+
Object messagesObj = exchange.get("messages");
115+
if (messagesObj instanceof List<?> messages) {
116+
for (Object msg : messages) {
117+
if (msg instanceof Map<?, ?> msgMap) {
118+
if ("system".equals(msgMap.get("role"))) {
119+
Object content = msgMap.get("content");
120+
return content != null ? content.toString() : null;
121+
}
122+
}
123+
}
124+
}
125+
return null;
126+
}
127+
}

0 commit comments

Comments
 (0)