carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package host
2
3import (
4 "bytes"
5 "context"
6 "crypto/ed25519"
7 "encoding/json"
8 "errors"
9 "os"
10 "path/filepath"
11 "testing"
12
13 "github.com/carlosframework/platform/internal/moves"
14 "github.com/carlosframework/platform/internal/release"
15)
16
17func TestPlan14FloorRiseWithoutPlatformUpdate(t *testing.T) {
18 for _, prev := range []string{"none", "v2.0.0", "v1.0.0"} {
19 t.Run(prev, func(t *testing.T) {
20 id := rootFloorIdentity{Deployment: "deploy", Box: "box", Enrollment: "en"}
21 f := rootMovesFloors{private: &rollbackMemory{files: map[string][]byte{}}, public: &rollbackMemory{files: map[string][]byte{}}, identity: id}
22 a := moves.Floor{Min: 1, MinRelease: "v1.0.0"}
23 b := moves.Floor{Min: 2, MinRelease: "v2.0.0"}
24 if err := f.reconstruct(t.Context(), rootFloorReconstruction{Identity: id, Floor: &a, Source: "history", Digest: floorTestDigest, Authorization: floorTestAuthorization(t, f)}); err != nil {
25 t.Fatal(err)
26 }
27 store := release.NewDirStore(t.TempDir())
28 raw, _ := json.Marshal(b)
29 if _, err := store.Put(t.Context(), moves.FloorKey, raw, ""); err != nil {
30 t.Fatal(err)
31 }
32 mirror := t.TempDir()
33 if _, err := syncLocalFloor(t.Context(), store, mirror); err != nil {
34 t.Fatal(err)
35 }
36 if p, err := f.projection(); err != nil || p.Floor.MinRelease != a.MinRelease {
37 t.Fatal("mirror acknowledged B", p, err)
38 }
39 reads := 0
40 read := func(context.Context) (*moves.Floor, error) { reads++; return &b, nil }
41 binary := func(path string) (rootFloorBinary, error) {
42 if path == "prev" && prev == "none" {
43 return rootFloorBinary{}, os.ErrNotExist
44 }
45 v := "v2.0.0"
46 if path == "prev" {
47 v = prev
48 }
49 return rootFloorBinary{Version: v, Protocol: 2, Digest: floorTestDigest}, nil
50 }
51 judge := rootFloorJudge{floors: f, remote: read, legacy: func() ([]*moves.Floor, error) { return rootFloorLegacy(mirror) }, binary: binary, current: "current", prev: "prev", idle: func(context.Context) error { return nil }}
52 if err := judge.refresh(t.Context()); err != nil {
53 t.Fatal(err)
54 }
55 if reads != 1 {
56 t.Fatal("no-prev path skipped authoritative GET")
57 }
58 p, err := f.projection()
59 if err != nil || p.Floor == nil || *p.Floor != b {
60 t.Fatal("root refresh", p, err)
61 }
62 ad, err := f.advertisement()
63 if err != nil {
64 t.Fatal(err)
65 }
66 if ad.PrevRelease != prev {
67 t.Fatal("prev identity", ad)
68 }
69 if (ad.PrevAllowedFor == b.MinRelease) != (prev == "v2.0.0") {
70 t.Fatal("verdict", ad)
71 }
72 if err := os.RemoveAll(mirror); err != nil {
73 t.Fatal(err)
74 }
75 if again, err := f.advertisement(); err != nil || again != ad {
76 t.Fatal("mirror changed advertisement", again, err)
77 }
78 // A failed persistence cannot publish the new generation's acknowledgement.
79 n := 0
80 broken := f
81 broken.private = &floorFaultStore{Store: f.private, n: &n, fail: 1}
82 judge.floors = broken
83 if judge.refresh(t.Context()) == nil {
84 t.Fatal("failed floor sync accepted")
85 }
86 if _, err := f.advertisement(); err == nil {
87 t.Fatal("failed sync left acceptance")
88 }
89 })
90 }
91}
92
93func TestPlan14RootFloorRecoveryOffline(t *testing.T) {
94 for _, entry := range []string{"recover", "rollback"} {
95 t.Run(entry, func(t *testing.T) {
96 f, _ := applyHappy(t)
97 j := f.brokenBox("v2.0.0", "v1.0.0", "v1.0.0")
98 journal := filepath.Join(systemRootDir(f.a.optDir), "journal.json")
99 before, _ := os.ReadFile(systemBinaryPath(f.a.optDir))
100 original, _ := os.ReadFile(journal)
101 unavailable := errors.New("provider unavailable")
102 reads := 0
103 f.a.rootMoves = func() (rootFloorIdentity, bool, error) {
104 return rootFloorIdentity{Deployment: "deploy", Box: "box", Enrollment: "en"}, true, nil
105 }
106 f.a.openStore = func(context.Context) (release.Store, ed25519.PublicKey, error) { reads++; return nil, nil, unavailable }
107 var err error
108 if entry == "recover" {
109 _, err = f.a.recoverIfNeeded(t.Context())
110 } else {
111 _, err = f.a.restoreFiles(t.Context(), &j)
112 }
113 if err == nil || reads != 0 {
114 t.Fatalf("recovery used network or accepted missing signed identity: reads=%d err=%v", reads, err)
115 }
116 after, _ := os.ReadFile(systemBinaryPath(f.a.optDir))
117 retained, _ := os.ReadFile(journal)
118 if !bytes.Equal(before, after) || !bytes.Equal(original, retained) {
119 t.Fatal("failed refresh changed executable or journal")
120 }
121 })
122 }
123}
124