carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package release
2
3import (
4 "bytes"
5 "context"
6 "errors"
7 "os"
8 "testing"
9)
10
11type heldSystemPublicationStore struct {
12 Store
13 key string
14 entered chan struct{}
15 resume chan struct{}
16}
17
18func (s heldSystemPublicationStore) Put(ctx context.Context, key string, raw []byte, etag string) (string, error) {
19 if key == s.key {
20 close(s.entered)
21 <-s.resume
22 }
23 return s.Store.Put(ctx, key, raw, etag)
24}
25
26func TestSystemPublicationCancellationWinsDelayedCAS(t *testing.T) {
27 for _, existing := range []bool{false, true} {
28 name := "absent"
29 if existing {
30 name = "existing"
31 }
32 t.Run(name, func(t *testing.T) {
33 ctx := t.Context()
34 key, pub := testKeys(t)
35 sg := RootSigner(key)
36 store := NewDirStore(t.TempDir())
37 if existing {
38 if _, err := PromoteSystem(ctx, store, sg, "router", "stable", testSystemRelease("v1.0.0"), SystemPromoteOptions{}); err != nil {
39 t.Fatal(err)
40 }
41 }
42 prepared, err := PrepareSystemPromotion(ctx, store, sg, "router", "stable", testSystemRelease("v1.1.0"), SystemPromoteOptions{}, "cancelled-update")
43 if err != nil {
44 t.Fatal(err)
45 }
46 held := heldSystemPublicationStore{Store: store, key: SystemPointerKey("router", "stable"), entered: make(chan struct{}), resume: make(chan struct{})}
47 done := make(chan error, 1)
48 go func() { _, err := PublishSystemPublication(ctx, held, pub, prepared); done <- err }()
49 <-held.entered
50 if err := CancelSystemPublication(ctx, store, sg, prepared); err != nil {
51 close(held.resume)
52 t.Fatal(err)
53 }
54 close(held.resume)
55 if err := <-done; !errors.Is(err, ErrCASConflict) {
56 t.Fatalf("delayed CAS: %v", err)
57 }
58 if err := CancelSystemPublication(ctx, store, sg, prepared); err != nil {
59 t.Fatalf("cancel retry: %v", err)
60 }
61 p, etag, err := GetSystemPointer(ctx, store, pub, "router", "stable")
62 if existing {
63 if err != nil || p.Current.Version != "v1.0.0" {
64 t.Fatal(p, err)
65 }
66 } else if !errors.Is(err, os.ErrNotExist) || etag == "" {
67 t.Fatalf("tombstone read: %s %v", etag, err)
68 }
69 if _, err := PromoteSystem(ctx, store, sg, "router", "stable", testSystemRelease("v1.2.0"), SystemPromoteOptions{}); err != nil {
70 t.Fatalf("new promotion after fence: %v", err)
71 }
72 if _, err := PublishSystemPublication(ctx, store, pub, prepared); !errors.Is(err, ErrCASConflict) {
73 t.Fatalf("cancelled activation resurrected: %v", err)
74 }
75 })
76 }
77}
78
79func TestSystemPublicationCancellationCannotUndoCommittedUpdate(t *testing.T) {
80 ctx := t.Context()
81 key, pub := testKeys(t)
82 sg := RootSigner(key)
83 store := NewDirStore(t.TempDir())
84 p, err := PrepareSystemPromotion(ctx, store, sg, "router", "stable", testSystemRelease("v1.0.0"), SystemPromoteOptions{}, "committed-update")
85 if err != nil {
86 t.Fatal(err)
87 }
88 if _, err := PublishSystemPublication(ctx, store, pub, p); err != nil {
89 t.Fatal(err)
90 }
91 if err := CancelSystemPublication(ctx, store, sg, p); !errors.Is(err, ErrCASConflict) {
92 t.Fatal(err)
93 }
94 raw, _, err := store.Get(ctx, SystemPointerKey("router", "stable"))
95 if err != nil || !bytes.Equal(raw, p.After) {
96 t.Fatal("committed publication changed", err)
97 }
98}
99