package apps import ( "os" "path/filepath" "strings" "testing" ) func TestKeyForURL(t *testing.T) { cases := []struct { raw, want string }{ {"https://zddc.varasys.io/releases/archive_stable.html", "zddc.varasys.io/releases/archive_stable.html"}, {"https://ZDDC.Varasys.IO/releases/archive_stable.html", "zddc.varasys.io/releases/archive_stable.html"}, {"http://example.com:80/foo.html", "example.com/foo.html"}, {"https://example.com:443/foo.html", "example.com/foo.html"}, {"https://example.com:8443/foo.html", "example.com:8443/foo.html"}, {"https://example.com/", "example.com/index.html"}, {"https://example.com", "example.com/index.html"}, {"https://example.com//foo//bar.html", "example.com/foo/bar.html"}, } for _, tc := range cases { t.Run(tc.raw, func(t *testing.T) { got, err := keyForURL(tc.raw) if err != nil { t.Fatalf("keyForURL error: %v", err) } if got != tc.want { t.Errorf("got %q, want %q", got, tc.want) } }) } } func TestKeyForURL_Errors(t *testing.T) { cases := []string{ "", "not-a-url", "ftp://example.com/x.html", "https:///x.html", "https://example.com/x.html?v=1", } for _, tc := range cases { t.Run(tc, func(t *testing.T) { if _, err := keyForURL(tc); err == nil { t.Errorf("keyForURL(%q) = nil, want error", tc) } }) } } func TestCacheRoundtrip(t *testing.T) { c, err := NewCache(filepath.Join(t.TempDir(), "_app")) if err != nil { t.Fatalf("NewCache: %v", err) } urlStr := "https://zddc.varasys.io/releases/archive_stable.html" body := []byte("archive content") if c.Has(urlStr) { t.Fatalf("Has(empty cache) = true, want false") } if err := c.Write(urlStr, body); err != nil { t.Fatalf("Write: %v", err) } if !c.Has(urlStr) { t.Fatalf("Has(after write) = false, want true") } got, err := c.Read(urlStr) if err != nil { t.Fatalf("Read: %v", err) } if string(got) != string(body) { t.Errorf("body mismatch") } } func TestCacheAtomicWrite_LeavesNoTempOnSuccess(t *testing.T) { root := filepath.Join(t.TempDir(), "_app") c, _ := NewCache(root) urlStr := "https://zddc.varasys.io/releases/archive_stable.html" if err := c.Write(urlStr, []byte("hello")); err != nil { t.Fatalf("Write: %v", err) } count := 0 _ = filepath.Walk(root, func(p string, info os.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() && strings.Contains(info.Name(), ".tmp.") { count++ } return nil }) if count != 0 { t.Errorf("found %d .tmp.* leftovers, want 0", count) } } func TestCacheSweepsTempsOnNew(t *testing.T) { root := filepath.Join(t.TempDir(), "_app") stale := filepath.Join(root, "example.com", "releases", "archive_stable.html.tmp.123") if err := os.MkdirAll(filepath.Dir(stale), 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(stale, []byte("partial"), 0o644); err != nil { t.Fatal(err) } if _, err := NewCache(root); err != nil { t.Fatalf("NewCache: %v", err) } if _, err := os.Stat(stale); !os.IsNotExist(err) { t.Errorf("stale tmp file not swept: %v", err) } }