prettywritertest.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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. char buffer[16];
  148. FileWriteStream os(fp, buffer, sizeof(buffer));
  149. PrettyWriter<FileWriteStream> writer(os);
  150. Reader reader;
  151. StringStream s(kJson);
  152. reader.Parse(s, writer);
  153. fclose(fp);
  154. fp = fopen(filename, "rb");
  155. fseek(fp, 0, SEEK_END);
  156. size_t size = static_cast<size_t>(ftell(fp));
  157. fseek(fp, 0, SEEK_SET);
  158. char* json = static_cast<char*>(malloc(size + 1));
  159. size_t readLength = fread(json, 1, size, fp);
  160. json[readLength] = '\0';
  161. fclose(fp);
  162. remove(filename);
  163. EXPECT_STREQ(kPrettyJson, json);
  164. free(json);
  165. }
  166. TEST(PrettyWriter, RawValue) {
  167. StringBuffer buffer;
  168. PrettyWriter<StringBuffer> writer(buffer);
  169. writer.StartObject();
  170. writer.Key("a");
  171. writer.Int(1);
  172. writer.Key("raw");
  173. const char json[] = "[\"Hello\\nWorld\", 123.456]";
  174. writer.RawValue(json, strlen(json), kArrayType);
  175. writer.EndObject();
  176. EXPECT_TRUE(writer.IsComplete());
  177. EXPECT_STREQ(
  178. "{\n"
  179. " \"a\": 1,\n"
  180. " \"raw\": [\"Hello\\nWorld\", 123.456]\n" // no indentation within raw value
  181. "}",
  182. buffer.GetString());
  183. }
  184. TEST(PrettyWriter, InvalidEventSequence) {
  185. // {]
  186. {
  187. StringBuffer buffer;
  188. PrettyWriter<StringBuffer> writer(buffer);
  189. writer.StartObject();
  190. EXPECT_THROW(writer.EndArray(), AssertException);
  191. EXPECT_FALSE(writer.IsComplete());
  192. }
  193. // [}
  194. {
  195. StringBuffer buffer;
  196. PrettyWriter<StringBuffer> writer(buffer);
  197. writer.StartArray();
  198. EXPECT_THROW(writer.EndObject(), AssertException);
  199. EXPECT_FALSE(writer.IsComplete());
  200. }
  201. // { 1:
  202. {
  203. StringBuffer buffer;
  204. PrettyWriter<StringBuffer> writer(buffer);
  205. writer.StartObject();
  206. EXPECT_THROW(writer.Int(1), AssertException);
  207. EXPECT_FALSE(writer.IsComplete());
  208. }
  209. // { 'a' }
  210. {
  211. StringBuffer buffer;
  212. PrettyWriter<StringBuffer> writer(buffer);
  213. writer.StartObject();
  214. writer.Key("a");
  215. EXPECT_THROW(writer.EndObject(), AssertException);
  216. EXPECT_FALSE(writer.IsComplete());
  217. }
  218. // { 'a':'b','c' }
  219. {
  220. StringBuffer buffer;
  221. PrettyWriter<StringBuffer> writer(buffer);
  222. writer.StartObject();
  223. writer.Key("a");
  224. writer.String("b");
  225. writer.Key("c");
  226. EXPECT_THROW(writer.EndObject(), AssertException);
  227. EXPECT_FALSE(writer.IsComplete());
  228. }
  229. }
  230. TEST(PrettyWriter, Issue_889) {
  231. char buf[100] = "Hello";
  232. StringBuffer buffer;
  233. PrettyWriter<StringBuffer> writer(buffer);
  234. writer.StartArray();
  235. writer.String(buf);
  236. writer.EndArray();
  237. EXPECT_STREQ("[\n \"Hello\"\n]", buffer.GetString());
  238. EXPECT_TRUE(writer.IsComplete()); \
  239. }
  240. #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
  241. static PrettyWriter<StringBuffer> WriterGen(StringBuffer &target) {
  242. PrettyWriter<StringBuffer> writer(target);
  243. writer.StartObject();
  244. writer.Key("a");
  245. writer.Int(1);
  246. return writer;
  247. }
  248. TEST(PrettyWriter, MoveCtor) {
  249. StringBuffer buffer;
  250. PrettyWriter<StringBuffer> writer(WriterGen(buffer));
  251. writer.EndObject();
  252. EXPECT_TRUE(writer.IsComplete());
  253. EXPECT_STREQ(
  254. "{\n"
  255. " \"a\": 1\n"
  256. "}",
  257. buffer.GetString());
  258. }
  259. #endif
  260. #ifdef __clang__
  261. RAPIDJSON_DIAG_POP
  262. #endif