GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: test/zserio/JsonWriterTest.cpp Lines: 287 287 100.0 %
Date: 2023-12-13 14:51:09 Branches: 559 1337 41.8 %

Line Branch Exec 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
29
class JsonWriterTest : public ::testing::Test
14
{
15
public:
16
29
    JsonWriterTest() :
17
29
            BOOL_FIELD_INFO{"boolField"_sv, BuiltinTypeInfo<>::getBool(),
18
                    {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false},
19
29
            INT8_FIELD_INFO{"int8Field"_sv, BuiltinTypeInfo<>::getInt8(),
20
                    {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false},
21
29
            INT16_FIELD_INFO{"int16Field"_sv, BuiltinTypeInfo<>::getInt16(),
22
                    {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false},
23
29
            INT32_FIELD_INFO{"int32Field"_sv, BuiltinTypeInfo<>::getInt32(),
24
                    {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false},
25
29
            INT64_FIELD_INFO{"int64Field"_sv, BuiltinTypeInfo<>::getInt64(),
26
                    {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false},
27
29
            UINT8_FIELD_INFO{"uint8Field"_sv, BuiltinTypeInfo<>::getUInt8(),
28
                    {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false},
29
29
            UINT16_FIELD_INFO{"uint16Field"_sv, BuiltinTypeInfo<>::getUInt16(),
30
                    {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false},
31
29
            UINT32_FIELD_INFO{"uint32Field"_sv, BuiltinTypeInfo<>::getUInt32(),
32
                    {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false},
33
29
            UINT64_FIELD_INFO{"uint64Field"_sv, BuiltinTypeInfo<>::getUInt64(),
34
                    {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false},
35
29
            FLOAT_FIELD_INFO{"floatField"_sv, BuiltinTypeInfo<>::getFloat32(),
36
                    {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false},
37
29
            DOUBLE_FIELD_INFO{"doubleField"_sv, BuiltinTypeInfo<>::getFloat64(),
38
                    {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false},
39
29
            BYTES_DATA_FIELD_INFO{"bytesData"_sv, BuiltinTypeInfo<>::getBytes(),
40
                    {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false},
41
29
            STRING_FIELD_INFO{"stringField"_sv, BuiltinTypeInfo<>::getString(),
42
                    {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false},
43
29
            EXTERN_DATA_FIELD_INFO{"externData"_sv, BuiltinTypeInfo<>::getBitBuffer(),
44
                    {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false},
45
29
            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
29
            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
29
            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
29
            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
29
            BITMASK_TYPE_INFO{"DummyBitmask"_sv, BuiltinTypeInfo<>::getUInt32(), {}, BITMASK_ITEMS},
70
            BITMASK_FIELD_INFO{"bitmaskField"_sv, BITMASK_TYPE_INFO,
71


580
                    {}, false, {}, {}, {}, false, {}, {}, false, {}, false, false}
72
29
    {}
73
74
protected:
75
5
    void walkNested(IWalkObserver& observer)
76
    {
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
2
    void walkArray(IWalkObserver& observer)
86
    {
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


802
TEST_F(JsonWriterTest, empty)
125
{
126
2
    std::ostringstream os;
127

2
    JsonWriter jsonWriter(os);
128
129




1
    ASSERT_EQ("", os.str());
130
}
131
132


802
TEST_F(JsonWriterTest, nullValue)
133
{
134
2
    std::ostringstream os;
135

2
    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
}
143
144


802
TEST_F(JsonWriterTest, boolValue)
145
{
146
2
    std::ostringstream os;
147

2
    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
}
155
156


802
TEST_F(JsonWriterTest, int8Value)
157
{
158
2
    std::ostringstream os;
159

2
    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
}
167
168


802
TEST_F(JsonWriterTest, int16Value)
169
{
170
2
    std::ostringstream os;
171

2
    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
}
179
180


802
TEST_F(JsonWriterTest, int32Value)
181
{
182
2
    std::ostringstream os;
183

2
    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
}
191
192


802
TEST_F(JsonWriterTest, int64Value)
193
{
194
2
    std::ostringstream os;
195

2
    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
}
203
204


802
TEST_F(JsonWriterTest, uint8Value)
205
{
206
2
    std::ostringstream os;
207

2
    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
}
215
216


802
TEST_F(JsonWriterTest, uint16Value)
217
{
218
2
    std::ostringstream os;
219

2
    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
}
227
228


802
TEST_F(JsonWriterTest, uint32Value)
229
{
230
2
    std::ostringstream os;
231

2
    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
}
239
240


802
TEST_F(JsonWriterTest, uint64Value)
241
{
242
2
    std::ostringstream os;
243

2
    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
}
251
252


802
TEST_F(JsonWriterTest, floatValue)
253
{
254
2
    std::ostringstream os;
255

2
    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
}
263
264


802
TEST_F(JsonWriterTest, doubleValue)
265
{
266
2
    std::ostringstream os;
267

2
    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
}
275
276


802
TEST_F(JsonWriterTest, bytesValue)
277
{
278
2
    std::ostringstream os;
279

2
    JsonWriter jsonWriter(os);
280
1
    IWalkObserver& observer = jsonWriter;
281
282

2
    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
}
288
289


802
TEST_F(JsonWriterTest, stringValue)
290
{
291
2
    std::ostringstream os;
292

2
    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
}
300
301


802
TEST_F(JsonWriterTest, externValue)
302
{
303
2
    std::ostringstream os;
304

2
    JsonWriter jsonWriter(os);
305
1
    IWalkObserver& observer = jsonWriter;
306
307

2
    BitBuffer bitBuffer({0xFF, 0x1F}, 13);
308
2
    observer.visitValue(ReflectableFactory::getBitBuffer(bitBuffer), EXTERN_DATA_FIELD_INFO,
309
2
            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
}
314
315


802
TEST_F(JsonWriterTest, signedEnumValue)
316
{
317
4
    class DummyEnumReflectable : public ReflectableBase<std::allocator<uint8_t>>
318
    {
319
    public:
320
4
        explicit DummyEnumReflectable(int8_t value, const EnumTypeInfo<std::allocator<uint8_t>>& typeInfo) :
321
                ReflectableBase<std::allocator<uint8_t>>(typeInfo),
322
4
                m_value(value)
323
4
        {}
324
325
8
        int64_t toInt() const override
326
        {
327
8
            return m_value;
328
        }
329
330
    private:
331
        int8_t m_value;
332
    };
333
334
2
    IReflectablePtr reflectableZero = std::make_shared<DummyEnumReflectable>(0, INT8_ENUM_TYPE_INFO);
335

2
    IReflectablePtr reflectableOne = std::make_shared<DummyEnumReflectable>(1, INT8_ENUM_TYPE_INFO);
336

2
    IReflectablePtr reflectableTwo = std::make_shared<DummyEnumReflectable>(2, INT8_ENUM_TYPE_INFO);
337

2
    IReflectablePtr reflectableMinusOne = std::make_shared<DummyEnumReflectable>(-1, INT8_ENUM_TYPE_INFO);
338
339
    {
340
2
        std::ostringstream os;
341

2
        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
                "\"enumField\": \"ZERO\", "
351
                "\"enumField\": \"One\", "
352
                "\"enumField\": \"2 /* no match */\", "
353
                "\"enumField\": \"MINUS_ONE\"", os.str());
354
    }
355
356
    {
357

2
        std::ostringstream os;
358

2
        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
    }
368
}
369
370


802
TEST_F(JsonWriterTest, unsignedEnumValue)
371
{
372
3
    class DummyEnumReflectable : public ReflectableBase<std::allocator<uint8_t>>
373
    {
374
    public:
375
3
        explicit DummyEnumReflectable(uint8_t value, const EnumTypeInfo<std::allocator<uint8_t>>& typeInfo) :
376
                ReflectableBase<std::allocator<uint8_t>>(typeInfo),
377
3
                m_value(value)
378
3
        {}
379
380
6
        uint64_t toUInt() const override
381
        {
382
6
            return m_value;
383
        }
384
385
    private:
386
        uint8_t m_value;
387
    };
388
389
2
    IReflectablePtr reflectableZero = std::make_shared<DummyEnumReflectable>(0, UINT8_ENUM_TYPE_INFO);
390

2
    IReflectablePtr reflectableOne = std::make_shared<DummyEnumReflectable>(1, UINT8_ENUM_TYPE_INFO);
391

2
    IReflectablePtr reflectableTwo = std::make_shared<DummyEnumReflectable>(2, UINT8_ENUM_TYPE_INFO);
392
393
    {
394
2
        std::ostringstream os;
395

2
        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
                "\"enumField\": \"ZERO\", "
404
                "\"enumField\": \"One\", "
405
                "\"enumField\": \"2 /* no match */\"", os.str());
406
    }
407
408
    {
409

2
        std::ostringstream os;
410

2
        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
    }
419
}
420
421


802
TEST_F(JsonWriterTest, bitmaskValue)
422
{
423
5
    class DummyBitmaskReflectable : public ReflectableBase<std::allocator<uint8_t>>
424
    {
425
    public:
426
5
        explicit DummyBitmaskReflectable(uint8_t value,
427
                const BitmaskTypeInfo<std::allocator<uint8_t>>& typeInfo) :
428
                ReflectableBase<std::allocator<uint8_t>>(typeInfo),
429
5
                m_value(value)
430
5
        {}
431
432
7
        uint64_t toUInt() const override
433
        {
434
7
            return m_value;
435
        }
436
437
    private:
438
        uint8_t m_value;
439
    };
440
441
2
    IReflectablePtr reflectableZero = std::make_shared<DummyBitmaskReflectable>(0, BITMASK_TYPE_INFO);
442

2
    IReflectablePtr reflectableTwo = std::make_shared<DummyBitmaskReflectable>(2, BITMASK_TYPE_INFO);
443

2
    IReflectablePtr reflectableThree = std::make_shared<DummyBitmaskReflectable>(3, BITMASK_TYPE_INFO);
444

2
    IReflectablePtr reflectableFour = std::make_shared<DummyBitmaskReflectable>(4, BITMASK_TYPE_INFO);
445

2
    IReflectablePtr reflectableSeven = std::make_shared<DummyBitmaskReflectable>(7, BITMASK_TYPE_INFO);
446
447
    {
448
2
        std::ostringstream os;
449

2
        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
                "\"bitmaskField\": \"ZERO\", "
460
                "\"bitmaskField\": \"TWO\", "
461
                "\"bitmaskField\": \"One | TWO\", "
462
                "\"bitmaskField\": \"4 /* no match */\", "
463
                "\"bitmaskField\": \"7 /* partial match: One | TWO */\"", os.str());
464
    }
465
466
    {
467

2
        std::ostringstream os;
468

2
        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
    }
477
}
478
479


802
TEST_F(JsonWriterTest, unexpectedValue)
480
{
481
    using allocator_type = ::std::allocator<uint8_t>;
482
483
2
    const StructTypeInfo<allocator_type> structTypeInfo("Struct"_sv, nullptr, ""_sv, {}, {}, {}, {});
484
1
    class Reflectable : public ::zserio::ReflectableAllocatorHolderBase<allocator_type>
485
    {
486
    public:
487
1
        explicit Reflectable(const StructTypeInfo<allocator_type>& structTypeInfo,
488
                const allocator_type& allocator) :
489
1
                ::zserio::ReflectableAllocatorHolderBase<allocator_type>(structTypeInfo, allocator)
490
1
        {}
491
    };
492

2
    auto reflectable = std::allocate_shared<Reflectable>(allocator_type(), structTypeInfo, allocator_type());
493
494















1
    ASSERT_THROW({
495
        try
496
        {
497
            std::ostringstream os;
498
            JsonWriter jsonWriter(os);
499
            IWalkObserver& observer = jsonWriter;
500
            observer.visitValue(reflectable, BOOL_FIELD_INFO, WALKER_NOT_ELEMENT);
501
        }
502
        catch (const CppRuntimeException& e)
503
        {
504
            ASSERT_STREQ("JsonWriter: Unexpected not-null value of type 'Struct'!", e.what());
505
            throw;
506
        }
507
    }, CppRuntimeException);
508
}
509
510


802
TEST_F(JsonWriterTest, compound)
511
{
512
2
    std::ostringstream os;
513

2
    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

2
    BitBuffer bitBuffer({0xFF, 0x1F}, 13);
520
2
    observer.visitValue(ReflectableFactory::getBitBuffer(bitBuffer), EXTERN_DATA_FIELD_INFO,
521
2
            WALKER_NOT_ELEMENT);
522

2
    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
            "\"externData\": {\"buffer\": [255, 31], \"bitSize\": 13}, "
528
            "\"bytesData\": {\"buffer\": [202, 254]}}", os.str());
529
}
530
531


802
TEST_F(JsonWriterTest, compoundArray)
532
{
533
2
    std::ostringstream os;
534

2
    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
}
549
550


802
TEST_F(JsonWriterTest, nestedCompound)
551
{
552
2
    std::ostringstream os;
553

2
    JsonWriter jsonWriter(os);
554
555
1
    walkNested(jsonWriter);
556
557




1
    ASSERT_EQ("{\"identifier\": 13, \"nested\": {\"stringField\": \"test\"}}", os.str());
558
}
559
560


802
TEST_F(JsonWriterTest, array)
561
{
562
2
    std::ostringstream os;
563

2
    JsonWriter jsonWriter(os);
564
565
1
    walkArray(jsonWriter);
566
567




1
    ASSERT_EQ("{\"array\": [1, 2]}", os.str());
568
}
569
570


802
TEST_F(JsonWriterTest, arrayWithIndent)
571
{
572
2
    std::ostringstream os;
573

2
    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
}
579
580


802
TEST_F(JsonWriterTest, emptyIndent)
581
{
582
2
    std::ostringstream os;
583

2
    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
}
589
590


802
TEST_F(JsonWriterTest, strIndent)
591
{
592
2
    std::ostringstream os;
593

2
    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
}
599
600


802
TEST_F(JsonWriterTest, intIndent)
601
{
602
2
    std::ostringstream os;
603

2
    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
}
609
610


802
TEST_F(JsonWriterTest, compactSeparators)
611
{
612
2
    std::ostringstream os;
613

2
    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
}
621
622

2394
} // namespace zserio