summaryrefslogtreecommitdiffstats
path: root/internal/nostr/envelope_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/nostr/envelope_test.go')
-rw-r--r--internal/nostr/envelope_test.go416
1 files changed, 416 insertions, 0 deletions
diff --git a/internal/nostr/envelope_test.go b/internal/nostr/envelope_test.go
new file mode 100644
index 0000000..8f79ad5
--- /dev/null
+++ b/internal/nostr/envelope_test.go
@@ -0,0 +1,416 @@
1package nostr
2
3import (
4 "encoding/json"
5 "testing"
6)
7
8func TestEventEnvelopeMarshalJSON(t *testing.T) {
9 event := &Event{
10 ID: "abc123",
11 PubKey: "def456",
12 CreatedAt: 1704067200,
13 Kind: 1,
14 Tags: Tags{},
15 Content: "Hello",
16 Sig: "sig789",
17 }
18
19 t.Run("client to relay", func(t *testing.T) {
20 env := EventEnvelope{Event: event}
21 data, err := env.MarshalJSON()
22 if err != nil {
23 t.Fatalf("MarshalJSON() error = %v", err)
24 }
25
26 var arr []json.RawMessage
27 if err := json.Unmarshal(data, &arr); err != nil {
28 t.Fatalf("Invalid JSON: %v", err)
29 }
30
31 if len(arr) != 2 {
32 t.Errorf("Array length = %d, want 2", len(arr))
33 }
34
35 var label string
36 json.Unmarshal(arr[0], &label)
37 if label != "EVENT" {
38 t.Errorf("Label = %s, want EVENT", label)
39 }
40 })
41
42 t.Run("relay to client", func(t *testing.T) {
43 env := EventEnvelope{SubscriptionID: "sub1", Event: event}
44 data, err := env.MarshalJSON()
45 if err != nil {
46 t.Fatalf("MarshalJSON() error = %v", err)
47 }
48
49 var arr []json.RawMessage
50 if err := json.Unmarshal(data, &arr); err != nil {
51 t.Fatalf("Invalid JSON: %v", err)
52 }
53
54 if len(arr) != 3 {
55 t.Errorf("Array length = %d, want 3", len(arr))
56 }
57 })
58}
59
60func TestReqEnvelopeMarshalJSON(t *testing.T) {
61 env := ReqEnvelope{
62 SubscriptionID: "sub1",
63 Filters: []Filter{
64 {Kinds: []int{1}},
65 {Authors: []string{"abc123"}},
66 },
67 }
68
69 data, err := env.MarshalJSON()
70 if err != nil {
71 t.Fatalf("MarshalJSON() error = %v", err)
72 }
73
74 var arr []json.RawMessage
75 if err := json.Unmarshal(data, &arr); err != nil {
76 t.Fatalf("Invalid JSON: %v", err)
77 }
78
79 if len(arr) != 4 { // ["REQ", "sub1", filter1, filter2]
80 t.Errorf("Array length = %d, want 4", len(arr))
81 }
82
83 var label string
84 json.Unmarshal(arr[0], &label)
85 if label != "REQ" {
86 t.Errorf("Label = %s, want REQ", label)
87 }
88
89 var subID string
90 json.Unmarshal(arr[1], &subID)
91 if subID != "sub1" {
92 t.Errorf("SubscriptionID = %s, want sub1", subID)
93 }
94}
95
96func TestCloseEnvelopeMarshalJSON(t *testing.T) {
97 env := CloseEnvelope{SubscriptionID: "sub1"}
98 data, err := env.MarshalJSON()
99 if err != nil {
100 t.Fatalf("MarshalJSON() error = %v", err)
101 }
102
103 var arr []interface{}
104 if err := json.Unmarshal(data, &arr); err != nil {
105 t.Fatalf("Invalid JSON: %v", err)
106 }
107
108 if len(arr) != 2 {
109 t.Errorf("Array length = %d, want 2", len(arr))
110 }
111 if arr[0] != "CLOSE" {
112 t.Errorf("Label = %v, want CLOSE", arr[0])
113 }
114 if arr[1] != "sub1" {
115 t.Errorf("SubscriptionID = %v, want sub1", arr[1])
116 }
117}
118
119func TestOKEnvelopeMarshalJSON(t *testing.T) {
120 env := OKEnvelope{
121 EventID: "event123",
122 OK: true,
123 Message: "accepted",
124 }
125
126 data, err := env.MarshalJSON()
127 if err != nil {
128 t.Fatalf("MarshalJSON() error = %v", err)
129 }
130
131 var arr []interface{}
132 if err := json.Unmarshal(data, &arr); err != nil {
133 t.Fatalf("Invalid JSON: %v", err)
134 }
135
136 if len(arr) != 4 {
137 t.Errorf("Array length = %d, want 4", len(arr))
138 }
139 if arr[0] != "OK" {
140 t.Errorf("Label = %v, want OK", arr[0])
141 }
142 if arr[1] != "event123" {
143 t.Errorf("EventID = %v, want event123", arr[1])
144 }
145 if arr[2] != true {
146 t.Errorf("OK = %v, want true", arr[2])
147 }
148 if arr[3] != "accepted" {
149 t.Errorf("Message = %v, want accepted", arr[3])
150 }
151}
152
153func TestEOSEEnvelopeMarshalJSON(t *testing.T) {
154 env := EOSEEnvelope{SubscriptionID: "sub1"}
155 data, err := env.MarshalJSON()
156 if err != nil {
157 t.Fatalf("MarshalJSON() error = %v", err)
158 }
159
160 var arr []interface{}
161 if err := json.Unmarshal(data, &arr); err != nil {
162 t.Fatalf("Invalid JSON: %v", err)
163 }
164
165 if len(arr) != 2 {
166 t.Errorf("Array length = %d, want 2", len(arr))
167 }
168 if arr[0] != "EOSE" {
169 t.Errorf("Label = %v, want EOSE", arr[0])
170 }
171}
172
173func TestClosedEnvelopeMarshalJSON(t *testing.T) {
174 env := ClosedEnvelope{
175 SubscriptionID: "sub1",
176 Message: "rate limited",
177 }
178
179 data, err := env.MarshalJSON()
180 if err != nil {
181 t.Fatalf("MarshalJSON() error = %v", err)
182 }
183
184 var arr []interface{}
185 if err := json.Unmarshal(data, &arr); err != nil {
186 t.Fatalf("Invalid JSON: %v", err)
187 }
188
189 if len(arr) != 3 {
190 t.Errorf("Array length = %d, want 3", len(arr))
191 }
192 if arr[0] != "CLOSED" {
193 t.Errorf("Label = %v, want CLOSED", arr[0])
194 }
195}
196
197func TestNoticeEnvelopeMarshalJSON(t *testing.T) {
198 env := NoticeEnvelope{Message: "error: rate limited"}
199 data, err := env.MarshalJSON()
200 if err != nil {
201 t.Fatalf("MarshalJSON() error = %v", err)
202 }
203
204 var arr []interface{}
205 if err := json.Unmarshal(data, &arr); err != nil {
206 t.Fatalf("Invalid JSON: %v", err)
207 }
208
209 if len(arr) != 2 {
210 t.Errorf("Array length = %d, want 2", len(arr))
211 }
212 if arr[0] != "NOTICE" {
213 t.Errorf("Label = %v, want NOTICE", arr[0])
214 }
215}
216
217func TestParseEnvelopeEvent(t *testing.T) {
218 t.Run("client to relay", func(t *testing.T) {
219 data := `["EVENT",{"id":"abc123","pubkey":"def456","created_at":1704067200,"kind":1,"tags":[],"content":"Hello","sig":"sig789"}]`
220 env, err := ParseEnvelope([]byte(data))
221 if err != nil {
222 t.Fatalf("ParseEnvelope() error = %v", err)
223 }
224
225 eventEnv, ok := env.(*EventEnvelope)
226 if !ok {
227 t.Fatalf("Expected *EventEnvelope, got %T", env)
228 }
229
230 if eventEnv.SubscriptionID != "" {
231 t.Errorf("SubscriptionID = %s, want empty", eventEnv.SubscriptionID)
232 }
233 if eventEnv.Event.ID != "abc123" {
234 t.Errorf("Event.ID = %s, want abc123", eventEnv.Event.ID)
235 }
236 })
237
238 t.Run("relay to client", func(t *testing.T) {
239 data := `["EVENT","sub1",{"id":"abc123","pubkey":"def456","created_at":1704067200,"kind":1,"tags":[],"content":"Hello","sig":"sig789"}]`
240 env, err := ParseEnvelope([]byte(data))
241 if err != nil {
242 t.Fatalf("ParseEnvelope() error = %v", err)
243 }
244
245 eventEnv, ok := env.(*EventEnvelope)
246 if !ok {
247 t.Fatalf("Expected *EventEnvelope, got %T", env)
248 }
249
250 if eventEnv.SubscriptionID != "sub1" {
251 t.Errorf("SubscriptionID = %s, want sub1", eventEnv.SubscriptionID)
252 }
253 })
254}
255
256func TestParseEnvelopeReq(t *testing.T) {
257 data := `["REQ","sub1",{"kinds":[1]},{"authors":["abc123"]}]`
258 env, err := ParseEnvelope([]byte(data))
259 if err != nil {
260 t.Fatalf("ParseEnvelope() error = %v", err)
261 }
262
263 reqEnv, ok := env.(*ReqEnvelope)
264 if !ok {
265 t.Fatalf("Expected *ReqEnvelope, got %T", env)
266 }
267
268 if reqEnv.SubscriptionID != "sub1" {
269 t.Errorf("SubscriptionID = %s, want sub1", reqEnv.SubscriptionID)
270 }
271 if len(reqEnv.Filters) != 2 {
272 t.Errorf("Filters length = %d, want 2", len(reqEnv.Filters))
273 }
274}
275
276func TestParseEnvelopeClose(t *testing.T) {
277 data := `["CLOSE","sub1"]`
278 env, err := ParseEnvelope([]byte(data))
279 if err != nil {
280 t.Fatalf("ParseEnvelope() error = %v", err)
281 }
282
283 closeEnv, ok := env.(*CloseEnvelope)
284 if !ok {
285 t.Fatalf("Expected *CloseEnvelope, got %T", env)
286 }
287
288 if closeEnv.SubscriptionID != "sub1" {
289 t.Errorf("SubscriptionID = %s, want sub1", closeEnv.SubscriptionID)
290 }
291}
292
293func TestParseEnvelopeOK(t *testing.T) {
294 data := `["OK","event123",true,"accepted"]`
295 env, err := ParseEnvelope([]byte(data))
296 if err != nil {
297 t.Fatalf("ParseEnvelope() error = %v", err)
298 }
299
300 okEnv, ok := env.(*OKEnvelope)
301 if !ok {
302 t.Fatalf("Expected *OKEnvelope, got %T", env)
303 }
304
305 if okEnv.EventID != "event123" {
306 t.Errorf("EventID = %s, want event123", okEnv.EventID)
307 }
308 if !okEnv.OK {
309 t.Error("OK = false, want true")
310 }
311 if okEnv.Message != "accepted" {
312 t.Errorf("Message = %s, want accepted", okEnv.Message)
313 }
314}
315
316func TestParseEnvelopeEOSE(t *testing.T) {
317 data := `["EOSE","sub1"]`
318 env, err := ParseEnvelope([]byte(data))
319 if err != nil {
320 t.Fatalf("ParseEnvelope() error = %v", err)
321 }
322
323 eoseEnv, ok := env.(*EOSEEnvelope)
324 if !ok {
325 t.Fatalf("Expected *EOSEEnvelope, got %T", env)
326 }
327
328 if eoseEnv.SubscriptionID != "sub1" {
329 t.Errorf("SubscriptionID = %s, want sub1", eoseEnv.SubscriptionID)
330 }
331}
332
333func TestParseEnvelopeClosed(t *testing.T) {
334 data := `["CLOSED","sub1","rate limited"]`
335 env, err := ParseEnvelope([]byte(data))
336 if err != nil {
337 t.Fatalf("ParseEnvelope() error = %v", err)
338 }
339
340 closedEnv, ok := env.(*ClosedEnvelope)
341 if !ok {
342 t.Fatalf("Expected *ClosedEnvelope, got %T", env)
343 }
344
345 if closedEnv.SubscriptionID != "sub1" {
346 t.Errorf("SubscriptionID = %s, want sub1", closedEnv.SubscriptionID)
347 }
348 if closedEnv.Message != "rate limited" {
349 t.Errorf("Message = %s, want rate limited", closedEnv.Message)
350 }
351}
352
353func TestParseEnvelopeNotice(t *testing.T) {
354 data := `["NOTICE","error: rate limited"]`
355 env, err := ParseEnvelope([]byte(data))
356 if err != nil {
357 t.Fatalf("ParseEnvelope() error = %v", err)
358 }
359
360 noticeEnv, ok := env.(*NoticeEnvelope)
361 if !ok {
362 t.Fatalf("Expected *NoticeEnvelope, got %T", env)
363 }
364
365 if noticeEnv.Message != "error: rate limited" {
366 t.Errorf("Message = %s, want 'error: rate limited'", noticeEnv.Message)
367 }
368}
369
370func TestParseEnvelopeErrors(t *testing.T) {
371 tests := []struct {
372 name string
373 data string
374 }{
375 {"invalid json", "not json"},
376 {"not array", `{"type":"EVENT"}`},
377 {"empty array", `[]`},
378 {"single element", `["EVENT"]`},
379 {"unknown type", `["UNKNOWN","data"]`},
380 {"invalid event length", `["EVENT","a","b","c"]`},
381 {"invalid ok length", `["OK","id",true]`},
382 {"invalid eose length", `["EOSE"]`},
383 }
384
385 for _, tt := range tests {
386 t.Run(tt.name, func(t *testing.T) {
387 _, err := ParseEnvelope([]byte(tt.data))
388 if err == nil {
389 t.Error("ParseEnvelope() expected error, got nil")
390 }
391 })
392 }
393}
394
395func TestEnvelopeLabel(t *testing.T) {
396 tests := []struct {
397 env Envelope
398 label string
399 }{
400 {EventEnvelope{}, "EVENT"},
401 {ReqEnvelope{}, "REQ"},
402 {CloseEnvelope{}, "CLOSE"},
403 {OKEnvelope{}, "OK"},
404 {EOSEEnvelope{}, "EOSE"},
405 {ClosedEnvelope{}, "CLOSED"},
406 {NoticeEnvelope{}, "NOTICE"},
407 }
408
409 for _, tt := range tests {
410 t.Run(tt.label, func(t *testing.T) {
411 if got := tt.env.Label(); got != tt.label {
412 t.Errorf("Label() = %s, want %s", got, tt.label)
413 }
414 })
415 }
416}