package uevent_test import ( "encoding" "reflect" "testing" "hakurei.app/internal/uevent" ) // adeT sets up a parallel subtest for a textual appender/decoder/encoder. func adeT[V any, S interface { encoding.TextAppender encoding.TextMarshaler encoding.TextUnmarshaler *V }](t *testing.T, name string, v V, want string, wantErr, wantErrE error) { t.Helper() f := func(t *testing.T) { if name != "" { t.Parallel() } t.Helper() t.Run("decode", func(t *testing.T) { t.Parallel() t.Helper() var got V if err := S(&got).UnmarshalText([]byte(want)); !reflect.DeepEqual(err, wantErr) { t.Fatalf("UnmarshalText: error = %v, want %v", err, wantErr) } if wantErr != nil { return } if !reflect.DeepEqual(&got, &v) { t.Errorf("UnmarshalText: %#v, want %#v", got, v) } }) t.Run("encode", func(t *testing.T) { t.Parallel() t.Helper() if got, err := S(&v).MarshalText(); !reflect.DeepEqual(err, wantErrE) { t.Fatalf("MarshalText: error = %v, want %v", err, wantErrE) } else if err == nil && string(got) != want { t.Errorf("MarshalText: %q, want %q", string(got), want) } }) } if name != "" { t.Run(name, f) } else { f(t) } } // adeT sets up a binary subtest for a textual appender/decoder/encoder. func adeB[V any, S interface { encoding.BinaryAppender encoding.BinaryMarshaler encoding.BinaryUnmarshaler *V }](t *testing.T, name string, v V, want string, wantErr, wantErrE error) { t.Helper() f := func(t *testing.T) { if name != "" { t.Parallel() } t.Helper() t.Run("decode", func(t *testing.T) { t.Parallel() t.Helper() var got V if err := S(&got).UnmarshalBinary([]byte(want)); !reflect.DeepEqual(err, wantErr) { t.Fatalf("UnmarshalBinary: error = %v, want %v", err, wantErr) } if wantErr != nil { return } if !reflect.DeepEqual(&got, &v) { t.Errorf("UnmarshalBinary: %#v, want %#v", got, v) } }) t.Run("encode", func(t *testing.T) { t.Parallel() t.Helper() if got, err := S(&v).MarshalBinary(); !reflect.DeepEqual(err, wantErrE) { t.Fatalf("MarshalBinary: error = %v, want %v", err, wantErrE) } else if err == nil && string(got) != want { t.Errorf("MarshalBinary: %q, want %q", string(got), want) } }) } if name != "" { t.Run(name, f) } else { f(t) } } func TestErrors(t *testing.T) { t.Parallel() testCases := []struct { name string err error want string }{ {"UnsupportedActionError", uevent.UnsupportedActionError("explode"), `unsupported kobject_action "explode"`}, {"MissingHeaderError", uevent.MissingHeaderError("move"), `message "move" has no header`}, {"MessageError MErrorKindHeaderSep", &uevent.MessageError{ Data: "move\x00", Section: "move", Kind: uevent.MErrorKindHeaderSep, }, `header "move" missing separator`}, {"MessageError MErrorKindFinalNUL", &uevent.MessageError{ Data: "move\x00truncated", Section: "truncated", Kind: uevent.MErrorKindFinalNUL, }, `entry "truncated" missing NUL`}, {"MessageError bad", &uevent.MessageError{ Data: "\x00", Kind: 0xbad, }, `section "" is invalid`}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { t.Parallel() if got := tc.err.Error(); got != tc.want { t.Errorf("Error: %q, want %q", got, tc.want) } }) } }