store_interface_test.go raw
1 package store
2
3 import (
4 "bytes"
5 "testing"
6
7 ntypes "next.orly.dev/pkg/nostr/types"
8 )
9
10 func TestNewIdPkTs(t *testing.T) {
11 // Create sample data
12 id := make([]byte, 32)
13 pub := make([]byte, 32)
14 for i := 0; i < 32; i++ {
15 id[i] = byte(i)
16 pub[i] = byte(i + 32)
17 }
18
19 ipk := NewIdPkTs(id, pub, 1234567890, 42)
20
21 // Test that data was copied correctly
22 if !bytes.Equal(ipk.Id[:], id) {
23 t.Errorf("Id: got %x, want %x", ipk.Id[:], id)
24 }
25 if !bytes.Equal(ipk.Pub[:], pub) {
26 t.Errorf("Pub: got %x, want %x", ipk.Pub[:], pub)
27 }
28 if ipk.Ts != 1234567890 {
29 t.Errorf("Ts: got %d, want 1234567890", ipk.Ts)
30 }
31 if ipk.Ser != 42 {
32 t.Errorf("Ser: got %d, want 42", ipk.Ser)
33 }
34
35 // Test that Id is a copy (modifying original doesn't affect struct)
36 id[0] = 0xFF
37 if ipk.Id[0] == 0xFF {
38 t.Error("NewIdPkTs should copy data, not reference")
39 }
40 }
41
42 func TestIdPkTsSliceMethods(t *testing.T) {
43 id := make([]byte, 32)
44 pub := make([]byte, 32)
45 for i := 0; i < 32; i++ {
46 id[i] = byte(i)
47 pub[i] = byte(i + 32)
48 }
49
50 ipk := NewIdPkTs(id, pub, 1234567890, 42)
51
52 // Test IDSlice returns correct data
53 idSlice := ipk.IDSlice()
54 if !bytes.Equal(idSlice, id) {
55 t.Errorf("IDSlice: got %x, want %x", idSlice, id)
56 }
57
58 // Test PubSlice returns correct data
59 pubSlice := ipk.PubSlice()
60 if !bytes.Equal(pubSlice, pub) {
61 t.Errorf("PubSlice: got %x, want %x", pubSlice, pub)
62 }
63
64 // Test hex methods
65 idHex := ipk.IDHex()
66 expectedIDHex := "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
67 if idHex != expectedIDHex {
68 t.Errorf("IDHex: got %s, want %s", idHex, expectedIDHex)
69 }
70 }
71
72 func TestIdPkTsCopyOnAssignment(t *testing.T) {
73 id := make([]byte, 32)
74 pub := make([]byte, 32)
75 for i := 0; i < 32; i++ {
76 id[i] = byte(i)
77 pub[i] = byte(i + 32)
78 }
79
80 ipk1 := NewIdPkTs(id, pub, 1234567890, 42)
81 ipk2 := ipk1 // Copy
82
83 // Modify the copy
84 ipk2.Id[0] = 0xFF
85
86 // Original should be unchanged (arrays are copied on assignment)
87 if ipk1.Id[0] == 0xFF {
88 t.Error("IdPkTs should copy on assignment")
89 }
90 }
91
92 func TestEventRef(t *testing.T) {
93 id := make([]byte, 32)
94 pub := make([]byte, 32)
95 for i := 0; i < 32; i++ {
96 id[i] = byte(i)
97 pub[i] = byte(i + 100)
98 }
99
100 // Create EventRef
101 ref := NewEventRef(id, pub, 1234567890, 42)
102
103 // Test accessors - need to get addressable values for slicing
104 refID := ref.ID()
105 refPub := ref.Pub()
106 if !bytes.Equal(refID[:], id) {
107 t.Error("ID() mismatch")
108 }
109 if !bytes.Equal(refPub[:], pub) {
110 t.Error("Pub() mismatch")
111 }
112 if ref.Ts() != 1234567890 {
113 t.Error("Ts() mismatch")
114 }
115 if ref.Ser() != 42 {
116 t.Error("Ser() mismatch")
117 }
118
119 // Test copy-on-assignment
120 ref2 := ref
121 testID := ref.ID()
122 testID[0] = 0xFF
123 ref2ID := ref2.ID()
124 if ref2ID[0] == 0xFF {
125 t.Error("EventRef should copy on assignment")
126 }
127
128 // Test hex methods
129 if len(ref.IDHex()) != 64 {
130 t.Errorf("IDHex length: got %d, want 64", len(ref.IDHex()))
131 }
132 }
133
134 func TestEventRefToIdPkTs(t *testing.T) {
135 id := make([]byte, 32)
136 pub := make([]byte, 32)
137 for i := 0; i < 32; i++ {
138 id[i] = byte(i)
139 pub[i] = byte(i + 100)
140 }
141
142 ref := NewEventRef(id, pub, 1234567890, 42)
143 ipk := ref.ToIdPkTs()
144
145 // Verify conversion
146 if !bytes.Equal(ipk.Id[:], id) {
147 t.Error("ToIdPkTs: Id mismatch")
148 }
149 if !bytes.Equal(ipk.Pub[:], pub) {
150 t.Error("ToIdPkTs: Pub mismatch")
151 }
152 if ipk.Ts != 1234567890 {
153 t.Error("ToIdPkTs: Ts mismatch")
154 }
155 if ipk.Ser != 42 {
156 t.Error("ToIdPkTs: Ser mismatch")
157 }
158
159 // Verify independence (modifications don't affect original)
160 ipk.Id[0] = 0xFF
161 if ref.ID()[0] == 0xFF {
162 t.Error("ToIdPkTs should create independent copy")
163 }
164 }
165
166 func TestIdPkTsToEventRef(t *testing.T) {
167 id := make([]byte, 32)
168 pub := make([]byte, 32)
169 for i := 0; i < 32; i++ {
170 id[i] = byte(i)
171 pub[i] = byte(i + 100)
172 }
173
174 ipk := NewIdPkTs(id, pub, 1234567890, 42)
175 ref := ipk.ToEventRef()
176
177 // Verify conversion - need addressable values for slicing
178 refID := ref.ID()
179 refPub := ref.Pub()
180 if !bytes.Equal(refID[:], id) {
181 t.Error("ToEventRef: ID mismatch")
182 }
183 if !bytes.Equal(refPub[:], pub) {
184 t.Error("ToEventRef: Pub mismatch")
185 }
186 if ref.Ts() != 1234567890 {
187 t.Error("ToEventRef: Ts mismatch")
188 }
189 if ref.Ser() != 42 {
190 t.Error("ToEventRef: Ser mismatch")
191 }
192 }
193
194 func BenchmarkIdPkTsCopy(b *testing.B) {
195 id := make([]byte, 32)
196 pub := make([]byte, 32)
197 for i := 0; i < 32; i++ {
198 id[i] = byte(i)
199 pub[i] = byte(i + 100)
200 }
201
202 ipk := NewIdPkTs(id, pub, 1234567890, 42)
203
204 b.ResetTimer()
205 for i := 0; i < b.N; i++ {
206 ipk2 := ipk // Copy (should stay on stack)
207 _ = ipk2
208 }
209 }
210
211 func BenchmarkEventRefCopy(b *testing.B) {
212 id := make([]byte, 32)
213 pub := make([]byte, 32)
214 for i := 0; i < 32; i++ {
215 id[i] = byte(i)
216 pub[i] = byte(i + 100)
217 }
218
219 ref := NewEventRef(id, pub, 1234567890, 42)
220
221 b.ResetTimer()
222 for i := 0; i < b.N; i++ {
223 ref2 := ref // Copy (should stay on stack)
224 _ = ref2
225 }
226 }
227
228 func BenchmarkIdPkTsToEventRef(b *testing.B) {
229 id := make([]byte, 32)
230 pub := make([]byte, 32)
231 for i := 0; i < 32; i++ {
232 id[i] = byte(i)
233 pub[i] = byte(i + 100)
234 }
235
236 ipk := NewIdPkTs(id, pub, 1234567890, 42)
237
238 b.ResetTimer()
239 for i := 0; i < b.N; i++ {
240 ref := ipk.ToEventRef()
241 _ = ref
242 }
243 }
244
245 func BenchmarkEventRefAccess(b *testing.B) {
246 id := make([]byte, 32)
247 pub := make([]byte, 32)
248 for i := 0; i < 32; i++ {
249 id[i] = byte(i)
250 pub[i] = byte(i + 100)
251 }
252
253 ref := NewEventRef(id, pub, 1234567890, 42)
254
255 b.ResetTimer()
256 for i := 0; i < b.N; i++ {
257 idCopy := ref.ID()
258 pubCopy := ref.Pub()
259 _ = idCopy
260 _ = pubCopy
261 }
262 }
263
264 func BenchmarkIdPkTsAccess(b *testing.B) {
265 id := make([]byte, 32)
266 pub := make([]byte, 32)
267 for i := 0; i < 32; i++ {
268 id[i] = byte(i)
269 pub[i] = byte(i + 100)
270 }
271
272 ipk := NewIdPkTs(id, pub, 1234567890, 42)
273
274 b.ResetTimer()
275 for i := 0; i < b.N; i++ {
276 idCopy := ipk.Id
277 pubCopy := ipk.Pub
278 _ = idCopy
279 _ = pubCopy
280 }
281 }
282
283 // Ensure types satisfy expected size for stack allocation
284 func TestStructSizes(t *testing.T) {
285 var ipk IdPkTs
286 var ref EventRef
287
288 // Both should be exactly 80 bytes (32+32+8+8)
289 // This is not directly testable in Go, but we can verify the fields exist
290 _ = ipk.Id
291 _ = ipk.Pub
292 _ = ipk.Ts
293 _ = ipk.Ser
294 _ = ref
295 }
296
297 // Ensure ntypes.EventID and ntypes.Pubkey are used correctly
298 func TestNtypesCompatibility(t *testing.T) {
299 var id ntypes.EventID
300 var pub ntypes.Pubkey
301
302 // Fill with test data
303 for i := 0; i < 32; i++ {
304 id[i] = byte(i)
305 pub[i] = byte(i + 32)
306 }
307
308 // Create IdPkTs directly with ntypes
309 ipk := IdPkTs{
310 Id: id,
311 Pub: pub,
312 Ts: 1234567890,
313 Ser: 42,
314 }
315
316 // Verify
317 if ipk.Id != id {
318 t.Error("ntypes.EventID should be directly assignable to IdPkTs.Id")
319 }
320 if ipk.Pub != pub {
321 t.Error("ntypes.Pubkey should be directly assignable to IdPkTs.Pub")
322 }
323 }
324