fixed adding file problem
[c11concurrency-benchmarks.git] / gdax-orderbook-hpp / demo / dependencies / rapidjson-1.1.0 / test / unittest / documenttest.cpp
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 #include "rapidjson/document.h"
17 #include "rapidjson/writer.h"
18 #include "rapidjson/filereadstream.h"
19 #include "rapidjson/encodedstream.h"
20 #include "rapidjson/stringbuffer.h"
21 #include <sstream>
22 #include <algorithm>
23
24 #ifdef __clang__
25 RAPIDJSON_DIAG_PUSH
26 RAPIDJSON_DIAG_OFF(c++98-compat)
27 RAPIDJSON_DIAG_OFF(missing-variable-declarations)
28 #endif
29
30 using namespace rapidjson;
31
32 template <typename DocumentType>
33 void ParseCheck(DocumentType& doc) {
34     typedef typename DocumentType::ValueType ValueType;
35
36     EXPECT_FALSE(doc.HasParseError());
37     if (doc.HasParseError())
38         printf("Error: %d at %zu\n", static_cast<int>(doc.GetParseError()), doc.GetErrorOffset());
39     EXPECT_TRUE(static_cast<ParseResult>(doc));
40
41     EXPECT_TRUE(doc.IsObject());
42
43     EXPECT_TRUE(doc.HasMember("hello"));
44     const ValueType& hello = doc["hello"];
45     EXPECT_TRUE(hello.IsString());
46     EXPECT_STREQ("world", hello.GetString());
47
48     EXPECT_TRUE(doc.HasMember("t"));
49     const ValueType& t = doc["t"];
50     EXPECT_TRUE(t.IsTrue());
51
52     EXPECT_TRUE(doc.HasMember("f"));
53     const ValueType& f = doc["f"];
54     EXPECT_TRUE(f.IsFalse());
55
56     EXPECT_TRUE(doc.HasMember("n"));
57     const ValueType& n = doc["n"];
58     EXPECT_TRUE(n.IsNull());
59
60     EXPECT_TRUE(doc.HasMember("i"));
61     const ValueType& i = doc["i"];
62     EXPECT_TRUE(i.IsNumber());
63     EXPECT_EQ(123, i.GetInt());
64
65     EXPECT_TRUE(doc.HasMember("pi"));
66     const ValueType& pi = doc["pi"];
67     EXPECT_TRUE(pi.IsNumber());
68     EXPECT_DOUBLE_EQ(3.1416, pi.GetDouble());
69
70     EXPECT_TRUE(doc.HasMember("a"));
71     const ValueType& a = doc["a"];
72     EXPECT_TRUE(a.IsArray());
73     EXPECT_EQ(4u, a.Size());
74     for (SizeType j = 0; j < 4; j++)
75         EXPECT_EQ(j + 1, a[j].GetUint());
76 }
77
78 template <typename Allocator, typename StackAllocator>
79 void ParseTest() {
80     typedef GenericDocument<UTF8<>, Allocator, StackAllocator> DocumentType;
81     DocumentType doc;
82
83     const char* json = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
84
85     doc.Parse(json);
86     ParseCheck(doc);
87
88     doc.SetNull();
89     StringStream s(json);
90     doc.template ParseStream<0>(s);
91     ParseCheck(doc);
92
93     doc.SetNull();
94     char *buffer = strdup(json);
95     doc.ParseInsitu(buffer);
96     ParseCheck(doc);
97     free(buffer);
98
99     // Parse(const Ch*, size_t)
100     size_t length = strlen(json);
101     buffer = reinterpret_cast<char*>(malloc(length * 2));
102     memcpy(buffer, json, length);
103     memset(buffer + length, 'X', length);
104 #if RAPIDJSON_HAS_STDSTRING
105     std::string s2(buffer, length); // backup buffer
106 #endif
107     doc.SetNull();
108     doc.Parse(buffer, length);
109     free(buffer);
110     ParseCheck(doc);
111
112 #if RAPIDJSON_HAS_STDSTRING
113     // Parse(std::string)
114     doc.SetNull();
115     doc.Parse(s2);
116     ParseCheck(doc);
117 #endif
118 }
119
120 TEST(Document, Parse) {
121     ParseTest<MemoryPoolAllocator<>, CrtAllocator>();
122     ParseTest<MemoryPoolAllocator<>, MemoryPoolAllocator<> >();
123     ParseTest<CrtAllocator, MemoryPoolAllocator<> >();
124     ParseTest<CrtAllocator, CrtAllocator>();
125 }
126
127 TEST(Document, UnchangedOnParseError) {
128     Document doc;
129     doc.SetArray().PushBack(0, doc.GetAllocator());
130
131     ParseResult err = doc.Parse("{]");
132     EXPECT_TRUE(doc.HasParseError());
133     EXPECT_EQ(err.Code(), doc.GetParseError());
134     EXPECT_EQ(err.Offset(), doc.GetErrorOffset());
135     EXPECT_TRUE(doc.IsArray());
136     EXPECT_EQ(doc.Size(), 1u);
137
138     err = doc.Parse("{}");
139     EXPECT_FALSE(doc.HasParseError());
140     EXPECT_FALSE(err.IsError());
141     EXPECT_EQ(err.Code(), doc.GetParseError());
142     EXPECT_EQ(err.Offset(), doc.GetErrorOffset());
143     EXPECT_TRUE(doc.IsObject());
144     EXPECT_EQ(doc.MemberCount(), 0u);
145 }
146
147 static FILE* OpenEncodedFile(const char* filename) {
148     const char *paths[] = {
149         "encodings",
150         "bin/encodings",
151         "../bin/encodings",
152         "../../bin/encodings",
153         "../../../bin/encodings"
154     };
155     char buffer[1024];
156     for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
157         sprintf(buffer, "%s/%s", paths[i], filename);
158         FILE *fp = fopen(buffer, "rb");
159         if (fp)
160             return fp;
161     }
162     return 0;
163 }
164
165 TEST(Document, Parse_Encoding) {
166     const char* json = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
167
168     typedef GenericDocument<UTF16<> > DocumentType;
169     DocumentType doc;
170     
171     // Parse<unsigned, SourceEncoding>(const SourceEncoding::Ch*)
172     // doc.Parse<kParseDefaultFlags, UTF8<> >(json);
173     // EXPECT_FALSE(doc.HasParseError());
174     // EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world"));
175
176     // Parse<unsigned, SourceEncoding>(const SourceEncoding::Ch*, size_t)
177     size_t length = strlen(json);
178     char* buffer = reinterpret_cast<char*>(malloc(length * 2));
179     memcpy(buffer, json, length);
180     memset(buffer + length, 'X', length);
181 #if RAPIDJSON_HAS_STDSTRING
182     std::string s2(buffer, length); // backup buffer
183 #endif
184     doc.SetNull();
185     doc.Parse<kParseDefaultFlags, UTF8<> >(buffer, length);
186     free(buffer);
187     EXPECT_FALSE(doc.HasParseError());
188     if (doc.HasParseError())
189         printf("Error: %d at %zu\n", static_cast<int>(doc.GetParseError()), doc.GetErrorOffset());
190     EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world"));
191
192 #if RAPIDJSON_HAS_STDSTRING
193     // Parse<unsigned, SourceEncoding>(std::string)
194     doc.SetNull();
195
196 #if defined(_MSC_VER) && _MSC_VER < 1800
197     doc.Parse<kParseDefaultFlags, UTF8<> >(s2.c_str()); // VS2010 or below cannot handle templated function overloading. Use const char* instead.
198 #else
199     doc.Parse<kParseDefaultFlags, UTF8<> >(s2);
200 #endif
201     EXPECT_FALSE(doc.HasParseError());
202     EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world"));
203 #endif
204 }
205
206 TEST(Document, ParseStream_EncodedInputStream) {
207     // UTF8 -> UTF16
208     FILE* fp = OpenEncodedFile("utf8.json");
209     char buffer[256];
210     FileReadStream bis(fp, buffer, sizeof(buffer));
211     EncodedInputStream<UTF8<>, FileReadStream> eis(bis);
212
213     GenericDocument<UTF16<> > d;
214     d.ParseStream<0, UTF8<> >(eis);
215     EXPECT_FALSE(d.HasParseError());
216
217     fclose(fp);
218
219     wchar_t expected[] = L"I can eat glass and it doesn't hurt me.";
220     GenericValue<UTF16<> >& v = d[L"en"];
221     EXPECT_TRUE(v.IsString());
222     EXPECT_EQ(sizeof(expected) / sizeof(wchar_t) - 1, v.GetStringLength());
223     EXPECT_EQ(0, StrCmp(expected, v.GetString()));
224
225     // UTF16 -> UTF8 in memory
226     StringBuffer bos;
227     typedef EncodedOutputStream<UTF8<>, StringBuffer> OutputStream;
228     OutputStream eos(bos, false);   // Not writing BOM
229     {
230         Writer<OutputStream, UTF16<>, UTF8<> > writer(eos);
231         d.Accept(writer);
232     }
233
234     // Condense the original file and compare.
235     fp = OpenEncodedFile("utf8.json");
236     FileReadStream is(fp, buffer, sizeof(buffer));
237     Reader reader;
238     StringBuffer bos2;
239     Writer<StringBuffer> writer2(bos2);
240     reader.Parse(is, writer2);
241     fclose(fp);
242
243     EXPECT_EQ(bos.GetSize(), bos2.GetSize());
244     EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize()));
245 }
246
247 TEST(Document, ParseStream_AutoUTFInputStream) {
248     // Any -> UTF8
249     FILE* fp = OpenEncodedFile("utf32be.json");
250     char buffer[256];
251     FileReadStream bis(fp, buffer, sizeof(buffer));
252     AutoUTFInputStream<unsigned, FileReadStream> eis(bis);
253
254     Document d;
255     d.ParseStream<0, AutoUTF<unsigned> >(eis);
256     EXPECT_FALSE(d.HasParseError());
257
258     fclose(fp);
259
260     char expected[] = "I can eat glass and it doesn't hurt me.";
261     Value& v = d["en"];
262     EXPECT_TRUE(v.IsString());
263     EXPECT_EQ(sizeof(expected) - 1, v.GetStringLength());
264     EXPECT_EQ(0, StrCmp(expected, v.GetString()));
265
266     // UTF8 -> UTF8 in memory
267     StringBuffer bos;
268     Writer<StringBuffer> writer(bos);
269     d.Accept(writer);
270
271     // Condense the original file and compare.
272     fp = OpenEncodedFile("utf8.json");
273     FileReadStream is(fp, buffer, sizeof(buffer));
274     Reader reader;
275     StringBuffer bos2;
276     Writer<StringBuffer> writer2(bos2);
277     reader.Parse(is, writer2);
278     fclose(fp);
279
280     EXPECT_EQ(bos.GetSize(), bos2.GetSize());
281     EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize()));
282 }
283
284 TEST(Document, Swap) {
285     Document d1;
286     Document::AllocatorType& a = d1.GetAllocator();
287
288     d1.SetArray().PushBack(1, a).PushBack(2, a);
289
290     Value o;
291     o.SetObject().AddMember("a", 1, a);
292
293     // Swap between Document and Value
294     // d1.Swap(o); // doesn't compile
295     o.Swap(d1);
296     EXPECT_TRUE(d1.IsObject());
297     EXPECT_TRUE(o.IsArray());
298
299     // Swap between Document and Document
300     Document d2;
301     d2.SetArray().PushBack(3, a);
302     d1.Swap(d2);
303     EXPECT_TRUE(d1.IsArray());
304     EXPECT_TRUE(d2.IsObject());
305     EXPECT_EQ(&d2.GetAllocator(), &a);
306
307     // reset value
308     Value().Swap(d1);
309     EXPECT_TRUE(d1.IsNull());
310
311     // reset document, including allocator
312     Document().Swap(d2);
313     EXPECT_TRUE(d2.IsNull());
314     EXPECT_NE(&d2.GetAllocator(), &a);
315
316     // testing std::swap compatibility
317     d1.SetBool(true);
318     using std::swap;
319     swap(d1, d2);
320     EXPECT_TRUE(d1.IsNull());
321     EXPECT_TRUE(d2.IsTrue());
322
323     swap(o, d2);
324     EXPECT_TRUE(o.IsTrue());
325     EXPECT_TRUE(d2.IsArray());
326 }
327
328
329 // This should be slow due to assignment in inner-loop.
330 struct OutputStringStream : public std::ostringstream {
331     typedef char Ch;
332
333     virtual ~OutputStringStream();
334
335     void Put(char c) {
336         put(c);
337     }
338     void Flush() {}
339 };
340
341 OutputStringStream::~OutputStringStream() {}
342
343 TEST(Document, AcceptWriter) {
344     Document doc;
345     doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ");
346
347     OutputStringStream os;
348     Writer<OutputStringStream> writer(os);
349     doc.Accept(writer);
350
351     EXPECT_EQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3,4]}", os.str());
352 }
353
354 TEST(Document, UserBuffer) {
355     typedef GenericDocument<UTF8<>, MemoryPoolAllocator<>, MemoryPoolAllocator<> > DocumentType;
356     char valueBuffer[4096];
357     char parseBuffer[1024];
358     MemoryPoolAllocator<> valueAllocator(valueBuffer, sizeof(valueBuffer));
359     MemoryPoolAllocator<> parseAllocator(parseBuffer, sizeof(parseBuffer));
360     DocumentType doc(&valueAllocator, sizeof(parseBuffer) / 2, &parseAllocator);
361     doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ");
362     EXPECT_FALSE(doc.HasParseError());
363     EXPECT_LE(valueAllocator.Size(), sizeof(valueBuffer));
364     EXPECT_LE(parseAllocator.Size(), sizeof(parseBuffer));
365
366     // Cover MemoryPoolAllocator::Capacity()
367     EXPECT_LE(valueAllocator.Size(), valueAllocator.Capacity());
368     EXPECT_LE(parseAllocator.Size(), parseAllocator.Capacity());
369 }
370
371 // Issue 226: Value of string type should not point to NULL
372 TEST(Document, AssertAcceptInvalidNameType) {
373     Document doc;
374     doc.SetObject();
375     doc.AddMember("a", 0, doc.GetAllocator());
376     doc.FindMember("a")->name.SetNull(); // Change name to non-string type.
377
378     OutputStringStream os;
379     Writer<OutputStringStream> writer(os);
380     ASSERT_THROW(doc.Accept(writer), AssertException);
381 }
382
383 // Issue 44:    SetStringRaw doesn't work with wchar_t
384 TEST(Document, UTF16_Document) {
385     GenericDocument< UTF16<> > json;
386     json.Parse<kParseValidateEncodingFlag>(L"[{\"created_at\":\"Wed Oct 30 17:13:20 +0000 2012\"}]");
387
388     ASSERT_TRUE(json.IsArray());
389     GenericValue< UTF16<> >& v = json[0];
390     ASSERT_TRUE(v.IsObject());
391
392     GenericValue< UTF16<> >& s = v[L"created_at"];
393     ASSERT_TRUE(s.IsString());
394
395     EXPECT_EQ(0, memcmp(L"Wed Oct 30 17:13:20 +0000 2012", s.GetString(), (s.GetStringLength() + 1) * sizeof(wchar_t)));
396 }
397
398 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
399
400 #if 0 // Many old compiler does not support these. Turn it off temporaily.
401
402 #include <type_traits>
403
404 TEST(Document, Traits) {
405     static_assert(std::is_constructible<Document>::value, "");
406     static_assert(std::is_default_constructible<Document>::value, "");
407 #ifndef _MSC_VER
408     static_assert(!std::is_copy_constructible<Document>::value, "");
409 #endif
410     static_assert(std::is_move_constructible<Document>::value, "");
411
412     static_assert(!std::is_nothrow_constructible<Document>::value, "");
413     static_assert(!std::is_nothrow_default_constructible<Document>::value, "");
414 #ifndef _MSC_VER
415     static_assert(!std::is_nothrow_copy_constructible<Document>::value, "");
416     static_assert(std::is_nothrow_move_constructible<Document>::value, "");
417 #endif
418
419     static_assert(std::is_assignable<Document,Document>::value, "");
420 #ifndef _MSC_VER
421   static_assert(!std::is_copy_assignable<Document>::value, "");
422 #endif
423     static_assert(std::is_move_assignable<Document>::value, "");
424
425 #ifndef _MSC_VER
426     static_assert(std::is_nothrow_assignable<Document, Document>::value, "");
427 #endif
428     static_assert(!std::is_nothrow_copy_assignable<Document>::value, "");
429 #ifndef _MSC_VER
430     static_assert(std::is_nothrow_move_assignable<Document>::value, "");
431 #endif
432
433     static_assert( std::is_destructible<Document>::value, "");
434 #ifndef _MSC_VER
435     static_assert(std::is_nothrow_destructible<Document>::value, "");
436 #endif
437 }
438
439 #endif
440
441 template <typename Allocator>
442 struct DocumentMove: public ::testing::Test {
443 };
444
445 typedef ::testing::Types< CrtAllocator, MemoryPoolAllocator<> > MoveAllocatorTypes;
446 TYPED_TEST_CASE(DocumentMove, MoveAllocatorTypes);
447
448 TYPED_TEST(DocumentMove, MoveConstructor) {
449     typedef TypeParam Allocator;
450     typedef GenericDocument<UTF8<>, Allocator> D;
451     Allocator allocator;
452
453     D a(&allocator);
454     a.Parse("[\"one\", \"two\", \"three\"]");
455     EXPECT_FALSE(a.HasParseError());
456     EXPECT_TRUE(a.IsArray());
457     EXPECT_EQ(3u, a.Size());
458     EXPECT_EQ(&a.GetAllocator(), &allocator);
459
460     // Document b(a); // does not compile (!is_copy_constructible)
461     D b(std::move(a));
462     EXPECT_TRUE(a.IsNull());
463     EXPECT_TRUE(b.IsArray());
464     EXPECT_EQ(3u, b.Size());
465     EXPECT_THROW(a.GetAllocator(), AssertException);
466     EXPECT_EQ(&b.GetAllocator(), &allocator);
467
468     b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}");
469     EXPECT_FALSE(b.HasParseError());
470     EXPECT_TRUE(b.IsObject());
471     EXPECT_EQ(2u, b.MemberCount());
472
473     // Document c = a; // does not compile (!is_copy_constructible)
474     D c = std::move(b);
475     EXPECT_TRUE(b.IsNull());
476     EXPECT_TRUE(c.IsObject());
477     EXPECT_EQ(2u, c.MemberCount());
478     EXPECT_THROW(b.GetAllocator(), AssertException);
479     EXPECT_EQ(&c.GetAllocator(), &allocator);
480 }
481
482 TYPED_TEST(DocumentMove, MoveConstructorParseError) {
483     typedef TypeParam Allocator;
484     typedef GenericDocument<UTF8<>, Allocator> D;
485
486     ParseResult noError;
487     D a;
488     a.Parse("{ 4 = 4]");
489     ParseResult error(a.GetParseError(), a.GetErrorOffset());
490     EXPECT_TRUE(a.HasParseError());
491     EXPECT_NE(error.Code(), noError.Code());
492     EXPECT_NE(error.Offset(), noError.Offset());
493
494     D b(std::move(a));
495     EXPECT_FALSE(a.HasParseError());
496     EXPECT_TRUE(b.HasParseError());
497     EXPECT_EQ(a.GetParseError(), noError.Code());
498     EXPECT_EQ(b.GetParseError(), error.Code());
499     EXPECT_EQ(a.GetErrorOffset(), noError.Offset());
500     EXPECT_EQ(b.GetErrorOffset(), error.Offset());
501
502     D c(std::move(b));
503     EXPECT_FALSE(b.HasParseError());
504     EXPECT_TRUE(c.HasParseError());
505     EXPECT_EQ(b.GetParseError(), noError.Code());
506     EXPECT_EQ(c.GetParseError(), error.Code());
507     EXPECT_EQ(b.GetErrorOffset(), noError.Offset());
508     EXPECT_EQ(c.GetErrorOffset(), error.Offset());
509 }
510
511 // This test does not properly use parsing, just for testing.
512 // It must call ClearStack() explicitly to prevent memory leak.
513 // But here we cannot as ClearStack() is private.
514 #if 0
515 TYPED_TEST(DocumentMove, MoveConstructorStack) {
516     typedef TypeParam Allocator;
517     typedef UTF8<> Encoding;
518     typedef GenericDocument<Encoding, Allocator> Document;
519
520     Document a;
521     size_t defaultCapacity = a.GetStackCapacity();
522
523     // Trick Document into getting GetStackCapacity() to return non-zero
524     typedef GenericReader<Encoding, Encoding, Allocator> Reader;
525     Reader reader(&a.GetAllocator());
526     GenericStringStream<Encoding> is("[\"one\", \"two\", \"three\"]");
527     reader.template Parse<kParseDefaultFlags>(is, a);
528     size_t capacity = a.GetStackCapacity();
529     EXPECT_GT(capacity, 0u);
530
531     Document b(std::move(a));
532     EXPECT_EQ(a.GetStackCapacity(), defaultCapacity);
533     EXPECT_EQ(b.GetStackCapacity(), capacity);
534
535     Document c = std::move(b);
536     EXPECT_EQ(b.GetStackCapacity(), defaultCapacity);
537     EXPECT_EQ(c.GetStackCapacity(), capacity);
538 }
539 #endif
540
541 TYPED_TEST(DocumentMove, MoveAssignment) {
542     typedef TypeParam Allocator;
543     typedef GenericDocument<UTF8<>, Allocator> D;
544     Allocator allocator;
545
546     D a(&allocator);
547     a.Parse("[\"one\", \"two\", \"three\"]");
548     EXPECT_FALSE(a.HasParseError());
549     EXPECT_TRUE(a.IsArray());
550     EXPECT_EQ(3u, a.Size());
551     EXPECT_EQ(&a.GetAllocator(), &allocator);
552
553     // Document b; b = a; // does not compile (!is_copy_assignable)
554     D b;
555     b = std::move(a);
556     EXPECT_TRUE(a.IsNull());
557     EXPECT_TRUE(b.IsArray());
558     EXPECT_EQ(3u, b.Size());
559     EXPECT_THROW(a.GetAllocator(), AssertException);
560     EXPECT_EQ(&b.GetAllocator(), &allocator);
561
562     b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}");
563     EXPECT_FALSE(b.HasParseError());
564     EXPECT_TRUE(b.IsObject());
565     EXPECT_EQ(2u, b.MemberCount());
566
567     // Document c; c = a; // does not compile (see static_assert)
568     D c;
569     c = std::move(b);
570     EXPECT_TRUE(b.IsNull());
571     EXPECT_TRUE(c.IsObject());
572     EXPECT_EQ(2u, c.MemberCount());
573     EXPECT_THROW(b.GetAllocator(), AssertException);
574     EXPECT_EQ(&c.GetAllocator(), &allocator);
575 }
576
577 TYPED_TEST(DocumentMove, MoveAssignmentParseError) {
578     typedef TypeParam Allocator;
579     typedef GenericDocument<UTF8<>, Allocator> D;
580
581     ParseResult noError;
582     D a;
583     a.Parse("{ 4 = 4]");
584     ParseResult error(a.GetParseError(), a.GetErrorOffset());
585     EXPECT_TRUE(a.HasParseError());
586     EXPECT_NE(error.Code(), noError.Code());
587     EXPECT_NE(error.Offset(), noError.Offset());
588
589     D b;
590     b = std::move(a);
591     EXPECT_FALSE(a.HasParseError());
592     EXPECT_TRUE(b.HasParseError());
593     EXPECT_EQ(a.GetParseError(), noError.Code());
594     EXPECT_EQ(b.GetParseError(), error.Code());
595     EXPECT_EQ(a.GetErrorOffset(), noError.Offset());
596     EXPECT_EQ(b.GetErrorOffset(), error.Offset());
597
598     D c;
599     c = std::move(b);
600     EXPECT_FALSE(b.HasParseError());
601     EXPECT_TRUE(c.HasParseError());
602     EXPECT_EQ(b.GetParseError(), noError.Code());
603     EXPECT_EQ(c.GetParseError(), error.Code());
604     EXPECT_EQ(b.GetErrorOffset(), noError.Offset());
605     EXPECT_EQ(c.GetErrorOffset(), error.Offset());
606 }
607
608 // This test does not properly use parsing, just for testing.
609 // It must call ClearStack() explicitly to prevent memory leak.
610 // But here we cannot as ClearStack() is private.
611 #if 0
612 TYPED_TEST(DocumentMove, MoveAssignmentStack) {
613     typedef TypeParam Allocator;
614     typedef UTF8<> Encoding;
615     typedef GenericDocument<Encoding, Allocator> D;
616
617     D a;
618     size_t defaultCapacity = a.GetStackCapacity();
619
620     // Trick Document into getting GetStackCapacity() to return non-zero
621     typedef GenericReader<Encoding, Encoding, Allocator> Reader;
622     Reader reader(&a.GetAllocator());
623     GenericStringStream<Encoding> is("[\"one\", \"two\", \"three\"]");
624     reader.template Parse<kParseDefaultFlags>(is, a);
625     size_t capacity = a.GetStackCapacity();
626     EXPECT_GT(capacity, 0u);
627
628     D b;
629     b = std::move(a);
630     EXPECT_EQ(a.GetStackCapacity(), defaultCapacity);
631     EXPECT_EQ(b.GetStackCapacity(), capacity);
632
633     D c;
634     c = std::move(b);
635     EXPECT_EQ(b.GetStackCapacity(), defaultCapacity);
636     EXPECT_EQ(c.GetStackCapacity(), capacity);
637 }
638 #endif
639
640 #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
641
642 // Issue 22: Memory corruption via operator=
643 // Fixed by making unimplemented assignment operator private.
644 //TEST(Document, Assignment) {
645 //  Document d1;
646 //  Document d2;
647 //  d1 = d2;
648 //}
649
650 #ifdef __clang__
651 RAPIDJSON_DIAG_POP
652 #endif