Skip to content

Commit ed4a7b9

Browse files
brunoborgesCopilot
andcommitted
test(java): cover owned default executor shutdown
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 349a419 commit ed4a7b9

1 file changed

Lines changed: 58 additions & 0 deletions

File tree

java/src/test/java/com/github/copilot/DefaultExecutorProviderTest.java

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import java.io.IOException;
1313
import java.lang.reflect.Method;
14+
import java.lang.reflect.Field;
1415
import java.net.URL;
1516
import java.net.URLClassLoader;
1617
import java.nio.file.Files;
@@ -95,6 +96,38 @@ void multiReleaseJarUsesOwnedVirtualThreadExecutorOnJdk25() throws Exception {
9596
}
9697
}
9798

99+
@Test
100+
void clientCloseShutsDownOwnedDefaultExecutorOnJdk25() throws Exception {
101+
if (Runtime.version().feature() < 25) {
102+
return;
103+
}
104+
105+
Path classes = Path.of("target", "classes");
106+
Path jar = Files.createTempFile("copilot-sdk-client-default-executor", ".jar");
107+
try {
108+
createClassesJar(jar, classes);
109+
110+
try (var loader = new URLClassLoader(new URL[]{jar.toUri().toURL()}, null)) {
111+
Class<?> clientClass = Class.forName("com.github.copilot.CopilotClient", true, loader);
112+
AutoCloseable client = (AutoCloseable) clientClass.getConstructor().newInstance();
113+
Field ownedExecutorField = clientClass.getDeclaredField("ownedExecutor");
114+
ownedExecutorField.setAccessible(true);
115+
ExecutorService ownedExecutor = (ExecutorService) ownedExecutorField.get(client);
116+
117+
assertNotNull(ownedExecutor);
118+
assertFalse(ownedExecutor.isShutdown());
119+
120+
client.close();
121+
122+
assertTrue(ownedExecutor.isShutdown());
123+
assertTrue(ownedExecutor.awaitTermination(5, TimeUnit.SECONDS));
124+
assertTrue(ownedExecutor.isTerminated());
125+
}
126+
} finally {
127+
Files.deleteIfExists(jar);
128+
}
129+
}
130+
98131
private static boolean isCurrentThreadVirtual() {
99132
try {
100133
Method isVirtual = Thread.class.getMethod("isVirtual");
@@ -116,6 +149,31 @@ private static void createProviderJar(Path jar, Path baseClass, Path java25Class
116149
}
117150
}
118151

152+
private static void createClassesJar(Path jar, Path classes) throws IOException {
153+
Manifest manifest = new Manifest();
154+
Attributes attributes = manifest.getMainAttributes();
155+
attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
156+
attributes.putValue("Multi-Release", "true");
157+
158+
try (JarOutputStream output = new JarOutputStream(Files.newOutputStream(jar), manifest);
159+
var files = Files.walk(classes)) {
160+
var iterator = files.iterator();
161+
while (iterator.hasNext()) {
162+
Path file = iterator.next();
163+
if (!Files.isRegularFile(file)) {
164+
continue;
165+
}
166+
167+
String entryName = classes.relativize(file).toString().replace('\\', '/');
168+
if ("META-INF/MANIFEST.MF".equals(entryName)) {
169+
continue;
170+
}
171+
172+
addClass(output, entryName, file);
173+
}
174+
}
175+
}
176+
119177
private static void addClass(JarOutputStream output, String entryName, Path classFile) throws IOException {
120178
output.putNextEntry(new JarEntry(entryName));
121179
Files.copy(classFile, output);

0 commit comments

Comments
 (0)