1 /*
2  * Copyright (C) 2011 Emweb bv, Herent, Belgium.
3  *
4  * See the LICENSE file for terms of use.
5  */
6 #include <boost/test/unit_test.hpp>
7 #include <boost/version.hpp>
8 
9 #include <Wt/Json/Parser.h>
10 #include <Wt/Json/Object.h>
11 #include <Wt/Json/Array.h>
12 
13 #include <fstream>
14 #include <streambuf>
15 
16 #if !defined(WT_NO_SPIRIT) && BOOST_VERSION >= 104100
17 #  define JSON_PARSER
18 #endif
19 
20 #ifdef JSON_PARSER
21 
22 #define JS(...) #__VA_ARGS__
23 
24 using namespace Wt;
25 
BOOST_AUTO_TEST_CASE(json_parse_empty_test)26 BOOST_AUTO_TEST_CASE( json_parse_empty_test )
27 {
28   Json::Value result;
29   Json::parse("{}", result);
30 
31   BOOST_REQUIRE(result.type() == Json::Type::Object);
32   BOOST_REQUIRE(((const Json::Object&) result).empty());
33 }
34 
BOOST_AUTO_TEST_CASE(json_parse_object1_test)35 BOOST_AUTO_TEST_CASE( json_parse_object1_test )
36 {
37   Json::Object result;
38   Json::parse("{ "
39 	      "  \"a\": \"That's great\", "
40 	      "  \"b\": true "
41 	      "}",
42 	      result);
43   BOOST_REQUIRE(result.size() == 2);
44 
45   WString a = result.get("a");
46   bool b = result.get("b");
47 
48   BOOST_REQUIRE(a == "That's great");
49   BOOST_REQUIRE(b == true);
50 }
51 
BOOST_AUTO_TEST_CASE(json_parse_object2_test)52 BOOST_AUTO_TEST_CASE( json_parse_object2_test )
53 {
54   Json::Object result;
55   Json::parse("{ \"a\": 5 }", result);
56 
57   BOOST_REQUIRE(result.size() == 1);
58 
59   int i = result.get("a");
60 
61   BOOST_REQUIRE(i == 5);
62 }
63 
BOOST_AUTO_TEST_CASE(json_parse_strings_test)64 BOOST_AUTO_TEST_CASE( json_parse_strings_test )
65 {
66   Json::Object result;
67   Json::parse(JS({
68 	"s1": "simple",
69 	"s2": "escaped: \\ \t \n \b \r",
70 	"s3": "unicode: \u0194"
71 	  }), result);
72 
73   BOOST_REQUIRE(result.size() == 3);
74 
75   const WString& s1 = result.get("s1");
76   BOOST_REQUIRE(s1 == "simple");
77   const WString& s2 = result.get("s2");
78   BOOST_REQUIRE(s2 == "escaped: \\ \t \n \b \r");
79   const WString& s3 = result.get("s3");
80   BOOST_REQUIRE(s3 == L"unicode: \x0194");
81 }
82 
BOOST_AUTO_TEST_CASE(json_structure_test)83 BOOST_AUTO_TEST_CASE( json_structure_test )
84 {
85   Json::Object result;
86   Json::parse(JS({
87      "firstName": "John",
88      "lastName": "Smith",
89      "age": 25,
90      "address":
91      {
92          "streetAddress": "21 2nd Street",
93          "city": "New York",
94          "state": "NY",
95          "postalCode": "10021"
96      },
97      "phoneNumber":
98      [
99          {
100            "type": "home",
101            "number": "212 555-1234"
102          },
103          {
104            "type": "fax",
105            "number": "646 555-4567"
106          }
107      ]
108 	  }), result);
109 
110   BOOST_REQUIRE(result.size() == 5);
111 
112   const Json::Array& phoneNumbers = result.get("phoneNumber");
113   BOOST_REQUIRE(phoneNumbers.size() == 2);
114 
115   const Json::Object& p1 = phoneNumbers[0];
116   WString t1 = p1.get("type");
117   WString n1 = p1.get("number");
118   BOOST_REQUIRE(t1 == "home");
119   BOOST_REQUIRE(n1 == "212 555-1234");
120 }
121 
BOOST_AUTO_TEST_CASE(json_bad_test)122 BOOST_AUTO_TEST_CASE( json_bad_test )
123 {
124   bool caught = false;
125 
126   try {
127     Json::Object result;
128     Json::parse("{ \"Field1\": \"one\" \n \"Field2\" : \"two\" }", result);
129   } catch (std::exception& e) {
130     caught = true;
131   }
132 
133   BOOST_REQUIRE(caught);
134 }
135 
BOOST_AUTO_TEST_CASE(json_utf8_test)136 BOOST_AUTO_TEST_CASE( json_utf8_test )
137 {
138   std::ifstream t("json/UTF-8-test.json", std::ios::in | std::ios::binary);
139   BOOST_REQUIRE(t.good());
140   std::string str((std::istreambuf_iterator<char>(t)),
141                    std::istreambuf_iterator<char>());
142 
143   Json::Object result;
144   Json::parse(str, result);
145   WString s1 = result.get("kosme");
146   WString s2 = result.get("2 bytes (U-00000080)");
147   WString s3 = result.get("3 bytes (U-00000800)");
148   WString s4 = result.get("4 bytes (U-00010000)");
149   WString s5 = result.get("1 byte  (U-0000007F)");
150   WString s6 = result.get("2 bytes (U-000007FF)");
151   WString s7 = result.get("3 bytes (U-0000FFFF)");
152   WString s8 = result.get("U-0000D7FF = ed 9f bf");
153   WString s9 = result.get("U-0000E000 = ee 80 80");
154   WString s10 = result.get("U-0000FFFD = ef bf bd");
155   WString s11 = result.get("U-0010FFFF = f4 8f bf bf");
156 
157   std::u32string u32s1 = s1.toUTF32();
158   std::u32string u32s2 = s2.toUTF32();
159   std::u32string u32s3 = s3.toUTF32();
160   std::u32string u32s4 = s4.toUTF32();
161   std::u32string u32s5 = s5.toUTF32();
162   std::u32string u32s6 = s6.toUTF32();
163   std::u32string u32s7 = s7.toUTF32();
164   std::u32string u32s8 = s8.toUTF32();
165   std::u32string u32s9 = s9.toUTF32();
166   std::u32string u32s10 = s10.toUTF32();
167   std::u32string u32s11 = s11.toUTF32();
168 
169   BOOST_REQUIRE(u32s1[0] == 954);
170   BOOST_REQUIRE(u32s1[1] == 8057);
171   BOOST_REQUIRE(u32s1[2] == 963);
172   BOOST_REQUIRE(u32s1[3] == 956);
173   BOOST_REQUIRE(u32s1[4] == 949);
174   BOOST_REQUIRE(u32s2[0] == 128);
175   BOOST_REQUIRE(u32s3[0] == 2048);
176   BOOST_REQUIRE(u32s4[0] == 65533 || u32s4[0] == 65536);
177   BOOST_REQUIRE(u32s5[0] == 127);
178   BOOST_REQUIRE(u32s6[0] == 2047);
179   BOOST_REQUIRE(u32s7[0] == 65535);
180   BOOST_REQUIRE(u32s8[0] == 55295);
181   BOOST_REQUIRE(u32s9[0] == 57344);
182   BOOST_REQUIRE(u32s10[0] == 65533);
183   BOOST_REQUIRE(u32s11[0] == '?'); // should this really be rejected?
184 
185   BOOST_REQUIRE(result.size() == 11);
186 }
187 
188 
189 #endif // JSON_PARSER
190