package imgcache import ( "bytes" "errors" "io" "os" "path/filepath" "testing" "sneak.berlin/go/pixa/internal/imagerequest" ) func TestFileStore_WriteAndOpen(t *testing.T) { t.Parallel() tmpDir := t.TempDir() storage, err := NewFileStore(tmpDir) if err != nil { t.Fatalf("NewFileStore() error = %v", err) } content := []byte("hello world") key := string(imagerequest.Source{Host: testHostCDN, Path: testPathCat}.Key()) err = storage.Write(key, content) if err != nil { t.Fatalf("Write() error = %v", err) } // Verify file exists at expected path expectedPath := filepath.Join(tmpDir, key[0:2], key[2:4], key) _, err = os.Stat(expectedPath) if err != nil { t.Errorf("File not at expected path %s: %v", expectedPath, err) } // Open and verify size and content r, size, err := storage.Open(key) if err != nil { t.Fatalf("Open() error = %v", err) } defer func() { _ = r.Close() }() if size != int64(len(content)) { t.Errorf("Open() size = %d, want %d", size, len(content)) } loaded, err := io.ReadAll(r) if err != nil { t.Fatalf("ReadAll() error = %v", err) } if !bytes.Equal(loaded, content) { t.Errorf("Open() content = %q, want %q", loaded, content) } } func TestFileStore_OpenNotFound(t *testing.T) { t.Parallel() tmpDir := t.TempDir() storage, err := NewFileStore(tmpDir) if err != nil { t.Fatalf("NewFileStore() error = %v", err) } _, _, err = storage.Open("nonexistent") if !errors.Is(err, ErrNotFound) { t.Errorf("Open() error = %v, want ErrNotFound", err) } } // TestFileStore_Size checks that Size returns the size of a written file, // and ErrNotFound for a key with no file. func TestFileStore_Size(t *testing.T) { t.Parallel() storage, err := NewFileStore(t.TempDir()) if err != nil { t.Fatalf("NewFileStore() error = %v", err) } content := []byte("the file's content") key := string(imagerequest.Source{Host: testHostCDN, Path: testPathCat}.Key()) err = storage.Write(key, content) if err != nil { t.Fatalf("Write() error = %v", err) } size, err := storage.Size(key) if err != nil || size != int64(len(content)) { t.Errorf("Size() = %d, error %v; want %d", size, err, len(content)) } _, err = storage.Size("nonexistent") if !errors.Is(err, ErrNotFound) { t.Errorf("Size() of a missing file error = %v, want ErrNotFound", err) } } func TestFileStore_Delete(t *testing.T) { t.Parallel() tmpDir := t.TempDir() storage, err := NewFileStore(tmpDir) if err != nil { t.Fatalf("NewFileStore() error = %v", err) } content := []byte("to be deleted") key := string(imagerequest.Source{Host: testHostCDN, Path: testPathCat}.Key()) path := storage.keyToPath(key) err = storage.Write(key, content) if err != nil { t.Fatalf("Write() error = %v", err) } _, err = os.Stat(path) if err != nil { t.Errorf("file missing before Delete(): %v", err) } err = storage.Delete(key) if err != nil { t.Fatalf("Delete() error = %v", err) } _, err = os.Stat(path) if err == nil { t.Error("file still on disk after Delete()") } } func TestFileStore_DeleteNonexistent(t *testing.T) { t.Parallel() tmpDir := t.TempDir() storage, err := NewFileStore(tmpDir) if err != nil { t.Fatalf("NewFileStore() error = %v", err) } // Should not error err = storage.Delete("nonexistent") if err != nil { t.Errorf("Delete() error = %v, want nil", err) } } func TestFileStore_KeyToPath(t *testing.T) { t.Parallel() tmpDir := t.TempDir() storage, err := NewFileStore(tmpDir) if err != nil { t.Fatalf("NewFileStore() error = %v", err) } // Test by writing and verifying the resulting path structure content := []byte("test content for path verification") key := string(imagerequest.Source{Host: testHostCDN, Path: testPathCat}.Key()) err = storage.Write(key, content) if err != nil { t.Fatalf("Write() error = %v", err) } expectedPath := filepath.Join(tmpDir, key[0:2], key[2:4], key) _, err = os.Stat(expectedPath) if err != nil { t.Errorf("File not at expected path %s: %v", expectedPath, err) } }