Skip to content

Commit ada4adc

Browse files
alxkmWillam2004
authored andcommitted
test: Add comprehensive runtime hints validation for Ollama GraalVM native image support (spring-projects#4418)
Auto-cherry-pick to 1.0.x Fixes spring-projects#4418 Signed-off-by: Oleksandr Klymenko <[email protected]> Signed-off-by: 家娃 <[email protected]>
1 parent 5e9c80b commit ada4adc

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/aot/OllamaRuntimeHintsTests.java

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,4 +194,95 @@ void verifyHintsRegistrationWithCustomClassLoader() {
194194
assertThat(registeredTypes.contains(TypeReference.of(OllamaChatOptions.class))).isTrue();
195195
}
196196

197+
@Test
198+
void verifyNoProxyHintsAreRegistered() {
199+
RuntimeHints runtimeHints = new RuntimeHints();
200+
OllamaRuntimeHints ollamaRuntimeHints = new OllamaRuntimeHints();
201+
ollamaRuntimeHints.registerHints(runtimeHints, null);
202+
203+
// Ollama should only register reflection hints, not proxy hints
204+
assertThat(runtimeHints.proxies().jdkProxyHints().count()).isEqualTo(0);
205+
}
206+
207+
@Test
208+
void verifyNoSerializationHintsAreRegistered() {
209+
RuntimeHints runtimeHints = new RuntimeHints();
210+
OllamaRuntimeHints ollamaRuntimeHints = new OllamaRuntimeHints();
211+
ollamaRuntimeHints.registerHints(runtimeHints, null);
212+
213+
// Ollama should only register reflection hints, not serialization hints
214+
assertThat(runtimeHints.serialization().javaSerializationHints().count()).isEqualTo(0);
215+
}
216+
217+
@Test
218+
void verifyConstructorHintsAreRegistered() {
219+
RuntimeHints runtimeHints = new RuntimeHints();
220+
OllamaRuntimeHints ollamaRuntimeHints = new OllamaRuntimeHints();
221+
ollamaRuntimeHints.registerHints(runtimeHints, null);
222+
223+
// Verify that reflection hints include constructor access for JSON
224+
// deserialization
225+
boolean hasConstructorHints = runtimeHints.reflection()
226+
.typeHints()
227+
.anyMatch(typeHint -> typeHint.constructors().findAny().isPresent() || typeHint.getMemberCategories()
228+
.contains(org.springframework.aot.hint.MemberCategory.INVOKE_DECLARED_CONSTRUCTORS));
229+
230+
assertThat(hasConstructorHints).as("Should register constructor hints for JSON deserialization").isTrue();
231+
}
232+
233+
@Test
234+
void verifyEnumTypesAreRegistered() {
235+
RuntimeHints runtimeHints = new RuntimeHints();
236+
OllamaRuntimeHints ollamaRuntimeHints = new OllamaRuntimeHints();
237+
ollamaRuntimeHints.registerHints(runtimeHints, null);
238+
239+
Set<TypeReference> registeredTypes = new HashSet<>();
240+
runtimeHints.reflection().typeHints().forEach(typeHint -> registeredTypes.add(typeHint.getType()));
241+
242+
// Verify enum types are registered (critical for JSON deserialization)
243+
boolean hasEnumTypes = registeredTypes.stream()
244+
.anyMatch(tr -> tr.getName().contains("$") || tr.getName().toLowerCase().contains("role")
245+
|| tr.getName().toLowerCase().contains("type"));
246+
247+
assertThat(hasEnumTypes).as("Enum types should be registered for native image compatibility").isTrue();
248+
}
249+
250+
@Test
251+
void verifyResponseTypesAreRegistered() {
252+
RuntimeHints runtimeHints = new RuntimeHints();
253+
OllamaRuntimeHints ollamaRuntimeHints = new OllamaRuntimeHints();
254+
ollamaRuntimeHints.registerHints(runtimeHints, null);
255+
256+
Set<TypeReference> registeredTypes = new HashSet<>();
257+
runtimeHints.reflection().typeHints().forEach(typeHint -> registeredTypes.add(typeHint.getType()));
258+
259+
// Verify response wrapper types are registered
260+
assertThat(registeredTypes.stream().anyMatch(tr -> tr.getName().contains("Response")))
261+
.as("Response types should be registered")
262+
.isTrue();
263+
264+
assertThat(registeredTypes.stream().anyMatch(tr -> tr.getName().contains("ChatResponse")))
265+
.as("ChatResponse type should be registered")
266+
.isTrue();
267+
}
268+
269+
@Test
270+
void verifyToolRelatedClassesAreRegistered() {
271+
RuntimeHints runtimeHints = new RuntimeHints();
272+
OllamaRuntimeHints ollamaRuntimeHints = new OllamaRuntimeHints();
273+
ollamaRuntimeHints.registerHints(runtimeHints, null);
274+
275+
Set<TypeReference> registeredTypes = new HashSet<>();
276+
runtimeHints.reflection().typeHints().forEach(typeHint -> registeredTypes.add(typeHint.getType()));
277+
278+
// Verify tool-related classes are registered
279+
assertThat(registeredTypes.contains(TypeReference.of(OllamaApi.ChatRequest.Tool.class))).isTrue();
280+
281+
// Count tool-related classes
282+
long toolClassCount = registeredTypes.stream()
283+
.filter(typeRef -> typeRef.getName().toLowerCase().contains("tool"))
284+
.count();
285+
assertThat(toolClassCount).isGreaterThan(0);
286+
}
287+
197288
}

0 commit comments

Comments
 (0)