Normalize zero outcomes and omitted diagnostic delivery state
This commit is contained in:
@@ -60,6 +60,9 @@ architecture. The issues below affect behavior within the implemented structure.
|
|||||||
- R-05 complete: validation header/record write failures retain `DeliveryError`
|
- R-05 complete: validation header/record write failures retain `DeliveryError`
|
||||||
separately from acquisition failures and combined diagnostic-stream failures.
|
separately from acquisition failures and combined diagnostic-stream failures.
|
||||||
|
|
||||||
|
- R-06 complete: zero outcomes normalize to success/0 and empty delivery state
|
||||||
|
normalizes to none without altering explicit domain outcomes.
|
||||||
|
|
||||||
## Findings and priority
|
## Findings and priority
|
||||||
|
|
||||||
P1 means a supported invocation is blocked or its report content is corrupted.
|
P1 means a supported invocation is blocked or its report content is corrupted.
|
||||||
|
|||||||
@@ -88,6 +88,14 @@ func (a *App) commandAt(path []string) (Command, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) present(outcome Outcome, path []string, streams Streams) Outcome {
|
func (a *App) present(outcome Outcome, path []string, streams Streams) Outcome {
|
||||||
|
if outcome.Kind == "" && outcome.Status == 0 && outcome.Domain == "" &&
|
||||||
|
outcome.Cause == nil && outcome.DeliveryError == nil &&
|
||||||
|
!outcome.ReportIncomplete && len(outcome.Diagnostics) == 0 {
|
||||||
|
outcome.Kind = OutcomeSuccess
|
||||||
|
}
|
||||||
|
if outcome.DiagnosticDelivery == "" {
|
||||||
|
outcome.DiagnosticDelivery = DeliveryNone
|
||||||
|
}
|
||||||
streams = normalizeStreams(streams)
|
streams = normalizeStreams(streams)
|
||||||
if outcome.DiagnosticDelivery == DeliveryComplete {
|
if outcome.DiagnosticDelivery == DeliveryComplete {
|
||||||
return outcome
|
return outcome
|
||||||
|
|||||||
@@ -437,3 +437,35 @@ func TestHelpEntryFormsPresentReportAndDiagnosticFailures(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExecuteNormalizesOutcomeDefaultsAndPreservesDomainValues(t *testing.T) {
|
||||||
|
cause := errors.New("domain cause")
|
||||||
|
for _, tc := range []struct {
|
||||||
|
outcome commandkit.Outcome
|
||||||
|
kind commandkit.OutcomeKind
|
||||||
|
status int
|
||||||
|
domain string
|
||||||
|
cause error
|
||||||
|
}{
|
||||||
|
{commandkit.Outcome{}, commandkit.OutcomeSuccess, 0, "", nil},
|
||||||
|
{commandkit.Outcome{Kind: commandkit.OutcomeDomain, Status: 2, Domain: "needs action", Cause: cause}, commandkit.OutcomeDomain, 2, "needs action", cause},
|
||||||
|
{commandkit.Outcome{Kind: commandkit.OutcomeDomain, Status: 0, Domain: "complete"}, commandkit.OutcomeDomain, 0, "complete", nil},
|
||||||
|
} {
|
||||||
|
command, err := commandkit.NewCommand(commandkit.CommandSpec[struct{}]{Name: "run", Run: func(commandkit.Invocation, struct{}) commandkit.Outcome { return tc.outcome }})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
app, err := commandkit.New(commandkit.Identity{Name: "example"}, command)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
result := app.Execute(context.Background(), []string{"run"}, commandkit.Streams{})
|
||||||
|
wantDelivery := commandkit.DeliveryNone
|
||||||
|
if tc.cause != nil {
|
||||||
|
wantDelivery = commandkit.DeliveryComplete
|
||||||
|
}
|
||||||
|
if result.Kind != tc.kind || result.Status != tc.status || result.Domain != tc.domain || result.Cause != tc.cause || result.DiagnosticDelivery != wantDelivery {
|
||||||
|
t.Fatalf("result=%#v expected=%#v", result, tc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ type Diagnostic struct {
|
|||||||
// Cause records the operation error. DeliveryError records an error encountered
|
// Cause records the operation error. DeliveryError records an error encountered
|
||||||
// while presenting diagnostics or reports; it is kept separate from Cause so
|
// while presenting diagnostics or reports; it is kept separate from Cause so
|
||||||
// both failures remain inspectable. Outcome does not implement error.
|
// both failures remain inspectable. Outcome does not implement error.
|
||||||
|
// Invocation coordination treats a zero Outcome as success with status 0.
|
||||||
type Outcome struct {
|
type Outcome struct {
|
||||||
// Kind classifies the result.
|
// Kind classifies the result.
|
||||||
Kind OutcomeKind
|
Kind OutcomeKind
|
||||||
|
|||||||
Reference in New Issue
Block a user