OLD | NEW |
(Empty) | |
| 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 |
| 31 #include <google/protobuf/util/internal/json_objectwriter.h> |
| 32 |
| 33 #include <google/protobuf/io/zero_copy_stream_impl_lite.h> |
| 34 #include <google/protobuf/util/internal/utility.h> |
| 35 #include <gtest/gtest.h> |
| 36 |
| 37 namespace google { |
| 38 namespace protobuf { |
| 39 namespace util { |
| 40 namespace converter { |
| 41 |
| 42 using google::protobuf::io::CodedOutputStream; |
| 43 using google::protobuf::io::StringOutputStream; |
| 44 |
| 45 class JsonObjectWriterTest : public ::testing::Test { |
| 46 protected: |
| 47 JsonObjectWriterTest() |
| 48 : str_stream_(new StringOutputStream(&output_)), |
| 49 out_stream_(new CodedOutputStream(str_stream_)), |
| 50 ow_(NULL) {} |
| 51 |
| 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 |
| 64 TEST_F(JsonObjectWriterTest, EmptyRootObject) { |
| 65 ow_ = new JsonObjectWriter("", out_stream_); |
| 66 ow_->StartObject("")->EndObject(); |
| 67 EXPECT_EQ("{}", output_.substr(0, out_stream_->ByteCount())); |
| 68 } |
| 69 |
| 70 TEST_F(JsonObjectWriterTest, EmptyObject) { |
| 71 ow_ = new JsonObjectWriter("", out_stream_); |
| 72 ow_->StartObject("") |
| 73 ->RenderString("test", "value") |
| 74 ->StartObject("empty") |
| 75 ->EndObject() |
| 76 ->EndObject(); |
| 77 EXPECT_EQ("{\"test\":\"value\",\"empty\":{}}", |
| 78 output_.substr(0, out_stream_->ByteCount())); |
| 79 } |
| 80 |
| 81 TEST_F(JsonObjectWriterTest, EmptyRootList) { |
| 82 ow_ = new JsonObjectWriter("", out_stream_); |
| 83 ow_->StartList("")->EndList(); |
| 84 EXPECT_EQ("[]", output_.substr(0, out_stream_->ByteCount())); |
| 85 } |
| 86 |
| 87 TEST_F(JsonObjectWriterTest, EmptyList) { |
| 88 ow_ = new JsonObjectWriter("", out_stream_); |
| 89 ow_->StartObject("") |
| 90 ->RenderString("test", "value") |
| 91 ->StartList("empty") |
| 92 ->EndList() |
| 93 ->EndObject(); |
| 94 EXPECT_EQ("{\"test\":\"value\",\"empty\":[]}", |
| 95 output_.substr(0, out_stream_->ByteCount())); |
| 96 } |
| 97 |
| 98 TEST_F(JsonObjectWriterTest, ObjectInObject) { |
| 99 ow_ = new JsonObjectWriter("", out_stream_); |
| 100 ow_->StartObject("") |
| 101 ->StartObject("nested") |
| 102 ->RenderString("field", "value") |
| 103 ->EndObject() |
| 104 ->EndObject(); |
| 105 EXPECT_EQ("{\"nested\":{\"field\":\"value\"}}", |
| 106 output_.substr(0, out_stream_->ByteCount())); |
| 107 } |
| 108 |
| 109 TEST_F(JsonObjectWriterTest, ListInObject) { |
| 110 ow_ = new JsonObjectWriter("", out_stream_); |
| 111 ow_->StartObject("") |
| 112 ->StartList("nested") |
| 113 ->RenderString("", "value") |
| 114 ->EndList() |
| 115 ->EndObject(); |
| 116 EXPECT_EQ("{\"nested\":[\"value\"]}", |
| 117 output_.substr(0, out_stream_->ByteCount())); |
| 118 } |
| 119 |
| 120 TEST_F(JsonObjectWriterTest, ObjectInList) { |
| 121 ow_ = new JsonObjectWriter("", out_stream_); |
| 122 ow_->StartList("") |
| 123 ->StartObject("") |
| 124 ->RenderString("field", "value") |
| 125 ->EndObject() |
| 126 ->EndList(); |
| 127 EXPECT_EQ("[{\"field\":\"value\"}]", |
| 128 output_.substr(0, out_stream_->ByteCount())); |
| 129 } |
| 130 |
| 131 TEST_F(JsonObjectWriterTest, ListInList) { |
| 132 ow_ = new JsonObjectWriter("", out_stream_); |
| 133 ow_->StartList("") |
| 134 ->StartList("") |
| 135 ->RenderString("", "value") |
| 136 ->EndList() |
| 137 ->EndList(); |
| 138 EXPECT_EQ("[[\"value\"]]", output_.substr(0, out_stream_->ByteCount())); |
| 139 } |
| 140 |
| 141 TEST_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," |
| 156 "\"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\":\"\"}", |
| 168 output_.substr(0, out_stream_->ByteCount())); |
| 169 } |
| 170 |
| 171 TEST_F(JsonObjectWriterTest, BytesEncodesAsNonWebSafeBase64) { |
| 172 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=" |
| 178 EXPECT_EQ("{\"bytes\":\"/+8=\"}", |
| 179 output_.substr(0, out_stream_->ByteCount())); |
| 180 } |
| 181 |
| 182 TEST_F(JsonObjectWriterTest, PrettyPrintList) { |
| 183 ow_ = new JsonObjectWriter(" ", out_stream_); |
| 184 ow_->StartObject("") |
| 185 ->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())); |
| 203 } |
| 204 |
| 205 TEST_F(JsonObjectWriterTest, PrettyPrintObject) { |
| 206 ow_ = new JsonObjectWriter(" ", out_stream_); |
| 207 ow_->StartObject("") |
| 208 ->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())); |
| 226 } |
| 227 |
| 228 TEST_F(JsonObjectWriterTest, PrettyPrintEmptyObjectInEmptyList) { |
| 229 ow_ = new JsonObjectWriter(" ", out_stream_); |
| 230 ow_->StartObject("") |
| 231 ->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())); |
| 243 } |
| 244 |
| 245 TEST_F(JsonObjectWriterTest, PrettyPrintDoubleIndent) { |
| 246 ow_ = new JsonObjectWriter(" ", out_stream_); |
| 247 ow_->StartObject("") |
| 248 ->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())); |
| 257 } |
| 258 |
| 259 TEST_F(JsonObjectWriterTest, StringsEscapedAndEnclosedInDoubleQuotes) { |
| 260 ow_ = new JsonObjectWriter("", out_stream_); |
| 261 ow_->StartObject("")->RenderString("string", "'<>&\\\"\r\n")->EndObject(); |
| 262 EXPECT_EQ("{\"string\":\"'\\u003c\\u003e&\\\\\\\"\\r\\n\"}", |
| 263 output_.substr(0, out_stream_->ByteCount())); |
| 264 } |
| 265 |
| 266 TEST_F(JsonObjectWriterTest, Stringification) { |
| 267 ow_ = new JsonObjectWriter("", out_stream_); |
| 268 ow_->StartObject("") |
| 269 ->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(); |
| 276 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 |
OLD | NEW |