Retain captured PromptKit evidence after cancellation
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"slices"
|
||||
@@ -858,18 +859,79 @@ func TestFromEngineRetainsConfigKitLoadExplanation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigScopeHonorsCancellationAfterLoad(t *testing.T) {
|
||||
func TestConfigScopeRetainsCapturedEvidenceAfterCancellation(t *testing.T) {
|
||||
engine := adapterEngine(t)
|
||||
native, err := engine.InspectConfiguration()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
engine := adapterEngine(t)
|
||||
scope := ConfigScope(func(context.Context, ckconfig.Selection, int, int) (*promptkit.Engine, error) {
|
||||
scope := ConfigScope(func(context.Context, ckconfig.Selection, struct{}, struct{}) (*promptkit.Engine, error) {
|
||||
cancel()
|
||||
return engine, nil
|
||||
})
|
||||
|
||||
acquired, err := scope.Acquire(ctx, ckconfig.Request{Operation: ckconfig.Show}, 0, 0)
|
||||
if !errors.Is(err, context.Canceled) || acquired.Value.Effective != nil {
|
||||
t.Fatalf("cancelled scope acquisition = (%#v, %v), want cancellation and no value", acquired, err)
|
||||
acquired, err := scope.Acquire(ctx, ckconfig.Request{}, struct{}{}, struct{}{})
|
||||
if !errors.Is(err, context.Canceled) || acquired.Value.Effective != nil || acquired.Value.Metadata != nil || acquired.Value.Explanation != nil || acquired.Value.Sources == nil || acquired.Value.Findings == nil {
|
||||
t.Fatalf("canceled acquisition = %#v, %v", acquired, err)
|
||||
}
|
||||
if !reflect.DeepEqual(acquired.Value.Sources.Sources(), native.Sources()) || !reflect.DeepEqual(acquired.Value.Findings.Records, native.Diagnostics()) {
|
||||
t.Fatalf("lost captured evidence: %#v", acquired.Value)
|
||||
}
|
||||
for _, operation := range []string{"sources", "validate"} {
|
||||
for _, failOutput := range []bool{false, true} {
|
||||
t.Run(fmt.Sprintf("%s/failOutput=%t", operation, failOutput), func(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
scope := ConfigScope(func(context.Context, ckconfig.Selection, struct{}, struct{}) (*promptkit.Engine, error) {
|
||||
cancel()
|
||||
return engine, nil
|
||||
})
|
||||
unvisited := 0
|
||||
app, err := commandkit.New(commandkit.Identity{Name: "fixture"}, ckconfig.Command(ckconfig.Suite[struct{}, struct{}]{Scopes: []ckconfig.Scope[struct{}, struct{}]{
|
||||
{Name: "app", Operations: []ckconfig.Operation{ckconfig.Validate}, Acquire: func(context.Context, ckconfig.Request, struct{}, struct{}) (commandkit.Acquired[ckconfig.View], error) {
|
||||
return commandkit.Acquired[ckconfig.View]{}, nil
|
||||
}},
|
||||
scope,
|
||||
{Name: "zeta", Operations: []ckconfig.Operation{ckconfig.Validate}, Acquire: func(context.Context, ckconfig.Request, struct{}, struct{}) (commandkit.Acquired[ckconfig.View], error) {
|
||||
unvisited++
|
||||
return commandkit.Acquired[ckconfig.View]{}, nil
|
||||
}},
|
||||
}}))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
args := []string{"config", operation, "--scope=promptkit", "--format=json"}
|
||||
if operation == "validate" {
|
||||
args = []string{"config", "validate", "--scope=all", "--details", "--format=json"}
|
||||
}
|
||||
var out bytes.Buffer
|
||||
var writer io.Writer = &out
|
||||
writeErr := errors.New("output failed")
|
||||
if failOutput {
|
||||
writer = failingDiagnosticWriter{err: writeErr}
|
||||
}
|
||||
got := app.Execute(ctx, args, commandkit.Streams{Out: writer, Err: io.Discard})
|
||||
if !errors.Is(got.Cause, context.Canceled) || unvisited != 0 {
|
||||
t.Fatalf("outcome=%#v unvisited=%d", got, unvisited)
|
||||
}
|
||||
if failOutput {
|
||||
if !errors.Is(got.Presentation.Output.WriteError, writeErr) {
|
||||
t.Fatalf("lost presentation failure: %#v", got)
|
||||
}
|
||||
} else {
|
||||
if operation == "sources" {
|
||||
for _, source := range native.Sources() {
|
||||
if !strings.Contains(out.String(), source.ID) {
|
||||
t.Fatalf("missing acquired source: %s", out.String())
|
||||
}
|
||||
}
|
||||
} else if !strings.Contains(out.String(), `"state": "empty"`) || !strings.Contains(out.String(), `"scope": "app"`) || strings.Contains(out.String(), `"scope": "zeta"`) {
|
||||
t.Fatalf("reached-scope evidence: %s", out.String())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user