damusTests.swift (14130B)
1 // 2 // damusTests.swift 3 // damusTests 4 // 5 // Created by William Casarin on 2022-04-01. 6 // 7 8 import XCTest 9 @testable import damus 10 11 12 class damusTests: XCTestCase { 13 14 override func setUpWithError() throws { 15 // Put setup code here. This method is called before the invocation of each test method in the class. 16 } 17 18 override func tearDownWithError() throws { 19 // Put teardown code here. This method is called after the invocation of each test method in the class. 20 } 21 22 func testEventVerify() throws { 23 let test_valid_note_text = """ 24 {"id":"f4a5635d78d4c1ec2bf7d15d33bd8d5e0afdb8a5a24047f095842281c744e6a3","created_at":1753898578,"content":"Test 1102","kind":1,"pubkey":"056b5b5966f500defb3b790a14633e5ec4a0e8883ca29bc23d0030553edb084a","sig":"d03f0beee7355a8b6ce437b43e01f2d3be8c0f3f17b41a8dec8a9b9804d44ab639b7906c545e4b51820f00b09d00cfa5058916e93126e8a11a65e2623f95f152","tags":[]} 25 """ 26 let test_invalid_note_tampered_sig_text = """ 27 {"id":"f4a5635d78d4c1ec2bf7d15d33bd8d5e0afdb8a5a24047f095842281c744e6a3","created_at":1753898578,"content":"Test 1102","kind":1,"pubkey":"056b5b5966f500defb3b790a14633e5ec4a0e8883ca29bc23d0030553edb084a","sig":"d03f0beee7355a8b6ce437b43e01f2d3be8c0f3f17b41a8dec8a9b9804d44ab639b7906c545e4b51820f00b09d00cfa5058916e93126e8a11a65e2623f95f153","tags":[]} 28 """ 29 let test_invalid_note_tampered_id_text = """ 30 {"id":"f4a5635d78d4c1ec2bf7d15d33bd8d5e0afdb8a5a24047f095842281c744e600","created_at":1753898578,"content":"Test 1102","kind":1,"pubkey":"056b5b5966f500defb3b790a14633e5ec4a0e8883ca29bc23d0030553edb084a","sig":"d03f0beee7355a8b6ce437b43e01f2d3be8c0f3f17b41a8dec8a9b9804d44ab639b7906c545e4b51820f00b09d00cfa5058916e93126e8a11a65e2623f95f152","tags":[]} 31 """ 32 let test_invalid_note_tampered_date_text = """ 33 {"id":"f4a5635d78d4c1ec2bf7d15d33bd8d5e0afdb8a5a24047f095842281c744e6a3","created_at":1753898579,"content":"Test 1102","kind":1,"pubkey":"056b5b5966f500defb3b790a14633e5ec4a0e8883ca29bc23d0030553edb084a","sig":"d03f0beee7355a8b6ce437b43e01f2d3be8c0f3f17b41a8dec8a9b9804d44ab639b7906c545e4b51820f00b09d00cfa5058916e93126e8a11a65e2623f95f152","tags":[]} 34 """ 35 let test_invalid_note_tampered_pubkey_text = """ 36 {"id":"f4a5635d78d4c1ec2bf7d15d33bd8d5e0afdb8a5a24047f095842281c744e6a3","created_at":1753898578,"content":"Test 1102","kind":1,"pubkey":"056b5b5966f500defb3b790a14633e5ec4a0e8883ca29bc23d0030553edb084b","sig":"d03f0beee7355a8b6ce437b43e01f2d3be8c0f3f17b41a8dec8a9b9804d44ab639b7906c545e4b51820f00b09d00cfa5058916e93126e8a11a65e2623f95f152","tags":[]} 37 """ 38 let test_invalid_note_tampered_content_text = """ 39 {"id":"f4a5635d78d4c1ec2bf7d15d33bd8d5e0afdb8a5a24047f095842281c744e6a3","created_at":1753898578,"content":"Test 1103","kind":1,"pubkey":"056b5b5966f500defb3b790a14633e5ec4a0e8883ca29bc23d0030553edb084a","sig":"d03f0beee7355a8b6ce437b43e01f2d3be8c0f3f17b41a8dec8a9b9804d44ab639b7906c545e4b51820f00b09d00cfa5058916e93126e8a11a65e2623f95f152","tags":[]} 40 """ 41 let test_invalid_note_tampered_kind_text = """ 42 {"id":"f4a5635d78d4c1ec2bf7d15d33bd8d5e0afdb8a5a24047f095842281c744e6a3","created_at":1753898578,"content":"Test 1102","kind":2,"pubkey":"056b5b5966f500defb3b790a14633e5ec4a0e8883ca29bc23d0030553edb084a","sig":"d03f0beee7355a8b6ce437b43e01f2d3be8c0f3f17b41a8dec8a9b9804d44ab639b7906c545e4b51820f00b09d00cfa5058916e93126e8a11a65e2623f95f152","tags":[]} 43 """ 44 let test_invalid_note_tampered_tags_text = """ 45 {"id":"f4a5635d78d4c1ec2bf7d15d33bd8d5e0afdb8a5a24047f095842281c744e6a3","created_at":1753898578,"content":"Test 1102","kind":1,"pubkey":"056b5b5966f500defb3b790a14633e5ec4a0e8883ca29bc23d0030553edb084a","sig":"d03f0beee7355a8b6ce437b43e01f2d3be8c0f3f17b41a8dec8a9b9804d44ab639b7906c545e4b51820f00b09d00cfa5058916e93126e8a11a65e2623f95f152","tags":[["t", "foo"]]} 46 """ 47 48 let test_valid_note = NdbNote.owned_from_json(json: test_valid_note_text)! 49 let test_invalid_note_tampered_sig = NdbNote.owned_from_json(json: test_invalid_note_tampered_sig_text)! 50 var test_invalid_note_tampered_id = NdbNote.owned_from_json(json: test_invalid_note_tampered_id_text)! 51 let test_invalid_note_tampered_date = NdbNote.owned_from_json(json: test_invalid_note_tampered_date_text)! 52 let test_invalid_note_tampered_pubkey = NdbNote.owned_from_json(json: test_invalid_note_tampered_pubkey_text)! 53 let test_invalid_note_tampered_content = NdbNote.owned_from_json(json: test_invalid_note_tampered_content_text)! 54 let test_invalid_note_tampered_kind = NdbNote.owned_from_json(json: test_invalid_note_tampered_kind_text)! 55 let test_invalid_note_tampered_tags = NdbNote.owned_from_json(json: test_invalid_note_tampered_tags_text)! 56 57 XCTAssertEqual(test_valid_note.verify(), true) 58 XCTAssertEqual(test_invalid_note_tampered_sig.verify(), false) 59 XCTAssertEqual(test_invalid_note_tampered_id.verify(), false) 60 XCTAssertEqual(test_invalid_note_tampered_date.verify(), false) 61 XCTAssertEqual(test_invalid_note_tampered_pubkey.verify(), false) 62 XCTAssertEqual(test_invalid_note_tampered_content.verify(), false) 63 XCTAssertEqual(test_invalid_note_tampered_kind.verify(), false) 64 XCTAssertEqual(test_invalid_note_tampered_tags.verify(), false) 65 } 66 67 func testIdEquality() throws { 68 let pubkey = test_pubkey 69 let ev = test_note 70 71 let pubkey_same = Pubkey(Data([0xf7, 0xda, 0xc4, 0x6a, 0xa2, 0x70, 0xf7, 0x28, 0x76, 0x06, 0xa2, 0x2b, 0xeb, 0x4d, 0x77, 0x25, 0x57, 0x3a, 0xfa, 0x0e, 0x02, 0x8c, 0xdf, 0xac, 0x39, 0xa4, 0xcb, 0x23, 0x31, 0x53, 0x7f, 0x66])) 72 73 XCTAssertEqual(pubkey.hashValue, pubkey_same.hashValue) 74 XCTAssertEqual(pubkey, pubkey_same) 75 } 76 77 func testRandomBytes() { 78 let bytes = random_bytes(count: 32) 79 80 print("testRandomBytes \(hex_encode(bytes))") 81 XCTAssertEqual(bytes.count, 32) 82 } 83 84 func testTrimSuffix() { 85 let txt = " bobs " 86 87 XCTAssertEqual(trim_suffix(txt), " bobs") 88 } 89 90 func testParseMentionWithMarkdown() { 91 let md = """ 92 Testing markdown in damus 93 94 **bold** 95 96 _italics_ 97 98 `monospace` 99 100 # h1 101 102 ## h2 103 104 ### h3 105 106 * list1 107 * list2 108 109 > some awesome quote 110 111 [my website](https://jb55.com) 112 """ 113 114 let parsed = parse_note_content(content: .content(md, nil))!.blocks 115 116 XCTAssertNotNil(parsed) 117 XCTAssertEqual(parsed.count, 3) 118 119 XCTAssertTrue(parsed[0].isText) 120 XCTAssertFalse(parsed[0].isURL) 121 122 XCTAssertTrue(parsed[1].isURL) 123 XCTAssertFalse(parsed[1].isText) 124 125 XCTAssertTrue(parsed[2].isText) 126 XCTAssertFalse(parsed[2].isURL) 127 } 128 129 func testStringArrayStorage() { 130 let key = "test_key_string_values" 131 let scoped_key = setting_property_key(key: key) 132 133 let res = setting_set_property_value(scoped_key: scoped_key, old_value: [], new_value: ["a"]) 134 XCTAssertEqual(res, ["a"]) 135 136 let got = setting_get_property_value(key: key, scoped_key: scoped_key, default_value: [String]()) 137 XCTAssertEqual(got, ["a"]) 138 139 _ = setting_set_property_value(scoped_key: scoped_key, old_value: got, new_value: ["a", "b", "c"]) 140 let got2 = setting_get_property_value(key: key, scoped_key: scoped_key, default_value: [String]()) 141 XCTAssertEqual(got2, ["a", "b", "c"]) 142 } 143 144 func testBech32Url() { 145 let parsed = decode_nostr_uri("nostr:npub1xtscya34g58tk0z605fvr788k263gsu6cy9x0mhnm87echrgufzsevkk5s") 146 147 let pk = Pubkey(hex:"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245")! 148 XCTAssertEqual(parsed, .ref(.pubkey(pk))) 149 } 150 151 func testSaveRelayFilters() { 152 var filters = Set<RelayFilter>() 153 154 let filter1 = RelayFilter(timeline: .search, relay_id: RelayURL("wss://abc.com")!) 155 let filter2 = RelayFilter(timeline: .home, relay_id: RelayURL("wss://abc.com")!) 156 filters.insert(filter1) 157 filters.insert(filter2) 158 159 save_relay_filters(test_pubkey, filters: filters) 160 let loaded_filters = load_relay_filters(test_pubkey)! 161 162 XCTAssertEqual(loaded_filters.count, 2) 163 XCTAssertTrue(loaded_filters.contains(filter1)) 164 XCTAssertTrue(loaded_filters.contains(filter2)) 165 XCTAssertEqual(filters, loaded_filters) 166 } 167 168 func testParseUrl() { 169 let parsed = parse_note_content(content: .content("a https://jb55.com b", nil))!.blocks 170 171 XCTAssertNotNil(parsed) 172 XCTAssertEqual(parsed.count, 3) 173 174 let url = URL(string: "https://jb55.com") 175 XCTAssertNotNil(url) 176 177 XCTAssertEqual(parsed[1].asURL, url) 178 } 179 180 func testParseUrlEnd() { 181 let parsed = parse_note_content(content: .content("a https://jb55.com", nil))!.blocks 182 183 XCTAssertNotNil(parsed) 184 XCTAssertEqual(parsed.count, 2) 185 186 XCTAssertEqual(parsed[0].asString, "a ") 187 188 let url = URL(string: "https://jb55.com") 189 XCTAssertNotNil(url) 190 191 XCTAssertEqual(parsed[1].asURL, url) 192 } 193 194 func testParseUrlStart() { 195 let parsed = parse_note_content(content: .content("https://jb55.com br",nil))!.blocks 196 197 XCTAssertNotNil(parsed) 198 XCTAssertEqual(parsed.count, 2) 199 200 let testURL = URL(string: "https://jb55.com") 201 XCTAssertNotNil(testURL) 202 203 XCTAssertEqual(parsed[0].asURL, testURL) 204 205 XCTAssertEqual(parsed[1].asText, " br") 206 } 207 208 func testNoParseUrlWithOnlyWhitespace() { 209 let testString = "https:// " 210 let parsed = parse_note_content(content: .content(testString,nil))!.blocks 211 212 XCTAssertNotNil(parsed) 213 XCTAssertFalse(parsed[0].isURL) 214 XCTAssertEqual(parsed[0].asText, testString) 215 } 216 217 func testNoParseUrlTrailingCharacters() { 218 let testString = "https://foo.bar, " 219 let parsed = parse_note_content(content: .content(testString,nil))!.blocks 220 221 let testURL = URL(string: "https://foo.bar") 222 XCTAssertNotNil(testURL) 223 224 XCTAssertNotNil(parsed) 225 XCTAssertEqual(parsed[0].asURL, testURL) 226 } 227 228 229 /* 230 func testParseMentionBlank() { 231 let parsed = parse_note_content(content: "", tags: [["e", "event_id"]]).blocks 232 233 XCTAssertNotNil(parsed) 234 XCTAssertEqual(parsed.count, 0) 235 } 236 */ 237 238 func testMakeHashtagPost() { 239 let post = NostrPost(content: "#damus some content #bitcoin derp #かっこいい wow", tags: []) 240 let ev = post.to_event(keypair: test_keypair_full)! 241 242 XCTAssertEqual(ev.tags.count, 3) 243 XCTAssertEqual(ev.content, "#damus some content #bitcoin derp #かっこいい wow") 244 XCTAssertEqual(ev.tags[0][0].string(), "t") 245 XCTAssertEqual(ev.tags[0][1].string(), "damus") 246 XCTAssertEqual(ev.tags[1][0].string(), "t") 247 XCTAssertEqual(ev.tags[1][1].string(), "bitcoin") 248 XCTAssertEqual(ev.tags[2][0].string(), "t") 249 XCTAssertEqual(ev.tags[2][1].string(), "かっこいい") 250 } 251 252 func testParseMentionOnlyText() { 253 let tags = [["e", "event_id"]] 254 let ev = NostrEvent(content: "there is no mention here", keypair: test_keypair, tags: tags)! 255 let parsed = parse_note_content(content: .init(note: ev, keypair: test_keypair))!.blocks 256 257 XCTAssertNotNil(parsed) 258 XCTAssertEqual(parsed.count, 1) 259 XCTAssertEqual(parsed[0].asText, "there is no mention here") 260 261 guard case .text(let txt) = parsed[0] else { 262 XCTAssertTrue(false) 263 return 264 } 265 266 XCTAssertEqual(txt, "there is no mention here") 267 } 268 269 func testTagGeneration_Note_ContainsNoTags() { 270 let ev = createEventFromContentString("note1h865g8j9egu30yequqp3e7ccudq8seeaes7nuw3m82vpwc9226tqtudlvp") 271 272 XCTAssertEqual(ev.tags.count, 0) 273 } 274 275 func testTagGeneration_Nevent_ContainsNoTags() { 276 let ev = createEventFromContentString("nevent1qqstna2yrezu5wghjvswqqculvvwxsrcvu7uc0f78gan4xqhvz49d9spr3mhxue69uhkummnw3ez6un9d3shjtn4de6x2argwghx6egpr4mhxue69uhkummnw3ez6ur4vgh8wetvd3hhyer9wghxuet5nxnepm") 277 278 XCTAssertEqual(ev.tags.count, 0) 279 } 280 281 func testTagGeneration_Npub_ContainsPTag() { 282 let ev = createEventFromContentString("npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6") 283 284 XCTAssertEqual(ev.tags.count, 1) 285 XCTAssertEqual(ev.tags[0][0].string(), "p") 286 XCTAssertEqual(ev.tags[0][1].string(), "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d") 287 } 288 289 func testTagGeneration_Nprofile_ContainsPTag() { 290 let ev = createEventFromContentString("nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p") 291 292 XCTAssertEqual(ev.tags.count, 1) 293 XCTAssertEqual(ev.tags[0][0].string(), "p") 294 XCTAssertEqual(ev.tags[0][1].string(), "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d") 295 } 296 297 func testTagGeneration_Naddr_ContainsATag(){ 298 let ev = createEventFromContentString("naddr1qqxnzdesxqmnxvpexqunzvpcqyt8wumn8ghj7un9d3shjtnwdaehgu3wvfskueqzypve7elhmamff3sr5mgxxms4a0rppkmhmn7504h96pfcdkpplvl2jqcyqqq823cnmhuld") 299 300 XCTAssertEqual(ev.tags.count, 1) 301 XCTAssertEqual(ev.tags[0][0].string(), "a") 302 XCTAssertEqual(ev.tags[0][1].string(), "30023:599f67f7df7694c603a6d0636e15ebc610db77dcfd47d6e5d05386d821fb3ea9:1700730909108") 303 } 304 305 } 306 307 private func createEventFromContentString(_ content: String) -> NostrEvent { 308 let post = NostrPost(content: content, tags: []) 309 guard let ev = post.to_event(keypair: test_keypair_full) else { 310 XCTFail("Could not create event") 311 return test_note 312 } 313 314 return ev 315 }