carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1//go:build unix
2
3package hostguard
4
5import (
6 "context"
7 "errors"
8 "testing"
9 "time"
10
11 "github.com/carlosframework/platform/internal/hostclaim"
12)
13
14func TestCompletedServingStops(t *testing.T) {
15 for _, tc := range []string{"exact", "pending", "wrong-session", "operation", "phase", "obligation", "wrong-box", "mixed-sessions", "view"} {
16 t.Run(tc, func(t *testing.T) {
17 f, target, captured := fenceFixture(t)
18 f.obs.Claim.Op = hostclaim.Op{Kind: hostclaim.KindServing, Exec: target.Box}
19 target.Op, target.Phase = "", ""
20 target.Region = "uk"
21 f.obs.Claim.Holder.WriterBox = target.Box
22 f.obs.Claim.Holder.Generation = "g7"
23 f.obs.Claim.Holder.Admissions = []hostclaim.AdmissionRecord{{Session: target.Session, Box: target.Box, Region: target.Region, Generation: "g7"}}
24 if _, err := f.g.BeginFence(t.Context(), target); err != nil {
25 t.Fatal(err)
26 }
27 if tc != "pending" {
28 if err := f.g.CompleteFence(t.Context(), target, []byte("receipt"), time.Now(), func(context.Context, FenceTarget, []byte, time.Time) error { return nil }); err != nil {
29 t.Fatal(err)
30 }
31 }
32 if tc == "operation" || tc == "phase" || tc == "obligation" || tc == "mixed-sessions" {
33 // Negative fixtures deliberately put unusable evidence in the journal.
34 err := f.g.locked(t.Context(), target.Host, func(d *recordDir) error {
35 r, err := d.read(target.Host)
36 if err != nil {
37 return err
38 }
39 switch tc {
40 case "operation":
41 r.FenceJournal[0].Target.Op = "op"
42 case "phase":
43 r.FenceJournal[0].Target.Phase = "phase"
44 case "obligation":
45 r.FenceJournal[0].Target.ObligationID = WriterStopObligation(target.Session)
46 case "mixed-sessions":
47 other := r.FenceJournal[0]
48 other.Target.Session++
49 other.Target.FenceID = "second"
50 r.FenceJournal = append(r.FenceJournal, other)
51 }
52 return d.write(r)
53 })
54 if err != nil {
55 t.Fatal(err)
56 }
57 }
58 if tc == "view" {
59 r, err := readRecord(f.g.DataDir, target.Host)
60 if err != nil {
61 t.Fatal(err)
62 }
63 f.g.FenceView = func(context.Context, string, Captured) (FenceView, error) {
64 return FenceView{Schema: 1, Host: target.Host, Captured: captured, Installation: RootInstallation{Host: target.Host, Migration: 1}, Receipts: r.FenceJournal}, nil
65 }
66 }
67 session, box := target.Session, target.Box
68 if tc == "wrong-session" {
69 session++
70 }
71 if tc == "wrong-box" {
72 box = "other"
73 }
74 got, err := f.g.CompletedServingStops(t.Context(), target.Host, captured, session, box)
75 if tc == "exact" || tc == "view" {
76 if err != nil || len(got) != 1 || got[0].Target != target || string(got[0].Bytes) != "receipt" {
77 t.Fatalf("receipts %+v: %v", got, err)
78 }
79 if _, err := f.g.CompletedWriterStops(t.Context(), target.Host, captured, "", box); !errors.Is(err, ErrInvalidInput) {
80 t.Fatalf("operation reader accepted serving: %v", err)
81 }
82 } else if !errors.Is(err, ErrNoFenceReceipt) || len(got) != 0 {
83 t.Fatalf("invalid evidence accepted: %+v %v", got, err)
84 }
85 })
86 }
87}
88
89func TestCompletedServingStopsRejectsZeroIdentity(t *testing.T) {
90 f, target, captured := fenceFixture(t)
91 for _, tc := range []struct {
92 host string
93 c Captured
94 session uint64
95 box string
96 }{
97 {"", captured, 7, "uk"}, {target.Host, Captured{}, 7, "uk"}, {target.Host, captured, 0, "uk"}, {target.Host, captured, 7, ""},
98 } {
99 if _, err := f.g.CompletedServingStops(t.Context(), tc.host, tc.c, tc.session, tc.box); !errors.Is(err, ErrInvalidInput) {
100 t.Fatalf("%+v: %v", tc, err)
101 }
102 }
103}
104