package suite import ( "errors" "testing" ) // S3 is the ingest call: (id, revision), no person, team-visible only. func TestS3ReturnsBody(t *testing.T) { got, err := DecodeS3(200, []byte("the body")) if err != nil { t.Fatalf("unexpected error: %v", err) } if string(got) != "the body" { t.Errorf("got %q, want %q", got, "the body") } } // 404 is the whole vocabulary of refusal. Deleted, never team-visible, or // departed from team-visibility all answer the same way, so a consumer cannot // learn from a refusal that the item exists (§4.2). func TestS3NotFoundIsIndistinguishable(t *testing.T) { _, err := DecodeS3(404, nil) if !errors.Is(err, ErrNotAvailable) { t.Errorf("got %v, want ErrNotAvailable", err) } } // A 403 breaks the contract, and the client says so rather than folding it in // with 404. "404, never 403" is the rule (§4.2, §6) because 403 means "this // exists and you may not have it" — which is precisely the fact custody hides. // A sibling answering 403 has a bug that leaks, and quietly treating it as a // refusal would keep that bug invisible. func TestS3ForbiddenIsAContractBreach(t *testing.T) { _, err := DecodeS3(403, nil) // Positively, not just "some error": mutating this branch to a plain // fmt.Errorf passed the suite, which lost exactly the breach-versus-outage // distinction the sentinel exists to carry. if !errors.Is(err, ErrContractBreach) { t.Errorf("got %v, want ErrContractBreach", err) } if errors.Is(err, ErrNotAvailable) { t.Error("403 was folded into ErrNotAvailable; it must be distinguishable") } } // Any other non-2xx is a failed call, not a refusal. func TestS3ServerErrorIsNotARefusal(t *testing.T) { _, err := DecodeS3(503, nil) if err == nil { t.Fatal("got nil error for a 503, want a failure") } if errors.Is(err, ErrNotAvailable) { t.Error("503 was reported as a refusal; an outage is not an answer") } if errors.Is(err, ErrContractBreach) { t.Error("503 was reported as a contract breach; a sibling being down is not a sibling misbehaving") } }