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 "strings"
8 "testing"
9)
10
11func TestManifestDigestIsTheStoredBytes(t *testing.T) {
12 s := NewDirStore(t.TempDir())
13 ctx := context.Background()
14 shipRelease(t, s, "bab", "km", "v1", adoptPlatform, []byte("bin one"))
15 raw, _, err := s.Get(ctx, ManifestKey("bab", "km", "v1"))
16 if err != nil {
17 t.Fatal(err)
18 }
19 m, got, err := GetManifestRaw(ctx, s, "bab", "km", "v1")
20 if err != nil || m.Version != "v1" || !bytes.Equal(got, raw) {
21 t.Fatalf("GetManifestRaw = %+v, %q, %v; want the stored bytes", m, got, err)
22 }
23 if d := ManifestDigest(raw); d != etagOf(raw) || !validDigest(d) {
24 t.Fatalf("ManifestDigest = %q, want the hex sha256 of the stored bytes", d)
25 }
26}
27
28func TestCheckManifestDigest(t *testing.T) {
29 s := NewDirStore(t.TempDir())
30 ctx := context.Background()
31 shipRelease(t, s, "bab", "km", "v1", adoptPlatform, []byte("bin one"))
32 raw, _, _ := s.Get(ctx, ManifestKey("bab", "km", "v1"))
33 want := ManifestDigest(raw)
34
35 if m, _, err := CheckManifestDigest(ctx, s, "bab", "km", "v1", want); err != nil || m == nil {
36 t.Fatalf("matching digest: %v", err)
37 }
38 if _, _, err := CheckManifestDigest(ctx, s, "bab", "km", "v1", ""); err != nil {
39 t.Fatalf("no digest asked for: %v", err)
40 }
41 other := ManifestDigest([]byte("some other manifest"))
42 if _, _, err := CheckManifestDigest(ctx, s, "bab", "km", "v1", other); !errors.Is(err, ErrManifestDigest) {
43 t.Fatalf("mismatched digest: %v, want ErrManifestDigest", err)
44 }
45}
46
47func TestValidDigest(t *testing.T) {
48 for d, ok := range map[string]bool{
49 ManifestDigest([]byte("x")): true,
50 "": false,
51 "ABCDEF" + ManifestDigest([]byte("x"))[6:]: false, // upper case is not canonical
52 ManifestDigest([]byte("x"))[:63]: false,
53 } {
54 if validDigest(d) != ok {
55 t.Errorf("validDigest(%q) = %v, want %v", d, !ok, ok)
56 }
57 }
58}
59
60// failingGetStore fails every Get of one key, as a transient bucket error
61// would, while listing still names it.
62type failingGetStore struct {
63 Store
64 key string
65}
66
67var errTransient = errors.New("transient read failure")
68
69func (f failingGetStore) Get(ctx context.Context, key string) ([]byte, string, error) {
70 if key == f.key {
71 return nil, "", errTransient
72 }
73 return f.Store.Get(ctx, key)
74}
75
76// Astra r1 #4: a channel whose pointer cannot be read is not skipped. It
77// comes back with Err set, so no consumer can count it as carrying digests.
78func TestDigestReportMarksAChannelItCannotRead(t *testing.T) {
79 base := NewDirStore(t.TempDir())
80 ctx := context.Background()
81 priv, pub := testKeys(t)
82 shipRelease(t, base, "bab", "km", "v1", adoptPlatform, []byte("one"))
83 if err := Promote(ctx, base, priv, "bab", "km", "beta", "v1"); err != nil { // no digests
84 t.Fatal(err)
85 }
86 markerOn(t, base, priv, "bab")
87 if err := Promote(ctx, base, priv, "bab", "km", "canary/x", "v1"); err != nil { // digests
88 t.Fatal(err)
89 }
90 s := failingGetStore{Store: base, key: ChannelKey("bab", "km", "beta")}
91 rows, _, err := DigestReport(ctx, s, pub, "bab", "km")
92 if err != nil || len(rows) != 2 {
93 t.Fatalf("report = %+v, %v; want both channels", rows, err)
94 }
95 got := map[string]ChannelDigestState{}
96 for _, r := range rows {
97 got[r.Channel] = r
98 }
99 if b := got["beta"]; b.Err == "" || !strings.Contains(b.Err, errTransient.Error()) || b.HeadDigest {
100 t.Fatalf("beta = %+v; want its read error, never a digest state", b)
101 }
102 if c := got["canary/x"]; c.Err != "" || !c.HeadDigest {
103 t.Fatalf("canary/x = %+v; want it read as carrying digests", c)
104 }
105}
106