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"
207 "[1,0] [ 0.707, 0.707 ] // vec2\n"
208 "[.577,.577 ,0.577] [ 1,-2,3] // vec3\n"
209 "[ 0, 0, 0, 1 ] [1,0,0,-1.0] // vec4\n"
210 "[640, 480] [3, 4, 5] [0, -10, 100, -1000] # ivecs\n"
211 "[ -0.945, 0, -0.326, 0] # quat\n"
213 TokenStreamReader in(ss);
218 in.ReadBoolean(value_bool);
219 assert_read("reading boolean true", true, value_bool, in);
220 in.ReadBoolean(value_bool);
221 assert_read("reading boolean false", false, value_bool, in);
222 in.ReadBoolean(value_bool);
223 assert_read("reading boolean yes", true, value_bool, in);
224 in.ReadBoolean(value_bool);
225 assert_read("reading boolean no", false, value_bool, in);
226 in.ReadBoolean(value_bool);
227 assert_read("reading boolean on", true, value_bool, in);
228 in.ReadBoolean(value_bool);
229 assert_read("reading boolean off", false, value_bool, in);
231 in.ReadBoolean(value_bool);
232 assert_read("reading boolean \"true\"", true, value_bool, in);
233 in.ReadBoolean(value_bool);
234 assert_read("reading boolean \"false\"", false, value_bool, in);
235 in.ReadBoolean(value_bool);
236 assert_read("reading boolean \"yes\"", true, value_bool, in);
237 in.ReadBoolean(value_bool);
238 assert_read("reading boolean \"no\"", false, value_bool, in);
239 in.ReadBoolean(value_bool);
240 assert_read("reading boolean \"on\"", true, value_bool, in);
241 in.ReadBoolean(value_bool);
242 assert_read("reading boolean \"off\"", false, value_bool, in);
244 in.ReadBoolean(value_bool);
245 assert_read("reading boolean 1", true, value_bool, in);
246 in.ReadBoolean(value_bool);
247 assert_read("reading boolean 0", false, value_bool, in);
248 in.ReadBoolean(value_bool);
249 assert_read("reading boolean -1", true, value_bool, in);
254 in.ReadIdentifier(value_ident);
255 assert_read<string>("reading identifier foo", "foo", value_ident, in);
256 in.ReadIdentifier(value_ident);
257 assert_read<string>("reading identifier foo_bar", "foo_bar", value_ident, in);
258 in.ReadIdentifier(value_ident);
259 assert_read<string>("reading identifier vec.y", "vec.y", value_ident, in);
263 in.ReadNumber(value_int);
264 assert_read("reading integer 0", 0, value_int, in);
265 in.ReadNumber(value_int);
266 assert_read("reading integer 1", 1, value_int, in);
267 in.ReadNumber(value_int);
268 assert_read("reading integer +2", 2, value_int, in);
269 in.ReadNumber(value_int);
270 assert_read("reading integer -3", -3, value_int, in);
271 in.ReadNumber(value_int);
272 assert_read("reading integer 4.5", 4, value_int, in);
275 in.ReadNumber(value_float);
276 assert_read("reading float .5", .5f, value_float, in);
277 in.ReadNumber(value_float);
278 assert_read("reading float 1.5", 1.5f, value_float, in);
279 in.ReadNumber(value_float);
280 assert_read("reading float 0.25", .25f, value_float, in);
281 in.ReadNumber(value_float);
282 assert_read("reading float -1.75", -1.75f, value_float, in);
283 in.ReadNumber(value_float);
284 assert_read("reading float 0.625", 0.625f, value_float, in);
286 unsigned long value_uint;
287 in.ReadNumber(value_uint);
288 assert_read("reading unsigned integer 0", 0ul, value_uint, in);
289 in.ReadNumber(value_uint);
290 assert_read("reading unsigned integer 1", 1ul, value_uint, in);
291 in.ReadNumber(value_uint);
292 assert_read("reading unsigned integer -1", -1ul, value_uint, in);
293 in.ReadNumber(value_uint);
294 assert_read("reading unsigned integer 2.5", 2ul, value_uint, in);
299 in.ReadString(value_string);
301 "reading string \"hello\"",
302 "hello", value_string, in);
303 in.ReadString(value_string);
305 "reading string \"\"",
306 "", value_string, in);
307 in.ReadString(value_string);
309 "reading string \"\\r\\n\\t\\\"\"",
310 "\r\n\t\"", value_string, in);
312 in.ReadRelaxedString(value_string);
314 "reading relaxed string \"world\"",
315 "world", value_string, in);
317 in.ReadRelaxedString(value_string);
319 "reading relaxed string foo",
320 "foo", value_string, in);
322 in.ReadRelaxedString(value_string);
324 "reading relaxed string 12",
325 "12", value_string, in);
329 glm::vec2 value_vec2;
330 in.ReadVec(value_vec2);
332 "reading vector [1,0]",
333 glm::vec2(1, 0), value_vec2, in);
334 in.ReadVec(value_vec2);
336 "reading vector [ 0.707, 0.707 ]",
337 glm::vec2(.707, .707), value_vec2, in);
339 glm::vec3 value_vec3;
340 in.ReadVec(value_vec3);
342 "reading vector [.577,.577 ,0.577]",
343 glm::vec3(.577, .577, .577), value_vec3, in);
344 in.ReadVec(value_vec3);
346 "reading vector [ 1,-2,3]",
347 glm::vec3(1, -2, 3), value_vec3, in);
349 glm::vec4 value_vec4;
350 in.ReadVec(value_vec4);
352 "reading vector [ 0, 0, 0, 1 ]",
353 glm::vec4(0, 0, 0, 1), value_vec4, in);
354 in.ReadVec(value_vec4);
356 "reading vector [1,0,0,-1.0]",
357 glm::vec4(1, 0, 0, -1), value_vec4, in);
359 glm::ivec2 value_ivec2;
360 in.ReadVec(value_ivec2);
362 "reading integer vector [640, 480]",
363 glm::ivec2(640, 480), value_ivec2, in);
364 glm::ivec3 value_ivec3;
365 in.ReadVec(value_ivec3);
367 "reading integer vector [3, 4, 5]",
368 glm::ivec3(3, 4, 5), value_ivec3, in);
369 glm::ivec4 value_ivec4;
370 in.ReadVec(value_ivec4);
372 "reading integer vector [0, -10, 100, -1000]",
373 glm::ivec4(0, -10, 100, -1000), value_ivec4, in);
375 glm::quat value_quat;
376 in.ReadQuat(value_quat);
378 "reading quaternion [ -0.945, 0, -0.326, 0]",
379 glm::quat(-0.945, 0, -0.326, 0), value_quat, in);
380 // TODO: comment at end of stream makes it think there's more?
381 //CPPUNIT_ASSERT_MESSAGE("expected end of stream", !in.HasMore());
382 // TODO: and it even works??
383 //CPPUNIT_ASSERT_THROW_MESSAGE(
384 // "extracting token after EOS",
385 // in.Next(), std::runtime_error);
388 void TokenTest::testReaderEmpty() {
389 { // zero length stream
392 TokenStreamReader in(ss);
393 CPPUNIT_ASSERT_MESSAGE(
394 "empty stream shouldn't have tokens",
397 { // stream consisting solely of comments
404 "// is there anybody out there\n"
406 TokenStreamReader in(ss);
407 CPPUNIT_ASSERT_MESSAGE(
408 "comment stream shouldn't have tokens",
413 void TokenTest::testReaderMalformed() {
417 TokenStreamReader in(ss);
418 CPPUNIT_ASSERT_THROW_MESSAGE(
419 "unexpected token type should throw",
420 in.GetInt(), std::runtime_error);
425 TokenStreamReader in(ss);
426 CPPUNIT_ASSERT_THROW_MESSAGE(
427 "casting ':' to bool should throw",
428 in.GetBool(), std::runtime_error);
433 TokenStreamReader in(ss);
434 CPPUNIT_ASSERT_THROW_MESSAGE(
435 "casting \"hello\" to bool should throw",
436 in.GetBool(), std::runtime_error);
441 void TokenTest::AssertStreamOutput(
447 CPPUNIT_ASSERT_EQUAL_MESSAGE(
448 "unexpected std::ostream << Token::Type result",
449 expected, conv.str());
452 void TokenTest::AssertStreamOutput(
458 CPPUNIT_ASSERT_EQUAL_MESSAGE(
459 "unexpected std::ostream << Token result",
460 expected, conv.str());
463 void TokenTest::AssertHasMore(Tokenizer &in) {
464 CPPUNIT_ASSERT_MESSAGE("unexpected end of stream", in.HasMore());
467 void TokenTest::AssertToken(
468 Token::Type expected_type,
469 const Token &actual_token
471 AssertToken(expected_type, "", actual_token);
474 void TokenTest::AssertToken(
475 Token::Type expected_type,
476 string expected_value,
477 const Token &actual_token
479 CPPUNIT_ASSERT_EQUAL_MESSAGE(
480 "unexpected token type",
481 expected_type, actual_token.type);
482 CPPUNIT_ASSERT_EQUAL_MESSAGE(
483 "unexpected token value",
484 expected_value, actual_token.value);