Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,19 @@ public void vertexAiEmbeddingNonTransientError() {
verify(this.mockPredictionServiceClient, times(1)).predict(any());
}

@Test
public void vertexAiEmbeddingWithEmptyTextList() {
PredictResponse emptyResponse = PredictResponse.newBuilder().build();
given(this.mockPredictionServiceClient.predict(any())).willReturn(emptyResponse);

EmbeddingOptions options = VertexAiTextEmbeddingOptions.builder().model("model").build();
EmbeddingResponse result = this.embeddingModel.call(new EmbeddingRequest(List.of(), options));

assertThat(result).isNotNull();
// Behavior depends on implementation - might be empty results or exception
verify(this.mockPredictionServiceClient, times(1)).predict(any());
}

private static class TestRetryListener implements RetryListener {

int onErrorRetryCount = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,102 @@ public void vertexAiGeminiChatWithEmptyResponse() throws Exception {
assertThat(this.retryListener.onErrorRetryCount).isEqualTo(1);
}

@Test
public void vertexAiGeminiChatMaxRetriesExceeded() throws Exception {
// Test that after max retries, the exception is propagated
given(this.mockGenerativeModel.generateContent(any(List.class)))
.willThrow(new TransientAiException("Persistent Error"))
.willThrow(new TransientAiException("Persistent Error"))
.willThrow(new TransientAiException("Persistent Error"))
.willThrow(new TransientAiException("Persistent Error"));

// Should throw the last TransientAiException after exhausting retries
assertThrows(TransientAiException.class, () -> this.chatModel.call(new Prompt("test prompt")));

// Verify retry attempts were made
assertThat(this.retryListener.onErrorRetryCount).isGreaterThan(0);
}

@Test
public void vertexAiGeminiChatWithMultipleCandidatesResponse() throws Exception {
// Test response with multiple candidates
GenerateContentResponse multiCandidateResponse = GenerateContentResponse.newBuilder()
.addCandidates(Candidate.newBuilder()
.setContent(Content.newBuilder().addParts(Part.newBuilder().setText("First candidate").build()).build())
.build())
.addCandidates(Candidate.newBuilder()
.setContent(
Content.newBuilder().addParts(Part.newBuilder().setText("Second candidate").build()).build())
.build())
.build();

given(this.mockGenerativeModel.generateContent(any(List.class)))
.willThrow(new TransientAiException("Temporary failure"))
.willReturn(multiCandidateResponse);

ChatResponse result = this.chatModel.call(new Prompt("test prompt"));

assertThat(result).isNotNull();
// Assuming the implementation uses the first candidate
assertThat(result.getResult().getOutput().getText()).isEqualTo("First candidate");
assertThat(this.retryListener.onSuccessRetryCount).isEqualTo(1);
}

@Test
public void vertexAiGeminiChatWithNullPrompt() throws Exception {
// Test handling of null prompt
Prompt prompt = null;
assertThrows(Exception.class, () -> this.chatModel.call(prompt));

// Should not trigger any retries for validation errors
assertThat(this.retryListener.onErrorRetryCount).isEqualTo(0);
assertThat(this.retryListener.onSuccessRetryCount).isEqualTo(0);
}

@Test
public void vertexAiGeminiChatWithEmptyPrompt() throws Exception {
// Test handling of empty prompt
GenerateContentResponse mockedResponse = GenerateContentResponse.newBuilder()
.addCandidates(Candidate.newBuilder()
.setContent(Content.newBuilder()
.addParts(Part.newBuilder().setText("Response to empty prompt").build())
.build())
.build())
.build();

given(this.mockGenerativeModel.generateContent(any(List.class))).willReturn(mockedResponse);

ChatResponse result = this.chatModel.call(new Prompt(""));

assertThat(result).isNotNull();
assertThat(result.getResult().getOutput().getText()).isEqualTo("Response to empty prompt");
assertThat(this.retryListener.onSuccessRetryCount).isEqualTo(0);
}

@Test
public void vertexAiGeminiChatAlternatingErrorsAndSuccess() throws Exception {
// Test pattern of error -> success -> error -> success
GenerateContentResponse successResponse = GenerateContentResponse.newBuilder()
.addCandidates(Candidate.newBuilder()
.setContent(Content.newBuilder()
.addParts(Part.newBuilder().setText("Success after alternating errors").build())
.build())
.build())
.build();

given(this.mockGenerativeModel.generateContent(any(List.class)))
.willThrow(new TransientAiException("First error"))
.willThrow(new TransientAiException("Second error"))
.willReturn(successResponse);

ChatResponse result = this.chatModel.call(new Prompt("test prompt"));

assertThat(result).isNotNull();
assertThat(result.getResult().getOutput().getText()).isEqualTo("Success after alternating errors");
assertThat(this.retryListener.onSuccessRetryCount).isEqualTo(2);
assertThat(this.retryListener.onErrorRetryCount).isEqualTo(2);
}

private static class TestRetryListener implements RetryListener {

int onErrorRetryCount = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,73 @@ void fromPromptIndexAndContentFilterMetadata() {
assertThat(promptFilterMetadata.<String>getContentFilterMetadata()).isEqualTo("{ content-sentiment: 'SAFE' }");
}

@Test
void promptMetadataWithEmptyFiltersArray() {
PromptMetadata promptMetadata = PromptMetadata.of();

assertThat(promptMetadata).isNotNull();
assertThat(promptMetadata).isEmpty();
}

@Test
void promptMetadataWithMultipleFilters() {
PromptFilterMetadata filter1 = mockPromptFilterMetadata(0);
PromptFilterMetadata filter2 = mockPromptFilterMetadata(1);
PromptFilterMetadata filter3 = mockPromptFilterMetadata(2);
PromptFilterMetadata filter4 = mockPromptFilterMetadata(3);

PromptMetadata promptMetadata = PromptMetadata.of(filter1, filter2, filter3, filter4);

assertThat(promptMetadata).isNotNull();
assertThat(promptMetadata).hasSize(4);
assertThat(promptMetadata).containsExactly(filter1, filter2, filter3, filter4);
}

@Test
void promptMetadataWithDuplicateIndices() {
PromptFilterMetadata filter1 = mockPromptFilterMetadata(1);
PromptFilterMetadata filter2 = mockPromptFilterMetadata(1);

PromptMetadata promptMetadata = PromptMetadata.of(filter1, filter2);

assertThat(promptMetadata).isNotNull();
assertThat(promptMetadata).hasSize(2);

assertThat(promptMetadata.findByPromptIndex(1).orElse(null)).isEqualTo(filter1);
}

@Test
void promptFilterMetadataWithEmptyContentFilter() {
PromptFilterMetadata promptFilterMetadata = PromptFilterMetadata.from(0, "");

assertThat(promptFilterMetadata).isNotNull();
assertThat(promptFilterMetadata.getPromptIndex()).isZero();
assertThat(promptFilterMetadata.<String>getContentFilterMetadata()).isEmpty();
}

@Test
void promptMetadataSize() {
PromptFilterMetadata filter1 = mockPromptFilterMetadata(0);
PromptFilterMetadata filter2 = mockPromptFilterMetadata(1);

PromptMetadata empty = PromptMetadata.empty();
PromptMetadata single = PromptMetadata.of(filter1);
PromptMetadata multiple = PromptMetadata.of(filter1, filter2);

assertThat(empty).hasSize(0);
assertThat(single).hasSize(1);
assertThat(multiple).hasSize(2);
}

@Test
void promptMetadataImmutability() {
PromptFilterMetadata filter1 = mockPromptFilterMetadata(0);
PromptFilterMetadata filter2 = mockPromptFilterMetadata(1);

PromptMetadata promptMetadata = PromptMetadata.of(filter1, filter2);

assertThat(promptMetadata).isNotNull();
assertThat(promptMetadata).hasSize(2);
}

}