package web
import (
"io/fs"
"os"
"path/filepath"
"regexp"
"strings"
"testing"
"craftdesign.group/quarry/internal/api"
"craftdesign.group/quarry/internal/oltp"
"craftdesign.group/quarry/internal/ops"
)
func referenceRegistry(t *testing.T) *ops.Registry {
t.Helper()
r := ops.NewRegistry()
if err := api.RegisterAll(r, api.Deps{Version: "v",
Repos: api.NewRepos(map[string]*api.Repo{})}); err != nil {
t.Fatal(err)
}
return r
}
// Every fossil letter is listed, whether or not quarry acts on it, so a
// fossil user table brought in never looks as if it lost something.
func TestReferenceListsEveryFossilLetterAndMarksTheUnused(t *testing.T) {
p := capReference(referenceRegistry(t), "", nil)
rows := map[string]capRefRow{}
for _, row := range p.Rows {
rows[row.Letter] = row
}
for _, l := range "abcefghijklmnopqrstuvwxyz234567ACD8" {
if _, ok := rows[string(l)]; !ok {
t.Errorf("letter %c is missing from the reference", l)
}
}
if row := rows["o"]; row.Ops == 0 || !row.Used {
t.Errorf("o is required by operations but reads %+v", row)
}
if rows["D"].Used {
t.Error("D does nothing in quarry and is not marked unused")
}
for _, l := range "gjoh2reC458uv" {
if !rows[string(l)].Used {
t.Errorf("%c is enforced outside the operations and shows as unused", l)
}
}
}
// The drift guard: a letter checked anywhere in the source must not be
// shown as unused. A new HasAny("X") with X in no operation and not in
// checkedOutsideOps fails here instead of reading as dead on the page.
func TestEveryCheckedLetterIsInTheReference(t *testing.T) {
used := map[rune]bool{}
for _, row := range capReference(referenceRegistry(t), "", nil).Rows {
if row.Used {
used[[]rune(row.Letter)[0]] = true
}
}
// a and s are the umbrellas; every op gate resolves them.
used['a'], used['s'] = true, true
lit := regexp.MustCompile(`HasAny\("([^"]+)"\)|repoReadLetters\s*=\s*"([^"]+)"`)
found := 0
for _, root := range []string{"../../cmd", "../../internal"} {
err := filepath.WalkDir(root, func(p string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() || !strings.HasSuffix(p, ".go") || strings.HasSuffix(p, "_test.go") {
return nil
}
b, err := os.ReadFile(p)
if err != nil {
return err
}
for _, m := range lit.FindAllStringSubmatch(string(b), -1) {
for _, l := range m[1] + m[2] {
found++
if !used[l] {
t.Errorf("%s checks %q, which the reference shows as unused", p, l)
}
}
}
return nil
})
if err != nil {
t.Fatal(err)
}
}
if found == 0 {
t.Fatal("no letter checks found; the scan proves nothing")
}
}
// Repository settings carry the reference, with who its categories
// give each letter to.
func TestRepositorySettingsShowTheReference(t *testing.T) {
plane := &memCaps{stored: map[string]string{"dan": "a"}}
body := asDan(t, peopleServer(t, plane), "/r/alpha/settings")
if !strings.Contains(body, `data-hook="cap-reference"`) {
t.Fatal("repository settings have no capability reference")
}
if !strings.Contains(body, `<tr data-letter="D" class="unused" aria-disabled="true">`) {
t.Error("an unused letter is not shown disabled")
}
p := capRefFor(nil, plane, "alpha")
for _, row := range p.Rows {
if row.Letter == "o" && len(row.Grants) == 0 {
t.Error("o is in the nobody category but no grant is named")
}
}
}
// A team's reference names what membership alone gives.
func TestTeamReferenceNamesTheFloor(t *testing.T) {
p := capRefTeam(nil)
for _, row := range p.Rows {
in := oltp.CapSet(oltp.Closure(oltp.TeamFloor)).HasAny(row.Letter)
if in != (len(row.Grants) > 0) {
t.Errorf("letter %s: in floor %v, grants %v", row.Letter, in, row.Grants)
}
}
}