1 #include <cassert> 2 #include <cstdlib> 3 #include "utils.h" 4 #include "doctest.h" 5 6 constexpr char32_t escape = '\\'; 7 // Correct Tests 8 TEST_SUITE_BEGIN("UTF"); 9 10 struct TestSet { 11 std::string u8; 12 std::u16string u16; 13 std::u32string u32; 14 }; 15 16 #define CONCAT2(x, y) x ## y 17 #define CONCAT(x, y) CONCAT2(x, y) 18 #define STRINGIZE(x) #x 19 //#define TS(X) { CONCAT(u8, STRINGIZE(X)), CONCAT(u, STRINGIZE(X)), CONCAT(U, STRINGIZE(X)) } 20 #define TS(X) { CONCAT(u8, X), CONCAT(u, X), CONCAT(U, X) } 21 22 TestSet tests[] = { 23 //Valid Strings 24 TS("κόσμε"), 25 //First Char tests 26 TS("\U00000000"), 27 TS("\U00000080"), 28 TS("\U00000800"), 29 TS("\U00010000"), 30 // TS("\U00200000"), 31 // TS("\U04000000"), 32 // //Last char tests 33 TS("\U0000007F"), 34 TS("\U000007FF"), 35 TS("\U0000FFFF"), 36 // TS("\U001FFFFF"), 37 // TS("\U03FFFFFF"), 38 // TS("\U7FFFFFFF"), 39 // //Other boundary tests 40 TS("\U0000D7FF"), 41 TS("\U0000E000"), 42 TS("\U0000FFFD"), 43 TS("\U0010FFFF"), 44 // TS("\U00110000"), 45 }; 46 47 TEST_CASE("8to16") { 48 for (auto& ts: tests) { 49 auto u16 = Utils::DecodeUTF16(ts.u8); 50 REQUIRE_EQ(u16, ts.u16); 51 } 52 } 53 54 TEST_CASE("8to32") { 55 for (auto& ts: tests) { 56 auto u32 = Utils::DecodeUTF32(ts.u8); 57 REQUIRE_EQ(u32, ts.u32); 58 } 59 } 60 61 TEST_CASE("16to8") { 62 for (auto& ts: tests) { 63 auto u8 = Utils::EncodeUTF(ts.u16); 64 REQUIRE_EQ(u8, ts.u8); 65 } 66 } 67 68 TEST_CASE("32to8") { 69 for (auto& ts: tests) { 70 auto u8 = Utils::EncodeUTF(ts.u32); 71 REQUIRE_EQ(u8, ts.u8); 72 } 73 } 74 75 TEST_CASE("next") { 76 for (auto& ts: tests) { 77 const char* iter = ts.u8.data(); 78 const char* const e = ts.u8.data() + ts.u8.size(); 79 int i = 0; 80 while (iter < e) { 81 auto ret = Utils::UTF8Next(iter, e); 82 REQUIRE_EQ(ret.ch, ts.u32[i]); 83 iter = ret.next; 84 ++i; 85 } 86 } 87 } 88 89 TEST_CASE("TextNext") { 90 std::string text = u8"H $A$B\\\\\\^\\n\nぽ"; 91 const auto* iter = text.data(); 92 const auto* end = text.data() + text.size(); 93 94 Utils::TextRet ret; 95 ret = Utils::TextNext(iter, end, escape); 96 REQUIRE_EQ(ret.ch, 'H'); 97 REQUIRE_NE(ret.next, end); 98 REQUIRE_FALSE(ret.is_exfont); 99 REQUIRE_FALSE(ret.is_escape); 100 iter = ret.next; 101 102 ret = Utils::TextNext(iter, end, escape); 103 REQUIRE_EQ(ret.ch, ' '); 104 REQUIRE_NE(ret.next, end); 105 REQUIRE_FALSE(ret.is_exfont); 106 REQUIRE_FALSE(ret.is_escape); 107 iter = ret.next; 108 109 ret = Utils::TextNext(iter, end, escape); 110 REQUIRE_EQ(ret.ch, 0); 111 REQUIRE_NE(ret.next, end); 112 REQUIRE(ret.is_exfont); 113 REQUIRE_FALSE(ret.is_escape); 114 iter = ret.next; 115 116 ret = Utils::TextNext(iter, end, escape); 117 REQUIRE_EQ(ret.ch, 1); 118 REQUIRE_NE(ret.next, end); 119 REQUIRE(ret.is_exfont); 120 REQUIRE_FALSE(ret.is_escape); 121 iter = ret.next; 122 123 ret = Utils::TextNext(iter, end, escape); 124 REQUIRE_EQ(ret.ch, '\\'); 125 REQUIRE_NE(ret.next, end); 126 REQUIRE_FALSE(ret.is_exfont); 127 REQUIRE(ret.is_escape); 128 iter = ret.next; 129 130 ret = Utils::TextNext(iter, end, escape); 131 REQUIRE_EQ(ret.ch, '^'); 132 REQUIRE_NE(ret.next, end); 133 REQUIRE_FALSE(ret.is_exfont); 134 REQUIRE(ret.is_escape); 135 iter = ret.next; 136 137 ret = Utils::TextNext(iter, end, escape); 138 REQUIRE_EQ(ret.ch, 'n'); 139 REQUIRE_NE(ret.next, end); 140 REQUIRE_FALSE(ret.is_exfont); 141 REQUIRE(ret.is_escape); 142 iter = ret.next; 143 144 ret = Utils::TextNext(iter, end, escape); 145 REQUIRE_EQ(ret.ch, '\n'); 146 REQUIRE_NE(ret.next, end); 147 REQUIRE_FALSE(ret.is_exfont); 148 REQUIRE_FALSE(ret.is_escape); 149 iter = ret.next; 150 151 ret = Utils::TextNext(iter, end, escape); 152 REQUIRE_EQ(ret.ch, U'ぽ'); 153 REQUIRE_EQ(ret.next, end); 154 REQUIRE_FALSE(ret.is_exfont); 155 REQUIRE_FALSE(ret.is_escape); 156 iter = ret.next; 157 } 158 159 TEST_CASE("TextNextNoEscape") { 160 std::string text = u8"\\$"; 161 const auto* iter = text.data(); 162 const auto* end = text.data() + text.size(); 163 164 Utils::TextRet ret; 165 166 ret = Utils::TextNext(iter, end, 0); 167 REQUIRE_EQ(ret.ch, '\\'); 168 REQUIRE_NE(ret.next, end); 169 REQUIRE_FALSE(ret.is_exfont); 170 REQUIRE_FALSE(ret.is_escape); 171 iter = ret.next; 172 173 ret = Utils::TextNext(iter, end, 0); 174 REQUIRE_EQ(ret.ch, '$'); 175 REQUIRE_EQ(ret.next, end); 176 REQUIRE_FALSE(ret.is_exfont); 177 REQUIRE_FALSE(ret.is_escape); 178 iter = ret.next; 179 } 180 181 TEST_SUITE_END(); 182