test/zserio/JsonParserTest.cpp
Line | Count | Source |
1 | | #include "gtest/gtest.h" |
2 | | |
3 | | #include <sstream> |
4 | | #include "zserio/JsonParser.h" |
5 | | |
6 | | namespace zserio |
7 | | { |
8 | | |
9 | | namespace |
10 | | { |
11 | | |
12 | | class DummyObserver : public JsonParser::IObserver |
13 | | { |
14 | | public: |
15 | | const std::vector<std::string>& getReport() const |
16 | 12 | { |
17 | 12 | return m_report; |
18 | 12 | } |
19 | | |
20 | | void beginObject() override |
21 | 9 | { |
22 | 9 | m_report.push_back("beginObject"); |
23 | 9 | } |
24 | | |
25 | | void endObject() override |
26 | 3 | { |
27 | 3 | m_report.push_back("endObject"); |
28 | 3 | } |
29 | | |
30 | | void beginArray() override |
31 | 2 | { |
32 | 2 | m_report.push_back("beginArray"); |
33 | 2 | } |
34 | | |
35 | | void endArray() override |
36 | 1 | { |
37 | 1 | m_report.push_back("endArray"); |
38 | 1 | } |
39 | | |
40 | | void visitKey(StringView stringValue) override |
41 | 7 | { |
42 | 7 | m_report.push_back("visitKey: " + toString(stringValue)); |
43 | 7 | } |
44 | | |
45 | | void visitValue(std::nullptr_t) override |
46 | 1 | { |
47 | 1 | m_report.push_back("visitValue: null"); |
48 | 1 | } |
49 | | |
50 | | void visitValue(bool boolValue) override |
51 | 1 | { |
52 | 1 | m_report.push_back("visitValue: " + toString(boolValue)); |
53 | 1 | } |
54 | | |
55 | | void visitValue(int64_t intValue) override |
56 | 1 | { |
57 | 1 | m_report.push_back("visitValue: " + toString(intValue)); |
58 | 1 | } |
59 | | |
60 | | void visitValue(uint64_t uintValue) override |
61 | 4 | { |
62 | 4 | m_report.push_back("visitValue: " + toString(uintValue)); |
63 | 4 | } |
64 | | |
65 | | void visitValue(double doubleValue) override |
66 | 1 | { |
67 | 1 | m_report.push_back("visitValue: " + std::to_string(doubleValue)); |
68 | 1 | } |
69 | | |
70 | | void visitValue(StringView stringValue) override |
71 | 6 | { |
72 | 6 | m_report.push_back("visitValue: " + toString(stringValue)); |
73 | 6 | } |
74 | | |
75 | | private: |
76 | | std::vector<std::string> m_report; |
77 | | }; |
78 | | |
79 | | } // namespace |
80 | | |
81 | | TEST(JsonParserTest, empty) |
82 | 1 | { |
83 | 1 | std::stringstream str(""); |
84 | 1 | DummyObserver observer; |
85 | 1 | JsonParser jsonParser(str, observer); |
86 | 1 | ASSERT_TRUE(jsonParser.parse()); |
87 | 1 | ASSERT_EQ(0, observer.getReport().size()); |
88 | 1 | } |
89 | | |
90 | | TEST(JsonParserTest, oneString) |
91 | 1 | { |
92 | 1 | std::stringstream str("\"text\""); |
93 | 1 | DummyObserver observer; |
94 | 1 | JsonParser jsonParser(str, observer); |
95 | 1 | ASSERT_TRUE(jsonParser.parse()); |
96 | 1 | ASSERT_EQ(std::vector<std::string>{{"visitValue: text"}}, observer.getReport()); |
97 | 1 | } |
98 | | |
99 | | TEST(JsonParserTest, twoStrings) |
100 | 1 | { |
101 | 1 | std::stringstream str("\"text\"\"second\""); |
102 | 1 | DummyObserver observer; |
103 | 1 | JsonParser jsonParser(str, observer); |
104 | 1 | ASSERT_FALSE(jsonParser.parse()); |
105 | 1 | std::vector<std::string> expectedReport = {{"visitValue: text"}}; |
106 | 1 | ASSERT_EQ(expectedReport, observer.getReport()); |
107 | 1 | ASSERT_TRUE(jsonParser.parse()); |
108 | 1 | expectedReport.push_back("visitValue: second"); |
109 | 1 | ASSERT_EQ(expectedReport, observer.getReport()); |
110 | 1 | } |
111 | | |
112 | | TEST(JsonParserTest, parse) |
113 | 1 | { |
114 | 1 | std::stringstream str("{\"array\":\n[\n{\"key1\":\n10, \"key2\":\n\"text\"}, {}]}"); |
115 | 1 | DummyObserver observer; |
116 | 1 | JsonParser jsonParser(str, observer); |
117 | 1 | ASSERT_TRUE(jsonParser.parse()); |
118 | | |
119 | 1 | std::vector<std::string> expectedReport = {{ |
120 | 1 | {"beginObject"}, |
121 | 1 | {"visitKey: array"}, |
122 | 1 | {"beginArray"}, |
123 | 1 | {"beginObject"}, |
124 | 1 | {"visitKey: key1"}, |
125 | 1 | {"visitValue: 10"}, |
126 | 1 | {"visitKey: key2"}, |
127 | 1 | {"visitValue: text"}, |
128 | 1 | {"endObject"}, |
129 | 1 | {"beginObject"}, |
130 | 1 | {"endObject"}, |
131 | 1 | {"endArray"}, |
132 | 1 | {"endObject"} |
133 | 1 | }}; |
134 | 1 | ASSERT_EQ(expectedReport, observer.getReport()); |
135 | 1 | } |
136 | | |
137 | | TEST(JsonParserTest, valueTypes) |
138 | 1 | { |
139 | 1 | std::stringstream str("null true 10 -10 1.1 \"str\""); |
140 | 1 | DummyObserver observer; |
141 | 1 | JsonParser jsonParser(str, observer); |
142 | 6 | while (!jsonParser.parse()) |
143 | 5 | {} |
144 | | |
145 | 1 | std::vector<std::string> expectedReport = {{ |
146 | 1 | {"visitValue: null"}, |
147 | 1 | {"visitValue: true"}, |
148 | 1 | {"visitValue: 10"}, |
149 | 1 | {"visitValue: -10"}, |
150 | 1 | {"visitValue: 1.100000"}, |
151 | 1 | {"visitValue: str"} |
152 | 1 | }}; |
153 | 1 | ASSERT_EQ(expectedReport, observer.getReport()); |
154 | 1 | } |
155 | | |
156 | | TEST(JsonParserTest, unexpectedObject) |
157 | 1 | { |
158 | 1 | std::stringstream str("{\n\n{\n\n"); |
159 | 1 | DummyObserver observer; |
160 | 1 | JsonParser jsonParser(str, observer); |
161 | 1 | ASSERT_THROW({ |
162 | 1 | try |
163 | 1 | { |
164 | 1 | jsonParser.parse(); |
165 | 1 | } |
166 | 1 | catch (const JsonParserException& e) |
167 | 1 | { |
168 | 1 | ASSERT_STREQ("JsonParser:3:1: unexpected token: BEGIN_OBJECT, expecting END_OBJECT!", e.what()); |
169 | 1 | throw; |
170 | 1 | } |
171 | 1 | }, JsonParserException); |
172 | | |
173 | 1 | std::vector<std::string> expectedReport = {{ |
174 | 1 | "beginObject" |
175 | 1 | }}; |
176 | 1 | ASSERT_EQ(expectedReport, observer.getReport()); |
177 | 1 | } |
178 | | |
179 | | TEST(JsonParserTest, unexpectedObjectAfterItemSeparator) |
180 | 1 | { |
181 | 1 | std::stringstream str("{\n \"key\": 10,\n {\n"); |
182 | 1 | DummyObserver observer; |
183 | 1 | JsonParser jsonParser(str, observer); |
184 | 1 | ASSERT_THROW({ |
185 | 1 | try |
186 | 1 | { |
187 | 1 | jsonParser.parse(); |
188 | 1 | } |
189 | 1 | catch (const JsonParserException& e) |
190 | 1 | { |
191 | 1 | ASSERT_STREQ("JsonParser:3:3: unexpected token: BEGIN_OBJECT, expecting VALUE!", e.what()); |
192 | 1 | throw; |
193 | 1 | } |
194 | 1 | }, JsonParserException); |
195 | | |
196 | 1 | std::vector<std::string> expectedReport = {{ |
197 | 1 | {"beginObject"}, |
198 | 1 | {"visitKey: key"}, |
199 | 1 | {"visitValue: 10"} |
200 | 1 | }}; |
201 | 1 | ASSERT_EQ(expectedReport, observer.getReport()); |
202 | 1 | } |
203 | | |
204 | | TEST(JsonParserTest, missingObjectItemSeparator) |
205 | 1 | { |
206 | 1 | std::stringstream str("{\n\"item1\":\"text\"\n\"item2\":\"text\"\n}"); |
207 | 1 | DummyObserver observer; |
208 | 1 | JsonParser jsonParser(str, observer); |
209 | 1 | ASSERT_THROW({ |
210 | 1 | try |
211 | 1 | { |
212 | 1 | jsonParser.parse(); |
213 | 1 | } |
214 | 1 | catch (const JsonParserException& e) |
215 | 1 | { |
216 | 1 | ASSERT_STREQ("JsonParser:3:1: unexpected token: VALUE, expecting END_OBJECT!", e.what()); |
217 | 1 | throw; |
218 | 1 | } |
219 | 1 | }, JsonParserException); |
220 | | |
221 | 1 | std::vector<std::string> expectedReport = {{ |
222 | 1 | {"beginObject"}, |
223 | 1 | {"visitKey: item1"}, |
224 | 1 | {"visitValue: text"} |
225 | 1 | }}; |
226 | 1 | ASSERT_EQ(expectedReport, observer.getReport()); |
227 | 1 | } |
228 | | |
229 | | TEST(JsonParserTest, wrongKeyType) |
230 | 1 | { |
231 | 1 | std::stringstream str("{\n10:\"text\"\n}"); |
232 | 1 | DummyObserver observer; |
233 | 1 | JsonParser jsonParser(str, observer); |
234 | 1 | ASSERT_THROW({ |
235 | 1 | try |
236 | 1 | { |
237 | 1 | jsonParser.parse(); |
238 | 1 | } |
239 | 1 | catch (const JsonParserException& e) |
240 | 1 | { |
241 | 1 | ASSERT_STREQ("JsonParser:2:1: Key must be a string value!", e.what()); |
242 | 1 | throw; |
243 | 1 | } |
244 | 1 | }, JsonParserException); |
245 | | |
246 | 1 | std::vector<std::string> expectedReport = {{ |
247 | 1 | "beginObject" |
248 | 1 | }}; |
249 | 1 | ASSERT_EQ(expectedReport, observer.getReport()); |
250 | 1 | } |
251 | | |
252 | | TEST(JsonParserTest, unexpectedElementToken) |
253 | 1 | { |
254 | 1 | std::stringstream str("{\n\"item\":}"); |
255 | 1 | DummyObserver observer; |
256 | 1 | JsonParser jsonParser(str, observer); |
257 | 1 | ASSERT_THROW({ |
258 | 1 | try |
259 | 1 | { |
260 | 1 | jsonParser.parse(); |
261 | 1 | } |
262 | 1 | catch (const JsonParserException& e) |
263 | 1 | { |
264 | 1 | ASSERT_STREQ("JsonParser:2:8: unexpected token: END_OBJECT, " |
265 | 1 | "expecting one of [BEGIN_OBJECT, BEGIN_ARRAY, VALUE]!", e.what()); |
266 | 1 | throw; |
267 | 1 | } |
268 | 1 | }, JsonParserException); |
269 | | |
270 | 1 | std::vector<std::string> expectedReport = {{ |
271 | 1 | {"beginObject"}, |
272 | 1 | {"visitKey: item"} |
273 | 1 | }}; |
274 | 1 | ASSERT_EQ(expectedReport, observer.getReport()); |
275 | 1 | } |
276 | | |
277 | | TEST(JsonParserTest, missingArrayElementSeparator) |
278 | 1 | { |
279 | 1 | std::stringstream str("{\n\"array\":\n[10\n20\n]}"); |
280 | 1 | DummyObserver observer; |
281 | 1 | JsonParser jsonParser(str, observer); |
282 | 1 | ASSERT_THROW({ |
283 | 1 | try |
284 | 1 | { |
285 | 1 | jsonParser.parse(); |
286 | 1 | } |
287 | 1 | catch (const JsonParserException& e) |
288 | 1 | { |
289 | 1 | ASSERT_STREQ("JsonParser:4:1: unexpected token: VALUE, expecting END_ARRAY!", e.what()); |
290 | 1 | throw; |
291 | 1 | } |
292 | 1 | }, JsonParserException); |
293 | | |
294 | 1 | std::vector<std::string> expectedReport = {{ |
295 | 1 | {"beginObject"}, |
296 | 1 | {"visitKey: array"}, |
297 | 1 | {"beginArray"}, |
298 | 1 | {"visitValue: 10"} |
299 | 1 | }}; |
300 | 1 | ASSERT_EQ(expectedReport, observer.getReport()); |
301 | 1 | } |
302 | | |
303 | | } // namespace zserio |