aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-15 17:51:24 +0200
committerDanilo M. <danix@danix.xyz>2026-09-15 17:51:24 +0200
commit35f78d269b9f275aecf1bd26eaec8c4f5c3ef17e (patch)
tree43f8a6c8ede98a5c0be37e9b903dbed83893f6bf
parent36208161e177d277a22e32fb21295df37cd8d218 (diff)
downloadnotifyd-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.
-rw-r--r--internal/notify/image_test.go53
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")
+ }
}