blob: 9d8201624dde5d9795d08e5380169a9124f6ae6b [file] [log] [blame]
Feng Xiaoe96ff302015-06-15 18:21:48 -07001// 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
31#include <google/protobuf/util/internal/json_objectwriter.h>
32
33#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
Feng Xiao818c5ee2015-06-15 21:42:57 -070034#include <google/protobuf/util/internal/utility.h>
Feng Xiaoe96ff302015-06-15 18:21:48 -070035#include <gtest/gtest.h>
36
37namespace google {
38namespace protobuf {
39namespace util {
40namespace converter {
41
42using google::protobuf::io::CodedOutputStream;
43using google::protobuf::io::StringOutputStream;
44
45class JsonObjectWriterTest : public ::testing::Test {
46 protected:
47 JsonObjectWriterTest()
48 : str_stream_(new StringOutputStream(&output_)),
49 out_stream_(new CodedOutputStream(str_stream_)),
Feng Xiaoe841bac2015-12-11 17:09:20 -080050 ow_(NULL) {}
Feng Xiaoe96ff302015-06-15 18:21:48 -070051
52 virtual ~JsonObjectWriterTest() {
53 delete ow_;
54 delete out_stream_;
55 delete str_stream_;
56 }
57
58 string output_;
59 StringOutputStream* const str_stream_;
60 CodedOutputStream* const out_stream_;
61 ObjectWriter* ow_;
62};
63
64TEST_F(JsonObjectWriterTest, EmptyRootObject) {
65 ow_ = new JsonObjectWriter("", out_stream_);
Feng Xiaoe841bac2015-12-11 17:09:20 -080066 ow_->StartObject("")->EndObject();
Feng Xiaoe96ff302015-06-15 18:21:48 -070067 EXPECT_EQ("{}", output_.substr(0, out_stream_->ByteCount()));
68}
69
70TEST_F(JsonObjectWriterTest, EmptyObject) {
71 ow_ = new JsonObjectWriter("", out_stream_);
72 ow_->StartObject("")
Feng Xiaoe841bac2015-12-11 17:09:20 -080073 ->RenderString("test", "value")
74 ->StartObject("empty")
75 ->EndObject()
76 ->EndObject();
Feng Xiaoe96ff302015-06-15 18:21:48 -070077 EXPECT_EQ("{\"test\":\"value\",\"empty\":{}}",
78 output_.substr(0, out_stream_->ByteCount()));
79}
80
81TEST_F(JsonObjectWriterTest, EmptyRootList) {
82 ow_ = new JsonObjectWriter("", out_stream_);
Feng Xiaoe841bac2015-12-11 17:09:20 -080083 ow_->StartList("")->EndList();
Feng Xiaoe96ff302015-06-15 18:21:48 -070084 EXPECT_EQ("[]", output_.substr(0, out_stream_->ByteCount()));
85}
86
87TEST_F(JsonObjectWriterTest, EmptyList) {
88 ow_ = new JsonObjectWriter("", out_stream_);
89 ow_->StartObject("")
Feng Xiaoe841bac2015-12-11 17:09:20 -080090 ->RenderString("test", "value")
91 ->StartList("empty")
92 ->EndList()
93 ->EndObject();
Feng Xiaoe96ff302015-06-15 18:21:48 -070094 EXPECT_EQ("{\"test\":\"value\",\"empty\":[]}",
95 output_.substr(0, out_stream_->ByteCount()));
96}
97
98TEST_F(JsonObjectWriterTest, ObjectInObject) {
99 ow_ = new JsonObjectWriter("", out_stream_);
100 ow_->StartObject("")
Feng Xiaoe841bac2015-12-11 17:09:20 -0800101 ->StartObject("nested")
102 ->RenderString("field", "value")
103 ->EndObject()
104 ->EndObject();
Feng Xiaoe96ff302015-06-15 18:21:48 -0700105 EXPECT_EQ("{\"nested\":{\"field\":\"value\"}}",
106 output_.substr(0, out_stream_->ByteCount()));
107}
108
109TEST_F(JsonObjectWriterTest, ListInObject) {
110 ow_ = new JsonObjectWriter("", out_stream_);
111 ow_->StartObject("")
Feng Xiaoe841bac2015-12-11 17:09:20 -0800112 ->StartList("nested")
113 ->RenderString("", "value")
114 ->EndList()
115 ->EndObject();
Feng Xiaoe96ff302015-06-15 18:21:48 -0700116 EXPECT_EQ("{\"nested\":[\"value\"]}",
117 output_.substr(0, out_stream_->ByteCount()));
118}
119
120TEST_F(JsonObjectWriterTest, ObjectInList) {
121 ow_ = new JsonObjectWriter("", out_stream_);
122 ow_->StartList("")
Feng Xiaoe841bac2015-12-11 17:09:20 -0800123 ->StartObject("")
124 ->RenderString("field", "value")
125 ->EndObject()
126 ->EndList();
Feng Xiaoe96ff302015-06-15 18:21:48 -0700127 EXPECT_EQ("[{\"field\":\"value\"}]",
128 output_.substr(0, out_stream_->ByteCount()));
129}
130
131TEST_F(JsonObjectWriterTest, ListInList) {
132 ow_ = new JsonObjectWriter("", out_stream_);
133 ow_->StartList("")
Feng Xiaoe841bac2015-12-11 17:09:20 -0800134 ->StartList("")
135 ->RenderString("", "value")
136 ->EndList()
137 ->EndList();
Feng Xiaoe96ff302015-06-15 18:21:48 -0700138 EXPECT_EQ("[[\"value\"]]", output_.substr(0, out_stream_->ByteCount()));
139}
140
141TEST_F(JsonObjectWriterTest, RenderPrimitives) {
142 ow_ = new JsonObjectWriter("", out_stream_);
143 ow_->StartObject("")
144 ->RenderBool("bool", true)
145 ->RenderDouble("double", std::numeric_limits<double>::max())
146 ->RenderFloat("float", std::numeric_limits<float>::max())
147 ->RenderInt32("int", std::numeric_limits<int32>::min())
148 ->RenderInt64("long", std::numeric_limits<int64>::min())
149 ->RenderBytes("bytes", "abracadabra")
150 ->RenderString("string", "string")
151 ->RenderBytes("emptybytes", "")
152 ->RenderString("emptystring", string())
153 ->EndObject();
154 EXPECT_EQ(
155 "{\"bool\":true,"
Feng Xiaoe841bac2015-12-11 17:09:20 -0800156 "\"double\":" +
157 ValueAsString<double>(std::numeric_limits<double>::max()) +
158 ","
159 "\"float\":" +
160 ValueAsString<float>(std::numeric_limits<float>::max()) +
161 ","
162 "\"int\":-2147483648,"
163 "\"long\":\"-9223372036854775808\","
164 "\"bytes\":\"YWJyYWNhZGFicmE=\","
165 "\"string\":\"string\","
166 "\"emptybytes\":\"\","
167 "\"emptystring\":\"\"}",
Feng Xiaoe96ff302015-06-15 18:21:48 -0700168 output_.substr(0, out_stream_->ByteCount()));
169}
170
Feng Xiaoeee38b02015-08-22 18:25:48 -0700171TEST_F(JsonObjectWriterTest, BytesEncodesAsNonWebSafeBase64) {
Feng Xiaoe96ff302015-06-15 18:21:48 -0700172 string s;
173 s.push_back('\377');
174 s.push_back('\357');
175 ow_ = new JsonObjectWriter("", out_stream_);
176 ow_->StartObject("")->RenderBytes("bytes", s)->EndObject();
177 // Non-web-safe would encode this as "/+8="
Feng Xiaoeee38b02015-08-22 18:25:48 -0700178 EXPECT_EQ("{\"bytes\":\"/+8=\"}",
Feng Xiaoe96ff302015-06-15 18:21:48 -0700179 output_.substr(0, out_stream_->ByteCount()));
180}
181
182TEST_F(JsonObjectWriterTest, PrettyPrintList) {
183 ow_ = new JsonObjectWriter(" ", out_stream_);
184 ow_->StartObject("")
Feng Xiaoe841bac2015-12-11 17:09:20 -0800185 ->StartList("items")
186 ->RenderString("", "item1")
187 ->RenderString("", "item2")
188 ->RenderString("", "item3")
189 ->EndList()
190 ->StartList("empty")
191 ->EndList()
192 ->EndObject();
193 EXPECT_EQ(
194 "{\n"
195 " \"items\": [\n"
196 " \"item1\",\n"
197 " \"item2\",\n"
198 " \"item3\"\n"
199 " ],\n"
200 " \"empty\": []\n"
201 "}\n",
202 output_.substr(0, out_stream_->ByteCount()));
Feng Xiaoe96ff302015-06-15 18:21:48 -0700203}
204
205TEST_F(JsonObjectWriterTest, PrettyPrintObject) {
206 ow_ = new JsonObjectWriter(" ", out_stream_);
207 ow_->StartObject("")
Feng Xiaoe841bac2015-12-11 17:09:20 -0800208 ->StartObject("items")
209 ->RenderString("key1", "item1")
210 ->RenderString("key2", "item2")
211 ->RenderString("key3", "item3")
212 ->EndObject()
213 ->StartObject("empty")
214 ->EndObject()
215 ->EndObject();
216 EXPECT_EQ(
217 "{\n"
218 " \"items\": {\n"
219 " \"key1\": \"item1\",\n"
220 " \"key2\": \"item2\",\n"
221 " \"key3\": \"item3\"\n"
222 " },\n"
223 " \"empty\": {}\n"
224 "}\n",
225 output_.substr(0, out_stream_->ByteCount()));
Feng Xiaoe96ff302015-06-15 18:21:48 -0700226}
227
228TEST_F(JsonObjectWriterTest, PrettyPrintEmptyObjectInEmptyList) {
229 ow_ = new JsonObjectWriter(" ", out_stream_);
230 ow_->StartObject("")
Feng Xiaoe841bac2015-12-11 17:09:20 -0800231 ->StartList("list")
232 ->StartObject("")
233 ->EndObject()
234 ->EndList()
235 ->EndObject();
236 EXPECT_EQ(
237 "{\n"
238 " \"list\": [\n"
239 " {}\n"
240 " ]\n"
241 "}\n",
242 output_.substr(0, out_stream_->ByteCount()));
Feng Xiaoe96ff302015-06-15 18:21:48 -0700243}
244
245TEST_F(JsonObjectWriterTest, PrettyPrintDoubleIndent) {
246 ow_ = new JsonObjectWriter(" ", out_stream_);
247 ow_->StartObject("")
Feng Xiaoe841bac2015-12-11 17:09:20 -0800248 ->RenderBool("bool", true)
249 ->RenderInt32("int", 42)
250 ->EndObject();
251 EXPECT_EQ(
252 "{\n"
253 " \"bool\": true,\n"
254 " \"int\": 42\n"
255 "}\n",
256 output_.substr(0, out_stream_->ByteCount()));
Feng Xiaoe96ff302015-06-15 18:21:48 -0700257}
258
259TEST_F(JsonObjectWriterTest, StringsEscapedAndEnclosedInDoubleQuotes) {
260 ow_ = new JsonObjectWriter("", out_stream_);
Feng Xiaoe841bac2015-12-11 17:09:20 -0800261 ow_->StartObject("")->RenderString("string", "'<>&amp;\\\"\r\n")->EndObject();
Feng Xiaoe96ff302015-06-15 18:21:48 -0700262 EXPECT_EQ("{\"string\":\"'\\u003c\\u003e&amp;\\\\\\\"\\r\\n\"}",
263 output_.substr(0, out_stream_->ByteCount()));
264}
265
266TEST_F(JsonObjectWriterTest, Stringification) {
267 ow_ = new JsonObjectWriter("", out_stream_);
268 ow_->StartObject("")
Feng Xiaoe841bac2015-12-11 17:09:20 -0800269 ->RenderDouble("double_nan", std::numeric_limits<double>::quiet_NaN())
270 ->RenderFloat("float_nan", std::numeric_limits<float>::quiet_NaN())
271 ->RenderDouble("double_pos", std::numeric_limits<double>::infinity())
272 ->RenderFloat("float_pos", std::numeric_limits<float>::infinity())
273 ->RenderDouble("double_neg", -std::numeric_limits<double>::infinity())
274 ->RenderFloat("float_neg", -std::numeric_limits<float>::infinity())
275 ->EndObject();
Feng Xiaoe96ff302015-06-15 18:21:48 -0700276 EXPECT_EQ(
277 "{\"double_nan\":\"NaN\","
278 "\"float_nan\":\"NaN\","
279 "\"double_pos\":\"Infinity\","
280 "\"float_pos\":\"Infinity\","
281 "\"double_neg\":\"-Infinity\","
282 "\"float_neg\":\"-Infinity\"}",
283 output_.substr(0, out_stream_->ByteCount()));
284}
285
286} // namespace converter
287} // namespace util
288} // namespace protobuf
289} // namespace google