//go:build unix package hostbox import ( "context" "errors" "github.com/carlosframework/platform/internal/hostclaim" "github.com/carlosframework/platform/internal/hostguard" "github.com/carlosframework/platform/internal/hostwrite" "github.com/carlosframework/platform/internal/park" "testing" "time" ) func TestReconcileDryRunAndExecutorValidation(t *testing.T) { source, store, obs := workFixture(t) h := obs.Claim.Holder selected := RecordSelection{Host: obs.Host, Key: h.Key, ETag: "record-etag", Incarnation: h.Incarnation, Family: h.Family, Layout: "flat", Paths: []string{"shop.example.db"}, DryRun: true} checks, writes := 0, 0 r := Reconciler{Claims: store, Guard: source.Guard, Local: park.Local{Guard: source.Guard, Claims: store, DataDir: source.Guard.DataDir, Box: "box"}, Writes: hostwrite.Config{Enabled: true, Selector: source}, Box: "box", Region: "ie", Now: func() time.Time { return time.Unix(100, 0) }, CheckRecord: func(context.Context, RecordSelection) error { return nil }, CheckLocal: func(context.Context, hostclaim.Observed, RecordSelection) error { checks++; return nil }} if err := r.Install(context.Background(), selected, func() error { writes++; return nil }); err != nil { t.Fatal(err) } if writes != 0 || checks != 1 { t.Fatal(writes, checks) } selected.DryRun = false r.CheckLocal = func(context.Context, hostclaim.Observed, RecordSelection) error { checks++ if checks >= 3 { return errors.New("quarantined after precheck") } return nil } if err := r.Install(context.Background(), selected, func() error { writes++; return nil }); err == nil { t.Fatal("executor bypassed fresh local check") } if writes != 0 { t.Fatal("row materialized") } } func TestInstallSettlesParticipationBeforeInventory(t *testing.T) { for _, refuse := range []bool{false, true} { t.Run(map[bool]string{false: "settled", true: "refused"}[refuse], func(t *testing.T) { source, store, obs := workFixture(t) h := obs.Claim.Holder selected := RecordSelection{Host: obs.Host, Key: h.Key, ETag: "record-etag", Incarnation: h.Incarnation, Family: h.Family, Layout: "flat", Paths: []string{"shop.example.db"}} prepared, inventory, written := false, false, false denied := errors.New("participation still owns prior operation") r := Reconciler{Claims: store, Guard: source.Guard, Local: park.Local{Guard: source.Guard, Claims: store, DataDir: source.Guard.DataDir, Box: "box"}, Writes: hostwrite.Config{Enabled: true, Selector: source}, Box: "box", Region: "ie", Now: func() time.Time { return time.Unix(100, 0) }, CheckRecord: func(context.Context, RecordSelection) error { return nil }, CheckLocal: func(context.Context, hostclaim.Observed, RecordSelection) error { return nil }} r.Prepare = func(context.Context, hostclaim.Observed) error { prepared = true if refuse { return denied } return nil } r.PrepareInventory = func(context.Context, RecordSelection, hostguard.Captured) error { if !prepared { t.Fatal("inventory preceded participation settlement") } inventory = true return nil } err := r.Install(t.Context(), selected, func() error { written = true; return nil }) if refuse { if !errors.Is(err, denied) || inventory || written { t.Fatal("unsettled participation reached effects", err, inventory, written) } } else if err != nil || !prepared || !inventory || !written { t.Fatal("settled installation", err, prepared, inventory, written) } }) } }