package main
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
"craftdesign.group/quarry/internal/api"
"craftdesign.group/quarry/internal/ci"
)
// #307: a new repository cannot take a name whose worker group a live
// engine token still reaches, since that token would run its CI. A
// revoked token, or a site admin's fleet token, does not hold the name;
// an engine that cannot list its tokens does.
func TestAddRefusesANameALiveTokenReaches(t *testing.T) {
addWith := func(eng *tokenEngine) error {
rg := newTestRegistrar(t, 25)
if err := rg.odb.AddAccount("dan", "pw12345678", false); err != nil {
t.Fatal(err)
}
srv := httptest.NewServer(eng)
t.Cleanup(srv.Close)
rg.engine = ci.New(srv.URL)
rg.engine.SetAdminToken("admin")
_, err := rg.Add(api.RepoSpec{Name: "reborn", Author: "dan"})
return err
}
held := func(err error) bool {
return err != nil && (strings.Contains(err.Error(), "still reaches worker group") || strings.Contains(err.Error(), "the name is held"))
}
group := ci.GroupFor("reborn")
if err := addWith(&tokenEngine{tokens: []ci.WorkerToken{{ID: "left", WorkerGroups: []string{group}}}}); !held(err) || !strings.Contains(err.Error(), "left") {
t.Errorf("FAIL: a live token for the group did not hold the name: %v", err)
}
if err := addWith(&tokenEngine{tokens: []ci.WorkerToken{{ID: "left", WorkerGroups: []string{group}, RevokedAt: "2026-10-01T00:00:00Z"}}}); held(err) {
t.Errorf("FAIL: a revoked token held the name: %v", err)
}
if err := addWith(&tokenEngine{tokens: []ci.WorkerToken{{ID: "fleet", TaskTypePrefixes: []string{group}}}}); held(err) {
t.Errorf("FAIL: a fleet token held the name: %v", err)
}
if err := addWith(&tokenEngine{tokens: []ci.WorkerToken{{ID: "other", WorkerGroups: []string{ci.GroupFor("another")}}}}); held(err) {
t.Errorf("FAIL: another group's token held the name: %v", err)
}
if err := addWith(&tokenEngine{listStatus: http.StatusUnauthorized}); !held(err) {
t.Errorf("FAIL: an engine that cannot list its tokens let the name through: %v", err)
}
}