+test.ha (3945B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use fmt; 5 use hare::ast; 6 use hare::lex; 7 use hare::unparse; 8 use memio; 9 use os; 10 use strings; 11 12 fn assert_doc_eq(a: doc, b: doc) void = { 13 assert(len(a) == len(b)); 14 for (let i = 0z; i < len(a); i += 1) { 15 match (a[i]) { 16 case let a: paragraph => 17 const b = b[i] as paragraph; 18 assert_paragraph_eq(a, b); 19 case let a: list => 20 const b = b[i] as list; 21 assert(len(a) == len(b)); 22 for (let i = 0z; i < len(a); i += 1) { 23 assert_paragraph_eq(a[i], b[i]); 24 }; 25 case let a: code_sample => 26 const b = b[i] as code_sample; 27 if (a != b) { 28 fmt::errorfln("=== wanted code sample\n{}", b)!; 29 fmt::errorfln("=== got code sample\n{}", a)!; 30 abort(); 31 }; 32 }; 33 }; 34 }; 35 36 fn assert_paragraph_eq(a: paragraph, b: paragraph) void = { 37 fmt::errorln(len(a), len(b))!; 38 assert(len(a) == len(b)); 39 for (let i = 0z; i < len(a); i += 1) { 40 match (a[i]) { 41 case let a: str => 42 const b = b[i] as str; 43 if (a != b) { 44 fmt::errorfln("=== wanted text\n{}", b)!; 45 fmt::errorfln("=== got text\n{}", a)!; 46 abort(); 47 }; 48 case let a: decl_ref => 49 const b = b[i] as decl_ref; 50 if (!ast::ident_eq(a, b)) { 51 fmt::error("=== wanted decl_ref ")!; 52 unparse::ident(os::stderr, b)!; 53 fmt::error("\n=== got decl_ref ")!; 54 unparse::ident(os::stderr, a)!; 55 fmt::errorln()!; 56 abort(); 57 }; 58 case let a: mod_ref => 59 const b = b[i] as mod_ref; 60 if (!ast::ident_eq(a, b)) { 61 fmt::error("=== wanted mod_ref ")!; 62 unparse::ident(os::stderr, b)!; 63 fmt::error("\n=== got mod_ref ")!; 64 unparse::ident(os::stderr, a)!; 65 fmt::errorln()!; 66 abort(); 67 }; 68 }; 69 }; 70 }; 71 72 @test fn doc() void = { 73 // if you have some way in your editor to distinguish tabs from spaces 74 // you're gonna want to use it here 75 let in = memio::fixed(strings::toutf8( 76 ` Blablabla asdfghjkl 77 qwerty[[uiop::]] zxcvbnm 78 79 new paragraph 80 - list starting immediately after paragraph 81 - another list item 82 - yet another 83 but this one 84 spans multiple lines 85 -no leading space 86 still multiple lines 87 88 code sample 89 line 2 90 no leading space 91 92 93 continuing the same code sample 94 indentation is preserved 95 as well as multiple spaces 96 this is now a paragraph because of the [[leading::spaces]] 97 98 - list starting [[after]] [[empty::line::]] 99 100 but with only [one item]] 101 - 102 code sample starting immediately after list with one empty item` 103 )); 104 105 const doc = parse(&in, lex::location { ... })!; 106 defer freeall(doc); 107 108 assert_doc_eq(doc, [ 109 [ 110 "Blablabla asdfghjkl qwerty", 111 ["uiop"]: mod_ref, 112 " zxcvbnm", 113 ]: paragraph, 114 115 ["new paragraph"]: paragraph, 116 117 [ 118 ["list starting immediately after paragraph"], 119 ["another list item"], 120 ["yet another but this one spans multiple lines"], 121 ["no leading space still multiple lines"], 122 ]: list, 123 124 `code sample 125 line 2 126 no leading space 127 128 129 continuing the same code sample 130 indentation is preserved 131 as well as multiple spaces`: code_sample, 132 133 [ 134 " this is now a paragraph because of the ", 135 ["leading", "spaces"]: decl_ref, 136 ]: paragraph, 137 138 [ 139 [ 140 "list starting ", 141 ["after"]: decl_ref, 142 " ", 143 ["empty", "line"]: mod_ref, 144 ], 145 ]: list, 146 147 ["but with only [one item]]"]: paragraph, 148 149 [[]]: list, 150 151 "code sample starting immediately after list with one empty item": code_sample, 152 ]); 153 }; 154 155 @test fn invalid_ref() void = { 156 const tests: [_](str, uint, uint) = [ 157 ("[[abort]]", 1, 3), 158 ("[[::foo]]", 1, 3), 159 ("[[]]", 1, 3), 160 ("[[foo]", 1, 7), 161 (" \t\n a\n asdf\t [[]]", 3, 12), 162 ]; 163 for (let i = 0u; i < len(tests): uint; i += 1) { 164 let in = memio::fixed(strings::toutf8(tests[i].0)); 165 fmt::errorln(tests[i].0)!; 166 const err = parse(&in, lex::location { 167 path = "<test>", 168 line = i + 1, 169 col = i + 1, 170 }) as lex::syntax; 171 assert(err.0.path == "<test>"); 172 assert(err.0.line == i + tests[i].1); 173 assert(err.0.col == i + tests[i].2); 174 }; 175 };