blob: 301a064d9bc68ab0761e1abdf20a9072dae4ccd0 [file] [log] [blame]
David Reissea2cba82009-03-30 21:35:00 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
Jake Farrell5d02b802014-01-07 21:42:01 -050020#define _USE_MATH_DEFINES
David Reissdb0ea152008-02-18 01:49:37 +000021#include <cmath>
Konrad Grochowskia84e1392015-10-16 11:22:10 +020022#include <iomanip>
23#include <sstream>
Roger Meier49ff8b12012-04-13 09:12:31 +000024#include <thrift/transport/TBufferTransports.h>
25#include <thrift/protocol/TJSONProtocol.h>
David Reissdb0ea152008-02-18 01:49:37 +000026#include "gen-cpp/DebugProtoTest_types.h"
27
Claudius Heine5ef662b2015-06-24 10:03:50 +020028#define BOOST_TEST_MODULE JSONProtoTest
29#include <boost/test/unit_test.hpp>
David Reissdb0ea152008-02-18 01:49:37 +000030
Claudius Heine5ef662b2015-06-24 10:03:50 +020031using namespace thrift::test::debug;
32using apache::thrift::transport::TMemoryBuffer;
33using apache::thrift::protocol::TJSONProtocol;
David Reissdb0ea152008-02-18 01:49:37 +000034
Claudius Heine5ef662b2015-06-24 10:03:50 +020035static std::auto_ptr<OneOfEach> ooe;
David Reissdb0ea152008-02-18 01:49:37 +000036
Claudius Heine5ef662b2015-06-24 10:03:50 +020037void testCaseSetup_1() {
38 ooe.reset(new OneOfEach);
39 ooe->im_true = true;
40 ooe->im_false = false;
41 ooe->a_bite = 0x7f;
42 ooe->integer16 = 27000;
43 ooe->integer32 = 1 << 24;
44 ooe->integer64 = (uint64_t)6000 * 1000 * 1000;
45 ooe->double_precision = M_PI;
46 ooe->some_characters = "JSON THIS! \"\1";
47 ooe->zomg_unicode = "\xd7\n\a\t";
48 ooe->base64 = "\1\2\3\255";
49}
David Reissdb0ea152008-02-18 01:49:37 +000050
Claudius Heine5ef662b2015-06-24 10:03:50 +020051BOOST_AUTO_TEST_CASE(test_json_proto_1) {
52 testCaseSetup_1();
David Reissdb0ea152008-02-18 01:49:37 +000053
Claudius Heine5ef662b2015-06-24 10:03:50 +020054 const std::string expected_result(
55 "{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127},\"4\":{\"i16\":27000},"
56 "\"5\":{\"i32\":16777216},\"6\":{\"i64\":6000000000},\"7\":{\"dbl\":3.1415926"
Wang Yaofu0433d172016-02-15 10:43:09 +080057 "535897931},\"8\":{\"str\":\"JSON THIS! \\\"\\u0001\"},\"9\":{\"str\":\"\xd7\\"
Claudius Heine5ef662b2015-06-24 10:03:50 +020058 "n\\u0007\\t\"},\"10\":{\"tf\":0},\"11\":{\"str\":\"AQIDrQ\"},\"12\":{\"lst\""
59 ":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64"
60 "\",3,1,2,3]}}");
61
62 const std::string result(apache::thrift::ThriftJSONString(*ooe));
63
64 BOOST_CHECK_MESSAGE(!expected_result.compare(result),
65 "Expected:\n" << expected_result << "\nGotten:\n" << result);
66}
67
68static std::auto_ptr<Nesting> n;
69
70void testCaseSetup_2() {
71 testCaseSetup_1();
72
73 n.reset(new Nesting);
74 n->my_ooe = *ooe;
75 n->my_ooe.integer16 = 16;
76 n->my_ooe.integer32 = 32;
77 n->my_ooe.integer64 = 64;
78 n->my_ooe.double_precision = (std::sqrt(5.0) + 1) / 2;
79 n->my_ooe.some_characters = ":R (me going \"rrrr\")";
80 n->my_ooe.zomg_unicode = "\xd3\x80\xe2\x85\xae\xce\x9d\x20\xd0\x9d\xce"
81 "\xbf\xe2\x85\xbf\xd0\xbe\xc9\xa1\xd0\xb3\xd0"
82 "\xb0\xcf\x81\xe2\x84\x8e\x20\xce\x91\x74\x74"
83 "\xce\xb1\xe2\x85\xbd\xce\xba\xc7\x83\xe2\x80"
84 "\xbc";
85 n->my_bonk.type = 31337;
86 n->my_bonk.message = "I am a bonk... xor!";
87}
88
89BOOST_AUTO_TEST_CASE(test_json_proto_2) {
90 testCaseSetup_2();
91
92 const std::string expected_result(
93 "{\"1\":{\"rec\":{\"1\":{\"i32\":31337},\"2\":{\"str\":\"I am a bonk... xor"
94 "!\"}}},\"2\":{\"rec\":{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127"
95 "},\"4\":{\"i16\":16},\"5\":{\"i32\":32},\"6\":{\"i64\":64},\"7\":{\"dbl\":"
Wang Yaofu0433d172016-02-15 10:43:09 +080096 "1.6180339887498949},\"8\":{\"str\":\":R (me going \\\"rrrr\\\")\"},\"9\":{"
Claudius Heine5ef662b2015-06-24 10:03:50 +020097 "\"str\":\"ӀⅮΝ Нοⅿоɡгаρℎ Αttαⅽκǃ‼\"},\"10\":{\"tf\":0},\"11\":{\"str\":\""
98 "AQIDrQ\"},\"12\":{\"lst\":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2"
99 ",3]},\"14\":{\"lst\":[\"i64\",3,1,2,3]}}}}"
100 );
101
102 const std::string result(apache::thrift::ThriftJSONString(*n));
103
104 BOOST_CHECK_MESSAGE(!expected_result.compare(result),
105 "Expected:\n" << expected_result << "\nGotten:\n" << result);
106}
107
108static std::auto_ptr<HolyMoley> hm;
109
110void testCaseSetup_3() {
111 testCaseSetup_2();
112
113 hm.reset(new HolyMoley);
114
115 hm->big.push_back(*ooe);
116 hm->big.push_back(n->my_ooe);
117 hm->big[0].a_bite = 0x22;
118 hm->big[1].a_bite = 0x33;
David Reissdb0ea152008-02-18 01:49:37 +0000119
120 std::vector<std::string> stage1;
121 stage1.push_back("and a one");
122 stage1.push_back("and a two");
Claudius Heine5ef662b2015-06-24 10:03:50 +0200123 hm->contain.insert(stage1);
David Reissdb0ea152008-02-18 01:49:37 +0000124 stage1.clear();
125 stage1.push_back("then a one, two");
126 stage1.push_back("three!");
127 stage1.push_back("FOUR!!");
Claudius Heine5ef662b2015-06-24 10:03:50 +0200128 hm->contain.insert(stage1);
David Reissdb0ea152008-02-18 01:49:37 +0000129 stage1.clear();
Claudius Heine5ef662b2015-06-24 10:03:50 +0200130 hm->contain.insert(stage1);
David Reissdb0ea152008-02-18 01:49:37 +0000131
132 std::vector<Bonk> stage2;
Claudius Heine5ef662b2015-06-24 10:03:50 +0200133 hm->bonks["nothing"] = stage2;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100134 stage2.resize(stage2.size() + 1);
David Reissdb0ea152008-02-18 01:49:37 +0000135 stage2.back().type = 1;
136 stage2.back().message = "Wait.";
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100137 stage2.resize(stage2.size() + 1);
David Reissdb0ea152008-02-18 01:49:37 +0000138 stage2.back().type = 2;
139 stage2.back().message = "What?";
Claudius Heine5ef662b2015-06-24 10:03:50 +0200140 hm->bonks["something"] = stage2;
David Reissdb0ea152008-02-18 01:49:37 +0000141 stage2.clear();
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100142 stage2.resize(stage2.size() + 1);
David Reissdb0ea152008-02-18 01:49:37 +0000143 stage2.back().type = 3;
144 stage2.back().message = "quoth";
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100145 stage2.resize(stage2.size() + 1);
David Reissdb0ea152008-02-18 01:49:37 +0000146 stage2.back().type = 4;
147 stage2.back().message = "the raven";
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100148 stage2.resize(stage2.size() + 1);
David Reissdb0ea152008-02-18 01:49:37 +0000149 stage2.back().type = 5;
150 stage2.back().message = "nevermore";
Claudius Heine5ef662b2015-06-24 10:03:50 +0200151 hm->bonks["poe"] = stage2;
152}
David Reissdb0ea152008-02-18 01:49:37 +0000153
Claudius Heine5ef662b2015-06-24 10:03:50 +0200154BOOST_AUTO_TEST_CASE(test_json_proto_3) {
155 testCaseSetup_3();
156
157 const std::string expected_result(
158 "{\"1\":{\"lst\":[\"rec\",2,{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":"
159 "34},\"4\":{\"i16\":27000},\"5\":{\"i32\":16777216},\"6\":{\"i64\":6000000000"
Wang Yaofu0433d172016-02-15 10:43:09 +0800160 "},\"7\":{\"dbl\":3.1415926535897931},\"8\":{\"str\":\"JSON THIS! \\\"\\u0001"
Claudius Heine5ef662b2015-06-24 10:03:50 +0200161 "\"},\"9\":{\"str\":\"\xd7\\n\\u0007\\t\"},\"10\":{\"tf\":0},\"11\":{\"str\":"
162 "\"AQIDrQ\"},\"12\":{\"lst\":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2"
163 ",3]},\"14\":{\"lst\":[\"i64\",3,1,2,3]}},{\"1\":{\"tf\":1},\"2\":{\"tf\":0},"
164 "\"3\":{\"i8\":51},\"4\":{\"i16\":16},\"5\":{\"i32\":32},\"6\":{\"i64\":64},"
Wang Yaofu0433d172016-02-15 10:43:09 +0800165 "\"7\":{\"dbl\":1.6180339887498949},\"8\":{\"str\":\":R (me going \\\"rrrr\\\""
Claudius Heine5ef662b2015-06-24 10:03:50 +0200166 ")\"},\"9\":{\"str\":\"ӀⅮΝ Нοⅿоɡгаρℎ Αttαⅽκǃ‼\"},\"10\":{\"tf\":0},\"11\":{"
167 "\"str\":\"AQIDrQ\"},\"12\":{\"lst\":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16"
168 "\",3,1,2,3]},\"14\":{\"lst\":[\"i64\",3,1,2,3]}}]},\"2\":{\"set\":[\"lst\",3"
169 ",[\"str\",0],[\"str\",2,\"and a one\",\"and a two\"],[\"str\",3,\"then a one"
170 ", two\",\"three!\",\"FOUR!!\"]]},\"3\":{\"map\":[\"str\",\"lst\",3,{\"nothin"
171 "g\":[\"rec\",0],\"poe\":[\"rec\",3,{\"1\":{\"i32\":3},\"2\":{\"str\":\"quoth"
172 "\"}},{\"1\":{\"i32\":4},\"2\":{\"str\":\"the raven\"}},{\"1\":{\"i32\":5},\""
173 "2\":{\"str\":\"nevermore\"}}],\"something\":[\"rec\",2,{\"1\":{\"i32\":1},\""
174 "2\":{\"str\":\"Wait.\"}},{\"1\":{\"i32\":2},\"2\":{\"str\":\"What?\"}}]}]}}"
175 );
176
177 const std::string result(apache::thrift::ThriftJSONString(*hm));
178
179 BOOST_CHECK_MESSAGE(!expected_result.compare(result),
180 "Expected:\n" << expected_result << "\nGotten:\n" << result);
181}
182
183BOOST_AUTO_TEST_CASE(test_json_proto_4) {
184 testCaseSetup_1();
David Reissdb0ea152008-02-18 01:49:37 +0000185
186 boost::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
187 boost::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
188
Claudius Heine5ef662b2015-06-24 10:03:50 +0200189 ooe->write(proto.get());
David Reissdb0ea152008-02-18 01:49:37 +0000190 OneOfEach ooe2;
191 ooe2.read(proto.get());
192
Claudius Heine5ef662b2015-06-24 10:03:50 +0200193 BOOST_CHECK(*ooe == ooe2);
194}
David Reissdb0ea152008-02-18 01:49:37 +0000195
Claudius Heine5ef662b2015-06-24 10:03:50 +0200196BOOST_AUTO_TEST_CASE(test_json_proto_5) {
197 testCaseSetup_3();
David Reissdb0ea152008-02-18 01:49:37 +0000198
Claudius Heine5ef662b2015-06-24 10:03:50 +0200199 boost::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
200 boost::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
201
202 hm->write(proto.get());
David Reissdb0ea152008-02-18 01:49:37 +0000203 HolyMoley hm2;
204 hm2.read(proto.get());
205
Claudius Heine5ef662b2015-06-24 10:03:50 +0200206 BOOST_CHECK(*hm == hm2);
David Reissdb0ea152008-02-18 01:49:37 +0000207
Christian Lavoiecbf87cb2010-11-28 14:34:26 +0000208 hm2.big[0].a_bite = 0x00;
David Reiss4a8f46c2008-03-07 20:12:07 +0000209
Claudius Heine5ef662b2015-06-24 10:03:50 +0200210 BOOST_CHECK(*hm != hm2);
211}
David Reiss4a8f46c2008-03-07 20:12:07 +0000212
Claudius Heine5ef662b2015-06-24 10:03:50 +0200213BOOST_AUTO_TEST_CASE(test_json_proto_6) {
David Reissdb0ea152008-02-18 01:49:37 +0000214 Doubles dub;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100215 dub.nan = HUGE_VAL / HUGE_VAL;
David Reissdb0ea152008-02-18 01:49:37 +0000216 dub.inf = HUGE_VAL;
217 dub.neginf = -HUGE_VAL;
Konrad Grochowski16a23a62014-11-13 15:33:38 +0100218 dub.repeating = 10.0 / 3.0;
David Reissdb0ea152008-02-18 01:49:37 +0000219 dub.big = 1E+305;
Roger Meier22888ce2014-02-09 11:31:02 +0100220 dub.tiny = 1E-305;
David Reissdb0ea152008-02-18 01:49:37 +0000221 dub.zero = 0.0;
222 dub.negzero = -0.0;
David Reissdb0ea152008-02-18 01:49:37 +0000223
Claudius Heine5ef662b2015-06-24 10:03:50 +0200224 const std::string expected_result(
225 "{\"1\":{\"dbl\":\"NaN\"},\"2\":{\"dbl\":\"Infinity\"},\"3\":{\"dbl\":\"-Infi"
Wang Yaofu0433d172016-02-15 10:43:09 +0800226 "nity\"},\"4\":{\"dbl\":3.3333333333333335},\"5\":{\"dbl\":9.9999999999999994e+"
Claudius Heine5ef662b2015-06-24 10:03:50 +0200227 "304},\"6\":{\"dbl\":1e-305},\"7\":{\"dbl\":0},\"8\":{\"dbl\":-0}}"
228 );
229
230 const std::string result(apache::thrift::ThriftJSONString(dub));
231
232 BOOST_CHECK_MESSAGE(!expected_result.compare(result),
233 "Expected:\n" << expected_result << "\nGotten:\n" << result);
234}
235
236BOOST_AUTO_TEST_CASE(test_json_proto_7) {
237 boost::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
238 boost::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
David Reiss4a8f46c2008-03-07 20:12:07 +0000239
240 Base64 base;
241 base.a = 123;
242 base.b1 = "1";
243 base.b2 = "12";
244 base.b3 = "123";
245 base.b4 = "1234";
246 base.b5 = "12345";
247 base.b6 = "123456";
248
249 base.write(proto.get());
250 Base64 base2;
251 base2.read(proto.get());
252
Claudius Heine5ef662b2015-06-24 10:03:50 +0200253 BOOST_CHECK(base == base2);
David Reissdb0ea152008-02-18 01:49:37 +0000254}
Claudius Heine8f11f522015-07-01 10:35:38 +0200255
256BOOST_AUTO_TEST_CASE(test_json_proto_8) {
257 const char* json_string =
258 "{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127},\"4\":{\"i16\":27000},"
259 "\"5\":{\"i32\":16.77216},\"6\":{\"i64\":6000000000},\"7\":{\"dbl\":3.1415926"
Wang Yaofu0433d172016-02-15 10:43:09 +0800260 "535897931},\"8\":{\"str\":\"JSON THIS! \\\"\\u0001\"},\"9\":{\"str\":\"\xd7\\"
Claudius Heine8f11f522015-07-01 10:35:38 +0200261 "n\\u0007\\t\"},\"10\":{\"tf\":0},\"11\":{\"str\":\"AQIDrQ\"},\"12\":{\"lst\""
262 ":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64"
263 "\",3,1,2,3]}}";
264
265 boost::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
266 (uint8_t*)(json_string), strlen(json_string)*sizeof(char)));
267 boost::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
268
269 OneOfEach ooe2;
270
271 BOOST_CHECK_THROW(ooe2.read(proto.get()),
272 apache::thrift::protocol::TProtocolException);
273}
Konrad Grochowskia84e1392015-10-16 11:22:10 +0200274
275static std::string toHexSequence(const std::string& str) {
276 std::stringstream ss;
277 ss << std::hex << std::setfill('0');
278 for (std::size_t i = 0; i < str.size(); i++) {
279 ss << "\\x" << int(uint8_t(str[i]));
280 }
281 return ss.str();
282}
283
284BOOST_AUTO_TEST_CASE(test_json_unicode_escaped) {
285 const char json_string[] =
286 "{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127},\"4\":{\"i16\":27000},"
287 "\"5\":{\"i32\":16},\"6\":{\"i64\":6000000000},\"7\":{\"dbl\":3.1415926"
Wang Yaofu0433d172016-02-15 10:43:09 +0800288 "535897931},\"8\":{\"str\":\"JSON THIS!\"},\"9\":{\"str\":\"\\u0e01 \\ud835\\udd3e\"},"
Konrad Grochowskia84e1392015-10-16 11:22:10 +0200289 "\"10\":{\"tf\":0},\"11\":{\"str\":\"000000\"},\"12\":{\"lst\""
290 ":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64"
291 "\",3,1,2,3]}}";
292 const char* expected_zomg_unicode = "\xe0\xb8\x81 \xf0\x9d\x94\xbe";
293
294 boost::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
295 (uint8_t*)(json_string), sizeof(json_string)));
296 boost::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
297
298 OneOfEach ooe2;
299 ooe2.read(proto.get());
300 BOOST_CHECK_MESSAGE(!ooe2.zomg_unicode.compare(expected_zomg_unicode),
301 "Expected:\n" << toHexSequence(expected_zomg_unicode) << "\nGotten:\n"
302 << toHexSequence(ooe2.zomg_unicode));
303
304}
305
306BOOST_AUTO_TEST_CASE(test_json_unicode_escaped_missing_low_surrogate) {
307 const char json_string[] =
308 "{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127},\"4\":{\"i16\":27000},"
309 "\"5\":{\"i32\":16},\"6\":{\"i64\":6000000000},\"7\":{\"dbl\":3.1415926"
Wang Yaofu0433d172016-02-15 10:43:09 +0800310 "535897931},\"8\":{\"str\":\"JSON THIS!\"},\"9\":{\"str\":\"\\ud835\"},"
Konrad Grochowskia84e1392015-10-16 11:22:10 +0200311 "\"10\":{\"tf\":0},\"11\":{\"str\":\"000000\"},\"12\":{\"lst\""
312 ":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64"
313 "\",3,1,2,3]}}";
314
315 boost::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
316 (uint8_t*)(json_string), sizeof(json_string)));
317 boost::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
318
319 OneOfEach ooe2;
320 BOOST_CHECK_THROW(ooe2.read(proto.get()),
321 apache::thrift::protocol::TProtocolException);
322}
323
324BOOST_AUTO_TEST_CASE(test_json_unicode_escaped_missing_hi_surrogate) {
325 const char json_string[] =
326 "{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127},\"4\":{\"i16\":27000},"
327 "\"5\":{\"i32\":16},\"6\":{\"i64\":6000000000},\"7\":{\"dbl\":3.1415926"
Wang Yaofu0433d172016-02-15 10:43:09 +0800328 "535897931},\"8\":{\"str\":\"JSON THIS!\"},\"9\":{\"str\":\"\\udd3e\"},"
Konrad Grochowskia84e1392015-10-16 11:22:10 +0200329 "\"10\":{\"tf\":0},\"11\":{\"str\":\"000000\"},\"12\":{\"lst\""
330 ":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64"
331 "\",3,1,2,3]}}";
332
333 boost::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
334 (uint8_t*)(json_string), sizeof(json_string)));
335 boost::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
336
337 OneOfEach ooe2;
338 BOOST_CHECK_THROW(ooe2.read(proto.get()),
339 apache::thrift::protocol::TProtocolException);
340}