package shortcodes import ( "bytes" "image" "image/color" "image/jpeg" "image/png" "os" "path/filepath" "strconv" "strings" "testing" "testing/fstest" "time" "khosra/internal/render" ) // wide builds a real encoded picture of a given width, so the tests exercise decoding rather than a stub. func wide(t *testing.T, width int, asPNG bool) []byte { t.Helper() img := image.NewRGBA(image.Rect(0, 0, width, width/2)) for x := range width { for y := range width / 2 { img.Set(x, y, color.RGBA{uint8(x % 256), uint8(y % 256), 128, 255}) } } var out bytes.Buffer var err error if asPNG { err = png.Encode(&out, img) } else { err = jpeg.Encode(&out, img, nil) } if err != nil { t.Fatal(err) } return out.Bytes() } func TestDeriveMakesEachMissingWidthAndIsIdempotent(t *testing.T) { cache := t.TempDir() big := wide(t, 2000, false) fsys := fstest.MapFS{ "content/art/set/index.md": {Data: []byte("---\ntitle: Set\n---\n")}, "content/art/set/big.jpg": {Data: big}, "content/art/set/small.png": {Data: wide(t, 300, true)}, // narrower than every target "content/art/set/notes.md": {Data: []byte("not a picture")}, } made, err := Derive(fsys, cache) if err != nil { t.Fatal(err) } if made != len(widths) { t.Errorf("made %d derivatives, want %d — one per width below the original's", made, len(widths)) } // Never upscale: nothing is made for a picture already narrower than the targets. entries, err := os.ReadDir(cache) if err != nil { t.Fatal(err) } if len(entries) != len(widths) { t.Errorf("cache holds %d files, want %d", len(entries), len(widths)) } // Each is a real image of the width it claims. for _, e := range entries { data, err := os.ReadFile(filepath.Join(cache, e.Name())) if err != nil { t.Fatal(err) } cfg, _, err := image.DecodeConfig(bytes.NewReader(data)) if err != nil { t.Fatalf("%s is not a decodable image: %v", e.Name(), err) } if !strings.Contains(e.Name(), "-w"+strconv.Itoa(cfg.Width)) { t.Errorf("%s decodes to width %d, which its name does not claim", e.Name(), cfg.Width) } if cfg.Height != cfg.Width/2 { t.Errorf("%s is %dx%d — the aspect ratio was not kept", e.Name(), cfg.Width, cfg.Height) } } // A second pass writes nothing: the name is the source's content, so there is nothing new to make. again, err := Derive(fsys, cache) if err != nil { t.Fatal(err) } if again != 0 { t.Errorf("second pass made %d, want 0 — the pass must be idempotent (ADR-0042)", again) } } func TestAnEditedPictureGetsADifferentName(t *testing.T) { // Content-addressed, so a stale derivative can never be served under a name that now means something else. first := derivedName(wide(t, 1000, false), "content/a/x.jpg", 480) second := derivedName(wide(t, 1200, false), "content/a/x.jpg", 480) if first == second { t.Error("two different pictures must not share a derivative name") } if derivedName([]byte("same"), "a.png", 480) == derivedName([]byte("same"), "a.png", 960) { t.Error("two widths of one picture must not share a name either") } if !strings.HasSuffix(derivedName([]byte("x"), "a.png", 480), ".png") { t.Error("a source that may carry transparency keeps a lossless derivative") } } func TestOriginalsAreNeverTouched(t *testing.T) { cache := t.TempDir() big := wide(t, 2000, false) original := append([]byte(nil), big...) fsys := fstest.MapFS{"content/art/set/big.jpg": {Data: big}} if _, err := Derive(fsys, cache); err != nil { t.Fatal(err) } after, err := fsys.ReadFile("content/art/set/big.jpg") if err != nil { t.Fatal(err) } if !bytes.Equal(original, after) { t.Error("the author's own file was modified") } } func TestAnEditedPictureIsInspectedAgain(t *testing.T) { // The whole risk of remembering: serving yesterday's size or srcset. The key carries size and modification // time, so an edit is a different key rather than a stale hit. fsys := fstest.MapFS{ "content/art/set/index.md": {Data: []byte("---\ntitle: Set\n---\n")}, "content/art/set/one.jpg": {Data: wide(t, 1200, false), ModTime: time.Unix(1000, 0)}, } origin := render.Origin{Dir: "content/art/set", Files: fsys} first, ok := picture(origin, "one.jpg") if !ok || first.Width != 1200 { t.Fatalf("first inspection = %+v", first) } if again, _ := picture(origin, "one.jpg"); again != first { t.Errorf("a second look at the same file should be identical, got %+v", again) } fsys["content/art/set/one.jpg"] = &fstest.MapFile{Data: wide(t, 800, false), ModTime: time.Unix(2000, 0)} edited, ok := picture(origin, "one.jpg") if !ok { t.Fatal("still a picture") } if edited.Width != 800 { t.Errorf("width = %d, want 800 — the edit was not noticed", edited.Width) } if edited.Srcset == first.Srcset { t.Error("the srcset should name different derivatives after an edit") } }