| 1 | package suite |
| 2 | |
| 3 | import "testing" |
| 4 | |
| 5 | // Doctrine §3: the asker subject is typed on the wire, because its meaning is |
| 6 | // shape-dependent — a person ref in suite shape, a lowercased address in lone |
| 7 | // shape — and nothing else in an S2 or S6 call says which shape the pair is |
| 8 | // in. A kind the receiver does not key on must reach the caller as UNKNOWN, |
| 9 | // never as NOT_VISIBLE, which is the one value it may act on silently. |
| 10 | func TestSubjectRejectsUnknownKind(t *testing.T) { |
| 11 | _, err := NewSubject("employee_number", "4471") |
| 12 | |
| 13 | if err == nil { |
| 14 | t.Fatal("got nil error for an unknown subject kind, want a refusal") |
| 15 | } |
| 16 | } |
| 17 | |
| 18 | func TestSubjectRejectsEmptyValue(t *testing.T) { |
| 19 | _, err := NewSubject(SubjectAddress, "") |
| 20 | |
| 21 | if err == nil { |
| 22 | t.Fatal("got nil error for an empty subject value, want a refusal") |
| 23 | } |
| 24 | } |
| 25 | |
| 26 | // An address subject is lowercased, because that is what a lone instance keys |
| 27 | // its members on (§3). Sending "Ana@Example.com" to a receiver storing |
| 28 | // "ana@example.com" misses, and a miss answers NOT_VISIBLE — silently. |
| 29 | func TestSubjectLowercasesAddress(t *testing.T) { |
| 30 | s, err := NewSubject(SubjectAddress, "Ana@Example.COM") |
| 31 | if err != nil { |
| 32 | t.Fatalf("unexpected refusal: %v", err) |
| 33 | } |
| 34 | |
| 35 | if s.Value != "ana@example.com" { |
| 36 | t.Errorf("got %q, want %q", s.Value, "ana@example.com") |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | // A person ref is opaque and is not touched. It is the assertion's `sub` |
| 41 | // (home §5.3), and case may be significant in it. |
| 42 | func TestSubjectLeavesPersonRefAlone(t *testing.T) { |
| 43 | s, err := NewSubject(SubjectPersonRef, "PeRs_7Fa2") |
| 44 | if err != nil { |
| 45 | t.Fatalf("unexpected refusal: %v", err) |
| 46 | } |
| 47 | |
| 48 | if s.Value != "PeRs_7Fa2" { |
| 49 | t.Errorf("got %q, want the person ref unchanged", s.Value) |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | // §6 caps an S2 question at 256 pairs. Over the cap the batch is refused, not |
| 54 | // truncated: a silently shortened question produces a confident answer about |
| 55 | // items nobody asked about, and the missing ones would decode as UNKNOWN |
| 56 | // without anyone learning why. |
| 57 | // The numbers are literal, not derived from MaxS2Pairs. Deriving both sides |
| 58 | // from the constant tests the code's self-consistency and nothing else: |
| 59 | // changing the constant to 512 passed the entire suite. 256 is the doctrine's |
| 60 | // number, so 256 is what appears here. |
| 61 | func TestS2BatchOverCapIsRefused(t *testing.T) { |
| 62 | if err := CheckS2Batch(make([]ItemRevision, 257)); err == nil { |
| 63 | t.Fatal("got nil error for 257 pairs, want a refusal at the doctrine's cap of 256") |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | func TestS2BatchAtCapIsAccepted(t *testing.T) { |
| 68 | if err := CheckS2Batch(make([]ItemRevision, 256)); err != nil { |
| 69 | t.Errorf("got %v for 256 pairs, want it accepted", err) |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | // And the constant itself is the doctrine's, so a later edit to it fails here |
| 74 | // rather than quietly widening every caller's batch. |
| 75 | func TestS2CapIsTheDoctrinesNumber(t *testing.T) { |
| 76 | if MaxS2Pairs != 256 { |
| 77 | t.Errorf("MaxS2Pairs is %d, want 256 (doctrine §6, memoria §6.1)", MaxS2Pairs) |
| 78 | } |
| 79 | } |
| 80 | |