test: cover the version-note guard path in observeNotes dedup

Add coverage for a real consumeBaseReplaceable call the suite was missing:
observers are also notified with the "version" note (getOrCreateNote(event.id),
a regular Note carrying the AddressableEvent), which the addressable-list guard
must drop while still listing the AddressableNote for the same event.

Confirmed the concurrency the stress tests exercise is real, not theoretical:
relay events are verified+consumed inline on per-relay socket dispatchers, so
distinct relays drive new()/remove() on the same note instance concurrently.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ah1aCniyjnzc27x4pwq2Df
This commit is contained in:
Claude
2026-07-28 19:17:57 +00:00
parent 636331487a
commit 5cb84e16dc
@@ -186,6 +186,27 @@ class NoteListMatchingFilterTest {
assertNull(firstViolation.get(), "an emission carried a duplicate idHex: ${firstViolation.get()}")
}
@Test
fun ignoresTheVersionNoteThatHoldsAnAddressableEvent() {
// consumeBaseReplaceable also notifies observers with the "version" note:
// getOrCreateNote(event.id), a regular Note (not AddressableNote) carrying
// the AddressableEvent. It must never enter the addressable list.
var last: List<Note> = emptyList()
val subject = newFilter { last = it }
subject.init()
val event = appDefinition("nostr-dvm-labeler", 1000)
val versionNote = Note(event.id).apply { this.event = event }
subject.new(event, versionNote)
assertEquals(emptyList(), last)
// The addressable note for the same event, however, is listed.
val addressable = noteFor("nostr-dvm-labeler").apply { this.event = event }
subject.new(event, addressable)
assertEquals(listOf(addressable.idHex), last.map { it.idHex })
}
@Test
fun removeDropsTheNoteEvenAfterCreatedAtChanged() {
var last: List<Note> = emptyList()