2025-03-12 00:17:01 -03:00
//go:build sonic
2023-05-09 16:31:10 -03:00
package nostr
import (
2025-03-07 15:50:55 -03:00
"bufio"
"os"
2023-05-09 16:31:10 -03:00
"testing"
2024-09-09 13:50:56 +03:30
2025-02-25 17:57:15 -03:00
"github.com/stretchr/testify/require"
2023-05-09 16:31:10 -03:00
)
2023-06-20 14:05:57 +02:00
func TestParseMessage ( t * testing . T ) {
testCases := [ ] struct {
Name string
2025-03-12 00:17:01 -03:00
Message string
2023-12-09 11:29:14 -03:00
ExpectedEnvelope Envelope
2023-06-20 14:05:57 +02:00
} {
{
Name : "nil" ,
2025-03-12 00:17:01 -03:00
Message : "" ,
2023-06-20 14:05:57 +02:00
ExpectedEnvelope : nil ,
} ,
{
Name : "invalid string" ,
2025-03-12 00:17:01 -03:00
Message : "invalid input" ,
2023-06-20 14:05:57 +02:00
ExpectedEnvelope : nil ,
} ,
{
Name : "invalid string with a comma" ,
2025-03-12 00:17:01 -03:00
Message : "invalid, input" ,
2023-06-20 14:05:57 +02:00
ExpectedEnvelope : nil ,
} ,
2023-12-09 11:29:14 -03:00
{
2025-03-06 19:34:36 -03:00
Name : "EVENT envelope with subscription id" ,
2025-03-12 00:17:01 -03:00
Message : ` ["EVENT","_", { "kind":1,"id":"dc90c95f09947507c1044e8f48bcf6350aa6bff1507dd4acfc755b9239b5c962","pubkey":"3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d","created_at":1644271588,"tags":[],"content":"now that https://blueskyweb.org/blog/2-7-2022-overview was announced we can stop working on nostr?","sig":"230e9d8f0ddaf7eb70b5f7741ccfa37e87a455c9a469282e3464e2052d3192cd63a167e196e381ef9d7e69e9ea43af2443b839974dc85d8aaab9efe1d9296524"}] ` ,
2025-03-06 19:34:36 -03:00
ExpectedEnvelope : & EventEnvelope { SubscriptionID : ptr ( "_" ) , Event : Event { Kind : 1 , ID : "dc90c95f09947507c1044e8f48bcf6350aa6bff1507dd4acfc755b9239b5c962" , PubKey : "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d" , CreatedAt : 1644271588 , Tags : Tags { } , Content : "now that https://blueskyweb.org/blog/2-7-2022-overview was announced we can stop working on nostr?" , Sig : "230e9d8f0ddaf7eb70b5f7741ccfa37e87a455c9a469282e3464e2052d3192cd63a167e196e381ef9d7e69e9ea43af2443b839974dc85d8aaab9efe1d9296524" } } ,
2023-12-09 11:29:14 -03:00
} ,
{
2025-03-06 19:34:36 -03:00
Name : "EVENT envelope without subscription id" ,
2025-03-12 00:17:01 -03:00
Message : ` ["EVENT", { "kind":1,"id":"dc90c95f09947507c1044e8f48bcf6350aa6bff1507dd4acfc755b9239b5c962","pubkey":"3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d","created_at":1644271588,"tags":[],"content":"now that https://blueskyweb.org/blog/2-7-2022-overview was announced we can stop working on nostr?","sig":"230e9d8f0ddaf7eb70b5f7741ccfa37e87a455c9a469282e3464e2052d3192cd63a167e196e381ef9d7e69e9ea43af2443b839974dc85d8aaab9efe1d9296524"}] ` ,
2025-03-06 19:34:36 -03:00
ExpectedEnvelope : & EventEnvelope { Event : Event { Kind : 1 , ID : "dc90c95f09947507c1044e8f48bcf6350aa6bff1507dd4acfc755b9239b5c962" , PubKey : "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d" , CreatedAt : 1644271588 , Tags : Tags { } , Content : "now that https://blueskyweb.org/blog/2-7-2022-overview was announced we can stop working on nostr?" , Sig : "230e9d8f0ddaf7eb70b5f7741ccfa37e87a455c9a469282e3464e2052d3192cd63a167e196e381ef9d7e69e9ea43af2443b839974dc85d8aaab9efe1d9296524" } } ,
2025-02-25 17:57:15 -03:00
} ,
{
2025-03-06 19:34:36 -03:00
Name : "EVENT envelope with tags" ,
2025-03-12 00:17:01 -03:00
Message : ` ["EVENT", { "kind":3,"id":"9e662bdd7d8abc40b5b15ee1ff5e9320efc87e9274d8d440c58e6eed2dddfbe2","pubkey":"373ebe3d45ec91977296a178d9f19f326c70631d2a1b0bbba5c5ecc2eb53b9e7","created_at":1644844224,"tags":[["p","3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d"],["e","75fc5ac2487363293bd27fb0d14fb966477d0f1dbc6361d37806a6a740eda91e"],["p","46d0dfd3a724a302ca9175163bdf788f3606b3fd1bb12d5fe055d1e418cb60ea"]],"content":" { \"wss://nostr-pub.wellorder.net\": { \"read\":true,\"write\":true},\"wss://nostr.bitcoiner.social\": { \"read\":false,\"write\":true},\"wss://expensive-relay.fiatjaf.com\": { \"read\":true,\"write\":true},\"wss://relayer.fiatjaf.com\": { \"read\":true,\"write\":true},\"wss://relay.bitid.nz\": { \"read\":true,\"write\":true},\"wss://nostr.rocks\": { \"read\":true,\"write\":true}}","sig":"811355d3484d375df47581cb5d66bed05002c2978894098304f20b595e571b7e01b2efd906c5650080ffe49cf1c62b36715698e9d88b9e8be43029a2f3fa66be"}] ` ,
2025-03-07 09:43:42 -03:00
ExpectedEnvelope : & EventEnvelope { Event : Event { Kind : 3 , ID : "9e662bdd7d8abc40b5b15ee1ff5e9320efc87e9274d8d440c58e6eed2dddfbe2" , PubKey : "373ebe3d45ec91977296a178d9f19f326c70631d2a1b0bbba5c5ecc2eb53b9e7" , CreatedAt : 1644844224 , Tags : Tags { Tag { "p" , "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d" } , Tag { "e" , "75fc5ac2487363293bd27fb0d14fb966477d0f1dbc6361d37806a6a740eda91e" } , Tag { "p" , "46d0dfd3a724a302ca9175163bdf788f3606b3fd1bb12d5fe055d1e418cb60ea" } } , Content : "{\"wss://nostr-pub.wellorder.net\":{\"read\":true,\"write\":true},\"wss://nostr.bitcoiner.social\":{\"read\":false,\"write\":true},\"wss://expensive-relay.fiatjaf.com\":{\"read\":true,\"write\":true},\"wss://relayer.fiatjaf.com\":{\"read\":true,\"write\":true},\"wss://relay.bitid.nz\":{\"read\":true,\"write\":true},\"wss://nostr.rocks\":{\"read\":true,\"write\":true}}" , Sig : "811355d3484d375df47581cb5d66bed05002c2978894098304f20b595e571b7e01b2efd906c5650080ffe49cf1c62b36715698e9d88b9e8be43029a2f3fa66be" } } ,
2025-02-25 17:57:15 -03:00
} ,
{
2025-03-06 19:34:36 -03:00
Name : "NOTICE envelope" ,
2025-03-12 00:17:01 -03:00
Message : ` ["NOTICE","kjasbdlasvdluiasvd\"kjasbdksab\\d"] ` ,
2025-03-06 19:34:36 -03:00
ExpectedEnvelope : ptr ( NoticeEnvelope ( "kjasbdlasvdluiasvd\"kjasbdksab\\d" ) ) ,
2025-02-25 17:57:15 -03:00
} ,
{
2025-03-06 19:34:36 -03:00
Name : "EOSE envelope" ,
2025-03-12 00:17:01 -03:00
Message : ` ["EOSE","kjasbdlasvdluiasvd\"kjasbdksab\\d"] ` ,
2025-03-06 19:34:36 -03:00
ExpectedEnvelope : ptr ( EOSEEnvelope ( "kjasbdlasvdluiasvd\"kjasbdksab\\d" ) ) ,
2025-02-25 17:57:15 -03:00
} ,
{
2025-03-06 19:34:36 -03:00
Name : "COUNT envelope" ,
2025-03-12 00:17:01 -03:00
Message : ` ["COUNT","z", { "count":12}] ` ,
2025-03-06 19:34:36 -03:00
ExpectedEnvelope : & CountEnvelope { SubscriptionID : "z" , Count : ptr ( int64 ( 12 ) ) } ,
2025-02-25 17:57:15 -03:00
} ,
{
2025-03-06 19:34:36 -03:00
Name : "COUNT envelope with HLL" ,
2025-03-12 00:17:01 -03:00
Message : ` ["COUNT","sub1", { "count":42, "hll": "0100000101000000000000040000000001020000000002000000000200000003000002040000000101020001010000000000000007000004010000000200040000020400000000000102000002000004010000010000000301000102030002000301000300010000070000000001000004000102010000000400010002000000000103000100010001000001040100020001000000000000010000020000000000030100000001000400010000000000000901010100000000040000000b030000010100010000010000010000000003000000000000010003000100020000000000010000010100000100000104000200030001000300000001000101000102"}] ` ,
2025-03-06 19:34:36 -03:00
ExpectedEnvelope : & CountEnvelope { SubscriptionID : "sub1" , Count : ptr ( int64 ( 42 ) ) , HyperLogLog : [ ] byte { 1 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 4 , 0 , 0 , 0 , 0 , 1 , 2 , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 0 , 2 , 0 , 0 , 0 , 3 , 0 , 0 , 2 , 4 , 0 , 0 , 0 , 1 , 1 , 2 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 7 , 0 , 0 , 4 , 1 , 0 , 0 , 0 , 2 , 0 , 4 , 0 , 0 , 2 , 4 , 0 , 0 , 0 , 0 , 0 , 1 , 2 , 0 , 0 , 2 , 0 , 0 , 4 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 3 , 1 , 0 , 1 , 2 , 3 , 0 , 2 , 0 , 3 , 1 , 0 , 3 , 0 , 1 , 0 , 0 , 7 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 4 , 0 , 1 , 2 , 1 , 0 , 0 , 0 , 4 , 0 , 1 , 0 , 2 , 0 , 0 , 0 , 0 , 1 , 3 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 0 , 1 , 4 , 1 , 0 , 2 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 3 , 1 , 0 , 0 , 0 , 1 , 0 , 4 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 9 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 4 , 0 , 0 , 0 , 11 , 3 , 0 , 0 , 1 , 1 , 0 , 1 , 0 , 0 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 1 , 1 , 0 , 0 , 1 , 0 , 0 , 1 , 4 , 0 , 2 , 0 , 3 , 0 , 1 , 0 , 3 , 0 , 0 , 0 , 1 , 0 , 1 , 1 , 0 , 1 , 2 } } ,
2025-02-25 17:57:15 -03:00
} ,
{
2025-03-06 19:34:36 -03:00
Name : "OK envelope success" ,
2025-03-12 00:17:01 -03:00
Message : ` ["OK","3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefaaaaa",true,""] ` ,
2025-03-06 19:34:36 -03:00
ExpectedEnvelope : & OKEnvelope { EventID : "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefaaaaa" , OK : true , Reason : "" } ,
2025-02-25 17:57:15 -03:00
} ,
{
2025-03-06 19:34:36 -03:00
Name : "OK envelope failure" ,
2025-03-12 00:17:01 -03:00
Message : ` ["OK","3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefaaaaa",false,"error: could not connect to the database"] ` ,
2025-03-06 19:34:36 -03:00
ExpectedEnvelope : & OKEnvelope { EventID : "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefaaaaa" , OK : false , Reason : "error: could not connect to the database" } ,
2025-02-25 17:57:15 -03:00
} ,
{
2025-03-06 19:34:36 -03:00
Name : "CLOSED envelope with underscore" ,
2025-03-12 00:17:01 -03:00
Message : ` ["CLOSED","_","error: something went wrong"] ` ,
2025-03-06 19:34:36 -03:00
ExpectedEnvelope : & ClosedEnvelope { SubscriptionID : "_" , Reason : "error: something went wrong" } ,
2025-02-25 17:57:15 -03:00
} ,
{
2025-03-06 19:34:36 -03:00
Name : "CLOSED envelope with colon" ,
2025-03-12 00:17:01 -03:00
Message : ` ["CLOSED",":1","auth-required: take a selfie and send it to the CIA"] ` ,
2025-03-06 19:34:36 -03:00
ExpectedEnvelope : & ClosedEnvelope { SubscriptionID : ":1" , Reason : "auth-required: take a selfie and send it to the CIA" } ,
2025-02-25 17:57:15 -03:00
} ,
{
Name : "AUTH envelope with challenge" ,
2025-03-12 00:17:01 -03:00
Message : ` ["AUTH","kjsabdlasb aslkd kasndkad \"as.kdnbskadb"] ` ,
2025-03-06 19:34:36 -03:00
ExpectedEnvelope : & AuthEnvelope { Challenge : ptr ( "kjsabdlasb aslkd kasndkad \"as.kdnbskadb" ) } ,
2025-02-25 17:57:15 -03:00
} ,
{
2025-03-06 19:34:36 -03:00
Name : "AUTH envelope with event" ,
2025-03-12 00:17:01 -03:00
Message : ` ["AUTH", { "kind":1,"id":"ae1fc7154296569d87ca4663f6bdf448c217d1590d28c85d158557b8b43b4d69","pubkey":"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","created_at":1683660344,"tags":[],"content":"hello world","sig":"94e10947814b1ebe38af42300ecd90c7642763896c4f69506ae97bfdf54eec3c0c21df96b7d95daa74ff3d414b1d758ee95fc258125deebc31df0c6ba9396a51"}] ` ,
2025-03-06 19:34:36 -03:00
ExpectedEnvelope : & AuthEnvelope { Event : Event { Kind : 1 , ID : "ae1fc7154296569d87ca4663f6bdf448c217d1590d28c85d158557b8b43b4d69" , PubKey : "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" , CreatedAt : 1683660344 , Tags : Tags { } , Content : "hello world" , Sig : "94e10947814b1ebe38af42300ecd90c7642763896c4f69506ae97bfdf54eec3c0c21df96b7d95daa74ff3d414b1d758ee95fc258125deebc31df0c6ba9396a51" } } ,
2025-02-25 17:57:15 -03:00
} ,
{
2025-03-06 19:34:36 -03:00
Name : "REQ envelope" ,
2025-03-12 00:17:01 -03:00
Message : ` ["REQ","million", { "kinds": [1]}, { "kinds": [30023 ], "#d": ["buteko", "batuke"]}] ` ,
2025-03-06 19:34:36 -03:00
ExpectedEnvelope : & ReqEnvelope { SubscriptionID : "million" , Filters : Filters { { Kinds : [ ] int { 1 } } , { Kinds : [ ] int { 30023 } , Tags : TagMap { "d" : [ ] string { "buteko" , "batuke" } } } } } ,
2025-02-25 17:57:15 -03:00
} ,
{
Name : "CLOSE envelope" ,
2025-03-12 00:17:01 -03:00
Message : ` ["CLOSE","subscription123"] ` ,
2025-02-25 17:57:15 -03:00
ExpectedEnvelope : ptr ( CloseEnvelope ( "subscription123" ) ) ,
} ,
2025-03-14 20:08:56 -03:00
{
Name : "AUTH envelope from nak 23gmt bug" ,
Message : ` ["AUTH","c45b2b06ad92e28a"] ` ,
ExpectedEnvelope : & AuthEnvelope { Challenge : ptr ( "c45b2b06ad92e28a" ) } ,
} ,
{
Name : "REQ from jumble" ,
Message : ` ["REQ","sub:1", { "kinds":[1,6],"limit":100}] ` ,
ExpectedEnvelope : & ReqEnvelope { SubscriptionID : "sub:1" , Filters : Filters { { Kinds : [ ] int { 1 , 6 } , Limit : 100 } } } ,
} ,
2025-02-25 17:57:15 -03:00
}
2025-03-06 19:34:36 -03:00
t . Run ( "standard" , func ( t * testing . T ) {
for _ , testCase := range testCases {
t . Run ( testCase . Name , func ( t * testing . T ) {
envelope := ParseMessage ( testCase . Message )
if testCase . ExpectedEnvelope == nil && envelope == nil {
return
}
if testCase . ExpectedEnvelope == nil {
2025-03-07 09:43:42 -03:00
require . Nil ( t , envelope , "expected nil but got %v" , envelope )
2025-03-06 19:34:36 -03:00
return
}
2025-03-07 09:43:42 -03:00
require . NotNil ( t , envelope , "expected non-nil envelope but got nil" )
require . Equal ( t , testCase . ExpectedEnvelope . String ( ) , envelope . String ( ) )
2025-03-06 19:34:36 -03:00
} )
}
} )
t . Run ( "sonic" , func ( t * testing . T ) {
2025-03-07 15:38:20 -03:00
smp := NewSonicMessageParser ( )
2025-03-06 19:34:36 -03:00
for _ , testCase := range testCases {
t . Run ( testCase . Name , func ( t * testing . T ) {
2025-03-07 15:38:20 -03:00
envelope , err := smp . ParseMessage ( testCase . Message )
2025-03-06 19:34:36 -03:00
if testCase . ExpectedEnvelope == nil && envelope == nil {
return
}
if testCase . ExpectedEnvelope == nil {
require . Nil ( t , envelope , "expected nil but got %v" , envelope )
return
}
2025-02-25 17:57:15 -03:00
2025-03-06 19:34:36 -03:00
require . NoError ( t , err )
require . NotNil ( t , envelope , "expected non-nil envelope but got nil" )
2025-03-07 09:43:42 -03:00
require . Equal ( t , testCase . ExpectedEnvelope , envelope )
2025-03-06 19:34:36 -03:00
} )
}
} )
2025-02-25 17:57:15 -03:00
}
2025-03-07 15:50:55 -03:00
func TestParseMessagesFromFile ( t * testing . T ) {
file , err := os . Open ( "testdata/messages.jsonl" )
if err != nil {
t . Skipf ( "Skipping test because testdata/messages.jsonl could not be opened: %v" , err )
return
}
defer file . Close ( )
scanner := bufio . NewScanner ( file )
smp := NewSonicMessageParser ( )
lineNum := 0
for scanner . Scan ( ) {
lineNum ++
line := scanner . Bytes ( )
if len ( line ) == 0 {
continue
}
2025-03-12 00:17:01 -03:00
standardEnvelope := ParseMessage ( string ( line ) )
sonicEnvelope , err := smp . ParseMessage ( string ( line ) )
2025-03-07 15:50:55 -03:00
if standardEnvelope == nil {
require . Nil ( t , sonicEnvelope , "line %d: standard parser returned nil but sonic parser didn't" , lineNum )
continue
}
require . NoError ( t , err , "line %d: sonic parser returned error" , lineNum )
require . NotNil ( t , sonicEnvelope , "line %d: standard parser returned non-nil but sonic parser returned nil" , lineNum )
require . Equal ( t , standardEnvelope , sonicEnvelope ,
"line %d: parsers returned different results" , lineNum )
}
require . NoError ( t , scanner . Err ( ) , "error reading file" )
}