Skip to content
quarry Artifact [ac2aaae596]
Login

Artifact [ac2aaae596]

Artifact ac2aaae596a94cf76ae2bbe24e9fb610beac41aa83f5f1534b90c9285ffc6948:


package oltp

import (
	"path/filepath"
	"testing"

	"craftdesign.group/quarry/internal/uv"
)

// One row per name: a write applies only by fossil's rule, a tombstone
// keeps its row, the catalog is per repository, and a rebuild replaces
// a repository's rows and records the bucket it came from.
func TestUnversionedCatalog(t *testing.T) {
	d, err := Open(filepath.Join(t.TempDir(), "oltp.db"))
	if err != nil {
		t.Fatal(err)
	}
	defer d.Close()
	if files, err := d.UVFiles("w"); err != nil || len(files) != 0 {
		t.Fatalf("FAIL: empty catalog = %v %v", files, err)
	}
	if _, ok, err := d.UVSource("w"); ok || err != nil {
		t.Fatalf("FAIL: a source before any build: %v %v", ok, err)
	}
	put := func(f uv.File) bool {
		t.Helper()
		applied, err := d.PutUVFile("w", f)
		if err != nil {
			t.Fatal(err)
		}
		return applied
	}
	if !put(uv.File{Name: "a.txt", Mtime: 100, Hash: "bb", Size: 3, Who: "lou"}) {
		t.Error("FAIL: the first write did not apply")
	}
	if put(uv.File{Name: "a.txt", Mtime: 99, Hash: "cc", Size: 4, Who: "mallory"}) {
		t.Error("FAIL: an older write applied")
	}
	if put(uv.File{Name: "gone.txt", Mtime: 5, Deleted: true, Who: "lou"}) {
		t.Error("FAIL: a tombstone for a name never held applied")
	}
	if !put(uv.File{Name: "a.txt", Mtime: 200, Deleted: true, Who: "dan"}) {
		t.Error("FAIL: a newer tombstone did not apply")
	}
	f, ok, err := d.UVFile("w", "a.txt")
	if err != nil || !ok || !f.Deleted || f.Hash != "" || f.Size != 0 || f.Mtime != 200 || f.Who != "dan" || f.At == "" {
		t.Errorf("FAIL: tombstone row = %+v %v %v", f, ok, err)
	}
	if !put(uv.File{Name: "a.txt", Mtime: 300, Hash: "dd", Size: 7, Who: "lou"}) {
		t.Error("FAIL: a newer write did not revive the name")
	}
	if _, ok, _ := d.UVFile("other", "a.txt"); ok {
		t.Error("FAIL: a row leaked into another repository")
	}
	rebuilt := []uv.File{
		{Name: "z.tgz", Mtime: 10, Hash: "ee", Size: 9, Who: "ci"},
		{Name: "old.txt", Mtime: 11, Deleted: true, Who: "dan"},
	}
	if err := d.ReplaceUVCatalog("w", "https://acct.example/files", rebuilt); err != nil {
		t.Fatal(err)
	}
	files, err := d.UVFiles("w")
	if err != nil || len(files) != 2 || files[0].Name != "old.txt" || !files[0].Deleted || files[1].Name != "z.tgz" || files[1].Hash != "ee" || files[1].Who != "ci" {
		t.Errorf("FAIL: rebuilt catalog = %+v %v", files, err)
	}
	if src, ok, err := d.UVSource("w"); !ok || err != nil || src != "https://acct.example/files" {
		t.Errorf("FAIL: source = %q %v %v", src, ok, err)
	}
	if err := d.DropUVCatalog("w"); err != nil {
		t.Fatal(err)
	}
	if files, _ := d.UVFiles("w"); len(files) != 0 {
		t.Errorf("FAIL: drop left %v", files)
	}
	if _, ok, _ := d.UVSource("w"); ok {
		t.Error("FAIL: drop left the source, so nothing would rebuild")
	}
	t.Log("ok: the catalog keeps one row per name by fossil's rule and rebuilds whole")
}