serial_test.mx raw
1 package serial
2
3 import (
4 "bytes"
5 "crypto/sha256"
6 "testing"
7 )
8
9 // TestPutGetRoundTrip pins the 5-byte big-endian encoding: every byte position
10 // matters because index keys are byte-compared by the sorted file.
11 func TestPutGetRoundTrip(t *testing.T) {
12 vals := []uint64{0, 1, 255, 256, 65535, 1 << 32, Max - 1, Max}
13 for _, v := range vals {
14 buf := []byte{:Len}
15 Put(buf, v)
16 if got := Get(buf); got != v {
17 t.Fatalf("Get(Put(%d)) = %d", v, got)
18 }
19 }
20 }
21
22 func TestPutByteLayout(t *testing.T) {
23 buf := []byte{:Len}
24 Put(buf, 0x0102030405)
25 want := []byte{0x01, 0x02, 0x03, 0x04, 0x05}
26 if !bytes.Equal(buf, want) {
27 t.Fatal("Put byte order")
28 }
29 Put(buf, 0)
30 if !bytes.Equal(buf, []byte{0, 0, 0, 0, 0}) {
31 t.Fatal("Put zero")
32 }
33 Put(buf, Max)
34 if !bytes.Equal(buf, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) {
35 t.Fatal("Put Max")
36 }
37 }
38
39 func TestGetReadsEveryByte(t *testing.T) {
40 // One bit per byte position: a decode that drops a shift reads wrong here.
41 if Get([]byte{1, 0, 0, 0, 0}) != 1<<32 {
42 t.Fatal("byte 0 shift")
43 }
44 if Get([]byte{0, 1, 0, 0, 0}) != 1<<24 {
45 t.Fatal("byte 1 shift")
46 }
47 if Get([]byte{0, 0, 1, 0, 0}) != 1<<16 {
48 t.Fatal("byte 2 shift")
49 }
50 if Get([]byte{0, 0, 0, 1, 0}) != 1<<8 {
51 t.Fatal("byte 3 shift")
52 }
53 if Get([]byte{0, 0, 0, 0, 1}) != 1 {
54 t.Fatal("byte 4 shift")
55 }
56 }
57
58 func TestAppend(t *testing.T) {
59 dst := Append([]byte("ab"), 0x0102030405)
60 want := []byte("ab\x01\x02\x03\x04\x05")
61 if !bytes.Equal(dst, want) {
62 t.Fatalf("Append = %x", dst)
63 }
64 only := Append(nil, 0)
65 if len(only) != Len {
66 t.Fatalf("Append(nil) len = %d", len(only))
67 }
68 if Get(only) != 0 {
69 t.Fatal("Append(nil) value")
70 }
71 // Two appends stack.
72 two := Append(Append(nil, 1), 2)
73 if len(two) != 2*Len {
74 t.Fatalf("two appends len = %d", len(two))
75 }
76 if Get(two[:Len]) != 1 || Get(two[Len:]) != 2 {
77 t.Fatal("two appends value")
78 }
79 }
80
81 // TestHashHelpers pins length, determinism and the exact sha256 prefix, since
82 // the engine compares these hashes as index keys.
83 func TestHashHelpers(t *testing.T) {
84 in := []byte("the quick brown fox")
85 sum := sha256.Sum256(in)
86
87 ih := IdHash(in)
88 if len(ih) != HashLen {
89 t.Fatalf("IdHash len = %d", len(ih))
90 }
91 if !bytes.Equal(ih, sum[:HashLen]) {
92 t.Fatal("IdHash is not the sha256 prefix")
93 }
94 if !bytes.Equal(IdHash(in), ih) {
95 t.Fatal("IdHash not deterministic")
96 }
97 if bytes.Equal(IdHash(in), IdHash([]byte("the quick brown fo"))) {
98 t.Fatal("IdHash collision on near input")
99 }
100
101 ph := PubHash(in)
102 if len(ph) != HashLen || !bytes.Equal(ph, sum[:HashLen]) {
103 t.Fatal("PubHash is not the sha256 prefix")
104 }
105 // Same input, same bytes: the three helpers are all truncated sha256.
106 if !bytes.Equal(ph, ih) {
107 t.Fatal("IdHash and PubHash differ for the same input")
108 }
109
110 ihash := Ident(in)
111 if len(ihash) != HashLen || !bytes.Equal(ihash, sum[:HashLen]) {
112 t.Fatal("Ident is not the sha256 prefix")
113 }
114 zeroSum := sha256.Sum256(nil)
115 if !bytes.Equal(Ident(nil), zeroSum[:HashLen]) {
116 t.Fatal("Ident(nil)")
117 }
118 if len(Ident(nil)) != HashLen {
119 t.Fatal("Ident(nil) length")
120 }
121 }
122
123 func TestTimestampRoundTrip(t *testing.T) {
124 vals := []int64{0, 1, -1, 1700000000, 1 << 40, -1700000000}
125 for _, v := range vals {
126 buf := []byte{:8}
127 PutTimestamp(buf, v)
128 if got := GetTimestamp(buf); got != v {
129 t.Fatalf("GetTimestamp(PutTimestamp(%d)) = %d", v, got)
130 }
131 }
132 }
133
134 func TestTimestampByteLayout(t *testing.T) {
135 buf := []byte{:8}
136 PutTimestamp(buf, 0x0102030405060708)
137 want := []byte{1, 2, 3, 4, 5, 6, 7, 8}
138 if !bytes.Equal(buf, want) {
139 t.Fatalf("PutTimestamp = %x", buf)
140 }
141 // -1 is all ones, so a signed cast that clamps would fail here.
142 PutTimestamp(buf, -1)
143 if !bytes.Equal(buf, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) {
144 t.Fatal("PutTimestamp(-1)")
145 }
146 }
147
148 func TestAppendTimestamp(t *testing.T) {
149 out := AppendTimestamp([]byte("x"), 0x0102030405060708)
150 if len(out) != 9 {
151 t.Fatalf("AppendTimestamp len = %d", len(out))
152 }
153 if out[0] != 'x' {
154 t.Fatal("AppendTimestamp clobbered dst")
155 }
156 if GetTimestamp(out[1:]) != 0x0102030405060708 {
157 t.Fatal("AppendTimestamp payload")
158 }
159 }
160
161 func TestKindRoundTrip(t *testing.T) {
162 vals := []uint16{0, 1, 7, 255, 256, 30023, 65535}
163 for _, v := range vals {
164 buf := []byte{:2}
165 PutKind(buf, v)
166 if got := GetKind(buf); got != v {
167 t.Fatalf("GetKind(PutKind(%d)) = %d", v, got)
168 }
169 }
170 kbuf := []byte{:2}
171 PutKind(kbuf, 0xABCD)
172 if !bytes.Equal(kbuf, []byte{0xAB, 0xCD}) {
173 t.Fatalf("PutKind = %x", kbuf)
174 }
175 }
176
177 func TestAppendKind(t *testing.T) {
178 out := AppendKind([]byte("k"), 7)
179 if !bytes.Equal(out, []byte{'k', 0, 7}) {
180 t.Fatalf("AppendKind = %x", out)
181 }
182 if len(AppendKind(nil, 0)) != 2 {
183 t.Fatal("AppendKind(nil) length")
184 }
185 if GetKind(AppendKind(nil, 30023)) != 30023 {
186 t.Fatal("AppendKind payload")
187 }
188 }
189