diff options
Diffstat (limited to 'bench/src/tests.zig')
| -rw-r--r-- | bench/src/tests.zig | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/bench/src/tests.zig b/bench/src/tests.zig new file mode 100644 index 0000000..a8a2a98 --- /dev/null +++ b/bench/src/tests.zig | |||
| @@ -0,0 +1,229 @@ | |||
| 1 | const std = @import("std"); | ||
| 2 | const testing = std.testing; | ||
| 3 | const expect = testing.expect; | ||
| 4 | const expectEqual = testing.expectEqual; | ||
| 5 | const expectEqualStrings = testing.expectEqualStrings; | ||
| 6 | |||
| 7 | const allocator = testing.allocator; | ||
| 8 | |||
| 9 | const GenCatData = @import("GenCatData"); | ||
| 10 | |||
| 11 | test "General Category" { | ||
| 12 | const gcd = try GenCatData.init(allocator); | ||
| 13 | defer gcd.deinit(); | ||
| 14 | |||
| 15 | try expect(gcd.gc('A') == .Lu); // Lu: uppercase letter | ||
| 16 | try expect(gcd.gc('3') == .Nd); // Nd: Decimal number | ||
| 17 | try expect(gcd.isControl(0)); | ||
| 18 | try expect(gcd.isLetter('z')); | ||
| 19 | try expect(gcd.isMark('\u{301}')); | ||
| 20 | try expect(gcd.isNumber('3')); | ||
| 21 | try expect(gcd.isPunctuation('[')); | ||
| 22 | try expect(gcd.isSeparator(' ')); | ||
| 23 | try expect(gcd.isSymbol('©')); | ||
| 24 | } | ||
| 25 | |||
| 26 | const PropsData = @import("PropsData"); | ||
| 27 | |||
| 28 | test "Properties" { | ||
| 29 | const pd = try PropsData.init(allocator); | ||
| 30 | defer pd.deinit(); | ||
| 31 | |||
| 32 | try expect(pd.isMath('+')); | ||
| 33 | try expect(pd.isAlphabetic('Z')); | ||
| 34 | try expect(pd.isWhitespace(' ')); | ||
| 35 | try expect(pd.isHexDigit('f')); | ||
| 36 | try expect(!pd.isHexDigit('z')); | ||
| 37 | |||
| 38 | try expect(pd.isDiacritic('\u{301}')); | ||
| 39 | try expect(pd.isIdStart('Z')); // Identifier start character | ||
| 40 | try expect(!pd.isIdStart('1')); | ||
| 41 | try expect(pd.isIdContinue('1')); | ||
| 42 | try expect(pd.isXidStart('\u{b33}')); // Extended identifier start character | ||
| 43 | try expect(pd.isXidContinue('\u{e33}')); | ||
| 44 | try expect(!pd.isXidStart('1')); | ||
| 45 | |||
| 46 | // Note surprising Unicode numeric types! | ||
| 47 | try expect(pd.isNumeric('\u{277f}')); | ||
| 48 | try expect(!pd.isNumeric('3')); | ||
| 49 | try expect(pd.isDigit('\u{2070}')); | ||
| 50 | try expect(!pd.isDigit('3')); | ||
| 51 | try expect(pd.isDecimal('3')); | ||
| 52 | } | ||
| 53 | |||
| 54 | const CaseData = @import("CaseData"); | ||
| 55 | |||
| 56 | test "Case" { | ||
| 57 | const cd = try CaseData.init(allocator); | ||
| 58 | defer cd.deinit(); | ||
| 59 | |||
| 60 | try expect(cd.isUpper('A')); | ||
| 61 | try expect('A' == cd.toUpper('a')); | ||
| 62 | try expect(cd.isLower('a')); | ||
| 63 | try expect('a' == cd.toLower('A')); | ||
| 64 | |||
| 65 | try expect(cd.isCased('É')); | ||
| 66 | try expect(!cd.isCased('3')); | ||
| 67 | |||
| 68 | try expect(cd.isUpperStr("HELLO 123!")); | ||
| 69 | const ucased = try cd.toUpperStr(allocator, "hello 123"); | ||
| 70 | defer allocator.free(ucased); | ||
| 71 | try expectEqualStrings("HELLO 123", ucased); | ||
| 72 | |||
| 73 | try expect(cd.isLowerStr("hello 123!")); | ||
| 74 | const lcased = try cd.toLowerStr(allocator, "HELLO 123"); | ||
| 75 | defer allocator.free(lcased); | ||
| 76 | try expectEqualStrings("hello 123", lcased); | ||
| 77 | } | ||
| 78 | |||
| 79 | const Normalize = @import("Normalize"); | ||
| 80 | |||
| 81 | test "Normalization" { | ||
| 82 | var norm_data = try Normalize.NormData.init(allocator); | ||
| 83 | defer norm_data.deinit(); | ||
| 84 | const n = Normalize{ .norm_data = &norm_data }; | ||
| 85 | |||
| 86 | // NFD: Canonical decomposition | ||
| 87 | const nfd_result = try n.nfd(allocator, "Héllo World! \u{3d3}"); | ||
| 88 | defer nfd_result.deinit(); | ||
| 89 | try expectEqualStrings("He\u{301}llo World! \u{3d2}\u{301}", nfd_result.slice); | ||
| 90 | |||
| 91 | // NFKD: Compatibility decomposition | ||
| 92 | const nfkd_result = try n.nfkd(allocator, "Héllo World! \u{3d3}"); | ||
| 93 | defer nfkd_result.deinit(); | ||
| 94 | try expectEqualStrings("He\u{301}llo World! \u{3a5}\u{301}", nfkd_result.slice); | ||
| 95 | |||
| 96 | // NFC: Canonical composition | ||
| 97 | const nfc_result = try n.nfc(allocator, "Complex char: \u{3D2}\u{301}"); | ||
| 98 | defer nfc_result.deinit(); | ||
| 99 | try expectEqualStrings("Complex char: \u{3D3}", nfc_result.slice); | ||
| 100 | |||
| 101 | // NFKC: Compatibility composition | ||
| 102 | const nfkc_result = try n.nfkc(allocator, "Complex char: \u{03A5}\u{0301}"); | ||
| 103 | defer nfkc_result.deinit(); | ||
| 104 | try expectEqualStrings("Complex char: \u{038E}", nfkc_result.slice); | ||
| 105 | |||
| 106 | // Test for equality of two strings after normalizing to NFC. | ||
| 107 | try expect(try n.eql(allocator, "foé", "foe\u{0301}")); | ||
| 108 | try expect(try n.eql(allocator, "foϓ", "fo\u{03D2}\u{0301}")); | ||
| 109 | } | ||
| 110 | |||
| 111 | const CaseFold = @import("CaseFold"); | ||
| 112 | |||
| 113 | test "Caseless matching" { | ||
| 114 | var norm_data = try Normalize.NormData.init(allocator); | ||
| 115 | defer norm_data.deinit(); | ||
| 116 | const n = Normalize{ .norm_data = &norm_data }; | ||
| 117 | |||
| 118 | const cfd = try CaseFold.FoldData.init(allocator); | ||
| 119 | defer cfd.deinit(); | ||
| 120 | const cf = CaseFold{ .fold_data = &cfd }; | ||
| 121 | |||
| 122 | // compatCaselessMatch provides the deepest level of caseless | ||
| 123 | // matching because it decomposes and composes fully to NFKC. | ||
| 124 | const a = "Héllo World! \u{3d3}"; | ||
| 125 | const b = "He\u{301}llo World! \u{3a5}\u{301}"; | ||
| 126 | try expect(try cf.compatCaselessMatch(allocator, &n, a, b)); | ||
| 127 | |||
| 128 | const c = "He\u{301}llo World! \u{3d2}\u{301}"; | ||
| 129 | try expect(try cf.compatCaselessMatch(allocator, &n, a, c)); | ||
| 130 | |||
| 131 | // canonCaselessMatch isn't as comprehensive as compatCaselessMatch | ||
| 132 | // because it only decomposes and composes to NFC. But it's faster. | ||
| 133 | try expect(!try cf.canonCaselessMatch(allocator, &n, a, b)); | ||
| 134 | try expect(try cf.canonCaselessMatch(allocator, &n, a, c)); | ||
| 135 | } | ||
| 136 | |||
| 137 | const DisplayWidth = @import("DisplayWidth"); | ||
| 138 | |||
| 139 | test "Display width" { | ||
| 140 | const dwd = try DisplayWidth.DisplayWidthData.init(allocator); | ||
| 141 | defer dwd.deinit(); | ||
| 142 | const dw = DisplayWidth{ .data = &dwd }; | ||
| 143 | |||
| 144 | // String display width | ||
| 145 | try expectEqual(@as(usize, 5), dw.strWidth("Hello\r\n")); | ||
| 146 | try expectEqual(@as(usize, 8), dw.strWidth("Hello 😊")); | ||
| 147 | try expectEqual(@as(usize, 8), dw.strWidth("Héllo 😊")); | ||
| 148 | try expectEqual(@as(usize, 9), dw.strWidth("Ẓ̌á̲l͔̝̞̄̑͌g̖̘̘̔̔͢͞͝o̪̔T̢̙̫̈̍͞e̬͈͕͌̏͑x̺̍ṭ̓̓ͅ")); | ||
| 149 | try expectEqual(@as(usize, 17), dw.strWidth("슬라바 우크라이나")); | ||
| 150 | |||
| 151 | // Centering text | ||
| 152 | const centered = try dw.center(allocator, "w😊w", 10, "-"); | ||
| 153 | defer allocator.free(centered); | ||
| 154 | try expectEqualStrings("---w😊w---", centered); | ||
| 155 | |||
| 156 | // Pad left | ||
| 157 | const right_aligned = try dw.padLeft(allocator, "abc", 9, "*"); | ||
| 158 | defer allocator.free(right_aligned); | ||
| 159 | try expectEqualStrings("******abc", right_aligned); | ||
| 160 | |||
| 161 | // Pad right | ||
| 162 | const left_aligned = try dw.padRight(allocator, "abc", 9, "*"); | ||
| 163 | defer allocator.free(left_aligned); | ||
| 164 | try expectEqualStrings("abc******", left_aligned); | ||
| 165 | |||
| 166 | // Wrap text | ||
| 167 | const input = "The quick brown fox\r\njumped over the lazy dog!"; | ||
| 168 | const wrapped = try dw.wrap(allocator, input, 10, 3); | ||
| 169 | defer allocator.free(wrapped); | ||
| 170 | const want = | ||
| 171 | \\The quick | ||
| 172 | \\brown fox | ||
| 173 | \\jumped | ||
| 174 | \\over the | ||
| 175 | \\lazy dog! | ||
| 176 | ; | ||
| 177 | try expectEqualStrings(want, wrapped); | ||
| 178 | } | ||
| 179 | |||
| 180 | const code_point = @import("code_point"); | ||
| 181 | |||
| 182 | test "Code point iterator" { | ||
| 183 | const str = "Hi 😊"; | ||
| 184 | var iter = code_point.Iterator{ .bytes = str }; | ||
| 185 | var i: usize = 0; | ||
| 186 | |||
| 187 | while (iter.next()) |cp| : (i += 1) { | ||
| 188 | if (i == 0) try expect(cp.code == 'H'); | ||
| 189 | if (i == 1) try expect(cp.code == 'i'); | ||
| 190 | if (i == 2) try expect(cp.code == ' '); | ||
| 191 | |||
| 192 | if (i == 3) { | ||
| 193 | try expect(cp.code == '😊'); | ||
| 194 | try expect(cp.offset == 3); | ||
| 195 | try expect(cp.len == 4); | ||
| 196 | } | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | const grapheme = @import("grapheme"); | ||
| 201 | |||
| 202 | test "Grapheme cluster iterator" { | ||
| 203 | const gd = try grapheme.GraphemeData.init(allocator); | ||
| 204 | defer gd.deinit(); | ||
| 205 | const str = "He\u{301}"; // Hé | ||
| 206 | var iter = grapheme.Iterator.init(str, &gd); | ||
| 207 | var i: usize = 0; | ||
| 208 | |||
| 209 | while (iter.next()) |gc| : (i += 1) { | ||
| 210 | if (i == 0) try expect(gc.len == 1); | ||
| 211 | |||
| 212 | if (i == 1) { | ||
| 213 | try expect(gc.len == 3); | ||
| 214 | try expect(gc.offset == 1); | ||
| 215 | try expectEqualStrings("e\u{301}", gc.bytes(str)); | ||
| 216 | } | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | const ScriptsData = @import("ScriptsData"); | ||
| 221 | |||
| 222 | test "Scripts" { | ||
| 223 | const sd = try ScriptsData.init(allocator); | ||
| 224 | defer sd.deinit(); | ||
| 225 | |||
| 226 | try expect(sd.script('A') == .Latin); | ||
| 227 | try expect(sd.script('Ω') == .Greek); | ||
| 228 | try expect(sd.script('צ') == .Hebrew); | ||
| 229 | } | ||