package commandkit_test import ( "bytes" "context" "errors" "io" "reflect" "strings" "testing" "testing/fstest" commandkit "gitea.maximumdirect.net/eric/CommandKit" configkit "gitea.maximumdirect.net/eric/ConfigKit" "go.yaml.in/yaml/v4" ) type effectiveYAML string func (document effectiveYAML) WriteEffective(writer io.Writer) error { _, err := io.WriteString(writer, string(document)) return err } type capturedSourceReader struct { entries []configkit.SourceInfo calls int } func (reader *capturedSourceReader) Sources() []configkit.SourceInfo { reader.calls++ return reader.entries } func TestConfigSourcesReportsCapturedConfigKitSourceInventory(t *testing.T) { type configuration struct { Value string `yaml:"value"` Shared string `yaml:"shared"` Synthetic string `yaml:"synthetic"` } filesystem := configkit.NewFilesystem("fixture", fstest.MapFS{ "root/config/main.yml": &fstest.MapFile{Data: []byte("configkit: {imports: [{path: ../shared.yml}]}\nvalue: base\n")}, "root/shared.yml": &fstest.MapFile{Data: []byte("shared: imported\n")}, "root/overlays/dev.yml": &fstest.MapFile{Data: []byte("value: overlay\n")}, }) filesystemContext := &configkit.FilesystemContext{Root: "root", FS: &filesystem} overlayFilesystemContext := &configkit.FilesystemContext{Root: "root", BaseDir: "root/config", FS: &filesystem} loaderCalls := 0 reader := &capturedSourceReader{} scope, err := commandkit.NewConfigKitScope[struct{}, configuration]("app", "", func(context.Context, commandkit.Selection, struct{}) (*configkit.Result[configuration], error) { loaderCalls++ result, err := configkit.LoadLayered(configkit.Input{ Source: filesystem.File("root/config/main.yml"), Imports: true, Filesystem: filesystemContext, }, configkit.LayeredOptions[configuration]{ Definition: configkit.Definition[configuration]{}, Underlays: []configkit.Underlay{{Inputs: []configkit.Input{{Source: configkit.Mapping("synthetic source", map[string]any{"synthetic": "underlay"})}}}}, Overlay: "dev", OverlayFilesystem: overlayFilesystemContext, }) if err != nil { return nil, err } reader.entries = result.Sources() return result, nil }) if err != nil { t.Fatal(err) } // Replace the result's reader after the owning loader has captured its source inventory. originalAcquire := scope.Acquire scope.Acquire = func(ctx context.Context, request commandkit.ConfigRequest, input struct{}) (commandkit.Acquired[commandkit.ConfigView], error) { acquired, err := originalAcquire(ctx, request, input) if err == nil { acquired.Value.Sources = reader } return acquired, err } // Register the wrapped scope so the command reads the captured public facet once. app, _ := commandkit.New(commandkit.Identity{Name: "example"}) if err := commandkit.RegisterConfig(app, commandkit.ConfigSuite[struct{}]{Scopes: []commandkit.ConfigScope[struct{}]{scope}}); err != nil { t.Fatal(err) } var output bytes.Buffer outcome := app.Execute(context.Background(), []string{"config", "sources", "--format", "yaml"}, commandkit.Streams{Out: &output, Err: io.Discard}) if outcome.Kind != commandkit.OutcomeSuccess || loaderCalls != 1 || reader.calls != 1 { var details bytes.Buffer for _, diagnostic := range outcome.Diagnostics { _ = diagnostic.Write(&details) } t.Fatalf("sources outcome=%#v cause=%v details=%q loader calls=%d reader calls=%d", outcome, outcome.Cause, details.String(), loaderCalls, reader.calls) } var report struct { Scope string `yaml:"scope"` Sources []struct { ID string `yaml:"id"` Label string `yaml:"label"` Path string `yaml:"path"` Layer string `yaml:"layer"` Kind string `yaml:"kind"` UnderlayIndex int `yaml:"underlay_index"` ImportedFrom *struct { SourceID string `yaml:"source_id"` Line int `yaml:"line"` Column int `yaml:"column"` } `yaml:"imported_from"` } `yaml:"sources"` } if err := yaml.Unmarshal(output.Bytes(), &report); err != nil { t.Fatal(err) } if report.Scope != "app" || len(report.Sources) != 4 { t.Fatalf("source report = %#v", report) } if report.Sources[0].Path != "root/config/main.yml" || report.Sources[0].ID != "source-1" { t.Fatalf("main source = %#v", report.Sources[0]) } if report.Sources[0].ImportedFrom != nil { t.Fatalf("root source imported_from = %#v, want null", report.Sources[0].ImportedFrom) } imported := report.Sources[1] if imported.Path != "root/shared.yml" || imported.ImportedFrom == nil || imported.ImportedFrom.SourceID != report.Sources[0].ID || imported.ImportedFrom.Line == 0 { t.Fatalf("import source correlation = %#v", imported) } synthetic := report.Sources[2] if synthetic.Kind != string(configkit.SourceKindMapping) || synthetic.Path != "" || synthetic.Layer != string(configkit.LayerUnderlay) || synthetic.UnderlayIndex != 1 { t.Fatalf("synthetic underlay source = %#v", synthetic) } if report.Sources[3].Layer != string(configkit.LayerOverlay) || report.Sources[3].Path != "root/overlays/dev.yml" { t.Fatalf("overlay source = %#v", report.Sources[3]) } } func TestConfigSourcesHandlesEmptyInventoryAllPreflightAndWriterFailure(t *testing.T) { reader := &capturedSourceReader{} newContextCalls, acquireCalls := 0, 0 app, err := commandkit.New(commandkit.Identity{Name: "example"}) if err != nil { t.Fatal(err) } suite := commandkit.ConfigSuite[string]{ NewContext: func() string { newContextCalls++; return "context" }, Scopes: []commandkit.ConfigScope[string]{{Name: "app", Operations: []commandkit.ConfigOperation{commandkit.ConfigSources}, Acquire: func(context.Context, commandkit.ConfigRequest, string) (commandkit.Acquired[commandkit.ConfigView], error) { acquireCalls++ return commandkit.Acquired[commandkit.ConfigView]{Value: commandkit.ConfigView{Sources: reader}}, nil }}}, } if err := commandkit.RegisterConfig(app, suite); err != nil { t.Fatal(err) } var output bytes.Buffer outcome := app.Execute(context.Background(), []string{"config", "sources", "--scope", "all"}, commandkit.Streams{Out: &output, Err: io.Discard}) if outcome.Kind != commandkit.OutcomeUsage || newContextCalls != 0 || acquireCalls != 0 || output.Len() != 0 { t.Fatalf("all preflight outcome=%#v contexts=%d acquires=%d output=%q", outcome, newContextCalls, acquireCalls, output.String()) } outcome = app.Execute(context.Background(), []string{"config", "sources", "--format", "yaml"}, commandkit.Streams{Out: &output, Err: io.Discard}) if outcome.Kind != commandkit.OutcomeSuccess || output.String() != "scope: app\nsources: []\n" || reader.calls != 1 { t.Fatalf("empty source report outcome=%#v output=%q reader calls=%d", outcome, output.String(), reader.calls) } reader.entries = []configkit.SourceInfo{{ID: "source-1", Label: "label with \"quotes\"", Path: "path with spaces.yml", Layer: configkit.LayerBase, Kind: configkit.SourceKindFile}} var textOutput bytes.Buffer outcome = app.Execute(context.Background(), []string{"config", "sources"}, commandkit.Streams{Out: &textOutput, Err: io.Discard}) if outcome.Kind != commandkit.OutcomeSuccess || !strings.Contains(textOutput.String(), `label: "label with \"quotes\""`) || !strings.Contains(textOutput.String(), `path: "path with spaces.yml"`) { t.Fatalf("quoted text source output outcome=%#v output=%q", outcome, textOutput.String()) } partial := &configKitShowPartialWriter{failure: io.ErrClosedPipe} outcome = app.Execute(context.Background(), []string{"config", "sources"}, commandkit.Streams{Out: partial, Err: io.Discard}) if outcome.Kind != commandkit.OutcomeOperational || !outcome.ReportIncomplete || !errors.Is(outcome.DeliveryError, io.ErrClosedPipe) { t.Fatalf("source writer failure = %#v", outcome) } } func TestConfigShowWritesNativeSingleScopeAndFramesAggregateYAML(t *testing.T) { const native = "%YAML 1.1\n# authored comment\n---\nvalue: null\nitems: []\nmissing: {}\n" app, err := commandkit.New(commandkit.Identity{Name: "example"}) if err != nil { t.Fatal(err) } var calls []string suite := commandkit.ConfigSuite[struct{}]{Scopes: []commandkit.ConfigScope[struct{}]{ {Name: "zeta", Operations: []commandkit.ConfigOperation{commandkit.ConfigShow}, Acquire: func(context.Context, commandkit.ConfigRequest, struct{}) (commandkit.Acquired[commandkit.ConfigView], error) { calls = append(calls, "zeta") return commandkit.Acquired[commandkit.ConfigView]{Value: commandkit.ConfigView{Effective: effectiveYAML("%YAML 1.1\n# zeta comment\nvalue: zeta\n")}}, nil }}, {Name: "app", Operations: []commandkit.ConfigOperation{commandkit.ConfigShow}, Acquire: func(context.Context, commandkit.ConfigRequest, struct{}) (commandkit.Acquired[commandkit.ConfigView], error) { calls = append(calls, "app") return commandkit.Acquired[commandkit.ConfigView]{Value: commandkit.ConfigView{Effective: effectiveYAML(native)}}, nil }}, }} if err := commandkit.RegisterConfig(app, suite); err != nil { t.Fatal(err) } var single bytes.Buffer outcome := app.Execute(context.Background(), []string{"config", "show"}, commandkit.Streams{Out: &single, Err: io.Discard}) if outcome.Kind != commandkit.OutcomeSuccess || single.String() != native { t.Fatalf("single show outcome=%#v output=%q", outcome, single.String()) } calls = nil outcome = app.Execute(context.Background(), []string{"config", "show", "--format", "text"}, commandkit.Streams{Out: &single, Err: io.Discard}) if outcome.Kind != commandkit.OutcomeUsage || len(calls) != 0 { t.Fatalf("text format outcome=%#v acquisitions=%v", outcome, calls) } calls = nil var aggregate bytes.Buffer outcome = app.Execute(context.Background(), []string{"config", "show", "--scope", "all"}, commandkit.Streams{Out: &aggregate, Err: io.Discard}) if outcome.Kind != commandkit.OutcomeSuccess || !reflect.DeepEqual(calls, []string{"app", "zeta"}) { t.Fatalf("aggregate outcome=%#v acquisitions=%v", outcome, calls) } if !strings.Contains(aggregate.String(), "%YAML 1.1\n# authored comment\n---\n# scope: app\n") || !strings.Contains(aggregate.String(), "...\n%YAML 1.1\n# zeta comment\n---\n# scope: zeta\nvalue: zeta\n") { t.Fatalf("aggregate framing = %q", aggregate.String()) } decoder := yaml.NewDecoder(bytes.NewReader(aggregate.Bytes())) var first, second map[string]any if err := decoder.Decode(&first); err != nil { t.Fatal(err) } if err := decoder.Decode(&second); err != nil { t.Fatal(err) } var extra any if err := decoder.Decode(&extra); err != io.EOF { t.Fatalf("third YAML document decode error = %v, value=%#v", err, extra) } if first["value"] != nil || first["items"] == nil || first["missing"] == nil || second["value"] != "zeta" { t.Fatalf("decoded documents = %#v and %#v", first, second) } if _, exists := first["absent"]; exists { t.Fatalf("absent field was added to native document: %#v", first) } } func TestConfigShowAcquiresAllBeforeOutputAndTracksWriterFailures(t *testing.T) { failure := errors.New("second scope failed") app, err := commandkit.New(commandkit.Identity{Name: "example"}) if err != nil { t.Fatal(err) } calls := 0 suite := commandkit.ConfigSuite[struct{}]{Scopes: []commandkit.ConfigScope[struct{}]{ {Name: "app", Operations: []commandkit.ConfigOperation{commandkit.ConfigShow}, Acquire: func(context.Context, commandkit.ConfigRequest, struct{}) (commandkit.Acquired[commandkit.ConfigView], error) { calls++ return commandkit.Acquired[commandkit.ConfigView]{Value: commandkit.ConfigView{Effective: effectiveYAML("value: app\n")}}, nil }}, {Name: "promptkit", Operations: []commandkit.ConfigOperation{commandkit.ConfigShow}, Acquire: func(context.Context, commandkit.ConfigRequest, struct{}) (commandkit.Acquired[commandkit.ConfigView], error) { calls++ return commandkit.Acquired[commandkit.ConfigView]{Diagnostics: []commandkit.Diagnostic{commandkit.MessageDiagnostic(configkit.SeverityWarning, "provider warning")}}, failure }}, }} if err := commandkit.RegisterConfig(app, suite); err != nil { t.Fatal(err) } var output bytes.Buffer outcome := app.Execute(context.Background(), []string{"config", "show", "--scope", "all"}, commandkit.Streams{Out: &output, Err: io.Discard}) if !errors.Is(outcome.Cause, failure) || outcome.ReportIncomplete || output.Len() != 0 || calls != 2 || len(outcome.Diagnostics) < 1 || outcome.Diagnostics[0].Severity != configkit.SeverityWarning { t.Fatalf("acquisition failure outcome=%#v output=%q calls=%d", outcome, output.String(), calls) } app, _ = commandkit.New(commandkit.Identity{Name: "example"}) if err := commandkit.RegisterConfig(app, commandkit.ConfigSuite[struct{}]{Scopes: []commandkit.ConfigScope[struct{}]{{Name: "app", Operations: []commandkit.ConfigOperation{commandkit.ConfigShow}, Acquire: func(context.Context, commandkit.ConfigRequest, struct{}) (commandkit.Acquired[commandkit.ConfigView], error) { return commandkit.Acquired[commandkit.ConfigView]{Value: commandkit.ConfigView{Effective: effectiveYAML("value: app\n")}}, nil }}}}); err != nil { t.Fatal(err) } partial := &configKitShowPartialWriter{failure: io.ErrClosedPipe} outcome = app.Execute(context.Background(), []string{"config", "show", "--scope", "all"}, commandkit.Streams{Out: partial, Err: io.Discard}) if outcome.Kind != commandkit.OutcomeOperational || !outcome.ReportIncomplete || !errors.Is(outcome.Cause, io.ErrClosedPipe) || !errors.Is(outcome.DeliveryError, io.ErrClosedPipe) || len(partial.written) == 0 { t.Fatalf("writer failure outcome = %#v", outcome) } } type configKitShowPartialWriter struct { written []byte failure error } func (writer *configKitShowPartialWriter) Write(data []byte) (int, error) { n := len(data) if n > 4 { n = 4 } writer.written = append(writer.written, data[:n]...) return n, writer.failure } func TestConfigKitScopeUsesDefaultsOverlayAndRecordedResolution(t *testing.T) { type configuration struct { Mode string `yaml:"mode"` Defaulted string `yaml:"defaulted"` } filesystem := configkit.NewFilesystem("fixture", fstest.MapFS{ "config/main.yml": &fstest.MapFile{Data: []byte("mode: base\n")}, "config/overlays/dev.yml": &fstest.MapFile{Data: []byte("mode: overlay\n")}, }) definition := configkit.Definition[configuration]{ Defaults: func() configuration { return configuration{Defaulted: "from default"} }, Resolve: func(input *configuration, resolution *configkit.Resolution) error { resolution.Record(configkit.Keys("mode"), configkit.ChangeNormalization, "normalized for use") input.Mode = strings.ToUpper(input.Mode) return nil }, } var received commandkit.Selection scope, err := commandkit.NewConfigKitScope[struct{}, configuration]("app", "Application settings.", func(_ context.Context, selection commandkit.Selection, _ struct{}) (*configkit.Result[configuration], error) { received = selection return configkit.LoadLayered(configkit.Input{Source: filesystem.File(selection.Config.Value)}, configkit.LayeredOptions[configuration]{ Definition: definition, Overlay: selection.Overlay.Value, OverlayFilesystem: &configkit.FilesystemContext{Root: "config", BaseDir: "config", FS: &filesystem}, }) }) if err != nil { t.Fatal(err) } selection := commandkit.Selection{ Config: commandkit.Supplied[string]{Value: "config/main.yml", Set: true}, Overlay: commandkit.Supplied[string]{Value: "dev", Set: true}, } acquired, err := scope.Acquire(context.Background(), commandkit.ConfigRequest{Operation: commandkit.ConfigValidate, Selection: selection}, struct{}{}) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(received, selection) { t.Fatalf("loader selection = %#v, want %#v", received, selection) } if acquired.Value.Effective == nil || acquired.Value.Sources == nil || acquired.Value.Explanation == nil { t.Fatalf("ConfigKit result facets = %#v", acquired.Value) } if got := acquired.Value.Sources.Sources(); len(got) < 2 { t.Fatalf("sources = %#v, want base and overlay", got) } var effective bytes.Buffer if err := acquired.Value.Effective.WriteEffective(&effective); err != nil { t.Fatal(err) } if !strings.Contains(effective.String(), "mode: OVERLAY") || !strings.Contains(effective.String(), "defaulted: from default") { t.Fatalf("effective configuration = %q", effective.String()) } if explanation, ok := acquired.Value.Explanation.Explain(configkit.Keys("mode")); !ok || len(explanation.History) == 0 { t.Fatalf("resolution explanation = %#v, present=%t", explanation, ok) } } func TestConfigKitScopePreservesAbsentAndEmptySelections(t *testing.T) { type configuration struct { Value string `yaml:"value"` } var seen []commandkit.Selection scope, err := commandkit.NewConfigKitScope[struct{}, configuration]("app", "", func(_ context.Context, selection commandkit.Selection, _ struct{}) (*configkit.Result[configuration], error) { seen = append(seen, selection) return configkit.Load(configkit.NoSource(), configkit.Options[configuration]{Definition: configkit.Definition[configuration]{Defaults: func() configuration { return configuration{Value: "default"} }}}) }) if err != nil { t.Fatal(err) } _, err = scope.Acquire(context.Background(), commandkit.ConfigRequest{}, struct{}{}) if err != nil { t.Fatal(err) } empty := commandkit.Selection{Config: commandkit.Supplied[string]{Set: true}, Overlay: commandkit.Supplied[string]{Set: true}} _, err = scope.Acquire(context.Background(), commandkit.ConfigRequest{Selection: empty}, struct{}{}) if err != nil { t.Fatal(err) } want := []commandkit.Selection{{}, empty} if !reflect.DeepEqual(seen, want) { t.Fatalf("loader selections = %#v, want %#v", seen, want) } } func TestConfigKitScopeRequiresLoaderAndNonNilResult(t *testing.T) { if _, err := commandkit.NewConfigKitScope[struct{}, struct{}]("app", "", nil); err == nil { t.Fatal("accepted a nil ConfigKit loader") } scope, err := commandkit.NewConfigKitScope[struct{}, struct{}]("app", "", func(context.Context, commandkit.Selection, struct{}) (*configkit.Result[struct{}], error) { return nil, nil }) if err != nil { t.Fatal(err) } if _, err := scope.Acquire(context.Background(), commandkit.ConfigRequest{}, struct{}{}); err == nil || !strings.Contains(err.Error(), "nil result") { t.Fatalf("nil result error = %v", err) } } func TestConfigKitLoadErrorRetainsIdentityAndStructuredDiagnostics(t *testing.T) { type configuration struct { Name string `yaml:"name"` } var loadError error scope, err := commandkit.NewConfigKitScope[struct{}, configuration]("app", "", func(context.Context, commandkit.Selection, struct{}) (*configkit.Result[configuration], error) { _, loadError = configkit.Load(configkit.Mapping("bad source", map[string]any{"unknown": true}), configkit.Options[configuration]{Definition: configkit.Definition[configuration]{}}) return nil, loadError }) if err != nil { t.Fatal(err) } acquired, acquireError := scope.Acquire(context.Background(), commandkit.ConfigRequest{}, struct{}{}) var publicLoadError *configkit.LoadError if acquireError != loadError || !errors.As(acquireError, &publicLoadError) { t.Fatalf("load error identity = %v (original %v), public type=%T", acquireError, loadError, acquireError) } if len(acquired.Diagnostics) != 1 || acquired.Diagnostics[0].Severity != configkit.SeverityError { t.Fatalf("structured diagnostics = %#v", acquired.Diagnostics) } var rendered bytes.Buffer if err := acquired.Diagnostics[0].Write(&rendered); err != nil { t.Fatal(err) } if !strings.Contains(rendered.String(), `Configuration scope "app":`) || !strings.Contains(rendered.String(), `"bad source"`) { t.Fatalf("grouped diagnostics = %q", rendered.String()) } app, _ := commandkit.New(commandkit.Identity{Name: "example"}) if err := commandkit.RegisterConfig(app, commandkit.ConfigSuite[struct{}]{Scopes: []commandkit.ConfigScope[struct{}]{scope}}); err != nil { t.Fatal(err) } var output, diagnostic bytes.Buffer outcome := app.Execute(context.Background(), []string{"config", "validate"}, commandkit.Streams{Out: &output, Err: &diagnostic}) if outcome.Cause != loadError || len(outcome.Diagnostics) != 1 || strings.Count(diagnostic.String(), `Configuration scope "app":`) != 1 || output.Len() != 0 { t.Fatalf("presented load failure outcome=%#v output=%q diagnostics=%q", outcome, output.String(), diagnostic.String()) } } func TestConfigValidationEmitsSuccessAsScopesCompleteAndStopsAtFailure(t *testing.T) { app, err := commandkit.New(commandkit.Identity{Name: "example"}) if err != nil { t.Fatal(err) } var calls []string newContextCalls := 0 failure := errors.New("promptkit could not load") suite := commandkit.ConfigSuite[string]{ NewContext: func() string { newContextCalls++; return "runtime" }, Scopes: []commandkit.ConfigScope[string]{ {Name: "zeta", Operations: []commandkit.ConfigOperation{commandkit.ConfigValidate}, Acquire: func(context.Context, commandkit.ConfigRequest, string) (commandkit.Acquired[commandkit.ConfigView], error) { calls = append(calls, "zeta") return commandkit.Acquired[commandkit.ConfigView]{}, nil }}, {Name: "promptkit", Operations: []commandkit.ConfigOperation{commandkit.ConfigValidate}, Acquire: func(context.Context, commandkit.ConfigRequest, string) (commandkit.Acquired[commandkit.ConfigView], error) { calls = append(calls, "promptkit") return commandkit.Acquired[commandkit.ConfigView]{}, failure }}, {Name: "app", Operations: []commandkit.ConfigOperation{commandkit.ConfigValidate}, Acquire: func(context.Context, commandkit.ConfigRequest, string) (commandkit.Acquired[commandkit.ConfigView], error) { calls = append(calls, "app") return commandkit.Acquired[commandkit.ConfigView]{}, nil }}, }, } if err := commandkit.RegisterConfig(app, suite); err != nil { t.Fatal(err) } var output, diagnostic bytes.Buffer outcome := app.Execute(context.Background(), []string{"config", "validate", "--scope", "all"}, commandkit.Streams{Out: &output, Err: &diagnostic}) if outcome.Kind != commandkit.OutcomeOperational || !errors.Is(outcome.Cause, failure) || !outcome.ReportIncomplete { t.Fatalf("validation outcome = %#v", outcome) } if !reflect.DeepEqual(calls, []string{"app", "promptkit"}) || newContextCalls != 1 { t.Fatalf("acquisitions = %v, NewContext calls=%d", calls, newContextCalls) } if output.String() != "app: valid\n" || !strings.Contains(diagnostic.String(), failure.Error()) { t.Fatalf("output=%q diagnostics=%q", output.String(), diagnostic.String()) } } func TestConfigValidationYAMLWarningsAndShortWrites(t *testing.T) { type configuration struct { Name string `yaml:"name"` } warningScope, err := commandkit.NewConfigKitScope[struct{}, configuration]("app", "", func(context.Context, commandkit.Selection, struct{}) (*configkit.Result[configuration], error) { return configkit.Load(configkit.NoSource(), configkit.Options[configuration]{Definition: configkit.Definition[configuration]{ Validate: func(_ *configuration, validation *configkit.Validation) { validation.Warning(configkit.Keys("name"), "uses a demonstration name") }, }}) }) if err != nil { t.Fatal(err) } app, _ := commandkit.New(commandkit.Identity{Name: "example"}) if err := commandkit.RegisterConfig(app, commandkit.ConfigSuite[struct{}]{Scopes: []commandkit.ConfigScope[struct{}]{warningScope}}); err != nil { t.Fatal(err) } var output, diagnostic bytes.Buffer outcome := app.Execute(context.Background(), []string{"config", "validate", "--format", "yaml"}, commandkit.Streams{Out: &output, Err: &diagnostic}) if outcome.Kind != commandkit.OutcomeSuccess || outcome.Status != 0 || outcome.DiagnosticDelivery != commandkit.DeliveryComplete { t.Fatalf("warning validation outcome = %#v", outcome) } if output.String() != "scopes:\n - name: app\n valid: true\n" || !strings.Contains(diagnostic.String(), "uses a demonstration name") { t.Fatalf("output=%q diagnostics=%q", output.String(), diagnostic.String()) } outcome = app.Execute(context.Background(), []string{"config", "validate"}, commandkit.Streams{Out: configKitPartialWriter{}, Err: io.Discard}) if outcome.Kind != commandkit.OutcomeOperational || !outcome.ReportIncomplete || !errors.Is(outcome.Cause, io.ErrShortWrite) { t.Fatalf("report short write outcome = %#v", outcome) } var delivered bytes.Buffer outcome = app.Execute(context.Background(), []string{"config", "validate"}, commandkit.Streams{Out: &delivered, Err: configKitPartialWriter{}}) if outcome.DiagnosticDelivery != commandkit.DeliveryIncomplete || !errors.Is(outcome.DeliveryError, io.ErrShortWrite) { t.Fatalf("diagnostic short write outcome = %#v", outcome) } } type configKitPartialWriter struct{} func (configKitPartialWriter) Write(data []byte) (int, error) { if len(data) == 0 { return 0, nil } return len(data) - 1, nil }