| 1 | package activator |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "errors" |
| 6 | "os/exec" |
| 7 | "testing" |
| 8 | "time" |
| 9 | |
| 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 TestStartAdmittedLazyLaunchFailureSettlesWithoutSpawn(t *testing.T) { |
| 16 | o := hostclaim.Observed{Host: "app.example.test", ETag: "one", Claim: &hostclaim.Claim{Holder: &hostclaim.Holder{Location: "instances/app/inc", Session: 1, Generation: "new"}, Op: hostclaim.Op{Kind: hostclaim.KindServing, Exec: "box"}}} |
| 17 | work, _ := (hostwrite.Config{}).Select(t.Context(), o.Host, "spawn") |
| 18 | restored, materialized, built := false, false, false |
| 19 | failures := 0 |
| 20 | failure := errors.New("constructor failed") |
| 21 | start := ClaimStart{Host: o.Host, Work: work, Identity: hostwrite.Identity{Config: "config", Release: "release"}, CurrentAttempt: func() hostclaim.WakeRetryAttempt { return hostclaim.WakeRetryAttempt{ID: "attempt"} }, Restore: func(context.Context) error { restored = true; return nil }, Materialize: func(context.Context) error { materialized = true; return nil }, Build: func() *exec.Cmd { built = true; return nil }, Ready: func(context.Context, *exec.Cmd) error { return nil }, Reserve: func(context.Context, int) error { return nil }, Failed: func(context.Context, int) error { failures++; return nil }, Healthy: func(context.Context, int, *exec.Cmd) error { return nil }, Replicate: func(context.Context, string) (Rep, error) { |
| 22 | t.Fatal("replicator opened without launch") |
| 23 | return nil, nil |
| 24 | }, Publish: func(context.Context, hostclaim.Observed) (hostclaim.Observed, error) { return o, nil }, Retain: func(Proc, Rep, error) {}, PrepareLaunch: func(context.Context) (*RoleLaunch, error) { |
| 25 | if !restored || !materialized { |
| 26 | t.Fatal("launch constructor ran before state materialization") |
| 27 | } |
| 28 | return nil, failure |
| 29 | }} |
| 30 | a := &Service{cfg: Config{HostWrites: hostwrite.Config{Enabled: true}, Claims: &ClaimRuntime{Box: "box", Read: func(context.Context, string) (hostclaim.Observed, error) { return o, nil }, Prepare: func(context.Context, registry.Route, hostclaim.Observed, StartPolicy) (ClaimStart, error) { |
| 31 | return start, nil |
| 32 | }}}} |
| 33 | err := a.startAdmitted(t.Context(), &actEntry{host: o.Host}, o, StartPolicy{MaxStarts: 1, Window: time.Second}) |
| 34 | if !errors.Is(err, failure) || failures != 1 || built { |
| 35 | t.Fatalf("err=%v failures=%d built=%v", err, failures, built) |
| 36 | } |
| 37 | live, cancel := context.WithCancel(context.Background()) |
| 38 | cancel() |
| 39 | start.Live = live |
| 40 | restored = false |
| 41 | if err = a.startAdmitted(t.Context(), &actEntry{host: o.Host}, o, StartPolicy{MaxStarts: 1, Window: time.Second}); !errors.Is(err, context.Canceled) || restored { |
| 42 | t.Fatalf("lost lease restored=%v err=%v", restored, err) |
| 43 | } |
| 44 | } |
| 45 | |