feat: add audited workflow review and bounded task recovery
This commit is contained in:
77
weave/recovery/service_test.go
Normal file
77
weave/recovery/service_test.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package recovery
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
core "git.yuntuo.hk/k2safe/orbit/model"
|
||||
"git.yuntuo.hk/k2safe/orbit/platform/auth"
|
||||
)
|
||||
|
||||
type captureStore struct{ calls int }
|
||||
|
||||
func (s *captureStore) ReviewTask(context.Context, auth.Token, core.ID, string, ReviewTaskInput) (Result, error) {
|
||||
s.calls++
|
||||
return Result{}, nil
|
||||
}
|
||||
func (s *captureStore) ResolveStep(context.Context, auth.Token, core.ID, string, ResolveStepInput) (Result, error) {
|
||||
s.calls++
|
||||
return Result{}, nil
|
||||
}
|
||||
func (s *captureStore) Continue(context.Context, auth.Token, core.ID, string, ContinueInput) (Result, error) {
|
||||
s.calls++
|
||||
return Result{}, nil
|
||||
}
|
||||
func (s *captureStore) RetryStep(context.Context, auth.Token, core.ID, string, RetryStepInput) (Result, error) {
|
||||
s.calls++
|
||||
return Result{}, nil
|
||||
}
|
||||
func TestRecoveryValidation(t *testing.T) {
|
||||
id := core.ID(strings.Repeat("a", 32))
|
||||
d := Decision{ExpectedRevision: 2, Reason: "核实外部结果", EvidenceRef: "evidence://case/1"}
|
||||
step := StepDecision{Decision: d, StepKey: "stage-1.v2", ActivationID: id, ExpectedStepRevision: 3}
|
||||
store := &captureStore{}
|
||||
s := New(store)
|
||||
ctx := context.Background()
|
||||
token := auth.Token{}
|
||||
if _, err := s.ReviewTask(ctx, token, id, "operation", ReviewTaskInput{Decision: d, TaskID: id, ExpectedTaskRevision: 4, ExecutionSettled: true, Outcome: "SUCCEEDED", Result: json.RawMessage(`{"n":9007199254740993}`)}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := s.ResolveStep(ctx, token, id, "operation", ResolveStepInput{StepDecision: step, ExecutionSettled: true, Outcome: "SUCCEEDED", Result: json.RawMessage(`null`)}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := s.Continue(ctx, token, id, "operation", ContinueInput{Decision: d, ReviewResolved: true}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := s.RetryStep(ctx, token, id, "operation", RetryStepInput{StepDecision: step, SafeToRetry: true}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, change := range []func(*Decision){func(v *Decision) { v.ExpectedRevision = 0 }, func(v *Decision) { v.Reason = " " }, func(v *Decision) { v.Reason = string([]byte{255}) }, func(v *Decision) { v.EvidenceRef = "secret bad" }, func(v *Decision) { v.EvidenceRef = "" }} {
|
||||
bad := d
|
||||
change(&bad)
|
||||
if _, err := s.Continue(ctx, token, id, "operation", ContinueInput{Decision: bad, ReviewResolved: true}); err == nil {
|
||||
t.Fatal("invalid decision accepted")
|
||||
}
|
||||
}
|
||||
for _, bad := range []ReviewTaskInput{
|
||||
{Decision: d, TaskID: id, ExpectedTaskRevision: 4, Outcome: "SUCCEEDED", Result: json.RawMessage(`{}`)},
|
||||
{Decision: d, TaskID: id, ExpectedTaskRevision: 4, ExecutionSettled: true, Outcome: "UNKNOWN", Result: json.RawMessage(`{}`)},
|
||||
{Decision: d, TaskID: id, ExpectedTaskRevision: 4, ExecutionSettled: true, Outcome: "SUCCEEDED", Result: json.RawMessage(`null`)},
|
||||
{Decision: d, TaskID: id, ExpectedTaskRevision: 4, ExecutionSettled: true, Outcome: "SUCCEEDED", Result: json.RawMessage(`{"n":1,"n":2}`)},
|
||||
} {
|
||||
if _, err := s.ReviewTask(ctx, token, id, "operation", bad); err == nil {
|
||||
t.Fatal("unsafe execution review accepted")
|
||||
}
|
||||
}
|
||||
if _, err := s.Continue(ctx, token, id, "operation", ContinueInput{Decision: d}); err == nil {
|
||||
t.Fatal("unresolved review continued")
|
||||
}
|
||||
if _, err := s.RetryStep(ctx, token, id, "operation", RetryStepInput{StepDecision: step}); err == nil {
|
||||
t.Fatal("unsafe retry accepted")
|
||||
}
|
||||
if store.calls != 4 {
|
||||
t.Fatal("invalid inputs reached storage", store.calls)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user