prettywritertest.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  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/reader.h"
  16. #include "rapidjson/prettywriter.h"
  17. #include "rapidjson/stringbuffer.h"
  18. #include "rapidjson/filewritestream.h"
  19. #ifdef __clang__
  20. RAPIDJSON_DIAG_PUSH
  21. RAPIDJSON_DIAG_OFF(c++98-compat)
  22. #endif
  23. using namespace rapidjson;
  24. static const char kJson[] = "{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3,-1],\"u64\":1234567890123456789,\"i64\":-1234567890123456789}";
  25. static const char kPrettyJson[] =
  26. "{\n"
  27. " \"hello\": \"world\",\n"
  28. " \"t\": true,\n"
  29. " \"f\": false,\n"
  30. " \"n\": null,\n"
  31. " \"i\": 123,\n"
  32. " \"pi\": 3.1416,\n"
  33. " \"a\": [\n"
  34. " 1,\n"
  35. " 2,\n"
  36. " 3,\n"
  37. " -1\n"
  38. " ],\n"
  39. " \"u64\": 1234567890123456789,\n"
  40. " \"i64\": -1234567890123456789\n"
  41. "}";
  42. static const char kPrettyJson_FormatOptions_SLA[] =
  43. "{\n"
  44. " \"hello\": \"world\",\n"
  45. " \"t\": true,\n"
  46. " \"f\": false,\n"
  47. " \"n\": null,\n"
  48. " \"i\": 123,\n"
  49. " \"pi\": 3.1416,\n"
  50. " \"a\": [1, 2, 3, -1],\n"
  51. " \"u64\": 1234567890123456789,\n"
  52. " \"i64\": -1234567890123456789\n"
  53. "}";
  54. TEST(PrettyWriter, Basic) {
  55. StringBuffer buffer;
  56. PrettyWriter<StringBuffer> writer(buffer);
  57. Reader reader;
  58. StringStream s(kJson);
  59. reader.Parse(s, writer);
  60. EXPECT_STREQ(kPrettyJson, buffer.GetString());
  61. }
  62. TEST(PrettyWriter, FormatOptions) {
  63. StringBuffer buffer;
  64. PrettyWriter<StringBuffer> writer(buffer);
  65. writer.SetFormatOptions(kFormatSingleLineArray);
  66. Reader reader;
  67. StringStream s(kJson);
  68. reader.Parse(s, writer);
  69. EXPECT_STREQ(kPrettyJson_FormatOptions_SLA, buffer.GetString());
  70. }
  71. TEST(PrettyWriter, SetIndent) {
  72. StringBuffer buffer;
  73. PrettyWriter<StringBuffer> writer(buffer);
  74. writer.SetIndent('\t', 1);
  75. Reader reader;
  76. StringStream s(kJson);
  77. reader.Parse(s, writer);
  78. EXPECT_STREQ(
  79. "{\n"
  80. "\t\"hello\": \"world\",\n"
  81. "\t\"t\": true,\n"
  82. "\t\"f\": false,\n"
  83. "\t\"n\": null,\n"
  84. "\t\"i\": 123,\n"
  85. "\t\"pi\": 3.1416,\n"
  86. "\t\"a\": [\n"
  87. "\t\t1,\n"
  88. "\t\t2,\n"
  89. "\t\t3,\n"
  90. "\t\t-1\n"
  91. "\t],\n"
  92. "\t\"u64\": 1234567890123456789,\n"
  93. "\t\"i64\": -1234567890123456789\n"
  94. "}",
  95. buffer.GetString());
  96. }
  97. TEST(PrettyWriter, String) {
  98. StringBuffer buffer;
  99. PrettyWriter<StringBuffer> writer(buffer);
  100. EXPECT_TRUE(writer.StartArray());
  101. EXPECT_TRUE(writer.String("Hello\n"));
  102. EXPECT_TRUE(writer.EndArray());
  103. EXPECT_STREQ("[\n \"Hello\\n\"\n]", buffer.GetString());
  104. }
  105. #if RAPIDJSON_HAS_STDSTRING
  106. TEST(PrettyWriter, String_STDSTRING) {
  107. StringBuffer buffer;
  108. PrettyWriter<StringBuffer> writer(buffer);
  109. EXPECT_TRUE(writer.StartArray());
  110. EXPECT_TRUE(writer.String(std::string("Hello\n")));
  111. EXPECT_TRUE(writer.EndArray());
  112. EXPECT_STREQ("[\n \"Hello\\n\"\n]", buffer.GetString());
  113. }
  114. #endif
  115. #include <sstream>
  116. class OStreamWrapper {
  117. public:
  118. typedef char Ch;
  119. OStreamWrapper(std::ostream& os) : os_(os) {}
  120. Ch Peek() const { assert(false); return '\0'; }
  121. Ch Take() { assert(false); return '\0'; }
  122. size_t Tell() const { return 0; }
  123. Ch* PutBegin() { assert(false); return 0; }
  124. void Put(Ch c) { os_.put(c); }
  125. void Flush() { os_.flush(); }
  126. size_t PutEnd(Ch*) { assert(false); return 0; }
  127. private:
  128. OStreamWrapper(const OStreamWrapper&);
  129. OStreamWrapper& operator=(const OStreamWrapper&);
  130. std::ostream& os_;
  131. };
  132. // For covering PutN() generic version
  133. TEST(PrettyWriter, OStreamWrapper) {
  134. StringStream s(kJson);
  135. std::stringstream ss;
  136. OStreamWrapper os(ss);
  137. PrettyWriter<OStreamWrapper> writer(os);
  138. Reader reader;
  139. reader.Parse(s, writer);
  140. std::string actual = ss.str();
  141. EXPECT_STREQ(kPrettyJson, actual.c_str());
  142. }
  143. // For covering FileWriteStream::PutN()
  144. TEST(PrettyWriter, FileWriteStream) {
  145. char filename[L_tmpnam];
  146. FILE* fp = TempFile(filename);
  147. ASSERT_TRUE(fp!=NULL);
  148. char buffer[16];
  149. FileWriteStream os(fp, buffer, sizeof(buffer));
  150. PrettyWriter<FileWriteStream> writer(os);
  151. Reader reader;
  152. StringStream s(kJson);
  153. reader.Parse(s, writer);
  154. fclose(fp);
  155. fp = fopen(filename, "rb");
  156. fseek(fp, 0, SEEK_END);
  157. size_t size = static_cast<size_t>(ftell(fp));
  158. fseek(fp, 0, SEEK_SET);
  159. char* json = static_cast<char*>(malloc(size + 1));
  160. size_t readLength = fread(json, 1, size, fp);
  161. json[readLength] = '\0';
  162. fclose(fp);
  163. remove(filename);
  164. EXPECT_STREQ(kPrettyJson, json);
  165. free(json);
  166. }
  167. TEST(PrettyWriter, RawValue) {
  168. StringBuffer buffer;
  169. PrettyWriter<StringBuffer> writer(buffer);
  170. writer.StartObject();
  171. writer.Key("a");
  172. writer.Int(1);
  173. writer.Key("raw");
  174. const char json[] = "[\"Hello\\nWorld\", 123.456]";
  175. writer.RawValue(json, strlen(json), kArrayType);
  176. writer.EndObject();
  177. EXPECT_TRUE(writer.IsComplete());
  178. EXPECT_STREQ(
  179. "{\n"
  180. " \"a\": 1,\n"
  181. " \"raw\": [\"Hello\\nWorld\", 123.456]\n" // no indentation within raw value
  182. "}",
  183. buffer.GetString());
  184. }
  185. TEST(PrettyWriter, InvalidEventSequence) {
  186. // {]
  187. {
  188. StringBuffer buffer;
  189. PrettyWriter<StringBuffer> writer(buffer);
  190. writer.StartObject();
  191. EXPECT_THROW(writer.EndArray(), AssertException);
  192. EXPECT_FALSE(writer.IsComplete());
  193. }
  194. // [}
  195. {
  196. StringBuffer buffer;
  197. PrettyWriter<StringBuffer> writer(buffer);
  198. writer.StartArray();
  199. EXPECT_THROW(writer.EndObject(), AssertException);
  200. EXPECT_FALSE(writer.IsComplete());
  201. }
  202. // { 1:
  203. {
  204. StringBuffer buffer;
  205. PrettyWriter<StringBuffer> writer(buffer);
  206. writer.StartObject();
  207. EXPECT_THROW(writer.Int(1), AssertException);
  208. EXPECT_FALSE(writer.IsComplete());
  209. }
  210. // { 'a' }
  211. {
  212. StringBuffer buffer;
  213. PrettyWriter<StringBuffer> writer(buffer);
  214. writer.StartObject();
  215. writer.Key("a");
  216. EXPECT_THROW(writer.EndObject(), AssertException);
  217. EXPECT_FALSE(writer.IsComplete());
  218. }
  219. // { 'a':'b','c' }
  220. {
  221. StringBuffer buffer;
  222. PrettyWriter<StringBuffer> writer(buffer);
  223. writer.StartObject();
  224. writer.Key("a");
  225. writer.String("b");
  226. writer.Key("c");
  227. EXPECT_THROW(writer.EndObject(), AssertException);
  228. EXPECT_FALSE(writer.IsComplete());
  229. }
  230. }
  231. TEST(PrettyWriter, NaN) {
  232. double nan = std::numeric_limits<double>::quiet_NaN();
  233. EXPECT_TRUE(internal::Double(nan).IsNan());
  234. StringBuffer buffer;
  235. {
  236. PrettyWriter<StringBuffer> writer(buffer);
  237. EXPECT_FALSE(writer.Double(nan));
  238. }
  239. {
  240. PrettyWriter<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> writer(buffer);
  241. EXPECT_TRUE(writer.Double(nan));
  242. EXPECT_STREQ("NaN", buffer.GetString());
  243. }
  244. GenericStringBuffer<UTF16<> > buffer2;
  245. PrettyWriter<GenericStringBuffer<UTF16<> > > writer2(buffer2);
  246. EXPECT_FALSE(writer2.Double(nan));
  247. }
  248. TEST(PrettyWriter, Inf) {
  249. double inf = std::numeric_limits<double>::infinity();
  250. EXPECT_TRUE(internal::Double(inf).IsInf());
  251. StringBuffer buffer;
  252. {
  253. PrettyWriter<StringBuffer> writer(buffer);
  254. EXPECT_FALSE(writer.Double(inf));
  255. }
  256. {
  257. PrettyWriter<StringBuffer> writer(buffer);
  258. EXPECT_FALSE(writer.Double(-inf));
  259. }
  260. {
  261. PrettyWriter<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> writer(buffer);
  262. EXPECT_TRUE(writer.Double(inf));
  263. }
  264. {
  265. PrettyWriter<StringBuffer, UTF8<>, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> writer(buffer);
  266. EXPECT_TRUE(writer.Double(-inf));
  267. }
  268. EXPECT_STREQ("Infinity-Infinity", buffer.GetString());
  269. }
  270. TEST(PrettyWriter, Issue_889) {
  271. char buf[100] = "Hello";
  272. StringBuffer buffer;
  273. PrettyWriter<StringBuffer> writer(buffer);
  274. writer.StartArray();
  275. writer.String(buf);
  276. writer.EndArray();
  277. EXPECT_STREQ("[\n \"Hello\"\n]", buffer.GetString());
  278. EXPECT_TRUE(writer.IsComplete()); \
  279. }
  280. #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
  281. static PrettyWriter<StringBuffer> WriterGen(StringBuffer &target) {
  282. PrettyWriter<StringBuffer> writer(target);
  283. writer.StartObject();
  284. writer.Key("a");
  285. writer.Int(1);
  286. return writer;
  287. }
  288. TEST(PrettyWriter, MoveCtor) {
  289. StringBuffer buffer;
  290. PrettyWriter<StringBuffer> writer(WriterGen(buffer));
  291. writer.EndObject();
  292. EXPECT_TRUE(writer.IsComplete());
  293. EXPECT_STREQ(
  294. "{\n"
  295. " \"a\": 1\n"
  296. "}",
  297. buffer.GetString());
  298. }
  299. #endif
  300. TEST(PrettyWriter, Issue_1336) {
  301. #define T(meth, val, expected) \
  302. { \
  303. StringBuffer buffer; \
  304. PrettyWriter<StringBuffer> writer(buffer); \
  305. writer.meth(val); \
  306. \
  307. EXPECT_STREQ(expected, buffer.GetString()); \
  308. EXPECT_TRUE(writer.IsComplete()); \
  309. }
  310. T(Bool, false, "false");
  311. T(Bool, true, "true");
  312. T(Int, 0, "0");
  313. T(Uint, 0, "0");
  314. T(Int64, 0, "0");
  315. T(Uint64, 0, "0");
  316. T(Double, 0, "0.0");
  317. T(String, "Hello", "\"Hello\"");
  318. #undef T
  319. StringBuffer buffer;
  320. PrettyWriter<StringBuffer> writer(buffer);
  321. writer.Null();
  322. EXPECT_STREQ("null", buffer.GetString());
  323. EXPECT_TRUE(writer.IsComplete());
  324. }
  325. #ifdef __clang__
  326. RAPIDJSON_DIAG_POP
  327. #endif