Skip to content

Commit 2221d5e

Browse files
committed
test: add AVError and WrapErr error handling tests
- Add TestAVError_KnownCodes verifying error string representation: - AVErrorEOF produces readable "End of file" description - EAgain produces "Resource temporarily unavailable" - Custom error codes include numeric code in message - AVError implements error interface correctly - Add TestWrapErr_BoundaryConditions verifying boundary behaviour: - Zero and positive values return nil - Negative values return AVError with correct code - Predefined errors have expected code values - Error comparison works for same codes
1 parent 5251de0 commit 2221d5e

1 file changed

Lines changed: 207 additions & 0 deletions

File tree

ffmpeg_test.go

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package ffmpeg_test
22

33
import (
44
"fmt"
5+
"strings"
56
"sync"
67
"testing"
78

@@ -231,3 +232,209 @@ func TestCStr_BasicOperations(t *testing.T) {
231232
}
232233
})
233234
}
235+
236+
// =============================================================================
237+
// Test 4.1: AVError String Representation
238+
// =============================================================================
239+
240+
// TestAVError_KnownCodes verifies that standard FFmpeg error codes produce
241+
// readable error messages containing both the code and a description.
242+
func TestAVError_KnownCodes(t *testing.T) {
243+
t.Run("averror_eof_has_description", func(t *testing.T) {
244+
err := ffmpeg.AVErrorEOF
245+
246+
errStr := err.Error()
247+
248+
// Should contain the error code
249+
if !strings.Contains(errStr, fmt.Sprintf("%d", ffmpeg.AVErrorEofConst)) {
250+
t.Errorf("Error string should contain code %d, got: %s", ffmpeg.AVErrorEofConst, errStr)
251+
}
252+
253+
// Should contain "averror" prefix
254+
if !strings.Contains(errStr, "averror") {
255+
t.Errorf("Error string should contain 'averror', got: %s", errStr)
256+
}
257+
258+
// Should have some description (not empty after the colon)
259+
parts := strings.SplitN(errStr, ":", 2)
260+
if len(parts) != 2 || strings.TrimSpace(parts[1]) == "" {
261+
t.Errorf("Error string should have non-empty description, got: %s", errStr)
262+
}
263+
264+
t.Logf("AVErrorEOF: %s", errStr)
265+
})
266+
267+
t.Run("eagain_has_description", func(t *testing.T) {
268+
err := ffmpeg.EAgain
269+
270+
errStr := err.Error()
271+
272+
// Should contain "averror" prefix
273+
if !strings.Contains(errStr, "averror") {
274+
t.Errorf("Error string should contain 'averror', got: %s", errStr)
275+
}
276+
277+
// Should have some description
278+
parts := strings.SplitN(errStr, ":", 2)
279+
if len(parts) != 2 || strings.TrimSpace(parts[1]) == "" {
280+
t.Errorf("Error string should have non-empty description, got: %s", errStr)
281+
}
282+
283+
t.Logf("EAgain: %s", errStr)
284+
})
285+
286+
t.Run("custom_error_code", func(t *testing.T) {
287+
// Test with a generic negative error code
288+
err := ffmpeg.AVError{Code: -1}
289+
290+
errStr := err.Error()
291+
292+
// Should contain the error code
293+
if !strings.Contains(errStr, "-1") {
294+
t.Errorf("Error string should contain code -1, got: %s", errStr)
295+
}
296+
297+
// Should contain "averror" prefix
298+
if !strings.Contains(errStr, "averror") {
299+
t.Errorf("Error string should contain 'averror', got: %s", errStr)
300+
}
301+
302+
t.Logf("Custom error -1: %s", errStr)
303+
})
304+
305+
t.Run("error_implements_error_interface", func(t *testing.T) {
306+
var err error = ffmpeg.AVError{Code: -1}
307+
308+
// Should be usable as error interface
309+
if err == nil {
310+
t.Error("AVError should not be nil when wrapped as error")
311+
}
312+
313+
// Error() should return a string
314+
if err.Error() == "" {
315+
t.Error("Error() should return non-empty string")
316+
}
317+
})
318+
319+
t.Run("error_code_accessible", func(t *testing.T) {
320+
code := ffmpeg.AVErrorEofConst
321+
err := ffmpeg.AVError{Code: code}
322+
323+
if err.Code != code {
324+
t.Errorf("Error code mismatch: expected %d, got %d", code, err.Code)
325+
}
326+
})
327+
}
328+
329+
// =============================================================================
330+
// Test 4.2: WrapErr Boundary Conditions
331+
// =============================================================================
332+
333+
// TestWrapErr_BoundaryConditions verifies that WrapErr correctly handles
334+
// boundary conditions: zero returns nil, negative returns error.
335+
func TestWrapErr_BoundaryConditions(t *testing.T) {
336+
t.Run("zero_returns_nil", func(t *testing.T) {
337+
err := ffmpeg.WrapErr(0)
338+
339+
if err != nil {
340+
t.Errorf("WrapErr(0) should return nil, got: %v", err)
341+
}
342+
})
343+
344+
t.Run("positive_returns_nil", func(t *testing.T) {
345+
testCases := []int{1, 10, 100, 1000, 1<<30 - 1}
346+
347+
for _, code := range testCases {
348+
err := ffmpeg.WrapErr(code)
349+
if err != nil {
350+
t.Errorf("WrapErr(%d) should return nil, got: %v", code, err)
351+
}
352+
}
353+
})
354+
355+
t.Run("negative_one_returns_error", func(t *testing.T) {
356+
err := ffmpeg.WrapErr(-1)
357+
358+
if err == nil {
359+
t.Error("WrapErr(-1) should return error, got nil")
360+
}
361+
362+
avErr, ok := err.(ffmpeg.AVError)
363+
if !ok {
364+
t.Errorf("WrapErr(-1) should return AVError, got %T", err)
365+
}
366+
367+
if avErr.Code != -1 {
368+
t.Errorf("AVError.Code should be -1, got %d", avErr.Code)
369+
}
370+
})
371+
372+
t.Run("various_negative_codes_return_error", func(t *testing.T) {
373+
testCases := []int{-1, -2, -10, -100, -1000, -1 << 30}
374+
375+
for _, code := range testCases {
376+
err := ffmpeg.WrapErr(code)
377+
if err == nil {
378+
t.Errorf("WrapErr(%d) should return error, got nil", code)
379+
}
380+
381+
avErr, ok := err.(ffmpeg.AVError)
382+
if !ok {
383+
t.Errorf("WrapErr(%d) should return AVError, got %T", code, err)
384+
continue
385+
}
386+
387+
if avErr.Code != code {
388+
t.Errorf("AVError.Code should be %d, got %d", code, avErr.Code)
389+
}
390+
}
391+
})
392+
393+
t.Run("averror_eof_const_wrapped", func(t *testing.T) {
394+
// AVERROR_EOF is a known negative constant
395+
err := ffmpeg.WrapErr(ffmpeg.AVErrorEofConst)
396+
397+
if err == nil {
398+
t.Error("WrapErr(AVErrorEofConst) should return error, got nil")
399+
}
400+
401+
avErr, ok := err.(ffmpeg.AVError)
402+
if !ok {
403+
t.Errorf("WrapErr(AVErrorEofConst) should return AVError, got %T", err)
404+
}
405+
406+
if avErr.Code != ffmpeg.AVErrorEofConst {
407+
t.Errorf("AVError.Code should be %d, got %d", ffmpeg.AVErrorEofConst, avErr.Code)
408+
}
409+
})
410+
411+
t.Run("error_comparison", func(t *testing.T) {
412+
// Wrapped errors with same code should be comparable
413+
err1 := ffmpeg.WrapErr(-1)
414+
err2 := ffmpeg.WrapErr(-1)
415+
416+
avErr1 := err1.(ffmpeg.AVError)
417+
avErr2 := err2.(ffmpeg.AVError)
418+
419+
if avErr1.Code != avErr2.Code {
420+
t.Error("Two AVErrors with same code should have equal Code fields")
421+
}
422+
423+
// Value comparison should work
424+
if avErr1 != avErr2 {
425+
t.Error("Two AVErrors with same code should be equal")
426+
}
427+
})
428+
429+
t.Run("predefined_errors", func(t *testing.T) {
430+
// Test predefined error variables
431+
if ffmpeg.AVErrorEOF.Code != ffmpeg.AVErrorEofConst {
432+
t.Errorf("AVErrorEOF.Code should be %d, got %d", ffmpeg.AVErrorEofConst, ffmpeg.AVErrorEOF.Code)
433+
}
434+
435+
// EAgain should have a negative code
436+
if ffmpeg.EAgain.Code >= 0 {
437+
t.Errorf("EAgain.Code should be negative, got %d", ffmpeg.EAgain.Code)
438+
}
439+
})
440+
}

0 commit comments

Comments
 (0)