Artifact b1d4e8b120a5ee22516c3f0e871dd030045558f82f68ef1efdfe8de5152b4937:
- File
internal/ops/ops_test.go
— part of check-in
[cfd3f85ff3]
at
2026-08-14 22:29:35
on branch trunk
— OpenAPI reflector over the registry (dagnats 0.0.13)
quarry spec subcommand, RegisterAll with meta.version, required Op.Doc, validate rules feed schemas; make spec-lint via vacuum. (user: dmestas, size: 3842) [annotate] [blame] [check-ins using]
package ops import ( "context" "strings" "testing" ) type echoIn struct { Repo string `json:"repo"` } type echoOut struct { Repo string `json:"repo"` Count int `json:"count"` } func echoOp(name, route string) Op[echoIn, echoOut] { return Op[echoIn, echoOut]{ Name: name, Doc: "echo test op", Kind: Query, Auth: Anonymous, Route: route, Run: func(_ context.Context, in echoIn) (echoOut, error) { return echoOut{Repo: in.Repo, Count: 1}, nil }, } } func TestRegisterAndInvoke(t *testing.T) { r := NewRegistry() if err := Register(r, echoOp("timeline.list", "GET /api/v1/r/{repo}/timeline")); err != nil { t.Fatal(err) } got, err := r.Invoke(context.Background(), "timeline.list", echoIn{Repo: "sqlite"}) if err != nil { t.Fatal(err) } out, ok := got.(echoOut) if !ok { t.Fatalf("got %T, want echoOut", got) } if out.Repo != "sqlite" || out.Count != 1 { t.Fatalf("got %+v", out) } } func TestInvokeWrongInputType(t *testing.T) { r := NewRegistry() if err := Register(r, echoOp("timeline.list", "GET /timeline")); err != nil { t.Fatal(err) } if _, err := r.Invoke(context.Background(), "timeline.list", struct{ X int }{}); err == nil { t.Fatal("want type-mismatch error, got nil") } } func TestInvokeUnknownOp(t *testing.T) { r := NewRegistry() if _, err := r.Invoke(context.Background(), "nope", echoIn{}); err == nil { t.Fatal("want unknown-op error, got nil") } } func TestDuplicateNameRejected(t *testing.T) { r := NewRegistry() if err := Register(r, echoOp("dup", "GET /a")); err != nil { t.Fatal(err) } err := Register(r, echoOp("dup", "GET /b")) if err == nil || !strings.Contains(err.Error(), "duplicate op name") { t.Fatalf("want duplicate-name error, got %v", err) } } func TestDuplicateRouteRejected(t *testing.T) { r := NewRegistry() if err := Register(r, echoOp("a", "GET /same")); err != nil { t.Fatal(err) } err := Register(r, echoOp("b", "GET /same")) if err == nil || !strings.Contains(err.Error(), "already registered") { t.Fatalf("want duplicate-route error, got %v", err) } } func TestKindMethodMismatchRejected(t *testing.T) { r := NewRegistry() q := echoOp("q", "POST /q") // query must be GET if err := Register(r, q); err == nil { t.Fatal("want query/POST mismatch error, got nil") } c := echoOp("c", "GET /c") c.Kind = Command // command must be POST if err := Register(r, c); err == nil { t.Fatal("want command/GET mismatch error, got nil") } } func TestBadRoutesRejected(t *testing.T) { for _, route := range []string{"", "GET", "GET relative/path", "DELETE /x", "/x"} { r := NewRegistry() if err := Register(r, echoOp("x", route)); err == nil { t.Fatalf("route %q: want error, got nil", route) } } } func TestNonStructInRejected(t *testing.T) { r := NewRegistry() err := Register(r, Op[string, echoOut]{ Name: "bad", Doc: "d", Kind: Query, Route: "GET /bad", Run: func(_ context.Context, _ string) (echoOut, error) { return echoOut{}, nil }, }) if err == nil || !strings.Contains(err.Error(), "In must be a struct") { t.Fatalf("want non-struct error, got %v", err) } } func TestNilRunRejected(t *testing.T) { r := NewRegistry() err := Register(r, Op[echoIn, echoOut]{Name: "nilrun", Doc: "d", Kind: Query, Route: "GET /n"}) if err == nil || !strings.Contains(err.Error(), "nil Run") { t.Fatalf("want nil-Run error, got %v", err) } } func TestAllSortedByName(t *testing.T) { r := NewRegistry() for _, n := range []string{"c.op", "a.op", "b.op"} { if err := Register(r, echoOp(n, "GET /"+n)); err != nil { t.Fatal(err) } } all := r.All() if len(all) != 3 || all[0].Name != "a.op" || all[1].Name != "b.op" || all[2].Name != "c.op" { names := make([]string, len(all)) for i, d := range all { names[i] = d.Name } t.Fatalf("got %v", names) } }