123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652 |
- // Tencent is pleased to support the open source community by making RapidJSON available.
- //
- // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
- //
- // Licensed under the MIT License (the "License"); you may not use this file except
- // in compliance with the License. You may obtain a copy of the License at
- //
- // http://opensource.org/licenses/MIT
- //
- // Unless required by applicable law or agreed to in writing, software distributed
- // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- // CONDITIONS OF ANY KIND, either express or implied. See the License for the
- // specific language governing permissions and limitations under the License.
- #include "unittest.h"
- #include "rapidjson/document.h"
- #include "rapidjson/writer.h"
- #include "rapidjson/filereadstream.h"
- #include "rapidjson/encodedstream.h"
- #include "rapidjson/stringbuffer.h"
- #include <sstream>
- #include <algorithm>
- #ifdef __clang__
- RAPIDJSON_DIAG_PUSH
- RAPIDJSON_DIAG_OFF(c++98-compat)
- RAPIDJSON_DIAG_OFF(missing-variable-declarations)
- #endif
- using namespace rapidjson;
- template <typename DocumentType>
- void ParseCheck(DocumentType& doc) {
- typedef typename DocumentType::ValueType ValueType;
- EXPECT_FALSE(doc.HasParseError());
- if (doc.HasParseError())
- printf("Error: %d at %zu\n", static_cast<int>(doc.GetParseError()), doc.GetErrorOffset());
- EXPECT_TRUE(static_cast<ParseResult>(doc));
- EXPECT_TRUE(doc.IsObject());
- EXPECT_TRUE(doc.HasMember("hello"));
- const ValueType& hello = doc["hello"];
- EXPECT_TRUE(hello.IsString());
- EXPECT_STREQ("world", hello.GetString());
- EXPECT_TRUE(doc.HasMember("t"));
- const ValueType& t = doc["t"];
- EXPECT_TRUE(t.IsTrue());
- EXPECT_TRUE(doc.HasMember("f"));
- const ValueType& f = doc["f"];
- EXPECT_TRUE(f.IsFalse());
- EXPECT_TRUE(doc.HasMember("n"));
- const ValueType& n = doc["n"];
- EXPECT_TRUE(n.IsNull());
- EXPECT_TRUE(doc.HasMember("i"));
- const ValueType& i = doc["i"];
- EXPECT_TRUE(i.IsNumber());
- EXPECT_EQ(123, i.GetInt());
- EXPECT_TRUE(doc.HasMember("pi"));
- const ValueType& pi = doc["pi"];
- EXPECT_TRUE(pi.IsNumber());
- EXPECT_DOUBLE_EQ(3.1416, pi.GetDouble());
- EXPECT_TRUE(doc.HasMember("a"));
- const ValueType& a = doc["a"];
- EXPECT_TRUE(a.IsArray());
- EXPECT_EQ(4u, a.Size());
- for (SizeType j = 0; j < 4; j++)
- EXPECT_EQ(j + 1, a[j].GetUint());
- }
- template <typename Allocator, typename StackAllocator>
- void ParseTest() {
- typedef GenericDocument<UTF8<>, Allocator, StackAllocator> DocumentType;
- DocumentType doc;
- const char* json = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
- doc.Parse(json);
- ParseCheck(doc);
- doc.SetNull();
- StringStream s(json);
- doc.template ParseStream<0>(s);
- ParseCheck(doc);
- doc.SetNull();
- char *buffer = strdup(json);
- doc.ParseInsitu(buffer);
- ParseCheck(doc);
- free(buffer);
- // Parse(const Ch*, size_t)
- size_t length = strlen(json);
- buffer = reinterpret_cast<char*>(malloc(length * 2));
- memcpy(buffer, json, length);
- memset(buffer + length, 'X', length);
- #if RAPIDJSON_HAS_STDSTRING
- std::string s2(buffer, length); // backup buffer
- #endif
- doc.SetNull();
- doc.Parse(buffer, length);
- free(buffer);
- ParseCheck(doc);
- #if RAPIDJSON_HAS_STDSTRING
- // Parse(std::string)
- doc.SetNull();
- doc.Parse(s2);
- ParseCheck(doc);
- #endif
- }
- TEST(Document, Parse) {
- ParseTest<MemoryPoolAllocator<>, CrtAllocator>();
- ParseTest<MemoryPoolAllocator<>, MemoryPoolAllocator<> >();
- ParseTest<CrtAllocator, MemoryPoolAllocator<> >();
- ParseTest<CrtAllocator, CrtAllocator>();
- }
- TEST(Document, UnchangedOnParseError) {
- Document doc;
- doc.SetArray().PushBack(0, doc.GetAllocator());
- ParseResult err = doc.Parse("{]");
- EXPECT_TRUE(doc.HasParseError());
- EXPECT_EQ(err.Code(), doc.GetParseError());
- EXPECT_EQ(err.Offset(), doc.GetErrorOffset());
- EXPECT_TRUE(doc.IsArray());
- EXPECT_EQ(doc.Size(), 1u);
- err = doc.Parse("{}");
- EXPECT_FALSE(doc.HasParseError());
- EXPECT_FALSE(err.IsError());
- EXPECT_EQ(err.Code(), doc.GetParseError());
- EXPECT_EQ(err.Offset(), doc.GetErrorOffset());
- EXPECT_TRUE(doc.IsObject());
- EXPECT_EQ(doc.MemberCount(), 0u);
- }
- static FILE* OpenEncodedFile(const char* filename) {
- const char *paths[] = {
- "encodings",
- "bin/encodings",
- "../bin/encodings",
- "../../bin/encodings",
- "../../../bin/encodings"
- };
- char buffer[1024];
- for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
- sprintf(buffer, "%s/%s", paths[i], filename);
- FILE *fp = fopen(buffer, "rb");
- if (fp)
- return fp;
- }
- return 0;
- }
- TEST(Document, Parse_Encoding) {
- const char* json = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
- typedef GenericDocument<UTF16<> > DocumentType;
- DocumentType doc;
-
- // Parse<unsigned, SourceEncoding>(const SourceEncoding::Ch*)
- // doc.Parse<kParseDefaultFlags, UTF8<> >(json);
- // EXPECT_FALSE(doc.HasParseError());
- // EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world"));
- // Parse<unsigned, SourceEncoding>(const SourceEncoding::Ch*, size_t)
- size_t length = strlen(json);
- char* buffer = reinterpret_cast<char*>(malloc(length * 2));
- memcpy(buffer, json, length);
- memset(buffer + length, 'X', length);
- #if RAPIDJSON_HAS_STDSTRING
- std::string s2(buffer, length); // backup buffer
- #endif
- doc.SetNull();
- doc.Parse<kParseDefaultFlags, UTF8<> >(buffer, length);
- free(buffer);
- EXPECT_FALSE(doc.HasParseError());
- if (doc.HasParseError())
- printf("Error: %d at %zu\n", static_cast<int>(doc.GetParseError()), doc.GetErrorOffset());
- EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world"));
- #if RAPIDJSON_HAS_STDSTRING
- // Parse<unsigned, SourceEncoding>(std::string)
- doc.SetNull();
- #if defined(_MSC_VER) && _MSC_VER < 1800
- doc.Parse<kParseDefaultFlags, UTF8<> >(s2.c_str()); // VS2010 or below cannot handle templated function overloading. Use const char* instead.
- #else
- doc.Parse<kParseDefaultFlags, UTF8<> >(s2);
- #endif
- EXPECT_FALSE(doc.HasParseError());
- EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world"));
- #endif
- }
- TEST(Document, ParseStream_EncodedInputStream) {
- // UTF8 -> UTF16
- FILE* fp = OpenEncodedFile("utf8.json");
- char buffer[256];
- FileReadStream bis(fp, buffer, sizeof(buffer));
- EncodedInputStream<UTF8<>, FileReadStream> eis(bis);
- GenericDocument<UTF16<> > d;
- d.ParseStream<0, UTF8<> >(eis);
- EXPECT_FALSE(d.HasParseError());
- fclose(fp);
- wchar_t expected[] = L"I can eat glass and it doesn't hurt me.";
- GenericValue<UTF16<> >& v = d[L"en"];
- EXPECT_TRUE(v.IsString());
- EXPECT_EQ(sizeof(expected) / sizeof(wchar_t) - 1, v.GetStringLength());
- EXPECT_EQ(0, StrCmp(expected, v.GetString()));
- // UTF16 -> UTF8 in memory
- StringBuffer bos;
- typedef EncodedOutputStream<UTF8<>, StringBuffer> OutputStream;
- OutputStream eos(bos, false); // Not writing BOM
- {
- Writer<OutputStream, UTF16<>, UTF8<> > writer(eos);
- d.Accept(writer);
- }
- // Condense the original file and compare.
- fp = OpenEncodedFile("utf8.json");
- FileReadStream is(fp, buffer, sizeof(buffer));
- Reader reader;
- StringBuffer bos2;
- Writer<StringBuffer> writer2(bos2);
- reader.Parse(is, writer2);
- fclose(fp);
- EXPECT_EQ(bos.GetSize(), bos2.GetSize());
- EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize()));
- }
- TEST(Document, ParseStream_AutoUTFInputStream) {
- // Any -> UTF8
- FILE* fp = OpenEncodedFile("utf32be.json");
- char buffer[256];
- FileReadStream bis(fp, buffer, sizeof(buffer));
- AutoUTFInputStream<unsigned, FileReadStream> eis(bis);
- Document d;
- d.ParseStream<0, AutoUTF<unsigned> >(eis);
- EXPECT_FALSE(d.HasParseError());
- fclose(fp);
- char expected[] = "I can eat glass and it doesn't hurt me.";
- Value& v = d["en"];
- EXPECT_TRUE(v.IsString());
- EXPECT_EQ(sizeof(expected) - 1, v.GetStringLength());
- EXPECT_EQ(0, StrCmp(expected, v.GetString()));
- // UTF8 -> UTF8 in memory
- StringBuffer bos;
- Writer<StringBuffer> writer(bos);
- d.Accept(writer);
- // Condense the original file and compare.
- fp = OpenEncodedFile("utf8.json");
- FileReadStream is(fp, buffer, sizeof(buffer));
- Reader reader;
- StringBuffer bos2;
- Writer<StringBuffer> writer2(bos2);
- reader.Parse(is, writer2);
- fclose(fp);
- EXPECT_EQ(bos.GetSize(), bos2.GetSize());
- EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize()));
- }
- TEST(Document, Swap) {
- Document d1;
- Document::AllocatorType& a = d1.GetAllocator();
- d1.SetArray().PushBack(1, a).PushBack(2, a);
- Value o;
- o.SetObject().AddMember("a", 1, a);
- // Swap between Document and Value
- // d1.Swap(o); // doesn't compile
- o.Swap(d1);
- EXPECT_TRUE(d1.IsObject());
- EXPECT_TRUE(o.IsArray());
- // Swap between Document and Document
- Document d2;
- d2.SetArray().PushBack(3, a);
- d1.Swap(d2);
- EXPECT_TRUE(d1.IsArray());
- EXPECT_TRUE(d2.IsObject());
- EXPECT_EQ(&d2.GetAllocator(), &a);
- // reset value
- Value().Swap(d1);
- EXPECT_TRUE(d1.IsNull());
- // reset document, including allocator
- Document().Swap(d2);
- EXPECT_TRUE(d2.IsNull());
- EXPECT_NE(&d2.GetAllocator(), &a);
- // testing std::swap compatibility
- d1.SetBool(true);
- using std::swap;
- swap(d1, d2);
- EXPECT_TRUE(d1.IsNull());
- EXPECT_TRUE(d2.IsTrue());
- swap(o, d2);
- EXPECT_TRUE(o.IsTrue());
- EXPECT_TRUE(d2.IsArray());
- }
- // This should be slow due to assignment in inner-loop.
- struct OutputStringStream : public std::ostringstream {
- typedef char Ch;
- virtual ~OutputStringStream();
- void Put(char c) {
- put(c);
- }
- void Flush() {}
- };
- OutputStringStream::~OutputStringStream() {}
- TEST(Document, AcceptWriter) {
- Document doc;
- doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ");
- OutputStringStream os;
- Writer<OutputStringStream> writer(os);
- doc.Accept(writer);
- EXPECT_EQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3,4]}", os.str());
- }
- TEST(Document, UserBuffer) {
- typedef GenericDocument<UTF8<>, MemoryPoolAllocator<>, MemoryPoolAllocator<> > DocumentType;
- char valueBuffer[4096];
- char parseBuffer[1024];
- MemoryPoolAllocator<> valueAllocator(valueBuffer, sizeof(valueBuffer));
- MemoryPoolAllocator<> parseAllocator(parseBuffer, sizeof(parseBuffer));
- DocumentType doc(&valueAllocator, sizeof(parseBuffer) / 2, &parseAllocator);
- doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ");
- EXPECT_FALSE(doc.HasParseError());
- EXPECT_LE(valueAllocator.Size(), sizeof(valueBuffer));
- EXPECT_LE(parseAllocator.Size(), sizeof(parseBuffer));
- // Cover MemoryPoolAllocator::Capacity()
- EXPECT_LE(valueAllocator.Size(), valueAllocator.Capacity());
- EXPECT_LE(parseAllocator.Size(), parseAllocator.Capacity());
- }
- // Issue 226: Value of string type should not point to NULL
- TEST(Document, AssertAcceptInvalidNameType) {
- Document doc;
- doc.SetObject();
- doc.AddMember("a", 0, doc.GetAllocator());
- doc.FindMember("a")->name.SetNull(); // Change name to non-string type.
- OutputStringStream os;
- Writer<OutputStringStream> writer(os);
- ASSERT_THROW(doc.Accept(writer), AssertException);
- }
- // Issue 44: SetStringRaw doesn't work with wchar_t
- TEST(Document, UTF16_Document) {
- GenericDocument< UTF16<> > json;
- json.Parse<kParseValidateEncodingFlag>(L"[{\"created_at\":\"Wed Oct 30 17:13:20 +0000 2012\"}]");
- ASSERT_TRUE(json.IsArray());
- GenericValue< UTF16<> >& v = json[0];
- ASSERT_TRUE(v.IsObject());
- GenericValue< UTF16<> >& s = v[L"created_at"];
- ASSERT_TRUE(s.IsString());
- EXPECT_EQ(0, memcmp(L"Wed Oct 30 17:13:20 +0000 2012", s.GetString(), (s.GetStringLength() + 1) * sizeof(wchar_t)));
- }
- #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- #if 0 // Many old compiler does not support these. Turn it off temporaily.
- #include <type_traits>
- TEST(Document, Traits) {
- static_assert(std::is_constructible<Document>::value, "");
- static_assert(std::is_default_constructible<Document>::value, "");
- #ifndef _MSC_VER
- static_assert(!std::is_copy_constructible<Document>::value, "");
- #endif
- static_assert(std::is_move_constructible<Document>::value, "");
- static_assert(!std::is_nothrow_constructible<Document>::value, "");
- static_assert(!std::is_nothrow_default_constructible<Document>::value, "");
- #ifndef _MSC_VER
- static_assert(!std::is_nothrow_copy_constructible<Document>::value, "");
- static_assert(std::is_nothrow_move_constructible<Document>::value, "");
- #endif
- static_assert(std::is_assignable<Document,Document>::value, "");
- #ifndef _MSC_VER
- static_assert(!std::is_copy_assignable<Document>::value, "");
- #endif
- static_assert(std::is_move_assignable<Document>::value, "");
- #ifndef _MSC_VER
- static_assert(std::is_nothrow_assignable<Document, Document>::value, "");
- #endif
- static_assert(!std::is_nothrow_copy_assignable<Document>::value, "");
- #ifndef _MSC_VER
- static_assert(std::is_nothrow_move_assignable<Document>::value, "");
- #endif
- static_assert( std::is_destructible<Document>::value, "");
- #ifndef _MSC_VER
- static_assert(std::is_nothrow_destructible<Document>::value, "");
- #endif
- }
- #endif
- template <typename Allocator>
- struct DocumentMove: public ::testing::Test {
- };
- typedef ::testing::Types< CrtAllocator, MemoryPoolAllocator<> > MoveAllocatorTypes;
- TYPED_TEST_CASE(DocumentMove, MoveAllocatorTypes);
- TYPED_TEST(DocumentMove, MoveConstructor) {
- typedef TypeParam Allocator;
- typedef GenericDocument<UTF8<>, Allocator> D;
- Allocator allocator;
- D a(&allocator);
- a.Parse("[\"one\", \"two\", \"three\"]");
- EXPECT_FALSE(a.HasParseError());
- EXPECT_TRUE(a.IsArray());
- EXPECT_EQ(3u, a.Size());
- EXPECT_EQ(&a.GetAllocator(), &allocator);
- // Document b(a); // does not compile (!is_copy_constructible)
- D b(std::move(a));
- EXPECT_TRUE(a.IsNull());
- EXPECT_TRUE(b.IsArray());
- EXPECT_EQ(3u, b.Size());
- EXPECT_THROW(a.GetAllocator(), AssertException);
- EXPECT_EQ(&b.GetAllocator(), &allocator);
- b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}");
- EXPECT_FALSE(b.HasParseError());
- EXPECT_TRUE(b.IsObject());
- EXPECT_EQ(2u, b.MemberCount());
- // Document c = a; // does not compile (!is_copy_constructible)
- D c = std::move(b);
- EXPECT_TRUE(b.IsNull());
- EXPECT_TRUE(c.IsObject());
- EXPECT_EQ(2u, c.MemberCount());
- EXPECT_THROW(b.GetAllocator(), AssertException);
- EXPECT_EQ(&c.GetAllocator(), &allocator);
- }
- TYPED_TEST(DocumentMove, MoveConstructorParseError) {
- typedef TypeParam Allocator;
- typedef GenericDocument<UTF8<>, Allocator> D;
- ParseResult noError;
- D a;
- a.Parse("{ 4 = 4]");
- ParseResult error(a.GetParseError(), a.GetErrorOffset());
- EXPECT_TRUE(a.HasParseError());
- EXPECT_NE(error.Code(), noError.Code());
- EXPECT_NE(error.Offset(), noError.Offset());
- D b(std::move(a));
- EXPECT_FALSE(a.HasParseError());
- EXPECT_TRUE(b.HasParseError());
- EXPECT_EQ(a.GetParseError(), noError.Code());
- EXPECT_EQ(b.GetParseError(), error.Code());
- EXPECT_EQ(a.GetErrorOffset(), noError.Offset());
- EXPECT_EQ(b.GetErrorOffset(), error.Offset());
- D c(std::move(b));
- EXPECT_FALSE(b.HasParseError());
- EXPECT_TRUE(c.HasParseError());
- EXPECT_EQ(b.GetParseError(), noError.Code());
- EXPECT_EQ(c.GetParseError(), error.Code());
- EXPECT_EQ(b.GetErrorOffset(), noError.Offset());
- EXPECT_EQ(c.GetErrorOffset(), error.Offset());
- }
- // This test does not properly use parsing, just for testing.
- // It must call ClearStack() explicitly to prevent memory leak.
- // But here we cannot as ClearStack() is private.
- #if 0
- TYPED_TEST(DocumentMove, MoveConstructorStack) {
- typedef TypeParam Allocator;
- typedef UTF8<> Encoding;
- typedef GenericDocument<Encoding, Allocator> Document;
- Document a;
- size_t defaultCapacity = a.GetStackCapacity();
- // Trick Document into getting GetStackCapacity() to return non-zero
- typedef GenericReader<Encoding, Encoding, Allocator> Reader;
- Reader reader(&a.GetAllocator());
- GenericStringStream<Encoding> is("[\"one\", \"two\", \"three\"]");
- reader.template Parse<kParseDefaultFlags>(is, a);
- size_t capacity = a.GetStackCapacity();
- EXPECT_GT(capacity, 0u);
- Document b(std::move(a));
- EXPECT_EQ(a.GetStackCapacity(), defaultCapacity);
- EXPECT_EQ(b.GetStackCapacity(), capacity);
- Document c = std::move(b);
- EXPECT_EQ(b.GetStackCapacity(), defaultCapacity);
- EXPECT_EQ(c.GetStackCapacity(), capacity);
- }
- #endif
- TYPED_TEST(DocumentMove, MoveAssignment) {
- typedef TypeParam Allocator;
- typedef GenericDocument<UTF8<>, Allocator> D;
- Allocator allocator;
- D a(&allocator);
- a.Parse("[\"one\", \"two\", \"three\"]");
- EXPECT_FALSE(a.HasParseError());
- EXPECT_TRUE(a.IsArray());
- EXPECT_EQ(3u, a.Size());
- EXPECT_EQ(&a.GetAllocator(), &allocator);
- // Document b; b = a; // does not compile (!is_copy_assignable)
- D b;
- b = std::move(a);
- EXPECT_TRUE(a.IsNull());
- EXPECT_TRUE(b.IsArray());
- EXPECT_EQ(3u, b.Size());
- EXPECT_THROW(a.GetAllocator(), AssertException);
- EXPECT_EQ(&b.GetAllocator(), &allocator);
- b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}");
- EXPECT_FALSE(b.HasParseError());
- EXPECT_TRUE(b.IsObject());
- EXPECT_EQ(2u, b.MemberCount());
- // Document c; c = a; // does not compile (see static_assert)
- D c;
- c = std::move(b);
- EXPECT_TRUE(b.IsNull());
- EXPECT_TRUE(c.IsObject());
- EXPECT_EQ(2u, c.MemberCount());
- EXPECT_THROW(b.GetAllocator(), AssertException);
- EXPECT_EQ(&c.GetAllocator(), &allocator);
- }
- TYPED_TEST(DocumentMove, MoveAssignmentParseError) {
- typedef TypeParam Allocator;
- typedef GenericDocument<UTF8<>, Allocator> D;
- ParseResult noError;
- D a;
- a.Parse("{ 4 = 4]");
- ParseResult error(a.GetParseError(), a.GetErrorOffset());
- EXPECT_TRUE(a.HasParseError());
- EXPECT_NE(error.Code(), noError.Code());
- EXPECT_NE(error.Offset(), noError.Offset());
- D b;
- b = std::move(a);
- EXPECT_FALSE(a.HasParseError());
- EXPECT_TRUE(b.HasParseError());
- EXPECT_EQ(a.GetParseError(), noError.Code());
- EXPECT_EQ(b.GetParseError(), error.Code());
- EXPECT_EQ(a.GetErrorOffset(), noError.Offset());
- EXPECT_EQ(b.GetErrorOffset(), error.Offset());
- D c;
- c = std::move(b);
- EXPECT_FALSE(b.HasParseError());
- EXPECT_TRUE(c.HasParseError());
- EXPECT_EQ(b.GetParseError(), noError.Code());
- EXPECT_EQ(c.GetParseError(), error.Code());
- EXPECT_EQ(b.GetErrorOffset(), noError.Offset());
- EXPECT_EQ(c.GetErrorOffset(), error.Offset());
- }
- // This test does not properly use parsing, just for testing.
- // It must call ClearStack() explicitly to prevent memory leak.
- // But here we cannot as ClearStack() is private.
- #if 0
- TYPED_TEST(DocumentMove, MoveAssignmentStack) {
- typedef TypeParam Allocator;
- typedef UTF8<> Encoding;
- typedef GenericDocument<Encoding, Allocator> D;
- D a;
- size_t defaultCapacity = a.GetStackCapacity();
- // Trick Document into getting GetStackCapacity() to return non-zero
- typedef GenericReader<Encoding, Encoding, Allocator> Reader;
- Reader reader(&a.GetAllocator());
- GenericStringStream<Encoding> is("[\"one\", \"two\", \"three\"]");
- reader.template Parse<kParseDefaultFlags>(is, a);
- size_t capacity = a.GetStackCapacity();
- EXPECT_GT(capacity, 0u);
- D b;
- b = std::move(a);
- EXPECT_EQ(a.GetStackCapacity(), defaultCapacity);
- EXPECT_EQ(b.GetStackCapacity(), capacity);
- D c;
- c = std::move(b);
- EXPECT_EQ(b.GetStackCapacity(), defaultCapacity);
- EXPECT_EQ(c.GetStackCapacity(), capacity);
- }
- #endif
- #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
- // Issue 22: Memory corruption via operator=
- // Fixed by making unimplemented assignment operator private.
- //TEST(Document, Assignment) {
- // Document d1;
- // Document d2;
- // d1 = d2;
- //}
- #ifdef __clang__
- RAPIDJSON_DIAG_POP
- #endif
|