Skip to content

Commit a8fdb6a

Browse files
author
Sahdev Garg
committed
test(go/veo): Enhance tests for VEO operation handling
This commit significantly enhances the test suite for the `fromVeoOperation` function to ensure robust handling of various VEO operation states. The test suite now includes: - More detailed checks for status messages, finish reasons, and media part counts. - New test cases for edge scenarios, such as completed operations that produce no videos. - General refactoring for clarity and better coverage. Additionally, a minor fix was made to remove a redundant `ModelResponse` creation in an error path that was discovered during testing.
1 parent 77c61bc commit a8fdb6a

File tree

2 files changed

+110
-57
lines changed

2 files changed

+110
-57
lines changed

go/plugins/googlegenai/veo.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,6 @@ func fromVeoOperation(veoOp *genai.GenerateVideosOperation) *ai.ModelOperation {
135135
} else {
136136
operation.Error = fmt.Errorf("operation error: %v", veoOp.Error)
137137
}
138-
operation.Output = &ai.ModelResponse{
139-
Message: &ai.Message{
140-
Role: ai.RoleModel,
141-
Content: []*ai.Part{ai.NewTextPart("Video generation failed")},
142-
},
143-
}
144138
return operation
145139
}
146140

go/plugins/googlegenai/veo_test.go

Lines changed: 110 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -236,23 +236,29 @@ func TestFromVeoOperation(t *testing.T) {
236236
t.Parallel()
237237

238238
tests := []struct {
239-
name string
240-
veoOp *genai.GenerateVideosOperation
241-
expectedID string
242-
expectedDone bool
243-
expectedError error
244-
expectedHasOutput bool
239+
name string
240+
veoOp *genai.GenerateVideosOperation
241+
expectedID string
242+
expectedDone bool
243+
expectedError error
244+
expectedHasOutput bool
245+
expectedStatusMsg string
246+
expectedFinishReason ai.FinishReason
247+
expectedMediaParts int
245248
}{
246249
{
247250
name: "pending operation",
248251
veoOp: &genai.GenerateVideosOperation{
249252
Name: "operations/test-operation-123",
250253
Done: false,
251254
},
252-
expectedID: "operations/test-operation-123",
253-
expectedDone: false,
254-
expectedError: nil,
255-
expectedHasOutput: false,
255+
expectedID: "operations/test-operation-123",
256+
expectedDone: false,
257+
expectedError: nil,
258+
expectedHasOutput: true,
259+
expectedStatusMsg: "Video generation in progress...",
260+
expectedFinishReason: "",
261+
expectedMediaParts: 0,
256262
},
257263
{
258264
name: "completed operation with video",
@@ -269,10 +275,13 @@ func TestFromVeoOperation(t *testing.T) {
269275
},
270276
},
271277
},
272-
expectedID: "operations/test-operation-456",
273-
expectedDone: true,
274-
expectedError: nil,
275-
expectedHasOutput: true,
278+
expectedID: "operations/test-operation-456",
279+
expectedDone: true,
280+
expectedError: nil,
281+
expectedHasOutput: true,
282+
expectedStatusMsg: "",
283+
expectedFinishReason: ai.FinishReasonStop,
284+
expectedMediaParts: 1,
276285
},
277286
{
278287
name: "operation with error",
@@ -284,10 +293,13 @@ func TestFromVeoOperation(t *testing.T) {
284293
"code": 400,
285294
},
286295
},
287-
expectedID: "operations/test-operation-error",
288-
expectedDone: true,
289-
expectedError: fmt.Errorf("%s", "Video generation failed due to content policy"),
290-
expectedHasOutput: false,
296+
expectedID: "operations/test-operation-error",
297+
expectedDone: true,
298+
expectedError: fmt.Errorf("%s", "Video generation failed due to content policy"),
299+
expectedHasOutput: false,
300+
expectedStatusMsg: "",
301+
expectedFinishReason: "",
302+
expectedMediaParts: 0,
291303
},
292304
{
293305
name: "operation with malformed error",
@@ -297,13 +309,15 @@ func TestFromVeoOperation(t *testing.T) {
297309
Error: map[string]any{
298310
"code": 500,
299311
"details": "Internal error",
300-
// No "message" field
301312
},
302313
},
303-
expectedID: "operations/test-operation-bad-error",
304-
expectedDone: true,
305-
expectedError: fmt.Errorf("operation error: map[code:500 details:Internal error]"),
306-
expectedHasOutput: false,
314+
expectedID: "operations/test-operation-bad-error",
315+
expectedDone: true,
316+
expectedError: fmt.Errorf("operation error: map[code:500 details:Internal error]"),
317+
expectedHasOutput: false,
318+
expectedStatusMsg: "",
319+
expectedFinishReason: "",
320+
expectedMediaParts: 0,
307321
},
308322
{
309323
name: "completed operation with multiple videos",
@@ -325,10 +339,30 @@ func TestFromVeoOperation(t *testing.T) {
325339
},
326340
},
327341
},
328-
expectedID: "operations/test-operation-multi",
329-
expectedDone: true,
330-
expectedError: nil,
331-
expectedHasOutput: true,
342+
expectedID: "operations/test-operation-multi",
343+
expectedDone: true,
344+
expectedError: nil,
345+
expectedHasOutput: true,
346+
expectedStatusMsg: "",
347+
expectedFinishReason: ai.FinishReasonStop,
348+
expectedMediaParts: 2,
349+
},
350+
{
351+
name: "completed operation without videos",
352+
veoOp: &genai.GenerateVideosOperation{
353+
Name: "operations/test-operation-no-videos",
354+
Done: true,
355+
Response: &genai.GenerateVideosResponse{
356+
GeneratedVideos: []*genai.GeneratedVideo{},
357+
},
358+
},
359+
expectedID: "operations/test-operation-no-videos",
360+
expectedDone: true,
361+
expectedError: nil,
362+
expectedHasOutput: true,
363+
expectedStatusMsg: "Video generation completed but no videos were generated",
364+
expectedFinishReason: ai.FinishReasonStop,
365+
expectedMediaParts: 0,
332366
},
333367
}
334368

