Add native configuration display
This commit is contained in:
@@ -12,8 +12,129 @@ import (
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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"`
|
||||
|
||||
Reference in New Issue
Block a user