@@ -2,6 +2,7 @@ package ffmpeg_test
22
33import (
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