]> git.localhorst.tv Git - blank.git/blob - tst/io/TokenTest.cpp
test for Tokenizer
[blank.git] / tst / io / TokenTest.cpp
1 #include "TokenTest.hpp"
2
3 #include <sstream>
4 #include <stdexcept>
5
6 CPPUNIT_TEST_SUITE_REGISTRATION(blank::test::TokenTest);
7
8 using namespace std;
9
10 namespace blank {
11 namespace test {
12
13 void TokenTest::setUp() {
14
15 }
16
17 void TokenTest::tearDown() {
18
19 }
20
21
22 void TokenTest::testTypeIO() {
23         AssertStreamOutput(Token::UNKNOWN, "UNKNOWN");
24         AssertStreamOutput(Token::ANGLE_BRACKET_OPEN, "ANGLE_BRACKET_OPEN");
25         AssertStreamOutput(Token::ANGLE_BRACKET_CLOSE, "ANGLE_BRACKET_CLOSE");
26         AssertStreamOutput(Token::CHEVRON_OPEN, "CHEVRON_OPEN");
27         AssertStreamOutput(Token::CHEVRON_CLOSE, "CHEVRON_CLOSE");
28         AssertStreamOutput(Token::BRACKET_OPEN, "BRACKET_OPEN");
29         AssertStreamOutput(Token::BRACKET_CLOSE, "BRACKET_CLOSE");
30         AssertStreamOutput(Token::PARENTHESIS_OPEN, "PARENTHESIS_OPEN");
31         AssertStreamOutput(Token::PARENTHESIS_CLOSE, "PARENTHESIS_CLOSE");
32         AssertStreamOutput(Token::COLON, "COLON");
33         AssertStreamOutput(Token::SEMICOLON, "SEMICOLON");
34         AssertStreamOutput(Token::COMMA, "COMMA");
35         AssertStreamOutput(Token::EQUALS, "EQUALS");
36         AssertStreamOutput(Token::NUMBER, "NUMBER");
37         AssertStreamOutput(Token::STRING, "STRING");
38         AssertStreamOutput(Token::IDENTIFIER, "IDENTIFIER");
39         AssertStreamOutput(Token::COMMENT, "COMMENT");
40 }
41
42 void TokenTest::testTokenIO() {
43         Token t;
44         t.value = "why oh why";
45         AssertStreamOutput(t, "UNKNOWN(why oh why)");
46         t.type = Token::UNKNOWN;
47         t.value = "do I have no purpose";
48         AssertStreamOutput(t, "UNKNOWN(do I have no purpose)");
49         t.type = Token::ANGLE_BRACKET_OPEN;
50         AssertStreamOutput(t, "ANGLE_BRACKET_OPEN");
51         t.type = Token::ANGLE_BRACKET_CLOSE;
52         AssertStreamOutput(t, "ANGLE_BRACKET_CLOSE");
53         t.type = Token::CHEVRON_OPEN;
54         AssertStreamOutput(t, "CHEVRON_OPEN");
55         t.type = Token::CHEVRON_CLOSE;
56         AssertStreamOutput(t, "CHEVRON_CLOSE");
57         t.type = Token::BRACKET_OPEN;
58         AssertStreamOutput(t, "BRACKET_OPEN");
59         t.type = Token::BRACKET_CLOSE;
60         AssertStreamOutput(t, "BRACKET_CLOSE");
61         t.type = Token::PARENTHESIS_OPEN;
62         AssertStreamOutput(t, "PARENTHESIS_OPEN");
63         t.type = Token::PARENTHESIS_CLOSE;
64         AssertStreamOutput(t, "PARENTHESIS_CLOSE");
65         t.type = Token::COLON;
66         AssertStreamOutput(t, "COLON");
67         t.type = Token::SEMICOLON;
68         AssertStreamOutput(t, "SEMICOLON");
69         t.type = Token::COMMA;
70         AssertStreamOutput(t, "COMMA");
71         t.type = Token::EQUALS;
72         AssertStreamOutput(t, "EQUALS");
73         t.type = Token::NUMBER;
74         t.value = "15";
75         AssertStreamOutput(t, "NUMBER(15)");
76         t.type = Token::STRING;
77         t.value = "hello world";
78         AssertStreamOutput(t, "STRING(hello world)");
79         t.type = Token::IDENTIFIER;
80         t.value = "foo";
81         AssertStreamOutput(t, "IDENTIFIER(foo)");
82         t.type = Token::COMMENT;
83         t.value = "WITHOUT ANY WARRANTY";
84         AssertStreamOutput(t, "COMMENT(WITHOUT ANY WARRANTY)");
85 }
86
87 void TokenTest::testTokenizer() {
88         stringstream stream;
89         stream << "[{0},<.5>+3=/**\n * test\n */ (-1.5); foo_bar.baz:\"hello\\r\\n\\t\\\"world\\\"\" ] // this line\n#that line";
90         Tokenizer in(stream);
91
92         AssertHasMore(in);
93         Token token(in.Next());
94         AssertToken(token.type, token.value, in.Current());
95         AssertToken(Token::BRACKET_OPEN, token);
96
97         AssertHasMore(in);
98         AssertToken(Token::ANGLE_BRACKET_OPEN, in.Next());
99         AssertHasMore(in);
100         AssertToken(Token::NUMBER, "0", in.Next());
101         AssertHasMore(in);
102         AssertToken(Token::ANGLE_BRACKET_CLOSE, in.Next());
103         AssertHasMore(in);
104         AssertToken(Token::COMMA, in.Next());
105         AssertHasMore(in);
106         AssertToken(Token::CHEVRON_OPEN, in.Next());
107         AssertHasMore(in);
108         AssertToken(Token::NUMBER, ".5", in.Next());
109         AssertHasMore(in);
110         AssertToken(Token::CHEVRON_CLOSE, in.Next());
111         AssertHasMore(in);
112         AssertToken(Token::NUMBER, "+3", in.Next());
113         AssertHasMore(in);
114         AssertToken(Token::EQUALS, in.Next());
115         AssertHasMore(in);
116         AssertToken(Token::COMMENT, "*\n * test\n ", in.Next());
117         AssertHasMore(in);
118         AssertToken(Token::PARENTHESIS_OPEN, in.Next());
119         AssertHasMore(in);
120         AssertToken(Token::NUMBER, "-1.5", in.Next());
121         AssertHasMore(in);
122         AssertToken(Token::PARENTHESIS_CLOSE, in.Next());
123         AssertHasMore(in);
124         AssertToken(Token::SEMICOLON, in.Next());
125         AssertHasMore(in);
126         AssertToken(Token::IDENTIFIER, "foo_bar.baz", in.Next());
127         AssertHasMore(in);
128         AssertToken(Token::COLON, in.Next());
129         AssertHasMore(in);
130         AssertToken(Token::STRING, "hello\r\n\t\"world\"", in.Next());
131         AssertHasMore(in);
132         AssertToken(Token::BRACKET_CLOSE, in.Next());
133         AssertHasMore(in);
134         AssertToken(Token::COMMENT, " this line", in.Next());
135         AssertHasMore(in);
136         AssertToken(Token::COMMENT, "that line", in.Next());
137         CPPUNIT_ASSERT_MESSAGE("expected end of stream", !in.HasMore());
138 }
139
140 void TokenTest::testTokenizerBrokenComment() {
141         {
142                 stringstream stream;
143                 stream << "/* just one more thing…*";
144                 Tokenizer in(stream);
145                 AssertHasMore(in);
146                 CPPUNIT_ASSERT_THROW_MESSAGE(
147                         "half-closed comment should throw",
148                         in.Next(), std::runtime_error);
149         }
150         {
151                 stringstream stream;
152                 stream << "  /";
153                 Tokenizer in(stream);
154                 AssertHasMore(in);
155                 CPPUNIT_ASSERT_THROW_MESSAGE(
156                         "sole '/' at end of stream should throw",
157                         in.Next(), std::runtime_error);
158         }
159         {
160                 stringstream stream;
161                 stream << "/.";
162                 Tokenizer in(stream);
163                 AssertHasMore(in);
164                 CPPUNIT_ASSERT_THROW_MESSAGE(
165                         "'/' followed by garbage should throw",
166                         in.Next(), std::runtime_error);
167         }
168 }
169
170
171 void TokenTest::AssertStreamOutput(
172         Token::Type t,
173         string expected
174 ) {
175         stringstream conv;
176         conv << t;
177         CPPUNIT_ASSERT_EQUAL_MESSAGE(
178                 "unexpected std::ostream << Token::Type result",
179                 expected, conv.str());
180 }
181
182 void TokenTest::AssertStreamOutput(
183         const Token &t,
184         string expected
185 ) {
186         stringstream conv;
187         conv << t;
188         CPPUNIT_ASSERT_EQUAL_MESSAGE(
189                 "unexpected std::ostream << Token result",
190                 expected, conv.str());
191 }
192
193 void TokenTest::AssertHasMore(Tokenizer &in) {
194         CPPUNIT_ASSERT_MESSAGE("unexpected end of stream", in.HasMore());
195 }
196
197 void TokenTest::AssertToken(
198         Token::Type expected_type,
199         const Token &actual_token
200 ) {
201         AssertToken(expected_type, "", actual_token);
202 }
203
204 void TokenTest::AssertToken(
205         Token::Type expected_type,
206         string expected_value,
207         const Token &actual_token
208 ) {
209         CPPUNIT_ASSERT_EQUAL_MESSAGE(
210                 "unexpected token type",
211                 expected_type, actual_token.type);
212         CPPUNIT_ASSERT_EQUAL_MESSAGE(
213                 "unexpected token value",
214                 expected_value, actual_token.value);
215 }
216
217 }
218 }