package spec import ( "context" "os" "strings" "testing" "time" commonv1 "github.com/johnandersen777/socialweb-computer-kcp/api/common/v1alpha1" "github.com/johnandersen777/socialweb-computer-kcp/internal/policyengine/policytest" "github.com/johnandersen777/socialweb-computer-kcp/internal/policyengine/runs" ) func TestMain(m *testing.M) { path, from, err := policytest.DenoPath() if err != nil { os.Stderr.WriteString("policy spec: " + err.Error() + "\n") os.Exit(1) } os.Stderr.WriteString("policy spec: deno " + path + " (" + from + ")\n") os.Exit(m.Run()) } type lane string const ( scope lane = runs.ModeScope full lane = runs.ModeFull ) type side string const ( bidderSide side = "bidder" requesterSide side = "requester" ) type decision struct { verdict runs.Decision runs []*policytest.Run } func (d decision) mustRun(t *testing.T, workflow string) *policytest.Run { t.Helper() if len(d.runs) == 0 { t.Fatalf("no policy run executed for %s; verdict %+v", workflow, d.verdict) } for _, run := range d.runs { if run.Workflow == workflow || run.Spec.WorkflowRef == workflow { if run.Status.Phase == "" || run.Status.CompletionTime == nil { t.Fatalf("the policy run %s for %s did not finish: %+v", run.Name, workflow, run.Status) } return run } } names := []string{} for _, run := range d.runs { names = append(names, run.Workflow) } t.Fatalf("no policy run of %s executed; runs: %v", workflow, names) return nil } func (d decision) mustAllow(t *testing.T) { t.Helper() if !d.verdict.Allow { t.Fatalf("want allow, got deny: %s %v", d.verdict.Reason, d.verdict.Violations) } } func (d decision) mustDeny(t *testing.T, reason string) { t.Helper() if d.verdict.Allow { t.Fatalf("want deny (%s), got allow from run %s", reason, d.verdict.Run) } text := d.verdict.Reason + " " + strings.Join(d.verdict.Violations, " ") if strings.TrimSpace(text) == "" { t.Fatalf("a deny carries no reason") } if reason != "" && !strings.Contains(text, reason) { t.Fatalf("want a deny with %q, got %q", reason, text) } } func (d decision) mustDenyBecause(t *testing.T, cause string) { t.Helper() d.mustDeny(t, "") text := d.verdict.Reason + " " + strings.Join(d.verdict.Violations, " ") for _, run := range d.runs { for _, raw := range run.Status.Annotations { text += " " + string(raw) } for _, condition := range run.Status.Conditions { text += " " + condition.Message } text += " " + run.Status.ConsoleOutput } if !strings.Contains(text, cause) { t.Fatalf("the deny does not carry the cause %q: %s", cause, text) } } func actionRan(t *testing.T, run *policytest.Run, policyName string, allow bool) policytest.ActionVerdict { t.Helper() for _, verdict := range run.Actions() { if verdict.Policy == policyName { if verdict.Allow != allow { t.Fatalf("the %s action answered allow=%t, want %t", policyName, verdict.Allow, allow) } return verdict } } t.Fatalf("the %s action did not run in %s; console:\n%s", policyName, run.Name, run.Status.ConsoleOutput) return policytest.ActionVerdict{} } func evaluate(t *testing.T, h *policytest.Harness, workflow string, perspective side, mode lane, self, counterparty string, rfp *policytest.Ref) decision { t.Helper() input := runs.Input{Perspective: string(perspective), Mode: string(mode), SelfDid: self, CounterpartyDid: counterparty} if mode == full { input.SubjectDid = counterparty input.RootRequesterDid = counterparty if perspective == requesterSide { input.RootRequesterDid = self } } if rfp != nil { input.RFP = &commonv1.StrongRef{URI: rfp.URI, CID: rfp.CID} } return run(t, h, string(perspective), runs.Request{WorkflowRef: workflow, Input: input}) } func run(t *testing.T, h *policytest.Harness, role string, req runs.Request) decision { t.Helper() mark := h.Runner.Mark() ctx, cancel := context.WithTimeout(context.Background(), 90*time.Second) defer cancel() verdict := h.Client(role).Run(ctx, req) return decision{verdict: verdict, runs: h.Runner.Since(mark)} }