carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package console
2
3import (
4 "encoding/json"
5 "testing"
6
7 "github.com/carlosframework/platform/internal/boxid"
8)
9
10// The predicate and the choice are tested in internal/boxchoice. These
11// tests hold console's conversion to it: every field the predicate reads
12// must survive boxSnapshot, or a box would silently read as missing it.
13
14// haBox is an eligible box's edges file in placement "uk".
15func haBox(id string, mut func(m map[string]any)) string {
16 m := map[string]any{
17 "v": 1, "box": id, "box_id": id, "eip": "1.2.3.4", "region": "eu-west-2", "placement": "uk",
18 "hosts": map[string]any{}, "hibernation_configured": true, "serves_shared_pool": true,
19 "accepts_inbound": true, "secrets_key_fp": testKeyFP, "capabilities": []string{"region-ha-1"},
20 "headroom": map[string]any{"mem_free_mib": 1000, "disk_free_mib": 2000, "awake": 3},
21 }
22 if mut != nil {
23 mut(m)
24 }
25 b, _ := json.Marshal(m)
26 return string(b)
27}
28
29func ids(cs []boxCandidate) []string {
30 out := make([]string, len(cs))
31 for i, c := range cs {
32 out[i] = c.BoxID
33 }
34 return out
35}
36
37// rosterFor enrolls each box in placement "uk" as an instance in eu-west-2.
38func rosterFor(boxes ...string) map[string]rosterBox {
39 out := map[string]rosterBox{}
40 for _, b := range boxes {
41 out[b] = rosterBox{Placement: "uk", Cloud: boxid.Cloud{Provider: "aws", Account: "1", Region: "eu-west-2", InstanceID: "i-" + b}}
42 }
43 return out
44}
45
46func TestEligibleBoxesCarriesEveryFieldThePredicateReads(t *testing.T) {
47 del := func(k string) func(map[string]any) { return func(m map[string]any) { delete(m, k) } }
48 set := func(k string, v any) func(map[string]any) { return func(m map[string]any) { m[k] = v } }
49 cases := []struct {
50 name string
51 mut func(map[string]any)
52 want bool
53 }{
54 {"all present", nil, true},
55 {"no dial address", set("eip", ""), false},
56 {"hibernation unconfigured", set("hibernation_configured", false), false},
57 {"hibernation unknown", del("hibernation_configured"), false},
58 {"refuses the shared pool", set("serves_shared_pool", false), false},
59 {"refuses inbound", set("accepts_inbound", false), false},
60 {"wrong secrets key", set("secrets_key_fp", "sha256:other"), false},
61 {"no capability", del("capabilities"), false},
62 {"draining", set("draining", true), false},
63 {"another placement", set("placement", "us"), false},
64 {"another region", set("region", "us-east-1"), false},
65 {"box_id names no roster entry", set("box_id", "i-0zzz"), false},
66 }
67 for _, tc := range cases {
68 t.Run(tc.name, func(t *testing.T) {
69 snap := views(t, haBox("i-0aaa", tc.mut))
70 got := eligibleBoxes(snap, rosterFor("i-0aaa"), "uk", "eu-west-2", "ie", testKeyFP, nil)
71 if (len(got) == 1) != tc.want {
72 t.Fatalf("eligible = %v, want %v", ids(got), tc.want)
73 }
74 })
75 }
76 got := eligibleBoxes(views(t, haBox("i-0aaa", nil)), rosterFor("i-0aaa"), "uk", "eu-west-2", "ie", testKeyFP, nil)
77 if want := (boxCandidate{BoxID: "i-0aaa", Region: "eu-west-2", MemFreeMiB: 1000, DiskFreeMiB: 2000, Awake: 3}); len(got) != 1 || got[0] != want {
78 t.Fatalf("got %+v, want %+v", got, want)
79 }
80 if got := eligibleBoxes(markStale(views(t, haBox("i-0aaa", nil)), "i-0aaa"), rosterFor("i-0aaa"), "uk", "eu-west-2", "ie", testKeyFP, nil); len(got) != 0 {
81 t.Fatalf("a stale box is eligible: %v", ids(got))
82 }
83}
84
85// Both halves of console's completeness carry over: an unread edges file,
86// and unknown liveness.
87func TestEligibleBoxesAnIncompleteSnapshotOffersNothing(t *testing.T) {
88 for _, bend := range []func(*edgesSnapshot){
89 func(s *edgesSnapshot) { s.Complete = false },
90 func(s *edgesSnapshot) { s.BoxesComplete = false },
91 } {
92 snap := views(t, haBox("i-0aaa", nil))
93 bend(&snap)
94 if got := eligibleBoxes(snap, rosterFor("i-0aaa"), "uk", "eu-west-2", "ie", testKeyFP, nil); len(got) != 0 {
95 t.Fatalf("got %v from an incomplete snapshot", ids(got))
96 }
97 }
98}
99
100func TestChooseBoxIsBoxchoiceChoose(t *testing.T) {
101 a, b := boxCandidate{BoxID: "i-0aaa"}, boxCandidate{BoxID: "i-0bbb"}
102 got, ok := chooseBox("shop.bab.oncarlos.com", []boxCandidate{a, b}, map[string]boxLoad{"i-0aaa": {Hosts: 5}, "i-0bbb": {Hosts: 2}}, "bab/jam")
103 if !ok || got.BoxID != "i-0bbb" {
104 t.Fatalf("got %s ok=%v, want i-0bbb", got.BoxID, ok)
105 }
106}
107