aboutsummaryrefslogblamecommitdiffstats
path: root/library/cpp/protobuf/json/ut/unknown_fields_collector_ut.cpp
blob: 00a2152a68953192b8c32e78b8e192041d2b1eb7 (plain) (tree)



































































































































































                                                                                                                                                                  
#include "json.h"
#include "proto.h"
#include "proto2json.h"

#include <library/cpp/protobuf/json/json2proto.h>

#include <library/cpp/testing/unittest/registar.h>

#include <util/generic/set.h>
#include <util/generic/string.h>

using namespace NProtobufJson;
using namespace NProtobufJsonTest;

struct TTestUnknownFieldsCollector : public IUnknownFieldsCollector {
    void OnEnterMapItem(const TString& key) override {
        CurrentPath.push_back(key);
    }

    void OnEnterArrayItem(ui64 id) override {
        CurrentPath.push_back(ToString(id));
    }

    void OnLeaveMapItem() override {
        CurrentPath.pop_back();
    }

    void OnLeaveArrayItem() override {
        CurrentPath.pop_back();
    }

    void OnUnknownField(const TString& key, const google::protobuf::Descriptor& value) override {
        TString path;
        for (auto& piece : CurrentPath) {
            path.append("/");
            path.append(piece);
        }
        path.append("/");
        path.append(key);
        UnknownKeys.insert(std::move(path));
        Y_UNUSED(value);
    }

    TVector<TString> CurrentPath;
    TSet<TString> UnknownKeys;
};

Y_UNIT_TEST_SUITE(TUnknownFieldsCollectorTest) {
    Y_UNIT_TEST(TestFlatOptional) {
        TFlatOptional proto;
        TSimpleSharedPtr<TTestUnknownFieldsCollector> collector = new TTestUnknownFieldsCollector;
        TJson2ProtoConfig cfg;
        cfg.SetUnknownFieldsCollector(collector).SetAllowUnknownFields(true);

        Json2Proto(TStringBuf(R"({"42":42,"I32":11,"test":2,"string":"str","String":"string","obj":{"inner":{}},"arr":[1,2,3]})"), proto, cfg);
        TSet<TString> expectedKeys = {
            {"/42"},
            {"/arr"},
            {"/obj"},
            {"/string"},
            {"/test"},
        };
        UNIT_ASSERT(collector->CurrentPath.empty());
        UNIT_ASSERT_VALUES_EQUAL(collector->UnknownKeys, expectedKeys);
    }

    Y_UNIT_TEST(TestFlatRepeated) {
        TFlatRepeated proto;
        TSimpleSharedPtr<TTestUnknownFieldsCollector> collector = new TTestUnknownFieldsCollector;
        TJson2ProtoConfig cfg;
        cfg.SetUnknownFieldsCollector(collector).SetAllowUnknownFields(true);

        Json2Proto(TStringBuf(R"({"42":42,"I32":[11,12],"test":12,"string":"str","String":["string1","string2"],"obj":{"inner":{}},"arr":[1,2,3]})"), proto, cfg);
        TSet<TString> expectedKeys = {
            {"/42"},
            {"/arr"},
            {"/obj"},
            {"/string"},
            {"/test"},
        };
        UNIT_ASSERT(collector->CurrentPath.empty());
        UNIT_ASSERT_VALUES_EQUAL(collector->UnknownKeys, expectedKeys);
    }

    Y_UNIT_TEST(TestCompositeOptional) {
        TCompositeOptional proto;
        TSimpleSharedPtr<TTestUnknownFieldsCollector> collector = new TTestUnknownFieldsCollector;
        TJson2ProtoConfig cfg;
        cfg.SetUnknownFieldsCollector(collector).SetAllowUnknownFields(true);

        Json2Proto(TStringBuf(R"({"Part":{"42":42,"I32":11,"test":12,"string":"str","String":"string"},"string2":"str"})"), proto, cfg);
        TSet<TString> expectedKeys = {
            {"/Part/42"},
            {"/Part/string"},
            {"/Part/test"},
            {"/string2"},
        };
        UNIT_ASSERT(collector->CurrentPath.empty());
        UNIT_ASSERT_VALUES_EQUAL(collector->UnknownKeys, expectedKeys);
    }

    Y_UNIT_TEST(TestCompositeRepeated) {
        TCompositeRepeated proto;
        TSimpleSharedPtr<TTestUnknownFieldsCollector> collector = new TTestUnknownFieldsCollector;
        TJson2ProtoConfig cfg;
        cfg.SetUnknownFieldsCollector(collector).SetAllowUnknownFields(true);

        Json2Proto(TStringBuf(R"({"Part":[)"
                              R"(         {"42":42,"I32":11,"test":12,"string":"str","String":"string"},)"
                              R"(         {"abc":"d"})"
                              R"(],)"
                              R"("string2":"str"})"), proto, cfg);
        TSet<TString> expectedKeys = {
            {"/Part/0/42"},
            {"/Part/0/string"},
            {"/Part/0/test"},
            {"/Part/1/abc"},
            {"/string2"},
        };
        UNIT_ASSERT(collector->CurrentPath.empty());
        UNIT_ASSERT_VALUES_EQUAL(collector->UnknownKeys, expectedKeys);
    }

    Y_UNIT_TEST(TestCompleMapType) {
        TComplexMapType proto;
        TSimpleSharedPtr<TTestUnknownFieldsCollector> collector = new TTestUnknownFieldsCollector;
        TJson2ProtoConfig cfg;
        cfg.SetUnknownFieldsCollector(collector).SetAllowUnknownFields(true);

        Json2Proto(TStringBuf(R"({"42":42,)"
                              R"("Nested":[)"
                              R"(         {"key":"abc","value":{"string":"string","Nested":[{"key":"def","value":{"string2":"string2"}}]}},)"
                              R"(         {"key":"car","value":{"string3":"string3"}})"
                              R"(]})"), proto, cfg);
        TSet<TString> expectedKeys = {
            {"/42"},
            {"/Nested/0/value/Nested/0/value/string2"},
            {"/Nested/0/value/string"},
            {"/Nested/1/value/string3"},
        };
        UNIT_ASSERT(collector->CurrentPath.empty());
        UNIT_ASSERT_VALUES_EQUAL(collector->UnknownKeys, expectedKeys);
    }

    Y_UNIT_TEST(TestCompleMapTypeMapAsObject) {
        TComplexMapType proto;
        TSimpleSharedPtr<TTestUnknownFieldsCollector> collector = new TTestUnknownFieldsCollector;
        TJson2ProtoConfig cfg;
        cfg.SetUnknownFieldsCollector(collector).SetAllowUnknownFields(true).SetMapAsObject(true);

        Json2Proto(TStringBuf(R"({"42":42,)"
                              R"("Nested":{)"
                              R"(    "abc":{"string":"string","Nested":{"def":{"string2":"string2"}}},)"
                              R"(    "car":{"string3":"string3"})"
                              R"(}})"), proto, cfg);
        TSet<TString> expectedKeys = {
            {"/42"},
            {"/Nested/abc/Nested/def/string2"},
            {"/Nested/abc/string"},
            {"/Nested/car/string3"},
        };
        UNIT_ASSERT(collector->CurrentPath.empty());
        UNIT_ASSERT_VALUES_EQUAL(collector->UnknownKeys, expectedKeys);
    }
} // TJson2ProtoTest