1
0
mirror of git://jb55.com/damus synced 2024-09-16 02:03:45 +00:00
damus/nostrdb/Test/NdbTests.swift
Daniel D’Aquino a1e6be214e Migrate NostrDB files to shared app group file container
This change was made so that NostrDB data can be accessed from different build targets such as the notification service extension.

Upon initialization of NostrDB, it will check both DB file locations (the old documents directory, and the new shared app group container). If it sees the DB is present on the old location, and not on the new location, it will move the files to the new location. In any other condition it will keep the files intact to prevent data loss.

In order to avoid any conflicts between the damusApp's Ndb instance and the extension's Ndb instance when writing or moving the file, a new parameter called "owns_db_file" was added, and set to "false" for the extension. This ensures that the extension will not attempt to move DB files or create a new DB file on its own. Only the main app can move or create the DB file.

Testing
-------

PASS

Device: iPhone 15 Pro simulator
iOS: 17.0.1
Damus: This commit
Steps:
1. Run with the debugger attached to the extension target.
2. Using Apple's push notification testing dashboard, send a test push notification with a real payload (that includes the nostr event under `nostr_event`. Payload generated by strfry-push-notify).
3. Watch logs. It should show a message like "Got push notification from <DISPLAY_NAME>", where `DISPLAY_NAME` is the correct profile name of the user who generated the event. PASS

Regression testing
------------------

