damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

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 }