carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package moves
2
3import (
4 "testing"
5 "time"
6
7 "github.com/carlosframework/platform/internal/provision"
8)
9
10// The auto-abort bound (spec §7.11, ruling K18): a Phase 1 move still
11// preparing AbortAfter after max(RequestedAt, ReadyAt) is due; one that is
12// not yet there, or is in any other state, or is a legacy move, is not.
13func TestAbortDue(t *testing.T) {
14 if AbortAfter != 6*time.Hour {
15 t.Fatalf("AbortAfter = %v, want 6h", AbortAfter)
16 }
17 req := time.Date(2026, 10, 9, 8, 0, 0, 0, time.UTC)
18 rec := func(state string, ready *time.Time) provision.Record {
19 return provision.Record{Host: "a.go.example.com", Move: &provision.MoveState{ID: "mv_abcdefghijklmnopqrstuvwxyz", State: state, RequestedAt: req, ReadyAt: ready}}
20 }
21 at := func(d time.Duration) time.Time { return req.Add(d) }
22 later := req.Add(2 * time.Hour)
23 for name, c := range map[string]struct {
24 rec provision.Record
25 now time.Time
26 want bool
27 }{
28 "preparing, just short": {rec(provision.MovePreparing, nil), at(AbortAfter - time.Second), false},
29 "preparing, at the bound": {rec(provision.MovePreparing, nil), at(AbortAfter), true},
30 "preparing, well past": {rec(provision.MovePreparing, nil), at(3 * AbortAfter), true},
31 "the bound is from the later time": {rec(provision.MovePreparing, &later), at(AbortAfter + time.Hour), false},
32 "and reached from it": {rec(provision.MovePreparing, &later), later.Add(AbortAfter), true},
33 "a non-UTC clock": {rec(provision.MovePreparing, nil), at(AbortAfter).In(time.FixedZone("x", -7*3600)), true},
34 "ready": {rec(provision.MoveReady, &later), at(10 * AbortAfter), false},
35 "cutting": {rec(provision.MoveCutting, &later), at(10 * AbortAfter), false},
36 "aborting": {rec(provision.MoveAborting, nil), at(10 * AbortAfter), false},
37 "landing": {rec(provision.MoveLanding, nil), at(10 * AbortAfter), false},
38 "legacy": {provision.Record{Move: &provision.MoveState{State: provision.MovePreparing, RequestedAt: req}}, at(10 * AbortAfter), false},
39 "no move": {provision.Record{}, at(10 * AbortAfter), false},
40 "no request time": {provision.Record{Move: &provision.MoveState{ID: "mv_abcdefghijklmnopqrstuvwxyz", State: provision.MovePreparing}}, at(10 * AbortAfter), false},
41 } {
42 if got := AbortDue(c.rec, c.now); got != c.want {
43 t.Errorf("%s: AbortDue = %v, want %v", name, got, c.want)
44 }
45 }
46}
47