test/zserio/JsonWriterTest.cpp
Line | Count | Source |
1 | | #include "gtest/gtest.h" |
2 | | |
3 | | #include <sstream> |
4 | | #include <vector> |
5 | | |
6 | | #include "zserio/JsonWriter.h" |
7 | | #include "zserio/TypeInfo.h" |
8 | | #include "zserio/Reflectable.h" |
9 | | |
10 | | namespace zserio |
11 | | { |
12 | | |
13 | | class JsonWriterTest : public ::testing::Test |
14 | | { |
15 | | public: |
16 | | JsonWriterTest() : |
17 | | BOOL_FIELD_INFO{"boolField"_sv, BuiltinTypeInfo<>::getBool(), |
18 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
19 | | INT8_FIELD_INFO{"int8Field"_sv, BuiltinTypeInfo<>::getInt8(), |
20 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
21 | | INT16_FIELD_INFO{"int16Field"_sv, BuiltinTypeInfo<>::getInt16(), |
22 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
23 | | INT32_FIELD_INFO{"int32Field"_sv, BuiltinTypeInfo<>::getInt32(), |
24 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
25 | | INT64_FIELD_INFO{"int64Field"_sv, BuiltinTypeInfo<>::getInt64(), |
26 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
27 | | UINT8_FIELD_INFO{"uint8Field"_sv, BuiltinTypeInfo<>::getUInt8(), |
28 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
29 | | UINT16_FIELD_INFO{"uint16Field"_sv, BuiltinTypeInfo<>::getUInt16(), |
30 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
31 | | UINT32_FIELD_INFO{"uint32Field"_sv, BuiltinTypeInfo<>::getUInt32(), |
32 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
33 | | UINT64_FIELD_INFO{"uint64Field"_sv, BuiltinTypeInfo<>::getUInt64(), |
34 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
35 | | FLOAT_FIELD_INFO{"floatField"_sv, BuiltinTypeInfo<>::getFloat32(), |
36 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
37 | | DOUBLE_FIELD_INFO{"doubleField"_sv, BuiltinTypeInfo<>::getFloat64(), |
38 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
39 | | BYTES_DATA_FIELD_INFO{"bytesData"_sv, BuiltinTypeInfo<>::getBytes(), |
40 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
41 | | STRING_FIELD_INFO{"stringField"_sv, BuiltinTypeInfo<>::getString(), |
42 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
43 | | EXTERN_DATA_FIELD_INFO{"externData"_sv, BuiltinTypeInfo<>::getBitBuffer(), |
44 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
45 | | IDENTIFIER_FIELD_INFO{"identifier", BuiltinTypeInfo<>::getUInt32(), |
46 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
47 | | DUMMY_TYPE_INFO{"Dummy"_sv, nullptr, {}, {}, {}, {}, {}}, |
48 | | NESTED_FIELD_INFO{"nested"_sv, DUMMY_TYPE_INFO, |
49 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
50 | | ARRAY_FIELD_INFO{"array", BuiltinTypeInfo<>::getUInt32(), |
51 | | {}, false, {}, {}, {}, false, {}, {}, true, {}, false, false}, |
52 | | INT8_ENUM_ITEMS{ |
53 | | ItemInfo{"ZERO"_sv, static_cast<uint64_t>(0), false, false}, |
54 | | ItemInfo{"One"_sv, static_cast<uint64_t>(1), false, false}, |
55 | | ItemInfo{"MINUS_ONE"_sv, static_cast<uint64_t>(-1), false, false}}, |
56 | | INT8_ENUM_TYPE_INFO{"DummyEnum"_sv, BuiltinTypeInfo<>::getInt8(), {}, INT8_ENUM_ITEMS}, |
57 | | INT8_ENUM_FIELD_INFO{"enumField"_sv, INT8_ENUM_TYPE_INFO, |
58 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
59 | | UINT8_ENUM_ITEMS{ |
60 | | ItemInfo{"ZERO"_sv, static_cast<uint64_t>(0), false, false}, |
61 | | ItemInfo{"One"_sv, static_cast<uint64_t>(1), false, false}}, |
62 | | UINT8_ENUM_TYPE_INFO{"DummyEnum"_sv, BuiltinTypeInfo<>::getUInt8(), {}, UINT8_ENUM_ITEMS}, |
63 | | UINT8_ENUM_FIELD_INFO{"enumField"_sv, UINT8_ENUM_TYPE_INFO, |
64 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}, |
65 | | BITMASK_ITEMS{ |
66 | | ItemInfo{"ZERO"_sv, static_cast<uint64_t>(0), false, false}, |
67 | | ItemInfo{"One"_sv, static_cast<uint64_t>(1), false, false}, |
68 | | ItemInfo{"TWO"_sv, static_cast<uint64_t>(2), false, false}}, |
69 | | BITMASK_TYPE_INFO{"DummyBitmask"_sv, BuiltinTypeInfo<>::getUInt32(), {}, BITMASK_ITEMS}, |
70 | | BITMASK_FIELD_INFO{"bitmaskField"_sv, BITMASK_TYPE_INFO, |
71 | | {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false} |
72 | 29 | {} |
73 | | |
74 | | protected: |
75 | | void walkNested(IWalkObserver& observer) |
76 | 5 | { |
77 | 5 | observer.beginRoot(nullptr); |
78 | 5 | observer.visitValue(ReflectableFactory::getUInt32(13), IDENTIFIER_FIELD_INFO, WALKER_NOT_ELEMENT); |
79 | 5 | observer.beginCompound(nullptr, NESTED_FIELD_INFO, WALKER_NOT_ELEMENT); |
80 | 5 | observer.visitValue(ReflectableFactory::getString("test"_sv), STRING_FIELD_INFO, WALKER_NOT_ELEMENT); |
81 | 5 | observer.endCompound(nullptr, NESTED_FIELD_INFO, WALKER_NOT_ELEMENT); |
82 | 5 | observer.endRoot(nullptr); |
83 | 5 | } |
84 | | |
85 | | void walkArray(IWalkObserver& observer) |
86 | 2 | { |
87 | 2 | observer.beginRoot(nullptr); |
88 | 2 | observer.beginArray(nullptr, ARRAY_FIELD_INFO); |
89 | 2 | observer.visitValue(ReflectableFactory::getUInt32(1), ARRAY_FIELD_INFO, 0); |
90 | 2 | observer.visitValue(ReflectableFactory::getUInt32(2), ARRAY_FIELD_INFO, 1); |
91 | 2 | observer.endArray(nullptr, ARRAY_FIELD_INFO); |
92 | 2 | observer.endRoot(nullptr); |
93 | 2 | } |
94 | | |
95 | | const FieldInfo BOOL_FIELD_INFO; |
96 | | const FieldInfo INT8_FIELD_INFO; |
97 | | const FieldInfo INT16_FIELD_INFO; |
98 | | const FieldInfo INT32_FIELD_INFO; |
99 | | const FieldInfo INT64_FIELD_INFO; |
100 | | const FieldInfo UINT8_FIELD_INFO; |
101 | | const FieldInfo UINT16_FIELD_INFO; |
102 | | const FieldInfo UINT32_FIELD_INFO; |
103 | | const FieldInfo UINT64_FIELD_INFO; |
104 | | const FieldInfo FLOAT_FIELD_INFO; |
105 | | const FieldInfo DOUBLE_FIELD_INFO; |
106 | | const FieldInfo BYTES_DATA_FIELD_INFO; |
107 | | const FieldInfo STRING_FIELD_INFO; |
108 | | const FieldInfo EXTERN_DATA_FIELD_INFO; |
109 | | const FieldInfo IDENTIFIER_FIELD_INFO; |
110 | | const StructTypeInfo<std::allocator<uint8_t>> DUMMY_TYPE_INFO; |
111 | | const FieldInfo NESTED_FIELD_INFO; |
112 | | const FieldInfo ARRAY_FIELD_INFO; |
113 | | const std::array<ItemInfo, 3> INT8_ENUM_ITEMS; |
114 | | const EnumTypeInfo<std::allocator<uint8_t>> INT8_ENUM_TYPE_INFO; |
115 | | const FieldInfo INT8_ENUM_FIELD_INFO; |
116 | | const std::array<ItemInfo, 2> UINT8_ENUM_ITEMS; |
117 | | const EnumTypeInfo<std::allocator<uint8_t>> UINT8_ENUM_TYPE_INFO; |
118 | | const FieldInfo UINT8_ENUM_FIELD_INFO; |
119 | | const std::array<ItemInfo, 3> BITMASK_ITEMS; |
120 | | const BitmaskTypeInfo<std::allocator<uint8_t>> BITMASK_TYPE_INFO; |
121 | | const FieldInfo BITMASK_FIELD_INFO; |
122 | | }; |
123 | | |
124 | | TEST_F(JsonWriterTest, empty) |
125 | 1 | { |
126 | 1 | std::ostringstream os; |
127 | 1 | JsonWriter jsonWriter(os); |
128 | | |
129 | 1 | ASSERT_EQ("", os.str()); |
130 | 1 | } |
131 | | |
132 | | TEST_F(JsonWriterTest, nullValue) |
133 | 1 | { |
134 | 1 | std::ostringstream os; |
135 | 1 | JsonWriter jsonWriter(os); |
136 | 1 | IWalkObserver& observer = jsonWriter; |
137 | | |
138 | 1 | observer.visitValue(nullptr, STRING_FIELD_INFO, WALKER_NOT_ELEMENT); |
139 | | |
140 | | // note that this is not valid json |
141 | 1 | ASSERT_EQ("\"stringField\": null", os.str()); |
142 | 1 | } |
143 | | |
144 | | TEST_F(JsonWriterTest, boolValue) |
145 | 1 | { |
146 | 1 | std::ostringstream os; |
147 | 1 | JsonWriter jsonWriter(os); |
148 | 1 | IWalkObserver& observer = jsonWriter; |
149 | | |
150 | 1 | observer.visitValue(ReflectableFactory::getBool(true), BOOL_FIELD_INFO, WALKER_NOT_ELEMENT); |
151 | | |
152 | | // note that this is not valid json |
153 | 1 | ASSERT_EQ("\"boolField\": true", os.str()); |
154 | 1 | } |
155 | | |
156 | | TEST_F(JsonWriterTest, int8Value) |
157 | 1 | { |
158 | 1 | std::ostringstream os; |
159 | 1 | JsonWriter jsonWriter(os); |
160 | 1 | IWalkObserver& observer = jsonWriter; |
161 | | |
162 | 1 | observer.visitValue(ReflectableFactory::getInt8(INT8_MIN), INT8_FIELD_INFO, WALKER_NOT_ELEMENT); |
163 | | |
164 | | // note that this is not valid json |
165 | 1 | ASSERT_EQ("\"int8Field\": " + std::to_string(INT8_MIN), os.str()); |
166 | 1 | } |
167 | | |
168 | | TEST_F(JsonWriterTest, int16Value) |
169 | 1 | { |
170 | 1 | std::ostringstream os; |
171 | 1 | JsonWriter jsonWriter(os); |
172 | 1 | IWalkObserver& observer = jsonWriter; |
173 | | |
174 | 1 | observer.visitValue(ReflectableFactory::getInt16(INT16_MIN), INT16_FIELD_INFO, WALKER_NOT_ELEMENT); |
175 | | |
176 | | // note that this is not valid json |
177 | 1 | ASSERT_EQ("\"int16Field\": " + std::to_string(INT16_MIN), os.str()); |
178 | 1 | } |
179 | | |
180 | | TEST_F(JsonWriterTest, int32Value) |
181 | 1 | { |
182 | 1 | std::ostringstream os; |
183 | 1 | JsonWriter jsonWriter(os); |
184 | 1 | IWalkObserver& observer = jsonWriter; |
185 | | |
186 | 1 | observer.visitValue(ReflectableFactory::getInt32(INT32_MIN), INT32_FIELD_INFO, WALKER_NOT_ELEMENT); |
187 | | |
188 | | // note that this is not valid json |
189 | 1 | ASSERT_EQ("\"int32Field\": " + std::to_string(INT32_MIN), os.str()); |
190 | 1 | } |
191 | | |
192 | | TEST_F(JsonWriterTest, int64Value) |
193 | 1 | { |
194 | 1 | std::ostringstream os; |
195 | 1 | JsonWriter jsonWriter(os); |
196 | 1 | IWalkObserver& observer = jsonWriter; |
197 | | |
198 | 1 | observer.visitValue(ReflectableFactory::getInt64(INT64_MIN), INT64_FIELD_INFO, WALKER_NOT_ELEMENT); |
199 | | |
200 | | // note that this is not valid json |
201 | 1 | ASSERT_EQ("\"int64Field\": " + std::to_string(INT64_MIN), os.str()); |
202 | 1 | } |
203 | | |
204 | | TEST_F(JsonWriterTest, uint8Value) |
205 | 1 | { |
206 | 1 | std::ostringstream os; |
207 | 1 | JsonWriter jsonWriter(os); |
208 | 1 | IWalkObserver& observer = jsonWriter; |
209 | | |
210 | 1 | observer.visitValue(ReflectableFactory::getUInt8(UINT8_MAX), UINT8_FIELD_INFO, WALKER_NOT_ELEMENT); |
211 | | |
212 | | // note that this is not valid json |
213 | 1 | ASSERT_EQ("\"uint8Field\": " + std::to_string(UINT8_MAX), os.str()); |
214 | 1 | } |
215 | | |
216 | | TEST_F(JsonWriterTest, uint16Value) |
217 | 1 | { |
218 | 1 | std::ostringstream os; |
219 | 1 | JsonWriter jsonWriter(os); |
220 | 1 | IWalkObserver& observer = jsonWriter; |
221 | | |
222 | 1 | observer.visitValue(ReflectableFactory::getUInt16(UINT16_MAX), UINT16_FIELD_INFO, WALKER_NOT_ELEMENT); |
223 | | |
224 | | // note that this is not valid json |
225 | 1 | ASSERT_EQ("\"uint16Field\": " + std::to_string(UINT16_MAX), os.str()); |
226 | 1 | } |
227 | | |
228 | | TEST_F(JsonWriterTest, uint32Value) |
229 | 1 | { |
230 | 1 | std::ostringstream os; |
231 | 1 | JsonWriter jsonWriter(os); |
232 | 1 | IWalkObserver& observer = jsonWriter; |
233 | | |
234 | 1 | observer.visitValue(ReflectableFactory::getUInt32(UINT32_MAX), UINT32_FIELD_INFO, WALKER_NOT_ELEMENT); |
235 | | |
236 | | // note that this is not valid json |
237 | 1 | ASSERT_EQ("\"uint32Field\": " + std::to_string(UINT32_MAX), os.str()); |
238 | 1 | } |
239 | | |
240 | | TEST_F(JsonWriterTest, uint64Value) |
241 | 1 | { |
242 | 1 | std::ostringstream os; |
243 | 1 | JsonWriter jsonWriter(os); |
244 | 1 | IWalkObserver& observer = jsonWriter; |
245 | | |
246 | 1 | observer.visitValue(ReflectableFactory::getUInt64(UINT64_MAX), UINT64_FIELD_INFO, WALKER_NOT_ELEMENT); |
247 | | |
248 | | // note that this is not valid json |
249 | 1 | ASSERT_EQ("\"uint64Field\": " + std::to_string(UINT64_MAX), os.str()); |
250 | 1 | } |
251 | | |
252 | | TEST_F(JsonWriterTest, floatValue) |
253 | 1 | { |
254 | 1 | std::ostringstream os; |
255 | 1 | JsonWriter jsonWriter(os); |
256 | 1 | IWalkObserver& observer = jsonWriter; |
257 | | |
258 | 1 | observer.visitValue(ReflectableFactory::getFloat32(3.5F), FLOAT_FIELD_INFO, WALKER_NOT_ELEMENT); |
259 | | |
260 | | // note that this is not valid json |
261 | 1 | ASSERT_EQ("\"floatField\": 3.5", os.str()); |
262 | 1 | } |
263 | | |
264 | | TEST_F(JsonWriterTest, doubleValue) |
265 | 1 | { |
266 | 1 | std::ostringstream os; |
267 | 1 | JsonWriter jsonWriter(os); |
268 | 1 | IWalkObserver& observer = jsonWriter; |
269 | | |
270 | 1 | observer.visitValue(ReflectableFactory::getFloat64(9.875), DOUBLE_FIELD_INFO, WALKER_NOT_ELEMENT); |
271 | | |
272 | | // note that this is not valid json |
273 | 1 | ASSERT_EQ("\"doubleField\": 9.875", os.str()); |
274 | 1 | } |
275 | | |
276 | | TEST_F(JsonWriterTest, bytesValue) |
277 | 1 | { |
278 | 1 | std::ostringstream os; |
279 | 1 | JsonWriter jsonWriter(os); |
280 | 1 | IWalkObserver& observer = jsonWriter; |
281 | | |
282 | 1 | vector<uint8_t> bytesData{{0xCA, 0xFE}}; |
283 | 1 | observer.visitValue(ReflectableFactory::getBytes(bytesData), BYTES_DATA_FIELD_INFO, WALKER_NOT_ELEMENT); |
284 | | |
285 | | // note that this is not valid json |
286 | 1 | ASSERT_EQ("\"bytesData\": {\"buffer\": [202, 254]}", os.str()); |
287 | 1 | } |
288 | | |
289 | | TEST_F(JsonWriterTest, stringValue) |
290 | 1 | { |
291 | 1 | std::ostringstream os; |
292 | 1 | JsonWriter jsonWriter(os); |
293 | 1 | IWalkObserver& observer = jsonWriter; |
294 | | |
295 | 1 | observer.visitValue(ReflectableFactory::getString("test"_sv), STRING_FIELD_INFO, WALKER_NOT_ELEMENT); |
296 | | |
297 | | // note that this is not valid json |
298 | 1 | ASSERT_EQ("\"stringField\": \"test\"", os.str()); |
299 | 1 | } |
300 | | |
301 | | TEST_F(JsonWriterTest, externValue) |
302 | 1 | { |
303 | 1 | std::ostringstream os; |
304 | 1 | JsonWriter jsonWriter(os); |
305 | 1 | IWalkObserver& observer = jsonWriter; |
306 | | |
307 | 1 | BitBuffer bitBuffer({0xFF, 0x1F}, 13); |
308 | 1 | observer.visitValue(ReflectableFactory::getBitBuffer(bitBuffer), EXTERN_DATA_FIELD_INFO, |
309 | 1 | WALKER_NOT_ELEMENT); |
310 | | |
311 | | // note that this is not valid json |
312 | 1 | ASSERT_EQ("\"externData\": {\"buffer\": [255, 31], \"bitSize\": 13}", os.str()); |
313 | 1 | } |
314 | | |
315 | | TEST_F(JsonWriterTest, signedEnumValue) |
316 | 1 | { |
317 | 1 | class DummyEnumReflectable : public ReflectableBase<std::allocator<uint8_t>> |
318 | 1 | { |
319 | 1 | public: |
320 | 1 | explicit DummyEnumReflectable(int8_t value, const EnumTypeInfo<std::allocator<uint8_t>>& typeInfo) : |
321 | 1 | ReflectableBase<std::allocator<uint8_t>>(typeInfo), |
322 | 1 | m_value(value) |
323 | 4 | {} |
324 | | |
325 | 1 | int64_t toInt() const override |
326 | 8 | { |
327 | 8 | return m_value; |
328 | 8 | } |
329 | | |
330 | 1 | private: |
331 | 1 | int8_t m_value; |
332 | 1 | }; |
333 | | |
334 | 1 | IReflectablePtr reflectableZero = std::make_shared<DummyEnumReflectable>(0, INT8_ENUM_TYPE_INFO); |
335 | 1 | IReflectablePtr reflectableOne = std::make_shared<DummyEnumReflectable>(1, INT8_ENUM_TYPE_INFO); |
336 | 1 | IReflectablePtr reflectableTwo = std::make_shared<DummyEnumReflectable>(2, INT8_ENUM_TYPE_INFO); |
337 | 1 | IReflectablePtr reflectableMinusOne = std::make_shared<DummyEnumReflectable>(-1, INT8_ENUM_TYPE_INFO); |
338 | | |
339 | 1 | { |
340 | 1 | std::ostringstream os; |
341 | 1 | JsonWriter jsonWriter(os); |
342 | 1 | IWalkObserver& observer = jsonWriter; |
343 | 1 | observer.visitValue(reflectableZero, INT8_ENUM_FIELD_INFO, WALKER_NOT_ELEMENT); |
344 | 1 | observer.visitValue(reflectableOne, INT8_ENUM_FIELD_INFO, WALKER_NOT_ELEMENT); |
345 | 1 | observer.visitValue(reflectableTwo, INT8_ENUM_FIELD_INFO, WALKER_NOT_ELEMENT); |
346 | 1 | observer.visitValue(reflectableMinusOne, INT8_ENUM_FIELD_INFO, WALKER_NOT_ELEMENT); |
347 | | |
348 | | // note that this is not valid json |
349 | 1 | ASSERT_EQ( |
350 | 1 | "\"enumField\": \"ZERO\", " |
351 | 1 | "\"enumField\": \"One\", " |
352 | 1 | "\"enumField\": \"2 /* no match */\", " |
353 | 1 | "\"enumField\": \"MINUS_ONE\"", os.str()); |
354 | 1 | } |
355 | | |
356 | 1 | { |
357 | 1 | std::ostringstream os; |
358 | 1 | JsonWriter jsonWriter(os); |
359 | 1 | jsonWriter.setEnumerableFormat(JsonWriter::EnumerableFormat::NUMBER); |
360 | 1 | IWalkObserver& observer = jsonWriter; |
361 | 1 | observer.visitValue(reflectableZero, INT8_ENUM_FIELD_INFO, WALKER_NOT_ELEMENT); |
362 | 1 | observer.visitValue(reflectableTwo, INT8_ENUM_FIELD_INFO, WALKER_NOT_ELEMENT); |
363 | 1 | observer.visitValue(reflectableMinusOne, INT8_ENUM_FIELD_INFO, WALKER_NOT_ELEMENT); |
364 | | |
365 | | // note that this is not valid json |
366 | 1 | ASSERT_EQ("\"enumField\": 0, \"enumField\": 2, \"enumField\": -1", os.str()); |
367 | 1 | } |
368 | 1 | } |
369 | | |
370 | | TEST_F(JsonWriterTest, unsignedEnumValue) |
371 | 1 | { |
372 | 1 | class DummyEnumReflectable : public ReflectableBase<std::allocator<uint8_t>> |
373 | 1 | { |
374 | 1 | public: |
375 | 1 | explicit DummyEnumReflectable(uint8_t value, const EnumTypeInfo<std::allocator<uint8_t>>& typeInfo) : |
376 | 1 | ReflectableBase<std::allocator<uint8_t>>(typeInfo), |
377 | 1 | m_value(value) |
378 | 3 | {} |
379 | | |
380 | 1 | uint64_t toUInt() const override |
381 | 6 | { |
382 | 6 | return m_value; |
383 | 6 | } |
384 | | |
385 | 1 | private: |
386 | 1 | uint8_t m_value; |
387 | 1 | }; |
388 | | |
389 | 1 | IReflectablePtr reflectableZero = std::make_shared<DummyEnumReflectable>(0, UINT8_ENUM_TYPE_INFO); |
390 | 1 | IReflectablePtr reflectableOne = std::make_shared<DummyEnumReflectable>(1, UINT8_ENUM_TYPE_INFO); |
391 | 1 | IReflectablePtr reflectableTwo = std::make_shared<DummyEnumReflectable>(2, UINT8_ENUM_TYPE_INFO); |
392 | | |
393 | 1 | { |
394 | 1 | std::ostringstream os; |
395 | 1 | JsonWriter jsonWriter(os); |
396 | 1 | IWalkObserver& observer = jsonWriter; |
397 | 1 | observer.visitValue(reflectableZero, UINT8_ENUM_FIELD_INFO, WALKER_NOT_ELEMENT); |
398 | 1 | observer.visitValue(reflectableOne, UINT8_ENUM_FIELD_INFO, WALKER_NOT_ELEMENT); |
399 | 1 | observer.visitValue(reflectableTwo, UINT8_ENUM_FIELD_INFO, WALKER_NOT_ELEMENT); |
400 | | |
401 | | // note that this is not valid json |
402 | 1 | ASSERT_EQ( |
403 | 1 | "\"enumField\": \"ZERO\", " |
404 | 1 | "\"enumField\": \"One\", " |
405 | 1 | "\"enumField\": \"2 /* no match */\"", os.str()); |
406 | 1 | } |
407 | | |
408 | 1 | { |
409 | 1 | std::ostringstream os; |
410 | 1 | JsonWriter jsonWriter(os); |
411 | 1 | jsonWriter.setEnumerableFormat(JsonWriter::EnumerableFormat::NUMBER); |
412 | 1 | IWalkObserver& observer = jsonWriter; |
413 | 1 | observer.visitValue(reflectableZero, UINT8_ENUM_FIELD_INFO, WALKER_NOT_ELEMENT); |
414 | 1 | observer.visitValue(reflectableTwo, UINT8_ENUM_FIELD_INFO, WALKER_NOT_ELEMENT); |
415 | | |
416 | | // note that this is not valid json |
417 | 1 | ASSERT_EQ("\"enumField\": 0, \"enumField\": 2", os.str()); |
418 | 1 | } |
419 | 1 | } |
420 | | |
421 | | TEST_F(JsonWriterTest, bitmaskValue) |
422 | 1 | { |
423 | 1 | class DummyBitmaskReflectable : public ReflectableBase<std::allocator<uint8_t>> |
424 | 1 | { |
425 | 1 | public: |
426 | 1 | explicit DummyBitmaskReflectable(uint8_t value, |
427 | 1 | const BitmaskTypeInfo<std::allocator<uint8_t>>& typeInfo) : |
428 | 1 | ReflectableBase<std::allocator<uint8_t>>(typeInfo), |
429 | 1 | m_value(value) |
430 | 5 | {} |
431 | | |
432 | 1 | uint64_t toUInt() const override |
433 | 7 | { |
434 | 7 | return m_value; |
435 | 7 | } |
436 | | |
437 | 1 | private: |
438 | 1 | uint8_t m_value; |
439 | 1 | }; |
440 | | |
441 | 1 | IReflectablePtr reflectableZero = std::make_shared<DummyBitmaskReflectable>(0, BITMASK_TYPE_INFO); |
442 | 1 | IReflectablePtr reflectableTwo = std::make_shared<DummyBitmaskReflectable>(2, BITMASK_TYPE_INFO); |
443 | 1 | IReflectablePtr reflectableThree = std::make_shared<DummyBitmaskReflectable>(3, BITMASK_TYPE_INFO); |
444 | 1 | IReflectablePtr reflectableFour = std::make_shared<DummyBitmaskReflectable>(4, BITMASK_TYPE_INFO); |
445 | 1 | IReflectablePtr reflectableSeven = std::make_shared<DummyBitmaskReflectable>(7, BITMASK_TYPE_INFO); |
446 | | |
447 | 1 | { |
448 | 1 | std::ostringstream os; |
449 | 1 | JsonWriter jsonWriter(os); |
450 | 1 | IWalkObserver& observer = jsonWriter; |
451 | 1 | observer.visitValue(reflectableZero, BITMASK_FIELD_INFO, WALKER_NOT_ELEMENT); |
452 | 1 | observer.visitValue(reflectableTwo, BITMASK_FIELD_INFO, WALKER_NOT_ELEMENT); |
453 | 1 | observer.visitValue(reflectableThree, BITMASK_FIELD_INFO, WALKER_NOT_ELEMENT); |
454 | 1 | observer.visitValue(reflectableFour, BITMASK_FIELD_INFO, WALKER_NOT_ELEMENT); |
455 | 1 | observer.visitValue(reflectableSeven, BITMASK_FIELD_INFO, WALKER_NOT_ELEMENT); |
456 | | |
457 | | // note that this is not valid json |
458 | 1 | ASSERT_EQ( |
459 | 1 | "\"bitmaskField\": \"ZERO\", " |
460 | 1 | "\"bitmaskField\": \"TWO\", " |
461 | 1 | "\"bitmaskField\": \"One | TWO\", " |
462 | 1 | "\"bitmaskField\": \"4 /* no match */\", " |
463 | 1 | "\"bitmaskField\": \"7 /* partial match: One | TWO */\"", os.str()); |
464 | 1 | } |
465 | | |
466 | 1 | { |
467 | 1 | std::ostringstream os; |
468 | 1 | JsonWriter jsonWriter(os); |
469 | 1 | jsonWriter.setEnumerableFormat(JsonWriter::EnumerableFormat::NUMBER); |
470 | 1 | IWalkObserver& observer = jsonWriter; |
471 | 1 | observer.visitValue(reflectableZero, BITMASK_FIELD_INFO, WALKER_NOT_ELEMENT); |
472 | 1 | observer.visitValue(reflectableSeven, BITMASK_FIELD_INFO, WALKER_NOT_ELEMENT); |
473 | | |
474 | | // note that this is not valid json |
475 | 1 | ASSERT_EQ("\"bitmaskField\": 0, \"bitmaskField\": 7", os.str()); |
476 | 1 | } |
477 | 1 | } |
478 | | |
479 | | TEST_F(JsonWriterTest, unexpectedValue) |
480 | 1 | { |
481 | 1 | using allocator_type = ::std::allocator<uint8_t>; |
482 | | |
483 | 1 | const StructTypeInfo<allocator_type> structTypeInfo("Struct"_sv, nullptr, ""_sv, {}, {}, {}, {}); |
484 | 1 | class Reflectable : public ::zserio::ReflectableAllocatorHolderBase<allocator_type> |
485 | 1 | { |
486 | 1 | public: |
487 | 1 | explicit Reflectable(const StructTypeInfo<allocator_type>& structTypeInfo, |
488 | 1 | const allocator_type& allocator) : |
489 | 1 | ::zserio::ReflectableAllocatorHolderBase<allocator_type>(structTypeInfo, allocator) |
490 | 1 | {} |
491 | 1 | }; |
492 | 1 | auto reflectable = std::allocate_shared<Reflectable>(allocator_type(), structTypeInfo, allocator_type()); |
493 | | |
494 | 1 | ASSERT_THROW({ |
495 | 1 | try |
496 | 1 | { |
497 | 1 | std::ostringstream os; |
498 | 1 | JsonWriter jsonWriter(os); |
499 | 1 | IWalkObserver& observer = jsonWriter; |
500 | 1 | observer.visitValue(reflectable, BOOL_FIELD_INFO, WALKER_NOT_ELEMENT); |
501 | 1 | } |
502 | 1 | catch (const CppRuntimeException& e) |
503 | 1 | { |
504 | 1 | ASSERT_STREQ("JsonWriter: Unexpected not-null value of type 'Struct'!", e.what()); |
505 | 1 | throw; |
506 | 1 | } |
507 | 1 | }, CppRuntimeException); |
508 | 1 | } |
509 | | |
510 | | TEST_F(JsonWriterTest, compound) |
511 | 1 | { |
512 | 1 | std::ostringstream os; |
513 | 1 | JsonWriter jsonWriter(os); |
514 | 1 | IWalkObserver& observer = jsonWriter; |
515 | | |
516 | 1 | observer.beginRoot(nullptr); |
517 | 1 | observer.visitValue(ReflectableFactory::getUInt32(13), IDENTIFIER_FIELD_INFO, WALKER_NOT_ELEMENT); |
518 | 1 | observer.visitValue(ReflectableFactory::getString("test"_sv), STRING_FIELD_INFO, WALKER_NOT_ELEMENT); |
519 | 1 | BitBuffer bitBuffer({0xFF, 0x1F}, 13); |
520 | 1 | observer.visitValue(ReflectableFactory::getBitBuffer(bitBuffer), EXTERN_DATA_FIELD_INFO, |
521 | 1 | WALKER_NOT_ELEMENT); |
522 | 1 | vector<uint8_t> bytesData{{0xCA, 0xFE}}; |
523 | 1 | observer.visitValue(ReflectableFactory::getBytes(bytesData), BYTES_DATA_FIELD_INFO, WALKER_NOT_ELEMENT); |
524 | 1 | observer.endRoot(nullptr); |
525 | | |
526 | 1 | ASSERT_EQ("{\"identifier\": 13, \"stringField\": \"test\", " |
527 | 1 | "\"externData\": {\"buffer\": [255, 31], \"bitSize\": 13}, " |
528 | 1 | "\"bytesData\": {\"buffer\": [202, 254]}}", os.str()); |
529 | 1 | } |
530 | | |
531 | | TEST_F(JsonWriterTest, compoundArray) |
532 | 1 | { |
533 | 1 | std::ostringstream os; |
534 | 1 | JsonWriter jsonWriter(os); |
535 | 1 | IWalkObserver& observer = jsonWriter; |
536 | | |
537 | 1 | observer.beginRoot(nullptr); |
538 | 1 | observer.beginArray(nullptr, ARRAY_FIELD_INFO); |
539 | | |
540 | 1 | observer.beginCompound(nullptr, NESTED_FIELD_INFO, 0); |
541 | 1 | observer.visitValue(ReflectableFactory::getString("test"_sv), STRING_FIELD_INFO, WALKER_NOT_ELEMENT); |
542 | 1 | observer.endCompound(nullptr, NESTED_FIELD_INFO, 0); |
543 | | |
544 | 1 | observer.endArray(nullptr, ARRAY_FIELD_INFO); |
545 | 1 | observer.endRoot(nullptr); |
546 | | |
547 | 1 | ASSERT_EQ("{\"array\": [{\"stringField\": \"test\"}]}", os.str()); |
548 | 1 | } |
549 | | |
550 | | TEST_F(JsonWriterTest, nestedCompound) |
551 | 1 | { |
552 | 1 | std::ostringstream os; |
553 | 1 | JsonWriter jsonWriter(os); |
554 | | |
555 | 1 | walkNested(jsonWriter); |
556 | | |
557 | 1 | ASSERT_EQ("{\"identifier\": 13, \"nested\": {\"stringField\": \"test\"}}", os.str()); |
558 | 1 | } |
559 | | |
560 | | TEST_F(JsonWriterTest, array) |
561 | 1 | { |
562 | 1 | std::ostringstream os; |
563 | 1 | JsonWriter jsonWriter(os); |
564 | | |
565 | 1 | walkArray(jsonWriter); |
566 | | |
567 | 1 | ASSERT_EQ("{\"array\": [1, 2]}", os.str()); |
568 | 1 | } |
569 | | |
570 | | TEST_F(JsonWriterTest, arrayWithIndent) |
571 | 1 | { |
572 | 1 | std::ostringstream os; |
573 | 1 | JsonWriter jsonWriter(os, 2); |
574 | | |
575 | 1 | walkArray(jsonWriter); |
576 | | |
577 | 1 | ASSERT_EQ("{\n \"array\": [\n 1,\n 2\n ]\n}", os.str()); |
578 | 1 | } |
579 | | |
580 | | TEST_F(JsonWriterTest, emptyIndent) |
581 | 1 | { |
582 | 1 | std::ostringstream os; |
583 | 1 | JsonWriter jsonWriter(os, ""); |
584 | | |
585 | 1 | walkNested(jsonWriter); |
586 | | |
587 | 1 | ASSERT_EQ("{\n\"identifier\": 13,\n\"nested\": {\n\"stringField\": \"test\"\n}\n}", os.str()); |
588 | 1 | } |
589 | | |
590 | | TEST_F(JsonWriterTest, strIndent) |
591 | 1 | { |
592 | 1 | std::ostringstream os; |
593 | 1 | JsonWriter jsonWriter(os, " "); |
594 | | |
595 | 1 | walkNested(jsonWriter); |
596 | | |
597 | 1 | ASSERT_EQ("{\n \"identifier\": 13,\n \"nested\": {\n \"stringField\": \"test\"\n }\n}", os.str()); |
598 | 1 | } |
599 | | |
600 | | TEST_F(JsonWriterTest, intIndent) |
601 | 1 | { |
602 | 1 | std::ostringstream os; |
603 | 1 | JsonWriter jsonWriter(os, 2); |
604 | | |
605 | 1 | walkNested(jsonWriter); |
606 | | |
607 | 1 | ASSERT_EQ("{\n \"identifier\": 13,\n \"nested\": {\n \"stringField\": \"test\"\n }\n}", os.str()); |
608 | 1 | } |
609 | | |
610 | | TEST_F(JsonWriterTest, compactSeparators) |
611 | 1 | { |
612 | 1 | std::ostringstream os; |
613 | 1 | JsonWriter jsonWriter(os); |
614 | 1 | jsonWriter.setItemSeparator(","); |
615 | 1 | jsonWriter.setKeySeparator(":"); |
616 | | |
617 | 1 | walkNested(jsonWriter); |
618 | | |
619 | 1 | ASSERT_EQ("{\"identifier\":13,\"nested\":{\"stringField\":\"test\"}}", os.str()); |
620 | 1 | } |
621 | | |
622 | | } // namespace zserio |