"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "test/unittest/documenttest.cpp" between
rapidjson-1.0.2.tar.gz and rapidjson-1.1.0.tar.gz

About: RapidJSON is a fast JSON parser/generator for C++ with both SAX/DOM style API.

documenttest.cpp  (rapidjson-1.0.2):documenttest.cpp  (rapidjson-1.1.0)
skipping to change at line 22 skipping to change at line 22
// CONDITIONS OF ANY KIND, either express or implied. See the License for the // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#include "unittest.h" #include "unittest.h"
#include "rapidjson/document.h" #include "rapidjson/document.h"
#include "rapidjson/writer.h" #include "rapidjson/writer.h"
#include "rapidjson/filereadstream.h" #include "rapidjson/filereadstream.h"
#include "rapidjson/encodedstream.h" #include "rapidjson/encodedstream.h"
#include "rapidjson/stringbuffer.h" #include "rapidjson/stringbuffer.h"
#include <sstream> #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; using namespace rapidjson;
template <typename DocumentType> template <typename DocumentType>
void ParseCheck(DocumentType& doc) { void ParseCheck(DocumentType& doc) {
typedef typename DocumentType::ValueType ValueType; typedef typename DocumentType::ValueType ValueType;
EXPECT_FALSE(doc.HasParseError()); 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.IsObject());
EXPECT_TRUE(doc.HasMember("hello")); EXPECT_TRUE(doc.HasMember("hello"));
const ValueType& hello = doc["hello"]; const ValueType& hello = doc["hello"];
EXPECT_TRUE(hello.IsString()); EXPECT_TRUE(hello.IsString());
EXPECT_STREQ("world", hello.GetString()); EXPECT_STREQ("world", hello.GetString());
EXPECT_TRUE(doc.HasMember("t")); EXPECT_TRUE(doc.HasMember("t"));
const ValueType& t = doc["t"]; const ValueType& t = doc["t"];
skipping to change at line 64 skipping to change at line 74
EXPECT_TRUE(doc.HasMember("pi")); EXPECT_TRUE(doc.HasMember("pi"));
const ValueType& pi = doc["pi"]; const ValueType& pi = doc["pi"];
EXPECT_TRUE(pi.IsNumber()); EXPECT_TRUE(pi.IsNumber());
EXPECT_DOUBLE_EQ(3.1416, pi.GetDouble()); EXPECT_DOUBLE_EQ(3.1416, pi.GetDouble());
EXPECT_TRUE(doc.HasMember("a")); EXPECT_TRUE(doc.HasMember("a"));
const ValueType& a = doc["a"]; const ValueType& a = doc["a"];
EXPECT_TRUE(a.IsArray()); EXPECT_TRUE(a.IsArray());
EXPECT_EQ(4u, a.Size()); EXPECT_EQ(4u, a.Size());
for (SizeType i = 0; i < 4; i++) for (SizeType j = 0; j < 4; j++)
EXPECT_EQ(i + 1, a[i].GetUint()); EXPECT_EQ(j + 1, a[j].GetUint());
} }
template <typename Allocator, typename StackAllocator> template <typename Allocator, typename StackAllocator>
void ParseTest() { void ParseTest() {
typedef GenericDocument<UTF8<>, Allocator, StackAllocator> DocumentType; typedef GenericDocument<UTF8<>, Allocator, StackAllocator> DocumentType;
DocumentType doc; DocumentType doc;
const char* json = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } "; const char* json = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
doc.Parse(json); doc.Parse(json);
skipping to change at line 88 skipping to change at line 98
doc.SetNull(); doc.SetNull();
StringStream s(json); StringStream s(json);
doc.template ParseStream<0>(s); doc.template ParseStream<0>(s);
ParseCheck(doc); ParseCheck(doc);
doc.SetNull(); doc.SetNull();
char *buffer = strdup(json); char *buffer = strdup(json);
doc.ParseInsitu(buffer); doc.ParseInsitu(buffer);
ParseCheck(doc); ParseCheck(doc);
free(buffer); 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) { TEST(Document, Parse) {
ParseTest<MemoryPoolAllocator<>, CrtAllocator>(); ParseTest<MemoryPoolAllocator<>, CrtAllocator>();
ParseTest<MemoryPoolAllocator<>, MemoryPoolAllocator<> >(); ParseTest<MemoryPoolAllocator<>, MemoryPoolAllocator<> >();
ParseTest<CrtAllocator, MemoryPoolAllocator<> >(); ParseTest<CrtAllocator, MemoryPoolAllocator<> >();
ParseTest<CrtAllocator, CrtAllocator>(); 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) { static FILE* OpenEncodedFile(const char* filename) {
const char *paths[] = { const char *paths[] = {
"encodings/%s", "encodings",
"bin/encodings/%s", "bin/encodings",
"../bin/encodings/%s", "../bin/encodings",
"../../bin/encodings/%s", "../../bin/encodings",
"../../../bin/encodings/%s" "../../../bin/encodings"
}; };
char buffer[1024]; char buffer[1024];
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
sprintf(buffer, paths[i], filename); sprintf(buffer, "%s/%s", paths[i], filename);
FILE *fp = fopen(buffer, "rb"); FILE *fp = fopen(buffer, "rb");
if (fp) if (fp)
return fp; return fp;
} }
return 0; 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 canno
t 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) { TEST(Document, ParseStream_EncodedInputStream) {
// UTF8 -> UTF16 // UTF8 -> UTF16
FILE* fp = OpenEncodedFile("utf8.json"); FILE* fp = OpenEncodedFile("utf8.json");
char buffer[256]; char buffer[256];
FileReadStream bis(fp, buffer, sizeof(buffer)); FileReadStream bis(fp, buffer, sizeof(buffer));
EncodedInputStream<UTF8<>, FileReadStream> eis(bis); EncodedInputStream<UTF8<>, FileReadStream> eis(bis);
GenericDocument<UTF16<> > d; GenericDocument<UTF16<> > d;
d.ParseStream<0, UTF8<> >(eis); d.ParseStream<0, UTF8<> >(eis);
EXPECT_FALSE(d.HasParseError()); EXPECT_FALSE(d.HasParseError());
skipping to change at line 138 skipping to change at line 229
wchar_t expected[] = L"I can eat glass and it doesn't hurt me."; wchar_t expected[] = L"I can eat glass and it doesn't hurt me.";
GenericValue<UTF16<> >& v = d[L"en"]; GenericValue<UTF16<> >& v = d[L"en"];
EXPECT_TRUE(v.IsString()); EXPECT_TRUE(v.IsString());
EXPECT_EQ(sizeof(expected) / sizeof(wchar_t) - 1, v.GetStringLength()); EXPECT_EQ(sizeof(expected) / sizeof(wchar_t) - 1, v.GetStringLength());
EXPECT_EQ(0, StrCmp(expected, v.GetString())); EXPECT_EQ(0, StrCmp(expected, v.GetString()));
// UTF16 -> UTF8 in memory // UTF16 -> UTF8 in memory
StringBuffer bos; StringBuffer bos;
typedef EncodedOutputStream<UTF8<>, StringBuffer> OutputStream; typedef EncodedOutputStream<UTF8<>, StringBuffer> OutputStream;
OutputStream eos(bos, false); // Not writing BOM OutputStream eos(bos, false); // Not writing BOM
Writer<OutputStream, UTF16<>, UTF8<> > writer(eos);
d.Accept(writer);
{ {
// Condense the original file and compare. Writer<OutputStream, UTF16<>, UTF8<> > writer(eos);
FILE *fp = OpenEncodedFile("utf8.json"); d.Accept(writer);
FileReadStream is(fp, buffer, sizeof(buffer));
Reader reader;
StringBuffer bos2;
Writer<StringBuffer> writer(bos2);
reader.Parse(is, writer);
fclose(fp);
EXPECT_EQ(bos.GetSize(), bos2.GetSize());
EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize()));
} }
// 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) { TEST(Document, ParseStream_AutoUTFInputStream) {
// Any -> UTF8 // Any -> UTF8
FILE* fp = OpenEncodedFile("utf32be.json"); FILE* fp = OpenEncodedFile("utf32be.json");
char buffer[256]; char buffer[256];
FileReadStream bis(fp, buffer, sizeof(buffer)); FileReadStream bis(fp, buffer, sizeof(buffer));
AutoUTFInputStream<unsigned, FileReadStream> eis(bis); AutoUTFInputStream<unsigned, FileReadStream> eis(bis);
Document d; Document d;
skipping to change at line 180 skipping to change at line 271
Value& v = d["en"]; Value& v = d["en"];
EXPECT_TRUE(v.IsString()); EXPECT_TRUE(v.IsString());
EXPECT_EQ(sizeof(expected) - 1, v.GetStringLength()); EXPECT_EQ(sizeof(expected) - 1, v.GetStringLength());
EXPECT_EQ(0, StrCmp(expected, v.GetString())); EXPECT_EQ(0, StrCmp(expected, v.GetString()));
// UTF8 -> UTF8 in memory // UTF8 -> UTF8 in memory
StringBuffer bos; StringBuffer bos;
Writer<StringBuffer> writer(bos); Writer<StringBuffer> writer(bos);
d.Accept(writer); d.Accept(writer);
{ // Condense the original file and compare.
// Condense the original file and compare. fp = OpenEncodedFile("utf8.json");
FILE *fp = OpenEncodedFile("utf8.json"); FileReadStream is(fp, buffer, sizeof(buffer));
FileReadStream is(fp, buffer, sizeof(buffer)); Reader reader;
Reader reader; StringBuffer bos2;
StringBuffer bos2; Writer<StringBuffer> writer2(bos2);
Writer<StringBuffer> writer(bos2); reader.Parse(is, writer2);
reader.Parse(is, writer); fclose(fp);
fclose(fp);
EXPECT_EQ(bos.GetSize(), bos2.GetSize()); EXPECT_EQ(bos.GetSize(), bos2.GetSize());
EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize())); EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize()));
}
} }
TEST(Document, Swap) { TEST(Document, Swap) {
Document d1; Document d1;
Document::AllocatorType& a = d1.GetAllocator(); Document::AllocatorType& a = d1.GetAllocator();
d1.SetArray().PushBack(1, a).PushBack(2, a); d1.SetArray().PushBack(1, a).PushBack(2, a);
Value o; Value o;
o.SetObject().AddMember("a", 1, a); o.SetObject().AddMember("a", 1, a);
// Swap between Document and Value // Swap between Document and Value
d1.Swap(o); // d1.Swap(o); // doesn't compile
o.Swap(d1);
EXPECT_TRUE(d1.IsObject()); EXPECT_TRUE(d1.IsObject());
EXPECT_TRUE(o.IsArray()); EXPECT_TRUE(o.IsArray());
// Swap between Document and Document // Swap between Document and Document
Document d2; Document d2;
d2.SetArray().PushBack(3, a); d2.SetArray().PushBack(3, a);
d1.Swap(d2); d1.Swap(d2);
EXPECT_TRUE(d1.IsArray()); EXPECT_TRUE(d1.IsArray());
EXPECT_TRUE(d2.IsObject()); 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. // This should be slow due to assignment in inner-loop.
struct OutputStringStream : public std::ostringstream { struct OutputStringStream : public std::ostringstream {
typedef char Ch; typedef char Ch;
virtual ~OutputStringStream();
void Put(char c) { void Put(char c) {
put(c); put(c);
} }
void Flush() {} void Flush() {}
}; };
OutputStringStream::~OutputStringStream() {}
TEST(Document, AcceptWriter) { TEST(Document, AcceptWriter) {
Document doc; Document doc;
doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": nu ll, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } "); doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": nu ll, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ");
OutputStringStream os; OutputStringStream os;
Writer<OutputStringStream> writer(os); Writer<OutputStringStream> writer(os);
doc.Accept(writer); 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()); EXPECT_EQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123, \"pi\":3.1416,\"a\":[1,2,3,4]}", os.str());
} }
skipping to change at line 284 skipping to change at line 399
ASSERT_TRUE(v.IsObject()); ASSERT_TRUE(v.IsObject());
GenericValue< UTF16<> >& s = v[L"created_at"]; GenericValue< UTF16<> >& s = v[L"created_at"];
ASSERT_TRUE(s.IsString()); ASSERT_TRUE(s.IsString());
EXPECT_EQ(0, memcmp(L"Wed Oct 30 17:13:20 +0000 2012", s.GetString(), (s.Get StringLength() + 1) * sizeof(wchar_t))); EXPECT_EQ(0, memcmp(L"Wed Oct 30 17:13:20 +0000 2012", s.GetString(), (s.Get StringLength() + 1) * sizeof(wchar_t)));
} }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
#if 0 // Many old compiler does not support these. Turn it off temporaily.
#include <type_traits> #include <type_traits>
TEST(Document, Traits) { TEST(Document, Traits) {
static_assert(std::is_constructible<Document>::value, ""); static_assert(std::is_constructible<Document>::value, "");
static_assert(std::is_default_constructible<Document>::value, ""); static_assert(std::is_default_constructible<Document>::value, "");
#ifndef _MSC_VER #ifndef _MSC_VER
static_assert(!std::is_copy_constructible<Document>::value, ""); static_assert(!std::is_copy_constructible<Document>::value, "");
#endif #endif
static_assert(std::is_move_constructible<Document>::value, ""); static_assert(std::is_move_constructible<Document>::value, "");
skipping to change at line 321 skipping to change at line 438
#ifndef _MSC_VER #ifndef _MSC_VER
static_assert(std::is_nothrow_move_assignable<Document>::value, ""); static_assert(std::is_nothrow_move_assignable<Document>::value, "");
#endif #endif
static_assert( std::is_destructible<Document>::value, ""); static_assert( std::is_destructible<Document>::value, "");
#ifndef _MSC_VER #ifndef _MSC_VER
static_assert(std::is_nothrow_destructible<Document>::value, ""); static_assert(std::is_nothrow_destructible<Document>::value, "");
#endif #endif
} }
#endif
template <typename Allocator> template <typename Allocator>
struct DocumentMove: public ::testing::Test { struct DocumentMove: public ::testing::Test {
}; };
typedef ::testing::Types< CrtAllocator, MemoryPoolAllocator<> > MoveAllocatorTyp es; typedef ::testing::Types< CrtAllocator, MemoryPoolAllocator<> > MoveAllocatorTyp es;
TYPED_TEST_CASE(DocumentMove, MoveAllocatorTypes); TYPED_TEST_CASE(DocumentMove, MoveAllocatorTypes);
TYPED_TEST(DocumentMove, MoveConstructor) { TYPED_TEST(DocumentMove, MoveConstructor) {
typedef TypeParam Allocator; typedef TypeParam Allocator;
typedef GenericDocument<UTF8<>, Allocator> Document; typedef GenericDocument<UTF8<>, Allocator> D;
Allocator allocator; Allocator allocator;
Document a(&allocator); D a(&allocator);
a.Parse("[\"one\", \"two\", \"three\"]"); a.Parse("[\"one\", \"two\", \"three\"]");
EXPECT_FALSE(a.HasParseError()); EXPECT_FALSE(a.HasParseError());
EXPECT_TRUE(a.IsArray()); EXPECT_TRUE(a.IsArray());
EXPECT_EQ(3u, a.Size()); EXPECT_EQ(3u, a.Size());
EXPECT_EQ(&a.GetAllocator(), &allocator); EXPECT_EQ(&a.GetAllocator(), &allocator);
// Document b(a); // does not compile (!is_copy_constructible) // Document b(a); // does not compile (!is_copy_constructible)
Document b(std::move(a)); D b(std::move(a));
EXPECT_TRUE(a.IsNull()); EXPECT_TRUE(a.IsNull());
EXPECT_TRUE(b.IsArray()); EXPECT_TRUE(b.IsArray());
EXPECT_EQ(3u, b.Size()); EXPECT_EQ(3u, b.Size());
EXPECT_EQ(&a.GetAllocator(), (void*)0); EXPECT_THROW(a.GetAllocator(), AssertException);
EXPECT_EQ(&b.GetAllocator(), &allocator); EXPECT_EQ(&b.GetAllocator(), &allocator);
b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}"); b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}");
EXPECT_FALSE(b.HasParseError()); EXPECT_FALSE(b.HasParseError());
EXPECT_TRUE(b.IsObject()); EXPECT_TRUE(b.IsObject());
EXPECT_EQ(2u, b.MemberCount()); EXPECT_EQ(2u, b.MemberCount());
// Document c = a; // does not compile (!is_copy_constructible) // Document c = a; // does not compile (!is_copy_constructible)
Document c = std::move(b); D c = std::move(b);
EXPECT_TRUE(b.IsNull()); EXPECT_TRUE(b.IsNull());
EXPECT_TRUE(c.IsObject()); EXPECT_TRUE(c.IsObject());
EXPECT_EQ(2u, c.MemberCount()); EXPECT_EQ(2u, c.MemberCount());
EXPECT_EQ(&b.GetAllocator(), (void*)0); EXPECT_THROW(b.GetAllocator(), AssertException);
EXPECT_EQ(&c.GetAllocator(), &allocator); EXPECT_EQ(&c.GetAllocator(), &allocator);
} }
TYPED_TEST(DocumentMove, MoveConstructorParseError) { TYPED_TEST(DocumentMove, MoveConstructorParseError) {
typedef TypeParam Allocator; typedef TypeParam Allocator;
typedef GenericDocument<UTF8<>, Allocator> Document; typedef GenericDocument<UTF8<>, Allocator> D;
ParseResult noError; ParseResult noError;
Document a; D a;
a.Parse("{ 4 = 4]"); a.Parse("{ 4 = 4]");
ParseResult error(a.GetParseError(), a.GetErrorOffset()); ParseResult error(a.GetParseError(), a.GetErrorOffset());
EXPECT_TRUE(a.HasParseError()); EXPECT_TRUE(a.HasParseError());
EXPECT_NE(error.Code(), noError.Code()); EXPECT_NE(error.Code(), noError.Code());
EXPECT_NE(error.Offset(), noError.Offset()); EXPECT_NE(error.Offset(), noError.Offset());
Document b(std::move(a)); D b(std::move(a));
EXPECT_FALSE(a.HasParseError()); EXPECT_FALSE(a.HasParseError());
EXPECT_TRUE(b.HasParseError()); EXPECT_TRUE(b.HasParseError());
EXPECT_EQ(a.GetParseError(), noError.Code()); EXPECT_EQ(a.GetParseError(), noError.Code());
EXPECT_EQ(b.GetParseError(), error.Code()); EXPECT_EQ(b.GetParseError(), error.Code());
EXPECT_EQ(a.GetErrorOffset(), noError.Offset()); EXPECT_EQ(a.GetErrorOffset(), noError.Offset());
EXPECT_EQ(b.GetErrorOffset(), error.Offset()); EXPECT_EQ(b.GetErrorOffset(), error.Offset());
Document c(std::move(b)); D c(std::move(b));
EXPECT_FALSE(b.HasParseError()); EXPECT_FALSE(b.HasParseError());
EXPECT_TRUE(c.HasParseError()); EXPECT_TRUE(c.HasParseError());
EXPECT_EQ(b.GetParseError(), noError.Code()); EXPECT_EQ(b.GetParseError(), noError.Code());
EXPECT_EQ(c.GetParseError(), error.Code()); EXPECT_EQ(c.GetParseError(), error.Code());
EXPECT_EQ(b.GetErrorOffset(), noError.Offset()); EXPECT_EQ(b.GetErrorOffset(), noError.Offset());
EXPECT_EQ(c.GetErrorOffset(), error.Offset()); EXPECT_EQ(c.GetErrorOffset(), error.Offset());
} }
// This test does not properly use parsing, just for testing. // This test does not properly use parsing, just for testing.
// It must call ClearStack() explicitly to prevent memory leak. // It must call ClearStack() explicitly to prevent memory leak.
skipping to change at line 423 skipping to change at line 542
EXPECT_EQ(b.GetStackCapacity(), capacity); EXPECT_EQ(b.GetStackCapacity(), capacity);
Document c = std::move(b); Document c = std::move(b);
EXPECT_EQ(b.GetStackCapacity(), defaultCapacity); EXPECT_EQ(b.GetStackCapacity(), defaultCapacity);
EXPECT_EQ(c.GetStackCapacity(), capacity); EXPECT_EQ(c.GetStackCapacity(), capacity);
} }
#endif #endif
TYPED_TEST(DocumentMove, MoveAssignment) { TYPED_TEST(DocumentMove, MoveAssignment) {
typedef TypeParam Allocator; typedef TypeParam Allocator;
typedef GenericDocument<UTF8<>, Allocator> Document; typedef GenericDocument<UTF8<>, Allocator> D;
Allocator allocator; Allocator allocator;
Document a(&allocator); D a(&allocator);
a.Parse("[\"one\", \"two\", \"three\"]"); a.Parse("[\"one\", \"two\", \"three\"]");
EXPECT_FALSE(a.HasParseError()); EXPECT_FALSE(a.HasParseError());
EXPECT_TRUE(a.IsArray()); EXPECT_TRUE(a.IsArray());
EXPECT_EQ(3u, a.Size()); EXPECT_EQ(3u, a.Size());
EXPECT_EQ(&a.GetAllocator(), &allocator); EXPECT_EQ(&a.GetAllocator(), &allocator);
// Document b; b = a; // does not compile (!is_copy_assignable) // Document b; b = a; // does not compile (!is_copy_assignable)
Document b; D b;
b = std::move(a); b = std::move(a);
EXPECT_TRUE(a.IsNull()); EXPECT_TRUE(a.IsNull());
EXPECT_TRUE(b.IsArray()); EXPECT_TRUE(b.IsArray());
EXPECT_EQ(3u, b.Size()); EXPECT_EQ(3u, b.Size());
EXPECT_EQ(&a.GetAllocator(), (void*)0); EXPECT_THROW(a.GetAllocator(), AssertException);
EXPECT_EQ(&b.GetAllocator(), &allocator); EXPECT_EQ(&b.GetAllocator(), &allocator);
b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}"); b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}");
EXPECT_FALSE(b.HasParseError()); EXPECT_FALSE(b.HasParseError());
EXPECT_TRUE(b.IsObject()); EXPECT_TRUE(b.IsObject());
EXPECT_EQ(2u, b.MemberCount()); EXPECT_EQ(2u, b.MemberCount());
// Document c; c = a; // does not compile (see static_assert) // Document c; c = a; // does not compile (see static_assert)
Document c; D c;
c = std::move(b); c = std::move(b);
EXPECT_TRUE(b.IsNull()); EXPECT_TRUE(b.IsNull());
EXPECT_TRUE(c.IsObject()); EXPECT_TRUE(c.IsObject());
EXPECT_EQ(2u, c.MemberCount()); EXPECT_EQ(2u, c.MemberCount());
EXPECT_EQ(&b.GetAllocator(), (void*)0); EXPECT_THROW(b.GetAllocator(), AssertException);
EXPECT_EQ(&c.GetAllocator(), &allocator); EXPECT_EQ(&c.GetAllocator(), &allocator);
} }
TYPED_TEST(DocumentMove, MoveAssignmentParseError) { TYPED_TEST(DocumentMove, MoveAssignmentParseError) {
typedef TypeParam Allocator; typedef TypeParam Allocator;
typedef GenericDocument<UTF8<>, Allocator> Document; typedef GenericDocument<UTF8<>, Allocator> D;
ParseResult noError; ParseResult noError;
Document a; D a;
a.Parse("{ 4 = 4]"); a.Parse("{ 4 = 4]");
ParseResult error(a.GetParseError(), a.GetErrorOffset()); ParseResult error(a.GetParseError(), a.GetErrorOffset());
EXPECT_TRUE(a.HasParseError()); EXPECT_TRUE(a.HasParseError());
EXPECT_NE(error.Code(), noError.Code()); EXPECT_NE(error.Code(), noError.Code());
EXPECT_NE(error.Offset(), noError.Offset()); EXPECT_NE(error.Offset(), noError.Offset());
Document b; D b;
b = std::move(a); b = std::move(a);
EXPECT_FALSE(a.HasParseError()); EXPECT_FALSE(a.HasParseError());
EXPECT_TRUE(b.HasParseError()); EXPECT_TRUE(b.HasParseError());
EXPECT_EQ(a.GetParseError(), noError.Code()); EXPECT_EQ(a.GetParseError(), noError.Code());
EXPECT_EQ(b.GetParseError(), error.Code()); EXPECT_EQ(b.GetParseError(), error.Code());
EXPECT_EQ(a.GetErrorOffset(), noError.Offset()); EXPECT_EQ(a.GetErrorOffset(), noError.Offset());
EXPECT_EQ(b.GetErrorOffset(), error.Offset()); EXPECT_EQ(b.GetErrorOffset(), error.Offset());
Document c; D c;
c = std::move(b); c = std::move(b);
EXPECT_FALSE(b.HasParseError()); EXPECT_FALSE(b.HasParseError());
EXPECT_TRUE(c.HasParseError()); EXPECT_TRUE(c.HasParseError());
EXPECT_EQ(b.GetParseError(), noError.Code()); EXPECT_EQ(b.GetParseError(), noError.Code());
EXPECT_EQ(c.GetParseError(), error.Code()); EXPECT_EQ(c.GetParseError(), error.Code());
EXPECT_EQ(b.GetErrorOffset(), noError.Offset()); EXPECT_EQ(b.GetErrorOffset(), noError.Offset());
EXPECT_EQ(c.GetErrorOffset(), error.Offset()); EXPECT_EQ(c.GetErrorOffset(), error.Offset());
} }
// This test does not properly use parsing, just for testing. // This test does not properly use parsing, just for testing.
// It must call ClearStack() explicitly to prevent memory leak. // It must call ClearStack() explicitly to prevent memory leak.
// But here we cannot as ClearStack() is private. // But here we cannot as ClearStack() is private.
#if 0 #if 0
TYPED_TEST(DocumentMove, MoveAssignmentStack) { TYPED_TEST(DocumentMove, MoveAssignmentStack) {
typedef TypeParam Allocator; typedef TypeParam Allocator;
typedef UTF8<> Encoding; typedef UTF8<> Encoding;
typedef GenericDocument<Encoding, Allocator> Document; typedef GenericDocument<Encoding, Allocator> D;
Document a; D a;
size_t defaultCapacity = a.GetStackCapacity(); size_t defaultCapacity = a.GetStackCapacity();
// Trick Document into getting GetStackCapacity() to return non-zero // Trick Document into getting GetStackCapacity() to return non-zero
typedef GenericReader<Encoding, Encoding, Allocator> Reader; typedef GenericReader<Encoding, Encoding, Allocator> Reader;
Reader reader(&a.GetAllocator()); Reader reader(&a.GetAllocator());
GenericStringStream<Encoding> is("[\"one\", \"two\", \"three\"]"); GenericStringStream<Encoding> is("[\"one\", \"two\", \"three\"]");
reader.template Parse<kParseDefaultFlags>(is, a); reader.template Parse<kParseDefaultFlags>(is, a);
size_t capacity = a.GetStackCapacity(); size_t capacity = a.GetStackCapacity();
EXPECT_GT(capacity, 0u); EXPECT_GT(capacity, 0u);
Document b; D b;
b = std::move(a); b = std::move(a);
EXPECT_EQ(a.GetStackCapacity(), defaultCapacity); EXPECT_EQ(a.GetStackCapacity(), defaultCapacity);
EXPECT_EQ(b.GetStackCapacity(), capacity); EXPECT_EQ(b.GetStackCapacity(), capacity);
Document c; D c;
c = std::move(b); c = std::move(b);
EXPECT_EQ(b.GetStackCapacity(), defaultCapacity); EXPECT_EQ(b.GetStackCapacity(), defaultCapacity);
EXPECT_EQ(c.GetStackCapacity(), capacity); EXPECT_EQ(c.GetStackCapacity(), capacity);
} }
#endif #endif
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
// Issue 22: Memory corruption via operator= // Issue 22: Memory corruption via operator=
// Fixed by making unimplemented assignment operator private. // Fixed by making unimplemented assignment operator private.
//TEST(Document, Assignment) { //TEST(Document, Assignment) {
// Document d1; // Document d1;
// Document d2; // Document d2;
// d1 = d2; // d1 = d2;
//} //}
#ifdef __clang__
RAPIDJSON_DIAG_POP
#endif
 End of changes. 44 change blocks. 
59 lines changed or deleted 182 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)