Cover SetCommandAnnotation nil-map initialization and residual schema delivery invariant error branches so aggregate Coverage passes alongside platform gates. Co-authored-by: Cursor <cursoragent@cursor.com>
557 lines
22 KiB
Go
557 lines
22 KiB
Go
// Copyright 2026 Alibaba Group
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
package cli
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/corecmd/contract"
|
|
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/testseam"
|
|
)
|
|
|
|
func TestValidateSchemaDeliveryInvariantsAcceptsOneTypedSource(t *testing.T) {
|
|
fixture := schemaDeliveryTestTool{
|
|
Canonical: "sample.run",
|
|
CLIPath: "sample category run",
|
|
Aliases: []string{"sample legacy execute"},
|
|
}
|
|
source := schemaDeliveryTestRegistry(fixture)
|
|
snapshot := schemaDeliveryTestSnapshot(fixture)
|
|
if err := ValidateSchemaDeliveryInvariants(source, snapshot); err != nil {
|
|
t.Fatalf("ValidateSchemaDeliveryInvariants(): %v", err)
|
|
}
|
|
}
|
|
|
|
func TestValidateSchemaDeliveryInvariantsRejectsConsistentSerializerMutation(t *testing.T) {
|
|
fixture := schemaDeliveryTestTool{Canonical: "sample.run", CLIPath: "sample run"}
|
|
source := schemaDeliveryTestRegistry(fixture)
|
|
snapshot := schemaDeliveryTestSnapshot(fixture)
|
|
|
|
// Mutate both wire projections together. Snapshot-only checks cannot detect
|
|
// this because the summary, full tool, queries, and --all remain mutually
|
|
// consistent; only the typed source proves that the value changed.
|
|
snapshot.Tools[fixture.Canonical]["risk"] = "high"
|
|
mutatedProvenance := schemaDeliveryTestProvenance(map[string]any{"risk": "high"})["risk"]
|
|
fullProvenance := snapshot.Tools[fixture.Canonical]["field_provenance"].(map[string]any)
|
|
encodedProvenance, err := typedJSONValue(mutatedProvenance)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
fullProvenance["risk"] = encodedProvenance
|
|
products := snapshot.Catalog["products"].([]map[string]any)
|
|
summaries := products[0]["tools"].([]map[string]any)
|
|
summaries[0]["risk"] = "high"
|
|
snapshot.SourceHash = schemaCatalogSnapshotHash(snapshot)
|
|
|
|
if err := validateSchemaSnapshotDeliveryInvariants(snapshot); err != nil {
|
|
t.Fatalf("snapshot should remain internally consistent: %v", err)
|
|
}
|
|
err = ValidateSchemaDeliveryInvariants(source, snapshot)
|
|
if err == nil || !strings.Contains(err.Error(), "differs from complete source SchemaRegistry") {
|
|
t.Fatalf("ValidateSchemaDeliveryInvariants() error = %v, want source mutation rejection", err)
|
|
}
|
|
}
|
|
|
|
func TestValidateSchemaDeliveryInvariantsRejectsSelectionProvenanceOmission(t *testing.T) {
|
|
fixture := schemaDeliveryTestTool{
|
|
Canonical: "sample.run",
|
|
CLIPath: "sample run",
|
|
Selection: contract.SelectionSpec{Examples: []string{"dws sample run"}},
|
|
}
|
|
source := schemaDeliveryTestRegistry(fixture)
|
|
snapshot := schemaDeliveryTestSnapshot(fixture)
|
|
|
|
// Examples are leaf-only on the wire, but once selected they participate in
|
|
// precedence. Dropping both the value and provenance must therefore fail at
|
|
// the production snapshot boundary rather than surviving until source diff.
|
|
full := snapshot.Tools[fixture.Canonical]
|
|
delete(full, "examples")
|
|
provenance := full["field_provenance"].(map[string]any)
|
|
delete(provenance, "examples")
|
|
snapshot.SourceHash = schemaCatalogSnapshotHash(snapshot)
|
|
|
|
if err := validateSchemaSnapshotDeliveryInvariants(snapshot); err != nil {
|
|
t.Fatalf("snapshot-only relationship validation should not apply production coverage: %v", err)
|
|
}
|
|
err := ValidateSchemaDeliveryInvariants(source, snapshot)
|
|
if err == nil || !strings.Contains(err.Error(), "differs from complete source SchemaRegistry") {
|
|
t.Fatalf("ValidateSchemaDeliveryInvariants() error = %v, want source selection omission rejection", err)
|
|
}
|
|
}
|
|
|
|
func TestProductionSnapshotRejectsProductSelectionProvenanceOmission(t *testing.T) {
|
|
registry := schemaDeliveryTestRegistry(schemaDeliveryTestTool{Canonical: "sample.run", CLIPath: "sample run"})
|
|
product := ®istry.Products[0]
|
|
product.Selection.AgentSummary = "Sample operations"
|
|
product.Selection.UseWhen = []string{"manage a sample"}
|
|
product.Selection.AvoidWhen = []string{"manage another product"}
|
|
product.FieldProvenance = schemaDeliveryTestProvenance(map[string]any{
|
|
"agent_summary": product.Selection.AgentSummary,
|
|
"use_when": product.Selection.UseWhen,
|
|
"avoid_when": product.Selection.AvoidWhen,
|
|
})
|
|
payload, err := registry.ToSnapshotPayload()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
snapshot := SchemaCatalogSnapshot{Version: SchemaCatalogSnapshotVersion, Catalog: payload.Catalog, Tools: payload.Tools}
|
|
products := snapshot.Catalog["products"].([]map[string]any)
|
|
provenance := products[0]["field_provenance"].(map[string]any)
|
|
delete(provenance, "agent_summary")
|
|
snapshot.SourceHash = schemaCatalogSnapshotHash(snapshot)
|
|
|
|
_, err = loadSchemaCatalogSnapshot(snapshot)
|
|
if err == nil || !strings.Contains(err.Error(), "Schema product sample has no provenance for agent_summary") {
|
|
t.Fatalf("loadSchemaCatalogSnapshot() error = %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSelectionExplicitEmptyListSurvivesFinalDelivery(t *testing.T) {
|
|
snapshot := schemaDeliveryTestSnapshot(schemaDeliveryTestTool{
|
|
Canonical: "sample.run",
|
|
CLIPath: "sample category run",
|
|
Aliases: []string{"sample legacy execute"},
|
|
Selection: contract.SelectionSpec{UseWhen: []string{}},
|
|
})
|
|
|
|
full, ok := snapshot.Tools["sample.run"]["use_when"].([]string)
|
|
if !ok || full == nil || len(full) != 0 {
|
|
t.Fatalf("generated ToolSpec use_when = %#v, want explicit []", snapshot.Tools["sample.run"]["use_when"])
|
|
}
|
|
if err := validateSchemaSnapshotDeliveryInvariants(snapshot); err != nil {
|
|
t.Fatalf("validateSchemaSnapshotDeliveryInvariants(): %v", err)
|
|
}
|
|
|
|
encoded, err := json.Marshal(snapshot)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
loaded, err := decodeSchemaCatalogSnapshot(encoded)
|
|
if err != nil {
|
|
t.Fatalf("decodeSchemaCatalogSnapshot(): %v", err)
|
|
}
|
|
canonical, err := schemaPayloadFromLoadedCatalog(loaded, []string{"sample.run"})
|
|
if err != nil {
|
|
t.Fatalf("canonical query: %v", err)
|
|
}
|
|
alias, err := schemaPayloadFromLoadedCatalog(loaded, []string{"sample legacy execute"})
|
|
if err != nil {
|
|
t.Fatalf("alias query: %v", err)
|
|
}
|
|
for name, payload := range map[string]map[string]any{"canonical": canonical, "alias": alias} {
|
|
value, ok := payload["use_when"].([]string)
|
|
if !ok || value == nil || len(value) != 0 {
|
|
t.Fatalf("%s delivered use_when = %#v, want explicit []", name, payload["use_when"])
|
|
}
|
|
provenance := payload["field_provenance"].(map[string]any)["use_when"].(map[string]any)
|
|
winner, ok := provenance["value"].([]any)
|
|
if !ok || winner == nil || len(winner) != 0 {
|
|
t.Fatalf("%s provenance winner = %#v, want JSON []", name, provenance["value"])
|
|
}
|
|
}
|
|
if problem := schemaAliasViewProblem(canonical, alias, "sample legacy execute"); problem != "" {
|
|
t.Fatalf("alias explicit-empty projection: %s", problem)
|
|
}
|
|
}
|
|
|
|
func TestCompatibleSchemaAliasSeparatorsSurviveFinalDelivery(t *testing.T) {
|
|
snapshot := schemaDeliveryTestSnapshot(schemaDeliveryTestTool{
|
|
Canonical: "sample.run",
|
|
CLIPath: "sample category run",
|
|
Aliases: []string{"sample legacy execute"},
|
|
})
|
|
encoded, err := json.Marshal(snapshot)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
loaded, err := decodeSchemaCatalogSnapshot(encoded)
|
|
if err != nil {
|
|
t.Fatalf("decodeSchemaCatalogSnapshot(): %v", err)
|
|
}
|
|
canonical, err := schemaPayloadFromLoadedCatalog(loaded, []string{"sample.run"})
|
|
if err != nil {
|
|
t.Fatalf("canonical query: %v", err)
|
|
}
|
|
for _, path := range []string{"sample legacy execute", "sample.legacy.execute", "sample/legacy/execute"} {
|
|
alias, aliasErr := schemaPayloadFromLoadedCatalog(loaded, []string{path})
|
|
if aliasErr != nil {
|
|
t.Fatalf("alias query %q: %v", path, aliasErr)
|
|
}
|
|
if problem := schemaAliasViewProblem(canonical, alias, "sample legacy execute"); problem != "" {
|
|
t.Fatalf("alias projection for %q: %s", path, problem)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestValidateSchemaDeliveryInvariantsAllowsOnlyEnvelopeHashes(t *testing.T) {
|
|
snapshot := schemaDeliveryTestSnapshot(schemaDeliveryTestTool{Canonical: "sample.run", CLIPath: "sample run"})
|
|
snapshot.SurfaceHash = "sha256:reviewed-command-registry"
|
|
snapshot.SourceHash = schemaCatalogSnapshotHash(snapshot)
|
|
|
|
if err := validateSchemaSnapshotDeliveryInvariants(snapshot); err != nil {
|
|
t.Fatalf("validateSchemaSnapshotDeliveryInvariants(): %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSchemaOverviewPayloadFromCatalogPreservesListSelectionPriority(t *testing.T) {
|
|
catalog := map[string]any{
|
|
"kind": "schema",
|
|
"source": "runtime-assembled",
|
|
"products": []map[string]any{
|
|
{
|
|
"id": "agent-summary",
|
|
"agent_summary": "reviewed summary",
|
|
"use_when": []string{"lower-priority use_when"},
|
|
"description": "lower-priority description",
|
|
"tools": []map[string]any{{"canonical_path": "agent-summary.run"}},
|
|
},
|
|
{
|
|
"id": "use-when",
|
|
"use_when": []any{"first use", "second use"},
|
|
"description": "lower-priority description",
|
|
"tools": []any{},
|
|
},
|
|
{
|
|
"id": "description",
|
|
"description": "product description",
|
|
"tools": []map[string]any{{}, {}},
|
|
},
|
|
},
|
|
"agent_metadata": map[string]any{"coverage": "reviewed"},
|
|
}
|
|
|
|
got := schemaOverviewPayloadFromCatalog(catalog)
|
|
wantProducts := []map[string]any{
|
|
{"id": "agent-summary", "schema_path": "agent-summary", "tool_count": 1, "agent_summary": "reviewed summary"},
|
|
{"id": "use-when", "schema_path": "use-when", "tool_count": 0, "use_when": []string{"first use"}},
|
|
{"id": "description", "schema_path": "description", "tool_count": 2, "description": "product description"},
|
|
}
|
|
if !schemaJSONEqual(got["products"], wantProducts) {
|
|
t.Fatalf("overview products = %#v, want %#v", got["products"], wantProducts)
|
|
}
|
|
if got["count"] != 3 || got["tool_count"] != 3 || got["source"] != "runtime-assembled" {
|
|
t.Fatalf("overview envelope = %#v", got)
|
|
}
|
|
if !schemaJSONEqual(got["agent_metadata"], catalog["agent_metadata"]) {
|
|
t.Fatalf("overview metadata = %#v", got)
|
|
}
|
|
}
|
|
|
|
func TestProductionSnapshotLoaderRejectsUnknownEnvelopeField(t *testing.T) {
|
|
snapshot := schemaDeliveryTestSnapshot(schemaDeliveryTestTool{Canonical: "sample.run", CLIPath: "sample run"})
|
|
encoded, err := json.Marshal(snapshot)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
encoded = append(encoded[:len(encoded)-1], []byte(`,"unexpected":true}`)...)
|
|
|
|
if _, err := decodeSchemaCatalogSnapshot(encoded); err == nil || !strings.Contains(err.Error(), `unknown field "unexpected"`) {
|
|
t.Fatalf("decodeSchemaCatalogSnapshot() error = %v, want unknown envelope field", err)
|
|
}
|
|
}
|
|
|
|
func TestProductionSnapshotLoaderRejectsTrailingJSON(t *testing.T) {
|
|
snapshot := schemaDeliveryTestSnapshot(schemaDeliveryTestTool{Canonical: "sample.run", CLIPath: "sample run"})
|
|
encoded, err := json.Marshal(snapshot)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
encoded = append(encoded, []byte(` {}`)...)
|
|
|
|
if _, err := decodeSchemaCatalogSnapshot(encoded); err == nil || !strings.Contains(err.Error(), "multiple JSON values") {
|
|
t.Fatalf("decodeSchemaCatalogSnapshot() error = %v, want trailing JSON rejection", err)
|
|
}
|
|
}
|
|
|
|
func TestProductionSnapshotLoaderRejectsUnknownCatalogField(t *testing.T) {
|
|
snapshot := schemaDeliveryTestSnapshot(schemaDeliveryTestTool{Canonical: "sample.run", CLIPath: "sample run"})
|
|
snapshot.Catalog["unexpected"] = true
|
|
snapshot.SourceHash = schemaCatalogSnapshotHash(snapshot)
|
|
|
|
if _, err := loadSchemaCatalogSnapshot(snapshot); err == nil || !strings.Contains(err.Error(), `unknown field "unexpected"`) {
|
|
t.Fatalf("loadSchemaCatalogSnapshot() error = %v, want unknown Catalog field", err)
|
|
}
|
|
}
|
|
|
|
func TestProductionSnapshotLoaderRejectsCatalogTopLevelDrift(t *testing.T) {
|
|
snapshot := schemaDeliveryTestSnapshot(schemaDeliveryTestTool{Canonical: "sample.run", CLIPath: "sample run"})
|
|
snapshot.Catalog["level"] = ""
|
|
snapshot.SourceHash = schemaCatalogSnapshotHash(snapshot)
|
|
|
|
if _, err := loadSchemaCatalogSnapshot(snapshot); err == nil || !strings.Contains(err.Error(), "changed complete Catalog content") {
|
|
t.Fatalf("loadSchemaCatalogSnapshot() error = %v, want complete Catalog drift rejection", err)
|
|
}
|
|
}
|
|
|
|
func TestProductionSnapshotLoaderRejectsAliasViewAsCanonicalTool(t *testing.T) {
|
|
for name, test := range map[string]struct {
|
|
mutate func(map[string]any)
|
|
want string
|
|
}{
|
|
"alternate cli path": {
|
|
mutate: func(tool map[string]any) { tool["cli_path"] = "sample execute" },
|
|
want: "must equal primary_cli_path",
|
|
},
|
|
"alias marker": {
|
|
mutate: func(tool map[string]any) { tool["is_alias"] = true },
|
|
want: "must have is_alias=false",
|
|
},
|
|
} {
|
|
t.Run(name, func(t *testing.T) {
|
|
snapshot := schemaDeliveryTestSnapshot(schemaDeliveryTestTool{
|
|
Canonical: "sample.run",
|
|
CLIPath: "sample run",
|
|
Aliases: []string{"sample execute"},
|
|
})
|
|
test.mutate(snapshot.Tools["sample.run"])
|
|
snapshot.SourceHash = schemaCatalogSnapshotHash(snapshot)
|
|
|
|
_, err := loadSchemaCatalogSnapshot(snapshot)
|
|
if err == nil || !strings.Contains(err.Error(), test.want) {
|
|
t.Fatalf("loadSchemaCatalogSnapshot() error = %v, want %q", err, test.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestValidateSchemaDeliveryInvariantsRejectsCatalogSummaryContentDrift(t *testing.T) {
|
|
snapshot := schemaDeliveryTestSnapshot(
|
|
schemaDeliveryTestTool{Canonical: "sample.one", CLIPath: "sample one"},
|
|
schemaDeliveryTestTool{Canonical: "sample.two", CLIPath: "sample two"},
|
|
)
|
|
products := snapshot.Catalog["products"].([]map[string]any)
|
|
tools := products[0]["tools"].([]map[string]any)
|
|
// Preserve every aggregate count and canonical set. A count gate would pass.
|
|
tools[0]["title"] = "count-preserving summary drift"
|
|
snapshot.SourceHash = schemaCatalogSnapshotHash(snapshot)
|
|
|
|
err := validateSchemaSnapshotDeliveryInvariants(snapshot)
|
|
if err == nil || (!strings.Contains(err.Error(), "changed product/tool summaries") && !strings.Contains(err.Error(), "differs from final ToolSpec summary")) {
|
|
t.Fatalf("ValidateSchemaDeliveryInvariants() error = %v, want content drift", err)
|
|
}
|
|
}
|
|
|
|
func TestValidateSchemaDeliveryInvariantsRejectsCatalogFullToolContentDrift(t *testing.T) {
|
|
snapshot := schemaDeliveryTestSnapshot(schemaDeliveryTestTool{Canonical: "sample.run", CLIPath: "sample run"})
|
|
// Keep the summary, tool count and canonical set unchanged while changing the
|
|
// full delivery contract.
|
|
snapshot.Tools["sample.run"]["title"] = "full contract drift"
|
|
snapshot.SourceHash = schemaCatalogSnapshotHash(snapshot)
|
|
|
|
err := validateSchemaSnapshotDeliveryInvariants(snapshot)
|
|
if err == nil || (!strings.Contains(err.Error(), "changed product/tool summaries") && !strings.Contains(err.Error(), "differs from final ToolSpec")) {
|
|
t.Fatalf("ValidateSchemaDeliveryInvariants() error = %v, want full tool drift", err)
|
|
}
|
|
}
|
|
|
|
func TestSchemaAliasViewProblemAllowsOnlyPathAndAliasMarker(t *testing.T) {
|
|
canonical := map[string]any{
|
|
"canonical_path": "sample.run",
|
|
"cli_path": "sample run",
|
|
"is_alias": false,
|
|
"title": "Run sample",
|
|
"parameters": map[string]any{
|
|
"name": map[string]any{"type": "string", "required": true},
|
|
},
|
|
}
|
|
alias := map[string]any{
|
|
"canonical_path": "sample.run",
|
|
"cli_path": "sample execute",
|
|
"is_alias": true,
|
|
"title": "Run sample",
|
|
"parameters": map[string]any{
|
|
"name": map[string]any{"type": "string", "required": true},
|
|
},
|
|
}
|
|
if problem := schemaAliasViewProblem(canonical, alias, "sample execute"); problem != "" {
|
|
t.Fatalf("valid alias projection: %s", problem)
|
|
}
|
|
|
|
alias["title"] = "alias-specific contract"
|
|
if problem := schemaAliasViewProblem(canonical, alias, "sample execute"); !strings.Contains(problem, "other than cli_path/is_alias") {
|
|
t.Fatalf("semantic alias drift problem = %q", problem)
|
|
}
|
|
alias["title"] = canonical["title"]
|
|
alias["is_alias"] = false
|
|
if problem := schemaAliasViewProblem(canonical, alias, "sample execute"); !strings.Contains(problem, "is_alias=true") {
|
|
t.Fatalf("alias marker problem = %q", problem)
|
|
}
|
|
}
|
|
|
|
func TestSchemaDeliveryToolsByCanonicalRejectsDuplicateWithoutRelyingOnCount(t *testing.T) {
|
|
payload := map[string]any{
|
|
"products": []map[string]any{{
|
|
"tools": []map[string]any{
|
|
{"canonical_path": "sample.same", "title": "first"},
|
|
{"canonical_path": "sample.same", "title": "second"},
|
|
},
|
|
}},
|
|
}
|
|
tools, problems := schemaDeliveryToolsByCanonical(payload, "test view")
|
|
if len(tools) != 1 || len(problems) != 1 || !strings.Contains(problems[0], "duplicate tool sample.same") {
|
|
t.Fatalf("tools=%v problems=%v", tools, problems)
|
|
}
|
|
}
|
|
|
|
func TestOverallCoverageGapDeliveryInvariantResidualBranches(t *testing.T) {
|
|
if err := ValidateSchemaDeliveryInvariants(SchemaRegistry{}, SchemaCatalogSnapshot{
|
|
Version: SchemaCatalogSnapshotVersion,
|
|
Catalog: map[string]any{"bad": func() {}},
|
|
}); err == nil || !strings.Contains(err.Error(), "encode final Schema Catalog") {
|
|
t.Fatalf("unmarshalable snapshot error = %v", err)
|
|
}
|
|
|
|
fixture := schemaDeliveryTestTool{Canonical: "sample.run", CLIPath: "sample run"}
|
|
source := schemaDeliveryTestRegistry(fixture)
|
|
snapshot := schemaDeliveryTestSnapshot(fixture)
|
|
t.Run("source snapshot render failure", func(t *testing.T) {
|
|
testseam.Swap(t, &snapshotToolSummary, func(ToolSpec) (map[string]any, error) {
|
|
return nil, fmt.Errorf("summary failed")
|
|
})
|
|
if problems := schemaSourceSnapshotInvariantErrors(source, snapshot); len(problems) == 0 || !strings.Contains(problems[0], "summary failed") {
|
|
t.Fatalf("ToSnapshotPayload error problems = %v", problems)
|
|
}
|
|
})
|
|
|
|
badSnapshot := SchemaCatalogSnapshot{
|
|
Version: SchemaCatalogSnapshotVersion,
|
|
Catalog: map[string]any{"bad": func() {}},
|
|
}
|
|
if err := validateSchemaSnapshotDeliveryInvariants(badSnapshot); err == nil || !strings.Contains(err.Error(), "encode final Schema Catalog") {
|
|
t.Fatalf("validate snapshot marshal error = %v", err)
|
|
}
|
|
|
|
if problems := schemaSourceDeliveryInvariantErrors(
|
|
SchemaRegistry{Products: []ProductSpec{{ID: ""}}},
|
|
schemaDeliveryTestRegistry(fixture),
|
|
); len(problems) == 0 || !strings.Contains(problems[0], "empty") {
|
|
t.Fatalf("source Index error problems = %v", problems)
|
|
}
|
|
if problems := schemaSourceDeliveryInvariantErrors(
|
|
source,
|
|
SchemaRegistry{Products: []ProductSpec{{ID: ""}}},
|
|
); len(problems) == 0 || !strings.Contains(problems[0], "empty") {
|
|
t.Fatalf("delivered Index error problems = %v", problems)
|
|
}
|
|
|
|
if path, _, _ := firstSchemaJSONDifference(map[string]any{"bad": func() {}}, map[string]any{"bad": "ok"}); path == "" {
|
|
t.Fatal("firstSchemaJSONDifference must report encode-error path")
|
|
}
|
|
if got := compactSchemaDiagnosticValue(func() {}); got == "" {
|
|
t.Fatal("compactSchemaDiagnosticValue must stringify unmarshalable values")
|
|
}
|
|
|
|
registry := schemaDeliveryTestRegistry(fixture)
|
|
index, err := registry.Index()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
payload, err := registry.ToSnapshotPayload()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
loadedSnapshot := SchemaCatalogSnapshot{
|
|
Version: SchemaCatalogSnapshotVersion,
|
|
Catalog: payload.Catalog,
|
|
Tools: payload.Tools,
|
|
}
|
|
loadedSnapshot.SourceHash = schemaCatalogSnapshotHash(loadedSnapshot)
|
|
copyLoaded := func() loadedSchemaCatalog {
|
|
toolsCopy := make(map[string]map[string]any, len(loadedSnapshot.Tools))
|
|
for key, value := range loadedSnapshot.Tools {
|
|
toolCopy := make(map[string]any, len(value))
|
|
for field, fieldValue := range value {
|
|
toolCopy[field] = fieldValue
|
|
}
|
|
toolsCopy[key] = toolCopy
|
|
}
|
|
catalogCopy := make(map[string]any, len(loadedSnapshot.Catalog))
|
|
for key, value := range loadedSnapshot.Catalog {
|
|
catalogCopy[key] = value
|
|
}
|
|
snapshotCopy := loadedSnapshot
|
|
snapshotCopy.Tools = toolsCopy
|
|
snapshotCopy.Catalog = catalogCopy
|
|
return loadedSchemaCatalog{Registry: registry, Index: index, Snapshot: snapshotCopy}
|
|
}
|
|
|
|
missingFullLoaded := copyLoaded()
|
|
delete(missingFullLoaded.Snapshot.Tools, fixture.Canonical)
|
|
if problems := schemaDeliveryInvariantErrors(missingFullLoaded); len(problems) == 0 || !strings.Contains(strings.Join(problems, "; "), "missing") {
|
|
t.Fatalf("missing stored full problems = %v", problems)
|
|
}
|
|
|
|
t.Run("missing --all tool", func(t *testing.T) {
|
|
missingAllLoaded := copyLoaded()
|
|
testseam.Swap(t, &deliveryRegistryPayload, func(SchemaRegistry) (map[string]any, error) {
|
|
return map[string]any{"products": []any{map[string]any{"tools": []any{}}}}, nil
|
|
})
|
|
problems := schemaDeliveryInvariantErrors(missingAllLoaded)
|
|
joined := strings.Join(problems, "; ")
|
|
if len(problems) == 0 || !strings.Contains(joined, "Schema --all is missing") {
|
|
t.Fatalf("missing --all tool problems = %v", problems)
|
|
}
|
|
})
|
|
|
|
t.Run("drifted --all tool", func(t *testing.T) {
|
|
driftAllLoaded := copyLoaded()
|
|
testseam.Swap(t, &deliveryRegistryPayload, func(reg SchemaRegistry) (map[string]any, error) {
|
|
all, allErr := reg.ToPayload()
|
|
if allErr != nil {
|
|
return nil, allErr
|
|
}
|
|
products := all["products"].([]map[string]any)
|
|
tools := products[0]["tools"].([]map[string]any)
|
|
tools[0] = map[string]any{"canonical_path": fixture.Canonical, "title": "drift"}
|
|
return all, nil
|
|
})
|
|
problems := schemaDeliveryInvariantErrors(driftAllLoaded)
|
|
if len(problems) == 0 || !strings.Contains(strings.Join(problems, "; "), "Schema --all tool") {
|
|
t.Fatalf("--all drift problems = %v", problems)
|
|
}
|
|
})
|
|
|
|
missingSummaryLoaded := copyLoaded()
|
|
missingSummaryLoaded.Snapshot.Catalog = map[string]any{"products": []any{map[string]any{"id": "sample", "tools": []any{}}}}
|
|
if problems := schemaDeliveryInvariantErrors(missingSummaryLoaded); len(problems) == 0 || !strings.Contains(strings.Join(problems, "; "), "Catalog summary is missing") {
|
|
t.Fatalf("missing catalog summary problems = %v", problems)
|
|
}
|
|
|
|
driftSummaryLoaded := copyLoaded()
|
|
driftProducts := driftSummaryLoaded.Snapshot.Catalog["products"].([]map[string]any)
|
|
driftSummaries := driftProducts[0]["tools"].([]map[string]any)
|
|
driftSummaries[0] = map[string]any{"canonical_path": fixture.Canonical, "title": "summary drift"}
|
|
if problems := schemaDeliveryInvariantErrors(driftSummaryLoaded); len(problems) == 0 || !strings.Contains(strings.Join(problems, "; "), "summary") {
|
|
t.Fatalf("catalog summary drift problems = %v", problems)
|
|
}
|
|
|
|
blankAliasFixture := schemaDeliveryTestTool{
|
|
Canonical: fixture.Canonical,
|
|
CLIPath: fixture.CLIPath,
|
|
Aliases: []string{" "},
|
|
}
|
|
blankRegistry := schemaDeliveryTestRegistry(blankAliasFixture)
|
|
blankIndex, err := blankRegistry.Index()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
blankPayload, err := blankRegistry.ToSnapshotPayload()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
blankSnapshot := SchemaCatalogSnapshot{
|
|
Version: SchemaCatalogSnapshotVersion,
|
|
Catalog: blankPayload.Catalog,
|
|
Tools: blankPayload.Tools,
|
|
}
|
|
blankSnapshot.SourceHash = schemaCatalogSnapshotHash(blankSnapshot)
|
|
blankLoaded := loadedSchemaCatalog{Registry: blankRegistry, Index: blankIndex, Snapshot: blankSnapshot}
|
|
if problems := schemaDeliveryInvariantErrors(blankLoaded); len(problems) != 0 {
|
|
t.Fatalf("blank alias must be skipped cleanly, problems = %v", problems)
|
|
}
|
|
}
|