diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-03-28 00:10:50 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-03-28 00:49:34 +0900 |
| commit | 713bff3eb0a77efff016acc02b6f10913810f887 (patch) | |
| tree | a648ab320007bf1aa15ab2f55e7856713cf92e88 /internal/uevent/uevent_test.go | |
| parent | 30f459e690ca561d3932cb6efa0cf14ea53c25b2 (diff) | |
internal/uevent: decode uevent messages
The wire format and behaviour is entirely undocumented. This is implemented by reading lib/kobject_uevent.c, with testdata collected from the internal/rosa kernel.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/uevent/uevent_test.go')
| -rw-r--r-- | internal/uevent/uevent_test.go | 84 |
1 files changed, 76 insertions, 8 deletions
diff --git a/internal/uevent/uevent_test.go b/internal/uevent/uevent_test.go index 9af3dcdd..53d9bafc 100644 --- a/internal/uevent/uevent_test.go +++ b/internal/uevent/uevent_test.go @@ -2,7 +2,6 @@ package uevent_test import ( "encoding" - "fmt" "reflect" "testing" @@ -14,13 +13,14 @@ func adeT[V any, S interface { encoding.TextAppender encoding.TextMarshaler encoding.TextUnmarshaler - fmt.Stringer *V }](t *testing.T, name string, v V, want string, wantErr, wantErrE error) { t.Helper() - t.Run(name, func(t *testing.T) { - t.Parallel() + f := func(t *testing.T) { + if name != "" { + t.Parallel() + } t.Helper() t.Run("decode", func(t *testing.T) { @@ -49,15 +49,63 @@ func adeT[V any, S interface { } else if err == nil && string(got) != want { t.Errorf("MarshalText: %q, want %q", string(got), want) } - if wantErrE != nil { + }) + } + 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 got := S(&v).String(); got != want { - t.Errorf("String: %q, want %q", got, want) + 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) { @@ -70,6 +118,26 @@ func TestErrors(t *testing.T) { }{ {"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) { |
