//go:build integration package inventory import ( "errors" "strings" "testing" "time" "github.com/novox/mesh-controller/internal/chain" ) // **A plan's id is a value, never a query** (novox/hq issue 561): the id reaches PlanByID from a caller of the // controller's plans verb, so an id holding a quote is read as a plain id — no error from the store, and no // other plan answered for it. On the bus an id is a key, and one the bus takes no spelling of is refused to be kept. func TestAPlanIdHoldingAQuoteIsReadAsAPlainId(t *testing.T) { inv := ForTest(t) ctx := t.Context() p := Plan{ID: "plan-561", Repository: "novox/mesh-controller", Commit: "abc", Created: time.Now().UTC(), State: PlanBuilding, Tiers: [][]string{{"a"}}, Modules: map[string]*PlanModule{"a": {}}} if err := inv.SavePlan(ctx, &p); err != nil { t.Fatal(err) } for _, id := range []string{ "x' or '1'='1", // every plan, when pasted into the query "plan-561' or id like '%", // the plan above, by a pattern "it's", // a quote alone: a syntax error, when pasted } { got, err := inv.PlanByID(ctx, id) if err == nil { t.Fatalf("PlanByID(%q) answered %s, a plan of another id", id, got.ID) } if want := "no plan " + id; err.Error() != want { t.Fatalf("PlanByID(%q) failed with %q, not as a plain id no plan has (%q)", id, err, want) } } // A plan whose id holds a quote cannot be a key of the bus: refused by name, never rewritten into another id. quoted := p quoted.ID, quoted.Revision = "plan-'561'", 0 if err := inv.SavePlan(ctx, "ed); !errors.Is(err, chain.ErrBadKey) { t.Fatalf("a plan with a quote in its id was kept, or refused for another reason: %v", err) } if recent, err := inv.RecentPlans(ctx, 1); err != nil || len(recent) != 1 || !strings.HasPrefix(recent[0].ID, "plan-") { t.Fatalf("RecentPlans with a parameter: %v %+v", err, recent) } }