Device: iPhone 13 Mini (Real device)
iOS: 17.1.1
Damus: This commit
Other preconditions:
- Damus is at 1.6 (29) at the start of the test
- NostrDB filled with real data on the old location
Steps:
1. Flash (upgrade) the new Damus version (this commit) (This will be the first time upgrading, shared file container is empty)
2. Try to use the app normally. Scroll and navigate to several locations. Interact with some notes. App should be stable, work, and appear to have profile names already (i.e. It shouldn't start with a bunch of npubs in the place of profile names on known contacts). PASS
3. Downgrade back to the App store version (v1.6 (29))
4. Try to use the app normally. Scroll and navigate, interact, etc. App should work and be stable, but profile name cache is expected to be lost (i.e. shows npubs for a bit until profile is reloaded into NostrDB). PASS
5. Upgrade app again to the version in this commit.
6. Repeat step 2. Everything should work as normal and all profiles should be preloaded from the start. PASS

Closes: https://github.com/damus-io/damus/issues/1744
2023-11-21 10:39:27 -08:00

250 lines
8.2 KiB
Swift

//
// NDBIterTests.swift
// damusTests
//
// Created by William Casarin on 2023-07-21.
//
import XCTest
@testable import damus
func test_ndb_dir() -> String? {
do {
let fileManager = FileManager.default
let tempDir = fileManager.temporaryDirectory.appendingPathComponent(UUID().uuidString)
try fileManager.createDirectory(at: tempDir, withIntermediateDirectories: true, attributes: nil)
return remove_file_prefix(tempDir.absoluteString)
} catch {
return nil
}
}
final class NdbTests: XCTestCase {
var db_dir: String = ""
override func setUpWithError() throws {
guard let db = test_ndb_dir() else {
XCTFail("Could not create temp directory")
return
}
db_dir = db
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func test_decode_eose() throws {
let json = "[\"EOSE\",\"DC268DBD-55DA-458A-B967-540925AF3497\"]"
let resp = decode_nostr_event(txt: json)
XCTAssertNotNil(resp)
}
func test_decode_command_result() throws {
let json = "[\"OK\",\"b1d8f68d39c07ce5c5ea10c235100d529b2ed2250140b36a35d940b712dc6eff\",true,\"\"]"
let resp = decode_nostr_event(txt: json)
XCTAssertNotNil(resp)
}
func test_profile_creation() {
let profile = make_test_profile()
XCTAssertEqual(profile.name, "jb55")
}
func test_ndb_init() {
do {
let ndb = try! Ndb(path: db_dir)!
let ok = ndb.process_events(test_wire_events)
XCTAssertTrue(ok)
}
do {
let ndb = try! Ndb(path: db_dir)!
let id = NoteId(hex: "d12c17bde3094ad32f4ab862a6cc6f5c289cfe7d5802270bdf34904df585f349")!
let txn = NdbTxn(ndb: ndb)
let note = ndb.lookup_note_with_txn(id: id, txn: txn)
XCTAssertNotNil(note)
guard let note else { return }
let pk = Pubkey(hex: "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245")!
XCTAssertEqual(note.pubkey, pk)
let profile = ndb.lookup_profile_with_txn(pk, txn: txn)
XCTAssertNotNil(profile)
guard let profile else { return }
XCTAssertEqual(profile.profile?.name, "jb55")
XCTAssertEqual(profile.lnurl, nil)
}
}
func test_ndb_note() throws {
let note = NdbNote.owned_from_json(json: test_contact_list_json)
XCTAssertNotNil(note)
guard let note else { return }
let id = NoteId(hex: "20d0ff27d6fcb13de8366328c5b1a7af26bcac07f2e558fbebd5e9242e608c09")!
let pubkey = Pubkey(hex: "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245")!
XCTAssertEqual(note.id, id)
XCTAssertEqual(note.pubkey, pubkey)
XCTAssertEqual(note.count, 34328)
XCTAssertEqual(note.kind, 3)
XCTAssertEqual(note.created_at, 1689904312)
let expected_count: UInt16 = 786
XCTAssertEqual(note.tags.count, expected_count)
XCTAssertEqual(note.tags.reduce(0, { sum, _ in sum + 1 }), expected_count)
var tags = 0
var total_count_stored = 0
var total_count_iter = 0
//let tags = note.tags()
for tag in note.tags {
total_count_stored += Int(tag.count)
if tags == 0 || tags == 1 || tags == 2 {
XCTAssertEqual(tag.count, 3)
}
if tags == 6 {
XCTAssertEqual(tag.count, 2)
}
if tags == 7 {
XCTAssertEqual(tag[2].string(), "wss://nostr-pub.wellorder.net")
}
for elem in tag {
print("tag[\(tags)][\(elem.index)]")
total_count_iter += 1
}
tags += 1
}
XCTAssertEqual(tags, 786)
XCTAssertEqual(total_count_stored, total_count_iter)
}
/// Based on https://github.com/damus-io/damus/issues/1468
/// Tests whether a JSON with optional escaped slash characters is correctly unescaped (In accordance to https://datatracker.ietf.org/doc/html/rfc8259#section-7)
func test_decode_json_with_escaped_slashes() {
let testJSONWithEscapedSlashes = "{\"tags\":[],\"pubkey\":\"f8e6c64342f1e052480630e27e1016dce35fc3a614e60434fef4aa2503328ca9\",\"content\":\"https:\\/\\/cdn.nostr.build\\/i\\/5c1d3296f66c2630131bf123106486aeaf051ed8466031c0e0532d70b33cddb2.jpg\",\"created_at\":1691864981,\"kind\":1,\"sig\":\"fc0033aa3d4df50b692a5b346fa816fdded698de2045e36e0642a021391468c44ca69c2471adc7e92088131872d4aaa1e90ea6e1ad97f3cc748f4aed96dfae18\",\"id\":\"e8f6eca3b161abba034dac9a02bb6930ecde9fd2fb5d6c5f22a05526e11382cb\"}"
let testNote = NdbNote.owned_from_json(json: testJSONWithEscapedSlashes)!
XCTAssertEqual(testNote.content, "https://cdn.nostr.build/i/5c1d3296f66c2630131bf123106486aeaf051ed8466031c0e0532d70b33cddb2.jpg")
}
func test_decode_perf() throws {
// This is an example of a performance test case.
self.measure {
_ = NdbNote.owned_from_json(json: test_contact_list_json)
}
}
func test_perf_old_decoding() {
self.measure {
let event = decode_nostr_event_json(test_contact_list_json)
XCTAssertNotNil(event)
}
}
func test_perf_old_iter() {
self.measure {
let event = decode_nostr_event_json(test_contact_list_json)
XCTAssertNotNil(event)
}
}
func longer_iter(_ n: Int = 1000) -> XCTMeasureOptions {
let opts = XCTMeasureOptions()
opts.iterationCount = n
return opts
}
func test_perf_interp_evrefs_old() {
guard let event = decode_nostr_event_json(test_reply_json) else {
return
}
self.measure(options: longer_iter()) {
let blocks = event.blocks(test_keypair).blocks
let xs = interpret_event_refs(blocks: blocks, tags: event.tags)
XCTAssertEqual(xs.count, 1)
}
}
func test_perf_interp_evrefs_ndb() {
guard let note = NdbNote.owned_from_json(json: test_reply_json) else {
return
}
self.measure(options: longer_iter()) {
let blocks = note.blocks(test_keypair).blocks
let xs = interpret_event_refs_ndb(blocks: blocks, tags: note.tags)
XCTAssertEqual(xs.count, 1)
}
}
func test_decoded_events_are_equal() {
let event = decode_nostr_event_json(test_reply_json)
let note = NdbNote.owned_from_json(json: test_reply_json)
XCTAssertNotNil(note)
XCTAssertNotNil(event)
guard let note else { return }
guard let event else { return }
XCTAssertEqual(note.content_len, UInt32(event.content.utf8.count))
XCTAssertEqual(note.pubkey, event.pubkey)
XCTAssertEqual(note.id, event.id)
let ev_blocks = event.blocks(test_keypair)
let note_blocks = note.blocks(test_keypair)
XCTAssertEqual(ev_blocks, note_blocks)
let event_refs = interpret_event_refs(blocks: ev_blocks.blocks, tags: event.tags)
let note_refs = interpret_event_refs_ndb(blocks: note_blocks.blocks, tags: note.tags)
XCTAssertEqual(event_refs, note_refs)
}
func test_iteration_perf() throws {
guard let note = NdbNote.owned_from_json(json: test_contact_list_json) else {
XCTAssert(false)
return
}
self.measure {
var count = 0
var char_count = 0
for tag in note.tags {
for elem in tag {
print("iter_elem \(elem.string())")
for c in elem {
if char_count == 0 {
let ac = AsciiCharacter(c)
XCTAssertEqual(ac, "p")
} else if char_count == 0 {
XCTAssertEqual(c, 0x6c)
}
char_count += 1
}
}
count += 1
}
XCTAssertEqual(count, 786)
XCTAssertEqual(char_count, 24370)
}
}
}