@@ -176,4 +176,100 @@ public void vertexAiGeminiChatWithEmptyResponse() throws Exception {
176176 assertThat (this .retryListener .onErrorRetryCount ).isEqualTo (1 );
177177 }
178178
179+ @ Test
180+ public void vertexAiGeminiChatMaxRetriesExceeded () throws Exception {
181+ // Test that after max retries, the exception is propagated
182+ given (this .mockGenerativeModel .generateContent (any (List .class )))
183+ .willThrow (new TransientAiException ("Persistent Error" ))
184+ .willThrow (new TransientAiException ("Persistent Error" ))
185+ .willThrow (new TransientAiException ("Persistent Error" ))
186+ .willThrow (new TransientAiException ("Persistent Error" ));
187+
188+ // Should throw the last TransientAiException after exhausting retries
189+ assertThrows (TransientAiException .class , () -> this .chatModel .call (new Prompt ("test prompt" )));
190+
191+ // Verify retry attempts were made
192+ assertThat (this .retryListener .onErrorRetryCount ).isGreaterThan (0 );
193+ }
194+
195+ @ Test
196+ public void vertexAiGeminiChatWithMultipleCandidatesResponse () throws Exception {
197+ // Test response with multiple candidates
198+ GenerateContentResponse multiCandidateResponse = GenerateContentResponse .newBuilder ()
199+ .addCandidates (Candidate .newBuilder ()
200+ .setContent (Content .newBuilder ().addParts (Part .newBuilder ().setText ("First candidate" ).build ()).build ())
201+ .build ())
202+ .addCandidates (Candidate .newBuilder ()
203+ .setContent (
204+ Content .newBuilder ().addParts (Part .newBuilder ().setText ("Second candidate" ).build ()).build ())
205+ .build ())
206+ .build ();
207+
208+ given (this .mockGenerativeModel .generateContent (any (List .class )))
209+ .willThrow (new TransientAiException ("Temporary failure" ))
210+ .willReturn (multiCandidateResponse );
211+
212+ ChatResponse result = this .chatModel .call (new Prompt ("test prompt" ));
213+
214+ assertThat (result ).isNotNull ();
215+ // Assuming the implementation uses the first candidate
216+ assertThat (result .getResult ().getOutput ().getText ()).isEqualTo ("First candidate" );
217+ assertThat (this .retryListener .onSuccessRetryCount ).isEqualTo (1 );
218+ }
219+
220+ @ Test
221+ public void vertexAiGeminiChatWithNullPrompt () throws Exception {
222+ // Test handling of null prompt
223+ Prompt prompt = null ;
224+ assertThrows (Exception .class , () -> this .chatModel .call (prompt ));
225+
226+ // Should not trigger any retries for validation errors
227+ assertThat (this .retryListener .onErrorRetryCount ).isEqualTo (0 );
228+ assertThat (this .retryListener .onSuccessRetryCount ).isEqualTo (0 );
229+ }
230+
231+ @ Test
232+ public void vertexAiGeminiChatWithEmptyPrompt () throws Exception {
233+ // Test handling of empty prompt
234+ GenerateContentResponse mockedResponse = GenerateContentResponse .newBuilder ()
235+ .addCandidates (Candidate .newBuilder ()
236+ .setContent (Content .newBuilder ()
237+ .addParts (Part .newBuilder ().setText ("Response to empty prompt" ).build ())
238+ .build ())
239+ .build ())
240+ .build ();
241+
242+ given (this .mockGenerativeModel .generateContent (any (List .class ))).willReturn (mockedResponse );
243+
244+ ChatResponse result = this .chatModel .call (new Prompt ("" ));
245+
246+ assertThat (result ).isNotNull ();
247+ assertThat (result .getResult ().getOutput ().getText ()).isEqualTo ("Response to empty prompt" );
248+ assertThat (this .retryListener .onSuccessRetryCount ).isEqualTo (0 );
249+ }
250+
251+ @ Test
252+ public void vertexAiGeminiChatAlternatingErrorsAndSuccess () throws Exception {
253+ // Test pattern of error -> success -> error -> success
254+ GenerateContentResponse successResponse = GenerateContentResponse .newBuilder ()
255+ .addCandidates (Candidate .newBuilder ()
256+ .setContent (Content .newBuilder ()
257+ .addParts (Part .newBuilder ().setText ("Success after alternating errors" ).build ())
258+ .build ())
259+ .build ())
260+ .build ();
261+
262+ given (this .mockGenerativeModel .generateContent (any (List .class )))
263+ .willThrow (new TransientAiException ("First error" ))
264+ .willThrow (new TransientAiException ("Second error" ))
265+ .willReturn (successResponse );
266+
267+ ChatResponse result = this .chatModel .call (new Prompt ("test prompt" ));
268+
269+ assertThat (result ).isNotNull ();
270+ assertThat (result .getResult ().getOutput ().getText ()).isEqualTo ("Success after alternating errors" );
271+ assertThat (this .retryListener .onSuccessRetryCount ).isEqualTo (2 );
272+ assertThat (this .retryListener .onErrorRetryCount ).isEqualTo (2 );
273+ }
274+
179275}
0 commit comments