package library import ( "io/fs" "os" "path/filepath" "testing" "time" "gitbay.org/cmc/gallery/internal/format" ) func statFile(t *testing.T, body string) (string, fs.FileInfo) { t.Helper() p := filepath.Join(t.TempDir(), "a.jpg") if err := os.WriteFile(p, []byte(body), 0o644); err != nil { t.Fatal(err) } fi, err := os.Stat(p) if err != nil { t.Fatal(err) } return p, fi } func TestMetaCacheRoundTrip(t *testing.T) { path := filepath.Join(t.TempDir(), "sub", "meta.json") c, err := OpenMetaCache(path) if err != nil { t.Fatal(err) } _, fi := statFile(t, "x") m := format.Meta{Width: 3, Height: 2, Camera: "X-T5", Taken: time.Date(2025, 3, 1, 0, 0, 0, 0, time.UTC)} c.put("tokyo/a.jpg", fi, m) c.put("gone/b.jpg", fi, m) if err := c.save(map[string]bool{"tokyo/a.jpg": true}); err != nil { t.Fatal(err) } c2, err := OpenMetaCache(path) if err != nil { t.Fatal(err) } got, ok := c2.get("tokyo/a.jpg", fi) if !ok || !got.Taken.Equal(m.Taken) || got.Camera != "X-T5" || got.Width != 3 { t.Fatalf("get = %+v, %v", got, ok) } if _, ok := c2.get("gone/b.jpg", fi); ok { t.Fatal("entry outside keep survived save") } } func TestMetaCacheMissOnChange(t *testing.T) { c, _ := OpenMetaCache(filepath.Join(t.TempDir(), "meta.json")) p, fi := statFile(t, "x") c.put("a.jpg", fi, format.Meta{Width: 1, Height: 1}) if err := os.WriteFile(p, []byte("longer"), 0o644); err != nil { t.Fatal(err) } fi2, _ := os.Stat(p) if _, ok := c.get("a.jpg", fi2); ok { t.Fatal("size change should miss") } later := fi.ModTime().Add(time.Hour) os.WriteFile(p, []byte("x"), 0o644) os.Chtimes(p, later, later) fi3, _ := os.Stat(p) if _, ok := c.get("a.jpg", fi3); ok { t.Fatal("mtime change should miss") } } func TestMetaCacheCorruptStartsEmpty(t *testing.T) { path := filepath.Join(t.TempDir(), "meta.json") os.WriteFile(path, []byte("{nope"), 0o644) c, err := OpenMetaCache(path) if err != nil { t.Fatal(err) } if len(c.entries) != 0 { t.Fatalf("entries = %v", c.entries) } }