Coverage Report

Created: 2024-04-30 09:35

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