414 lines
11 KiB
Go
414 lines
11 KiB
Go
package test
|
|
|
|
import (
|
|
"slices"
|
|
"testing"
|
|
|
|
"fiatjaf.com/nostr"
|
|
"fiatjaf.com/nostr/eventstore"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func basicTest(t *testing.T, db eventstore.Store) {
|
|
err := db.Init()
|
|
require.NoError(t, err)
|
|
|
|
// define public keys for use throughout the test
|
|
pk3 := nostr.GetPublicKey(sk3)
|
|
pk4 := nostr.GetPublicKey(sk4)
|
|
|
|
// from basic-test.patch
|
|
{
|
|
// create test events with different tags and authors
|
|
|
|
events := []nostr.Event{
|
|
// event with 'e' tag
|
|
{
|
|
CreatedAt: 100,
|
|
Content: "event with e tag",
|
|
Tags: nostr.Tags{{"e", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}},
|
|
Kind: 1,
|
|
},
|
|
// event with 'q' tag
|
|
{
|
|
CreatedAt: 101,
|
|
Content: "event with q tag",
|
|
Tags: nostr.Tags{{"q", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}},
|
|
Kind: 1,
|
|
},
|
|
// event with 'p' tag and kind 3
|
|
{
|
|
CreatedAt: 102,
|
|
Content: "event with p tag kind 3",
|
|
Tags: nostr.Tags{{"p", pk3.Hex()}},
|
|
Kind: 3,
|
|
},
|
|
// event with 'p' tag and kind 7
|
|
{
|
|
CreatedAt: 103,
|
|
Content: "event with p tag kind 7",
|
|
Tags: nostr.Tags{{"p", pk4.Hex()}},
|
|
Kind: 7,
|
|
},
|
|
// event from author pk3 with kind 1
|
|
{
|
|
CreatedAt: 104,
|
|
Content: "event from pk3 kind 1",
|
|
Tags: nostr.Tags{},
|
|
Kind: 1,
|
|
},
|
|
// event from author pk4 with kind 3
|
|
{
|
|
CreatedAt: 105,
|
|
Content: "event from pk4 kind 3",
|
|
Tags: nostr.Tags{},
|
|
Kind: 3,
|
|
},
|
|
}
|
|
|
|
// sign events with appropriate keys
|
|
events[0].Sign(sk3)
|
|
events[1].Sign(sk3)
|
|
events[2].Sign(sk3)
|
|
events[3].Sign(sk3)
|
|
events[4].Sign(sk3)
|
|
events[5].Sign(sk4)
|
|
|
|
// save all events
|
|
for _, evt := range events {
|
|
err = db.SaveEvent(evt)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// test 0: query all
|
|
{
|
|
results := slices.Collect(db.QueryEvents(nostr.Filter{}, 1000))
|
|
require.NoError(t, err)
|
|
require.Len(t, results, 6)
|
|
}
|
|
|
|
// test 1: query by 'e' tag
|
|
{
|
|
results := slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Tags: nostr.TagMap{"e": []string{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}},
|
|
}, 1000))
|
|
require.NoError(t, err)
|
|
require.Len(t, results, 1)
|
|
require.Equal(t, events[0].ID, results[0].ID, "e tag query error")
|
|
}
|
|
|
|
// test 2: query by 'q' tag
|
|
{
|
|
results := slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Tags: nostr.TagMap{"q": []string{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}},
|
|
}, 1000))
|
|
require.NoError(t, err)
|
|
require.Len(t, results, 1)
|
|
require.Equal(t, events[1].ID, results[0].ID, "q tag query error")
|
|
}
|
|
|
|
// test 3: query by 'p' tag + kind
|
|
{
|
|
results := slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Tags: nostr.TagMap{"p": []string{pk3.Hex()}},
|
|
Kinds: []nostr.Kind{3},
|
|
}, 1000))
|
|
require.NoError(t, err)
|
|
require.Len(t, results, 1)
|
|
require.Equal(t, events[2].ID, results[0].ID, "p tag + kind query error")
|
|
}
|
|
|
|
// test 4: query by author + kind
|
|
{
|
|
results := slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Authors: []nostr.PubKey{pk4},
|
|
Kinds: []nostr.Kind{3},
|
|
}, 1000))
|
|
require.NoError(t, err)
|
|
require.Len(t, results, 1)
|
|
require.Equal(t, events[5].ID, results[0].ID, "author + kind query error")
|
|
}
|
|
}
|
|
|
|
// from another-basic-test.patch
|
|
{
|
|
evt1 := nostr.Event{
|
|
CreatedAt: nostr.Now(),
|
|
Content: "two tags",
|
|
Tags: nostr.Tags{
|
|
{"e", "f355341a03672c5b136a6002fb4b69ad52111a1646638771c3995fc0a4db2a78"},
|
|
{"q", "f355341a03672c5b136a6002fb4b69ad52111a1646638771c3995fc0a4db2a78"},
|
|
},
|
|
Kind: 23122,
|
|
}
|
|
evt1.Sign(sk3)
|
|
require.NoError(t, db.SaveEvent(evt1))
|
|
|
|
{
|
|
results := slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Tags: nostr.TagMap{"e": []string{"f355341a03672c5b136a6002fb4b69ad52111a1646638771c3995fc0a4db2a78"}},
|
|
}, 1000))
|
|
require.NoError(t, err)
|
|
require.Len(t, results, 1)
|
|
require.ElementsMatch(t,
|
|
[]nostr.Event{evt1},
|
|
results,
|
|
"querying by 'e' tag")
|
|
}
|
|
{
|
|
results := slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Tags: nostr.TagMap{"q": []string{"f355341a03672c5b136a6002fb4b69ad52111a1646638771c3995fc0a4db2a78"}},
|
|
}, 1000))
|
|
require.NoError(t, err)
|
|
require.Len(t, results, 1)
|
|
require.ElementsMatch(t,
|
|
[]nostr.Event{evt1},
|
|
results,
|
|
"querying by 'q' tag")
|
|
}
|
|
|
|
evt2 := nostr.Event{
|
|
CreatedAt: nostr.Now(),
|
|
Content: "e tag",
|
|
Tags: nostr.Tags{
|
|
{"e", "f355341a03672c5b136a6002fb4b69ad52111a1646638771c3995fc0a4db2a78"},
|
|
},
|
|
Kind: 23122,
|
|
}
|
|
evt2.Sign(sk3)
|
|
require.NoError(t, db.SaveEvent(evt2))
|
|
|
|
evt3 := nostr.Event{
|
|
CreatedAt: nostr.Now(),
|
|
Content: "q tag",
|
|
Tags: nostr.Tags{
|
|
{"q", "f355341a03672c5b136a6002fb4b69ad52111a1646638771c3995fc0a4db2a78"},
|
|
},
|
|
Kind: 23122,
|
|
}
|
|
evt3.Sign(sk3)
|
|
require.NoError(t, db.SaveEvent(evt3))
|
|
|
|
{
|
|
results := slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Tags: nostr.TagMap{"e": []string{"f355341a03672c5b136a6002fb4b69ad52111a1646638771c3995fc0a4db2a78"}},
|
|
}, 1000))
|
|
require.NoError(t, err)
|
|
require.Len(t, results, 2)
|
|
require.ElementsMatch(t,
|
|
[]nostr.Event{evt1, evt2},
|
|
results,
|
|
"querying by 'e' tag")
|
|
}
|
|
{
|
|
results := slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Tags: nostr.TagMap{"q": []string{"f355341a03672c5b136a6002fb4b69ad52111a1646638771c3995fc0a4db2a78"}},
|
|
}, 1000))
|
|
require.NoError(t, err)
|
|
require.Len(t, results, 2)
|
|
require.ElementsMatch(t,
|
|
[]nostr.Event{evt1, evt3},
|
|
results,
|
|
"querying by 'q' tag")
|
|
}
|
|
}
|
|
|
|
// test ReplaceEvent()
|
|
{
|
|
originalProfile := nostr.Event{
|
|
CreatedAt: 200,
|
|
Content: `{"name":"original","about":"original profile"}`,
|
|
Tags: nostr.Tags{},
|
|
Kind: 0,
|
|
}
|
|
originalProfile.Sign(sk3)
|
|
|
|
err = db.ReplaceEvent(originalProfile)
|
|
require.NoError(t, err)
|
|
|
|
// verify
|
|
results := slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Authors: []nostr.PubKey{pk3},
|
|
Kinds: []nostr.Kind{0},
|
|
}, 1000))
|
|
require.Len(t, results, 1)
|
|
require.Equal(t, originalProfile.ID, results[0].ID)
|
|
|
|
// create newer profile event
|
|
newProfile := nostr.Event{
|
|
CreatedAt: 300, // newer timestamp
|
|
Content: `{"name":"updated","about":"updated profile"}`,
|
|
Tags: nostr.Tags{},
|
|
Kind: 0,
|
|
}
|
|
newProfile.Sign(sk3)
|
|
|
|
// replace with newer event
|
|
err = db.ReplaceEvent(newProfile)
|
|
require.NoError(t, err)
|
|
|
|
// verify only the newer event exists
|
|
results = slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Authors: []nostr.PubKey{pk3},
|
|
Kinds: []nostr.Kind{0},
|
|
}, 1000))
|
|
require.Len(t, results, 1)
|
|
require.Equal(t, newProfile.ID, results[0].ID)
|
|
|
|
// try to replace with older event (should be ignored)
|
|
olderProfile := nostr.Event{
|
|
CreatedAt: 250, // older than current
|
|
Content: `{"name":"older","about":"older profile"}`,
|
|
Tags: nostr.Tags{},
|
|
Kind: 0,
|
|
}
|
|
olderProfile.Sign(sk3)
|
|
|
|
err = db.ReplaceEvent(olderProfile)
|
|
require.NoError(t, err)
|
|
|
|
// verify the newer event is still there
|
|
results = slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Authors: []nostr.PubKey{pk3},
|
|
Kinds: []nostr.Kind{0},
|
|
}, 1000))
|
|
require.Len(t, results, 1)
|
|
require.Equal(t, newProfile.ID, results[0].ID)
|
|
|
|
// test addressable event (kind 30023 - article)
|
|
articleV1 := nostr.Event{
|
|
CreatedAt: 400,
|
|
Content: "first version of article",
|
|
Tags: nostr.Tags{{"d", "my-article"}}, // addressable identifier
|
|
Kind: 30023, // article - addressable
|
|
}
|
|
articleV1.Sign(sk3)
|
|
|
|
err = db.ReplaceEvent(articleV1)
|
|
require.NoError(t, err)
|
|
|
|
// verify article was saved
|
|
results = slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Authors: []nostr.PubKey{pk3},
|
|
Kinds: []nostr.Kind{30023},
|
|
Tags: nostr.TagMap{"d": []string{"my-article"}},
|
|
}, 1000))
|
|
require.Len(t, results, 1)
|
|
require.Equal(t, articleV1.ID, results[0].ID)
|
|
|
|
// create updated version of same article
|
|
articleV2 := nostr.Event{
|
|
CreatedAt: 500,
|
|
Content: "second version of article",
|
|
Tags: nostr.Tags{{"d", "my-article"}}, // same identifier
|
|
Kind: 30023,
|
|
}
|
|
articleV2.Sign(sk3)
|
|
|
|
err = db.ReplaceEvent(articleV2)
|
|
require.NoError(t, err)
|
|
|
|
// verify only the newer version exists
|
|
results = slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Authors: []nostr.PubKey{pk3},
|
|
Kinds: []nostr.Kind{30023},
|
|
Tags: nostr.TagMap{"d": []string{"my-article"}},
|
|
}, 1000))
|
|
require.Len(t, results, 1)
|
|
require.Equal(t, articleV2.ID, results[0].ID)
|
|
require.Equal(t, "second version of article", results[0].Content)
|
|
|
|
// create different article with different d tag
|
|
differentArticle := nostr.Event{
|
|
CreatedAt: 600,
|
|
Content: "different article",
|
|
Tags: nostr.Tags{{"d", "other-article"}}, // different identifier
|
|
Kind: 30023,
|
|
}
|
|
differentArticle.Sign(sk3)
|
|
|
|
err = db.ReplaceEvent(differentArticle)
|
|
require.NoError(t, err)
|
|
|
|
// verify both articles exist (different d tags)
|
|
results = slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Authors: []nostr.PubKey{pk3},
|
|
Kinds: []nostr.Kind{30023},
|
|
}, 1000))
|
|
require.Len(t, results, 2)
|
|
}
|
|
|
|
// test DeleteEvent()
|
|
{
|
|
// create other events to ensure they are not deleted
|
|
otherEvent1 := nostr.Event{
|
|
CreatedAt: 601,
|
|
Content: "other event 1",
|
|
Tags: nostr.Tags{},
|
|
Kind: 1,
|
|
}
|
|
otherEvent1.Sign(sk3)
|
|
err = db.SaveEvent(otherEvent1)
|
|
require.NoError(t, err)
|
|
|
|
otherEvent2 := nostr.Event{
|
|
CreatedAt: 602,
|
|
Content: "other event 2",
|
|
Tags: nostr.Tags{},
|
|
Kind: 2,
|
|
}
|
|
otherEvent2.Sign(sk4)
|
|
err = db.SaveEvent(otherEvent2)
|
|
require.NoError(t, err)
|
|
|
|
// create a test event to delete
|
|
deleteEvent := nostr.Event{
|
|
CreatedAt: 600,
|
|
Content: "event to be deleted",
|
|
Tags: nostr.Tags{},
|
|
Kind: 1,
|
|
}
|
|
deleteEvent.Sign(sk3)
|
|
err = db.SaveEvent(deleteEvent)
|
|
require.NoError(t, err)
|
|
|
|
// verify events exist
|
|
results := slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Authors: []nostr.PubKey{pk3},
|
|
Kinds: []nostr.Kind{1},
|
|
}, 1000))
|
|
require.Contains(t, results, deleteEvent)
|
|
require.Contains(t, results, otherEvent1)
|
|
|
|
results2 := slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Authors: []nostr.PubKey{pk4},
|
|
Kinds: []nostr.Kind{2},
|
|
}, 1000))
|
|
require.Contains(t, results2, otherEvent2)
|
|
|
|
// delete the event
|
|
err = db.DeleteEvent(deleteEvent.ID)
|
|
require.NoError(t, err)
|
|
|
|
// verify event is deleted
|
|
results = slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Authors: []nostr.PubKey{pk3},
|
|
Kinds: []nostr.Kind{1},
|
|
}, 1000))
|
|
require.NotContains(t, results, deleteEvent)
|
|
require.Contains(t, results, otherEvent1)
|
|
|
|
// verify other event still exists
|
|
results2 = slices.Collect(db.QueryEvents(nostr.Filter{
|
|
Authors: []nostr.PubKey{pk4},
|
|
Kinds: []nostr.Kind{2},
|
|
}, 1000))
|
|
require.Contains(t, results2, otherEvent2)
|
|
|
|
// test deleting non-existent event (should not error)
|
|
fakeID, _ := nostr.IDFromHex("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
|
|
err = db.DeleteEvent(fakeID)
|
|
require.NoError(t, err)
|
|
}
|
|
}
|