| 1 | package host |
| 2 | |
| 3 | import ( |
| 4 | "encoding/json" |
| 5 | "strings" |
| 6 | "testing" |
| 7 | |
| 8 | "github.com/carlosframework/platform/internal/hostclaim" |
| 9 | ) |
| 10 | |
| 11 | func servingStopFixture(t *testing.T) (ClaimStopCoordinator, StopRequest) { |
| 12 | c, req, _ := claimStopFixture(t) |
| 13 | observed, err := c.Claims.Read(t.Context(), req.Host) |
| 14 | if err != nil { |
| 15 | t.Fatal(err) |
| 16 | } |
| 17 | observed.Claim.Op = hostclaim.Op{Kind: hostclaim.KindServing} |
| 18 | observed.Claim.Holder.WriterBox = req.Box |
| 19 | observed.Claim.Holder.Generation = "generation-1" |
| 20 | observed.Claim.Holder.Admissions = []hostclaim.AdmissionRecord{{Region: "eu-west-1", Box: req.Box, Session: req.WriterSession, Generation: "generation-1"}} |
| 21 | c.Claims = stopClaimReader{observed} |
| 22 | c.Guard.Claims = stopClaimReader{observed} |
| 23 | req.Region = "eu-west-1" |
| 24 | req.OperationID = "" |
| 25 | req.Phase = "" |
| 26 | req.ObligationID = "" |
| 27 | return c, req |
| 28 | } |
| 29 | func TestClaimStopOrdinaryServingUsesHolderAuthority(t *testing.T) { |
| 30 | c, req := servingStopFixture(t) |
| 31 | result, err := c.FenceAndStop(t.Context(), req) |
| 32 | if err != nil { |
| 33 | t.Fatal(err) |
| 34 | } |
| 35 | if !strings.Contains(result.Key, "/serving-evidence/") { |
| 36 | t.Fatalf("serving evidence entered operation namespace: %s", result.Key) |
| 37 | } |
| 38 | var receipt StopReceipt |
| 39 | if err := json.Unmarshal(result.Bytes, &receipt); err != nil { |
| 40 | t.Fatal(err) |
| 41 | } |
| 42 | if receipt.OperationID != "" || receipt.Phase != "" || receipt.ObligationID != "" || receipt.Region != req.Region { |
| 43 | t.Fatalf("serving receipt grants operation authority: %+v", receipt) |
| 44 | } |
| 45 | } |
| 46 | func TestClaimStopServingRefusesDifferentHolderScope(t *testing.T) { |
| 47 | for _, change := range []func(*StopRequest){func(r *StopRequest) { r.Region = "elsewhere" }, func(r *StopRequest) { r.Box = "other-box" }, func(r *StopRequest) { |
| 48 | r.OperationID = "invented" |
| 49 | r.Phase = "stop" |
| 50 | r.ObligationID = "invented-obligation" |
| 51 | }} { |
| 52 | c, req := servingStopFixture(t) |
| 53 | change(&req) |
| 54 | if _, err := c.FenceAndStop(t.Context(), req); err == nil { |
| 55 | t.Fatal("accepted wrong serving authority") |
| 56 | } |
| 57 | } |
| 58 | c, req := servingStopFixture(t) |
| 59 | req.WriterSession = 0 |
| 60 | // A holder past session zero never takes the no-process witness (R4). |
| 61 | if _, err := c.FenceAndStop(t.Context(), req); err == nil { |
| 62 | t.Fatal("a session-zero request stopped a holder at session 13") |
| 63 | } |
| 64 | } |
| 65 | |