1 #include "TokenTest.hpp"
3 #include "io/TokenStreamReader.hpp"
7 #include <glm/gtx/io.hpp>
9 CPPUNIT_TEST_SUITE_REGISTRATION(blobs::io::test::TokenTest);
17 void TokenTest::setUp() {
21 void TokenTest::tearDown() {
26 void TokenTest::testTypeIO() {
27 AssertStreamOutput(Token::UNKNOWN, "UNKNOWN");
28 AssertStreamOutput(Token::ANGLE_BRACKET_OPEN, "ANGLE_BRACKET_OPEN");
29 AssertStreamOutput(Token::ANGLE_BRACKET_CLOSE, "ANGLE_BRACKET_CLOSE");
30 AssertStreamOutput(Token::CHEVRON_OPEN, "CHEVRON_OPEN");
31 AssertStreamOutput(Token::CHEVRON_CLOSE, "CHEVRON_CLOSE");
32 AssertStreamOutput(Token::BRACKET_OPEN, "BRACKET_OPEN");
33 AssertStreamOutput(Token::BRACKET_CLOSE, "BRACKET_CLOSE");
34 AssertStreamOutput(Token::PARENTHESIS_OPEN, "PARENTHESIS_OPEN");
35 AssertStreamOutput(Token::PARENTHESIS_CLOSE, "PARENTHESIS_CLOSE");
36 AssertStreamOutput(Token::COLON, "COLON");
37 AssertStreamOutput(Token::SEMICOLON, "SEMICOLON");
38 AssertStreamOutput(Token::COMMA, "COMMA");
39 AssertStreamOutput(Token::EQUALS, "EQUALS");
40 AssertStreamOutput(Token::NUMBER, "NUMBER");
41 AssertStreamOutput(Token::STRING, "STRING");
42 AssertStreamOutput(Token::IDENTIFIER, "IDENTIFIER");
43 AssertStreamOutput(Token::COMMENT, "COMMENT");
46 void TokenTest::testTokenIO() {
48 t.value = "why oh why";
49 AssertStreamOutput(t, "UNKNOWN(why oh why)");
50 t.type = Token::UNKNOWN;
51 t.value = "do I have no purpose";
52 AssertStreamOutput(t, "UNKNOWN(do I have no purpose)");
53 t.type = Token::ANGLE_BRACKET_OPEN;
54 AssertStreamOutput(t, "ANGLE_BRACKET_OPEN");
55 t.type = Token::ANGLE_BRACKET_CLOSE;
56 AssertStreamOutput(t, "ANGLE_BRACKET_CLOSE");
57 t.type = Token::CHEVRON_OPEN;
58 AssertStreamOutput(t, "CHEVRON_OPEN");
59 t.type = Token::CHEVRON_CLOSE;
60 AssertStreamOutput(t, "CHEVRON_CLOSE");
61 t.type = Token::BRACKET_OPEN;
62 AssertStreamOutput(t, "BRACKET_OPEN");
63 t.type = Token::BRACKET_CLOSE;
64 AssertStreamOutput(t, "BRACKET_CLOSE");
65 t.type = Token::PARENTHESIS_OPEN;
66 AssertStreamOutput(t, "PARENTHESIS_OPEN");
67 t.type = Token::PARENTHESIS_CLOSE;
68 AssertStreamOutput(t, "PARENTHESIS_CLOSE");
69 t.type = Token::COLON;
70 AssertStreamOutput(t, "COLON");
71 t.type = Token::SEMICOLON;
72 AssertStreamOutput(t, "SEMICOLON");
73 t.type = Token::COMMA;
74 AssertStreamOutput(t, "COMMA");
75 t.type = Token::EQUALS;
76 AssertStreamOutput(t, "EQUALS");
77 t.type = Token::NUMBER;
79 AssertStreamOutput(t, "NUMBER(15)");
80 t.type = Token::STRING;
81 t.value = "hello world";
82 AssertStreamOutput(t, "STRING(hello world)");
83 t.type = Token::IDENTIFIER;
85 AssertStreamOutput(t, "IDENTIFIER(foo)");
86 t.type = Token::COMMENT;
87 t.value = "WITHOUT ANY WARRANTY";
88 AssertStreamOutput(t, "COMMENT(WITHOUT ANY WARRANTY)");
91 void TokenTest::testTokenizer() {
93 stream << "[{0},<.5>+3=/**\n * test\n */ (-1.5); foo_bar.baz:\"hello\\r\\n\\t\\\"world\\\"\" ] // this line\n#that line";
97 Token token(in.Next());
98 AssertToken(token.type, token.value, in.Current());
99 AssertToken(Token::BRACKET_OPEN, token);
102 AssertToken(Token::ANGLE_BRACKET_OPEN, in.Next());
104 AssertToken(Token::NUMBER, "0", in.Next());
106 AssertToken(Token::ANGLE_BRACKET_CLOSE, in.Next());
108 AssertToken(Token::COMMA, in.Next());
110 AssertToken(Token::CHEVRON_OPEN, in.Next());
112 AssertToken(Token::NUMBER, ".5", in.Next());
114 AssertToken(Token::CHEVRON_CLOSE, in.Next());
116 AssertToken(Token::NUMBER, "+3", in.Next());
118 AssertToken(Token::EQUALS, in.Next());
120 AssertToken(Token::COMMENT, "*\n * test\n ", in.Next());
122 AssertToken(Token::PARENTHESIS_OPEN, in.Next());
124 AssertToken(Token::NUMBER, "-1.5", in.Next());
126 AssertToken(Token::PARENTHESIS_CLOSE, in.Next());
128 AssertToken(Token::SEMICOLON, in.Next());
130 AssertToken(Token::IDENTIFIER, "foo_bar.baz", in.Next());
132 AssertToken(Token::COLON, in.Next());
134 AssertToken(Token::STRING, "hello\r\n\t\"world\"", in.Next());
136 AssertToken(Token::BRACKET_CLOSE, in.Next());
138 AssertToken(Token::COMMENT, " this line", in.Next());
140 AssertToken(Token::COMMENT, "that line", in.Next());
141 CPPUNIT_ASSERT_MESSAGE("expected end of stream", !in.HasMore());
142 CPPUNIT_ASSERT_THROW_MESSAGE(
143 "extracting token after EOS",
144 in.Next(), std::runtime_error);
147 void TokenTest::testTokenizerBrokenComment() {
150 stream << "/* just one more thing…*";
151 Tokenizer in(stream);
153 CPPUNIT_ASSERT_THROW_MESSAGE(
154 "half-closed comment should throw",
155 in.Next(), std::runtime_error);
160 Tokenizer in(stream);
162 CPPUNIT_ASSERT_THROW_MESSAGE(
163 "sole '/' at end of stream should throw",
164 in.Next(), std::runtime_error);
169 Tokenizer in(stream);
171 CPPUNIT_ASSERT_THROW_MESSAGE(
172 "'/' followed by garbage should throw",
173 in.Next(), std::runtime_error);
181 void assert_read(std::string message, T expected, T actual, TokenStreamReader &in) {
183 msg << message << ", current token: " << in.Peek();
184 CPPUNIT_ASSERT_EQUAL_MESSAGE(
191 void TokenTest::testReader() {
195 "true false yes no on off\n"
196 "\"true\" \"false\" \"yes\" \"no\" \"on\" \"off\"\n"
199 "foo foo_bar vec.y\n"
202 ".5 1.5 0.25 -1.75 0.625\n"
205 "\"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);
314 glm::vec2 value_vec2;
315 in.ReadVec(value_vec2);
317 "reading vector [1,0]",
318 glm::vec2(1, 0), value_vec2, in);
319 in.ReadVec(value_vec2);
321 "reading vector [ 0.707, 0.707 ]",
322 glm::vec2(.707, .707), value_vec2, in);
324 glm::vec3 value_vec3;
325 in.ReadVec(value_vec3);
327 "reading vector [.577,.577 ,0.577]",
328 glm::vec3(.577, .577, .577), value_vec3, in);
329 in.ReadVec(value_vec3);
331 "reading vector [ 1,-2,3]",
332 glm::vec3(1, -2, 3), value_vec3, in);
334 glm::vec4 value_vec4;
335 in.ReadVec(value_vec4);
337 "reading vector [ 0, 0, 0, 1 ]",
338 glm::vec4(0, 0, 0, 1), value_vec4, in);
339 in.ReadVec(value_vec4);
341 "reading vector [1,0,0,-1.0]",
342 glm::vec4(1, 0, 0, -1), value_vec4, in);
344 glm::ivec2 value_ivec2;
345 in.ReadVec(value_ivec2);
347 "reading integer vector [640, 480]",
348 glm::ivec2(640, 480), value_ivec2, in);
349 glm::ivec3 value_ivec3;
350 in.ReadVec(value_ivec3);
352 "reading integer vector [3, 4, 5]",
353 glm::ivec3(3, 4, 5), value_ivec3, in);
354 glm::ivec4 value_ivec4;
355 in.ReadVec(value_ivec4);
357 "reading integer vector [0, -10, 100, -1000]",
358 glm::ivec4(0, -10, 100, -1000), value_ivec4, in);
360 glm::quat value_quat;
361 in.ReadQuat(value_quat);
363 "reading quaternion [ -0.945, 0, -0.326, 0]",
364 glm::quat(-0.945, 0, -0.326, 0), value_quat, in);
365 // TODO: comment at end of stream makes it think there's more?
366 //CPPUNIT_ASSERT_MESSAGE("expected end of stream", !in.HasMore());
367 // TODO: and it even works??
368 //CPPUNIT_ASSERT_THROW_MESSAGE(
369 // "extracting token after EOS",
370 // in.Next(), std::runtime_error);
373 void TokenTest::testReaderEmpty() {
374 { // zero length stream
377 TokenStreamReader in(ss);
378 CPPUNIT_ASSERT_MESSAGE(
379 "empty stream shouldn't have tokens",
382 { // stream consisting solely of comments
389 "// is there anybody out there\n"
391 TokenStreamReader in(ss);
392 CPPUNIT_ASSERT_MESSAGE(
393 "comment stream shouldn't have tokens",
398 void TokenTest::testReaderMalformed() {
402 TokenStreamReader in(ss);
403 CPPUNIT_ASSERT_THROW_MESSAGE(
404 "unexpected token type should throw",
405 in.GetInt(), std::runtime_error);
410 TokenStreamReader in(ss);
411 CPPUNIT_ASSERT_THROW_MESSAGE(
412 "casting ':' to bool should throw",
413 in.GetBool(), std::runtime_error);
418 TokenStreamReader in(ss);
419 CPPUNIT_ASSERT_THROW_MESSAGE(
420 "casting \"hello\" to bool should throw",
421 in.GetBool(), std::runtime_error);
426 void TokenTest::AssertStreamOutput(
432 CPPUNIT_ASSERT_EQUAL_MESSAGE(
433 "unexpected std::ostream << Token::Type result",
434 expected, conv.str());
437 void TokenTest::AssertStreamOutput(
443 CPPUNIT_ASSERT_EQUAL_MESSAGE(
444 "unexpected std::ostream << Token result",
445 expected, conv.str());
448 void TokenTest::AssertHasMore(Tokenizer &in) {
449 CPPUNIT_ASSERT_MESSAGE("unexpected end of stream", in.HasMore());
452 void TokenTest::AssertToken(
453 Token::Type expected_type,
454 const Token &actual_token
456 AssertToken(expected_type, "", actual_token);
459 void TokenTest::AssertToken(
460 Token::Type expected_type,
461 string expected_value,
462 const Token &actual_token
464 CPPUNIT_ASSERT_EQUAL_MESSAGE(
465 "unexpected token type",
466 expected_type, actual_token.type);
467 CPPUNIT_ASSERT_EQUAL_MESSAGE(
468 "unexpected token value",
469 expected_value, actual_token.value);