Files
dingtalk-workspace-cli/internal/cli/schema_small_coverage_test.go
T

507 lines
21 KiB
Go

// Copyright 2026 Alibaba Group
// Licensed under the Apache License, Version 2.0 (the "License");
package cli
import (
"bytes"
"encoding/json"
"errors"
"io/fs"
"strings"
"sync"
"testing"
"testing/fstest"
"github.com/spf13/cobra"
)
func TestSchemaCommandRemainingBranches(t *testing.T) {
for _, tc := range []struct {
name string
args []string
wantErr string
}{
{"cli path conflict", []string{"sample", "--cli-path", "sample get"}, "mutually exclusive"},
{"list alias", []string{"list"}, ""},
{"all path conflict", []string{"sample", "--all"}, "--all cannot"},
{"cli path", []string{"--cli-path", "aisearch person"}, ""},
{"all", []string{"--all"}, ""},
{"overview", nil, ""},
{"missing", []string{"definitely-missing-schema-path"}, ""},
{"compact", []string{"--compact"}, ""},
} {
t.Run(tc.name, func(t *testing.T) {
cmd := NewSchemaCommand(nil)
var output bytes.Buffer
cmd.SetOut(&output)
cmd.SetErr(&output)
cmd.SetArgs(tc.args)
err := cmd.Execute()
if tc.name == "missing" {
if err == nil {
t.Fatal("missing schema path succeeded")
}
return
}
if tc.wantErr != "" {
if err == nil || !strings.Contains(err.Error(), tc.wantErr) {
t.Fatalf("error = %v, want %q", err, tc.wantErr)
}
return
}
if err != nil || output.Len() == 0 {
t.Fatalf("schema output length = %d, error = %v", output.Len(), err)
}
})
}
}
func TestSchemaCommandCatalogFailure(t *testing.T) {
original := schemaCommandCatalogError
t.Cleanup(func() { schemaCommandCatalogError = original })
schemaCommandCatalogError = func() error { return errors.New("catalog failed") }
cmd := NewSchemaCommand(nil)
cmd.SetArgs(nil)
if err := cmd.Execute(); err == nil || !strings.Contains(err.Error(), "catalog failed") {
t.Fatalf("catalog failure error = %v", err)
}
}
func TestSchemaSupportParameterAndIdentityEdges(t *testing.T) {
if hasRuntimeSchemaCommand(nil) {
t.Fatal("nil command has runtime schema")
}
root := &cobra.Command{Use: "root"}
help := &cobra.Command{Use: "help", Run: func(*cobra.Command, []string) {}}
hidden := &cobra.Command{Use: "hidden", Hidden: true}
leaf := &cobra.Command{Use: "leaf", Run: func(*cobra.Command, []string) {}}
AttachRuntimeSchema(leaf, "sample", "get", "fixture")
hidden.AddCommand(leaf)
root.AddCommand(help, hidden)
var visited []*cobra.Command
walkLeafCommands(root, func(command *cobra.Command) { visited = append(visited, command) })
if len(visited) != 1 || visited[0] != leaf {
t.Fatalf("visited leaves = %#v", visited)
}
original := runtimeSchemaParameterMetadataByCanonical
t.Cleanup(func() { runtimeSchemaParameterMetadataByCanonical = original })
runtimeSchemaParameterMetadataByCanonical = map[string]RuntimeSchemaParameterMetadata{}
applyRuntimeSchemaParameterMetadata(leaf, "missing")
provenance := commandRegistryIdentityProvenance(BoundCommandSpec{
CommandSpec: CommandSpec{CanonicalPath: "sample.get", PrimaryCLIPath: "sample get", Source: "reviewed_manual_hint"},
AliasCommands: []BoundAlias{{Path: "sample alias", Command: nil}},
})
if provenance.Precedence != "reviewed_manual" || len(provenance.Candidates) != 1 {
t.Fatalf("identity provenance = %#v", provenance)
}
}
func TestAgentMetadataRemainingPureEdges(t *testing.T) {
provenance := resolvedFieldProvenance(make(chan int), " source ", " ref ", " precedence ", " resolution ", " reason ")
if string(provenance.Value) != "null" || len(provenance.Candidates) != 1 {
t.Fatalf("fallback provenance = %#v", provenance)
}
}
func TestEmbeddedAgentMetadataLoaderEdges(t *testing.T) {
for _, source := range []fs.FS{
fstest.MapFS{},
fstest.MapFS{"schema_agent_metadata/index.json": {Data: []byte("{")}},
fstest.MapFS{"schema_agent_metadata/index.json": {Data: []byte(`{"domains":[" "]}`)}},
fstest.MapFS{"schema_agent_metadata/index.json": {Data: []byte(`{"domains":["bad/path"]}`)}},
fstest.MapFS{"schema_agent_metadata/index.json": {Data: []byte(`{"domains":["sample"]}`)}},
fstest.MapFS{
"schema_agent_metadata/index.json": {Data: []byte(`{"domains":["sample"]}`)},
"schema_agent_metadata/sample.json": {Data: []byte("{")},
},
fstest.MapFS{
"schema_agent_metadata/index.json": {Data: []byte(`{"domains":["sample"]}`)},
"schema_agent_metadata/sample.json": {Data: []byte(`{"product_id":"other"}`)},
},
} {
metadata := loadEmbeddedAgentMetadataFrom(source)
if metadata.Products == nil || metadata.Tools == nil || len(metadata.Tools) != 0 {
t.Fatalf("empty fallback metadata = %#v", metadata)
}
}
valid := fstest.MapFS{
"schema_agent_metadata/index.json": {Data: []byte(`{"domains":["sample"]}`)},
"schema_agent_metadata/sample.json": {Data: []byte(`{"product_id":"sample","tools":{"sample.get":{}}}`)},
}
metadata := loadEmbeddedAgentMetadataFrom(valid)
if metadata.Products == nil || len(metadata.Tools) != 1 {
t.Fatalf("loaded agent metadata = %#v", metadata)
}
}
func TestManualAgentSelectionRemainingEdges(t *testing.T) {
baseBound := manualAgentSelectionBoundFixture()
baseHints := manualAgentHintSetFixture()
for _, tc := range []struct {
name string
mutate func(*BoundCommandRegistry, *ManualAgentHintSet)
}{
{"invalid bound canonical", func(bound *BoundCommandRegistry, hints *ManualAgentHintSet) {
item := bound.Commands[0]
item.CanonicalPath = "invalid"
bound.Commands[0] = item
}},
{"missing by canonical", func(bound *BoundCommandRegistry, hints *ManualAgentHintSet) {
delete(bound.ByCanonical, "sample.search_items")
}},
{"missing use when", func(_ *BoundCommandRegistry, hints *ManualAgentHintSet) {
item := hints.Tools["sample.search_items"]
item.UseWhen = nil
hints.Tools["sample.search_items"] = item
}},
{"missing avoid when", func(_ *BoundCommandRegistry, hints *ManualAgentHintSet) {
item := hints.Tools["sample.search_items"]
item.AvoidWhen = nil
hints.Tools["sample.search_items"] = item
}},
{"blank use when", func(_ *BoundCommandRegistry, hints *ManualAgentHintSet) {
item := hints.Tools["sample.search_items"]
item.UseWhen = []string{" "}
hints.Tools["sample.search_items"] = item
}},
{"blank avoid when", func(_ *BoundCommandRegistry, hints *ManualAgentHintSet) {
item := hints.Tools["sample.search_items"]
item.AvoidWhen = []string{" "}
hints.Tools["sample.search_items"] = item
}},
} {
t.Run(tc.name, func(t *testing.T) {
bound, hints := baseBound, baseHints
bound.Commands = append([]BoundCommandSpec(nil), baseBound.Commands...)
bound.ByCanonical = cloneBoundByCanonical(baseBound.ByCanonical)
bound.ByCLIPath = cloneBoundByCanonical(baseBound.ByCLIPath)
hints.Tools = cloneManualAgentTools(baseHints.Tools)
tc.mutate(&bound, &hints)
if _, _, err := BuildManualAgentSelectionEvalFixture(bound, hints); err == nil {
t.Fatal("invalid selection fixture succeeded")
}
})
}
canonical := "sample.search_items"
boundItem := baseBound.ByCanonical[canonical]
for _, tc := range []struct {
name string
mutate func(*BoundCommandRegistry, *BoundCommandSpec)
}{
{"mismatch", func(_ *BoundCommandRegistry, item *BoundCommandSpec) { item.CanonicalPath = "other.tool" }},
{"nil command", func(_ *BoundCommandRegistry, item *BoundCommandSpec) { item.PrimaryCommand = nil }},
{"non runnable", func(_ *BoundCommandRegistry, item *BoundCommandSpec) {
item.PrimaryCommand = &cobra.Command{Use: "leaf"}
}},
{"empty path", func(_ *BoundCommandRegistry, item *BoundCommandSpec) { item.PrimaryCLIPath = " " }},
{"path mismatch", func(bound *BoundCommandRegistry, _ *BoundCommandSpec) { delete(bound.ByCLIPath, "sample item search") }},
} {
t.Run("binding "+tc.name, func(t *testing.T) {
bound := baseBound
bound.ByCLIPath = cloneBoundByCanonical(baseBound.ByCLIPath)
item := boundItem
tc.mutate(&bound, &item)
if err := validateManualAgentSelectionBinding(bound, canonical, item); err == nil {
t.Fatal("invalid binding succeeded")
}
})
}
originalMarshal := marshalManualAgentSelectionFixture
t.Cleanup(func() { marshalManualAgentSelectionFixture = originalMarshal })
marshalManualAgentSelectionFixture = func(any) ([]byte, error) { return nil, errors.New("marshal failed") }
if _, err := manualAgentSelectionFixtureDigest(ManualAgentSelectionFixture{}); err == nil {
t.Fatal("selection digest marshal failure succeeded")
}
if _, _, err := BuildManualAgentSelectionEvalFixture(baseBound, baseHints); err == nil {
t.Fatal("selection fixture ignored digest failure")
}
marshalManualAgentSelectionFixture = json.Marshal
}
func cloneBoundByCanonical(source map[string]BoundCommandSpec) map[string]BoundCommandSpec {
out := make(map[string]BoundCommandSpec, len(source))
for key, value := range source {
out[key] = value
}
return out
}
func cloneManualAgentTools(source map[string]ManualAgentToolHint) map[string]ManualAgentToolHint {
out := make(map[string]ManualAgentToolHint, len(source))
for key, value := range source {
out[key] = value
}
return out
}
func TestHintDirectoryLoaderRemainingEdges(t *testing.T) {
directoryJSON := fstest.MapFS{"bad.json": {Mode: fs.ModeDir}}
invalidJSON := fstest.MapFS{"bad.json": {Data: []byte("{")}}
if _, err := loadParameterCommandsFromMetadata(fstest.MapFS{}, "["); err == nil {
t.Fatal("invalid metadata glob succeeded")
}
if _, err := loadParameterCommandsFromMetadata(directoryJSON, "*.json"); err == nil {
t.Fatal("metadata directory read succeeded")
}
if _, err := loadParameterCommandsFromMetadata(invalidJSON, "*.json"); err == nil {
t.Fatal("invalid metadata JSON succeeded")
}
missingPath := fstest.MapFS{"metadata.json": {Data: []byte(`{"version":1,"tools":{"sample.get":{"parameters":{"value":{"description":"value"}}}}}`)}}
if _, err := loadParameterCommandsFromMetadata(missingPath, "*.json"); err == nil {
t.Fatal("parameter metadata without cli_path succeeded")
}
validMetadata := fstest.MapFS{"metadata.json": {Data: []byte(`{"version":1,"tools":{"skip":{},"sample.get":{"cli_path":" sample get ","parameters":{"value":{"description":"value"}}}}}`)}}
commands, err := loadParameterCommandsFromMetadata(validMetadata, "*.json")
if err != nil || len(commands) != 1 || commands[0].Reason == "" || commands[0].CLIPath != "sample get" {
t.Fatalf("metadata commands = %#v, %v", commands, err)
}
if _, err := loadAgentHintsFromSelection(fstest.MapFS{}, "["); err == nil {
t.Fatal("invalid selection glob succeeded")
}
if _, err := loadAgentHintsFromSelection(directoryJSON, "*.json"); err == nil {
t.Fatal("selection directory read succeeded")
}
if _, err := loadAgentHintsFromSelection(invalidJSON, "*.json"); err == nil {
t.Fatal("invalid selection JSON succeeded")
}
validSelection := fstest.MapFS{"sample.json": {Data: []byte(`{
"version":1,
"products":{"sample":{"agent_summary":"summary","use_when":["use"],"avoid_when":["avoid"],"reviewed":true}},
"tools":{"sample.get":{"agent_summary":"summary","use_when":["use"],"avoid_when":["avoid"],"examples":["dws sample get"],"reviewed":true}}
}`)}}
hints, err := loadAgentHintsFromSelection(validSelection, "*.json")
if err != nil || hints.Products["sample"].Reason == "" || len(hints.Products["sample"].Evidence) != 1 || hints.Tools["sample.get"].Reason == "" || len(hints.Tools["sample.get"].Evidence) != 1 {
t.Fatalf("selection hints = %#v, %v", hints, err)
}
if _, err := loadManualSchemaHintsFromHintDirs(invalidJSON, "*.json", validSelection, "*.json"); err == nil {
t.Fatal("wrapper metadata failure succeeded")
}
if _, err := loadManualSchemaHintsFromHintDirs(validMetadata, "*.json", invalidJSON, "*.json"); err == nil {
t.Fatal("wrapper selection failure succeeded")
}
invalidSelection := fstest.MapFS{"sample.json": {Data: []byte(`{"version":1,"tools":{"sample.get":{}}}`)}}
if _, err := loadManualSchemaHintsFromHintDirs(validMetadata, "*.json", invalidSelection, "*.json"); err == nil {
t.Fatal("wrapper selection validation failure succeeded")
}
}
func TestInterfaceRegistryRemainingEdges(t *testing.T) {
ref := &embeddedMCPInterfaceRef{ProductID: "sample", RPCName: "get"}
for _, tools := range []map[string]embeddedMCPToolMetadata{
{" ": {InterfaceRef: ref}},
{"sample.none": {}},
{"sample.incomplete": {InterfaceRef: &embeddedMCPInterfaceRef{ProductID: "sample"}}},
} {
if _, err := buildInterfaceRegistry(tools); err == nil {
t.Fatalf("invalid interface registry succeeded: %#v", tools)
}
}
if err := validateSchemaRegistryInterfacesWithMetadata(SchemaRegistry{}, embeddedMCPMetadata{Tools: map[string]embeddedMCPToolMetadata{"bad": {}}}); err == nil {
t.Fatal("invalid embedded interface metadata succeeded")
}
interfaces, err := buildInterfaceRegistry(map[string]embeddedMCPToolMetadata{"sample.get": {InterfaceRef: ref}})
if err != nil {
t.Fatal(err)
}
for _, candidate := range []*InterfaceRefSpec{nil, {ProductID: "sample"}, {ProductID: "sample", RPCName: "missing"}} {
if err := validateToolInterfaceRef("sample.get", "mcp", candidate, interfaces); err == nil {
t.Fatalf("invalid interface ref succeeded: %#v", candidate)
}
}
registry := SchemaRegistry{Products: []ProductSpec{{ID: "sample", Tools: []ToolSpec{{
Identity: ToolIdentitySpec{ProductID: "", Name: ""},
Interface: InterfaceSpec{Mode: "remote", Availability: "available"},
}}}}}
if err := validateSchemaRegistryInterfacesWithMetadata(registry, embeddedMCPMetadata{Tools: map[string]embeddedMCPToolMetadata{"sample.get": {InterfaceRef: ref}}}); err == nil || !strings.Contains(err.Error(), "<unknown>") {
t.Fatalf("unknown canonical interface error = %v", err)
}
}
func TestReviewedDryRunCapabilityRemainingEdges(t *testing.T) {
originalGroups := reviewedDryRunCapabilityGroups
t.Cleanup(func() {
reviewedDryRunCapabilityGroups = originalGroups
resetReviewedDryRunCapabilitiesForTest()
})
for _, groups := range [][]dryRunCapabilityGroup{
{{PreviewKind: "invalid", CanonicalPaths: []string{"sample.get"}}},
{{PreviewKind: DryRunPreviewRequest, CanonicalPaths: []string{" "}}},
{{PreviewKind: DryRunPreviewRequest, CanonicalPaths: []string{"sample.z", "sample.a"}}},
{{PreviewKind: DryRunPreviewRequest, CanonicalPaths: []string{"sample.get"}}, {PreviewKind: DryRunPreviewPlan, CanonicalPaths: []string{"sample.get"}}},
} {
reviewedDryRunCapabilityGroups = groups
resetReviewedDryRunCapabilitiesForTest()
if _, err := loadReviewedDryRunCapabilities(); err == nil {
t.Fatalf("invalid dry-run groups succeeded: %#v", groups)
}
if _, err := reviewedDryRunCapability("sample.get"); err == nil {
t.Fatal("dry-run lookup ignored registry error")
}
if err := ValidateReviewedDryRunCapabilityDelivery(SchemaRegistry{}); err == nil {
t.Fatal("dry-run delivery ignored registry error")
}
}
reviewedDryRunCapabilityGroups = []dryRunCapabilityGroup{{PreviewKind: DryRunPreviewRequest, CanonicalPaths: []string{"sample.get"}}}
resetReviewedDryRunCapabilitiesForTest()
capabilities, err := ReviewedDryRunCapabilities()
if err != nil {
t.Fatal(err)
}
delete(capabilities, "sample.get")
if second, err := ReviewedDryRunCapabilities(); err != nil || len(second) != 1 {
t.Fatalf("defensive dry-run copy = %#v, %v", second, err)
}
if spec, err := reviewedDryRunCapability("missing"); err != nil || spec != nil {
t.Fatalf("missing dry-run capability = %#v, %v", spec, err)
}
if err := ValidateReviewedDryRunCapabilityDelivery(SchemaRegistry{}); err == nil {
t.Fatal("missing final dry-run capability succeeded")
}
registry := SchemaRegistry{Products: []ProductSpec{{ID: "sample", Tools: []ToolSpec{
{Identity: ToolIdentitySpec{CanonicalPath: "sample.get"}, DryRun: &DryRunSpec{PreviewKind: DryRunPreviewPlan}},
{Identity: ToolIdentitySpec{CanonicalPath: "sample.other"}, DryRun: &DryRunSpec{PreviewKind: DryRunPreviewRequest}},
}}}}
if err := ValidateReviewedDryRunCapabilityDelivery(registry); err == nil {
t.Fatal("mismatched and unreviewed dry-run capabilities succeeded")
}
}
func resetReviewedDryRunCapabilitiesForTest() {
reviewedDryRunCapabilitiesLazy.once = sync.Once{}
reviewedDryRunCapabilitiesLazy.byCanonical = nil
reviewedDryRunCapabilitiesLazy.err = nil
}
func TestSchemaSnapshotAdapterRemainingEdges(t *testing.T) {
if _, err := schemaToolSpecFromPayload(map[string]any{"bad": make(chan int)}); err == nil {
t.Fatal("unmarshalable tool payload succeeded")
}
if err := decodeStrictSchemaJSON([]byte(`{} {}`), &map[string]any{}); err == nil || !strings.Contains(err.Error(), "multiple") {
t.Fatalf("multiple JSON values error = %v", err)
}
if err := decodeStrictSchemaJSON([]byte(`{} trailing`), &map[string]any{}); err == nil || !strings.Contains(err.Error(), "trailing") {
t.Fatalf("trailing JSON error = %v", err)
}
if schemaJSONEqual(make(chan int), map[string]any{}) {
t.Fatal("unmarshalable JSON values compared equal")
}
registry, snapshot := validSnapshotAdapterFixture(t)
if _, _, err := schemaRegistryFromSnapshot(SchemaCatalogSnapshot{Catalog: map[string]any{"bad": make(chan int)}}); err == nil {
t.Fatal("unmarshalable catalog succeeded")
}
if _, _, err := schemaRegistryFromSnapshot(SchemaCatalogSnapshot{Catalog: map[string]any{"unknown": true}}); err == nil {
t.Fatal("unknown catalog field succeeded")
}
canonical := registry.Products[0].Tools[0].Identity.CanonicalPath
missing := cloneSnapshotForCoverage(t, snapshot)
delete(missing.Tools, canonical)
if _, _, err := schemaRegistryFromSnapshot(missing); err == nil || !strings.Contains(err.Error(), "no full ToolSpec") {
t.Fatalf("missing detail error = %v", err)
}
badTool := cloneSnapshotForCoverage(t, snapshot)
badTool.Tools[canonical]["unknown"] = true
if _, _, err := schemaRegistryFromSnapshot(badTool); err == nil || !strings.Contains(err.Error(), "decode Schema ToolSpec") {
t.Fatalf("invalid detail error = %v", err)
}
wrongProduct := cloneSnapshotForCoverage(t, snapshot)
wrongProduct.Tools[canonical]["product_id"] = "other"
wrongProduct.Tools[canonical]["canonical_path"] = "other.get"
if _, _, err := schemaRegistryFromSnapshot(wrongProduct); err == nil || !strings.Contains(err.Error(), "belongs to product") {
t.Fatalf("wrong product error = %v", err)
}
extra := cloneSnapshotForCoverage(t, snapshot)
extra.Tools["sample.extra"] = cloneCoverageSchemaMap(extra.Tools[canonical])
if _, _, err := schemaRegistryFromSnapshot(extra); err == nil || !strings.Contains(err.Error(), "absent from typed products") {
t.Fatalf("extra detail error = %v", err)
}
roundTrip := cloneSnapshotForCoverage(t, snapshot)
products := schemaMapSlice(roundTrip.Catalog["products"])
tools := schemaMapSlice(products[0]["tools"])
tools[0]["title"] = "changed summary"
products[0]["tools"] = tools
roundTrip.Catalog["products"] = products
if _, _, err := schemaRegistryFromSnapshot(roundTrip); err == nil {
t.Fatal("inconsistent summary round trip succeeded")
}
invalidRegistry := SchemaRegistry{Products: []ProductSpec{{ID: " "}}}
if err := validateSnapshotTypedRoundTrip(snapshot, invalidRegistry); err == nil {
t.Fatal("invalid registry snapshot round trip succeeded")
}
missingRendered := cloneSnapshotForCoverage(t, snapshot)
missingRendered.Tools["sample.extra"] = map[string]any{}
if err := validateSnapshotTypedRoundTrip(missingRendered, registry); err == nil || !strings.Contains(err.Error(), "dropped full tool") {
t.Fatalf("dropped full tool error = %v", err)
}
changedTool := cloneSnapshotForCoverage(t, snapshot)
changedTool.Tools[canonical]["title"] = "changed"
if err := validateSnapshotTypedRoundTrip(changedTool, registry); err == nil || !strings.Contains(err.Error(), "changed full tool") {
t.Fatalf("changed full tool error = %v", err)
}
changedProducts := cloneSnapshotForCoverage(t, snapshot)
products = schemaMapSlice(changedProducts.Catalog["products"])
products[0]["name"] = "changed"
changedProducts.Catalog["products"] = products
if err := validateSnapshotTypedRoundTrip(changedProducts, registry); err == nil || !strings.Contains(err.Error(), "product/tool summaries") {
t.Fatalf("changed products error = %v", err)
}
changedCatalog := cloneSnapshotForCoverage(t, snapshot)
changedCatalog.Catalog["source"] = "changed"
if err := validateSnapshotTypedRoundTrip(changedCatalog, registry); err == nil || !strings.Contains(err.Error(), "complete Catalog") {
t.Fatalf("changed catalog error = %v", err)
}
}
func validSnapshotAdapterFixture(t *testing.T) (SchemaRegistry, SchemaCatalogSnapshot) {
t.Helper()
tool, err := ToolSpecFromRuntime(RuntimeToolSpecInput{Identity: ToolIdentitySpec{
ProductID: "sample", Name: "get", CLIName: "get", CLIPath: "sample get",
}})
if err != nil {
t.Fatal(err)
}
registry, err := SchemaRegistryFromRuntime("fixture", []ProductSpec{{ID: "sample", Name: "Sample", Tools: []ToolSpec{tool}}})
if err != nil {
t.Fatal(err)
}
payload, err := registry.ToSnapshotPayload()
if err != nil {
t.Fatal(err)
}
return registry, SchemaCatalogSnapshot{Catalog: payload.Catalog, Tools: payload.Tools}
}
func cloneSnapshotForCoverage(t *testing.T, source SchemaCatalogSnapshot) SchemaCatalogSnapshot {
t.Helper()
data, err := json.Marshal(source)
if err != nil {
t.Fatal(err)
}
var out SchemaCatalogSnapshot
if err := json.Unmarshal(data, &out); err != nil {
t.Fatal(err)
}
return out
}
func cloneCoverageSchemaMap(source map[string]any) map[string]any {
out := make(map[string]any, len(source))
for key, value := range source {
out[key] = value
}
return out
}