From 23d2882adfa589f4b2f314a64abd81ae42be391f Mon Sep 17 00:00:00 2001 From: OriginalAuthority Date: Wed, 22 Oct 2025 20:47:26 +0100 Subject: [PATCH] chore: add some small tests, more to come! --- models/image_test.go | 34 ++++++++++++++++++ models/thumbnail_test.go | 36 +++++++++++++++++++ services/image_test.go | 76 ++++++++++++++++++++++++++++++++++++++++ utils/validator_test.go | 46 ++++++++++++++++++++++++ 4 files changed, 192 insertions(+) create mode 100644 models/image_test.go create mode 100644 models/thumbnail_test.go create mode 100644 services/image_test.go create mode 100644 utils/validator_test.go diff --git a/models/image_test.go b/models/image_test.go new file mode 100644 index 0000000..6e12a01 --- /dev/null +++ b/models/image_test.go @@ -0,0 +1,34 @@ +package models + +import "testing" + +// Test that an image request returns the appropriate key +func TestGetS3Key(t *testing.T) { + ir := &ImageRequest{ + Wiki: "metawiki", + Hash1: "a", + Hash2: "a0", + Filename: "foo.png", + } + + expectedKey := "metawiki/a/a0/foo.png" + if got := ir.GetS3Key(); got != expectedKey { + t.Fatalf("GetS3Key() = %q, but we expected %q", got, expectedKey) + } +} + +// Test that an image request with a revision returns the appropriate archive key +func TestGetArchiveKey(t *testing.T) { + ir := &ImageRequest{ + Wiki: "metawiki", + Hash1: "a", + Hash2: "a0", + Filename: "foo.png", + Revision: "20251021233101", + } + + expectedKey := "metawiki/archive/a/a0/20251021233101!foo.png" + if got := ir.GetArchiveKey(); got != expectedKey { + t.Fatalf("GetArchiveKey() = %q, but we expected %q", got, expectedKey) + } +} diff --git a/models/thumbnail_test.go b/models/thumbnail_test.go new file mode 100644 index 0000000..1654f99 --- /dev/null +++ b/models/thumbnail_test.go @@ -0,0 +1,36 @@ +package models + +import "testing" + +// Test that a thumbnail request returns the appropriate S3 thumb key +func TestGetS3ThumbKey(t *testing.T) { + tr := &ThumbnailRequest{ + Wiki: "metawiki", + Hash1: "a", + Hash2: "a0", + Filename: "foo.png", + Width: "200", + } + + expectedKey := "metawiki/thumb/a/a0/foo.png/200px-foo.png" + if got := tr.GetS3ThumbKey(); got != expectedKey { + t.Fatalf("GetS3ThumbKey() = %q, but we expected %q", got, expectedKey) + } +} + +// Test that an archive thumbnail request returns the appropriate thumb archive key +func TestGetThumbArchiveKey(t *testing.T) { + tr := &ThumbnailRequest{ + Wiki: "metawiki", + Hash1: "a", + Hash2: "a0", + Filename: "foo.png", + Width: "200", + Revision: "20251021233101", + } + + expectedKey := "metawiki/thumb/archive/a/a0/20251021233101!foo.png/200px-foo.png" + if got := tr.GetThumbArchiveKey(); got != expectedKey { + t.Fatalf("GetThumbArchiveKey() = %q, want %q", got, expectedKey) + } +} diff --git a/services/image_test.go b/services/image_test.go new file mode 100644 index 0000000..7616501 --- /dev/null +++ b/services/image_test.go @@ -0,0 +1,76 @@ +package services + +import ( + "bytes" + "image" + "image/color" + "image/png" + "os" + "path/filepath" + "testing" + + "github.com/telepedia/thumbra/models" +) + +// Encode and decode a PNG image to test helper functions +func TestDecodeEncodePNG(t *testing.T) { + // 10x10 red square for testing + img := image.NewRGBA(image.Rect(0, 0, 10, 10)) + for y := 0; y < 10; y++ { + for x := 0; x < 10; x++ { + img.Set(x, y, color.RGBA{255, 0, 0, 255}) + } + } + + var buf bytes.Buffer + if err := png.Encode(&buf, img); err != nil { + t.Fatalf("failed to encode png: %v", err) + } + + dec, err := decodeImage(bytes.NewReader(buf.Bytes()), "png") + if err != nil { + t.Fatalf("decodeImage failed: %v", err) + } + if dec.Bounds().Dx() != 10 || dec.Bounds().Dy() != 10 { + t.Fatalf("decoded image has wrong dimensions: %v", dec.Bounds()) + } + + tmp := t.TempDir() + outPath := filepath.Join(tmp, "out.png") + f, err := os.Create(outPath) + if err != nil { + t.Fatalf("failed to create temp file: %v", err) + } + if err := encodeImage(f, dec, "png"); err != nil { + t.Fatalf("encodeImage failed: %v", err) + } + f.Close() +} + +// Test thumbnailing an image +func TestThumbnailImage(t *testing.T) { + // 100x50 png + img := image.NewRGBA(image.Rect(0, 0, 100, 50)) + var buf bytes.Buffer + if err := png.Encode(&buf, img); err != nil { + t.Fatalf("failed to encode png: %v", err) + } + + obj := &models.ImageResponse{Data: buf.Bytes()} + svc := &ImageService{} + + // this is larger than the original width, therefore expect an error + tr := models.ThumbnailRequest{Filename: "foo.png", Width: "200"} + if _, err := svc.ThumbnailImage(tr, obj); err == nil { + t.Fatalf("expected error when requesting width larger than original, got nil") + } + + // not actually interested in the image, just check that it returned a valid path + tr2 := models.ThumbnailRequest{Filename: "foo.png", Width: "50"} + path, err := svc.ThumbnailImage(tr2, obj) + if err != nil { + t.Fatalf("ThumbnailImage failed: %v", err) + } + // cleanup + os.Remove(path) +} diff --git a/utils/validator_test.go b/utils/validator_test.go new file mode 100644 index 0000000..02476d2 --- /dev/null +++ b/utils/validator_test.go @@ -0,0 +1,46 @@ +package utils + +import ( + "testing" + + "github.com/telepedia/thumbra/models" +) + +func TestValidateImageRequest(t *testing.T) { + good := models.ImageRequest{ + Wiki: "metawiki", + Hash1: "a", + Hash2: "a0", + Filename: "foo.png", + Revision: "latest", + } + + if err := ValidateImageRequest(good); err != nil { + t.Fatalf("expected nil error for valid request, got %v", err) + } + + bad := models.ImageRequest{} + if err := ValidateImageRequest(bad); err == nil { + t.Fatalf("expected error for invalid request, got nil") + } +} + +func TestValidateThumbnailRequest(t *testing.T) { + good := models.ThumbnailRequest{ + Wiki: "metawiki", + Hash1: "a", + Hash2: "a0", + Filename: "foo.png", + Revision: "latest", + Width: "200", + } + + if err := ValidateThumbnailRequest(good); err != nil { + t.Fatalf("expected nil error for valid thumbnail request, got %v", err) + } + + bad := models.ThumbnailRequest{} + if err := ValidateThumbnailRequest(bad); err == nil { + t.Fatalf("expected error for invalid thumbnail request, got nil") + } +}