package oltp
import "testing"
// rawCaps reads the stored string, bypassing every read-side strip, so
// each test fails when its write-side or migration strip is removed.
func rawCaps(t *testing.T, db *DB, query string, args ...any) string {
t.Helper()
var caps string
if err := db.db.QueryRow(query, args...).Scan(&caps); err != nil {
t.Fatal(err)
}
return caps
}
func TestWritesStripSetupFromStoredCaps(t *testing.T) {
db := testDB(t)
for _, who := range []string{"dan", "tm"} {
if err := db.AddAccount(who, "a long password", false); err != nil {
t.Fatal(err)
}
}
if err := db.SetCaps("dan", "r", "sg"); err != nil {
t.Fatal(err)
}
if got := rawCaps(t, db, `SELECT caps FROM repo_caps WHERE account = 'dan' AND repo = 'r'`); got != "ga" {
t.Fatalf("setCaps stored %q, want ga", got)
}
if err := db.SetCategoryCaps("r", "reader", "usa"); err != nil {
t.Fatal(err)
}
if got := rawCaps(t, db, `SELECT caps FROM repo_category_caps WHERE repo = 'r' AND category = 'reader'`); got != "u" {
t.Fatalf("SetCategoryCaps stored %q, want u", got)
}
if err := db.AddTeam("t", "t", "", "dan"); err != nil {
t.Fatal(err)
}
if err := db.SetTeamMember("t", "tm", "sg", false, true); err != nil {
t.Fatal(err)
}
if got := rawCaps(t, db, `SELECT caps FROM team_member WHERE team = 't' AND account = 'tm'`); got != "ga" {
t.Fatalf("setTeamMember stored %q, want ga", got)
}
}
func TestFleetDefaultCategoryIsStrippedOnRead(t *testing.T) {
db := testDB(t)
if _, err := db.w.Exec(`INSERT OR REPLACE INTO repo_category_caps (repo, category, caps) VALUES ('', 'reader', 'usa')`); err != nil {
t.Fatal(err)
}
if got := db.CategoryCaps("somerepo", "reader"); got != "u" {
t.Fatalf("fleet default read %q, want u", got)
}
}
func TestMigrateSetupCapsCoversEveryTable(t *testing.T) {
db := testDB(t)
for _, q := range []string{
`INSERT INTO repo_caps (account, repo, caps) VALUES ('dan', 'old', 'sg')`,
`INSERT INTO team (name, title, created) VALUES ('t', 't', 'x')`,
`INSERT INTO team_member (team, account, caps) VALUES ('t', 'tm', 'sg')`,
`INSERT INTO repo_category_caps (repo, category, caps) VALUES ('old', 'reader', 'usa')`,
} {
if _, err := db.w.Exec(q); err != nil {
t.Fatal(err)
}
}
if err := db.MigrateSetupCaps(); err != nil {
t.Fatal(err)
}
for q, want := range map[string]string{
`SELECT caps FROM repo_caps WHERE account = 'dan' AND repo = 'old'`: "ga",
`SELECT caps FROM team_member WHERE team = 't' AND account = 'tm'`: "ga",
`SELECT caps FROM repo_category_caps WHERE repo = 'old' AND category = 'reader'`: "u",
} {
if got := rawCaps(t, db, q); got != want {
t.Errorf("%s migrated to %q, want %q", q, got, want)
}
}
}
// Attribution never lists a letter that grants nothing.
func TestSourcesWithDoesNotAttributeSetup(t *testing.T) {
db := testDB(t)
if err := db.AddAccount("tm", "a long password", false); err != nil {
t.Fatal(err)
}
if err := db.AddTeam("t", "t", "", "tm"); err != nil {
t.Fatal(err)
}
if err := db.SetTeamRepo("t", "r", "tm"); err != nil {
t.Fatal(err)
}
if _, err := db.w.Exec(`UPDATE team_member SET caps = 'sg' WHERE team = 't' AND account = 'tm'`); err != nil {
t.Fatal(err)
}
src := db.SourcesWith("tm", "r", "sg")
if _, ok := src['s']; ok {
t.Fatalf("an s is attributed to %q", src['s'])
}
if _, ok := src['a']; !ok {
t.Fatal("the admin an s maps to has no source")
}
}