Skip to content

Commit b2a072b

Browse files
committed
test: Enhance Document and DocumentBuilder test coverage with edge cases and validation tests
Signed-off-by: Alex Klimenko <[email protected]>
1 parent e0ccc13 commit b2a072b

File tree

2 files changed

+262
-0
lines changed

2 files changed

+262
-0
lines changed

spring-ai-commons/src/test/java/org/springframework/ai/document/DocumentBuilderTests.java

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,4 +290,120 @@ void testBuilderReuse() {
290290
assertThat(doc2.getMetadata()).containsEntry("key", "value2");
291291
}
292292

293+
@Test
294+
void testMediaDocumentWithoutText() {
295+
Media media = getMedia();
296+
Document document = this.builder.media(media).build();
297+
298+
assertThat(document.getMedia()).isEqualTo(media);
299+
assertThat(document.getText()).isNull();
300+
}
301+
302+
@Test
303+
void testTextDocumentWithoutMedia() {
304+
Document document = this.builder.text("test content").build();
305+
306+
assertThat(document.getText()).isEqualTo("test content");
307+
assertThat(document.getMedia()).isNull();
308+
}
309+
310+
@Test
311+
void testOverwritingMediaWithNull() {
312+
Media media = getMedia();
313+
Document document = this.builder.media(media).media(null).text("fallback").build();
314+
315+
assertThat(document.getMedia()).isNull();
316+
}
317+
318+
@Test
319+
void testMetadataWithSpecialCharacterKeys() {
320+
Document document = this.builder.text("test")
321+
.metadata("key-with-dashes", "value1")
322+
.metadata("key.with.dots", "value2")
323+
.metadata("key_with_underscores", "value3")
324+
.metadata("key with spaces", "value4")
325+
.build();
326+
327+
assertThat(document.getMetadata()).containsEntry("key-with-dashes", "value1")
328+
.containsEntry("key.with.dots", "value2")
329+
.containsEntry("key_with_underscores", "value3")
330+
.containsEntry("key with spaces", "value4");
331+
}
332+
333+
@Test
334+
void testBuilderStateIsolation() {
335+
// Configure first builder state
336+
this.builder.text("first").metadata("shared", "first");
337+
338+
// Create first document
339+
Document doc1 = this.builder.build();
340+
341+
// Modify builder for second document
342+
this.builder.text("second").metadata("shared", "second");
343+
344+
// Create second document
345+
Document doc2 = this.builder.build();
346+
347+
// Verify first document wasn't affected by subsequent changes
348+
assertThat(doc1.getText()).isEqualTo("first");
349+
assertThat(doc1.getMetadata()).containsEntry("shared", "first");
350+
351+
assertThat(doc2.getText()).isEqualTo("second");
352+
assertThat(doc2.getMetadata()).containsEntry("shared", "second");
353+
}
354+
355+
@Test
356+
void testBuilderMethodChaining() {
357+
Document document = this.builder.text("chained")
358+
.id("chain-id")
359+
.metadata("key1", "value1")
360+
.metadata("key2", "value2")
361+
.score(0.75)
362+
.build();
363+
364+
assertThat(document.getText()).isEqualTo("chained");
365+
assertThat(document.getId()).isEqualTo("chain-id");
366+
assertThat(document.getMetadata()).hasSize(2);
367+
assertThat(document.getScore()).isEqualTo(0.75);
368+
}
369+
370+
@Test
371+
void testTextWithNewlinesAndTabs() {
372+
String textWithFormatting = "Line 1\nLine 2\n\tTabbed line\r\nWindows line ending";
373+
Document document = this.builder.text(textWithFormatting).build();
374+
375+
assertThat(document.getText()).isEqualTo(textWithFormatting);
376+
}
377+
378+
@Test
379+
void testMetadataOverwritingWithMapAfterKeyValue() {
380+
Map<String, Object> newMetadata = new HashMap<>();
381+
newMetadata.put("map-key", "map-value");
382+
383+
Document document = this.builder.text("test")
384+
.metadata("old-key", "old-value")
385+
.metadata("another-key", "another-value")
386+
.metadata(newMetadata) // This should replace all previous metadata
387+
.build();
388+
389+
assertThat(document.getMetadata()).hasSize(1);
390+
assertThat(document.getMetadata()).containsEntry("map-key", "map-value");
391+
assertThat(document.getMetadata()).doesNotContainKey("old-key");
392+
assertThat(document.getMetadata()).doesNotContainKey("another-key");
393+
}
394+
395+
@Test
396+
void testMetadataKeyValuePairsAccumulation() {
397+
Document document = this.builder.text("test")
398+
.metadata("a", "1")
399+
.metadata("b", "2")
400+
.metadata("c", "3")
401+
.metadata("d", "4")
402+
.metadata("e", "5")
403+
.build();
404+
405+
assertThat(document.getMetadata()).hasSize(5);
406+
assertThat(document.getMetadata().keySet()).containsExactlyInAnyOrder("a", "b", "c", "d", "e");
407+
}
408+
293409
}

spring-ai-commons/src/test/java/org/springframework/ai/document/DocumentTests.java

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,4 +213,150 @@ private static Media getMedia() {
213213
return Media.builder().mimeType(MimeTypeUtils.IMAGE_JPEG).data(URI.create("http://type1")).build();
214214
}
215215

