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