Skip to content

Commit a82938c

Browse files
Copilotedburns
andauthored
test: add comprehensive clearXxx() and Jackson serialization roundtrip tests
Co-authored-by: edburns <75821+edburns@users.noreply.github.com>
1 parent 7a4b7ac commit a82938c

2 files changed

Lines changed: 373 additions & 1 deletion

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ void testModelInfoDeserialization() throws Exception {
156156
// Capabilities
157157
assertNotNull(model.getCapabilities());
158158
assertTrue(model.getCapabilities().getSupports().isVision());
159-
assertEquals(8192, model.getCapabilities().getLimits().getMaxPromptTokens().getAsInt());
159+
assertEquals(8192, model.getCapabilities().getLimits().getMaxPromptTokens());
160160
assertEquals(128000, model.getCapabilities().getLimits().getMaxContextWindowTokens());
161161

162162
// Vision limits
Lines changed: 372 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,372 @@
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 com.fasterxml.jackson.databind.ObjectMapper;
10+
import com.github.copilot.sdk.json.CopilotClientOptions;
11+
import com.github.copilot.sdk.json.CustomAgentConfig;
12+
import com.github.copilot.sdk.json.InfiniteSessionConfig;
13+
import com.github.copilot.sdk.json.InputOptions;
14+
import com.github.copilot.sdk.json.ModelCapabilitiesOverride;
15+
import com.github.copilot.sdk.json.ProviderConfig;
16+
import com.github.copilot.sdk.json.ResumeSessionConfig;
17+
import com.github.copilot.sdk.json.SessionConfig;
18+
import com.github.copilot.sdk.json.SessionUiCapabilities;
19+
import com.github.copilot.sdk.json.TelemetryConfig;
20+
import com.github.copilot.sdk.json.UserInputRequest;
21+
import org.junit.jupiter.api.Test;
22+
23+
/**
24+
* Validates that every {@code clearXxx()} method resets its field to absent,
25+
* that Optional-returning getters report the correct state, and that Jackson
26+
* omits cleared fields from serialized output.
27+
*/
28+
class OptionalApiAndJacksonTest {
29+
30+
private static final ObjectMapper MAPPER = JsonRpcClient.getObjectMapper();
31+
32+
// ── CopilotClientOptions ──────────────────────────────────────────
33+
34+
@Test
35+
void copilotClientOptions_clearSessionIdleTimeoutSeconds() {
36+
var opts = new CopilotClientOptions();
37+
opts.setSessionIdleTimeoutSeconds(120);
38+
assertFalse(opts.getSessionIdleTimeoutSeconds().isEmpty());
39+
40+
opts.clearSessionIdleTimeoutSeconds();
41+
assertTrue(opts.getSessionIdleTimeoutSeconds().isEmpty());
42+
}
43+
44+
@Test
45+
void copilotClientOptions_clearUseLoggedInUser() {
46+
var opts = new CopilotClientOptions();
47+
opts.setUseLoggedInUser(true);
48+
assertTrue(opts.getUseLoggedInUser().isPresent());
49+
50+
opts.clearUseLoggedInUser();
51+
assertTrue(opts.getUseLoggedInUser().isEmpty());
52+
}
53+
54+
// ── SessionConfig ─────────────────────────────────────────────────
55+
56+
@Test
57+
void sessionConfig_clearEnableSessionTelemetry() {
58+
var cfg = new SessionConfig();
59+
cfg.setEnableSessionTelemetry(true);
60+
assertTrue(cfg.getEnableSessionTelemetry().isPresent());
61+
62+
cfg.clearEnableSessionTelemetry();
63+
assertTrue(cfg.getEnableSessionTelemetry().isEmpty());
64+
}
65+
66+
@Test
67+
void sessionConfig_clearEnableConfigDiscovery() {
68+
var cfg = new SessionConfig();
69+
cfg.setEnableConfigDiscovery(false);
70+
assertTrue(cfg.getEnableConfigDiscovery().isPresent());
71+
72+
cfg.clearEnableConfigDiscovery();
73+
assertTrue(cfg.getEnableConfigDiscovery().isEmpty());
74+
}
75+
76+
@Test
77+
void sessionConfig_clearIncludeSubAgentStreamingEvents() {
78+
var cfg = new SessionConfig();
79+
cfg.setIncludeSubAgentStreamingEvents(true);
80+
assertTrue(cfg.getIncludeSubAgentStreamingEvents().isPresent());
81+
82+
cfg.clearIncludeSubAgentStreamingEvents();
83+
assertTrue(cfg.getIncludeSubAgentStreamingEvents().isEmpty());
84+
}
85+
86+
// ── ResumeSessionConfig ───────────────────────────────────────────
87+
88+
@Test
89+
void resumeSessionConfig_clearEnableSessionTelemetry() {
90+
var cfg = new ResumeSessionConfig();
91+
cfg.setEnableSessionTelemetry(false);
92+
assertTrue(cfg.getEnableSessionTelemetry().isPresent());
93+
94+
cfg.clearEnableSessionTelemetry();
95+
assertTrue(cfg.getEnableSessionTelemetry().isEmpty());
96+
}
97+
98+
@Test
99+
void resumeSessionConfig_clearEnableConfigDiscovery() {
100+
var cfg = new ResumeSessionConfig();
101+
cfg.setEnableConfigDiscovery(true);
102+
assertTrue(cfg.getEnableConfigDiscovery().isPresent());
103+
104+
cfg.clearEnableConfigDiscovery();
105+
assertTrue(cfg.getEnableConfigDiscovery().isEmpty());
106+
}
107+
108+
@Test
109+
void resumeSessionConfig_clearIncludeSubAgentStreamingEvents() {
110+
var cfg = new ResumeSessionConfig();
111+
cfg.setIncludeSubAgentStreamingEvents(false);
112+
assertTrue(cfg.getIncludeSubAgentStreamingEvents().isPresent());
113+
114+
cfg.clearIncludeSubAgentStreamingEvents();
115+
assertTrue(cfg.getIncludeSubAgentStreamingEvents().isEmpty());
116+
}
117+
118+
// ── InfiniteSessionConfig ─────────────────────────────────────────
119+
120+
@Test
121+
void infiniteSessionConfig_clearEnabled() {
122+
var cfg = new InfiniteSessionConfig();
123+
cfg.setEnabled(true);
124+
assertTrue(cfg.getEnabled().isPresent());
125+
126+
cfg.clearEnabled();
127+
assertTrue(cfg.getEnabled().isEmpty());
128+
}
129+
130+
@Test
131+
void infiniteSessionConfig_clearBackgroundCompactionThreshold() {
132+
var cfg = new InfiniteSessionConfig();
133+
cfg.setBackgroundCompactionThreshold(0.75);
134+
assertFalse(cfg.getBackgroundCompactionThreshold().isEmpty());
135+
136+
cfg.clearBackgroundCompactionThreshold();
137+
assertTrue(cfg.getBackgroundCompactionThreshold().isEmpty());
138+
}
139+
140+
@Test
141+
void infiniteSessionConfig_clearBufferExhaustionThreshold() {
142+
var cfg = new InfiniteSessionConfig();
143+
cfg.setBufferExhaustionThreshold(0.9);
144+
assertFalse(cfg.getBufferExhaustionThreshold().isEmpty());
145+
146+
cfg.clearBufferExhaustionThreshold();
147+
assertTrue(cfg.getBufferExhaustionThreshold().isEmpty());
148+
}
149+
150+
// ── InputOptions ──────────────────────────────────────────────────
151+
152+
@Test
153+
void inputOptions_clearMinLength() {
154+
var opts = new InputOptions();
155+
opts.setMinLength(5);
156+
assertFalse(opts.getMinLength().isEmpty());
157+
158+
opts.clearMinLength();
159+
assertTrue(opts.getMinLength().isEmpty());
160+
}
161+
162+
@Test
163+
void inputOptions_clearMaxLength() {
164+
var opts = new InputOptions();
165+
opts.setMaxLength(100);
166+
assertFalse(opts.getMaxLength().isEmpty());
167+
168+
opts.clearMaxLength();
169+
assertTrue(opts.getMaxLength().isEmpty());
170+
}
171+
172+
// ── ModelCapabilitiesOverride.Supports ─────────────────────────────
173+
174+
@Test
175+
void supports_clearVision() {
176+
var s = new ModelCapabilitiesOverride.Supports();
177+
s.setVision(true);
178+
assertTrue(s.getVision().isPresent());
179+
180+
s.clearVision();
181+
assertTrue(s.getVision().isEmpty());
182+
}
183+
184+
@Test
185+
void supports_clearReasoningEffort() {
186+
var s = new ModelCapabilitiesOverride.Supports();
187+
s.setReasoningEffort(false);
188+
assertTrue(s.getReasoningEffort().isPresent());
189+
190+
s.clearReasoningEffort();
191+
assertTrue(s.getReasoningEffort().isEmpty());
192+
}
193+
194+
// ── ModelCapabilitiesOverride.Limits ───────────────────────────────
195+
196+
@Test
197+
void limits_clearMaxPromptTokens() {
198+
var l = new ModelCapabilitiesOverride.Limits();
199+
l.setMaxPromptTokens(4096);
200+
assertFalse(l.getMaxPromptTokens().isEmpty());
201+
202+
l.clearMaxPromptTokens();
203+
assertTrue(l.getMaxPromptTokens().isEmpty());
204+
}
205+
206+
@Test
207+
void limits_clearMaxOutputTokens() {
208+
var l = new ModelCapabilitiesOverride.Limits();
209+
l.setMaxOutputTokens(1024);
210+
assertFalse(l.getMaxOutputTokens().isEmpty());
211+
212+
l.clearMaxOutputTokens();
213+
assertTrue(l.getMaxOutputTokens().isEmpty());
214+
}
215+
216+
@Test
217+
void limits_clearMaxContextWindowTokens() {
218+
var l = new ModelCapabilitiesOverride.Limits();
219+
l.setMaxContextWindowTokens(16384);
220+
assertFalse(l.getMaxContextWindowTokens().isEmpty());
221+
222+
l.clearMaxContextWindowTokens();
223+
assertTrue(l.getMaxContextWindowTokens().isEmpty());
224+
}
225+
226+
// ── ProviderConfig ────────────────────────────────────────────────
227+
228+
@Test
229+
void providerConfig_clearMaxPromptTokens() {
230+
var cfg = new ProviderConfig();
231+
cfg.setMaxPromptTokens(2048);
232+
assertFalse(cfg.getMaxPromptTokens().isEmpty());
233+
234+
cfg.clearMaxPromptTokens();
235+
assertTrue(cfg.getMaxPromptTokens().isEmpty());
236+
}
237+
238+
@Test
239+
void providerConfig_clearMaxOutputTokens() {
240+
var cfg = new ProviderConfig();
241+
cfg.setMaxOutputTokens(512);
242+
assertFalse(cfg.getMaxOutputTokens().isEmpty());
243+
244+
cfg.clearMaxOutputTokens();
245+
assertTrue(cfg.getMaxOutputTokens().isEmpty());
246+
}
247+
248+
// ── TelemetryConfig ───────────────────────────────────────────────
249+
250+
@Test
251+
void telemetryConfig_clearCaptureContent() {
252+
var cfg = new TelemetryConfig();
253+
cfg.setCaptureContent(true);
254+
assertTrue(cfg.getCaptureContent().isPresent());
255+
256+
cfg.clearCaptureContent();
257+
assertTrue(cfg.getCaptureContent().isEmpty());
258+
}
259+
260+
// ── SessionUiCapabilities ─────────────────────────────────────────
261+
262+
@Test
263+
void sessionUiCapabilities_clearElicitation() {
264+
var caps = new SessionUiCapabilities();
265+
caps.setElicitation(true);
266+
assertTrue(caps.getElicitation().isPresent());
267+
268+
caps.clearElicitation();
269+
assertTrue(caps.getElicitation().isEmpty());
270+
}
271+
272+
// ── CustomAgentConfig ─────────────────────────────────────────────
273+
274+
@Test
275+
void customAgentConfig_clearInfer() {
276+
var cfg = new CustomAgentConfig();
277+
cfg.setInfer(true);
278+
assertTrue(cfg.getInfer().isPresent());
279+
280+
cfg.clearInfer();
281+
assertTrue(cfg.getInfer().isEmpty());
282+
}
283+
284+
// ── UserInputRequest ──────────────────────────────────────────────
285+
286+
@Test
287+
void userInputRequest_clearAllowFreeform() {
288+
var req = new UserInputRequest();
289+
req.setAllowFreeform(false);
290+
assertTrue(req.getAllowFreeform().isPresent());
291+
292+
req.clearAllowFreeform();
293+
assertTrue(req.getAllowFreeform().isEmpty());
294+
}
295+
296+
// ── Jackson serialization roundtrip ───────────────────────────────
297+
298+
// ── Jackson serialization roundtrip ───────────────────────────────
299+
//
300+
// Classes whose fields carry @JsonProperty (InfiniteSessionConfig,
301+
// ModelCapabilitiesOverride inner classes) are serialized via field
302+
// access: Jackson writes the field when set and omits it when cleared.
303+
//
304+
// Classes without @JsonProperty on fields (SessionConfig,
305+
// CopilotClientOptions, TelemetryConfig, ProviderConfig) are not
306+
// directly serialized — their values are copied to wire DTOs by
307+
// SessionRequestBuilder. The @JsonIgnore on their Optional-returning
308+
// getters prevents Jackson from attempting to serialize Optional
309+
// wrappers if the class is ever processed.
310+
311+
@Test
312+
void jackson_infiniteSessionConfigClearedFieldsOmitted() throws Exception {
313+
var cfg = new InfiniteSessionConfig();
314+
cfg.setEnabled(true);
315+
cfg.setBackgroundCompactionThreshold(0.75);
316+
cfg.setBufferExhaustionThreshold(0.9);
317+
318+
String withFields = MAPPER.writeValueAsString(cfg);
319+
assertTrue(withFields.contains("enabled"));
320+
assertTrue(withFields.contains("backgroundCompactionThreshold"));
321+
assertTrue(withFields.contains("bufferExhaustionThreshold"));
322+
323+
cfg.clearEnabled();
324+
cfg.clearBackgroundCompactionThreshold();
325+
cfg.clearBufferExhaustionThreshold();
326+
327+
String cleared = MAPPER.writeValueAsString(cfg);
328+
assertFalse(cleared.contains("enabled"));
329+
assertFalse(cleared.contains("backgroundCompactionThreshold"));
330+
assertFalse(cleared.contains("bufferExhaustionThreshold"));
331+
}
332+
333+
@Test
334+
void jackson_modelCapabilitiesOverrideSupportsClearedFieldsOmitted() throws Exception {
335+
var supports = new ModelCapabilitiesOverride.Supports();
336+
supports.setVision(true);
337+
supports.setReasoningEffort(false);
338+
339+
String withFields = MAPPER.writeValueAsString(supports);
340+
assertTrue(withFields.contains("vision"));
341+
assertTrue(withFields.contains("reasoningEffort"));
342+
343+
supports.clearVision();
344+
supports.clearReasoningEffort();
345+
346+
String cleared = MAPPER.writeValueAsString(supports);
347+
assertFalse(cleared.contains("vision"));
348+
assertFalse(cleared.contains("reasoningEffort"));
349+
}
350+
351+
@Test
352+
void jackson_modelCapabilitiesOverrideLimitsClearedFieldsOmitted() throws Exception {
353+
var limits = new ModelCapabilitiesOverride.Limits();
354+
limits.setMaxPromptTokens(2048);
355+
limits.setMaxOutputTokens(512);
356+
limits.setMaxContextWindowTokens(16384);
357+
358+
String withFields = MAPPER.writeValueAsString(limits);
359+
assertTrue(withFields.contains("max_prompt_tokens"));
360+
assertTrue(withFields.contains("max_output_tokens"));
361+
assertTrue(withFields.contains("max_context_window_tokens"));
362+
363+
limits.clearMaxPromptTokens();
364+
limits.clearMaxOutputTokens();
365+
limits.clearMaxContextWindowTokens();
366+
367+
String cleared = MAPPER.writeValueAsString(limits);
368+
assertFalse(cleared.contains("max_prompt_tokens"));
369+
assertFalse(cleared.contains("max_output_tokens"));
370+
assertFalse(cleared.contains("max_context_window_tokens"));
371+
}
372+
}

0 commit comments

Comments
 (0)