Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions lycaon/internal/toolexecution/program_preparation_review_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,17 @@ import (
)

// Preparation can read source bytes before the final producer is invoked.
// A human reply cannot preserve an operation or branch removed during that wait.
// A human reply cannot preserve authority withdrawn during that wait.
func TestNativePreparationRechecksAuthorityAfterApproval(t *testing.T) {
for _, name := range []string{"unchanged", "profile-withdrawn", "branch-unchanged", "branch-withdrawn"} {
for _, name := range []string{"unchanged", "profile-withdrawn", "branch-unchanged", "branch-withdrawn", "frame-closed", "disclosure-unchanged", "disclosure-frame-closed"} {
t.Run(name, func(t *testing.T) {
parent, tc := frameFixture(t)
withdraw := name == "profile-withdrawn" || name == "branch-withdrawn"
disclose := name == "disclosure-unchanged" || name == "disclosure-frame-closed"
withdraw := name == "profile-withdrawn" || name == "branch-withdrawn" || name == "frame-closed" || name == "disclosure-frame-closed"
wantAsks := 1
if disclose {
wantAsks = 2
}
readRoot := tc.ActiveRootPath()
branch := &preparationBranch{}
retired := errors.New("fixture branch retired")
Expand Down Expand Up @@ -61,12 +66,12 @@ func TestNativePreparationRechecksAuthorityAfterApproval(t *testing.T) {
bound, err := toolcontract.BindOperation(definition, child, "cat", definition.Facts().Commands[0].Effects[0].Mode, nil)
testutil.FailErr(t, "bind read", err)
var preparedBytes, output bytes.Buffer
asks, records := 0, 0
asks, records, preparations := 0, 0, 0
manager := &nativeRecorderReviewManager{invariantCheckpointMgr: invariantCheckpointMgr{status: hitl.DecisionStatusApproved, result: &hitl.DecisionResult{Approved: true}}}
manager.onRequest = func(req hitl.CheckpointRequest) {
asks++
if asks != 1 || preparedBytes.Len() != 0 || records != 0 {
t.Fatal("review repeated or followed preparation")
if asks > wantAsks || preparedBytes.Len() != 0 || records != 0 {
t.Fatalf("review repeated or followed preparation: asks=%d want=%d preparations=%d bytes=%q records=%d", asks, wantAsks, preparations, preparedBytes.String(), records)
}
matched := false
for _, rule := range req.ApprovalMatches {
Expand All @@ -75,6 +80,9 @@ func TestNativePreparationRechecksAuthorityAfterApproval(t *testing.T) {
if !matched {
t.Fatal("read requirement absent from review")
}
if name == "frame-closed" || name == "disclosure-frame-closed" && asks == 2 {
frame.Close()
}
if name == "profile-withdrawn" {
profile.DenyTools = []string{"read"}
}
Expand All @@ -88,6 +96,10 @@ func TestNativePreparationRechecksAuthorityAfterApproval(t *testing.T) {
})
effect := NativeEffect{Operation: bound, Stage: toolcontract.ExecutionStage{ExecutionID: "child", OperationID: "read", Argv: []string{"cat", "input"}}, Arguments: map[string]any{"path": "input"}, Streams: commandprogram.Streams{Output: &output}}
effect.PrepareReviewed = func(ctx context.Context, args map[string]any, actual tools.ToolContext) (PreparedNativeEffect, error) {
preparations++
if disclose && preparations == 1 {
return PreparedNativeEffect{Operation: bound, DisclosedArgv: &commandprogram.ArgvReview{OperationID: "read", Command: "cat", Operands: []string{"input"}, PathTargets: []commandprogram.PathTarget{{Path: "input"}}}}, nil
}
paths, err := projectpaths.NewProgramPaths(ctx, boundary, actual, ".")
if err != nil {
return PreparedNativeEffect{}, err
Expand Down Expand Up @@ -117,7 +129,7 @@ func TestNativePreparationRechecksAuthorityAfterApproval(t *testing.T) {
return nil
}), effect, tc)
frame.Close()
if asks != 1 || memory.InUse().State != 0 || frameMemory.InUse().State != 0 {
if asks != wantAsks || memory.InUse().State != 0 || frameMemory.InUse().State != 0 {
t.Fatal("review or retention contract failed")
}
// The cwd door projects binding errors into its own repair code.
Expand All @@ -135,6 +147,9 @@ func TestNativePreparationRechecksAuthorityAfterApproval(t *testing.T) {
}
} else {
testutil.FailErr(t, "resume approved preparation", err)
if preparations != wantAsks {
t.Fatalf("preparation passes=%d want=%d", preparations, wantAsks)
}
if preparedBytes.String() != "source bytes" || output.String() != "source bytes" || records != 1 || !result.OwnerInvoked || !result.OutputPublishable {
t.Fatalf("authorized preparation failed: prepared=%q output=%q records=%d result=%+v", preparedBytes.String(), output.String(), records, result)
}
Expand Down