1 #include "TokenTest.hpp"
3 #include "io/TokenStreamReader.hpp"
7 #include <glm/gtx/io.hpp>
9 CPPUNIT_TEST_SUITE_REGISTRATION(blank::test::TokenTest);
16 void TokenTest::setUp() {
20 void TokenTest::tearDown() {
25 void TokenTest::testTypeIO() {
26 AssertStreamOutput(Token::UNKNOWN, "UNKNOWN");
27 AssertStreamOutput(Token::ANGLE_BRACKET_OPEN, "ANGLE_BRACKET_OPEN");
28 AssertStreamOutput(Token::ANGLE_BRACKET_CLOSE, "ANGLE_BRACKET_CLOSE");
29 AssertStreamOutput(Token::CHEVRON_OPEN, "CHEVRON_OPEN");
30 AssertStreamOutput(Token::CHEVRON_CLOSE, "CHEVRON_CLOSE");
31 AssertStreamOutput(Token::BRACKET_OPEN, "BRACKET_OPEN");
32 AssertStreamOutput(Token::BRACKET_CLOSE, "BRACKET_CLOSE");
33 AssertStreamOutput(Token::PARENTHESIS_OPEN, "PARENTHESIS_OPEN");
34 AssertStreamOutput(Token::PARENTHESIS_CLOSE, "PARENTHESIS_CLOSE");
35 AssertStreamOutput(Token::COLON, "COLON");
36 AssertStreamOutput(Token::SEMICOLON, "SEMICOLON");
37 AssertStreamOutput(Token::COMMA, "COMMA");
38 AssertStreamOutput(Token::EQUALS, "EQUALS");
39 AssertStreamOutput(Token::NUMBER, "NUMBER");
40 AssertStreamOutput(Token::STRING, "STRING");
41 AssertStreamOutput(Token::IDENTIFIER, "IDENTIFIER");
42 AssertStreamOutput(Token::COMMENT, "COMMENT");
45 void TokenTest::testTokenIO() {
47 t.value = "why oh why";
48 AssertStreamOutput(t, "UNKNOWN(why oh why)");
49 t.type = Token::UNKNOWN;
50 t.value = "do I have no purpose";
51 AssertStreamOutput(t, "UNKNOWN(do I have no purpose)");
52 t.type = Token::ANGLE_BRACKET_OPEN;
53 AssertStreamOutput(t, "ANGLE_BRACKET_OPEN");
54 t.type = Token::ANGLE_BRACKET_CLOSE;
55 AssertStreamOutput(t, "ANGLE_BRACKET_CLOSE");
56 t.type = Token::CHEVRON_OPEN;
57 AssertStreamOutput(t, "CHEVRON_OPEN");
58 t.type = Token::CHEVRON_CLOSE;
59 AssertStreamOutput(t, "CHEVRON_CLOSE");
60 t.type = Token::BRACKET_OPEN;
61 AssertStreamOutput(t, "BRACKET_OPEN");
62 t.type = Token::BRACKET_CLOSE;
63 AssertStreamOutput(t, "BRACKET_CLOSE");
64 t.type = Token::PARENTHESIS_OPEN;
65 AssertStreamOutput(t, "PARENTHESIS_OPEN");
66 t.type = Token::PARENTHESIS_CLOSE;
67 AssertStreamOutput(t, "PARENTHESIS_CLOSE");
68 t.type = Token::COLON;
69 AssertStreamOutput(t, "COLON");
70 t.type = Token::SEMICOLON;
71 AssertStreamOutput(t, "SEMICOLON");
72 t.type = Token::COMMA;
73 AssertStreamOutput(t, "COMMA");
74 t.type = Token::EQUALS;
75 AssertStreamOutput(t, "EQUALS");
76 t.type = Token::NUMBER;
78 AssertStreamOutput(t, "NUMBER(15)");
79 t.type = Token::STRING;
80 t.value = "hello world";
81 AssertStreamOutput(t, "STRING(hello world)");
82 t.type = Token::IDENTIFIER;
84 AssertStreamOutput(t, "IDENTIFIER(foo)");
85 t.type = Token::COMMENT;
86 t.value = "WITHOUT ANY WARRANTY";
87 AssertStreamOutput(t, "COMMENT(WITHOUT ANY WARRANTY)");
90 void TokenTest::testTokenizer() {
92 stream << "[{0},<.5>+3=/**\n * test\n */ (-1.5); foo_bar.baz:\"hello\\r\\n\\t\\\"world\\\"\" ] // this line\n#that line";
96 Token token(in.Next());
97 AssertToken(token.type, token.value, in.Current());
98 AssertToken(Token::BRACKET_OPEN, token);
101 AssertToken(Token::ANGLE_BRACKET_OPEN, in.Next());
103 AssertToken(Token::NUMBER, "0", in.Next());
105 AssertToken(Token::ANGLE_BRACKET_CLOSE, in.Next());
107 AssertToken(Token::COMMA, in.Next());
109 AssertToken(Token::CHEVRON_OPEN, in.Next());
111 AssertToken(Token::NUMBER, ".5", in.Next());
113 AssertToken(Token::CHEVRON_CLOSE, in.Next());
115 AssertToken(Token::NUMBER, "+3", in.Next());
117 AssertToken(Token::EQUALS, in.Next());
119 AssertToken(Token::COMMENT, "*\n * test\n ", in.Next());
121 AssertToken(Token::PARENTHESIS_OPEN, in.Next());
123 AssertToken(Token::NUMBER, "-1.5", in.Next());
125 AssertToken(Token::PARENTHESIS_CLOSE, in.Next());
127 AssertToken(Token::SEMICOLON, in.Next());
129 AssertToken(Token::IDENTIFIER, "foo_bar.baz", in.Next());
131 AssertToken(Token::COLON, in.Next());
133 AssertToken(Token::STRING, "hello\r\n\t\"world\"", in.Next());
135 AssertToken(Token::BRACKET_CLOSE, in.Next());
137 AssertToken(Token::COMMENT, " this line", in.Next());
139 AssertToken(Token::COMMENT, "that line", in.Next());
140 CPPUNIT_ASSERT_MESSAGE("expected end of stream", !in.HasMore());
141 CPPUNIT_ASSERT_THROW_MESSAGE(
142 "extracting token after EOS",
143 in.Next(), std::runtime_error);
146 void TokenTest::testTokenizerBrokenComment() {
149 stream << "/* just one more thing…*";
150 Tokenizer in(stream);
152 CPPUNIT_ASSERT_THROW_MESSAGE(
153 "half-closed comment should throw",
154 in.Next(), std::runtime_error);
159 Tokenizer in(stream);
161 CPPUNIT_ASSERT_THROW_MESSAGE(
162 "sole '/' at end of stream should throw",
163 in.Next(), std::runtime_error);
168 Tokenizer in(stream);
170 CPPUNIT_ASSERT_THROW_MESSAGE(
171 "'/' followed by garbage should throw",
172 in.Next(), std::runtime_error);
180 void assert_read(std::string message, T expected, T actual, TokenStreamReader &in) {
182 msg << message << ", current token: " << in.Peek();
183 CPPUNIT_ASSERT_EQUAL_MESSAGE(
190 void TokenTest::testReader() {
194 "true false yes no on off\n"
195 "\"true\" \"false\" \"yes\" \"no\" \"on\" \"off\"\n"
198 "foo foo_bar vec.y\n"
201 ".5 1.5 0.25 -1.75 0.625\n"
204 "\"hello\" \"\" \"\\r\\n\\t\\\"\"\n"
206 "[1,0] [ 0.707, 0.707 ] // vec2\n"
207 "[.577,.577 ,0.577] [ 1,-2,3] // vec3\n"
208 "[ 0, 0, 0, 1 ] [1,0,0,-1.0] // vec4\n"
209 "[640, 480] [3, 4, 5] [0, -10, 100, -1000] # ivecs\n"
210 "[ -0.945, 0, -0.326, 0] # quat\n"
212 TokenStreamReader in(ss);
217 in.ReadBoolean(value_bool);
218 assert_read("reading boolean true", true, value_bool, in);
219 in.ReadBoolean(value_bool);
220 assert_read("reading boolean false", false, value_bool, in);
221 in.ReadBoolean(value_bool);
222 assert_read("reading boolean yes", true, value_bool, in);
223 in.ReadBoolean(value_bool);
224 assert_read("reading boolean no", false, value_bool, in);
225 in.ReadBoolean(value_bool);
226 assert_read("reading boolean on", true, value_bool, in);
227 in.ReadBoolean(value_bool);
228 assert_read("reading boolean off", false, value_bool, in);
230 in.ReadBoolean(value_bool);
231 assert_read("reading boolean \"true\"", true, value_bool, in);
232 in.ReadBoolean(value_bool);
233 assert_read("reading boolean \"false\"", false, value_bool, in);
234 in.ReadBoolean(value_bool);
235 assert_read("reading boolean \"yes\"", true, value_bool, in);
236 in.ReadBoolean(value_bool);
237 assert_read("reading boolean \"no\"", false, value_bool, in);
238 in.ReadBoolean(value_bool);
239 assert_read("reading boolean \"on\"", true, value_bool, in);
240 in.ReadBoolean(value_bool);
241 assert_read("reading boolean \"off\"", false, value_bool, in);
243 in.ReadBoolean(value_bool);
244 assert_read("reading boolean 1", true, value_bool, in);
245 in.ReadBoolean(value_bool);
246 assert_read("reading boolean 0", false, value_bool, in);
247 in.ReadBoolean(value_bool);
248 assert_read("reading boolean -1", true, value_bool, in);
253 in.ReadIdentifier(value_ident);
254 assert_read<string>("reading identifier foo", "foo", value_ident, in);
255 in.ReadIdentifier(value_ident);
256 assert_read<string>("reading identifier foo_bar", "foo_bar", value_ident, in);
257 in.ReadIdentifier(value_ident);
258 assert_read<string>("reading identifier vec.y", "vec.y", value_ident, in);
262 in.ReadNumber(value_int);
263 assert_read("reading integer 0", 0, value_int, in);
264 in.ReadNumber(value_int);
265 assert_read("reading integer 1", 1, value_int, in);
266 in.ReadNumber(value_int);
267 assert_read("reading integer +2", 2, value_int, in);
268 in.ReadNumber(value_int);
269 assert_read("reading integer -3", -3, value_int, in);
270 in.ReadNumber(value_int);
271 assert_read("reading integer 4.5", 4, value_int, in);
274 in.ReadNumber(value_float);
275 assert_read("reading float .5", .5f, value_float, in);
276 in.ReadNumber(value_float);
277 assert_read("reading float 1.5", 1.5f, value_float, in);
278 in.ReadNumber(value_float);
279 assert_read("reading float 0.25", .25f, value_float, in);
280 in.ReadNumber(value_float);
281 assert_read("reading float -1.75", -1.75f, value_float, in);
282 in.ReadNumber(value_float);
283 assert_read("reading float 0.625", 0.625f, value_float, in);
285 unsigned long value_uint;
286 in.ReadNumber(value_uint);
287 assert_read("reading unsigned integer 0", 0ul, value_uint, in);
288 in.ReadNumber(value_uint);
289 assert_read("reading unsigned integer 1", 1ul, value_uint, in);
290 in.ReadNumber(value_uint);
291 assert_read("reading unsigned integer -1", -1ul, value_uint, in);
292 in.ReadNumber(value_uint);
293 assert_read("reading unsigned integer 2.5", 2ul, value_uint, in);
298 in.ReadString(value_string);
300 "reading string \"hello\"",
301 "hello", value_string, in);
302 in.ReadString(value_string);
304 "reading string \"\"",
305 "", value_string, in);
306 in.ReadString(value_string);
308 "reading string \"\\r\\n\\t\\\"\"",
309 "\r\n\t\"", value_string, in);
313 glm::vec2 value_vec2;
314 in.ReadVec(value_vec2);
316 "reading vector [1,0]",
317 glm::vec2(1, 0), value_vec2, in);
318 in.ReadVec(value_vec2);
320 "reading vector [ 0.707, 0.707 ]",
321 glm::vec2(.707, .707), value_vec2, in);
323 glm::vec3 value_vec3;
324 in.ReadVec(value_vec3);
326 "reading vector [.577,.577 ,0.577]",
327 glm::vec3(.577, .577, .577), value_vec3, in);
328 in.ReadVec(value_vec3);
330 "reading vector [ 1,-2,3]",
331 glm::vec3(1, -2, 3), value_vec3, in);
333 glm::vec4 value_vec4;
334 in.ReadVec(value_vec4);
336 "reading vector [ 0, 0, 0, 1 ]",
337 glm::vec4(0, 0, 0, 1), value_vec4, in);
338 in.ReadVec(value_vec4);
340 "reading vector [1,0,0,-1.0]",
341 glm::vec4(1, 0, 0, -1), value_vec4, in);
343 glm::ivec2 value_ivec2;
344 in.ReadVec(value_ivec2);
346 "reading integer vector [640, 480]",
347 glm::ivec2(640, 480), value_ivec2, in);
348 glm::ivec3 value_ivec3;
349 in.ReadVec(value_ivec3);
351 "reading integer vector [3, 4, 5]",
352 glm::ivec3(3, 4, 5), value_ivec3, in);
353 glm::ivec4 value_ivec4;
354 in.ReadVec(value_ivec4);
356 "reading integer vector [0, -10, 100, -1000]",
357 glm::ivec4(0, -10, 100, -1000), value_ivec4, in);
359 glm::quat value_quat;
360 in.ReadQuat(value_quat);
362 "reading quaternion [ -0.945, 0, -0.326, 0]",
363 glm::quat(-0.945, 0, -0.326, 0), value_quat, in);
364 // TODO: comment at end of stream makes it think there's more?
365 //CPPUNIT_ASSERT_MESSAGE("expected end of stream", !in.HasMore());
366 // TODO: and it even works??
367 //CPPUNIT_ASSERT_THROW_MESSAGE(
368 // "extracting token after EOS",
369 // in.Next(), std::runtime_error);
372 void TokenTest::testReaderEmpty() {
373 { // zero length stream
376 TokenStreamReader in(ss);
377 CPPUNIT_ASSERT_MESSAGE(
378 "empty stream shouldn't have tokens",
381 { // stream consisting solely of comments
388 "// is there anybody out there\n"
390 TokenStreamReader in(ss);
391 CPPUNIT_ASSERT_MESSAGE(
392 "comment stream shouldn't have tokens",
397 void TokenTest::testReaderMalformed() {
401 TokenStreamReader in(ss);
402 CPPUNIT_ASSERT_THROW_MESSAGE(
403 "unexpected token type should throw",
404 in.GetInt(), std::runtime_error);
409 TokenStreamReader in(ss);
410 CPPUNIT_ASSERT_THROW_MESSAGE(
411 "casting ':' to bool should throw",
412 in.GetBool(), std::runtime_error);
417 TokenStreamReader in(ss);
418 CPPUNIT_ASSERT_THROW_MESSAGE(
419 "casting \"hello\" to bool should throw",
420 in.GetBool(), std::runtime_error);
425 void TokenTest::AssertStreamOutput(
431 CPPUNIT_ASSERT_EQUAL_MESSAGE(
432 "unexpected std::ostream << Token::Type result",
433 expected, conv.str());
436 void TokenTest::AssertStreamOutput(
442 CPPUNIT_ASSERT_EQUAL_MESSAGE(
443 "unexpected std::ostream << Token result",
444 expected, conv.str());
447 void TokenTest::AssertHasMore(Tokenizer &in) {
448 CPPUNIT_ASSERT_MESSAGE("unexpected end of stream", in.HasMore());
451 void TokenTest::AssertToken(
452 Token::Type expected_type,
453 const Token &actual_token
455 AssertToken(expected_type, "", actual_token);
458 void TokenTest::AssertToken(
459 Token::Type expected_type,
460 string expected_value,
461 const Token &actual_token
463 CPPUNIT_ASSERT_EQUAL_MESSAGE(
464 "unexpected token type",
465 expected_type, actual_token.type);
466 CPPUNIT_ASSERT_EQUAL_MESSAGE(
467 "unexpected token value",
468 expected_value, actual_token.value);