Skip to content
quarry Artifact [c70c03b448]
Login

Artifact [c70c03b448]

Artifact c70c03b4489b37771d075dd421faee9ad03428bc17d5d120e7db3aac90b252e3:


package oltp

import (
	"path/filepath"
	"testing"
	"time"
)

// Every repository gets an address, namespace/handle, and the handle of
// one made before namespaced names is its name (RFC 0025): nothing that
// holds a name changes meaning. Two repositories may not share an
// address.
func TestEveryRepositoryHasItsNameAsItsHandle(t *testing.T) {
	path := filepath.Join(t.TempDir(), "oltp.db")
	d, err := Open(path)
	if err != nil {
		t.Fatal(err)
	}
	if err := d.AddRepo("tools", t.TempDir(), "", Public); err != nil {
		t.Fatal(err)
	}
	if err := d.AddImportingRepo("mirror", filepath.Join(t.TempDir(), "m"), "", Public, "https://example.com/m"); err != nil {
		t.Fatal(err)
	}
	// A row from before the column: no handle yet.
	if _, err := d.w.Exec(`UPDATE repo SET handle = '' WHERE name = 'tools'`); err != nil {
		t.Fatal(err)
	}
	d.Close()
	d, err = Open(path)
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { d.Close() })
	for _, name := range []string{"tools", "mirror"} {
		var handle string
		if err := d.db.QueryRow(`SELECT handle FROM repo WHERE name = ?`, name).Scan(&handle); err != nil || handle != name {
			t.Errorf("FAIL: %s has handle %q (%v), want its name", name, handle, err)
		}
	}
	// One address, one repository.
	if _, err := d.w.Exec(`UPDATE repo SET handle = 'tools' WHERE name = 'mirror'`); err == nil {
		t.Error("FAIL: two repositories took the same address")
	}
}

// The forge's namespace is reserved in the pool accounts and teams share.
func TestTheForgeNamespaceIsReserved(t *testing.T) {
	d, err := Open(filepath.Join(t.TempDir(), "oltp.db"))
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { d.Close() })
	for _, name := range []string{ForgeNamespace, "ZeitForge"} {
		if err := d.AddAccount(name, "a-long-enough-password", false); err == nil {
			t.Errorf("FAIL: an account took %q", name)
		}
	}
}

// addressRig is two people, a team ada owns, and ada's own "tools".
func addressRig(t *testing.T) *DB {
	t.Helper()
	d, err := Open(filepath.Join(t.TempDir(), "oltp.db"))
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { d.Close() })
	for _, who := range []string{"ada", "bob"} {
		if err := d.AddAccount(who, "a-long-enough-password", false); err != nil {
			t.Fatal(err)
		}
	}
	if err := d.AddTeam("crew", "Crew", "", "ada"); err != nil {
		t.Fatal(err)
	}
	add := func(key, handle, owner string) {
		t.Helper()
		if err := d.AddRepo(key, t.TempDir(), "", Public); err != nil {
			t.Fatal(err)
		}
		if err := d.SetOwner(key, owner); err != nil {
			t.Fatal(err)
		}
		if err := d.SetNamespace(key, owner, owner, time.Now()); err != nil {
			t.Fatal(err)
		}
		if err := d.SetHandle(key, handle); err != nil {
			t.Fatal(err)
		}
	}
	add("tools", "tools", "ada")
	add("rp-second", "tools", "bob")
	return d
}

