Skip to content
quarry Artifact [22c7bc910c]
Login

Artifact [22c7bc910c]

Artifact 22c7bc910ce745c4d98bc66f7f7a8d347ee9162be23fa5a9b73ae0c279c1c2ed:


package oltp

import "testing"

// RFC 0021, Reach and following: a site agent holds its person's string
// on every repository the person owns, now and as they come, and on
// nothing else; a removal sticks; the deed moving moves it.
func TestASiteAgentFollowsItsPersonIntoTheirRepositories(t *testing.T) {
	db := agentRig(t)
	if err := db.NewForgeAgent("zg", "root"); err != nil {
		t.Fatal(err)
	}
	if err := db.AddRepo("theirs", t.TempDir(), "", Public); err != nil {
		t.Fatal(err)
	}
	for repo, owner := range map[string]string{"pub": "root", "theirs": "jva"} {
		if err := db.SetOwner(repo, owner); err != nil {
			t.Fatal(err)
		}
		if err := db.SetCaps(owner, repo, "a"); err != nil {
			t.Fatal(err)
		}
	}
	held := func(repo string) string { c, _ := db.CapsOf("zg", repo); return c }

	if err := db.SetReach("zg", ReachSite); err != nil {
		t.Fatal(err)
	}
	if held("pub") != "a" || !db.FollowedOn("zg", "pub") {
		t.Errorf("FAIL: the site agent holds %q on its person's repository, want a, followed", held("pub"))
	}
	if held("theirs") != "" {
		t.Errorf("FAIL: the site agent followed into somebody else's repository: %q", held("theirs"))
	}

	// A repository made later is followed into when its deed lands.
	if err := db.AddRepo("later", t.TempDir(), "", Public); err != nil {
		t.Fatal(err)
	}
	if err := db.SetOwner("later", "root"); err != nil {
		t.Fatal(err)
	}
	if err := db.SetCaps("root", "later", "a"); err != nil {
		t.Fatal(err)
	}
	if held("later") != "a" {
		t.Errorf("FAIL: a new repository of its person's: %q, want a", held("later"))
	}
	// The person's string changing changes the follower's.
	if err := db.SetCaps("root", "later", "uv"); err != nil {
		t.Fatal(err)
	}
	if held("later") != "uv" {
		t.Errorf("FAIL: after the person's string changed the follower holds %q, want uv", held("later"))
	}
	// The deed leaving the person takes the follower out.
	if err := db.SetOwner("later", "jva"); err != nil {
		t.Fatal(err)
	}
	if held("later") != "" {
		t.Errorf("FAIL: the follower kept %q on a repository its person gave away", held("later"))
	}

	// An admin's removal sticks across a reconcile.
	if _, err := db.SetCapsGuarded("root", "zg", "pub", ""); err != nil {
		t.Fatal(err)
	}
	if err := db.ReconcileAllFollowing(); err != nil {
		t.Fatal(err)
	}
	if held("pub") != "" {
		t.Errorf("FAIL: a removed followed grant came back: %q", held("pub"))
	}
	// Granting by hand clears the removal, and the row is the admin's.
	if _, err := db.SetCapsGuarded("root", "zg", "pub", "u"); err != nil {
		t.Fatal(err)
	}
	if err := db.ReconcileAllFollowing(); err != nil {
		t.Fatal(err)
	}
	if held("pub") != "u" || db.FollowedOn("zg", "pub") {
		t.Errorf("FAIL: a hand grant reads %q followed=%v, want u and not followed", held("pub"), db.FollowedOn("zg", "pub"))
	}

	// Taking the reach away takes the followed grants with it, and
	// leaves the hand grant.
	if err := db.SetReach("zg", ""); err != nil {
		t.Fatal(err)
	}
	if held("pub") != "u" {
		t.Errorf("FAIL: clearing the reach removed a hand grant: %q", held("pub"))
	}
}

func TestOnlyAnAgentHasAReachAndAPersonHasOneSiteAgent(t *testing.T) {
	db := agentRig(t)
	if err := db.SetReach("jva", ReachSite); !IsRefusal(err) {
		t.Errorf("FAIL: a person took a reach: %v", err)
	}
	if err := db.SetReach("dmestas-coder", "everywhere"); !IsRefusal(err) {
		t.Errorf("FAIL: an unknown reach was taken: %v", err)
	}
	if err := db.SetReach("dmestas-coder", ReachSite); err != nil {
		t.Fatal(err)
	}
	if err := db.NewAgent("dmestas-other", "dmestas", -1); err != nil {
		t.Fatal(err)
	}
	if err := db.SetReach("dmestas-other", ReachSite); !IsRefusal(err) {
		t.Errorf("FAIL: a second site agent for one person: %v", err)
	}
	if got := db.SiteAgentOf("dmestas"); got != "dmestas-coder" {
		t.Errorf("FAIL: SiteAgentOf = %q", got)
	}
}