Skip to content
quarry Artifact [1210cbf4d3]
Login

Artifact [1210cbf4d3]

Artifact 1210cbf4d375b3acf647b964beb33fb9d50855b08f383e257de6af699868c50c:


package oltp

import (
	"sync"
	"testing"

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

// An account whose only token resolves to no push letter has no push
// credential, but its token still proves it: LetterlessSecrets answers
// that token's secret so a card signed with it can be told what is
// missing. A name that is not an account, and a disabled account, have
// nothing to answer.
func TestLetterlessSecretsAreTheTokensThatSignNoPush(t *testing.T) {
	db := tokenDB(t, "sandbox")
	if err := db.AddAccount("pat", "irrelevant to pushing", false); err != nil {
		t.Fatal(err)
	}
	if err := db.Grant("pat", "sandbox", Read); err != nil {
		t.Fatal(err)
	}
	if _, err := db.MintSyncToken("pat"); err != nil {
		t.Fatal(err)
	}
	if got := db.Secrets("sandbox", "pat"); len(got) != 0 {
		t.Fatalf("FAIL: a reader's token signs a push: %+v", got)
	}
	got := db.LetterlessSecrets("sandbox", "pat")
	if len(got) != 1 || got[0].CheckIn || got[0].Publish || got[0].Secret == "" {
		t.Fatalf("FAIL: the reader's token is not offered as letterless: %+v", got)
	}
	if got := db.LetterlessSecrets("sandbox", "nobody-here"); len(got) != 0 {
		t.Errorf("FAIL: an unknown name has credentials: %+v", got)
	}
	// An account that may push has its token in Secrets, not here.
	writerWithToken(t, db, "jan", "sandbox")
	if got := db.LetterlessSecrets("sandbox", "jan"); len(got) != 0 {
		t.Errorf("FAIL: a pushing token is offered as letterless: %+v", got)
	}
	if err := db.SetDisabled("pat", true); err != nil {
		t.Fatal(err)
	}
	if got := db.LetterlessSecrets("sandbox", "pat"); len(got) != 0 {
		t.Errorf("FAIL: a disabled account has credentials: %+v", got)
	}
	t.Log("ok")
}

// SecretsAt is Secrets with the secret derived from the code given: the
// same credentials, the same letters, a different code, and nothing at
// all for an empty code, a run's name, a disabled account or a name that
// is no account.
func TestSecretsAtDerivesFromTheGivenCodeAndChangesNothingElse(t *testing.T) {
	db := tokenDB(t, "sandbox")
	writerWithToken(t, db, "jan", "sandbox")
	base := db.Secrets("sandbox", "jan")
	if len(base) != 1 {
		t.Fatalf("FAIL: want one credential, got %+v", base)
	}
	other := "0123456789abcdef0123456789abcdef01234567"
	at := db.SecretsAt("sandbox", "jan", other)
	if len(at) != 1 || at[0].Secret == base[0].Secret || at[0].Token != base[0].Token ||
		at[0].CheckIn != base[0].CheckIn || at[0].Publish != base[0].Publish {
		t.Errorf("FAIL: SecretsAt = %+v beside %+v", at, base)
	}
	same, _ := db.SyncProjectCode("sandbox")
	if got := db.SecretsAt("sandbox", "jan", same); len(got) != 1 || got[0].Secret != base[0].Secret {
		t.Errorf("FAIL: the store's own code derives %+v, not %+v", got, base)
	}
	for name, got := range map[string][]xfer.Credential{
		"empty code": db.SecretsAt("sandbox", "jan", ""),
		"run name":   db.SecretsAt("sandbox", "run-x", other),
		"no account": db.SecretsAt("sandbox", "nobody-here", other),
	} {
		if len(got) != 0 {
			t.Errorf("FAIL: %s derives %+v", name, got)
		}
	}
	if err := db.SetDisabled("jan", true); err != nil {
		t.Fatal(err)
	}
	if got := db.SecretsAt("sandbox", "jan", other); len(got) != 0 {
		t.Errorf("FAIL: a disabled account derives %+v", got)
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// A claim on a project code is one statement that succeeds only while no
// other repository has the code or lacks one to compare; repositories
// that already share a code keep sharing it.
func TestClaimProjectCode(t *testing.T) {
	db := tokenDB(t, "a", "b", "c")
	if got, err := db.ClaimProjectCode("a", "X"); err != nil || got != CodeUnknown {
		t.Fatalf("FAIL: with other rows recording no code, claim = %v, %v; want CodeUnknown", got, err)
	}
	for _, r := range []string{"b", "c"} {
		if err := db.SetRepoCode(r, "SHARED"); err != nil {
			t.Fatal(err)
		}
	}
	if err := db.SetRepoCode("a", "OWN"); err != nil {
		t.Fatal(err)
	}
	if got, _ := db.ClaimProjectCode("a", "SHARED"); got != CodeTaken {
		t.Errorf("FAIL: a code two repositories hold was claimed: %v", got)
	}
	if got, err := db.ClaimProjectCode("a", "NEW"); err != nil || got != CodeClaimed {
		t.Fatalf("FAIL: an unused code was %v, %v", got, err)
	}
	if got, _ := db.RepoCode("a"); got != "NEW" {
		t.Errorf("FAIL: the row records %q", got)
	}
	// b and c share a code and are untouched by it.
	if got, _ := db.RepoCode("b"); got != "SHARED" {
		t.Errorf("FAIL: an existing shared code moved: %q", got)
	}
	// Taken now, by a; and given back by the store's answer.
	if got, _ := db.ClaimProjectCode("b", "NEW"); got != CodeTaken {
		t.Errorf("FAIL: a claimed code was claimed again: %v", got)
	}
	if err := db.SetRepoCode("a", "OWN"); err != nil {
		t.Fatal(err)
	}
	if got, _ := db.ClaimProjectCode("b", "NEW"); got != CodeClaimed {
		t.Errorf("FAIL: a released code was %v", got)
	}
	if got, _ := db.ClaimProjectCode("nobody", "Z"); got == CodeClaimed {
		t.Errorf("FAIL: a repository that is not registered claimed a code")
	}
	if got, _ := db.ClaimProjectCode("a", ""); got == CodeClaimed {
		t.Errorf("FAIL: an empty code was claimed")
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// Two repositories claiming one code at once: exactly one wins.
func TestConcurrentClaimsHaveOneWinner(t *testing.T) {
	db := tokenDB(t, "a", "b")
	for _, r := range []string{"a", "b"} {
		if err := db.SetRepoCode(r, "own-"+r); err != nil {
			t.Fatal(err)
		}
	}
	var wg sync.WaitGroup
	won := make(chan string, 2)
	for _, r := range []string{"a", "b"} {
		wg.Add(1)
		go func() {
			defer wg.Done()
			if got, err := db.ClaimProjectCode(r, "SAME"); err == nil && got == CodeClaimed {
				won <- r
			}
		}()
	}
	wg.Wait()
	close(won)
	if n := len(won); n != 1 {
		t.Errorf("FAIL: %d repositories won one code", n)
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// Only a repository that could hold a code it has not recorded blocks a
// claim: a Failed row is a record and a Cloning one is let through, while
// a Ready one with no code blocks until it is backfilled.
func TestClaimIgnoresFailedAndCloningRowsButNotUnrecordedReadyOnes(t *testing.T) {
	db := tokenDB(t, "mine", "failed", "cloning", "ready")
	if err := db.SetRepoState("failed", Failed, "x"); err != nil {
		t.Fatal(err)
	}
	if err := db.SetRepoState("cloning", Cloning, ""); err != nil {
		t.Fatal(err)
	}
	if got, _ := db.ClaimProjectCode("mine", "NEW"); got != CodeUnknown {
		t.Fatalf("FAIL: a Ready row with no code did not block the claim: %v", got)
	}
	rows, err := db.ReadyWithoutCode()
	if err != nil || len(rows) != 2 || rows["ready"] == "" || rows["mine"] == "" {
		t.Fatalf("FAIL: ReadyWithoutCode = %v, %v", rows, err)
	}
	if err := db.SetRepoCode("ready", "OTHER"); err != nil {
		t.Fatal(err)
	}
	if got, err := db.ClaimProjectCode("mine", "NEW"); err != nil || got != CodeClaimed {
		t.Errorf("FAIL: with only Failed and Cloning rows unrecorded the claim was %v, %v", got, err)
	}
	if n, _ := db.CodeHeldElsewhere("ready", "NEW"); n != 1 {
		t.Errorf("FAIL: CodeHeldElsewhere = %d, want 1", n)
	}
	if !t.Failed() {
		t.Log("ok")
	}
}

// A private import still cloning blocks a claim, since its channel would
// otherwise be shared with whoever claimed its code meanwhile; a public
// one, or a failed one of either, does not.
func TestAPrivateCloningRowBlocksAClaim(t *testing.T) {
	db := tokenDB(t, "mine", "other")
	if err := db.SetRepoCode("other", "OTHER"); err != nil {
		t.Fatal(err)
	}
	if err := db.SetRepoCode("mine", "OWN"); err != nil {
		t.Fatal(err)
	}
	add := func(name, vis, state string) {
		t.Helper()
		if err := db.AddRepo(name, t.TempDir(), "", vis); err != nil {
			t.Fatal(err)
		}
		if err := db.SetRepoState(name, state, "x"); err != nil {
			t.Fatal(err)
		}
	}
	add("pubclone", Public, Cloning)
	add("privfail", Private, Failed)
	if got, err := db.ClaimProjectCode("mine", "A"); err != nil || got != CodeClaimed {
		t.Fatalf("FAIL: a public Cloning and a private Failed row blocked a claim: %v, %v", got, err)
	}
	add("privclone", Private, Cloning)
	if got, _ := db.ClaimProjectCode("mine", "B"); got != CodeUnknown {
		t.Errorf("FAIL: a private Cloning row did not block a claim: %v", got)
	}
	if err := db.SetRepoState("privclone", Ready, ""); err != nil {
		t.Fatal(err)
	}
	if err := db.SetRepoCode("privclone", "P"); err != nil {
		t.Fatal(err)
	}
	if got, _ := db.ClaimProjectCode("mine", "B"); got != CodeClaimed {
		t.Errorf("FAIL: a recorded Ready row still blocked: %v", got)
	}
	if !t.Failed() {
		t.Log("ok")
	}
}