PageRenderTime 106ms CodeModel.GetById 27ms RepoModel.GetById 2ms app.codeStats 0ms

/src/google/protobuf/util/json_util_test.cc

https://gitlab.com/github-cloud-corporation/protobuf
C++ | 354 lines | 267 code | 34 blank | 53 comment | 13 complexity | 4df53b9258564db9b6ac9bc20a673b67 MD5 | raw file
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. #include <google/protobuf/util/json_util.h>
  31. #include <list>
  32. #include <string>
  33. #include <google/protobuf/io/zero_copy_stream.h>
  34. #include <google/protobuf/descriptor_database.h>
  35. #include <google/protobuf/dynamic_message.h>
  36. #include <google/protobuf/util/json_format_proto3.pb.h>
  37. #include <google/protobuf/util/type_resolver.h>
  38. #include <google/protobuf/util/type_resolver_util.h>
  39. #include <gtest/gtest.h>
  40. namespace google {
  41. namespace protobuf {
  42. namespace util {
  43. namespace {
  44. using proto3::FOO;
  45. using proto3::BAR;
  46. using proto3::TestMessage;
  47. using proto3::TestMap;
  48. static const char kTypeUrlPrefix[] = "type.googleapis.com";
  49. static string GetTypeUrl(const Descriptor* message) {
  50. return string(kTypeUrlPrefix) + "/" + message->full_name();
  51. }
  52. // As functions defined in json_util.h are just thin wrappers around the
  53. // JSON conversion code in //net/proto2/util/converter, in this test we
  54. // only cover some very basic cases to make sure the wrappers have forwarded
  55. // parameters to the underlying implementation correctly. More detailed
  56. // tests are contained in the //net/proto2/util/converter directory.
  57. class JsonUtilTest : public testing::Test {
  58. protected:
  59. JsonUtilTest() {
  60. }
  61. string ToJson(const Message& message, const JsonPrintOptions& options) {
  62. string result;
  63. GOOGLE_CHECK_OK(MessageToJsonString(message, &result, options));
  64. return result;
  65. }
  66. bool FromJson(const string& json, Message* message,
  67. const JsonParseOptions& options) {
  68. return JsonStringToMessage(json, message, options).ok();
  69. }
  70. bool FromJson(const string& json, Message* message) {
  71. return FromJson(json, message, JsonParseOptions());
  72. }
  73. google::protobuf::scoped_ptr<TypeResolver> resolver_;
  74. };
  75. TEST_F(JsonUtilTest, TestWhitespaces) {
  76. TestMessage m;
  77. m.mutable_message_value();
  78. JsonPrintOptions options;
  79. EXPECT_EQ("{\"messageValue\":{}}", ToJson(m, options));
  80. options.add_whitespace = true;
  81. EXPECT_EQ(
  82. "{\n"
  83. " \"messageValue\": {}\n"
  84. "}\n",
  85. ToJson(m, options));
  86. }
  87. TEST_F(JsonUtilTest, TestDefaultValues) {
  88. TestMessage m;
  89. JsonPrintOptions options;
  90. EXPECT_EQ("{}", ToJson(m, options));
  91. options.always_print_primitive_fields = true;
  92. EXPECT_EQ(
  93. "{\"boolValue\":false,"
  94. "\"int32Value\":0,"
  95. "\"int64Value\":\"0\","
  96. "\"uint32Value\":0,"
  97. "\"uint64Value\":\"0\","
  98. "\"floatValue\":0,"
  99. "\"doubleValue\":0,"
  100. "\"stringValue\":\"\","
  101. "\"bytesValue\":\"\","
  102. "\"enumValue\":\"FOO\","
  103. "\"repeatedBoolValue\":[],"
  104. "\"repeatedInt32Value\":[],"
  105. "\"repeatedInt64Value\":[],"
  106. "\"repeatedUint32Value\":[],"
  107. "\"repeatedUint64Value\":[],"
  108. "\"repeatedFloatValue\":[],"
  109. "\"repeatedDoubleValue\":[],"
  110. "\"repeatedStringValue\":[],"
  111. "\"repeatedBytesValue\":[],"
  112. "\"repeatedEnumValue\":[],"
  113. "\"repeatedMessageValue\":[]"
  114. "}",
  115. ToJson(m, options));
  116. }
  117. TEST_F(JsonUtilTest, ParseMessage) {
  118. // Some random message but good enough to verify that the parsing warpper
  119. // functions are working properly.
  120. string input =
  121. "{\n"
  122. " \"int32Value\": 1024,\n"
  123. " \"repeatedInt32Value\": [1, 2],\n"
  124. " \"messageValue\": {\n"
  125. " \"value\": 2048\n"
  126. " },\n"
  127. " \"repeatedMessageValue\": [\n"
  128. " {\"value\": 40}, {\"value\": 96}\n"
  129. " ]\n"
  130. "}\n";
  131. JsonParseOptions options;
  132. TestMessage m;
  133. ASSERT_TRUE(FromJson(input, &m, options));
  134. EXPECT_EQ(1024, m.int32_value());
  135. ASSERT_EQ(2, m.repeated_int32_value_size());
  136. EXPECT_EQ(1, m.repeated_int32_value(0));
  137. EXPECT_EQ(2, m.repeated_int32_value(1));
  138. EXPECT_EQ(2048, m.message_value().value());
  139. ASSERT_EQ(2, m.repeated_message_value_size());
  140. EXPECT_EQ(40, m.repeated_message_value(0).value());
  141. EXPECT_EQ(96, m.repeated_message_value(1).value());
  142. }
  143. TEST_F(JsonUtilTest, ParseMap) {
  144. TestMap message;
  145. (*message.mutable_string_map())["hello"] = 1234;
  146. JsonPrintOptions print_options;
  147. JsonParseOptions parse_options;
  148. EXPECT_EQ("{\"stringMap\":{\"hello\":1234}}", ToJson(message, print_options));
  149. TestMap other;
  150. ASSERT_TRUE(FromJson(ToJson(message, print_options), &other, parse_options));
  151. EXPECT_EQ(message.DebugString(), other.DebugString());
  152. }
  153. TEST_F(JsonUtilTest, TestParseIgnoreUnknownFields) {
  154. TestMessage m;
  155. JsonParseOptions options;
  156. options.ignore_unknown_fields = true;
  157. EXPECT_TRUE(FromJson("{\"unknownName\":0}", &m, options));
  158. }
  159. TEST_F(JsonUtilTest, TestParseErrors) {
  160. TestMessage m;
  161. JsonParseOptions options;
  162. // Parsing should fail if the field name can not be recognized.
  163. EXPECT_FALSE(FromJson("{\"unknownName\":0}", &m, options));
  164. // Parsing should fail if the value is invalid.
  165. EXPECT_FALSE(FromJson("{\"int32Value\":2147483648}", &m, options));
  166. }
  167. TEST_F(JsonUtilTest, TestDynamicMessage) {
  168. // Some random message but good enough to test the wrapper functions.
  169. string input =
  170. "{\n"
  171. " \"int32Value\": 1024,\n"
  172. " \"repeatedInt32Value\": [1, 2],\n"
  173. " \"messageValue\": {\n"
  174. " \"value\": 2048\n"
  175. " },\n"
  176. " \"repeatedMessageValue\": [\n"
  177. " {\"value\": 40}, {\"value\": 96}\n"
  178. " ]\n"
  179. "}\n";
  180. // Create a new DescriptorPool with the same protos as the generated one.
  181. DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
  182. DescriptorPool pool(&database);
  183. // A dynamic version of the test proto.
  184. DynamicMessageFactory factory;
  185. google::protobuf::scoped_ptr<Message> message(factory.GetPrototype(
  186. pool.FindMessageTypeByName("proto3.TestMessage"))->New());
  187. EXPECT_TRUE(FromJson(input, message.get()));
  188. // Convert to generated message for easy inspection.
  189. TestMessage generated;
  190. EXPECT_TRUE(generated.ParseFromString(message->SerializeAsString()));
  191. EXPECT_EQ(1024, generated.int32_value());
  192. ASSERT_EQ(2, generated.repeated_int32_value_size());
  193. EXPECT_EQ(1, generated.repeated_int32_value(0));
  194. EXPECT_EQ(2, generated.repeated_int32_value(1));
  195. EXPECT_EQ(2048, generated.message_value().value());
  196. ASSERT_EQ(2, generated.repeated_message_value_size());
  197. EXPECT_EQ(40, generated.repeated_message_value(0).value());
  198. EXPECT_EQ(96, generated.repeated_message_value(1).value());
  199. JsonOptions options;
  200. EXPECT_EQ(ToJson(generated, options), ToJson(*message, options));
  201. }
  202. typedef pair<char*, int> Segment;
  203. // A ZeroCopyOutputStream that writes to multiple buffers.
  204. class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream {
  205. public:
  206. explicit SegmentedZeroCopyOutputStream(list<Segment> segments)
  207. : segments_(segments), last_segment_(static_cast<char*>(NULL), 0), byte_count_(0) {}
  208. virtual bool Next(void** buffer, int* length) {
  209. if (segments_.empty()) {
  210. return false;
  211. }
  212. last_segment_ = segments_.front();
  213. segments_.pop_front();
  214. *buffer = last_segment_.first;
  215. *length = last_segment_.second;
  216. byte_count_ += *length;
  217. return true;
  218. }
  219. virtual void BackUp(int length) {
  220. GOOGLE_CHECK(length <= last_segment_.second);
  221. segments_.push_front(
  222. Segment(last_segment_.first + last_segment_.second - length, length));
  223. last_segment_ = Segment(last_segment_.first, last_segment_.second - length);
  224. byte_count_ -= length;
  225. }
  226. virtual int64 ByteCount() const { return byte_count_; }
  227. private:
  228. list<Segment> segments_;
  229. Segment last_segment_;
  230. int64 byte_count_;
  231. };
  232. // This test splits the output buffer and also the input data into multiple
  233. // segments and checks that the implementation of ZeroCopyStreamByteSink
  234. // handles all possible cases correctly.
  235. TEST(ZeroCopyStreamByteSinkTest, TestAllInputOutputPatterns) {
  236. static const int kOutputBufferLength = 10;
  237. // An exhaustive test takes too long, skip some combinations to make the test
  238. // run faster.
  239. static const int kSkippedPatternCount = 7;
  240. char buffer[kOutputBufferLength];
  241. for (int split_pattern = 0; split_pattern < (1 << (kOutputBufferLength - 1));
  242. split_pattern += kSkippedPatternCount) {
  243. // Split the buffer into small segments according to the split_pattern.
  244. list<Segment> segments;
  245. int segment_start = 0;
  246. for (int i = 0; i < kOutputBufferLength - 1; ++i) {
  247. if (split_pattern & (1 << i)) {
  248. segments.push_back(
  249. Segment(buffer + segment_start, i - segment_start + 1));
  250. segment_start = i + 1;
  251. }
  252. }
  253. segments.push_back(
  254. Segment(buffer + segment_start, kOutputBufferLength - segment_start));
  255. // Write exactly 10 bytes through the ByteSink.
  256. string input_data = "0123456789";
  257. for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
  258. input_pattern += kSkippedPatternCount) {
  259. memset(buffer, 0, sizeof(buffer));
  260. {
  261. SegmentedZeroCopyOutputStream output_stream(segments);
  262. internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
  263. int start = 0;
  264. for (int j = 0; j < input_data.length() - 1; ++j) {
  265. if (input_pattern & (1 << j)) {
  266. byte_sink.Append(&input_data[start], j - start + 1);
  267. start = j + 1;
  268. }
  269. }
  270. byte_sink.Append(&input_data[start], input_data.length() - start);
  271. }
  272. EXPECT_EQ(input_data, string(buffer, input_data.length()));
  273. }
  274. // Write only 9 bytes through the ByteSink.
  275. input_data = "012345678";
  276. for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
  277. input_pattern += kSkippedPatternCount) {
  278. memset(buffer, 0, sizeof(buffer));
  279. {
  280. SegmentedZeroCopyOutputStream output_stream(segments);
  281. internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
  282. int start = 0;
  283. for (int j = 0; j < input_data.length() - 1; ++j) {
  284. if (input_pattern & (1 << j)) {
  285. byte_sink.Append(&input_data[start], j - start + 1);
  286. start = j + 1;
  287. }
  288. }
  289. byte_sink.Append(&input_data[start], input_data.length() - start);
  290. }
  291. EXPECT_EQ(input_data, string(buffer, input_data.length()));
  292. EXPECT_EQ(0, buffer[input_data.length()]);
  293. }
  294. // Write 11 bytes through the ByteSink. The extra byte will just
  295. // be ignored.
  296. input_data = "0123456789A";
  297. for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
  298. input_pattern += kSkippedPatternCount) {
  299. memset(buffer, 0, sizeof(buffer));
  300. {
  301. SegmentedZeroCopyOutputStream output_stream(segments);
  302. internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
  303. int start = 0;
  304. for (int j = 0; j < input_data.length() - 1; ++j) {
  305. if (input_pattern & (1 << j)) {
  306. byte_sink.Append(&input_data[start], j - start + 1);
  307. start = j + 1;
  308. }
  309. }
  310. byte_sink.Append(&input_data[start], input_data.length() - start);
  311. }
  312. EXPECT_EQ(input_data.substr(0, kOutputBufferLength),
  313. string(buffer, kOutputBufferLength));
  314. }
  315. }
  316. }
  317. } // namespace
  318. } // namespace util
  319. } // namespace protobuf
  320. } // namespace google