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