aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/protobuf/json/ut/inline_ut.cpp
blob: 548b6c29608d7eefe004c6a8a145527fcd679869 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <library/cpp/protobuf/json/ut/inline_ut.pb.h>

#include <library/cpp/protobuf/json/inline.h>
#include <library/cpp/protobuf/json/field_option.h>
#include <library/cpp/protobuf/json/proto2json.h>
#include <library/cpp/testing/unittest/registar.h>

#include <util/generic/string.h>

using namespace NProtobufJson;

static NProtobufJsonUt::TInlineTest GetTestMsg() {
    NProtobufJsonUt::TInlineTest msg;
    msg.SetOptJson(R"({"a":1,"b":"000"})");
    msg.SetNotJson("12{}34");
    msg.AddRepJson("{}");
    msg.AddRepJson("[1,2]");
    msg.MutableInner()->AddNumber(100);
    msg.MutableInner()->AddNumber(200);
    msg.MutableInner()->SetInnerJson(R"({"xxx":[]})");
    return msg;
}

Y_UNIT_TEST_SUITE(TProto2JsonInlineTest){ 
    Y_UNIT_TEST(TestNormalPrint){ 
        NProtobufJsonUt::TInlineTest msg = GetTestMsg();
// normal print should output these fields as just string values
TString expRaw = R"({"OptJson":"{\"a\":1,\"b\":\"000\"}","NotJson":"12{}34","RepJson":["{}","[1,2]"],)"
                 R"("Inner":{"Number":[100,200],"InnerJson":"{\"xxx\":[]}"}})";
TString myRaw;
Proto2Json(msg, myRaw);
UNIT_ASSERT_STRINGS_EQUAL(myRaw, expRaw);

myRaw = PrintInlined(msg, [](const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor*) { return false; });
UNIT_ASSERT_STRINGS_EQUAL(myRaw, expRaw); // result is the same
}

Y_UNIT_TEST(TestInliningPrinter) { 
    NProtobufJsonUt::TInlineTest msg = GetTestMsg();
    // inlined print should output these fields as inlined json sub-objects
    TString expInlined = R"({"OptJson":{"a":1,"b":"000"},"NotJson":"12{}34","RepJson":[{},[1,2]],)"
                         R"("Inner":{"Number":[100,200],"InnerJson":{"xxx":[]}}})";

    {
        TString myInlined = PrintInlined(msg, MakeFieldOptionFunctor(NProtobufJsonUt::inline_test));
        UNIT_ASSERT_STRINGS_EQUAL(myInlined, expInlined);
    }
    {
        auto functor = [](const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor* field) {
            return field->name() == "OptJson" || field->name() == "RepJson" || field->name() == "InnerJson";
        };
        TString myInlined = PrintInlined(msg, functor);
        UNIT_ASSERT_STRINGS_EQUAL(myInlined, expInlined);
    }
}

Y_UNIT_TEST(TestNoValues) { 
    // no values - no printing
    NProtobufJsonUt::TInlineTest msg;
    msg.MutableInner()->AddNumber(100);
    msg.MutableInner()->AddNumber(200);

    TString expInlined = R"({"Inner":{"Number":[100,200]}})";

    TString myInlined = PrintInlined(msg, MakeFieldOptionFunctor(NProtobufJsonUt::inline_test));
    UNIT_ASSERT_STRINGS_EQUAL(myInlined, expInlined);
}

Y_UNIT_TEST(TestMissingKeyModeNull) { 
    NProtobufJsonUt::TInlineTest msg;
    msg.MutableInner()->AddNumber(100);
    msg.MutableInner()->AddNumber(200);

    TString expInlined = R"({"OptJson":null,"NotJson":null,"RepJson":null,"Inner":{"Number":[100,200],"InnerJson":null}})";

    TProto2JsonConfig cfg;
    cfg.SetMissingSingleKeyMode(TProto2JsonConfig::MissingKeyNull).SetMissingRepeatedKeyMode(TProto2JsonConfig::MissingKeyNull);
    TString myInlined = PrintInlined(msg, MakeFieldOptionFunctor(NProtobufJsonUt::inline_test), cfg);
    UNIT_ASSERT_STRINGS_EQUAL(myInlined, expInlined);
}

Y_UNIT_TEST(TestMissingKeyModeDefault) { 
    NProtobufJsonUt::TInlineTestDefaultValues msg;

    TString expInlined = R"({"OptJson":{"default":1},"Number":0,"RepJson":[],"Inner":{"OptJson":{"default":2}}})";

    TProto2JsonConfig cfg;
    cfg.SetMissingSingleKeyMode(TProto2JsonConfig::MissingKeyDefault).SetMissingRepeatedKeyMode(TProto2JsonConfig::MissingKeyDefault);
    TString myInlined = PrintInlined(msg, MakeFieldOptionFunctor(NProtobufJsonUt::inline_test), cfg);
    UNIT_ASSERT_STRINGS_EQUAL(myInlined, expInlined);
}

Y_UNIT_TEST(NoUnnecessaryCopyFunctor) { 
    size_t CopyCount = 0;
    struct TFunctorMock {
        TFunctorMock(size_t* copyCount)
            : CopyCount(copyCount)
        {
            UNIT_ASSERT(*CopyCount <= 1);
        }

        TFunctorMock(const TFunctorMock& f)
            : CopyCount(f.CopyCount)
        {
            ++*CopyCount;
        }

        TFunctorMock(TFunctorMock&& f) = default;

        bool operator()(const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor*) const {
            return false;
        }

        size_t* CopyCount;
    };

    TProto2JsonConfig cfg;
    TInliningPrinter<> printer(TFunctorMock(&CopyCount), cfg);
    UNIT_ASSERT(CopyCount <= 1);
}
}
;