NdbTests.swift (8090B)
1 // 2 // NDBIterTests.swift 3 // damusTests 4 // 5 // Created by William Casarin on 2023-07-21. 6 // 7 8 import XCTest 9 @testable import damus 10 11 func test_ndb_dir() -> String? { 12 do { 13 let fileManager = FileManager.default 14 let tempDir = fileManager.temporaryDirectory.appendingPathComponent(UUID().uuidString) 15 try fileManager.createDirectory(at: tempDir, withIntermediateDirectories: true, attributes: nil) 16 return remove_file_prefix(tempDir.absoluteString) 17 } catch { 18 return nil 19 } 20 } 21 22 final class NdbTests: XCTestCase { 23 var db_dir: String = "" 24 25 override func setUpWithError() throws { 26 guard let db = test_ndb_dir() else { 27 XCTFail("Could not create temp directory") 28 return 29 } 30 db_dir = db 31 } 32 33 override func tearDownWithError() throws { 34 // Put teardown code here. This method is called after the invocation of each test method in the class. 35 } 36 37 func test_decode_eose() throws { 38 let json = "[\"EOSE\",\"DC268DBD-55DA-458A-B967-540925AF3497\"]" 39 let resp = decode_nostr_event(txt: json) 40 XCTAssertNotNil(resp) 41 } 42 43 func test_decode_command_result() throws { 44 let json = "[\"OK\",\"b1d8f68d39c07ce5c5ea10c235100d529b2ed2250140b36a35d940b712dc6eff\",true,\"\"]" 45 let resp = decode_nostr_event(txt: json) 46 XCTAssertNotNil(resp) 47 48 } 49 50 func test_profile_creation() { 51 let profile = make_test_profile() 52 XCTAssertEqual(profile.name, "jb55") 53 } 54 55 func test_ndb_init() { 56 57 do { 58 let ndb = Ndb(path: db_dir)! 59 let ok = ndb.process_events(test_wire_events) 60 XCTAssertTrue(ok) 61 } 62 63 do { 64 let ndb = Ndb(path: db_dir)! 65 let id = NoteId(hex: "d12c17bde3094ad32f4ab862a6cc6f5c289cfe7d5802270bdf34904df585f349")! 66 guard let txn = NdbTxn(ndb: ndb) else { return XCTAssert(false) } 67 let note = ndb.lookup_note_with_txn(id: id, txn: txn) 68 XCTAssertNotNil(note) 69 guard let note else { return } 70 let pk = Pubkey(hex: "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245")! 71 XCTAssertEqual(note.pubkey, pk) 72 73 let profile = ndb.lookup_profile_with_txn(pk, txn: txn) 74 XCTAssertNotNil(profile) 75 guard let profile else { return } 76 77 XCTAssertEqual(profile.profile?.name, "jb55") 78 XCTAssertEqual(profile.lnurl, nil) 79 } 80 81 82 } 83 84 func test_ndb_seach() throws { 85 do { 86 let ndb = Ndb(path: db_dir)! 87 let ok = ndb.process_events(test_wire_events) 88 XCTAssertTrue(ok) 89 } 90 91 do { 92 let ndb = Ndb(path: db_dir)! 93 let note_ids = ndb.text_search(query: "barked") 94 XCTAssertEqual(note_ids.count, 1) 95 let expected_note_id = NoteId(hex: "b17a540710fe8495b16bfbaf31c6962c4ba8387f3284a7973ad523988095417e")! 96 let note_id = ndb.lookup_note_by_key(note_ids[0])?.map({ n in n?.id }).value 97 XCTAssertEqual(note_id, .some(expected_note_id)) 98 } 99 } 100 101 func test_ndb_note() throws { 102 let note = NdbNote.owned_from_json(json: test_contact_list_json) 103 XCTAssertNotNil(note) 104 guard let note else { return } 105 106 let id = NoteId(hex: "20d0ff27d6fcb13de8366328c5b1a7af26bcac07f2e558fbebd5e9242e608c09")! 107 let pubkey = Pubkey(hex: "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245")! 108 109 XCTAssertEqual(note.id, id) 110 XCTAssertEqual(note.pubkey, pubkey) 111 112 XCTAssertEqual(note.count, 34328) 113 XCTAssertEqual(note.kind, 3) 114 XCTAssertEqual(note.created_at, 1689904312) 115 116 let expected_count: UInt16 = 786 117 XCTAssertEqual(note.tags.count, expected_count) 118 XCTAssertEqual(note.tags.reduce(0, { sum, _ in sum + 1 }), expected_count) 119 120 var tags = 0 121 var total_count_stored = 0 122 var total_count_iter = 0 123 //let tags = note.tags() 124 for tag in note.tags { 125 total_count_stored += Int(tag.count) 126 127 if tags == 0 || tags == 1 || tags == 2 { 128 XCTAssertEqual(tag.count, 3) 129 } 130 131 if tags == 6 { 132 XCTAssertEqual(tag.count, 2) 133 } 134 135 if tags == 7 { 136 XCTAssertEqual(tag[2].string(), "wss://nostr-pub.wellorder.net") 137 } 138 139 for elem in tag { 140 print("tag[\(tags)][\(elem.index)]") 141 total_count_iter += 1 142 } 143 144 tags += 1 145 } 146 147 XCTAssertEqual(tags, 786) 148 XCTAssertEqual(total_count_stored, total_count_iter) 149 } 150 151 /// Based on https://github.com/damus-io/damus/issues/1468 152 /// Tests whether a JSON with optional escaped slash characters is correctly unescaped (In accordance to https://datatracker.ietf.org/doc/html/rfc8259#section-7) 153 func test_decode_json_with_escaped_slashes() { 154 let testJSONWithEscapedSlashes = "{\"tags\":[],\"pubkey\":\"f8e6c64342f1e052480630e27e1016dce35fc3a614e60434fef4aa2503328ca9\",\"content\":\"https:\\/\\/cdn.nostr.build\\/i\\/5c1d3296f66c2630131bf123106486aeaf051ed8466031c0e0532d70b33cddb2.jpg\",\"created_at\":1691864981,\"kind\":1,\"sig\":\"fc0033aa3d4df50b692a5b346fa816fdded698de2045e36e0642a021391468c44ca69c2471adc7e92088131872d4aaa1e90ea6e1ad97f3cc748f4aed96dfae18\",\"id\":\"e8f6eca3b161abba034dac9a02bb6930ecde9fd2fb5d6c5f22a05526e11382cb\"}" 155 let testNote = NdbNote.owned_from_json(json: testJSONWithEscapedSlashes)! 156 XCTAssertEqual(testNote.content, "https://cdn.nostr.build/i/5c1d3296f66c2630131bf123106486aeaf051ed8466031c0e0532d70b33cddb2.jpg") 157 } 158 159 func test_inherited_transactions() throws { 160 let ndb = Ndb(path: db_dir)! 161 do { 162 guard let txn1 = NdbTxn(ndb: ndb) else { return XCTAssert(false) } 163 164 let ntxn = (Thread.current.threadDictionary.value(forKey: "ndb_txn") as? ndb_txn)! 165 XCTAssertEqual(txn1.txn.lmdb, ntxn.lmdb) 166 XCTAssertEqual(txn1.txn.mdb_txn, ntxn.mdb_txn) 167 168 guard let txn2 = NdbTxn(ndb: ndb) else { return XCTAssert(false) } 169 170 XCTAssertEqual(txn1.inherited, false) 171 XCTAssertEqual(txn2.inherited, true) 172 } 173 174 let ndb_txn = Thread.current.threadDictionary.value(forKey: "ndb_txn") 175 XCTAssertNil(ndb_txn) 176 } 177 178 func test_decode_perf() throws { 179 // This is an example of a performance test case. 180 self.measure { 181 _ = NdbNote.owned_from_json(json: test_contact_list_json) 182 } 183 } 184 185 func test_perf_old_decoding() { 186 self.measure { 187 let event = decode_nostr_event_json(test_contact_list_json) 188 XCTAssertNotNil(event) 189 } 190 } 191 192 func test_perf_old_iter() { 193 self.measure { 194 let event = decode_nostr_event_json(test_contact_list_json) 195 XCTAssertNotNil(event) 196 } 197 } 198 199 func longer_iter(_ n: Int = 1000) -> XCTMeasureOptions { 200 let opts = XCTMeasureOptions() 201 opts.iterationCount = n 202 return opts 203 } 204 205 func test_iteration_perf() throws { 206 guard let note = NdbNote.owned_from_json(json: test_contact_list_json) else { 207 XCTAssert(false) 208 return 209 } 210 211 212 self.measure { 213 var count = 0 214 var char_count = 0 215 216 for tag in note.tags { 217 for elem in tag { 218 print("iter_elem \(elem.string())") 219 for c in elem { 220 if char_count == 0 { 221 let ac = AsciiCharacter(c) 222 XCTAssertEqual(ac, "p") 223 } else if char_count == 0 { 224 XCTAssertEqual(c, 0x6c) 225 } 226 char_count += 1 227 } 228 } 229 count += 1 230 } 231 232 XCTAssertEqual(count, 786) 233 XCTAssertEqual(char_count, 24370) 234 } 235 236 } 237 238 } 239