Skip to content
quarry Artifact [4c5b8c42a9]
Login

Artifact [4c5b8c42a9]

Artifact 4c5b8c42a9bb55e37e4475ed9ab323e4574b749fef33a5aafa3d8be40e30748a:


package events

import "testing"

// A family reads back keyed by what follows the prefix, and stops at the
// family's edge: a page showing "who cloned" must not also sweep in the
// client breakdown, or every reader would be counted twice.
func TestAFamilyReadsBackWholeAndNoWider(t *testing.T) {
	s := testServer(t)
	for name, n := range map[string]int64{
		"clone":                  341,
		"clone.anon":             293,
		"clone.auth.zeitgeist":   31,
		"clone.auth.alice":       8,
		"clone.claim.dave":       2,
		"clone.client.zit.22900": 271,
		"fetch.auth.alice":       97,
	} {
		if err := s.Count("alpha", name, n); err != nil {
			t.Fatal(err)
		}
	}

	got, err := s.Totals("alpha", "clone.auth")
	if err != nil {
		t.Fatal(err)
	}
	want := map[string]int64{"zeitgeist": 31, "alice": 8}
	if len(got) != len(want) {
		t.Fatalf("FAIL: clone.auth = %v, want %v", got, want)
	}
	for k, v := range want {
		if got[k] != v {
			t.Fatalf("FAIL: clone.auth = %v, want %v", got, want)
		}
	}

	// A family whose members carry their own structure keeps it: the
	// client family is kind and version, and the caller splits it.
	if got, _ := s.Totals("alpha", "clone.client"); got["zit.22900"] != 271 || len(got) != 1 {
		t.Errorf("FAIL: clone.client = %v, want one zit.22900 at 271", got)
	}
	// The same family under a different verb is a different family.
	if got, _ := s.Totals("alpha", "fetch.auth"); got["alice"] != 97 || len(got) != 1 {
		t.Errorf("FAIL: fetch.auth = %v, want one alice at 97", got)
	}
	// And a family nobody has touched is empty, not an error: "nobody
	// has claimed anything here" is an answer.
	got, err = s.Totals("alpha", "clone.claim")
	if err != nil || got["dave"] != 2 {
		t.Errorf("FAIL: clone.claim = %v, %v; want dave at 2", got, err)
	}
	if got, err := s.Totals("beta", "clone.auth"); err != nil || len(got) != 0 {
		t.Errorf("FAIL: an untouched family = %v, %v; want empty and no error", got, err)
	}
}

// A counter subject is built from names quarry does not control. Subject
// grammar is not the place to be relaxed: a dot would graft a level onto
// the tree, and a > would turn a stored subject into a wildcard matching
// its siblings.
func TestATokenCannotReshapeTheSubjectTree(t *testing.T) {
	for in, want := range map[string]string{
		"alice":        "alice",
		"zeit-geist_1": "zeit-geist_1",
		"a.b":          "a_b",
		"a>b":          "a_b",
		"a*b":          "a_b",
		"a b":          "a_b",
		"":             "_",
		"..":           "__",
	} {
		if got := CounterToken(in); got != want {
			t.Errorf("FAIL: CounterToken(%q) = %q, want %q", in, got, want)
		}
	}
}

// A name that sanitizes into a subject must still land in its own family
// and be readable back — the sanitizer is not allowed to produce a
// subject the reader then cannot find.
func TestASanitizedNameStillCountsAndReadsBack(t *testing.T) {
	s := testServer(t)
	if err := s.Count("alpha", "clone.auth."+CounterToken("weird.name>here"), 4); err != nil {
		t.Fatal(err)
	}
	got, err := s.Totals("alpha", "clone.auth")
	if err != nil {
		t.Fatal(err)
	}
	if got["weird_name_here"] != 4 {
		t.Errorf("FAIL: clone.auth = %v, want weird_name_here at 4", got)
	}
}

func TestTotalsRefusesAnUnnamedFamily(t *testing.T) {
	s := testServer(t)
	if _, err := s.Totals("alpha", ""); err == nil {
		t.Error("FAIL: a family with no prefix was accepted")
	}
	if _, err := s.Totals("", "clone.auth"); err == nil {
		t.Error("FAIL: a family with no repo was accepted")
	}
}