// Every way a repository comes to appear somewhere checks that nothing
// else appears there by its name (RFC 0025), and says so in words.
func TestNoTwoRepositoriesShareAnAddress(t *testing.T) {
	d := addressRig(t)
	// Two tools, under ada and bob: allowed.
	var n int
	if err := d.db.QueryRow(`SELECT COUNT(*) FROM repo WHERE handle = 'tools'`).Scan(&n); err != nil || n != 2 {
		t.Fatalf("FAIL: %d repositories called tools (%v), want ada's and bob's", n, err)
	}
	// bob's tools cannot join a namespace that has one.
	if err := d.SetNamespace("rp-second", "ada", "bob", time.Now()); !IsRefusal(err) {
		t.Errorf("FAIL: a second tools moved under ada: %v", err)
	}
	// A deed handed to ada would put bob's tools beside ada's.
	if err := d.DeedMoveRefusal("rp-second", "ada"); !IsRefusal(err) {
		t.Errorf("FAIL: handing bob's tools to ada was not refused: %v", err)
	}
	if err := d.DeedMoveRefusal("rp-second", "bob"); err != nil {
		t.Errorf("FAIL: keeping the deed where it is was refused: %v", err)
	}
	// bob's tools in ada's team is crew/tools: free while crew is public.
	if err := d.SetOwner("rp-second", "ada"); err != nil {
		t.Fatal(err)
	}
	if err := d.SetTeamRepo("crew", "rp-second", "ada"); err != nil {
		t.Fatalf("FAIL: crew/tools refused: %v", err)
	}
	// Private, crew's repositories appear under ada, beside ada's tools.
	if _, err := d.SetTeamPrivate("crew", true); !IsRefusal(err) {
		t.Errorf("FAIL: crew went private with two tools under ada: %v", err)
	}
	// Dissolved, crew's tools would go back to ada, beside ada's tools.
	if err := d.DeleteTeam("crew"); !IsRefusal(err) {
		t.Errorf("FAIL: crew dissolved onto ada's tools: %v", err)
	}
}

// The start-up repair that holds a namespace to its owner leaves a
// repository where it is rather than put two at one address: refusing
// would stop the forge from starting.
func TestTheStartupRepairNeverSharesAnAddress(t *testing.T) {
	path := filepath.Join(t.TempDir(), "oltp.db")
	d, err := Open(path)
	if err != nil {
		t.Fatal(err)
	}
	for _, who := range []string{"ada", "bob"} {
		if err := d.AddAccount(who, "a-long-enough-password", false); err != nil {
			t.Fatal(err)
		}
	}
	for _, key := range []string{"tools", "rp-second"} {
		if err := d.AddRepo(key, t.TempDir(), "", Public); err != nil {
			t.Fatal(err)
		}
	}
	// ada owns both; the second sits under bob's name, which the repair
	// would move back to ada, where ada's own tools is.
	if _, err := d.w.Exec(`UPDATE repo SET owner = 'ada', namespace = 'ada' WHERE name = 'tools'`); err != nil {
		t.Fatal(err)
	}
	if _, err := d.w.Exec(`UPDATE repo SET owner = 'ada', namespace = 'bob', handle = 'tools' WHERE name = 'rp-second'`); err != nil {
		t.Fatal(err)
	}
	d.Close()
	d, err = Open(path)
	if err != nil {
		t.Fatalf("FAIL: the forge did not start: %v", err)
	}
	defer d.Close()
	if ns, _ := d.NamespaceOf("rp-second"); ns != "bob" {
		t.Errorf("FAIL: the repair moved the second tools to %q", ns)
	}
}

// The deed backfill gives an unheld repository to its one admin; where
// that admin already has one by its name, the repository keeps no
// namespace rather than stop the forge starting (RFC 0025).
func TestTheDeedBackfillNeverSharesAnAddress(t *testing.T) {
	path := filepath.Join(t.TempDir(), "oltp.db")
	d, err := Open(path)
	if err != nil {
		t.Fatal(err)
	}
	if err := d.AddAccount("ada", "a-long-enough-password", false); err != nil {
		t.Fatal(err)
	}
	for _, key := range []string{"x", "rp-adasx"} {
		if err := d.AddRepo(key, t.TempDir(), "", Public); err != nil {
			t.Fatal(err)
		}
	}
	if _, err := d.w.Exec(`UPDATE repo SET owner = 'ada', namespace = 'ada', handle = 'x' WHERE name = 'rp-adasx'`); err != nil {
		t.Fatal(err)
	}
	if err := d.SetCaps("ada", "x", "a"); err != nil {
		t.Fatal(err)
	}
	d.Close()
	d, err = Open(path)
	if err != nil {
		t.Fatalf("FAIL: the forge did not start: %v", err)
	}
	defer d.Close()
	if ns, _ := d.NamespaceOf("x"); ns != "" {
		t.Errorf("FAIL: the unheld x was put under %q beside ada's own x", ns)
	}
}