Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
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"
22
23#ifdef __clang__
24RAPIDJSON_DIAG_PUSH
25RAPIDJSON_DIAG_OFF(c++98-compat)
26#endif
27
28using namespace rapidjson;
29
30TEST(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
54TEST(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
64TEST(Writer, Int) {
65 TEST_ROUNDTRIP("[-1]");
66 TEST_ROUNDTRIP("[-123]");
67 TEST_ROUNDTRIP("[-2147483648]");
68}
69
70TEST(Writer, UInt) {
71 TEST_ROUNDTRIP("[0]");
72 TEST_ROUNDTRIP("[1]");
73 TEST_ROUNDTRIP("[123]");
74 TEST_ROUNDTRIP("[2147483647]");
75 TEST_ROUNDTRIP("[4294967295]");
76}
77
78TEST(Writer, Int64) {
79 TEST_ROUNDTRIP("[-1234567890123456789]");
80 TEST_ROUNDTRIP("[-9223372036854775808]");
81}
82
83TEST(Writer, Uint64) {
84 TEST_ROUNDTRIP("[1234567890123456789]");
85 TEST_ROUNDTRIP("[9223372036854775807]");
86}
87
88TEST(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
103TEST(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
116TEST(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));
126 }
127}
128
129TEST(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
143template <typename TargetEncoding>
144void 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
160TEST(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);
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
199class OStreamWrapper {
200public:
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
214private:
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
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
236TEST(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
255TEST(Writer, AssertIncorrectObjectLevel) {
256 StringBuffer buffer;
257 Writer<StringBuffer> writer(buffer);
258 writer.StartObject();
259 writer.EndObject();
261}
262
263TEST(Writer, AssertIncorrectArrayLevel) {
264 StringBuffer buffer;
265 Writer<StringBuffer> writer(buffer);
266 writer.StartArray();
267 writer.EndArray();
269}
270
271TEST(Writer, AssertIncorrectEndObject) {
272 StringBuffer buffer;
273 Writer<StringBuffer> writer(buffer);
274 writer.StartObject();
276}
277
278TEST(Writer, AssertIncorrectEndArray) {
279 StringBuffer buffer;
280 Writer<StringBuffer> writer(buffer);
281 writer.StartObject();
283}
284
285TEST(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
306TEST(Writer, AssertMultipleRoot) {
307 StringBuffer buffer;
308 Writer<StringBuffer> writer(buffer);
309
310 writer.StartObject();
311 writer.EndObject();
313
314 writer.Reset(buffer);
315 writer.Null();
316 ASSERT_THROW(writer.Int(0), AssertException);
317
318 writer.Reset(buffer);
319 writer.String("foo");
321
322 writer.Reset(buffer);
323 writer.StartArray();
324 writer.EndArray();
325 //ASSERT_THROW(writer.Double(3.14), AssertException);
326}
327
328TEST(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
342TEST(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
356TEST(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
377TEST(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
406TEST(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
433TEST(Writer, InvalidEventSequence) {
434 // {]
435 {
436 StringBuffer buffer;
437 Writer<StringBuffer> writer(buffer);
438 writer.StartObject();
440 EXPECT_FALSE(writer.IsComplete());
441 }
442
443 // [}
444 {
445 StringBuffer buffer;
446 Writer<StringBuffer> writer(buffer);
447 writer.StartArray();
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");
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");
480 EXPECT_FALSE(writer.IsComplete());
481 }
482}
483
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 }
499 Writer<GenericStringBuffer<UTF16<> > > writer2(buffer2);
500 EXPECT_FALSE(writer2.Double(nan));
501}
502
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
527TEST(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
541TEST(Write, RawValue_Issue1152) {
542 {
545 writer.RawValue("null", 4, kNullType);
546 EXPECT_TRUE(writer.IsComplete());
547 const unsigned *out = sb.GetString();
548 EXPECT_EQ(static_cast<unsigned>('n'), out[0]);
549 EXPECT_EQ(static_cast<unsigned>('u'), out[1]);
550 EXPECT_EQ(static_cast<unsigned>('l'), out[2]);
551 EXPECT_EQ(static_cast<unsigned>('l'), out[3]);
552 EXPECT_EQ(static_cast<unsigned>(0 ), out[4]);
553 }
554
555 {
558 writer.RawValue(L"null", 4, kNullType);
559 EXPECT_TRUE(writer.IsComplete());
560 EXPECT_STREQ("null", sb.GetString());
561 }
562
563 {
564 // Fail in transcoding
567 EXPECT_FALSE(writer.RawValue("\"\xfe\"", 3, kStringType));
568 }
569
570 {
571 // Fail in encoding validation
572 StringBuffer buffer;
574 EXPECT_FALSE(writer.RawValue("\"\xfe\"", 3, kStringType));
575 }
576}
577
578#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
579static Writer<StringBuffer> WriterGen(StringBuffer &target) {
580 Writer<StringBuffer> writer(target);
581 writer.StartObject();
582 writer.Key("a");
583 writer.Int(1);
584 return writer;
585}
586
587TEST(Writer, MoveCtor) {
588 StringBuffer buffer;
589 Writer<StringBuffer> writer(WriterGen(buffer));
590 writer.EndObject();
591 EXPECT_TRUE(writer.IsComplete());
592 EXPECT_STREQ("{\"a\":1}", buffer.GetString());
593}
594#endif
595
596#ifdef __clang__
597RAPIDJSON_DIAG_POP
598#endif
const mie::Vuint & p
Definition bn.cpp:27
Input stream wrapper with dynamically bound encoding and automatic encoding detection.
Output stream wrapper with dynamically bound encoding and automatic encoding detection.
C-runtime library allocator.
Definition allocators.h:75
ParseResult Parse(InputStream &is, Handler &handler)
Parse JSON text.
Definition reader.h:557
const Ch * GetString() const
size_t GetSize() const
Get the size of string in bytes in the string buffer.
size_t Tell() const
void Put(Ch c)
Ch Peek() const
OStreamWrapper(std::ostream &os)
size_t PutEnd(Ch *)
JSON writer.
Definition writer.h:89
bool EndObject(SizeType memberCount=0)
Definition writer.h:230
bool IsComplete() const
Checks whether the output is a complete JSON.
Definition writer.h:143
bool Key(const Ch *str, SizeType length, bool copy=false)
Definition writer.h:221
bool Double(double d)
Writes the given double value to the stream.
Definition writer.h:193
bool StartArray()
Definition writer.h:239
bool String(const Ch *str, SizeType length, bool copy=false)
Definition writer.h:202
void Reset(OutputStream &os)
Reset the writer with a new stream.
Definition writer.h:133
bool EndArray(SizeType elementCount=0)
Definition writer.h:245
bool Int(int i)
Definition writer.h:183
bool RawValue(const Ch *json, size_t length, Type type)
Write a raw JSON value.
Definition writer.h:271
bool StartObject()
Definition writer.h:215
bool Null()
Definition writer.h:181
UTFType
Runtime-specified UTF encoding type of a stream.
Definition encodings.h:603
@ kUTF32BE
UTF-32 big endian.
Definition encodings.h:608
@ kUTF16BE
UTF-16 big endian.
Definition encodings.h:606
@ kUTF8
UTF-8.
Definition encodings.h:604
@ kUTF32LE
UTF-32 little endian.
Definition encodings.h:607
@ kUTF16LE
UTF-16 little endian.
Definition encodings.h:605
os_t os
#define EXPECT_EQ(val1, val2)
Definition gtest.h:1954
#define EXPECT_THROW(statement, expected_exception)
Definition gtest.h:1879
#define EXPECT_TRUE(condition)
Definition gtest.h:1895
#define EXPECT_STREQ(s1, s2)
Definition gtest.h:2027
#define TEST(test_case_name, test_name)
Definition gtest.h:2275
#define EXPECT_FALSE(condition)
Definition gtest.h:1898
#define ASSERT_THROW(statement, expected_exception)
Definition gtest.h:1885
main RapidJSON namespace
BasicOStreamWrapper< std::ostream > OStreamWrapper
@ kStringType
string
Definition rapidjson.h:650
@ kNullType
null
Definition rapidjson.h:645
@ kArrayType
array
Definition rapidjson.h:649
ASCII encoding.
Definition encodings.h:542
Dynamically select encoding according to stream's runtime-specified UTF encoding type.
Definition encodings.h:615
Represents an in-memory output byte stream.
const Ch * GetBuffer() const
size_t GetSize() const
Read-only string stream.
Definition stream.h:154
Represents an in-memory input byte stream.
UTF-16 encoding.
Definition encodings.h:269
UTF-32 encoding.
Definition encodings.h:418
CharType Ch
Definition encodings.h:419
UTF-8 encoding.
Definition encodings.h:96
@ kWriteNanAndInfFlag
Allow writing of Infinity, -Infinity and NaN.
Definition writer.h:68
@ kWriteValidateEncodingFlag
Validate encoding of JSON strings.
Definition writer.h:67
#define TEST_ROUNDTRIP(json)
void TestTranscode(const char *json)
#define T(x)
char * s
uint8_t buf[2048]
memcpy((char *) pInfo->slotDescription, s, l)