writertest.cpp
Go to the documentation of this file.
1 // Tencent is pleased to support the open source community by making RapidJSON available.
2 //
3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4 //
5 // Licensed under the MIT License (the "License"); you may not use this file except
6 // in compliance with the License. You may obtain a copy of the License at
7 //
8 // http://opensource.org/licenses/MIT
9 //
10 // Unless required by applicable law or agreed to in writing, software distributed
11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 // specific language governing permissions and limitations under the License.
14 
15 #include "unittest.h"
16 
17 #include "rapidjson/document.h"
18 #include "rapidjson/reader.h"
19 #include "rapidjson/writer.h"
20 #include "rapidjson/stringbuffer.h"
21 #include "rapidjson/memorybuffer.h"
22 
23 #ifdef __clang__
24 RAPIDJSON_DIAG_PUSH
25 RAPIDJSON_DIAG_OFF(c++98-compat)
26 #endif
27 
28 using namespace rapidjson;
29 
30 TEST(Writer, Compact) {
31  StringStream s("{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] } ");
32  StringBuffer buffer;
33  Writer<StringBuffer> writer(buffer);
34  buffer.ShrinkToFit();
35  Reader reader;
36  reader.Parse<0>(s, writer);
37  EXPECT_STREQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3]}", buffer.GetString());
38  EXPECT_EQ(77u, buffer.GetSize());
39  EXPECT_TRUE(writer.IsComplete());
40 }
41 
42 // json -> parse -> writer -> json
43 #define TEST_ROUNDTRIP(json) \
44  { \
45  StringStream s(json); \
46  StringBuffer buffer; \
47  Writer<StringBuffer> writer(buffer); \
48  Reader reader; \
49  reader.Parse<kParseFullPrecisionFlag>(s, writer); \
50  EXPECT_STREQ(json, buffer.GetString()); \
51  EXPECT_TRUE(writer.IsComplete()); \
52  }
53 
54 TEST(Writer, Root) {
55  TEST_ROUNDTRIP("null");
56  TEST_ROUNDTRIP("true");
57  TEST_ROUNDTRIP("false");
58  TEST_ROUNDTRIP("0");
59  TEST_ROUNDTRIP("\"foo\"");
60  TEST_ROUNDTRIP("[]");
61  TEST_ROUNDTRIP("{}");
62 }
63 
64 TEST(Writer, Int) {
65  TEST_ROUNDTRIP("[-1]");
66  TEST_ROUNDTRIP("[-123]");
67  TEST_ROUNDTRIP("[-2147483648]");
68 }
69 
70 TEST(Writer, UInt) {
71  TEST_ROUNDTRIP("[0]");
72  TEST_ROUNDTRIP("[1]");
73  TEST_ROUNDTRIP("[123]");
74  TEST_ROUNDTRIP("[2147483647]");
75  TEST_ROUNDTRIP("[4294967295]");
76 }
77 
78 TEST(Writer, Int64) {
79  TEST_ROUNDTRIP("[-1234567890123456789]");
80  TEST_ROUNDTRIP("[-9223372036854775808]");
81 }
82 
83 TEST(Writer, Uint64) {
84  TEST_ROUNDTRIP("[1234567890123456789]");
85  TEST_ROUNDTRIP("[9223372036854775807]");
86 }
87 
88 TEST(Writer, String) {
89  TEST_ROUNDTRIP("[\"Hello\"]");
90  TEST_ROUNDTRIP("[\"Hello\\u0000World\"]");
91  TEST_ROUNDTRIP("[\"\\\"\\\\/\\b\\f\\n\\r\\t\"]");
92 
93 #if RAPIDJSON_HAS_STDSTRING
94  {
95  StringBuffer buffer;
96  Writer<StringBuffer> writer(buffer);
97  writer.String(std::string("Hello\n"));
98  EXPECT_STREQ("\"Hello\\n\"", buffer.GetString());
99  }
100 #endif
101 }
102 
103 TEST(Writer, Issue_889) {
104  char buf[100] = "Hello";
105 
106  StringBuffer buffer;
107  Writer<StringBuffer> writer(buffer);
108  writer.StartArray();
109  writer.String(buf);
110  writer.EndArray();
111 
112  EXPECT_STREQ("[\"Hello\"]", buffer.GetString());
113  EXPECT_TRUE(writer.IsComplete()); \
114 }
115 
116 TEST(Writer, ScanWriteUnescapedString) {
117  const char json[] = "[\" \\\"0123456789ABCDEF\"]";
118  // ^ scanning stops here.
119  char buffer2[sizeof(json) + 32];
120 
121  // Use different offset to test different alignments
122  for (int i = 0; i < 32; i++) {
123  char* p = buffer2 + i;
124  memcpy(p, json, sizeof(json));
125  TEST_ROUNDTRIP(p);
126  }
127 }
128 
129 TEST(Writer, Double) {
130  TEST_ROUNDTRIP("[1.2345,1.2345678,0.123456789012,1234567.8]");
131  TEST_ROUNDTRIP("0.0");
132  TEST_ROUNDTRIP("-0.0"); // Issue #289
133  TEST_ROUNDTRIP("1e30");
134  TEST_ROUNDTRIP("1.0");
135  TEST_ROUNDTRIP("5e-324"); // Min subnormal positive double
136  TEST_ROUNDTRIP("2.225073858507201e-308"); // Max subnormal positive double
137  TEST_ROUNDTRIP("2.2250738585072014e-308"); // Min normal positive double
138  TEST_ROUNDTRIP("1.7976931348623157e308"); // Max double
139 
140 }
141 
142 // UTF8 -> TargetEncoding -> UTF8
143 template <typename TargetEncoding>
144 void TestTranscode(const char* json) {
145  StringStream s(json);
147  Writer<GenericStringBuffer<TargetEncoding>, UTF8<>, TargetEncoding> writer(buffer);
148  Reader reader;
149  reader.Parse(s, writer);
150 
151  StringBuffer buffer2;
152  Writer<StringBuffer> writer2(buffer2);
155  reader2.Parse(s2, writer2);
156 
157  EXPECT_STREQ(json, buffer2.GetString());
158 }
159 
160 TEST(Writer, Transcode) {
161  const char json[] = "{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3],\"dollar\":\"\x24\",\"cents\":\"\xC2\xA2\",\"euro\":\"\xE2\x82\xAC\",\"gclef\":\"\xF0\x9D\x84\x9E\"}";
162 
163  // UTF8 -> UTF16 -> UTF8
164  TestTranscode<UTF8<> >(json);
165 
166  // UTF8 -> ASCII -> UTF8
167  TestTranscode<ASCII<> >(json);
168 
169  // UTF8 -> UTF16 -> UTF8
170  TestTranscode<UTF16<> >(json);
171 
172  // UTF8 -> UTF32 -> UTF8
173  TestTranscode<UTF32<> >(json);
174 
175  // UTF8 -> AutoUTF -> UTF8
176  UTFType types[] = { kUTF8, kUTF16LE , kUTF16BE, kUTF32LE , kUTF32BE };
177  for (size_t i = 0; i < 5; i++) {
178  StringStream s(json);
179  MemoryBuffer buffer;
180  AutoUTFOutputStream<unsigned, MemoryBuffer> os(buffer, types[i], true);
182  Reader reader;
183  reader.Parse(s, writer);
184 
185  StringBuffer buffer2;
186  Writer<StringBuffer> writer2(buffer2);
187  GenericReader<AutoUTF<unsigned>, UTF8<> > reader2;
188  MemoryStream s2(buffer.GetBuffer(), buffer.GetSize());
190  reader2.Parse(is, writer2);
191 
192  EXPECT_STREQ(json, buffer2.GetString());
193  }
194 
195 }
196 
197 #include <sstream>
198 
199 class OStreamWrapper {
200 public:
201  typedef char Ch;
202 
203  OStreamWrapper(std::ostream& os) : os_(os) {}
204 
205  Ch Peek() const { assert(false); return '\0'; }
206  Ch Take() { assert(false); return '\0'; }
207  size_t Tell() const { return 0; }
208 
209  Ch* PutBegin() { assert(false); return 0; }
210  void Put(Ch c) { os_.put(c); }
211  void Flush() { os_.flush(); }
212  size_t PutEnd(Ch*) { assert(false); return 0; }
213 
214 private:
216  OStreamWrapper& operator=(const OStreamWrapper&);
217 
218  std::ostream& os_;
219 };
220 
222  StringStream s("{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3], \"u64\": 1234567890123456789, \"i64\":-1234567890123456789 } ");
223 
224  std::stringstream ss;
225  OStreamWrapper os(ss);
226 
227  Writer<OStreamWrapper> writer(os);
228 
229  Reader reader;
230  reader.Parse<0>(s, writer);
231 
232  std::string actual = ss.str();
233  EXPECT_STREQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3],\"u64\":1234567890123456789,\"i64\":-1234567890123456789}", actual.c_str());
234 }
235 
236 TEST(Writer, AssertRootMayBeAnyValue) {
237 #define T(x)\
238  {\
239  StringBuffer buffer;\
240  Writer<StringBuffer> writer(buffer);\
241  EXPECT_TRUE(x);\
242  }
243  T(writer.Bool(false));
244  T(writer.Bool(true));
245  T(writer.Null());
246  T(writer.Int(0));
247  T(writer.Uint(0));
248  T(writer.Int64(0));
249  T(writer.Uint64(0));
250  T(writer.Double(0));
251  T(writer.String("foo"));
252 #undef T
253 }
254 
255 TEST(Writer, AssertIncorrectObjectLevel) {
256  StringBuffer buffer;
257  Writer<StringBuffer> writer(buffer);
258  writer.StartObject();
259  writer.EndObject();
260  ASSERT_THROW(writer.EndObject(), AssertException);
261 }
262 
263 TEST(Writer, AssertIncorrectArrayLevel) {
264  StringBuffer buffer;
265  Writer<StringBuffer> writer(buffer);
266  writer.StartArray();
267  writer.EndArray();
268  ASSERT_THROW(writer.EndArray(), AssertException);
269 }
270 
271 TEST(Writer, AssertIncorrectEndObject) {
272  StringBuffer buffer;
273  Writer<StringBuffer> writer(buffer);
274  writer.StartObject();
275  ASSERT_THROW(writer.EndArray(), AssertException);
276 }
277 
278 TEST(Writer, AssertIncorrectEndArray) {
279  StringBuffer buffer;
280  Writer<StringBuffer> writer(buffer);
281  writer.StartObject();
282  ASSERT_THROW(writer.EndArray(), AssertException);
283 }
284 
285 TEST(Writer, AssertObjectKeyNotString) {
286 #define T(x)\
287  {\
288  StringBuffer buffer;\
289  Writer<StringBuffer> writer(buffer);\
290  writer.StartObject();\
291  ASSERT_THROW(x, AssertException); \
292  }
293  T(writer.Bool(false));
294  T(writer.Bool(true));
295  T(writer.Null());
296  T(writer.Int(0));
297  T(writer.Uint(0));
298  T(writer.Int64(0));
299  T(writer.Uint64(0));
300  T(writer.Double(0));
301  T(writer.StartObject());
302  T(writer.StartArray());
303 #undef T
304 }
305 
306 TEST(Writer, AssertMultipleRoot) {
307  StringBuffer buffer;
308  Writer<StringBuffer> writer(buffer);
309 
310  writer.StartObject();
311  writer.EndObject();
312  ASSERT_THROW(writer.StartObject(), AssertException);
313 
314  writer.Reset(buffer);
315  writer.Null();
316  ASSERT_THROW(writer.Int(0), AssertException);
317 
318  writer.Reset(buffer);
319  writer.String("foo");
320  ASSERT_THROW(writer.StartArray(), AssertException);
321 
322  writer.Reset(buffer);
323  writer.StartArray();
324  writer.EndArray();
325  //ASSERT_THROW(writer.Double(3.14), AssertException);
326 }
327 
328 TEST(Writer, RootObjectIsComplete) {
329  StringBuffer buffer;
330  Writer<StringBuffer> writer(buffer);
331  EXPECT_FALSE(writer.IsComplete());
332  writer.StartObject();
333  EXPECT_FALSE(writer.IsComplete());
334  writer.String("foo");
335  EXPECT_FALSE(writer.IsComplete());
336  writer.Int(1);
337  EXPECT_FALSE(writer.IsComplete());
338  writer.EndObject();
339  EXPECT_TRUE(writer.IsComplete());
340 }
341 
342 TEST(Writer, RootArrayIsComplete) {
343  StringBuffer buffer;
344  Writer<StringBuffer> writer(buffer);
345  EXPECT_FALSE(writer.IsComplete());
346  writer.StartArray();
347  EXPECT_FALSE(writer.IsComplete());
348  writer.String("foo");
349  EXPECT_FALSE(writer.IsComplete());
350  writer.Int(1);
351  EXPECT_FALSE(writer.IsComplete());
352  writer.EndArray();
353  EXPECT_TRUE(writer.IsComplete());
354 }
355 
356 TEST(Writer, RootValueIsComplete) {
357 #define T(x)\
358  {\
359  StringBuffer buffer;\
360  Writer<StringBuffer> writer(buffer);\
361  EXPECT_FALSE(writer.IsComplete()); \
362  x; \
363  EXPECT_TRUE(writer.IsComplete()); \
364  }
365  T(writer.Null());
366  T(writer.Bool(true));
367  T(writer.Bool(false));
368  T(writer.Int(0));
369  T(writer.Uint(0));
370  T(writer.Int64(0));
371  T(writer.Uint64(0));
372  T(writer.Double(0));
373  T(writer.String(""));
374 #undef T
375 }
376 
377 TEST(Writer, InvalidEncoding) {
378  // Fail in decoding invalid UTF-8 sequence http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
379  {
382  writer.StartArray();
383  EXPECT_FALSE(writer.String("\xfe"));
384  EXPECT_FALSE(writer.String("\xff"));
385  EXPECT_FALSE(writer.String("\xfe\xfe\xff\xff"));
386  writer.EndArray();
387  }
388 
389  // Fail in encoding
390  {
391  StringBuffer buffer;
392  Writer<StringBuffer, UTF32<> > writer(buffer);
393  static const UTF32<>::Ch s[] = { 0x110000, 0 }; // Out of U+0000 to U+10FFFF
394  EXPECT_FALSE(writer.String(s));
395  }
396 
397  // Fail in unicode escaping in ASCII output
398  {
399  StringBuffer buffer;
400  Writer<StringBuffer, UTF32<>, ASCII<> > writer(buffer);
401  static const UTF32<>::Ch s[] = { 0x110000, 0 }; // Out of U+0000 to U+10FFFF
402  EXPECT_FALSE(writer.String(s));
403  }
404 }
405 
406 TEST(Writer, ValidateEncoding) {
407  {
408  StringBuffer buffer;
410  writer.StartArray();
411  EXPECT_TRUE(writer.String("\x24")); // Dollar sign U+0024
412  EXPECT_TRUE(writer.String("\xC2\xA2")); // Cents sign U+00A2
413  EXPECT_TRUE(writer.String("\xE2\x82\xAC")); // Euro sign U+20AC
414  EXPECT_TRUE(writer.String("\xF0\x9D\x84\x9E")); // G clef sign U+1D11E
415  EXPECT_TRUE(writer.String("\x01")); // SOH control U+0001
416  EXPECT_TRUE(writer.String("\x1B")); // Escape control U+001B
417  writer.EndArray();
418  EXPECT_STREQ("[\"\x24\",\"\xC2\xA2\",\"\xE2\x82\xAC\",\"\xF0\x9D\x84\x9E\",\"\\u0001\",\"\\u001B\"]", buffer.GetString());
419  }
420 
421  // Fail in decoding invalid UTF-8 sequence http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
422  {
423  StringBuffer buffer;
425  writer.StartArray();
426  EXPECT_FALSE(writer.String("\xfe"));
427  EXPECT_FALSE(writer.String("\xff"));
428  EXPECT_FALSE(writer.String("\xfe\xfe\xff\xff"));
429  writer.EndArray();
430  }
431 }
432 
433 TEST(Writer, InvalidEventSequence) {
434  // {]
435  {
436  StringBuffer buffer;
437  Writer<StringBuffer> writer(buffer);
438  writer.StartObject();
439  EXPECT_THROW(writer.EndArray(), AssertException);
440  EXPECT_FALSE(writer.IsComplete());
441  }
442 
443  // [}
444  {
445  StringBuffer buffer;
446  Writer<StringBuffer> writer(buffer);
447  writer.StartArray();
448  EXPECT_THROW(writer.EndObject(), AssertException);
449  EXPECT_FALSE(writer.IsComplete());
450  }
451 
452  // { 1:
453  {
454  StringBuffer buffer;
455  Writer<StringBuffer> writer(buffer);
456  writer.StartObject();
457  EXPECT_THROW(writer.Int(1), AssertException);
458  EXPECT_FALSE(writer.IsComplete());
459  }
460 
461  // { 'a' }
462  {
463  StringBuffer buffer;
464  Writer<StringBuffer> writer(buffer);
465  writer.StartObject();
466  writer.Key("a");
467  EXPECT_THROW(writer.EndObject(), AssertException);
468  EXPECT_FALSE(writer.IsComplete());
469  }
470 
471  // { 'a':'b','c' }
472  {
473  StringBuffer buffer;
474  Writer<StringBuffer> writer(buffer);
475  writer.StartObject();
476  writer.Key("a");
477  writer.String("b");
478  writer.Key("c");
479  EXPECT_THROW(writer.EndObject(), AssertException);
480  EXPECT_FALSE(writer.IsComplete());
481  }
482 }
483 
484 TEST(Writer, NaN) {
485  double nan = std::numeric_limits<double>::quiet_NaN();
486 
487  EXPECT_TRUE(internal::Double(nan).IsNan());
488  StringBuffer buffer;
489  {
490  Writer<StringBuffer> writer(buffer);
491  EXPECT_FALSE(writer.Double(nan));
492  }
493  {
495  EXPECT_TRUE(writer.Double(nan));
496  EXPECT_STREQ("NaN", buffer.GetString());
497  }
498  GenericStringBuffer<UTF16<> > buffer2;
499  Writer<GenericStringBuffer<UTF16<> > > writer2(buffer2);
500  EXPECT_FALSE(writer2.Double(nan));
501 }
502 
503 TEST(Writer, Inf) {
504  double inf = std::numeric_limits<double>::infinity();
505 
506  EXPECT_TRUE(internal::Double(inf).IsInf());
507  StringBuffer buffer;
508  {
509  Writer<StringBuffer> writer(buffer);
510  EXPECT_FALSE(writer.Double(inf));
511  }
512  {
513  Writer<StringBuffer> writer(buffer);
514  EXPECT_FALSE(writer.Double(-inf));
515  }
516  {
518  EXPECT_TRUE(writer.Double(inf));
519  }
520  {
522  EXPECT_TRUE(writer.Double(-inf));
523  }
524  EXPECT_STREQ("Infinity-Infinity", buffer.GetString());
525 }
526 
527 TEST(Writer, RawValue) {
528  StringBuffer buffer;
529  Writer<StringBuffer> writer(buffer);
530  writer.StartObject();
531  writer.Key("a");
532  writer.Int(1);
533  writer.Key("raw");
534  const char json[] = "[\"Hello\\nWorld\", 123.456]";
535  writer.RawValue(json, strlen(json), kArrayType);
536  writer.EndObject();
537  EXPECT_TRUE(writer.IsComplete());
538  EXPECT_STREQ("{\"a\":1,\"raw\":[\"Hello\\nWorld\", 123.456]}", buffer.GetString());
539 }
540 
541 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
542 static Writer<StringBuffer> WriterGen(StringBuffer &target) {
543  Writer<StringBuffer> writer(target);
544  writer.StartObject();
545  writer.Key("a");
546  writer.Int(1);
547  return writer;
548 }
549 
550 TEST(Writer, MoveCtor) {
551  StringBuffer buffer;
552  Writer<StringBuffer> writer(WriterGen(buffer));
553  writer.EndObject();
554  EXPECT_TRUE(writer.IsComplete());
555  EXPECT_STREQ("{\"a\":1}", buffer.GetString());
556 }
557 #endif
558 
559 #ifdef __clang__
560 RAPIDJSON_DIAG_POP
561 #endif
void TestTranscode(const char *json)
Definition: writertest.cpp:144
Ch Peek() const
Definition: writertest.cpp:205
size_t Tell() const
Definition: writertest.cpp:207
size_t GetSize() const
Get the size of string in bytes in the string buffer.
Definition: stringbuffer.h:82
bool EndArray(SizeType elementCount=0)
Definition: writer.h:247
ParseResult Parse(InputStream &is, Handler &handler)
Parse JSON text.
Definition: reader.h:558
bool EndObject(SizeType memberCount=0)
Definition: writer.h:232
UTFType
Runtime-specified UTF encoding type of a stream.
Definition: encodings.h:603
Represents an in-memory input byte stream.
Definition: memorystream.h:40
JSON writer.
Definition: fwd.h:95
ASCII encoding.
Definition: encodings.h:542
const Ch * GetString() const
Definition: stringbuffer.h:73
Read-only string stream.
Definition: fwd.h:47
array
Definition: rapidjson.h:621
Represents an in-memory output byte stream.
Definition: fwd.h:74
UTF-32 big endian.
Definition: encodings.h:608
UTF-16 little endian.
Definition: encodings.h:605
XmlRpcServer s
UTF-8.
Definition: encodings.h:604
UTF-16 encoding.
Definition: encodings.h:269
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition: writer.h:273
bool Int(int i)
Definition: writer.h:185
bool Double(double d)
Writes the given double value to the stream.
Definition: writer.h:195
Validate encoding of JSON strings.
Definition: writer.h:69
UTF-16 big endian.
Definition: encodings.h:606
size_t GetSize() const
Definition: memorybuffer.h:54
OStreamWrapper(std::ostream &os)
Definition: writertest.cpp:203
Output stream wrapper with dynamically bound encoding and automatic encoding detection.
bool String(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:204
size_t PutEnd(Ch *)
Definition: writertest.cpp:212
TEST(Writer, Compact)
Definition: writertest.cpp:30
CharType Ch
Definition: encodings.h:419
UTF-8 encoding.
Definition: encodings.h:96
bool Null()
Definition: writer.h:183
static const char json[]
void Put(Ch c)
Definition: writertest.cpp:210
BasicOStreamWrapper< std::ostream > OStreamWrapper
const Ch * GetBuffer() const
Definition: memorybuffer.h:50
bool Key(const Ch *str, SizeType length, bool copy=false)
Definition: writer.h:223
main RapidJSON namespace
Input stream wrapper with dynamically bound encoding and automatic encoding detection.
#define TEST_ROUNDTRIP(json)
Definition: writertest.cpp:43
C-runtime library allocator.
Definition: allocators.h:62
#define T(x)
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition: writer.h:145
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition: writer.h:135
UTF-32 little endian.
Definition: encodings.h:607
bool StartObject()
Definition: writer.h:217
Allow writing of Infinity, -Infinity and NaN.
Definition: writer.h:70
bool StartArray()
Definition: writer.h:241


choreo_rapidjson
Author(s):
autogenerated on Thu Jul 18 2019 03:59:09