package main import ( "bytes" "errors" "io" "io/fs" "path/filepath" "testing" ) // blobPath points tests at the default disk store's file for a blob id — // test-only sugar (asserting bytes really live on disk / were unlinked). // Production code goes through db.blobs and must not assume bytes are files. func (db *DB) blobPath(id string) string { return db.blobs.(*diskBlobStore).path(id) } // The blobStore contract, exercised against implementation #1 (disk): a staged // write committed under an id round-trips byte-for-byte, and remove makes it // unopenable. Any future implementation (an object store, per issue #550) must // pass this same sequence. func TestDiskBlobStoreRoundTrip(t *testing.T) { store, err := newDiskBlobStore(filepath.Join(t.TempDir(), "blobs")) if err != nil { t.Fatalf("newDiskBlobStore: %v", err) } payload := []byte("pretend-this-is-encrypted-bytes\x00\x01\x02") // put: stream in two writes to prove staging accumulates, then publish. w, err := store.create() if err != nil { t.Fatalf("create: %v", err) } if _, err := w.Write(payload[:10]); err != nil { t.Fatalf("write: %v", err) } if _, err := w.Write(payload[10:]); err != nil { t.Fatalf("write: %v", err) } if err := w.commit("blobid_123-abc"); err != nil { t.Fatalf("commit: %v", err) } // open: bytes, size, and a usable modtime all come back. r, size, modTime, err := store.open("blobid_123-abc") if err != nil { t.Fatalf("open: %v", err) } got, err := io.ReadAll(r) r.Close() if err != nil || !bytes.Equal(got, payload) { t.Fatalf("round-trip mismatch: err=%v got=%q", err, got) } if size != int64(len(payload)) { t.Fatalf("size = %d, want %d", size, len(payload)) } if modTime.IsZero() { t.Fatal("zero modtime") } // delete → open fails with the contractual not-exist error. if err := store.remove("blobid_123-abc"); err != nil { t.Fatalf("remove: %v", err) } if _, _, _, err := store.open("blobid_123-abc"); !errors.Is(err, fs.ErrNotExist) { t.Fatalf("open after remove: want fs.ErrNotExist, got %v", err) } // GC unlinks best-effort, so removing an id that's already gone is not an // error. if err := store.remove("blobid_123-abc"); err != nil { t.Fatalf("remove of missing id: %v", err) } } // An aborted staged write leaves nothing fetchable — the id is never published. func TestDiskBlobStoreAbortDiscards(t *testing.T) { store, err := newDiskBlobStore(filepath.Join(t.TempDir(), "blobs")) if err != nil { t.Fatalf("newDiskBlobStore: %v", err) } w, err := store.create() if err != nil { t.Fatalf("create: %v", err) } if _, err := w.Write([]byte("half an upload")); err != nil { t.Fatalf("write: %v", err) } w.abort() if _, _, _, err := store.open("neverpublished"); !errors.Is(err, fs.ErrNotExist) { t.Fatalf("open of aborted write: want fs.ErrNotExist, got %v", err) } }