documenttest.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  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. #include "unittest.h"
  15. #include "rapidjson/document.h"
  16. #include "rapidjson/writer.h"
  17. #include "rapidjson/filereadstream.h"
  18. #include "rapidjson/encodedstream.h"
  19. #include "rapidjson/stringbuffer.h"
  20. #include <sstream>
  21. #include <algorithm>
  22. #ifdef __clang__
  23. RAPIDJSON_DIAG_PUSH
  24. RAPIDJSON_DIAG_OFF(c++98-compat)
  25. RAPIDJSON_DIAG_OFF(missing-variable-declarations)
  26. #endif
  27. using namespace rapidjson;
  28. template <typename DocumentType>
  29. void ParseCheck(DocumentType& doc) {
  30. typedef typename DocumentType::ValueType ValueType;
  31. EXPECT_FALSE(doc.HasParseError());
  32. EXPECT_TRUE(static_cast<ParseResult>(doc));
  33. EXPECT_TRUE(doc.IsObject());
  34. EXPECT_TRUE(doc.HasMember("hello"));
  35. const ValueType& hello = doc["hello"];
  36. EXPECT_TRUE(hello.IsString());
  37. EXPECT_STREQ("world", hello.GetString());
  38. EXPECT_TRUE(doc.HasMember("t"));
  39. const ValueType& t = doc["t"];
  40. EXPECT_TRUE(t.IsTrue());
  41. EXPECT_TRUE(doc.HasMember("f"));
  42. const ValueType& f = doc["f"];
  43. EXPECT_TRUE(f.IsFalse());
  44. EXPECT_TRUE(doc.HasMember("n"));
  45. const ValueType& n = doc["n"];
  46. EXPECT_TRUE(n.IsNull());
  47. EXPECT_TRUE(doc.HasMember("i"));
  48. const ValueType& i = doc["i"];
  49. EXPECT_TRUE(i.IsNumber());
  50. EXPECT_EQ(123, i.GetInt());
  51. EXPECT_TRUE(doc.HasMember("pi"));
  52. const ValueType& pi = doc["pi"];
  53. EXPECT_TRUE(pi.IsNumber());
  54. EXPECT_DOUBLE_EQ(3.1416, pi.GetDouble());
  55. EXPECT_TRUE(doc.HasMember("a"));
  56. const ValueType& a = doc["a"];
  57. EXPECT_TRUE(a.IsArray());
  58. EXPECT_EQ(4u, a.Size());
  59. for (SizeType j = 0; j < 4; j++)
  60. EXPECT_EQ(j + 1, a[j].GetUint());
  61. }
  62. template <typename Allocator, typename StackAllocator>
  63. void ParseTest() {
  64. typedef GenericDocument<UTF8<>, Allocator, StackAllocator> DocumentType;
  65. DocumentType doc;
  66. const char* json = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
  67. doc.Parse(json);
  68. ParseCheck(doc);
  69. doc.SetNull();
  70. StringStream s(json);
  71. doc.template ParseStream<0>(s);
  72. ParseCheck(doc);
  73. doc.SetNull();
  74. char *buffer = strdup(json);
  75. doc.ParseInsitu(buffer);
  76. ParseCheck(doc);
  77. free(buffer);
  78. }
  79. TEST(Document, Parse) {
  80. ParseTest<MemoryPoolAllocator<>, CrtAllocator>();
  81. ParseTest<MemoryPoolAllocator<>, MemoryPoolAllocator<> >();
  82. ParseTest<CrtAllocator, MemoryPoolAllocator<> >();
  83. ParseTest<CrtAllocator, CrtAllocator>();
  84. }
  85. TEST(Document, UnchangedOnParseError) {
  86. Document doc;
  87. doc.SetArray().PushBack(0, doc.GetAllocator());
  88. ParseResult err = doc.Parse("{]");
  89. EXPECT_TRUE(doc.HasParseError());
  90. EXPECT_EQ(err.Code(), doc.GetParseError());
  91. EXPECT_EQ(err.Offset(), doc.GetErrorOffset());
  92. EXPECT_TRUE(doc.IsArray());
  93. EXPECT_EQ(doc.Size(), 1u);
  94. err = doc.Parse("{}");
  95. EXPECT_FALSE(doc.HasParseError());
  96. EXPECT_FALSE(err.IsError());
  97. EXPECT_EQ(err.Code(), doc.GetParseError());
  98. EXPECT_EQ(err.Offset(), doc.GetErrorOffset());
  99. EXPECT_TRUE(doc.IsObject());
  100. EXPECT_EQ(doc.MemberCount(), 0u);
  101. }
  102. static FILE* OpenEncodedFile(const char* filename) {
  103. const char *paths[] = {
  104. "encodings",
  105. "bin/encodings",
  106. "../bin/encodings",
  107. "../../bin/encodings",
  108. "../../../bin/encodings"
  109. };
  110. char buffer[1024];
  111. for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
  112. sprintf(buffer, "%s/%s", paths[i], filename);
  113. FILE *fp = fopen(buffer, "rb");
  114. if (fp)
  115. return fp;
  116. }
  117. return 0;
  118. }
  119. TEST(Document, ParseStream_EncodedInputStream) {
  120. // UTF8 -> UTF16
  121. FILE* fp = OpenEncodedFile("utf8.json");
  122. char buffer[256];
  123. FileReadStream bis(fp, buffer, sizeof(buffer));
  124. EncodedInputStream<UTF8<>, FileReadStream> eis(bis);
  125. GenericDocument<UTF16<> > d;
  126. d.ParseStream<0, UTF8<> >(eis);
  127. EXPECT_FALSE(d.HasParseError());
  128. fclose(fp);
  129. wchar_t expected[] = L"I can eat glass and it doesn't hurt me.";
  130. GenericValue<UTF16<> >& v = d[L"en"];
  131. EXPECT_TRUE(v.IsString());
  132. EXPECT_EQ(sizeof(expected) / sizeof(wchar_t) - 1, v.GetStringLength());
  133. EXPECT_EQ(0, StrCmp(expected, v.GetString()));
  134. // UTF16 -> UTF8 in memory
  135. StringBuffer bos;
  136. typedef EncodedOutputStream<UTF8<>, StringBuffer> OutputStream;
  137. OutputStream eos(bos, false); // Not writing BOM
  138. {
  139. Writer<OutputStream, UTF16<>, UTF8<> > writer(eos);
  140. d.Accept(writer);
  141. }
  142. // Condense the original file and compare.
  143. fp = OpenEncodedFile("utf8.json");
  144. FileReadStream is(fp, buffer, sizeof(buffer));
  145. Reader reader;
  146. StringBuffer bos2;
  147. Writer<StringBuffer> writer2(bos2);
  148. reader.Parse(is, writer2);
  149. fclose(fp);
  150. EXPECT_EQ(bos.GetSize(), bos2.GetSize());
  151. EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize()));
  152. }
  153. TEST(Document, ParseStream_AutoUTFInputStream) {
  154. // Any -> UTF8
  155. FILE* fp = OpenEncodedFile("utf32be.json");
  156. char buffer[256];
  157. FileReadStream bis(fp, buffer, sizeof(buffer));
  158. AutoUTFInputStream<unsigned, FileReadStream> eis(bis);
  159. Document d;
  160. d.ParseStream<0, AutoUTF<unsigned> >(eis);
  161. EXPECT_FALSE(d.HasParseError());
  162. fclose(fp);
  163. char expected[] = "I can eat glass and it doesn't hurt me.";
  164. Value& v = d["en"];
  165. EXPECT_TRUE(v.IsString());
  166. EXPECT_EQ(sizeof(expected) - 1, v.GetStringLength());
  167. EXPECT_EQ(0, StrCmp(expected, v.GetString()));
  168. // UTF8 -> UTF8 in memory
  169. StringBuffer bos;
  170. Writer<StringBuffer> writer(bos);
  171. d.Accept(writer);
  172. // Condense the original file and compare.
  173. fp = OpenEncodedFile("utf8.json");
  174. FileReadStream is(fp, buffer, sizeof(buffer));
  175. Reader reader;
  176. StringBuffer bos2;
  177. Writer<StringBuffer> writer2(bos2);
  178. reader.Parse(is, writer2);
  179. fclose(fp);
  180. EXPECT_EQ(bos.GetSize(), bos2.GetSize());
  181. EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize()));
  182. }
  183. TEST(Document, Swap) {
  184. Document d1;
  185. Document::AllocatorType& a = d1.GetAllocator();
  186. d1.SetArray().PushBack(1, a).PushBack(2, a);
  187. Value o;
  188. o.SetObject().AddMember("a", 1, a);
  189. // Swap between Document and Value
  190. // d1.Swap(o); // doesn't compile
  191. o.Swap(d1);
  192. EXPECT_TRUE(d1.IsObject());
  193. EXPECT_TRUE(o.IsArray());
  194. // Swap between Document and Document
  195. Document d2;
  196. d2.SetArray().PushBack(3, a);
  197. d1.Swap(d2);
  198. EXPECT_TRUE(d1.IsArray());
  199. EXPECT_TRUE(d2.IsObject());
  200. EXPECT_EQ(&d2.GetAllocator(), &a);
  201. // reset value
  202. Value().Swap(d1);
  203. EXPECT_TRUE(d1.IsNull());
  204. // reset document, including allocator
  205. Document().Swap(d2);
  206. EXPECT_TRUE(d2.IsNull());
  207. EXPECT_NE(&d2.GetAllocator(), &a);
  208. // testing std::swap compatibility
  209. d1.SetBool(true);
  210. using std::swap;
  211. swap(d1, d2);
  212. EXPECT_TRUE(d1.IsNull());
  213. EXPECT_TRUE(d2.IsTrue());
  214. swap(o, d2);
  215. EXPECT_TRUE(o.IsTrue());
  216. EXPECT_TRUE(d2.IsArray());
  217. }
  218. // This should be slow due to assignment in inner-loop.
  219. struct OutputStringStream : public std::ostringstream {
  220. typedef char Ch;
  221. virtual ~OutputStringStream();
  222. void Put(char c) {
  223. put(c);
  224. }
  225. void Flush() {}
  226. };
  227. OutputStringStream::~OutputStringStream() {}
  228. TEST(Document, AcceptWriter) {
  229. Document doc;
  230. doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ");
  231. OutputStringStream os;
  232. Writer<OutputStringStream> writer(os);
  233. doc.Accept(writer);
  234. EXPECT_EQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3,4]}", os.str());
  235. }
  236. TEST(Document, UserBuffer) {
  237. typedef GenericDocument<UTF8<>, MemoryPoolAllocator<>, MemoryPoolAllocator<> > DocumentType;
  238. char valueBuffer[4096];
  239. char parseBuffer[1024];
  240. MemoryPoolAllocator<> valueAllocator(valueBuffer, sizeof(valueBuffer));
  241. MemoryPoolAllocator<> parseAllocator(parseBuffer, sizeof(parseBuffer));
  242. DocumentType doc(&valueAllocator, sizeof(parseBuffer) / 2, &parseAllocator);
  243. doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ");
  244. EXPECT_FALSE(doc.HasParseError());
  245. EXPECT_LE(valueAllocator.Size(), sizeof(valueBuffer));
  246. EXPECT_LE(parseAllocator.Size(), sizeof(parseBuffer));
  247. // Cover MemoryPoolAllocator::Capacity()
  248. EXPECT_LE(valueAllocator.Size(), valueAllocator.Capacity());
  249. EXPECT_LE(parseAllocator.Size(), parseAllocator.Capacity());
  250. }
  251. // Issue 226: Value of string type should not point to NULL
  252. TEST(Document, AssertAcceptInvalidNameType) {
  253. Document doc;
  254. doc.SetObject();
  255. doc.AddMember("a", 0, doc.GetAllocator());
  256. doc.FindMember("a")->name.SetNull(); // Change name to non-string type.
  257. OutputStringStream os;
  258. Writer<OutputStringStream> writer(os);
  259. ASSERT_THROW(doc.Accept(writer), AssertException);
  260. }
  261. // Issue 44: SetStringRaw doesn't work with wchar_t
  262. TEST(Document, UTF16_Document) {
  263. GenericDocument< UTF16<> > json;
  264. json.Parse<kParseValidateEncodingFlag>(L"[{\"created_at\":\"Wed Oct 30 17:13:20 +0000 2012\"}]");
  265. ASSERT_TRUE(json.IsArray());
  266. GenericValue< UTF16<> >& v = json[0];
  267. ASSERT_TRUE(v.IsObject());
  268. GenericValue< UTF16<> >& s = v[L"created_at"];
  269. ASSERT_TRUE(s.IsString());
  270. EXPECT_EQ(0, memcmp(L"Wed Oct 30 17:13:20 +0000 2012", s.GetString(), (s.GetStringLength() + 1) * sizeof(wchar_t)));
  271. }
  272. #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
  273. #if 0 // Many old compiler does not support these. Turn it off temporaily.
  274. #include <type_traits>
  275. TEST(Document, Traits) {
  276. static_assert(std::is_constructible<Document>::value, "");
  277. static_assert(std::is_default_constructible<Document>::value, "");
  278. #ifndef _MSC_VER
  279. static_assert(!std::is_copy_constructible<Document>::value, "");
  280. #endif
  281. static_assert(std::is_move_constructible<Document>::value, "");
  282. static_assert(!std::is_nothrow_constructible<Document>::value, "");
  283. static_assert(!std::is_nothrow_default_constructible<Document>::value, "");
  284. #ifndef _MSC_VER
  285. static_assert(!std::is_nothrow_copy_constructible<Document>::value, "");
  286. static_assert(std::is_nothrow_move_constructible<Document>::value, "");
  287. #endif
  288. static_assert(std::is_assignable<Document,Document>::value, "");
  289. #ifndef _MSC_VER
  290. static_assert(!std::is_copy_assignable<Document>::value, "");
  291. #endif
  292. static_assert(std::is_move_assignable<Document>::value, "");
  293. #ifndef _MSC_VER
  294. static_assert(std::is_nothrow_assignable<Document, Document>::value, "");
  295. #endif
  296. static_assert(!std::is_nothrow_copy_assignable<Document>::value, "");
  297. #ifndef _MSC_VER
  298. static_assert(std::is_nothrow_move_assignable<Document>::value, "");
  299. #endif
  300. static_assert( std::is_destructible<Document>::value, "");
  301. #ifndef _MSC_VER
  302. static_assert(std::is_nothrow_destructible<Document>::value, "");
  303. #endif
  304. }
  305. #endif
  306. template <typename Allocator>
  307. struct DocumentMove: public ::testing::Test {
  308. };
  309. typedef ::testing::Types< CrtAllocator, MemoryPoolAllocator<> > MoveAllocatorTypes;
  310. TYPED_TEST_CASE(DocumentMove, MoveAllocatorTypes);
  311. TYPED_TEST(DocumentMove, MoveConstructor) {
  312. typedef TypeParam Allocator;
  313. typedef GenericDocument<UTF8<>, Allocator> Document;
  314. Allocator allocator;
  315. Document a(&allocator);
  316. a.Parse("[\"one\", \"two\", \"three\"]");
  317. EXPECT_FALSE(a.HasParseError());
  318. EXPECT_TRUE(a.IsArray());
  319. EXPECT_EQ(3u, a.Size());
  320. EXPECT_EQ(&a.GetAllocator(), &allocator);
  321. // Document b(a); // does not compile (!is_copy_constructible)
  322. Document b(std::move(a));
  323. EXPECT_TRUE(a.IsNull());
  324. EXPECT_TRUE(b.IsArray());
  325. EXPECT_EQ(3u, b.Size());
  326. EXPECT_THROW(a.GetAllocator(), AssertException);
  327. EXPECT_EQ(&b.GetAllocator(), &allocator);
  328. b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}");
  329. EXPECT_FALSE(b.HasParseError());
  330. EXPECT_TRUE(b.IsObject());
  331. EXPECT_EQ(2u, b.MemberCount());
  332. // Document c = a; // does not compile (!is_copy_constructible)
  333. Document c = std::move(b);
  334. EXPECT_TRUE(b.IsNull());
  335. EXPECT_TRUE(c.IsObject());
  336. EXPECT_EQ(2u, c.MemberCount());
  337. EXPECT_THROW(b.GetAllocator(), AssertException);
  338. EXPECT_EQ(&c.GetAllocator(), &allocator);
  339. }
  340. TYPED_TEST(DocumentMove, MoveConstructorParseError) {
  341. typedef TypeParam Allocator;
  342. typedef GenericDocument<UTF8<>, Allocator> Document;
  343. ParseResult noError;
  344. Document a;
  345. a.Parse("{ 4 = 4]");
  346. ParseResult error(a.GetParseError(), a.GetErrorOffset());
  347. EXPECT_TRUE(a.HasParseError());
  348. EXPECT_NE(error.Code(), noError.Code());
  349. EXPECT_NE(error.Offset(), noError.Offset());
  350. Document b(std::move(a));
  351. EXPECT_FALSE(a.HasParseError());
  352. EXPECT_TRUE(b.HasParseError());
  353. EXPECT_EQ(a.GetParseError(), noError.Code());
  354. EXPECT_EQ(b.GetParseError(), error.Code());
  355. EXPECT_EQ(a.GetErrorOffset(), noError.Offset());
  356. EXPECT_EQ(b.GetErrorOffset(), error.Offset());
  357. Document c(std::move(b));
  358. EXPECT_FALSE(b.HasParseError());
  359. EXPECT_TRUE(c.HasParseError());
  360. EXPECT_EQ(b.GetParseError(), noError.Code());
  361. EXPECT_EQ(c.GetParseError(), error.Code());
  362. EXPECT_EQ(b.GetErrorOffset(), noError.Offset());
  363. EXPECT_EQ(c.GetErrorOffset(), error.Offset());
  364. }
  365. // This test does not properly use parsing, just for testing.
  366. // It must call ClearStack() explicitly to prevent memory leak.
  367. // But here we cannot as ClearStack() is private.
  368. #if 0
  369. TYPED_TEST(DocumentMove, MoveConstructorStack) {
  370. typedef TypeParam Allocator;
  371. typedef UTF8<> Encoding;
  372. typedef GenericDocument<Encoding, Allocator> Document;
  373. Document a;
  374. size_t defaultCapacity = a.GetStackCapacity();
  375. // Trick Document into getting GetStackCapacity() to return non-zero
  376. typedef GenericReader<Encoding, Encoding, Allocator> Reader;
  377. Reader reader(&a.GetAllocator());
  378. GenericStringStream<Encoding> is("[\"one\", \"two\", \"three\"]");
  379. reader.template Parse<kParseDefaultFlags>(is, a);
  380. size_t capacity = a.GetStackCapacity();
  381. EXPECT_GT(capacity, 0u);
  382. Document b(std::move(a));
  383. EXPECT_EQ(a.GetStackCapacity(), defaultCapacity);
  384. EXPECT_EQ(b.GetStackCapacity(), capacity);
  385. Document c = std::move(b);
  386. EXPECT_EQ(b.GetStackCapacity(), defaultCapacity);
  387. EXPECT_EQ(c.GetStackCapacity(), capacity);
  388. }
  389. #endif
  390. TYPED_TEST(DocumentMove, MoveAssignment) {
  391. typedef TypeParam Allocator;
  392. typedef GenericDocument<UTF8<>, Allocator> Document;
  393. Allocator allocator;
  394. Document a(&allocator);
  395. a.Parse("[\"one\", \"two\", \"three\"]");
  396. EXPECT_FALSE(a.HasParseError());
  397. EXPECT_TRUE(a.IsArray());
  398. EXPECT_EQ(3u, a.Size());
  399. EXPECT_EQ(&a.GetAllocator(), &allocator);
  400. // Document b; b = a; // does not compile (!is_copy_assignable)
  401. Document b;
  402. b = std::move(a);
  403. EXPECT_TRUE(a.IsNull());
  404. EXPECT_TRUE(b.IsArray());
  405. EXPECT_EQ(3u, b.Size());
  406. EXPECT_THROW(a.GetAllocator(), AssertException);
  407. EXPECT_EQ(&b.GetAllocator(), &allocator);
  408. b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}");
  409. EXPECT_FALSE(b.HasParseError());
  410. EXPECT_TRUE(b.IsObject());
  411. EXPECT_EQ(2u, b.MemberCount());
  412. // Document c; c = a; // does not compile (see static_assert)
  413. Document c;
  414. c = std::move(b);
  415. EXPECT_TRUE(b.IsNull());
  416. EXPECT_TRUE(c.IsObject());
  417. EXPECT_EQ(2u, c.MemberCount());
  418. EXPECT_THROW(b.GetAllocator(), AssertException);
  419. EXPECT_EQ(&c.GetAllocator(), &allocator);
  420. }
  421. TYPED_TEST(DocumentMove, MoveAssignmentParseError) {
  422. typedef TypeParam Allocator;
  423. typedef GenericDocument<UTF8<>, Allocator> Document;
  424. ParseResult noError;
  425. Document a;
  426. a.Parse("{ 4 = 4]");
  427. ParseResult error(a.GetParseError(), a.GetErrorOffset());
  428. EXPECT_TRUE(a.HasParseError());
  429. EXPECT_NE(error.Code(), noError.Code());
  430. EXPECT_NE(error.Offset(), noError.Offset());
  431. Document b;
  432. b = std::move(a);
  433. EXPECT_FALSE(a.HasParseError());
  434. EXPECT_TRUE(b.HasParseError());
  435. EXPECT_EQ(a.GetParseError(), noError.Code());
  436. EXPECT_EQ(b.GetParseError(), error.Code());
  437. EXPECT_EQ(a.GetErrorOffset(), noError.Offset());
  438. EXPECT_EQ(b.GetErrorOffset(), error.Offset());
  439. Document c;
  440. c = std::move(b);
  441. EXPECT_FALSE(b.HasParseError());
  442. EXPECT_TRUE(c.HasParseError());
  443. EXPECT_EQ(b.GetParseError(), noError.Code());
  444. EXPECT_EQ(c.GetParseError(), error.Code());
  445. EXPECT_EQ(b.GetErrorOffset(), noError.Offset());
  446. EXPECT_EQ(c.GetErrorOffset(), error.Offset());
  447. }
  448. // This test does not properly use parsing, just for testing.
  449. // It must call ClearStack() explicitly to prevent memory leak.
  450. // But here we cannot as ClearStack() is private.
  451. #if 0
  452. TYPED_TEST(DocumentMove, MoveAssignmentStack) {
  453. typedef TypeParam Allocator;
  454. typedef UTF8<> Encoding;
  455. typedef GenericDocument<Encoding, Allocator> Document;
  456. Document a;
  457. size_t defaultCapacity = a.GetStackCapacity();
  458. // Trick Document into getting GetStackCapacity() to return non-zero
  459. typedef GenericReader<Encoding, Encoding, Allocator> Reader;
  460. Reader reader(&a.GetAllocator());
  461. GenericStringStream<Encoding> is("[\"one\", \"two\", \"three\"]");
  462. reader.template Parse<kParseDefaultFlags>(is, a);
  463. size_t capacity = a.GetStackCapacity();
  464. EXPECT_GT(capacity, 0u);
  465. Document b;
  466. b = std::move(a);
  467. EXPECT_EQ(a.GetStackCapacity(), defaultCapacity);
  468. EXPECT_EQ(b.GetStackCapacity(), capacity);
  469. Document c;
  470. c = std::move(b);
  471. EXPECT_EQ(b.GetStackCapacity(), defaultCapacity);
  472. EXPECT_EQ(c.GetStackCapacity(), capacity);
  473. }
  474. #endif
  475. #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
  476. // Issue 22: Memory corruption via operator=
  477. // Fixed by making unimplemented assignment operator private.
  478. //TEST(Document, Assignment) {
  479. // Document d1;
  480. // Document d2;
  481. // d1 = d2;
  482. //}
  483. #ifdef __clang__
  484. RAPIDJSON_DIAG_POP
  485. #endif