216+
@Test
217+
void testMetadataModeNone() {
218+
Map<String, Object> metadata = new HashMap<>();
219+
metadata.put("secret", "hidden");
220+
221+
Document document = Document.builder().text("Visible content").metadata(metadata).build();
222+
223+
String formattedContent = document.getFormattedContent(MetadataMode.NONE);
224+
assertThat(formattedContent).contains("Visible content");
225+
assertThat(formattedContent).doesNotContain("secret");
226+
assertThat(formattedContent).doesNotContain("hidden");
227+
}
228+
229+
@Test
230+
void testMetadataModeEmbed() {
231+
Map<String, Object> metadata = new HashMap<>();
232+
metadata.put("embedKey", "embedValue");
233+
metadata.put("filterKey", "filterValue");
234+
235+
Document document = Document.builder().text("Test content").metadata(metadata).build();
236+
237+
String formattedContent = document.getFormattedContent(MetadataMode.EMBED);
238+
// This test assumes EMBED mode includes all metadata - adjust based on actual
239+
// implementation
240+
assertThat(formattedContent).contains("Test content");
241+
}
242+
243+
@Test
244+
void testDocumentBuilderChaining() {
245+
Map<String, Object> metadata = new HashMap<>();
246+
metadata.put("chain", "test");
247+
248+
Document document = Document.builder()
249+
.text("Chain test")
250+
.metadata(metadata)
251+
.metadata("additional", "value")
252+
.score(0.85)
253+
.build();
254+
255+
assertThat(document.getText()).isEqualTo("Chain test");
256+
assertThat(document.getMetadata()).containsEntry("chain", "test");
257+
assertThat(document.getMetadata()).containsEntry("additional", "value");
258+
assertThat(document.getScore()).isEqualTo(0.85);
259+
}
260+
261+
@Test
262+
void testDocumentWithScoreGreaterThanOne() {
263+
Document document = Document.builder().text("High score test").score(1.5).build();
264+
265+
assertThat(document.getScore()).isEqualTo(1.5);
266+
}
267+
268+
@Test
269+
void testMutateWithChanges() {
270+
Document original = Document.builder().text("Original text").score(0.5).metadata("original", "value").build();
271+
272+
Document mutated = original.mutate().text("Mutated text").score(0.8).metadata("new", "metadata").build();
273+
274+
assertThat(mutated.getText()).isEqualTo("Mutated text");
275+
assertThat(mutated.getScore()).isEqualTo(0.8);
276+
assertThat(mutated.getMetadata()).containsEntry("new", "metadata");
277+
assertThat(original.getText()).isEqualTo("Original text"); // Original unchanged
278+
}
279+
280+
@Test
281+
void testDocumentEqualityWithDifferentScores() {
282+
Document doc1 = Document.builder().id("sameId").text("Same text").score(0.5).build();
283+
284+
Document doc2 = Document.builder().id("sameId").text("Same text").score(0.8).build();
285+
286+
// Assuming score affects equality - adjust if it doesn't
287+
assertThat(doc1).isNotEqualTo(doc2);
288+
}
289+
290+
@Test
291+
void testDocumentWithComplexMetadata() {
292+
Map<String, Object> nestedMap = new HashMap<>();
293+
nestedMap.put("nested", "value");
294+
295+
Map<String, Object> metadata = new HashMap<>();
296+
metadata.put("string", "value");
297+
metadata.put("number", 1);
298+
metadata.put("boolean", true);
299+
metadata.put("map", nestedMap);
300+
301+
Document document = Document.builder().text("Complex metadata test").metadata(metadata).build();
302+
303+
assertThat(document.getMetadata()).containsEntry("string", "value");
304+
assertThat(document.getMetadata()).containsEntry("number", 1);
305+
assertThat(document.getMetadata()).containsEntry("boolean", true);
306+
assertThat(document.getMetadata()).containsEntry("map", nestedMap);
307+
}
308+
309+
@Test
310+
void testMetadataImmutability() {
311+
Map<String, Object> originalMetadata = new HashMap<>();
312+
originalMetadata.put("key", "value");
313+
314+
Document document = Document.builder().text("Immutability test").metadata(originalMetadata).build();
315+
316+
// Modify original map
317+
originalMetadata.put("key", "modified");
318+
originalMetadata.put("newKey", "newValue");
319+
320+
// Document's metadata should be unaffected (if properly copied)
321+
assertThat(document.getMetadata()).containsEntry("key", "value");
322+
assertThat(document.getMetadata()).doesNotContainKey("newKey");
323+
}
324+
325+
@Test
326+
void testDocumentWithEmptyMetadata() {
327+
Document document = Document.builder().text("Empty metadata test").metadata(new HashMap<>()).build();
328+
329+
assertThat(document.getMetadata()).isEmpty();
330+
}
331+
332+
@Test
333+
void testMetadataWithNullValueInMap() {
334+
Map<String, Object> metadata = new HashMap<>();
335+
metadata.put("validKey", "validValue");
336+
metadata.put("nullKey", null);
337+
338+
assertThrows(IllegalArgumentException.class, () -> {
339+
Document.builder().text("test").metadata(metadata).build();
340+
});
341+
}
342+
343+
@Test
344+
void testDocumentWithWhitespaceOnlyText() {
345+
String whitespaceText = " \n\t\r ";
346+
Document document = Document.builder().text(whitespaceText).build();
347+
348+
assertThat(document.getText()).isEqualTo(whitespaceText);
349+
assertThat(document.isText()).isTrue();
350+
}
351+
352+
@Test
353+
void testDocumentHashCodeConsistency() {
354+
Document document = Document.builder().text("Hash test").metadata("key", "value").score(0.1).build();
355+
356+
int hashCode1 = document.hashCode();
357+
int hashCode2 = document.hashCode();
358+
359+
assertThat(hashCode1).isEqualTo(hashCode2);
360+
}
361+
216362
}

0 commit comments

Comments
 (0)