Coverage Report

Created: 2023-12-13 14:58

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