| 1 | package activator |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "errors" |
| 6 | "testing" |
| 7 | "time" |
| 8 | |
| 9 | "github.com/carlosframework/platform/internal/hostbox" |
| 10 | "github.com/carlosframework/platform/internal/hostclaim" |
| 11 | "github.com/carlosframework/platform/internal/hostwrite" |
| 12 | "github.com/carlosframework/platform/internal/registry" |
| 13 | ) |
| 14 | |
| 15 | func TestPlan12RecoveryResumeReachesPrepare(t *testing.T) { |
| 16 | for _, mode := range []string{"verified", "missing", "refused", "changed", "changed-after-resume", "session", "op", "writer", "stamp", "kind", "phase", "exec"} { |
| 17 | t.Run(mode, func(t *testing.T) { |
| 18 | o := hostclaim.Observed{Host: "x.example", ETag: "etag", Claim: &hostclaim.Claim{Holder: &hostclaim.Holder{Incarnation: "inc", Session: 3, Stamp: 3, Generation: "gen", WriterBox: "box"}, Op: hostclaim.Op{ID: "move", Kind: hostclaim.KindRestoring, Phase: hostclaim.PhaseProbing, Exec: "box"}}} |
| 19 | prepared := errors.New("prepare reached") |
| 20 | current := o |
| 21 | r := &ClaimRuntime{Box: "box", Read: func(context.Context, string) (hostclaim.Observed, error) { return current, nil }, StopForeign: func(context.Context, string) error { return nil }, Prerequisites: func(context.Context, registry.Route, hostclaim.Observed, startPolicy) error { return nil }, Admit: func(context.Context, registry.Route, hostclaim.Observed, startPolicy) (hostclaim.Observed, error) { |
| 22 | next := o |
| 23 | claim := *o.Claim |
| 24 | holder := *claim.Holder |
| 25 | next.Claim = &claim |
| 26 | claim.Holder = &holder |
| 27 | switch mode { |
| 28 | case "session": |
| 29 | holder.Session-- |
| 30 | case "op": |
| 31 | claim.Op.ID = "other" |
| 32 | case "writer": |
| 33 | holder.WriterBox = "other" |
| 34 | case "stamp": |
| 35 | holder.Stamp++ |
| 36 | case "kind": |
| 37 | claim.Op.Kind = hostclaim.KindReverting |
| 38 | case "phase": |
| 39 | claim.Op.Phase = "other" |
| 40 | case "exec": |
| 41 | claim.Op.Exec = "other" |
| 42 | } |
| 43 | if mode == "changed" { |
| 44 | next.ETag = "changed" |
| 45 | } |
| 46 | current = next |
| 47 | return next, nil |
| 48 | }, Prepare: func(context.Context, registry.Route, hostclaim.Observed, startPolicy) (ClaimStart, error) { |
| 49 | return ClaimStart{}, prepared |
| 50 | }, FailedAdmission: func(context.Context, hostclaim.Observed, error) error { return nil }} |
| 51 | if mode != "missing" { |
| 52 | r.ResumedAdmission = func(context.Context, hostclaim.Observed, hostclaim.Observed) error { |
| 53 | if mode == "changed-after-resume" { |
| 54 | current.ETag = "changed" |
| 55 | } |
| 56 | if mode == "refused" { |
| 57 | return hostbox.ErrChanged |
| 58 | } |
| 59 | return nil |
| 60 | } |
| 61 | } |
| 62 | s := &Service{cfg: Config{HostWrites: hostwrite.Config{Enabled: true}, Claims: r}} |
| 63 | _, err := s.doClaimWake(t.Context(), &actEntry{host: o.Host, route: registry.Route{Host: o.Host}, recoveryPolicy: &StartPolicy{Probe: true, MaxStarts: 5, Window: 30 * time.Second}}) |
| 64 | if mode == "verified" || mode == "changed" || mode == "changed-after-resume" { |
| 65 | if !errors.Is(err, prepared) { |
| 66 | t.Fatalf("resume did not reach prepare: %v", err) |
| 67 | } |
| 68 | } else if !errors.Is(err, hostbox.ErrChanged) { |
| 69 | t.Fatalf("unverified resume: %v", err) |
| 70 | } |
| 71 | }) |
| 72 | } |
| 73 | } |
| 74 | |