documenttest.cpp 5.51 KB
Newer Older
1 2 3
#include "unittest.h"
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
4 5 6
#include "rapidjson/filereadstream.h"
#include "rapidjson/encodedstream.h"
#include "rapidjson/stringbuffer.h"
7 8 9 10 11 12 13
#include <sstream>

using namespace rapidjson;

TEST(Document, Parse) {
	Document doc;

14
	doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ");
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

	EXPECT_TRUE(doc.IsObject());

	EXPECT_TRUE(doc.HasMember("hello"));
	Value& hello = doc["hello"];
	EXPECT_TRUE(hello.IsString());
	EXPECT_STREQ("world", hello.GetString());

	EXPECT_TRUE(doc.HasMember("t"));
	Value& t = doc["t"];
	EXPECT_TRUE(t.IsTrue());

	EXPECT_TRUE(doc.HasMember("f"));
	Value& f = doc["f"];
	EXPECT_TRUE(f.IsFalse());

	EXPECT_TRUE(doc.HasMember("n"));
	Value& n = doc["n"];
	EXPECT_TRUE(n.IsNull());

	EXPECT_TRUE(doc.HasMember("i"));
	Value& i = doc["i"];
	EXPECT_TRUE(i.IsNumber());
	EXPECT_EQ(123, i.GetInt());

	EXPECT_TRUE(doc.HasMember("pi"));
	Value& pi = doc["pi"];
	EXPECT_TRUE(pi.IsNumber());
	EXPECT_EQ(3.1416, pi.GetDouble());

	EXPECT_TRUE(doc.HasMember("a"));
	Value& a = doc["a"];
	EXPECT_TRUE(a.IsArray());
48
	EXPECT_EQ(4u, a.Size());
49 50 51 52
	for (SizeType i = 0; i < 4; i++)
		EXPECT_EQ(i + 1, a[i].GetUint());
}

53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
static FILE* OpenEncodedFile(const char* filename) {
	char buffer[1024];
	sprintf(buffer, "encodings/%s", filename);
	FILE *fp = fopen(buffer, "rb");
	if (!fp) {
		sprintf(buffer, "../../bin/encodings/%s", filename);
		fp = fopen(buffer, "rb");
	}
	return fp;
}

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.
		FILE *fp = OpenEncodedFile("utf8.json");
93 94 95 96 97 98 99 100 101 102 103 104 105
		FileReadStream is(fp, buffer, sizeof(buffer));
		Reader reader;
		StringBuffer bos2;
		Writer<StringBuffer> writer(bos2);
		reader.Parse(is, writer);

		EXPECT_EQ(bos.GetSize(), bos2.GetSize());
		EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize()));
	}
}

TEST(Document, ParseStream_AutoUTFInputStream) {
	// Any -> UTF8
106
	FILE* fp = OpenEncodedFile("utf32be.json");
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
	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.
		FILE *fp = OpenEncodedFile("utf8.json");
131 132 133 134 135 136 137 138 139 140 141
		FileReadStream is(fp, buffer, sizeof(buffer));
		Reader reader;
		StringBuffer bos2;
		Writer<StringBuffer> writer(bos2);
		reader.Parse(is, writer);

		EXPECT_EQ(bos.GetSize(), bos2.GetSize());
		EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize()));
	}
}

142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
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);
	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());
}

164
// This should be slow due to assignment in inner-loop.
165 166 167 168 169 170
struct OutputStringStream : public std::ostringstream {
	typedef char Ch;

	void Put(char c) {
		put(c);
	}
171
	void Flush() {}
172 173 174 175
};

TEST(Document, AcceptWriter) {
	Document doc;
176
	doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ");
177 178 179 180 181 182 183

	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());
}
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198

// 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[0u];
	ASSERT_TRUE(v.IsObject());

	GenericValue< UTF16<> >& s = v[L"created_at"];
	ASSERT_TRUE(s.IsString());

	EXPECT_EQ(0, wcscmp(L"Wed Oct 30 17:13:20 +0000 2012", s.GetString()));
}
199 200 201 202 203 204 205 206

// Issue 22: Memory corruption via operator=
// Fixed by making unimplemented assignment operator private.
//TEST(Document, Assignment) {
//	Document d1;
//	Document d2;
//	d1 = d2;
//}