tinyrelayfile
tinyrelay/protocol/nostr/event_test.go/

protocol/nostr/event_test.go raw
1package nostr
2
3import (
4 "bytes"
5 "crypto/sha256"
6 "encoding/hex"
7 "encoding/json"
8 "strings"
9 "testing"
10)
11
12func TestSignParseValidateCanonical(t *testing.T) {
13 secret := strings.Repeat("0", 63) + "1"
14 e := Event{CreatedAt: 1, Kind: 1, Tags: [][]string{{"t", "go"}}, Content: "hello"}
15 if err := Sign(&e, secret); err != nil {
16 t.Fatalf("sign: %v", err)
17 }
18 if err := Validate(e); err != nil {
19 t.Fatalf("validate: %v", err)
20 }
21 got, err := Parse(mustJSON(t, e))
22 if err != nil {
23 t.Fatalf("parse: %v", err)
24 }
25 canonical, err := Canonical(e)
26 if err != nil {
27 t.Fatalf("canonical: %v", err)
28 }
29 if string(canonical) != string(mustJSON(t, got)) {
30 t.Fatalf("canonical changed event: %s", canonical)
31 }
32}
33
34func TestFilterTagJSONAndEmptyLists(t *testing.T) {
35 f, err := ParseFilter([]byte(`{"#t":["go"],"kinds":[],"limit":0}`))
36 if err != nil {
37 t.Fatalf("parse filter: %v", err)
38 }
39 if len(f.Tags["t"]) != 1 || len(f.Kinds) != 0 || f.Kinds == nil {
40 t.Fatalf("filter fields lost: %#v", f)
41 }
42 e := Event{ID: strings.Repeat("a", 64), PubKey: strings.Repeat("b", 64), Kind: 1, Tags: [][]string{{"t", "go"}}}
43 if Matches(f, e) {
44 t.Fatal("empty kinds must match nothing")
45 }
46 f.Kinds = nil
47 if !Matches(f, e) {
48 t.Fatal("tag filter should match")
49 }
50 raw, err := json.Marshal(f)
51 if err != nil || !strings.Contains(string(raw), `"#t"`) {
52 t.Fatalf("marshal tags: %s (%v)", raw, err)
53 }
54}
55
56func TestSearchTermsAndKinds(t *testing.T) {
57 terms := SearchTerms("hello lang:en world:")
58 if len(terms) != 1 || terms[0] != "hello" {
59 t.Fatalf("terms: %#v", terms)
60 }
61 if !IsEphemeral(20001) || IsEphemeral(30000) || !IsReplaceable(10001) || !IsAddressable(30001) {
62 t.Fatal("kind classification mismatch")
63 }
64}
65
66func TestNIP01CanonicalEscapingMatchesJSONStringify(t *testing.T) {
67 e := Event{CreatedAt: 1700000000, Kind: 1, Tags: [][]string{{"x", "a\b\f\u2028\u2029é"}}, Content: "quote \" slash \\ newline\n <tag>"}
68 got, err := serializeForID(e)
69 if err != nil {
70 t.Fatal(err)
71 }
72 if bytes.Contains(got, []byte(`\u003c`)) || !bytes.Contains(got, []byte(`\b`)) || !bytes.Contains(got, []byte(`\f`)) {
73 t.Fatalf("unexpected HTML/control escaping: %s", got)
74 }
75 if strings.Contains(string(got), `\u2028`) || strings.Contains(string(got), `\u2029`) {
76 t.Fatalf("U+2028/U+2029 must remain literal like JSON.stringify: %s", got)
77 }
78}
79
80func TestParseRequiresEveryWireField(t *testing.T) {
81 e := Event{CreatedAt: 1, Kind: 1, Tags: [][]string{}, Content: ""}
82 if err := Sign(&e, strings.Repeat("0", 63)+"1"); err != nil {
83 t.Fatal(err)
84 }
85 raw, err := json.Marshal(e)
86 if err != nil {
87 t.Fatal(err)
88 }
89 for _, field := range []string{"id", "pubkey", "created_at", "kind", "tags", "content", "sig"} {
90 var values map[string]json.RawMessage
91 if err := json.Unmarshal(raw, &values); err != nil {
92 t.Fatal(err)
93 }
94 delete(values, field)
95 missing, err := json.Marshal(values)
96 if err != nil {
97 t.Fatal(err)
98 }
99 if _, err := Parse(missing); err == nil {
100 t.Errorf("missing %s accepted", field)
101 }
102 }
103}
104
105func TestNIP01IDIsSHA256OfCanonicalArray(t *testing.T) {
106 e := Event{CreatedAt: 1, Kind: 1, Tags: [][]string{}, Content: "hello"}
107 if err := Sign(&e, strings.Repeat("0", 63)+"1"); err != nil {
108 t.Fatal(err)
109 }
110 serialized, err := serializeForID(e)
111 if err != nil {
112 t.Fatal(err)
113 }
114 sum := sha256.Sum256(serialized)
115 if e.ID != hex.EncodeToString(sum[:]) {
116 t.Fatalf("id %s does not hash canonical array %x", e.ID, sum)
117 }
118}
119
120func mustJSON(t *testing.T, value any) []byte {
121 t.Helper()
122 b, err := json.Marshal(value)
123 if err != nil {
124 t.Fatalf("marshal: %v", err)
125 }
126 return b
127}

About

ownerc01503e8035f
visibilitypublic
headd730679639bf

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs