diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-15 17:51:24 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-15 17:51:24 +0200 |
| commit | 35f78d269b9f275aecf1bd26eaec8c4f5c3ef17e (patch) | |
| tree | 43f8a6c8ede98a5c0be37e9b903dbed83893f6bf /internal | |
| parent | 36208161e177d277a22e32fb21295df37cd8d218 (diff) | |
| download | notifyd-35f78d269b9f275aecf1bd26eaec8c4f5c3ef17e.tar.gz notifyd-35f78d269b9f275aecf1bd26eaec8c4f5c3ef17e.zip | |
test(notify): actually exercise rowstride, 3-channel and short-data paths
The stride test was Height 1, so the second row and the padding beyond the
used pixels were never reached and rowstride was untested despite the
comment. It is now 2x2 with RowStride 12 and asserts a pixel in row 1,
which fails if the stride is ignored (verified by mutation). Add the
3-channel opaque encode and the short-data rejection, both explicit
requirements of the image-data contract.
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/notify/image_test.go | 53 |
1 files changed, 46 insertions, 7 deletions
diff --git a/internal/notify/image_test.go b/internal/notify/image_test.go index 2db4c75..7121f32 100644 --- a/internal/notify/image_test.go +++ b/internal/notify/image_test.go @@ -13,6 +13,8 @@ package notify import ( "bytes" + "image" + "image/color" "image/png" "testing" @@ -70,10 +72,23 @@ func TestImagePathFromHints(t *testing.T) { } } +// checkPixel asserts the RGBA of img at (x,y) matches want. +func checkPixel(t *testing.T, img image.Image, x, y int, want color.RGBA) { + t.Helper() + r, g, b, a := img.At(x, y).RGBA() + if r>>8 != uint32(want.R) || g>>8 != uint32(want.G) || b>>8 != uint32(want.B) || a>>8 != uint32(want.A) { + t.Fatalf("pixel (%d,%d) = %d %d %d %d, want %v", x, y, r>>8, g>>8, b>>8, a>>8, want) + } +} + func TestRawImagePNG(t *testing.T) { - // 2x1 RGBA on a rowstride wider than the data, to prove stride is honoured. - r := &RawImage{Width: 2, Height: 1, RowStride: 12, HasAlpha: true, BitsPerSample: 8, Channels: 4, - Data: []byte{255, 0, 0, 255, 0, 255, 0, 255, 9, 9, 9, 9}} + // 2x2 RGBA with a rowstride wider than Width*Channels. The second row is + // the point: if stride were ignored, row 1 would read the row-0 padding. + r := &RawImage{Width: 2, Height: 2, RowStride: 12, HasAlpha: true, BitsPerSample: 8, Channels: 4, + Data: []byte{ + 255, 0, 0, 255, 0, 255, 0, 255, 9, 9, 9, 9, // row 0: red, green, pad + 0, 0, 255, 255, 255, 255, 255, 255, 9, 9, 9, 9, // row 1: blue, white, pad + }} data, err := r.PNG() if err != nil { t.Fatalf("PNG: %v", err) @@ -82,13 +97,32 @@ func TestRawImagePNG(t *testing.T) { if err != nil { t.Fatalf("decode: %v", err) } - if img.Bounds().Dx() != 2 || img.Bounds().Dy() != 1 { + if img.Bounds().Dx() != 2 || img.Bounds().Dy() != 2 { t.Fatalf("bounds = %v", img.Bounds()) } - r0, g0, b0, a0 := img.At(0, 0).RGBA() - if r0>>8 != 255 || g0>>8 != 0 || b0>>8 != 0 || a0>>8 != 255 { - t.Fatalf("pixel 0 = %d %d %d %d", r0>>8, g0>>8, b0>>8, a0>>8) + checkPixel(t, img, 0, 0, color.RGBA{255, 0, 0, 255}) + checkPixel(t, img, 1, 0, color.RGBA{0, 255, 0, 255}) + checkPixel(t, img, 0, 1, color.RGBA{0, 0, 255, 255}) + checkPixel(t, img, 1, 1, color.RGBA{255, 255, 255, 255}) +} + +func TestRawImagePNGThreeChannel(t *testing.T) { + // 2x1 RGB, no alpha byte: PNG() must force opaque. + r := &RawImage{Width: 2, Height: 1, RowStride: 6, HasAlpha: false, BitsPerSample: 8, Channels: 3, + Data: []byte{255, 0, 0, 0, 255, 0}} + data, err := r.PNG() + if err != nil { + t.Fatalf("PNG: %v", err) } + img, err := png.Decode(bytes.NewReader(data)) + if err != nil { + t.Fatalf("decode: %v", err) + } + if img.Bounds().Dx() != 2 || img.Bounds().Dy() != 1 { + t.Fatalf("bounds = %v", img.Bounds()) + } + checkPixel(t, img, 0, 0, color.RGBA{255, 0, 0, 255}) + checkPixel(t, img, 1, 0, color.RGBA{0, 255, 0, 255}) } func TestRawImagePNGRejectsBadData(t *testing.T) { @@ -98,4 +132,9 @@ func TestRawImagePNGRejectsBadData(t *testing.T) { if _, err := (&RawImage{Width: 1, Height: 1, Channels: 2, BitsPerSample: 8}).PNG(); err == nil { t.Fatal("channels 2 must error") } + // 2x2 RGBA needs 16 bytes; the slice holds one row. + if _, err := (&RawImage{Width: 2, Height: 2, RowStride: 8, BitsPerSample: 8, Channels: 4, + Data: []byte{0, 0, 0, 255, 255, 255, 255, 255}}).PNG(); err == nil { + t.Fatal("short data must error") + } } |