@@ -345,7 +379,12 @@ func TestFromVeoOperation(t *testing.T) {
345379
t.Errorf("fromVeoOperation() Done = %t, want %t", result.Done, tt.expectedDone)
346380
}
347381

348-
// Compare errors properly - both nil or both non-nil with same message
382+
// Check metadata is initialized
383+
if result.Metadata == nil {
384+
t.Error("fromVeoOperation() Metadata is nil, expected initialized map")
385+
}
386+
387+
// Compare errors
349388
if (result.Error == nil) != (tt.expectedError == nil) {
350389
t.Errorf("fromVeoOperation() Error nil mismatch: got %v, want %v", result.Error, tt.expectedError)
351390
} else if result.Error != nil && tt.expectedError != nil {
@@ -360,31 +399,51 @@ func TestFromVeoOperation(t *testing.T) {
360399
t.Errorf("fromVeoOperation() has output = %t, want %t", hasOutput, tt.expectedHasOutput)
361400
}
362401

363-
// If we expect output, validate it's a ModelResponse with correct structure
364-
if tt.expectedHasOutput && result.Output != nil {
365-
modelResp := result.Output
366-
if modelResp.Message == nil {
367-
t.Error("fromVeoOperation() ModelResponse.Message is nil")
368-
} else {
369-
if modelResp.Message.Role != ai.RoleModel {
370-
t.Errorf("fromVeoOperation() Message.Role = %v, want %v", modelResp.Message.Role, ai.RoleModel)
371-
}
372-
373-
if len(modelResp.Message.Content) == 0 {
374-
t.Error("fromVeoOperation() Message.Content is empty")
375-
} else {
376-
// Verify first content part is a media part
377-
firstPart := modelResp.Message.Content[0]
378-
if !firstPart.IsMedia() {
379-
t.Error("fromVeoOperation() first content part is not media")
380-
}
381-
}
382-
383-
if modelResp.FinishReason != ai.FinishReasonStop {
384-
t.Errorf("fromVeoOperation() FinishReason = %v, want %v", modelResp.FinishReason, ai.FinishReasonStop)
385-
}
402+
// Only validate output structure if we expect output
403+
if !tt.expectedHasOutput {
404+
return
405+
}
406+
407+
// Validate output structure
408+
if result.Output == nil {
409+
t.Fatal("fromVeoOperation() Output is nil, expected ModelResponse")
410+
}
411+
412+
if result.Output.Message == nil {
413+
t.Fatal("fromVeoOperation() ModelResponse.Message is nil")
414+
}
415+
416+
if result.Output.Message.Role != ai.RoleModel {
417+
t.Errorf("fromVeoOperation() Message.Role = %v, want %v", result.Output.Message.Role, ai.RoleModel)
418+
}
419+
420+
if len(result.Output.Message.Content) == 0 {
421+
t.Fatal("fromVeoOperation() Message.Content is empty")
422+
}
423+
424+
// Check status message for text-based responses
425+
if tt.expectedStatusMsg != "" {
426+
firstPart := result.Output.Message.Content[0]
427+
if firstPart.Text != tt.expectedStatusMsg {
428+
t.Errorf("fromVeoOperation() status message = %q, want %q", firstPart.Text, tt.expectedStatusMsg)
386429
}
387430
}
431+
432+
// Check media parts count
433+
mediaCount := 0
434+
for _, part := range result.Output.Message.Content {
435+
if part.IsMedia() {
436+
mediaCount++
437+
}
438+
}
439+
if mediaCount != tt.expectedMediaParts {
440+
t.Errorf("fromVeoOperation() media parts count = %d, want %d", mediaCount, tt.expectedMediaParts)
441+
}
442+
443+
// Check finish reason
444+
if result.Output.FinishReason != tt.expectedFinishReason {
445+
t.Errorf("fromVeoOperation() FinishReason = %v, want %v", result.Output.FinishReason, tt.expectedFinishReason)
446+
}
388447
})
389448
}
390449
}

0 commit comments

Comments
 (0)