package buildstep import ( "reflect" "strings" "testing" ) // A build's fetch is handed the paths of a module that names them (novox/hq ADR 0499 clause 4): the builder fills them // from the indexer's kept inputs and the build module reads them from the call, never from the manifest (ADR 0495 // clause 1). The request survives the trip through a tool call's arguments. func TestAFetchRequestCarriesTheNamedPathsThroughTheToolCall(t *testing.T) { // And the versions of the mesh packages to build against (novox/hq ADR 0573 ยง2; issue 1585 S4). req := FetchRequest{Repository: "novox/mesh-sdk", Commit: strings.Repeat("a", 40), Ref: "refs/pull/7/head", Dir: ".", Paths: []string{"package.json", "src"}, Packages: map[string]string{"git.novox.be/novox/mesh-sdk/go": strings.Repeat("d", 40)}} args := req.Args() // A tool call's arguments arrive as JSON: lists of any, objects of any. args["paths"] = []any{"package.json", "src"} if p, ok := args["packages"].(map[string]any); !ok || p["git.novox.be/novox/mesh-sdk/go"] != strings.Repeat("d", 40) { t.Fatalf("the packages are not in the call's arguments: %v", args["packages"]) } got, err := ParseFetchRequest(args) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(got, req) { t.Fatalf("got %+v, want %+v", got, req) } plain, err := ParseFetchRequest(map[string]any{"repository": "novox/x", "commit": strings.Repeat("b", 40), "base": strings.Repeat("c", 40), "beside": []any{}}) if err != nil || plain.Paths != nil || plain.Base != strings.Repeat("c", 40) { t.Fatalf("a request without paths: %+v, %v", plain, err) } ok := map[string]any{"repository": "novox/x", "commit": strings.Repeat("b", 40)} for _, c := range []struct { set map[string]any says string }{ {map[string]any{"repository": "novox"}, "is not a repository"}, {map[string]any{"repository": "novox/../x"}, "is not a repository"}, {map[string]any{"commit": "abc"}, "is not a full commit"}, {map[string]any{"base": "abc"}, "is not a trunk commit"}, {map[string]any{"paths": []any{"src"}}, "names no module directory"}, {map[string]any{"dir": "modules/a", "paths": []any{"../b"}}, "leaves the module's directory"}, {map[string]any{"dir": "../a", "paths": []any{"src"}}, "leaves the repository"}, {map[string]any{"dir": "modules/a", "paths": []any{3}}, "paths is a list of strings"}, {map[string]any{"dir": "modules/a"}, "names a module directory and no path"}, {map[string]any{"packages": map[string]any{"git.novox.be/novox/mesh-sdk/go": "v0.1.7"}}, "no full commit"}, {map[string]any{"packages": map[string]any{"a b": strings.Repeat("d", 40)}}, "no module path"}, {map[string]any{"packages": []any{"x"}}, "packages is an object"}, } { args := map[string]any{} for k, v := range ok { args[k] = v } for k, v := range c.set { args[k] = v } if _, err := ParseFetchRequest(args); err == nil || !strings.Contains(err.Error(), c.says) { t.Errorf("%v: %v, wanted a refusal saying %q", c.set, err, c.says) } } }