carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package hostops
2
3import (
4 "context"
5 "encoding/json"
6 "errors"
7 "fmt"
8 "io"
9 "strings"
10 "testing"
11
12 "github.com/carlosframework/platform/internal/hostclaim"
13 "github.com/carlosframework/platform/internal/release"
14)
15
16type plan15StreamStore struct {
17 release.Store
18 bytes, closes, opens, puts int
19}
20
21func (s *plan15StreamStore) Get(ctx context.Context, key string) ([]byte, string, error) {
22 if strings.Contains(key, "control/host-origins/") {
23 panic("unbounded origin Get")
24 }
25 return s.Store.Get(ctx, strings.TrimPrefix(key, "deployment/"))
26}
27func (s *plan15StreamStore) Put(ctx context.Context, key string, b []byte, tag string) (string, error) {
28 s.puts++
29 return "", release.ErrCASConflict
30}
31func (s *plan15StreamStore) Open(context.Context, string) (io.ReadCloser, string, error) {
32 s.opens++
33 return plan15StreamReader{s, strings.NewReader(strings.Repeat("x", 8192))}, "", nil
34}
35
36type plan15StreamReader struct {
37 s *plan15StreamStore
38 r io.Reader
39}
40
41func (r plan15StreamReader) Read(b []byte) (int, error) {
42 n, e := r.r.Read(b)
43 r.s.bytes += n
44 return n, e
45}
46func (r plan15StreamReader) Close() error { r.s.closes++; return nil }
47
48type plan15NoOpen struct{ release.Store }
49
50func TestPlan15StreamingCompositions(t *testing.T) {
51 for _, stream := range []bool{false, true} {
52 for _, boundary := range []bool{false, true} {
53 t.Run(fmt.Sprintf("stream=%v/boundary=%v", stream, boundary), func(t *testing.T) {
54 w, o, _ := wakeResetFixture(t)
55 o.Claim.Origins = &hostclaim.OriginHead{Digest: strings.Repeat("a", 64), Count: 1}
56 key, _ := hostclaim.Key(o.Host)
57 body, _ := json.Marshal(o.Claim)
58 var err error
59 o.ETag, err = w.raw.Put(t.Context(), key, body, o.ETag)
60 if err != nil {
61 t.Fatal(err)
62 }
63 raw := &plan15StreamStore{Store: w.raw}
64 var s release.Store = raw
65 if !stream {
66 s = plan15NoOpen{s}
67 }
68 s = release.NewPrefixStore(s, "deployment")
69 s = conditionalRecordStore{raw: s}
70 if boundary {
71 s = &mutationBoundary{raw: s, check: func(context.Context, MutationTarget) error { return nil }}
72 }
73 h := o.Claim.Holder
74 if ok, err := hostclaim.AdmittedOrigin(t.Context(), s, o, h.Incarnation, h.Location, "ie", "real"); ok || !errors.Is(err, hostclaim.ErrMalformed) {
75 t.Fatalf("proof %v %v", ok, err)
76 }
77 if stream && (raw.bytes != 4097 || raw.opens != 1 || raw.closes != 1) {
78 t.Fatalf("bytes=%d opens=%d closes=%d", raw.bytes, raw.opens, raw.closes)
79 }
80 if !stream && (raw.bytes != 0 || raw.opens != 0) {
81 t.Fatal("nonstreaming store opened")
82 }
83 })
84 }
85 }
86}
87func TestPlan15BoundaryRefusesCandidateBeforeRead(t *testing.T) {
88 for _, flag := range []string{"", "1"} {
89 t.Setenv("CARLOS_HOST_CLAIM_ORIGINS", flag)
90 raw := &plan15StreamStore{}
91 s := &mutationBoundary{raw: conditionalRecordStore{raw: release.NewPrefixStore(raw, "deployment")}, check: func(context.Context, MutationTarget) error { t.Fatal("origin reached grant checker"); return nil }}
92 if _, err := s.Put(t.Context(), "control/host-origins/x.example/node.json", []byte("candidate"), ""); !errors.Is(err, ErrUnclassified) {
93 t.Fatal(err)
94 }
95 if raw.puts != 0 || raw.opens != 0 {
96 t.Fatal("candidate touched raw store")
97 }
98 }
99}
100