| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| #include <sys/time.h> |
| #include <gtest/gtest.h> |
| #include <iostream> |
| #include <fstream> |
| #include <string> |
| #include <google/protobuf/text_format.h> |
| #include "butil/iobuf.h" |
| #include "butil/string_printf.h" |
| #include "butil/strings/string_util.h" |
| #include "butil/third_party/rapidjson/rapidjson.h" |
| #include "butil/time.h" |
| #include "butil/gperftools_profiler.h" |
| #include "json2pb/pb_to_json.h" |
| #include "json2pb/json_to_pb.h" |
| #include "json2pb/encode_decode.h" |
| #include "json2pb/zero_copy_stream_reader.h" |
| #include "message.pb.h" |
| #include "addressbook1.pb.h" |
| #include "addressbook.pb.h" |
| #include "addressbook_encode_decode.pb.h" |
| #include "addressbook_map.pb.h" |
| |
| namespace { // just for coding-style check |
| |
| using addressbook::AddressBook; |
| using addressbook::Person; |
| |
| class ProtobufJsonTest : public testing::Test { |
| protected: |
| void SetUp() {} |
| void TearDown() {} |
| }; |
| |
| inline int64_t gettimeofday_us() { |
| timeval now; |
| gettimeofday(&now, NULL); |
| return now.tv_sec * 1000000L + now.tv_usec; |
| } |
| |
| TEST_F(ProtobufJsonTest, json_to_pb_normal_case) { |
| const int N = 1000; |
| int64_t total_tm = 0; |
| int64_t total_tm2 = 0; |
| for (int i = 0; i < N; ++i) { |
| std::string info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\"ext\":" |
| "{\"age\":1666666666, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":1}," |
| "\"uid\":\"someone\"},{\"distance\":10,\"unknown_member\":20," |
| "\"ext\":{\"age\":1666666660, \"databyte\":\"d2VsY29tZQ==\"," |
| "\"enumtype\":2},\"uid\":\"someone0\"}], \"judge\":false," |
| "\"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10]}"; |
| std::string error; |
| |
| JsonContextBody data; |
| const int64_t tm1 = gettimeofday_us(); |
| const bool ret = json2pb::JsonToProtoMessage(info3, &data, &error); |
| const int64_t tm2 = gettimeofday_us(); |
| total_tm += tm2 - tm1; |
| ASSERT_TRUE(ret); |
| |
| std::string info4; |
| std::string error1; |
| const int64_t tm3 = gettimeofday_us(); |
| bool ret2 = json2pb::ProtoMessageToJson(data, &info4, &error1); |
| const int64_t tm4 = gettimeofday_us(); |
| ASSERT_TRUE(ret2); |
| total_tm2 += tm4 - tm3; |
| #ifndef RAPIDJSON_VERSION_0_1 |
| ASSERT_STREQ("{\"data\":[1,2,3,4,5,6,7,8,9,10]," |
| "\"judge\":false,\"spur\":2.0,\"content\":[{\"uid\":\"someone\"," |
| "\"distance\":1.0,\"ext\":{\"age\":1666666666,\"databyte\":\"d2VsY29tZQ==\"," |
| "\"enumtype\":\"HOME\"}},\{\"uid\":\"someone0\",\"distance\":10.0,\"ext\":" |
| "{\"age\":1666666660,\"databyte\":\"d2VsY29tZQ==\",\"enumtype\":\"WORK\"}}]}", |
| info4.data()); |
| #else |
| ASSERT_STREQ("{\"data\":[1,2,3,4,5,6,7,8,9,10]," |
| "\"judge\":false,\"spur\":2,\"content\":[{\"uid\":\"someone\"," |
| "\"distance\":1,\"ext\":{\"age\":1666666666,\"databyte\":\"d2VsY29tZQ==\"," |
| "\"enumtype\":\"HOME\"}},\{\"uid\":\"someone0\",\"distance\":10,\"ext\":" |
| "{\"age\":1666666660,\"databyte\":\"d2VsY29tZQ==\",\"enumtype\":\"WORK\"}}]}", |
| info4.data()); |
| #endif |
| } |
| std::cout << "json2pb=" << total_tm / N |
| << "us pb2json=" << total_tm2 / N << "us" |
| << std::endl; |
| } |
| |
| TEST_F(ProtobufJsonTest, json_base64_string_to_pb_types_case) { |
| std::string info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\"ext\":" |
| "{\"age\":1666666666, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":1}," |
| "\"uid\":\"someone\"},{\"distance\":10,\"unknown_member\":20," |
| "\"ext\":{\"age\":1666666660, \"databyte\":\"d2VsY29tZTA=\"," |
| "\"enumtype\":2},\"uid\":\"someone0\"}], \"judge\":false," |
| "\"spur\":2}"; |
| std::string error; |
| |
| JsonContextBody data; |
| json2pb::Json2PbOptions options_j2pb; |
| options_j2pb.base64_to_bytes = true; |
| const bool ret = json2pb::JsonToProtoMessage(info3, &data, options_j2pb, &error); |
| ASSERT_TRUE(ret); |
| ASSERT_TRUE(data.content_size() == 2); |
| ASSERT_EQ(data.content(0).ext().databyte(), "welcome"); |
| ASSERT_EQ(data.content(1).ext().databyte(), "welcome0"); |
| |
| std::string info4; |
| std::string error1; |
| json2pb::Pb2JsonOptions options_pb2j; |
| options_pb2j.bytes_to_base64 = true; |
| bool ret2 = json2pb::ProtoMessageToJson(data, &info4, options_pb2j, &error1); |
| ASSERT_TRUE(ret2); |
| #ifndef RAPIDJSON_VERSION_0_1 |
| ASSERT_STREQ("{\"judge\":false,\"spur\":2.0,\"content\":[{\"uid\":\"someone\"," |
| "\"distance\":1.0,\"ext\":{\"age\":1666666666,\"databyte\":\"d2VsY29tZQ==\"," |
| "\"enumtype\":\"HOME\"}},\{\"uid\":\"someone0\",\"distance\":10.0,\"ext\":" |
| "{\"age\":1666666660,\"databyte\":\"d2VsY29tZTA=\",\"enumtype\":\"WORK\"}}]}", |
| info4.data()); |
| #else |
| ASSERT_STREQ("{\"judge\":false,\"spur\":2,\"content\":[{\"uid\":\"someone\"," |
| "\"distance\":1,\"ext\":{\"age\":1666666666,\"databyte\":\"d2VsY29tZQ==\"," |
| "\"enumtype\":\"HOME\"}},\{\"uid\":\"someone0\",\"distance\":10,\"ext\":" |
| "{\"age\":1666666660,\"databyte\":\"d2VsY29tZTA=\",\"enumtype\":\"WORK\"}}]}", |
| info4.data()); |
| #endif |
| } |
| |
| TEST_F(ProtobufJsonTest, json_to_pb_map_case) { |
| std::string json = "{\"addr\":\"baidu.com\"," |
| "\"numbers\":{\"tel\":123456,\"cell\":654321}," |
| "\"contacts\":{\"email\":\"frank@baidu.com\"," |
| " \"office\":\"Shanghai\"}," |
| "\"friends\":{\"John\":[{\"school\":\"SJTU\",\"year\":2007}]}}"; |
| std::string error; |
| AddressNoMap ab1; |
| ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &ab1, &error)); |
| ASSERT_EQ("baidu.com", ab1.addr()); |
| |
| AddressIntMap ab2; |
| ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &ab2, &error)); |
| ASSERT_EQ("baidu.com", ab2.addr()); |
| ASSERT_EQ("tel", ab2.numbers(0).key()); |
| ASSERT_EQ(123456, ab2.numbers(0).value()); |
| ASSERT_EQ("cell", ab2.numbers(1).key()); |
| ASSERT_EQ(654321, ab2.numbers(1).value()); |
| |
| AddressStringMap ab3; |
| ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &ab3, &error)); |
| ASSERT_EQ("baidu.com", ab3.addr()); |
| ASSERT_EQ("email", ab3.contacts(0).key()); |
| ASSERT_EQ("frank@baidu.com", ab3.contacts(0).value()); |
| ASSERT_EQ("office", ab3.contacts(1).key()); |
| ASSERT_EQ("Shanghai", ab3.contacts(1).value()); |
| |
| AddressComplex ab4; |
| ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &ab4, &error)) << error; |
| ASSERT_EQ("baidu.com", ab4.addr()); |
| ASSERT_EQ("John", ab4.friends(0).key()); |
| ASSERT_EQ("SJTU", ab4.friends(0).value(0).school()); |
| ASSERT_EQ(2007, ab4.friends(0).value(0).year()); |
| |
| std::string old_json = "{\"addr\":\"baidu.com\"," |
| "\"numbers\":[{\"key\":\"tel\",\"value\":123456}," |
| " {\"key\":\"cell\",\"value\":654321}]}"; |
| ab2.Clear(); |
| ASSERT_TRUE(json2pb::JsonToProtoMessage(old_json, &ab2, &error)) << error; |
| ASSERT_EQ("baidu.com", ab2.addr()); |
| ASSERT_EQ("tel", ab2.numbers(0).key()); |
| ASSERT_EQ(123456, ab2.numbers(0).value()); |
| ASSERT_EQ("cell", ab2.numbers(1).key()); |
| ASSERT_EQ(654321, ab2.numbers(1).value()); |
| } |
| |
| TEST_F(ProtobufJsonTest, json_to_pb_encode_decode) { |
| std::string info3 = "{\"@Content_Test%@\":[{\"Distance_info_\":1,\ |
| \"_ext%T_\":{\"Aa_ge(\":1666666666, \"databyte(std::string)\":\ |
| \"d2VsY29tZQ==\", \"enum--type\":\"HOME\"},\"uid*\":\"welcome\"}], \ |
| \"judge\":false, \"spur\":2, \"data:array\":[]}"; |
| printf("----------test json to pb------------\n\n"); |
| std::string error; |
| JsonContextBodyEncDec data; |
| ASSERT_TRUE(json2pb::JsonToProtoMessage(info3, &data, &error)); |
| |
| std::string info4; |
| std::string error1; |
| ASSERT_TRUE(json2pb::ProtoMessageToJson(data, &info4, &error1)); |
| #ifndef RAPIDJSON_VERSION_0_1 |
| ASSERT_STREQ("{\"judge\":false,\"spur\":2.0," |
| "\"@Content_Test%@\":[{\"uid*\":\"welcome\",\"Distance_info_\":1.0," |
| "\"_ext%T_\":{\"Aa_ge(\":1666666666,\"databyte(std::string)\":\"d2VsY29tZQ==\"," |
| "\"enum--type\":\"HOME\"}}]}", info4.data()); |
| #else |
| ASSERT_STREQ("{\"judge\":false,\"spur\":2," |
| "\"@Content_Test%@\":[{\"uid*\":\"welcome\",\"Distance_info_\":1," |
| "\"_ext%T_\":{\"Aa_ge(\":1666666666,\"databyte(std::string)\":\"d2VsY29tZQ==\"," |
| "\"enum--type\":\"HOME\"}}]}", info4.data()); |
| #endif |
| } |
| |
| TEST_F(ProtobufJsonTest, json_to_pb_unicode_case) { |
| AddressBook address_book; |
| |
| Person* person = address_book.add_person(); |
| |
| person->set_id(100); |
| |
| char name[255 * 1024]; |
| for (int j = 0; j < 255; j++) { |
| for (int i = 0; i < 1024; i++) { |
| name[j*1024 + i] = i + 1; |
| } |
| } |
| name[255 * 1024 - 1] = '\0'; |
| person->set_name(name); |
| person->set_data(-240000000); |
| person->set_data32(6); |
| person->set_data64(-1820000000); |
| person->set_datadouble(123.456); |
| person->set_datadouble_scientific(1.23456789e+08); |
| person->set_datafloat_scientific(1.23456789e+08); |
| person->set_datafloat(8.6123); |
| person->set_datau32(60); |
| person->set_datau64(960); |
| person->set_databool(0); |
| person->set_databyte("welcome to china"); |
| person->set_datafix32(1); |
| person->set_datafix64(666); |
| person->set_datasfix32(120); |
| person->set_datasfix64(-802); |
| |
| std::string info1; |
| std::string error; |
| |
| google::protobuf::TextFormat::Printer printer; |
| std::string text; |
| printer.PrintToString(*person, &text); |
| |
| printf("----------test pb to json------------\n\n"); |
| bool ret = json2pb::ProtoMessageToJson(address_book, &info1, &error); |
| ASSERT_TRUE(ret); |
| AddressBook address_book_test; |
| ret = json2pb::JsonToProtoMessage(info1, &address_book_test, &error); |
| ASSERT_TRUE(ret); |
| std::string info2; |
| ret = json2pb::ProtoMessageToJson(address_book_test, &info2, &error); |
| ASSERT_TRUE(ret); |
| ASSERT_TRUE(!info1.compare(info2)); |
| butil::IOBuf buf; |
| butil::IOBufAsZeroCopyOutputStream stream(&buf); |
| bool res = json2pb::ProtoMessageToJson(address_book, &stream, NULL); |
| ASSERT_TRUE(res); |
| butil::IOBufAsZeroCopyInputStream stream2(buf); |
| AddressBook address_book_test3; |
| ret = json2pb::JsonToProtoMessage(&stream2, &address_book_test3, &error); |
| ASSERT_TRUE(ret); |
| std::string info3; |
| ret = json2pb::ProtoMessageToJson(address_book_test3, &info3, &error); |
| ASSERT_TRUE(ret); |
| ASSERT_TRUE(!info2.compare(info3)); |
| } |
| |
| TEST_F(ProtobufJsonTest, json_to_pb_edge_case) { |
| std::string info3 = "{\"judge\":false, \"spur\":2.0e1}"; |
| |
| std::string error; |
| JsonContextBody data; |
| bool ret = json2pb::JsonToProtoMessage(info3, &data, &error); |
| ASSERT_TRUE(ret); |
| |
| std::string info4; |
| std::string error1; |
| ret = json2pb::ProtoMessageToJson(data, &info4, &error1); |
| ASSERT_TRUE(ret); |
| |
| info3 = "{\"judge\":false, \"spur\":-2, \"data\":[], \"info\":[],\"content\":[]}"; |
| error.clear(); |
| |
| JsonContextBody data1; |
| ret = json2pb::JsonToProtoMessage(info3, &data1, &error); |
| ASSERT_TRUE(ret); |
| |
| info4.clear(); |
| error1.clear(); |
| ret = json2pb::ProtoMessageToJson(data1, &info4, &error1); |
| ASSERT_TRUE(ret); |
| |
| info3 = "{\"judge\":false, \"spur\":\"NaN\"}"; |
| error.clear(); |
| |
| JsonContextBody data2; |
| ret = json2pb::JsonToProtoMessage(info3, &data2, &error); |
| ASSERT_TRUE(ret); |
| |
| info4.clear(); |
| error1.clear(); |
| ret = json2pb::ProtoMessageToJson(data2, &info4, &error1); |
| ASSERT_TRUE(ret); |
| |
| info3 = "{\"judge\":false, \"spur\":\"Infinity\"}"; |
| error.clear(); |
| |
| JsonContextBody data3; |
| ret = json2pb::JsonToProtoMessage(info3, &data3, &error); |
| ASSERT_TRUE(ret); |
| |
| info4.clear(); |
| error1.clear(); |
| ret = json2pb::ProtoMessageToJson(data3, &info4, &error1); |
| ASSERT_TRUE(ret); |
| |
| info3 = "{\"judge\":false, \"spur\":\"-inFiNITY\"}"; |
| error.clear(); |
| |
| JsonContextBody data4; |
| ret = json2pb::JsonToProtoMessage(info3, &data4, &error); |
| ASSERT_TRUE(ret); |
| |
| info4.clear(); |
| error1.clear(); |
| ret = json2pb::ProtoMessageToJson(data4, &info4, &error1); |
| ASSERT_TRUE(ret); |
| |
| info3 = "{\"judge\":false, \"spur\":2.0, \"content\":[{\"distance\":2.5, " |
| "\"ext\":{\"databyte\":\"d2VsY29tZQ==\", \"enumtype\":\"MOBILE\"}}]}"; |
| error.clear(); |
| |
| JsonContextBody data5; |
| ret = json2pb::JsonToProtoMessage(info3, &data5, &error); |
| ASSERT_TRUE(ret); |
| |
| info4.clear(); |
| error1.clear(); |
| ret = json2pb::ProtoMessageToJson(data5, &info4, &error1); |
| ASSERT_TRUE(ret); |
| |
| info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\ |
| \"ext\":{\"age\":1666666666, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":1},\ |
| \"uid\":\"someone\"},{\"distance\":2.3,\"unknown_member\":20,\ |
| \"ext\":{\"age\":1666666660, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":\"Test\"},\ |
| \"uid\":\"someone0\"}], \"judge\":false, \ |
| \"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10]}"; |
| error.clear(); |
| |
| JsonContextBody data9; |
| ret = json2pb::JsonToProtoMessage(info3, &data9, &error); |
| ASSERT_TRUE(ret); |
| ASSERT_STREQ("Invalid value `\"Test\"' for optional field `Ext.enumtype' which SHOULD be enum", error.data()); |
| |
| info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\ |
| \"ext\":{\"age\":1666666666, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":1},\ |
| \"uid\":\"someone\"},{\"distance\":5,\"unknown_member\":20,\ |
| \"ext\":{\"age\":1666666660, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":15},\ |
| \"uid\":\"someone0\"}], \"judge\":false, \ |
| \"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10]}"; |
| error.clear(); |
| |
| JsonContextBody data10; |
| ret = json2pb::JsonToProtoMessage(info3, &data10, &error); |
| ASSERT_TRUE(ret); |
| ASSERT_STREQ("Invalid value `15' for optional field `Ext.enumtype' which SHOULD be enum", error.data()); |
| |
| info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\ |
| \"ext\":{\"age\":1666666666, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":1},\ |
| \"uid\":\"someone\"},{\"distance\":5,\"unknown_member\":20,\ |
| \"ext\":{\"age\":1666666660, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":15},\ |
| \"uid\":\"someone0\"}], \"judge\":false, \ |
| \"spur\":2, \"type\":[\"123\"]}"; |
| error.clear(); |
| |
| JsonContextBody data11; |
| ret = json2pb::JsonToProtoMessage(info3, &data11, &error); |
| ASSERT_TRUE(ret); |
| ASSERT_STREQ("Invalid value `array' for optional field `JsonContextBody.type' which SHOULD be INT64, Invalid value `15' for optional field `Ext.enumtype' which SHOULD be enum", |
| error.data()); |
| } |
| |
| TEST_F(ProtobufJsonTest, json_to_pb_expected_failed_case) { |
| std::string info3 = "{\"content\":[{\"unknown_member\":2,\"ext\":{\"age\":1666666666, \ |
| \"databyte\":\"welcome\", \"enumtype\":1},\"uid\":\"someone\"},\ |
| {\"unknown_member\":20,\"ext\":{\"age\":1666666660, \"databyte\":\ |
| \"welcome0\", \"enumtype\":2},\"uid\":\"someone0\"}], \ |
| \"judge\":false, \"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10]}"; |
| std::string error; |
| |
| JsonContextBody data; |
| bool ret = json2pb::JsonToProtoMessage(info3, &data, &error); |
| ASSERT_FALSE(ret); |
| ASSERT_STREQ("Missing required field: Content.distance", error.data()); |
| |
| info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\"ext\":{\"age\":1666666666, \ |
| \"enumtype\":1},\"uid\":\"someone\"},{\"distance\":10,\"unknown_member\":20,\ |
| \"ext\":{\"age\":1666666660, \"databyte\":\"welcome0\", \"enumtype\":2},\ |
| \"uid\":\"someone0\"}], \"judge\":false, \ |
| \"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10]}"; |
| error.clear(); |
| |
| JsonContextBody data2; |
| ret = json2pb::JsonToProtoMessage(info3, &data2, &error); |
| ASSERT_FALSE(ret); |
| ASSERT_STREQ("Missing required field: Ext.databyte", error.data()); |
| |
| info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\ |
| \"ext\":{\"age\":1666666666, \"databyte\":\"welcome\", \"enumtype\":1},\ |
| \"uid\":\"someone\"},{\"distance\":10,\"unknown_member\":20,\ |
| \"ext\":{\"age\":1666666660, \"databyte\":\"welcome0\", \"enumtype\":2},\ |
| \"uid\":\"someone0\"}], \"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10]}"; |
| error.clear(); |
| |
| JsonContextBody data3; |
| ret = json2pb::JsonToProtoMessage(info3, &data, &error); |
| ASSERT_FALSE(ret); |
| ASSERT_STREQ("Missing required field: JsonContextBody.judge", error.data()); |
| |
| info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\ |
| \"ext\":{\"age\":1666666666, \"databyte\":\"welcome\", \"enumtype\":1},\ |
| \"uid\":\"someone\"},{\"distance\":10,\"unknown_member\":20,\ |
| \"ext\":{\"age\":1666666660, \"databyte\":\"welcome0\", \"enumtype\":2},\ |
| \"uid\":\"someone0\"}], \"judge\":\"false\", \ |
| \"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10]}"; |
| error.clear(); |
| |
| JsonContextBody data4; |
| ret = json2pb::JsonToProtoMessage(info3, &data4, &error); |
| ASSERT_FALSE(ret); |
| ASSERT_STREQ("Invalid value `\"false\"' for field `JsonContextBody.judge' which SHOULD be BOOL", error.data()); |
| |
| info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\ |
| \"ext\":{\"age\":1666666666, \"databyte\":\"welcome\", \"enumtype\":1},\ |
| \"uid\":\"someone\"},{\"distance\":10,\"unknown_member\":20,\ |
| \"ext\":{\"age\":1666666660, \"databyte\":\"welcome0\", \"enumtype\":2},\ |
| \"uid\":\"someone0\"}], \"judge\":false, \ |
| \"spur\":2, \"data\":[\"1\",\"2\",\"3\",\"4\"]}"; |
| error.clear(); |
| |
| JsonContextBody data5; |
| ret = json2pb::JsonToProtoMessage(info3, &data5, &error); |
| ASSERT_FALSE(ret); |
| ASSERT_STREQ("Invalid value `\"1\"' for field `JsonContextBody.data' which SHOULD be INT32", error.data()); |
| |
| info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\ |
| \"ext\":{\"age\":1666666666, \"databyte\":\"welcome\", \"enumtype\":1},\ |
| \"uid\":\"someone\"},{\"distance\":10,\"unknown_member\":20,\ |
| \"ext\":{\"age\":1666666660, \"databyte\":\"welcome0\", \"enumtype\":2},\ |
| \"uid\":\"someone0\"}], \"judge\":false, \ |
| \"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10], \"info\":2}"; |
| error.clear(); |
| |
| JsonContextBody data6; |
| ret = json2pb::JsonToProtoMessage(info3, &data6, &error); |
| ASSERT_FALSE(ret); |
| ASSERT_STREQ("Invalid value for repeated field: JsonContextBody.info", error.data()); |
| |
| info3 = "{\"judge\":false, \"spur\":\"NaNa\"}"; |
| error.clear(); |
| |
| JsonContextBody data7; |
| ret = json2pb::JsonToProtoMessage(info3, &data7, &error); |
| ASSERT_FALSE(ret); |
| ASSERT_STREQ("Invalid value `\"NaNa\"' for field `JsonContextBody.spur' which SHOULD be d", |
| error.data()); |
| |
| info3 = "{\"judge\":false, \"spur\":\"Infinty\"}"; |
| error.clear(); |
| |
| JsonContextBody data8; |
| ret = json2pb::JsonToProtoMessage(info3, &data8, &error); |
| ASSERT_FALSE(ret); |
| ASSERT_STREQ("Invalid value `\"Infinty\"' for field `JsonContextBody.spur' which SHOULD be d", |
| error.data()); |
| |
| info3 = "{\"content\":[{\"distance\":1,\"unknown_member\":2,\"ext\":{\"age\":1666666666, \ |
| \"enumtype\":1},\"uid\":23},{\"distance\":10,\"unknown_member\":20,\ |
| \"ext\":{\"age\":1666666660, \"databyte\":\"welcome0\", \"enumtype\":2},\ |
| \"uid\":\"someone0\"}], \"judge\":false, \ |
| \"spur\":2, \"data\":[1,2,3,4,5,6,7,8,9,10]}"; |
| error.clear(); |
| |
| JsonContextBody data9; |
| ret = json2pb::JsonToProtoMessage(info3, &data9, &error); |
| ASSERT_FALSE(ret); |
| ASSERT_STREQ("Invalid value `23' for optional field `Content.uid' which SHOULD be string, Missing required field: Ext.databyte", error.data()); |
| } |
| |
| TEST_F(ProtobufJsonTest, json_to_pb_perf_case) { |
| |
| std::string info3 = "{\"content\":[{\"distance\":1.0,\ |
| \"ext\":{\"age\":1666666666, \"databyte\":\"d2VsY29tZQ==\", \"enumtype\":1},\ |
| \"uid\":\"welcome\"}], \"judge\":false, \"spur\":2.0, \"data\":[]}"; |
| |
| printf("----------test json to pb performance------------\n\n"); |
| |
| std::string error; |
| |
| ProfilerStart("json_to_pb_perf.prof"); |
| butil::Timer timer; |
| bool res; |
| float avg_time1 = 0; |
| float avg_time2 = 0; |
| const int times = 100000; |
| for (int i = 0; i < times; i++) { |
| JsonContextBody data; |
| timer.start(); |
| res = json2pb::JsonToProtoMessage(info3, &data, &error); |
| timer.stop(); |
| avg_time1 += timer.u_elapsed(); |
| ASSERT_TRUE(res); |
| |
| std::string info4; |
| std::string error1; |
| timer.start(); |
| res = json2pb::ProtoMessageToJson(data, &info4, &error1); |
| timer.stop(); |
| avg_time2 += timer.u_elapsed(); |
| ASSERT_TRUE(res); |
| } |
| avg_time1 /= times; |
| avg_time2 /= times; |
| ProfilerStop(); |
| printf("avg time to convert json to pb is %fus\n", avg_time1); |
| printf("avg time to convert pb to json is %fus\n", avg_time2); |
| } |
| |
| TEST_F(ProtobufJsonTest, json_to_pb_encode_decode_perf_case) { |
| std::string info3 = "{\"@Content_Test%@\":[{\"Distance_info_\":1,\ |
| \"_ext%T_\":{\"Aa_ge(\":1666666666, \"databyte(std::string)\":\ |
| \"welcome\", \"enum--type\":1},\"uid*\":\"welcome\"}], \ |
| \"judge\":false, \"spur\":2, \"data:array\":[]}"; |
| printf("----------test json to pb encode/decode performance------------\n\n"); |
| std::string error; |
| |
| ProfilerStart("json_to_pb_encode_decode_perf.prof"); |
| butil::Timer timer; |
| bool res; |
| float avg_time1 = 0; |
| float avg_time2 = 0; |
| const int times = 100000; |
| for (int i = 0; i < times; i++) { |
| JsonContextBody data; |
| timer.start(); |
| res = json2pb::JsonToProtoMessage(info3, &data, &error); |
| timer.stop(); |
| avg_time1 += timer.u_elapsed(); |
| ASSERT_TRUE(res); |
| |
| std::string info4; |
| std::string error1; |
| timer.start(); |
| res = json2pb::ProtoMessageToJson(data, &info4, &error1); |
| timer.stop(); |
| avg_time2 += timer.u_elapsed(); |
| ASSERT_TRUE(res); |
| } |
| avg_time1 /= times; |
| avg_time2 /= times; |
| ProfilerStop(); |
| printf("avg time to convert json to pb is %fus\n", avg_time1); |
| printf("avg time to convert pb to json is %fus\n", avg_time2); |
| } |
| |
| TEST_F(ProtobufJsonTest, json_to_pb_complex_perf_case) { |
| std::ifstream in("jsonout", std::ios::in); |
| std::ostringstream tmp; |
| tmp << in.rdbuf(); |
| butil::IOBuf buf; |
| buf.append(tmp.str()); |
| in.close(); |
| |
| printf("----------test json to pb performance------------\n\n"); |
| |
| std::string error; |
| |
| butil::Timer timer; |
| |
| bool res; |
| float avg_time1 = 0; |
| const int times = 10000; |
| json2pb::Json2PbOptions options; |
| options.base64_to_bytes = false; |
| ProfilerStart("json_to_pb_complex_perf.prof"); |
| for (int i = 0; i < times; i++) { |
| gss::message::gss_us_res_t data; |
| butil::IOBufAsZeroCopyInputStream stream(buf); |
| timer.start(); |
| res = json2pb::JsonToProtoMessage(&stream, &data, options, &error); |
| timer.stop(); |
| avg_time1 += timer.u_elapsed(); |
| ASSERT_TRUE(res); |
| } |
| ProfilerStop(); |
| avg_time1 /= times; |
| printf("avg time to convert json to pb is %fus\n", avg_time1); |
| } |
| |
| TEST_F(ProtobufJsonTest, json_to_pb_to_string_complex_perf_case) { |
| std::ifstream in("jsonout", std::ios::in); |
| std::ostringstream tmp; |
| tmp << in.rdbuf(); |
| std::string info3 = tmp.str(); |
| in.close(); |
| |
| printf("----------test json to pb performance------------\n\n"); |
| |
| std::string error; |
| |
| butil::Timer timer; |
| bool res; |
| float avg_time1 = 0; |
| const int times = 10000; |
| json2pb::Json2PbOptions options; |
| options.base64_to_bytes = false; |
| ProfilerStart("json_to_pb_to_string_complex_perf.prof"); |
| for (int i = 0; i < times; i++) { |
| gss::message::gss_us_res_t data; |
| timer.start(); |
| res = json2pb::JsonToProtoMessage(info3, &data, options, &error); |
| timer.stop(); |
| avg_time1 += timer.u_elapsed(); |
| ASSERT_TRUE(res); |
| } |
| avg_time1 /= times; |
| ProfilerStop(); |
| printf("avg time to convert json to pb is %fus\n", avg_time1); |
| } |
| |
| TEST_F(ProtobufJsonTest, pb_to_json_normal_case) { |
| AddressBook address_book; |
| |
| Person* person = address_book.add_person(); |
| |
| person->set_id(100); |
| person->set_name("baidu"); |
| person->set_email("welcome@baidu.com"); |
| |
| Person::PhoneNumber* phone_number = person->add_phone(); |
| phone_number->set_number("number123"); |
| phone_number->set_type(Person::HOME); |
| |
| person->set_data(-240000000); |
| person->set_data32(6); |
| person->set_data64(-1820000000); |
| person->set_datadouble(123.456); |
| person->set_datadouble_scientific(1.23456789e+08); |
| person->set_datafloat_scientific(1.23456789e+08); |
| person->set_datafloat(8.6123); |
| person->set_datau32(60); |
| person->set_datau64(960); |
| person->set_databool(0); |
| person->set_databyte("welcome"); |
| person->set_datafix32(1); |
| person->set_datafix64(666); |
| person->set_datasfix32(120); |
| person->set_datasfix64(-802); |
| |
| std::string info1; |
| |
| google::protobuf::TextFormat::Printer printer; |
| std::string text; |
| printer.PrintToString(*person, &text); |
| |
| printf("text:%s\n", text.data()); |
| |
| printf("----------test pb to json------------\n\n"); |
| json2pb::Pb2JsonOptions option; |
| option.bytes_to_base64 = true; |
| bool ret = json2pb::ProtoMessageToJson(address_book, &info1, option, NULL); |
| ASSERT_TRUE(ret); |
| |
| #ifndef RAPIDJSON_VERSION_0_1 |
| ASSERT_STREQ("{\"person\":[{\"name\":\"baidu\",\"id\":100,\"email\":\"welcome@baidu.com\"," |
| "\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000," |
| "\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456," |
| "\"datafloat\":8.612299919128418,\"datau32\":60,\"datau64\":960," |
| "\"databool\":false,\"databyte\":\"d2VsY29tZQ==\",\"datafix32\":1," |
| "\"datafix64\":666,\"datasfix32\":120,\"datasfix64\":-802," |
| "\"datafloat_scientific\":123456792.0,\"datadouble_scientific\":123456789.0}]}", |
| info1.data()); |
| #else |
| ASSERT_STREQ("{\"person\":[{\"name\":\"baidu\",\"id\":100,\"email\":\"welcome@baidu.com\"," |
| "\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000," |
| "\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456," |
| "\"datafloat\":8.612299919,\"datau32\":60,\"datau64\":960,\"databool\":false," |
| "\"databyte\":\"d2VsY29tZQ==\",\"datafix32\":1,\"datafix64\":666," |
| "\"datasfix32\":120,\"datasfix64\":-802,\"datafloat_scientific\":123456792," |
| "\"datadouble_scientific\":123456789}]}", info1.data()); |
| #endif |
| |
| info1.clear(); |
| { |
| json2pb::Pb2JsonOptions option; |
| option.bytes_to_base64 = true; |
| ret = ProtoMessageToJson(address_book, &info1, option, NULL); |
| } |
| ASSERT_TRUE(ret); |
| |
| #ifndef RAPIDJSON_VERSION_0_1 |
| ASSERT_STREQ("{\"person\":[{\"name\":\"baidu\",\"id\":100,\"email\":\"welcome@baidu.com\"," |
| "\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000," |
| "\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456," |
| "\"datafloat\":8.612299919128418,\"datau32\":60,\"datau64\":960," |
| "\"databool\":false,\"databyte\":\"d2VsY29tZQ==\",\"datafix32\":1," |
| "\"datafix64\":666,\"datasfix32\":120,\"datasfix64\":-802," |
| "\"datafloat_scientific\":123456792.0,\"datadouble_scientific\":123456789.0}]}", |
| info1.data()); |
| #else |
| ASSERT_STREQ("{\"person\":[{\"name\":\"baidu\",\"id\":100,\"email\":\"welcome@baidu.com\"," |
| "\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000," |
| "\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456," |
| "\"datafloat\":8.612299919,\"datau32\":60,\"datau64\":960,\"databool\":false," |
| "\"databyte\":\"d2VsY29tZQ==\",\"datafix32\":1,\"datafix64\":666," |
| "\"datasfix32\":120,\"datasfix64\":-802,\"datafloat_scientific\":123456792," |
| "\"datadouble_scientific\":123456789}]}", info1.data()); |
| #endif |
| |
| info1.clear(); |
| { |
| json2pb::Pb2JsonOptions option; |
| option.bytes_to_base64 = true; |
| option.enum_option = json2pb::OUTPUT_ENUM_BY_NUMBER; |
| ret = ProtoMessageToJson(address_book, &info1, option, NULL); |
| } |
| ASSERT_TRUE(ret); |
| |
| #ifndef RAPIDJSON_VERSION_0_1 |
| ASSERT_STREQ("{\"person\":[{\"name\":\"baidu\",\"id\":100,\"email\":\"welcome@baidu.com\"," |
| "\"phone\":[{\"number\":\"number123\",\"type\":1}],\"data\":-240000000," |
| "\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456," |
| "\"datafloat\":8.612299919128418,\"datau32\":60,\"datau64\":960," |
| "\"databool\":false,\"databyte\":\"d2VsY29tZQ==\",\"datafix32\":1," |
| "\"datafix64\":666,\"datasfix32\":120,\"datasfix64\":-802," |
| "\"datafloat_scientific\":123456792.0,\"datadouble_scientific\":123456789.0}]}", |
| info1.data()); |
| #else |
| ASSERT_STREQ("{\"person\":[{\"name\":\"baidu\",\"id\":100,\"email\":\"welcome@baidu.com\"," |
| "\"phone\":[{\"number\":\"number123\",\"type\":1}],\"data\":-240000000," |
| "\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456," |
| "\"datafloat\":8.612299919,\"datau32\":60,\"datau64\":960,\"databool\":false," |
| "\"databyte\":\"d2VsY29tZQ==\",\"datafix32\":1,\"datafix64\":666," |
| "\"datasfix32\":120,\"datasfix64\":-802,\"datafloat_scientific\":123456792," |
| "\"datadouble_scientific\":123456789}]}", info1.data()); |
| #endif |
| |
| printf("----------test json to pb------------\n\n"); |
| |
| const int N = 1000; |
| int64_t total_tm = 0; |
| int64_t total_tm2 = 0; |
| for (int i = 0; i < N; ++i) { |
| |
| std::string info3; |
| AddressBook data1; |
| std::string error1; |
| const int64_t tm1 = gettimeofday_us(); |
| bool ret1 = json2pb::JsonToProtoMessage(info1, &data1, &error1); |
| const int64_t tm2 = gettimeofday_us(); |
| total_tm += tm2 - tm1; |
| ASSERT_TRUE(ret1); |
| |
| std::string error2; |
| const int64_t tm3 = gettimeofday_us(); |
| ret1 = json2pb::ProtoMessageToJson(data1, &info3, &error2); |
| const int64_t tm4 = gettimeofday_us(); |
| ASSERT_TRUE(ret1); |
| total_tm2 += tm4 - tm3; |
| #ifndef RAPIDJSON_VERSION_0_1 |
| ASSERT_STREQ("{\"person\":[{\"name\":\"baidu\",\"id\":100,\"email\":\"welcome@baidu.com\"," |
| "\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000," |
| "\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456," |
| "\"datafloat\":8.612299919128418,\"datau32\":60,\"datau64\":960," |
| "\"databool\":false,\"databyte\":\"d2VsY29tZQ==\",\"datafix32\":1," |
| "\"datafix64\":666,\"datasfix32\":120,\"datasfix64\":-802," |
| "\"datafloat_scientific\":123456792.0,\"datadouble_scientific\":123456789.0}]}", |
| info3.data()); |
| #else |
| ASSERT_STREQ("{\"person\":[{\"name\":\"baidu\",\"id\":100,\"email\":\"welcome@baidu.com\"," |
| "\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000," |
| "\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456," |
| "\"datafloat\":8.612299919,\"datau32\":60,\"datau64\":960,\"databool\":false," |
| "\"databyte\":\"d2VsY29tZQ==\",\"datafix32\":1,\"datafix64\":666," |
| "\"datasfix32\":120,\"datasfix64\":-802,\"datafloat_scientific\":123456792," |
| "\"datadouble_scientific\":123456789}]}", info3.data()); |
| #endif |
| } |
| std::cout << "json2pb=" << total_tm / N |
| << "us pb2json=" << total_tm2 / N << "us" |
| << std::endl; |
| } |
| |
| TEST_F(ProtobufJsonTest, pb_to_json_map_case) { |
| std::string json = "{\"addr\":\"baidu.com\"," |
| "\"numbers\":{\"tel\":123456,\"cell\":654321}," |
| "\"contacts\":{\"email\":\"frank@baidu.com\"," |
| " \"office\":\"Shanghai\"}," |
| "\"friends\":{\"John\":[{\"school\":\"SJTU\",\"year\":2007}]}}"; |
| std::string output; |
| std::string error; |
| AddressNoMap ab1; |
| ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &ab1, &error)); |
| ASSERT_TRUE(json2pb::ProtoMessageToJson(ab1, &output, &error)); |
| ASSERT_TRUE(output.find("\"addr\":\"baidu.com\"") != std::string::npos); |
| |
| output.clear(); |
| AddressIntMap ab2; |
| ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &ab2, &error)); |
| ASSERT_TRUE(json2pb::ProtoMessageToJson(ab2, &output, &error)); |
| ASSERT_TRUE(output.find("\"addr\":\"baidu.com\"") != std::string::npos); |
| ASSERT_TRUE(output.find("\"tel\":123456") != std::string::npos); |
| ASSERT_TRUE(output.find("\"cell\":654321") != std::string::npos); |
| |
| output.clear(); |
| AddressStringMap ab3; |
| ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &ab3, &error)); |
| ASSERT_TRUE(json2pb::ProtoMessageToJson(ab3, &output, &error)); |
| ASSERT_TRUE(output.find("\"addr\":\"baidu.com\"") != std::string::npos); |
| ASSERT_TRUE(output.find("\"email\":\"frank@baidu.com\"") != std::string::npos); |
| ASSERT_TRUE(output.find("\"office\":\"Shanghai\"") != std::string::npos); |
| |
| output.clear(); |
| AddressComplex ab4; |
| ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &ab4, &error)); |
| ASSERT_TRUE(json2pb::ProtoMessageToJson(ab4, &output, &error)); |
| ASSERT_TRUE(output.find("\"addr\":\"baidu.com\"") != std::string::npos); |
| ASSERT_TRUE(output.find("\"friends\":{\"John\":[{\"school\":\"SJTU\"," |
| "\"year\":2007}]}") != std::string::npos); |
| } |
| |
| TEST_F(ProtobufJsonTest, pb_to_json_encode_decode) { |
| JsonContextBodyEncDec json_data; |
| json_data.set_type(80000); |
| json_data.add_data_z058_array(200); |
| json_data.add_data_z058_array(300); |
| json_data.add_info("this is json data's info"); |
| json_data.add_info("this is a test"); |
| json_data.set_judge(true); |
| json_data.set_spur(3.45); |
| |
| ContentEncDec * content = json_data.add__z064_content_test_z037__z064_(); |
| content->set_uid_z042_("content info"); |
| content->set_distance_info_(1234.56); |
| |
| ExtEncDec* ext = content->mutable__ext_z037_t_(); |
| ext->set_aa_ge_z040_(160000); |
| ext->set_databyte_z040_std_z058__z058_string_z041_("databyte"); |
| ext->set_enum_z045__z045_type(ExtEncDec_PhoneTypeEncDec_WORK); |
| |
| std::string info1; |
| |
| google::protobuf::TextFormat::Printer printer; |
| std::string text; |
| printer.PrintToString(json_data, &text); |
| |
| printf("text:%s\n", text.data()); |
| |
| printf("----------test pb to json------------\n\n"); |
| json2pb::Pb2JsonOptions option; |
| option.bytes_to_base64 = true; |
| ASSERT_TRUE(ProtoMessageToJson(json_data, &info1, option, NULL)); |
| #ifndef RAPIDJSON_VERSION_0_1 |
| ASSERT_STREQ("{\"info\":[\"this is json data's info\",\"this is a test\"],\"type\":80000," |
| "\"data:array\":[200,300],\"judge\":true,\"spur\":3.45,\"@Content_Test%@\":" |
| "[{\"uid*\":\"content info\",\"Distance_info_\":1234.56005859375,\"_ext%T_\":" |
| "{\"Aa_ge(\":160000,\"databyte(std::string)\":\"ZGF0YWJ5dGU=\"," |
| "\"enum--type\":\"WORK\"}}]}", |
| info1.data()); |
| #else |
| ASSERT_STREQ("{\"info\":[\"this is json data's info\",\"this is a test\"],\"type\":80000," |
| "\"data:array\":[200,300],\"judge\":true,\"spur\":3.45,\"@Content_Test%@\":" |
| "[{\"uid*\":\"content info\",\"Distance_info_\":1234.560059,\"_ext%T_\":" |
| "{\"Aa_ge(\":160000,\"databyte(std::string)\":\"ZGF0YWJ5dGU=\"," |
| "\"enum--type\":\"WORK\"}}]}", |
| info1.data()); |
| #endif |
| printf("----------test json to pb------------\n\n"); |
| |
| std::string info3; |
| JsonContextBodyEncDec data1; |
| json2pb::JsonToProtoMessage(info1, &data1, NULL); |
| json2pb::ProtoMessageToJson(data1, &info3, NULL); |
| ASSERT_STREQ(info1.data(), info3.data()); |
| |
| printf("----------test single repeated pb to json array------------\n\n"); |
| |
| AddressBookEncDec single_repeated_json_data; |
| |
| auto person = single_repeated_json_data.add_person(); |
| person->set_id(1); |
| person->set_name("foo"); |
| *person->mutable_json_body() = json_data; |
| option.bytes_to_base64 = true; |
| |
| std::string text1; |
| printer.PrintToString(single_repeated_json_data, &text1); |
| |
| printf("text1:\n\n%s\n", text1.data()); |
| |
| std::string info4; |
| option.single_repeated_to_array = false; |
| ASSERT_TRUE(ProtoMessageToJson(single_repeated_json_data, &info4, option, NULL)); |
| #ifndef RAPIDJSON_VERSION_0_1 |
| ASSERT_STREQ("{\"person\":[" |
| "{\"name\":\"foo\",\"id\":1,\"json_body\":" |
| "{\"info\":[\"this is json data's info\",\"this is a test\"],\"type\":80000," |
| "\"data:array\":[200,300],\"judge\":true,\"spur\":3.45,\"@Content_Test%@\":" |
| "[{\"uid*\":\"content info\",\"Distance_info_\":1234.56005859375,\"_ext%T_\":" |
| "{\"Aa_ge(\":160000,\"databyte(std::string)\":\"ZGF0YWJ5dGU=\"," |
| "\"enum--type\":\"WORK\"}}]}}]}", |
| info4.data()); |
| #else |
| ASSERT_STREQ("{\"person\":[" |
| "{\"name\":\"foo\",\"id\":1,\"json_body\":" |
| "{\"info\":[\"this is json data's info\",\"this is a test\"],\"type\":80000," |
| "\"data:array\":[200,300],\"judge\":true,\"spur\":3.45,\"@Content_Test%@\":" |
| "[{\"uid*\":\"content info\",\"Distance_info_\":1234.560059,\"_ext%T_\":" |
| "{\"Aa_ge(\":160000,\"databyte(std::string)\":\"ZGF0YWJ5dGU=\"," |
| "\"enum--type\":\"WORK\"}}]}}]}", |
| info4.data()); |
| #endif |
| |
| std::string info5; |
| option.single_repeated_to_array = true; |
| ASSERT_TRUE(ProtoMessageToJson(single_repeated_json_data, &info5, option, NULL)); |
| #ifndef RAPIDJSON_VERSION_0_1 |
| ASSERT_STREQ("[{\"name\":\"foo\",\"id\":1,\"json_body\":" |
| "{\"info\":[\"this is json data's info\",\"this is a test\"],\"type\":80000," |
| "\"data:array\":[200,300],\"judge\":true,\"spur\":3.45,\"@Content_Test%@\":" |
| "[{\"uid*\":\"content info\",\"Distance_info_\":1234.56005859375,\"_ext%T_\":" |
| "{\"Aa_ge(\":160000,\"databyte(std::string)\":\"ZGF0YWJ5dGU=\"," |
| "\"enum--type\":\"WORK\"}}]}}]", |
| info5.data()); |
| #else |
| ASSERT_STREQ("[{\"name\":\"foo\",\"id\":1,\"json_body\":" |
| "{\"info\":[\"this is json data's info\",\"this is a test\"],\"type\":80000," |
| "\"data:array\":[200,300],\"judge\":true,\"spur\":3.45,\"@Content_Test%@\":" |
| "[{\"uid*\":\"content info\",\"Distance_info_\":1234.560059,\"_ext%T_\":" |
| "{\"Aa_ge(\":160000,\"databyte(std::string)\":\"ZGF0YWJ5dGU=\"," |
| "\"enum--type\":\"WORK\"}}]}}]", |
| info5.data()); |
| #endif |
| |
| printf("----------test json array to single repeated pb------------\n\n"); |
| |
| std::string info6; |
| AddressBookEncDec data2; |
| // object -> pb |
| json2pb::JsonToProtoMessage(info4, &data2, NULL); |
| json2pb::ProtoMessageToJson(data2, &info6, option, NULL); |
| |
| ASSERT_STREQ(info6.data(), info5.data()); |
| |
| std::string info7; |
| AddressBookEncDec data3; |
| json2pb::Json2PbOptions option2; |
| option2.array_to_single_repeated = true; |
| // array -> pb |
| json2pb::JsonToProtoMessage(info5, &data3, option2, NULL); |
| json2pb::ProtoMessageToJson(data3, &info7, option, NULL); |
| ASSERT_STREQ(info7.data(), info5.data()); |
| |
| std::string info8; |
| option.single_repeated_to_array = false; |
| json2pb::ProtoMessageToJson(data3, &info8, option, NULL); |
| ASSERT_STREQ(info8.data(), info4.data()); |
| } |
| |
| TEST_F(ProtobufJsonTest, pb_to_json_control_char_case) { |
| AddressBook address_book; |
| |
| Person* person = address_book.add_person(); |
| |
| person->set_id(100); |
| char ch = 0x01; |
| char* name = new char[17]; |
| memcpy(name, "baidu ", 6); |
| name[6] = ch; |
| char c = 0x08; |
| char t = 0x1A; |
| memcpy(name + 7, "test", 4); |
| name[11] = c; |
| name[12] = t; |
| memcpy(name + 13, "end", 3); |
| name[16] = '\0'; |
| person->set_name(name); |
| printf("name is %s\n", name); |
| person->set_email("welcome@baidu.com"); |
| |
| Person::PhoneNumber* phone_number = person->add_phone(); |
| phone_number->set_number("number123"); |
| phone_number->set_type(Person::HOME); |
| |
| person->set_data(-240000000); |
| person->set_data32(6); |
| person->set_data64(-1820000000); |
| person->set_datadouble(123.456); |
| person->set_datadouble_scientific(1.23456789e+08); |
| person->set_datafloat_scientific(1.23456789e+08); |
| person->set_datafloat(8.6123); |
| person->set_datau32(60); |
| person->set_datau64(960); |
| person->set_databool(0); |
| person->set_databyte("welcome to china"); |
| person->set_datafix32(1); |
| person->set_datafix64(666); |
| person->set_datasfix32(120); |
| person->set_datasfix64(-802); |
| |
| std::string info1; |
| |
| google::protobuf::TextFormat::Printer printer; |
| std::string text; |
| printer.PrintToString(*person, &text); |
| |
| printf("text:%s\n", text.data()); |
| |
| bool ret = false; |
| printf("----------test pb to json------------\n\n"); |
| { |
| json2pb::Pb2JsonOptions option; |
| option.bytes_to_base64 = false; |
| ret = ProtoMessageToJson(address_book, &info1, option, NULL); |
| ASSERT_TRUE(ret); |
| } |
| |
| #ifndef RAPIDJSON_VERSION_0_1 |
| ASSERT_STREQ("{\"person\":[{\"name\":\"baidu \\u0001test\\b\\u001Aend\",\"id\":100,\"email\":" |
| "\"welcome@baidu.com\"," |
| "\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000," |
| "\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456," |
| "\"datafloat\":8.612299919128418,\"datau32\":60,\"datau64\":960," |
| "\"databool\":false,\"databyte\":\"welcome to china\",\"datafix32\":1," |
| "\"datafix64\":666,\"datasfix32\":120,\"datasfix64\":-802," |
| "\"datafloat_scientific\":123456792.0,\"datadouble_scientific\":123456789.0}]}", |
| info1.data()); |
| #else |
| ASSERT_STREQ("{\"person\":[{\"name\":\"baidu \\u0001test\\b\\u001Aend\",\"id\":100,\"email\":" |
| "\"welcome@baidu.com\"," |
| "\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000," |
| "\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456," |
| "\"datafloat\":8.612299919,\"datau32\":60,\"datau64\":960,\"databool\":false," |
| "\"databyte\":\"welcome to china\",\"datafix32\":1,\"datafix64\":666," |
| "\"datasfix32\":120,\"datasfix64\":-802,\"datafloat_scientific\":123456792," |
| "\"datadouble_scientific\":123456789}]}", info1.data()); |
| #endif |
| |
| info1.clear(); |
| { |
| json2pb::Pb2JsonOptions option; |
| option.bytes_to_base64 = true; |
| ret = ProtoMessageToJson(address_book, &info1, option, NULL); |
| ASSERT_TRUE(ret); |
| } |
| |
| #ifndef RAPIDJSON_VERSION_0_1 |
| ASSERT_STREQ("{\"person\":[{\"name\":\"baidu \\u0001test\\b\\u001Aend\",\"id\":100,\"email\":" |
| "\"welcome@baidu.com\"," |
| "\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000," |
| "\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456," |
| "\"datafloat\":8.612299919128418,\"datau32\":60,\"datau64\":960," |
| "\"databool\":false,\"databyte\":\"d2VsY29tZSB0byBjaGluYQ==\",\"datafix32\":1," |
| "\"datafix64\":666,\"datasfix32\":120,\"datasfix64\":-802," |
| "\"datafloat_scientific\":123456792.0,\"datadouble_scientific\":123456789.0}]}", |
| info1.data()); |
| #else |
| ASSERT_STREQ("{\"person\":[{\"name\":\"baidu \\u0001test\\b\\u001Aend\",\"id\":100,\"email\":" |
| "\"welcome@baidu.com\"," |
| "\"phone\":[{\"number\":\"number123\",\"type\":\"HOME\"}],\"data\":-240000000," |
| "\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456," |
| "\"datafloat\":8.612299919,\"datau32\":60,\"datau64\":960,\"databool\":false," |
| "\"databyte\":\"d2VsY29tZSB0byBjaGluYQ==\",\"datafix32\":1,\"datafix64\":666," |
| "\"datasfix32\":120,\"datasfix64\":-802,\"datafloat_scientific\":123456792," |
| "\"datadouble_scientific\":123456789}]}", info1.data()); |
| #endif |
| |
| info1.clear(); |
| { |
| json2pb::Pb2JsonOptions option; |
| option.enum_option = json2pb::OUTPUT_ENUM_BY_NUMBER; |
| option.bytes_to_base64 = false; |
| ret = ProtoMessageToJson(address_book, &info1, option, NULL); |
| ASSERT_TRUE(ret); |
| } |
| |
| #ifndef RAPIDJSON_VERSION_0_1 |
| ASSERT_STREQ("{\"person\":[{\"name\":\"baidu \\u0001test\\b\\u001Aend\",\"id\":100,\"email\":" |
| "\"welcome@baidu.com\"," |
| "\"phone\":[{\"number\":\"number123\",\"type\":1}],\"data\":-240000000," |
| "\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456," |
| "\"datafloat\":8.612299919128418,\"datau32\":60,\"datau64\":960," |
| "\"databool\":false,\"databyte\":\"welcome to china\",\"datafix32\":1," |
| "\"datafix64\":666,\"datasfix32\":120,\"datasfix64\":-802," |
| "\"datafloat_scientific\":123456792.0,\"datadouble_scientific\":123456789.0}]}", |
| info1.data()); |
| #else |
| std::cout << info1.data() << std::endl; |
| ASSERT_STREQ("{\"person\":[{\"name\":\"baidu \\u0001test\\b\\u001Aend\",\"id\":100,\"email\":" |
| "\"welcome@baidu.com\"," |
| "\"phone\":[{\"number\":\"number123\",\"type\":1}],\"data\":-240000000," |
| "\"data32\":6,\"data64\":-1820000000,\"datadouble\":123.456," |
| "\"datafloat\":8.612299919,\"datau32\":60,\"datau64\":960," |
| "\"databool\":false,\"databyte\":\"welcome to china\",\"datafix32\":1," |
| "\"datafix64\":666,\"datasfix32\":120,\"datasfix64\":-802," |
| "\"datafloat_scientific\":123456792,\"datadouble_scientific\":123456789}]}", |
| info1.data()); |
| #endif |
| } |
| |
| TEST_F(ProtobufJsonTest, pb_to_json_unicode_case) { |
| AddressBook address_book; |
| |
| Person* person = address_book.add_person(); |
| |
| person->set_id(100); |
| |
| char name[255*1024]; |
| for (int j = 0; j < 1024; j++) { |
| for (int i = 0; i < 255; i++) { |
| name[j*255 + i] = i + 1; |
| } |
| } |
| name[255*1024 - 1] = '\0'; |
| person->set_name(name); |
| person->set_data(-240000000); |
| person->set_data32(6); |
| person->set_data64(-1820000000); |
| person->set_datadouble(123.456); |
| person->set_datadouble_scientific(1.23456789e+08); |
| person->set_datafloat_scientific(1.23456789e+08); |
| person->set_datafloat(8.6123); |
| person->set_datau32(60); |
| person->set_datau64(960); |
| person->set_databool(0); |
| person->set_databyte("welcome to china"); |
| person->set_datafix32(1); |
| person->set_datafix64(666); |
| person->set_datasfix32(120); |
| person->set_datasfix64(-802); |
| |
| std::string info1; |
| std::string error; |
| |
| google::protobuf::TextFormat::Printer printer; |
| std::string text; |
| printer.PrintToString(*person, &text); |
| |
| printf("----------test pb to json------------\n\n"); |
| bool ret = json2pb::ProtoMessageToJson(address_book, &info1, &error); |
| ASSERT_TRUE(ret); |
| butil::IOBuf buf; |
| butil::IOBufAsZeroCopyOutputStream stream(&buf); |
| bool res = json2pb::ProtoMessageToJson(address_book, &stream, NULL); |
| ASSERT_TRUE(res); |
| ASSERT_TRUE(!info1.compare(buf.to_string())); |
| } |
| |
| TEST_F(ProtobufJsonTest, pb_to_json_edge_case) { |
| AddressBook address_book; |
| |
| std::string info1; |
| std::string error; |
| bool ret = json2pb::ProtoMessageToJson(address_book, &info1, &error); |
| ASSERT_TRUE(ret); |
| |
| info1.clear(); |
| Person* person = address_book.add_person(); |
| |
| person->set_id(100); |
| person->set_name("baidu"); |
| |
| Person::PhoneNumber* phone_number = person->add_phone(); |
| phone_number->set_number("1234556"); |
| |
| person->set_datadouble(-345.67); |
| person->set_datafloat(8.6123); |
| |
| ret = json2pb::ProtoMessageToJson(address_book, &info1, &error); |
| |
| ASSERT_TRUE(ret); |
| ASSERT_TRUE(error.empty()); |
| |
| std::string info3; |
| AddressBook data1; |
| std::string error1; |
| bool ret1 = json2pb::JsonToProtoMessage(info1, &data1, &error1); |
| ASSERT_TRUE(ret1); |
| ASSERT_TRUE(error1.empty()); |
| |
| std::string error2; |
| bool ret2 = json2pb::ProtoMessageToJson(data1, &info3, &error2); |
| ASSERT_TRUE(ret2); |
| ASSERT_TRUE(error2.empty()); |
| } |
| |
| TEST_F(ProtobufJsonTest, pb_to_json_expected_failed_case) { |
| AddressBook address_book; |
| std::string info1; |
| std::string error; |
| |
| Person* person = address_book.add_person(); |
| |
| person->set_name("baidu"); |
| person->set_email("welcome@baidu.com"); |
| |
| bool ret = json2pb::ProtoMessageToJson(address_book, &info1, &error); |
| ASSERT_FALSE(ret); |
| ASSERT_STREQ("Missing required field: addressbook.Person.id", error.data()); |
| |
| address_book.clear_person(); |
| person = address_book.add_person(); |
| |
| person->set_id(2); |
| person->set_email("welcome@baidu.com"); |
| |
| ret = json2pb::ProtoMessageToJson(address_book, &info1, &error); |
| ASSERT_FALSE(ret); |
| ASSERT_STREQ("Missing required field: addressbook.Person.name", error.data()); |
| |
| address_book.clear_person(); |
| person = address_book.add_person(); |
| |
| person->set_id(2); |
| person->set_name("name"); |
| person->set_email("welcome@baidu.com"); |
| |
| ret = json2pb::ProtoMessageToJson(address_book, &info1, &error); |
| ASSERT_FALSE(ret); |
| ASSERT_STREQ("Missing required field: addressbook.Person.datadouble", error.data()); |
| } |
| |
| TEST_F(ProtobufJsonTest, pb_to_json_perf_case) { |
| AddressBook address_book; |
| |
| Person* person = address_book.add_person(); |
| |
| person->set_id(100); |
| person->set_name("baidu"); |
| person->set_email("welcome@baidu.com"); |
| |
| Person::PhoneNumber* phone_number = person->add_phone(); |
| phone_number->set_number("number123"); |
| phone_number->set_type(Person::HOME); |
| |
| person->set_data(-240000000); |
| |
| person->set_data32(6); |
| |
| person->set_data64(-1820000000); |
| |
| person->set_datadouble(123.456); |
| |
| person->set_datadouble_scientific(1.23456789e+08); |
| |
| person->set_datafloat_scientific(1.23456789e+08); |
| |
| person->set_datafloat(8.6123); |
| |
| person->set_datau32(60); |
| |
| person->set_datau64(960); |
| |
| person->set_databool(0); |
| |
| person->set_databyte("welcome to china"); |
| |
| person->set_datafix32(1); |
| |
| person->set_datafix64(666); |
| |
| person->set_datasfix32(120); |
| |
| person->set_datasfix64(-802); |
| |
| std::string info1; |
| |
| google::protobuf::TextFormat::Printer printer; |
| std::string text; |
| printer.PrintToString(*person, &text); |
| |
| printf("text:%s\n", text.data()); |
| |
| printf("----------test pb to json performance------------\n\n"); |
| ProfilerStart("pb_to_json_perf.prof"); |
| butil::Timer timer; |
| bool res; |
| float avg_time1 = 0; |
| float avg_time2 = 0; |
| const int times = 100000; |
| ASSERT_TRUE(json2pb::ProtoMessageToJson(address_book, &info1, NULL)); |
| for (int i = 0; i < times; i++) { |
| std::string info3; |
| AddressBook data1; |
| timer.start(); |
| res = json2pb::JsonToProtoMessage(info1, &data1, NULL); |
| timer.stop(); |
| avg_time1 += timer.u_elapsed(); |
| ASSERT_TRUE(res); |
| |
| timer.start(); |
| res = json2pb::ProtoMessageToJson(data1, &info3, NULL); |
| timer.stop(); |
| avg_time2 += timer.u_elapsed(); |
| ASSERT_TRUE(res); |
| } |
| avg_time1 /= times; |
| avg_time2 /= times; |
| ProfilerStop(); |
| printf("avg time to convert json to pb is %fus\n", avg_time1); |
| printf("avg time to convert pb to json is %fus\n", avg_time2); |
| } |
| |
| TEST_F(ProtobufJsonTest, pb_to_json_encode_decode_perf_case) { |
| JsonContextBodyEncDec json_data; |
| json_data.set_type(80000); |
| json_data.add_data_z058_array(200); |
| json_data.add_data_z058_array(300); |
| json_data.add_info("this is json data's info"); |
| json_data.add_info("this is a test"); |
| json_data.set_judge(true); |
| json_data.set_spur(3.45); |
| |
| ContentEncDec * content = json_data.add__z064_content_test_z037__z064_(); |
| content->set_uid_z042_("content info"); |
| content->set_distance_info_(1234.56); |
| |
| ExtEncDec* ext = content->mutable__ext_z037_t_(); |
| ext->set_aa_ge_z040_(160000); |
| ext->set_databyte_z040_std_z058__z058_string_z041_("databyte"); |
| ext->set_enum_z045__z045_type(ExtEncDec_PhoneTypeEncDec_WORK); |
| |
| std::string info1; |
| |
| google::protobuf::TextFormat::Printer printer; |
| std::string text; |
| printer.PrintToString(json_data, &text); |
| |
| printf("text:%s\n", text.data()); |
| |
| ASSERT_TRUE(json2pb::ProtoMessageToJson(json_data, &info1, NULL)); |
| |
| printf("----------test pb to json encode decode performance------------\n\n"); |
| ProfilerStart("pb_to_json_encode_decode_perf.prof"); |
| butil::Timer timer; |
| bool res; |
| float avg_time1 = 0; |
| float avg_time2 = 0; |
| const int times = 100000; |
| for (int i = 0; i < times; i++) { |
| std::string info3; |
| JsonContextBody json_body; |
| timer.start(); |
| res = json2pb::JsonToProtoMessage(info1, &json_body, NULL); |
| timer.stop(); |
| avg_time1 += timer.u_elapsed(); |
| ASSERT_TRUE(res); |
| |
| timer.start(); |
| res = json2pb::ProtoMessageToJson(json_body, &info3, NULL); |
| timer.stop(); |
| avg_time2 += timer.u_elapsed(); |
| ASSERT_TRUE(res); |
| } |
| avg_time1 /= times; |
| avg_time2 /= times; |
| ProfilerStop(); |
| printf("avg time to convert json to pb is %fus\n", avg_time1); |
| printf("avg time to convert pb to json is %fus\n", avg_time2); |
| } |
| |
| TEST_F(ProtobufJsonTest, pb_to_json_complex_perf_case) { |
| |
| std::ifstream in("jsonout", std::ios::in); |
| std::ostringstream tmp; |
| tmp << in.rdbuf(); |
| std::string info3 = tmp.str(); |
| in.close(); |
| |
| printf("----------test pb to json performance------------\n\n"); |
| |
| std::string error; |
| |
| butil::Timer timer; |
| bool res; |
| float avg_time2 = 0; |
| const int times = 10000; |
| gss::message::gss_us_res_t data; |
| json2pb::Json2PbOptions option; |
| option.base64_to_bytes = false; |
| res = JsonToProtoMessage(info3, &data, option, &error); |
| ASSERT_TRUE(res) << error; |
| ProfilerStart("pb_to_json_complex_perf.prof"); |
| for (int i = 0; i < times; i++) { |
| std::string error1; |
| timer.start(); |
| butil::IOBuf buf; |
| butil::IOBufAsZeroCopyOutputStream stream(&buf); |
| res = json2pb::ProtoMessageToJson(data, &stream, &error1); |
| timer.stop(); |
| avg_time2 += timer.u_elapsed(); |
| ASSERT_TRUE(res); |
| } |
| avg_time2 /= times; |
| ProfilerStop(); |
| printf("avg time to convert pb to json is %fus\n", avg_time2); |
| } |
| |
| TEST_F(ProtobufJsonTest, pb_to_json_to_string_complex_perf_case) { |
| std::ifstream in("jsonout", std::ios::in); |
| std::ostringstream tmp; |
| tmp << in.rdbuf(); |
| std::string info3 = tmp.str(); |
| in.close(); |
| |
| printf("----------test pb to json performance------------\n\n"); |
| |
| std::string error; |
| |
| butil::Timer timer; |
| bool res; |
| float avg_time2 = 0; |
| const int times = 10000; |
| gss::message::gss_us_res_t data; |
| json2pb::Json2PbOptions option; |
| option.base64_to_bytes = false; |
| res = JsonToProtoMessage(info3, &data, option, &error); |
| ASSERT_TRUE(res); |
| ProfilerStart("pb_to_json_to_string_complex_perf.prof"); |
| for (int i = 0; i < times; i++) { |
| std::string info4; |
| std::string error1; |
| timer.start(); |
| std::string inf4; |
| res = json2pb::ProtoMessageToJson(data, &info4, &error1); |
| timer.stop(); |
| avg_time2 += timer.u_elapsed(); |
| ASSERT_TRUE(res); |
| } |
| avg_time2 /= times; |
| ProfilerStop(); |
| printf("avg time to convert pb to json is %fus\n", avg_time2); |
| } |
| |
| TEST_F(ProtobufJsonTest, encode_decode_case) { |
| |
| std::string json_key = "abcdek123lske_slkejfl_l1kdle"; |
| std::string field_name; |
| ASSERT_FALSE(json2pb::encode_name(json_key, field_name)); |
| ASSERT_TRUE(field_name.empty()); |
| std::string json_key_decode; |
| ASSERT_FALSE(json2pb::decode_name(field_name, json_key_decode)); |
| ASSERT_TRUE(json_key_decode.empty()); |
| |
| json_key = "_Afledk2e*_+%leGi___hE_Z278_t#"; |
| field_name.clear(); |
| json2pb::encode_name(json_key, field_name); |
| const char* encode_json_key = "_Afledk2e_Z042___Z043__Z037_leGi___hE_Z278_t_Z035_"; |
| ASSERT_TRUE(strcmp(field_name.data(), encode_json_key) == 0); |
| json_key_decode.clear(); |
| json2pb::decode_name(field_name, json_key_decode); |
| ASSERT_TRUE(strcmp(json_key_decode.data(), json_key.data()) == 0); |
| |
| json_key = "_ext%T_"; |
| field_name.clear(); |
| json2pb::encode_name(json_key, field_name); |
| encode_json_key = "_ext_Z037_T_"; |
| ASSERT_TRUE(strcmp(field_name.data(), encode_json_key) == 0); |
| json_key_decode.clear(); |
| json2pb::decode_name(field_name, json_key_decode); |
| ASSERT_TRUE(strcmp(json_key_decode.data(), json_key.data()) == 0); |
| |
| std::string empty_key; |
| std::string empty_result; |
| ASSERT_FALSE(json2pb::encode_name(empty_key, empty_result)); |
| ASSERT_TRUE(empty_result.empty() == true); |
| ASSERT_FALSE(json2pb::decode_name(empty_result, empty_key)); |
| ASSERT_TRUE(empty_key.empty() == true); |
| } |
| |
| TEST_F(ProtobufJsonTest, json_to_zero_copy_stream_normal_case) { |
| Person person; |
| person.set_name("hello"); |
| person.set_id(9); |
| person.set_datadouble(2.2); |
| person.set_datafloat(1); |
| butil::IOBuf iobuf; |
| butil::IOBufAsZeroCopyOutputStream wrapper(&iobuf); |
| std::string error; |
| ASSERT_TRUE(json2pb::ProtoMessageToJson(person, &wrapper, &error)) << error; |
| std::string out = iobuf.to_string(); |
| ASSERT_EQ("{\"name\":\"hello\",\"id\":9,\"datadouble\":2.2,\"datafloat\":1.0}", out); |
| } |
| |
| TEST_F(ProtobufJsonTest, zero_copy_stream_to_json_normal_case) { |
| butil::IOBuf iobuf; |
| iobuf = "{\"name\":\"hello\",\"id\":9,\"datadouble\":2.2,\"datafloat\":1.0}"; |
| butil::IOBufAsZeroCopyInputStream wrapper(iobuf); |
| Person person; |
| ASSERT_TRUE(json2pb::JsonToProtoMessage(&wrapper, &person)); |
| ASSERT_STREQ("hello", person.name().c_str()); |
| ASSERT_EQ(9, person.id()); |
| ASSERT_EQ(2.2, person.datadouble()); |
| ASSERT_EQ(1, person.datafloat()); |
| } |
| |
| TEST_F(ProtobufJsonTest, extension_case) { |
| std::string json = "{\"name\":\"hello\",\"id\":9,\"datadouble\":2.2,\"datafloat\":1.0,\"hobby\":\"coding\"}"; |
| Person person; |
| ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &person)); |
| ASSERT_STREQ("coding", person.GetExtension(addressbook::hobby).data()); |
| std::string output; |
| ASSERT_TRUE(json2pb::ProtoMessageToJson(person, &output)); |
| ASSERT_EQ("{\"hobby\":\"coding\",\"name\":\"hello\",\"id\":9,\"datadouble\":2.2,\"datafloat\":1.0}", output); |
| } |
| |
| TEST_F(ProtobufJsonTest, string_to_int64) { |
| auto json = R"({"name":"hello", "id":9, "data": "123456", "datadouble":2.2, "datafloat":1.0})"; |
| Person person; |
| std::string err; |
| ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &person, &err)) << err; |
| ASSERT_EQ(person.data(), 123456); |
| json = R"({"name":"hello", "id":9, "data": 1234567, "datadouble":2.2, "datafloat":1.0})"; |
| ASSERT_TRUE(json2pb::JsonToProtoMessage(json, &person)); |
| ASSERT_EQ(person.data(), 1234567); |
| } |
| |
| TEST_F(ProtobufJsonTest, parse_multiple_json) { |
| const int COUNT = 4; |
| std::vector<std::string> expectedNames = { "tom", "bob", "jerry", "lucy" }; |
| std::vector<int> expectedIds = { 33, 12, 2432, 435 }; |
| std::vector<double> expectedData = { 1.0, 2.0, 3.0, 4.0 }; |
| std::string jsonStr; |
| butil::IOBuf jsonBuf; |
| for (int i = 0; i < COUNT; ++i) { |
| const std::string d = |
| butil::string_printf(R"( { "name":"%s", "id":%d, "datadouble":%f } )", |
| expectedNames[i].c_str(), |
| expectedIds[i], |
| expectedData[i]); |
| jsonStr.append(d); |
| jsonBuf.append(d); |
| } |
| |
| Person req; |
| json2pb::Json2PbOptions copt; |
| copt.allow_remaining_bytes_after_parsing = true; |
| std::string err; |
| |
| for (int i = 0; true; ++i) { |
| req.Clear(); |
| size_t offset; |
| if (json2pb::JsonToProtoMessage(jsonStr, &req, copt, &err, &offset)) { |
| jsonStr = jsonStr.substr(offset); |
| ASSERT_EQ(expectedNames[i], req.name()); |
| ASSERT_EQ(expectedIds[i], req.id()); |
| ASSERT_EQ(expectedData[i], req.datadouble()); |
| |
| std::cout << "parsed=" << req.ShortDebugString() << " after_offset=" << jsonStr << std::endl; |
| } else { |
| if (err.empty()) { |
| // document is empty |
| break; |
| } |
| std::cerr << "error=" << err << " offset=" << offset << std::endl; |
| ASSERT_FALSE(true); |
| } |
| } |
| |
| butil::IOBufAsZeroCopyInputStream stream(jsonBuf); |
| json2pb::ZeroCopyStreamReader reader(&stream); |
| |
| for (int i = 0; true; ++i) { |
| req.Clear(); |
| size_t offset; |
| auto res = json2pb::JsonToProtoMessage(&reader, &req, copt, &err, &offset); |
| if (res) { |
| ASSERT_EQ(expectedNames[i], req.name()); |
| ASSERT_EQ(expectedIds[i], req.id()); |
| ASSERT_EQ(expectedData[i], req.datadouble()); |
| std::string afterOffset; |
| jsonBuf.copy_to(&afterOffset, (size_t)-1L, offset); |
| std::cout << "parsed=" << req.ShortDebugString() << " after_offset=" << afterOffset << std::endl; |
| } else { |
| if (err.empty()) { |
| // document is empty |
| break; |
| } |
| std::cerr << "error=" << err << " offset=" << offset << std::endl; |
| ASSERT_FALSE(true) << i; |
| } |
| } |
| } |
| |
| TEST_F(ProtobufJsonTest, parse_multiple_json_error) { |
| std::string jsonStr = R"( { "name":"tom", "id":323, "datadouble":3.2 } abc )"; |
| butil::IOBuf jsonBuf; |
| jsonBuf.append(jsonStr); |
| |
| Person req; |
| json2pb::Json2PbOptions copt; |
| copt.allow_remaining_bytes_after_parsing = true; |
| std::string err; |
| size_t offset; |
| |
| ASSERT_TRUE(json2pb::JsonToProtoMessage(jsonStr, &req, copt, &err, &offset)); |
| jsonStr = jsonStr.substr(offset); |
| ASSERT_STREQ("tom", req.name().c_str()); |
| ASSERT_EQ(323, req.id()); |
| ASSERT_EQ(3.2, req.datadouble()); |
| |
| req.Clear(); |
| ASSERT_FALSE(json2pb::JsonToProtoMessage(jsonStr, &req, copt, &err, &offset)); |
| ASSERT_STREQ("Invalid json: Invalid value. [Person]", err.c_str()); |
| ASSERT_EQ(2ul, offset); |
| |
| butil::IOBufAsZeroCopyInputStream stream(jsonBuf); |
| json2pb::ZeroCopyStreamReader reader(&stream); |
| req.Clear(); |
| ASSERT_TRUE(json2pb::JsonToProtoMessage(&reader, &req, copt, &err, &offset)); |
| ASSERT_STREQ("tom", req.name().c_str()); |
| ASSERT_EQ(323, req.id()); |
| ASSERT_EQ(3.2, req.datadouble()); |
| |
| req.Clear(); |
| ASSERT_FALSE(json2pb::JsonToProtoMessage(&reader, &req, copt, &err, &offset)); |
| ASSERT_STREQ("Invalid json: Invalid value. [Person]", err.c_str()); |
| ASSERT_EQ(47ul, offset); |
| } |
| |
| } // namespace |