]>
git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/thrift/test/cpp/src/TestClient.cpp
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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
25 #include <thrift/protocol/TBinaryProtocol.h>
26 #include <thrift/protocol/TCompactProtocol.h>
27 #include <thrift/protocol/THeaderProtocol.h>
28 #include <thrift/protocol/TJSONProtocol.h>
29 #include <thrift/protocol/TMultiplexedProtocol.h>
30 #include <thrift/transport/THttpClient.h>
31 #include <thrift/transport/TTransportUtils.h>
32 #include <thrift/transport/TSocket.h>
33 #include <thrift/transport/TSSLSocket.h>
34 #include <thrift/transport/TZlibTransport.h>
35 #include <thrift/async/TEvhttpClientChannel.h>
36 #include <thrift/server/TNonblockingServer.h> // <event.h>
41 #ifdef HAVE_INTTYPES_H
45 #include <boost/algorithm/string.hpp>
46 #include <boost/filesystem.hpp>
47 #include <boost/program_options.hpp>
48 #include <boost/random/random_device.hpp>
50 #include <thrift/windows/TWinsockSingleton.h>
53 #include "SecondService.h"
54 #include "ThriftTest.h"
57 using namespace apache::thrift
;
58 using namespace apache::thrift::async
;
59 using namespace apache::thrift::protocol
;
60 using namespace apache::thrift::transport
;
61 using namespace thrift::test
;
64 // A pedantic protocol that checks to make sure the response sequence ID
65 // is the same as the sent sequence ID. lib/cpp always sends zero for
66 // synchronous clients, so this bumps the number to make sure it gets
67 // returned properly from the remote server. Any server that does not
68 // respond with the same sequence number is violating the sequence ID
69 // agreement between client and server.
72 template<typename Proto
>
73 class TPedanticProtocol
: public Proto
76 TPedanticProtocol(std::shared_ptr
<TTransport
>& transport
)
77 : Proto(transport
), m_last_seqid((std::numeric_limits
<int32_t>::max
)() - 10) { }
79 virtual uint32_t writeMessageBegin_virt(const std::string
& name
,
80 const TMessageType messageType
,
81 const int32_t in_seqid
) override
83 int32_t seqid
= in_seqid
;
84 if (!seqid
) { // this is typical for normal cpp generated code
85 seqid
= ++m_last_seqid
;
88 return Proto::writeMessageBegin_virt(name
, messageType
, seqid
);
91 virtual uint32_t readMessageBegin_virt(std::string
& name
,
92 TMessageType
& messageType
,
93 int32_t& seqid
) override
95 uint32_t result
= Proto::readMessageBegin_virt(name
, messageType
, seqid
);
96 if (seqid
!= m_last_seqid
) {
98 ss
<< "ERROR: send request with seqid " << m_last_seqid
<< " and got reply with seqid " << seqid
;
99 throw std::logic_error(ss
.str());
101 std::cout << "verified seqid " << m_last_seqid << " round trip OK" << std::endl;
107 int32_t m_last_seqid
;
110 // Current time, microseconds since the epoch
115 THRIFT_GETTIMEOFDAY(&tv
, nullptr);
117 ret
= ret
* 1000 * 1000 + tv
.tv_usec
;
121 static void testString_clientReturn(event_base
* base
,
123 ThriftTestCobClient
* client
) {
126 client
->recv_testString(s
);
127 std::ostringstream os
;
128 os
<< "test" << testNr
;
129 const bool ok
= (s
== os
.str());
130 cout
<< "testString: " << s
<< " " << ((ok
) ? "ok" : "failed") << endl
;
131 } catch (TException
& exn
) {
132 cout
<< "Error: " << exn
.what() << endl
;
136 event_base_loopbreak(base
); // end test
139 static void testVoid_clientReturn(event_base
* base
, ThriftTestCobClient
* client
) {
141 client
->recv_testVoid();
142 cout
<< "testVoid" << endl
;
144 for (int testNr
= 0; testNr
< 10; ++testNr
) {
145 std::ostringstream os
;
146 os
<< "test" << testNr
;
147 client
->testString(std::bind(testString_clientReturn
,
150 std::placeholders::_1
),
153 } catch (TException
& exn
) {
154 cout
<< "Error: " << exn
.what() << endl
;
158 // Workaround for absense of C++11 "auto" keyword.
159 template <typename T
>
160 bool print_eq(T expected
, T actual
) {
161 cout
<< "(" << actual
<< ")" << endl
;
162 if (expected
!= actual
) {
163 cout
<< "*** FAILED ***" << endl
<< "Expected: " << expected
<< " but got: " << actual
<< endl
;
169 #define BASETYPE_IDENTITY_TEST(func, value) \
170 cout << #func "(" << value << ") = "; \
172 if (!print_eq(value, testClient.func(value))) \
173 return_code |= ERR_BASETYPES; \
174 } catch (TTransportException&) { \
176 } catch (exception & ex) { \
177 cout << "*** FAILED ***" << endl << ex.what() << endl; \
178 return_code |= ERR_BASETYPES; \
181 int binary_test(ThriftTestClient
& testClient
, string::size_type siz
);
183 BOOST_CONSTEXPR_OR_CONST
int ERR_BASETYPES
= 1;
184 BOOST_CONSTEXPR_OR_CONST
int ERR_STRUCTS
= 2;
185 BOOST_CONSTEXPR_OR_CONST
int ERR_CONTAINERS
= 4;
186 BOOST_CONSTEXPR_OR_CONST
int ERR_EXCEPTIONS
= 8;
187 BOOST_CONSTEXPR_OR_CONST
int ERR_UNKNOWN
= 64;
189 int main(int argc
, char** argv
) {
192 string testDir
= boost::filesystem::system_complete(argv
[0]).parent_path().parent_path().parent_path().string();
193 string caPath
= testDir
+ "/keys/CA.pem";
194 string certPath
= testDir
+ "/keys/client.crt";
195 string keyPath
= testDir
+ "/keys/client.key";
198 transport::TWinsockSingleton::create();
200 string host
= "localhost";
205 string transport_type
= "buffered";
206 string protocol_type
= "binary";
207 string domain_socket
= "";
208 bool abstract_namespace
= false;
209 bool noinsane
= false;
213 boost::program_options::options_description
desc("Allowed options");
215 ("help,h", "produce help message")
217 boost::program_options::value
<string
>(&host
)->default_value(host
),
220 boost::program_options::value
<int>(&port
)->default_value(port
),
221 "Port number to connect")
223 boost::program_options::value
<string
>(&domain_socket
)->default_value(domain_socket
),
224 "Domain Socket (e.g. /tmp/ThriftTest.thrift), instead of host and port")
225 ("abstract-namespace",
226 "Look for the domain socket in the Abstract Namespace"
227 " (no connection with filesystem pathnames)")
229 boost::program_options::value
<string
>(&transport_type
)->default_value(transport_type
),
230 "Transport: buffered, framed, http, evhttp, zlib")
232 boost::program_options::value
<string
>(&protocol_type
)->default_value(protocol_type
),
233 "Protocol: binary, compact, header, json, multi, multic, multih, multij")
235 "Encrypted Transport using SSL")
237 "Wrap Transport with Zlib")
239 boost::program_options::value
<int>(&numTests
)->default_value(numTests
),
242 "Do not run insanity test");
244 boost::program_options::variables_map vm
;
245 boost::program_options::store(boost::program_options::parse_command_line(argc
, argv
, desc
), vm
);
246 boost::program_options::notify(vm
);
248 if (vm
.count("help")) {
249 cout
<< desc
<< endl
;
254 if (!protocol_type
.empty()) {
255 if (protocol_type
== "binary") {
256 } else if (protocol_type
== "compact") {
257 } else if (protocol_type
== "header") {
258 } else if (protocol_type
== "json") {
259 } else if (protocol_type
== "multi") {
260 } else if (protocol_type
== "multic") {
261 } else if (protocol_type
== "multih") {
262 } else if (protocol_type
== "multij") {
264 throw invalid_argument("Unknown protocol type " + protocol_type
);
268 if (!transport_type
.empty()) {
269 if (transport_type
== "buffered") {
270 } else if (transport_type
== "framed") {
271 } else if (transport_type
== "http") {
272 } else if (transport_type
== "evhttp") {
273 } else if (transport_type
== "zlib") {
274 // crosstest will pass zlib as a transport and as a flag right now..
276 throw invalid_argument("Unknown transport type " + transport_type
);
280 } catch (exception
& e
) {
281 cerr
<< e
.what() << endl
;
282 cout
<< desc
<< endl
;
286 if (vm
.count("ssl")) {
290 if (vm
.count("zlib")) {
294 if (vm
.count("abstract-namespace")) {
295 abstract_namespace
= true;
298 if (vm
.count("noinsane")) {
302 // THRIFT-4164: The factory MUST outlive any sockets it creates for correct behavior!
303 std::shared_ptr
<TSSLSocketFactory
> factory
;
304 std::shared_ptr
<TSocket
> socket
;
305 std::shared_ptr
<TTransport
> transport
;
306 std::shared_ptr
<TProtocol
> protocol
;
307 std::shared_ptr
<TProtocol
> protocol2
; // SecondService for multiplexed
310 cout
<< "Client Certificate File: " << certPath
<< endl
;
311 cout
<< "Client Key File: " << keyPath
<< endl
;
312 cout
<< "CA File: " << caPath
<< endl
;
314 factory
= std::shared_ptr
<TSSLSocketFactory
>(new TSSLSocketFactory());
315 factory
->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
316 factory
->loadTrustedCertificates(caPath
.c_str());
317 factory
->loadCertificate(certPath
.c_str());
318 factory
->loadPrivateKey(keyPath
.c_str());
319 factory
->authenticate(true);
320 socket
= factory
->createSocket(host
, port
);
322 if (domain_socket
!= "") {
323 if (abstract_namespace
) {
324 std::string
abstract_socket("\0", 1);
325 abstract_socket
+= domain_socket
;
326 socket
= std::shared_ptr
<TSocket
>(new TSocket(abstract_socket
));
328 socket
= std::shared_ptr
<TSocket
>(new TSocket(domain_socket
));
332 socket
= std::shared_ptr
<TSocket
>(new TSocket(host
, port
));
336 if (transport_type
.compare("http") == 0) {
337 transport
= std::make_shared
<THttpClient
>(socket
, host
, "/service");
338 } else if (transport_type
.compare("framed") == 0) {
339 transport
= std::make_shared
<TFramedTransport
>(socket
);
341 transport
= std::make_shared
<TBufferedTransport
>(socket
);
345 transport
= std::make_shared
<TZlibTransport
>(transport
);
348 if (protocol_type
== "json" || protocol_type
== "multij") {
349 typedef TPedanticProtocol
<TJSONProtocol
> TPedanticJSONProtocol
;
350 protocol
= std::make_shared
<TPedanticJSONProtocol
>(transport
);
351 } else if (protocol_type
== "compact" || protocol_type
== "multic") {
352 typedef TPedanticProtocol
<TCompactProtocol
> TPedanticCompactProtocol
;
353 protocol
= std::make_shared
<TPedanticCompactProtocol
>(transport
);
354 } else if (protocol_type
== "header" || protocol_type
== "multih") {
355 typedef TPedanticProtocol
<THeaderProtocol
> TPedanticHeaderProtocol
;
356 protocol
= std::make_shared
<TPedanticHeaderProtocol
>(transport
);
358 typedef TPedanticProtocol
<TBinaryProtocol
> TPedanticBinaryProtocol
;
359 protocol
= std::make_shared
<TPedanticBinaryProtocol
>(transport
);
362 if (boost::starts_with(protocol_type
, "multi")) {
363 protocol2
= std::make_shared
<TMultiplexedProtocol
>(protocol
, "SecondService");
364 // we don't need access to the original protocol any more, so...
365 protocol
= std::make_shared
<TMultiplexedProtocol
>(protocol
, "ThriftTest");
369 cout
<< "Connecting (" << transport_type
<< "/" << protocol_type
<< ") to: ";
370 if (abstract_namespace
) {
373 cout
<< domain_socket
;
375 cout
<< host
<< ":" << port
;
379 if (transport_type
.compare("evhttp") == 0) {
380 event_base
* base
= event_base_new();
381 cout
<< "Libevent Version: " << event_get_version() << endl
;
382 cout
<< "Libevent Method: " << event_base_get_method(base
) << endl
;
383 #if LIBEVENT_VERSION_NUMBER >= 0x02000000
384 cout
<< "Libevent Features: 0x" << hex
<< event_base_get_features(base
) << endl
;
387 std::shared_ptr
<TProtocolFactory
> protocolFactory(new TBinaryProtocolFactory());
389 std::shared_ptr
<TAsyncChannel
> channel(
390 new TEvhttpClientChannel(host
.c_str(), "/", host
.c_str(), port
, base
));
391 ThriftTestCobClient
* client
= new ThriftTestCobClient(channel
, protocolFactory
.get());
392 client
->testVoid(std::bind(testVoid_clientReturn
,
394 std::placeholders::_1
));
396 event_base_loop(base
, 0);
400 ThriftTestClient
testClient(protocol
);
402 uint64_t time_min
= 0;
403 uint64_t time_max
= 0;
404 uint64_t time_tot
= 0;
407 for (test
= 0; test
< numTests
; ++test
) {
411 } catch (TTransportException
& ex
) {
412 cout
<< "Connect failed: " << ex
.what() << endl
;
419 printf("Test #%d, connect %s:%d\n", test
+ 1, host
.c_str(), port
);
421 uint64_t start
= now();
427 cout
<< "testVoid()" << flush
;
428 testClient
.testVoid();
429 cout
<< " = void" << endl
;
430 } catch (TTransportException
&) {
431 // Stop here if transport got broken
433 } catch (exception
& ex
) {
434 cout
<< "*** FAILED ***" << endl
<< ex
.what() << endl
;
435 return_code
|= ERR_BASETYPES
;
441 cout
<< "testString(\"Test\")" << flush
;
443 testClient
.testString(s
, "Test");
444 cout
<< " = " << s
<< endl
;
446 cout
<< "*** FAILED ***" << endl
;
447 return_code
|= ERR_BASETYPES
;
451 // Multiplexed protocol - call another service method
452 // in the middle of the ThriftTest
454 if (boost::starts_with(protocol_type
, "multi")) {
455 SecondServiceClient
ssc(protocol2
);
456 // transport is already open...
459 cout
<< "secondService.secondTestString(\"foo\") => " << flush
;
461 ssc
.secondtestString(result
, "foo");
462 cout
<< "{" << result
<< "}" << endl
;
463 } catch (std::exception
& e
) {
464 cout
<< " *** FAILED *** " << e
.what() << endl
;
465 return_code
|= ERR_EXCEPTIONS
;
471 #pragma warning( push )
472 #pragma warning( disable : 4566 )
475 "}{Afrikaans, Alemannisch, Aragonés, العربية, مصرى, "
476 "Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, "
477 "Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, "
478 "বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, "
479 "Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, "
480 "Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, "
481 "Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, "
482 "Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, "
483 "Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, "
484 "Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, "
485 "Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, "
486 "ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, "
487 "Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, "
488 "Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa "
489 "Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, مازِرونی, Bahasa "
490 "Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, "
491 "Norsk (nynorsk), Norsk (bokmål), Nouormand, Diné bizaad, "
492 "Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو, "
493 "Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română, "
494 "Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple "
495 "English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, "
496 "Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, "
497 "Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, "
498 "Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, "
501 #pragma warning( pop )
503 cout
<< "testString(" << str
<< ") = " << flush
;
504 testClient
.testString(s
, str
);
507 cout
.imbue(locale("en_US.UTF8"));
508 cout
<< "*** FAILED ***" << endl
<< "Expected string: " << str
<< " but got: " << s
<< endl
<< "CLEAR";
509 return_code
|= ERR_BASETYPES
;
511 } catch (TTransportException
&) {
513 } catch (exception
& ex
) {
514 cout
<< "*** FAILED ***" << endl
<< ex
.what() << endl
;
515 return_code
|= ERR_BASETYPES
;
520 "quote: \" backslash:"
521 " forwardslash-escaped: \\/ "
522 " backspace: \b formfeed: \f newline: \n return: \r tab: "
523 " now-all-of-them-together: \"\\\\/\b\n\r\t"
524 " now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><"
525 " char-to-test-json-parsing: ]] \"]] \\\" }}}{ [[[ ");
526 cout
<< "testString(" << str
<< ") = " << flush
;
527 testClient
.testString(s
, str
);
530 cout
.imbue(locale("en_US.UTF8"));
531 cout
<< "*** FAILED ***" << endl
532 << "Expected string: " << str
<< " but got: " << s
<< endl
535 return_code
|= ERR_BASETYPES
;
537 } catch (TTransportException
&) {
539 } catch (exception
& ex
) {
540 cout
<< "*** FAILED ***" << endl
<< ex
.what() << endl
;
541 return_code
|= ERR_BASETYPES
;
549 BASETYPE_IDENTITY_TEST(testBool
, true);
550 BASETYPE_IDENTITY_TEST(testBool
, false);
555 BASETYPE_IDENTITY_TEST(testByte
, (int8_t)0);
556 BASETYPE_IDENTITY_TEST(testByte
, (int8_t)-1);
557 BASETYPE_IDENTITY_TEST(testByte
, (int8_t)42);
558 BASETYPE_IDENTITY_TEST(testByte
, (int8_t)-42);
559 BASETYPE_IDENTITY_TEST(testByte
, (int8_t)127);
560 BASETYPE_IDENTITY_TEST(testByte
, (int8_t)-128);
565 BASETYPE_IDENTITY_TEST(testI32
, 0);
566 BASETYPE_IDENTITY_TEST(testI32
, -1);
567 BASETYPE_IDENTITY_TEST(testI32
, 190000013);
568 BASETYPE_IDENTITY_TEST(testI32
, -190000013);
569 BASETYPE_IDENTITY_TEST(testI32
, (numeric_limits
<int32_t>::max
)());
570 BASETYPE_IDENTITY_TEST(testI32
, (numeric_limits
<int32_t>::min
)());
575 BASETYPE_IDENTITY_TEST(testI64
, (int64_t)0);
576 BASETYPE_IDENTITY_TEST(testI64
, (int64_t)-1);
577 BASETYPE_IDENTITY_TEST(testI64
, (int64_t)7000000000000000123LL);
578 BASETYPE_IDENTITY_TEST(testI64
, (int64_t)-7000000000000000123LL);
579 BASETYPE_IDENTITY_TEST(testI64
, (int64_t)pow(static_cast<double>(2LL), 32));
580 BASETYPE_IDENTITY_TEST(testI64
, (int64_t)-pow(static_cast<double>(2LL), 32));
581 BASETYPE_IDENTITY_TEST(testI64
, (int64_t)pow(static_cast<double>(2LL), 32) + 1);
582 BASETYPE_IDENTITY_TEST(testI64
, (int64_t)-pow(static_cast<double>(2LL), 32) - 1);
583 BASETYPE_IDENTITY_TEST(testI64
, (numeric_limits
<int64_t>::max
)());
584 BASETYPE_IDENTITY_TEST(testI64
, (numeric_limits
<int64_t>::min
)());
589 // Comparing double values with plain equality because Thrift handles full precision of double
590 BASETYPE_IDENTITY_TEST(testDouble
, 0.0);
591 BASETYPE_IDENTITY_TEST(testDouble
, -1.0);
592 BASETYPE_IDENTITY_TEST(testDouble
, -5.2098523);
593 BASETYPE_IDENTITY_TEST(testDouble
, -0.000341012439638598279);
594 BASETYPE_IDENTITY_TEST(testDouble
, pow(static_cast<double>(2), 32));
595 BASETYPE_IDENTITY_TEST(testDouble
, pow(static_cast<double>(2), 32) + 1);
596 BASETYPE_IDENTITY_TEST(testDouble
, pow(static_cast<double>(2), 53) - 1);
597 BASETYPE_IDENTITY_TEST(testDouble
, -pow(static_cast<double>(2), 32));
598 BASETYPE_IDENTITY_TEST(testDouble
, -pow(static_cast<double>(2), 32) - 1);
599 BASETYPE_IDENTITY_TEST(testDouble
, -pow(static_cast<double>(2), 53) + 1);
602 double expected
= pow(static_cast<double>(10), 307);
603 cout
<< "testDouble(" << expected
<< ") = " << flush
;
604 double actual
= testClient
.testDouble(expected
);
605 cout
<< "(" << actual
<< ")" << endl
;
606 if (expected
- actual
> pow(static_cast<double>(10), 292)) {
607 cout
<< "*** FAILED ***" << endl
608 << "Expected: " << expected
<< " but got: " << actual
<< endl
;
610 } catch (TTransportException
&) {
612 } catch (exception
& ex
) {
613 cout
<< "*** FAILED ***" << endl
<< ex
.what() << endl
;
614 return_code
|= ERR_BASETYPES
;
618 double expected
= pow(static_cast<double>(10), -292);
619 cout
<< "testDouble(" << expected
<< ") = " << flush
;
620 double actual
= testClient
.testDouble(expected
);
621 cout
<< "(" << actual
<< ")" << endl
;
622 if (expected
- actual
> pow(static_cast<double>(10), -307)) {
623 cout
<< "*** FAILED ***" << endl
624 << "Expected: " << expected
<< " but got: " << actual
<< endl
;
626 } catch (TTransportException
&) {
628 } catch (exception
& ex
) {
629 cout
<< "*** FAILED ***" << endl
<< ex
.what() << endl
;
630 return_code
|= ERR_BASETYPES
;
636 for (string::size_type i
= 0; i
< 131073 && !return_code
; ) {
637 return_code
|= binary_test(testClient
, i
);
638 if (i
> 0) { i
*= 2; } else { ++i
; }
645 cout
<< "testStruct({\"Zero\", 1, -3, -5})" << flush
;
647 out
.string_thing
= "Zero";
652 testClient
.testStruct(in
, out
);
653 printf(" = {\"%s\", %d, %d, %" PRId64
"}\n",
654 in
.string_thing
.c_str(),
659 cout
<< "*** FAILED ***" << endl
;
660 return_code
|= ERR_STRUCTS
;
666 cout
<< "testNest({1, {\"Zero\", 1, -3, -5}), 5}" << flush
;
669 out2
.struct_thing
= out
;
672 testClient
.testNest(in2
, out2
);
673 in
= in2
.struct_thing
;
674 printf(" = {%d, {\"%s\", %d, %d, %" PRId64
"}, %d}\n",
676 in
.string_thing
.c_str(),
682 cout
<< "*** FAILED ***" << endl
;
683 return_code
|= ERR_STRUCTS
;
689 map
<int32_t, int32_t> mapout
;
690 for (int32_t i
= 0; i
< 5; ++i
) {
691 mapout
.insert(make_pair(i
, i
- 10));
693 cout
<< "testMap({" << flush
;
694 map
<int32_t, int32_t>::const_iterator m_iter
;
696 for (m_iter
= mapout
.begin(); m_iter
!= mapout
.end(); ++m_iter
) {
702 cout
<< m_iter
->first
<< " => " << m_iter
->second
;
705 map
<int32_t, int32_t> mapin
;
706 testClient
.testMap(mapin
, mapout
);
709 for (m_iter
= mapin
.begin(); m_iter
!= mapin
.end(); ++m_iter
) {
715 cout
<< m_iter
->first
<< " => " << m_iter
->second
;
718 if (mapin
!= mapout
) {
719 cout
<< "*** FAILED ***" << endl
;
720 return_code
|= ERR_CONTAINERS
;
726 cout
<< "testStringMap({a => 2, b => blah, some => thing}) = {" << flush
;
727 map
<string
, string
> smapin
;
728 map
<string
, string
> smapout
;
730 smapin
["b"] = "blah";
731 smapin
["some"] = "thing";
733 testClient
.testStringMap(smapout
, smapin
);
735 for (map
<string
, string
>::const_iterator it
= smapout
.begin(); it
!= smapout
.end(); ++it
) {
740 cout
<< it
->first
<< " => " << it
->second
;
743 if (smapin
!= smapout
) {
744 cout
<< "*** FAILED ***" << endl
;
745 return_code
|= ERR_CONTAINERS
;
747 } catch (TTransportException
&) {
749 } catch (exception
& ex
) {
750 cout
<< "*** FAILED ***" << endl
<< ex
.what() << endl
;
751 return_code
|= ERR_CONTAINERS
;
758 for (int32_t i
= -2; i
< 3; ++i
) {
761 cout
<< "testSet({" << flush
;
762 set
<int32_t>::const_iterator s_iter
;
764 for (s_iter
= setout
.begin(); s_iter
!= setout
.end(); ++s_iter
) {
774 testClient
.testSet(setin
, setout
);
777 for (s_iter
= setin
.begin(); s_iter
!= setin
.end(); ++s_iter
) {
786 if (setin
!= setout
) {
787 cout
<< "*** FAILED ***" << endl
;
788 return_code
|= ERR_CONTAINERS
;
794 cout
<< "testList(empty)" << flush
;
796 vector
<int32_t> listout
;
797 testClient
.testList(listout
, vector
<int32_t>());
798 if (!listout
.empty()) {
799 cout
<< "*** FAILED ***" << endl
;
800 cout
<< "invalid length: " << listout
.size() << endl
;
801 return_code
|= ERR_CONTAINERS
;
803 } catch (TTransportException
&) {
805 } catch (exception
& ex
) {
806 cout
<< "*** FAILED ***" << endl
<< ex
.what() << endl
;
807 return_code
|= ERR_CONTAINERS
;
810 vector
<int32_t> listout
;
811 for (int32_t i
= -2; i
< 3; ++i
) {
812 listout
.push_back(i
);
814 cout
<< "testList({" << flush
;
815 vector
<int32_t>::const_iterator l_iter
;
817 for (l_iter
= listout
.begin(); l_iter
!= listout
.end(); ++l_iter
) {
826 vector
<int32_t> listin
;
827 testClient
.testList(listin
, listout
);
830 for (l_iter
= listin
.begin(); l_iter
!= listin
.end(); ++l_iter
) {
839 if (listin
!= listout
) {
840 cout
<< "*** FAILED ***" << endl
;
841 return_code
|= ERR_CONTAINERS
;
843 } catch (TTransportException
&) {
845 } catch (exception
& ex
) {
846 cout
<< "*** FAILED ***" << endl
<< ex
.what() << endl
;
847 return_code
|= ERR_CONTAINERS
;
853 cout
<< "testEnum(ONE)" << flush
;
854 Numberz::type ret
= testClient
.testEnum(Numberz::ONE
);
855 cout
<< " = " << ret
<< endl
;
856 if (ret
!= Numberz::ONE
) {
857 cout
<< "*** FAILED ***" << endl
;
858 return_code
|= ERR_STRUCTS
;
861 cout
<< "testEnum(TWO)" << flush
;
862 ret
= testClient
.testEnum(Numberz::TWO
);
863 cout
<< " = " << ret
<< endl
;
864 if (ret
!= Numberz::TWO
) {
865 cout
<< "*** FAILED ***" << endl
;
866 return_code
|= ERR_STRUCTS
;
869 cout
<< "testEnum(THREE)" << flush
;
870 ret
= testClient
.testEnum(Numberz::THREE
);
871 cout
<< " = " << ret
<< endl
;
872 if (ret
!= Numberz::THREE
) {
873 cout
<< "*** FAILED ***" << endl
;
874 return_code
|= ERR_STRUCTS
;
877 cout
<< "testEnum(FIVE)" << flush
;
878 ret
= testClient
.testEnum(Numberz::FIVE
);
879 cout
<< " = " << ret
<< endl
;
880 if (ret
!= Numberz::FIVE
) {
881 cout
<< "*** FAILED ***" << endl
;
882 return_code
|= ERR_STRUCTS
;
885 cout
<< "testEnum(EIGHT)" << flush
;
886 ret
= testClient
.testEnum(Numberz::EIGHT
);
887 cout
<< " = " << ret
<< endl
;
888 if (ret
!= Numberz::EIGHT
) {
889 cout
<< "*** FAILED ***" << endl
;
890 return_code
|= ERR_STRUCTS
;
896 cout
<< "testTypedef(309858235082523)" << flush
;
897 UserId uid
= testClient
.testTypedef(309858235082523LL);
898 cout
<< " = " << uid
<< endl
;
899 if (uid
!= 309858235082523LL) {
900 cout
<< "*** FAILED ***" << endl
;
901 return_code
|= ERR_STRUCTS
;
907 cout
<< "testMapMap(1)" << flush
;
908 map
<int32_t, map
<int32_t, int32_t> > mm
;
909 testClient
.testMapMap(mm
, 1);
911 map
<int32_t, map
<int32_t, int32_t> >::const_iterator mi
;
912 for (mi
= mm
.begin(); mi
!= mm
.end(); ++mi
) {
913 printf("%d => {", mi
->first
);
914 map
<int32_t, int32_t>::const_iterator mi2
;
915 for (mi2
= mi
->second
.begin(); mi2
!= mi
->second
.end(); ++mi2
) {
916 cout
<< mi2
->first
<< " => " << mi2
->second
;
921 if (mm
.size() != 2 ||
930 cout
<< "*** FAILED ***" << endl
;
931 return_code
|= ERR_CONTAINERS
;
939 insane
.userMap
.insert(make_pair(Numberz::FIVE
, 5));
940 insane
.userMap
.insert(make_pair(Numberz::EIGHT
, 8));
942 truck
.string_thing
= "Goodbye4";
943 truck
.byte_thing
= 4;
947 truck2
.string_thing
= "Hello2";
948 truck2
.byte_thing
= 2;
949 truck2
.i32_thing
= 2;
950 truck2
.i64_thing
= 2;
951 insane
.xtructs
.push_back(truck
);
952 insane
.xtructs
.push_back(truck2
);
953 cout
<< "testInsanity()" << flush
;
954 map
<UserId
, map
<Numberz::type
, Insanity
> > whoa
;
955 testClient
.testInsanity(whoa
, insane
);
957 map
<UserId
, map
<Numberz::type
, Insanity
> >::const_iterator i_iter
;
958 for (i_iter
= whoa
.begin(); i_iter
!= whoa
.end(); ++i_iter
) {
959 printf("%" PRId64
" => {", i_iter
->first
);
960 map
<Numberz::type
, Insanity
>::const_iterator i2_iter
;
961 for (i2_iter
= i_iter
->second
.begin(); i2_iter
!= i_iter
->second
.end(); ++i2_iter
) {
962 printf("%d => {", i2_iter
->first
);
963 map
<Numberz::type
, UserId
> userMap
= i2_iter
->second
.userMap
;
964 map
<Numberz::type
, UserId
>::const_iterator um
;
966 for (um
= userMap
.begin(); um
!= userMap
.end(); ++um
) {
967 cout
<< um
->first
<< " => " << um
->second
;
971 vector
<Xtruct
> xtructs
= i2_iter
->second
.xtructs
;
972 vector
<Xtruct
>::const_iterator x
;
974 for (x
= xtructs
.begin(); x
!= xtructs
.end(); ++x
) {
975 printf("{\"%s\", %d, %d, %" PRId64
"}, ",
976 x
->string_thing
.c_str(),
989 map
<UserId
, map
<Numberz::type
, Insanity
> >::const_iterator it1
= whoa
.find(UserId(1));
990 if (whoa
.size() != 2) {
993 if (it1
== whoa
.end()) {
996 auto it12
= it1
->second
.find(Numberz::TWO
);
997 if (it12
== it1
->second
.end() || it12
->second
!= insane
) {
1000 auto it13
= it1
->second
.find(Numberz::THREE
);
1001 if (it13
== it1
->second
.end() || it13
->second
!= insane
) {
1005 map
<UserId
, map
<Numberz::type
, Insanity
> >::const_iterator it2
= whoa
.find(UserId(2));
1006 if (it2
== whoa
.end()) {
1009 auto it26
= it2
->second
.find(Numberz::SIX
);
1010 if (it26
== it2
->second
.end() || it26
->second
!= Insanity()) {
1015 cout
<< "*** FAILED ***" << endl
;
1016 return_code
|= ERR_STRUCTS
;
1023 cout
<< "testMulti()" << endl
;
1025 map
<int16_t, string
> mul_map
;
1027 mul_map
[1] = "blah";
1028 mul_map
[2] = "thing";
1029 testClient
.testMulti(mul_result
, 42, 4242, 424242, mul_map
, Numberz::EIGHT
, UserId(24));
1031 xxs
.string_thing
= "Hello2";
1032 xxs
.byte_thing
= 42;
1033 xxs
.i32_thing
= 4242;
1034 xxs
.i64_thing
= 424242;
1035 if (mul_result
!= xxs
) {
1036 cout
<< "*** FAILED ***" << endl
;
1037 return_code
|= ERR_STRUCTS
;
1039 } catch (TTransportException
&) {
1041 } catch (exception
& ex
) {
1042 cout
<< "*** FAILED ***" << endl
<< ex
.what() << endl
;
1043 return_code
|= ERR_STRUCTS
;
1046 /* test exception */
1049 cout
<< "testClient.testException(\"Xception\") =>" << flush
;
1050 testClient
.testException("Xception");
1051 cout
<< " void\n*** FAILED ***" << endl
;
1052 return_code
|= ERR_EXCEPTIONS
;
1054 } catch (Xception
& e
) {
1055 printf(" {%u, \"%s\"}\n", e
.errorCode
, e
.message
.c_str());
1059 cout
<< "testClient.testException(\"TException\") =>" << flush
;
1060 testClient
.testException("TException");
1061 cout
<< " void\n*** FAILED ***" << endl
;
1062 return_code
|= ERR_EXCEPTIONS
;
1064 } catch (const TException
&) {
1065 cout
<< " Caught TException" << endl
;
1069 cout
<< "testClient.testException(\"success\") =>" << flush
;
1070 testClient
.testException("success");
1071 cout
<< " void" << endl
;
1072 } catch (exception
& ex
) { \
1073 cout
<< "*** FAILED ***" << endl
<< ex
.what() << endl
;
1074 return_code
|= ERR_EXCEPTIONS
;
1077 /* test multi exception */
1080 cout
<< "testClient.testMultiException(\"Xception\", \"test 1\") =>" << flush
;
1082 testClient
.testMultiException(result
, "Xception", "test 1");
1083 cout
<< " result\n*** FAILED ***" << endl
;
1084 return_code
|= ERR_EXCEPTIONS
;
1085 } catch (Xception
& e
) {
1086 printf(" {%u, \"%s\"}\n", e
.errorCode
, e
.message
.c_str());
1090 cout
<< "testClient.testMultiException(\"Xception2\", \"test 2\") =>" << flush
;
1092 testClient
.testMultiException(result
, "Xception2", "test 2");
1093 cout
<< " result\n*** FAILED ***" << endl
;
1094 return_code
|= ERR_EXCEPTIONS
;
1096 } catch (Xception2
& e
) {
1097 printf(" {%u, {\"%s\"}}\n", e
.errorCode
, e
.struct_thing
.string_thing
.c_str());
1101 cout
<< "testClient.testMultiException(\"success\", \"test 3\") =>" << flush
;
1103 testClient
.testMultiException(result
, "success", "test 3");
1104 printf(" {{\"%s\"}}\n", result
.string_thing
.c_str());
1105 } catch (exception
& ex
) { \
1106 cout
<< "*** FAILED ***" << endl
<< ex
.what() << endl
;
1107 return_code
|= ERR_EXCEPTIONS
;
1110 /* test oneway void */
1112 cout
<< "testClient.testOneway(1) =>" << flush
;
1113 uint64_t startOneway
= now();
1114 testClient
.testOneway(1);
1115 uint64_t elapsed
= now() - startOneway
;
1116 if (elapsed
> 200 * 1000) { // 0.2 seconds
1117 printf("*** FAILED *** - took %.2f ms\n", (double)elapsed
/ 1000.0);
1118 return_code
|= ERR_BASETYPES
;
1120 printf(" success - took %.2f ms\n", (double)elapsed
/ 1000.0);
1125 * redo a simple test after the oneway to make sure we aren't "off by one" --
1126 * if the server treated oneway void like normal void, this next test will
1127 * fail since it will get the void confirmation rather than the correct
1128 * result. In this circumstance, the client will throw the exception:
1130 * TApplicationException: Wrong method namea
1135 cout
<< "re-test testI32(-1)" << flush
;
1136 int i32
= testClient
.testI32(-1);
1137 cout
<< " = " << i32
<< endl
;
1139 return_code
|= ERR_BASETYPES
;
1141 cout
<< endl
<< "All tests done." << endl
<< flush
;
1143 uint64_t stop
= now();
1144 uint64_t tot
= stop
- start
;
1146 cout
<< "Total time: " << stop
- start
<< " us" << endl
;
1149 if (time_min
== 0 || tot
< time_min
) {
1152 if (tot
> time_max
) {
1161 uint64_t time_avg
= time_tot
/ numTests
;
1163 cout
<< "Min time: " << time_min
<< " us" << endl
;
1164 cout
<< "Max time: " << time_max
<< " us" << endl
;
1165 cout
<< "Avg time: " << time_avg
<< " us" << endl
;
1170 void binary_fill(std::string
& str
, string::size_type siz
)
1172 static const signed char bin_data
[256]
1173 = {-128, -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, -116, -115, -114,
1174 -113, -112, -111, -110, -109, -108, -107, -106, -105, -104, -103, -102, -101, -100, -99,
1175 -98, -97, -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, -86, -85, -84,
1176 -83, -82, -81, -80, -79, -78, -77, -76, -75, -74, -73, -72, -71, -70, -69,
1177 -68, -67, -66, -65, -64, -63, -62, -61, -60, -59, -58, -57, -56, -55, -54,
1178 -53, -52, -51, -50, -49, -48, -47, -46, -45, -44, -43, -42, -41, -40, -39,
1179 -38, -37, -36, -35, -34, -33, -32, -31, -30, -29, -28, -27, -26, -25, -24,
1180 -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9,
1181 -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6,
1182 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
1183 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
1184 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
1185 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
1186 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
1187 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
1188 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
1189 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
1193 char *ptr
= &str
[0];
1194 string::size_type pos
= 0;
1195 for (string::size_type i
= 0; i
< siz
; ++i
)
1197 if (pos
== 255) { pos
= 0; } else { ++pos
; }
1198 *ptr
++ = bin_data
[pos
];
1202 int binary_test(ThriftTestClient
& testClient
, string::size_type siz
)
1207 cout
<< "testBinary(siz = " << siz
<< ")" << endl
;
1208 binary_fill(bin_request
, siz
);
1210 testClient
.testBinary(bin_result
, bin_request
);
1212 if (bin_request
.size() != bin_result
.size()) {
1213 cout
<< "*** FAILED: request size " << bin_request
.size() << "; result size " << bin_result
.size() << endl
;
1214 return ERR_BASETYPES
;
1217 for (string::size_type i
= 0; i
< siz
; ++i
) {
1218 if (bin_request
.at(i
) != bin_result
.at(i
)) {
1219 cout
<< "*** FAILED: at position " << i
<< " request[i] is h" << hex
<< bin_request
.at(i
) << " result[i] is h" << hex
<< bin_result
.at(i
) << endl
;
1220 return ERR_BASETYPES
;
1223 } catch (TTransportException
&) {
1225 } catch (exception
& ex
) {
1226 cout
<< "*** FAILED ***" << endl
<< ex
.what() << endl
;
1227 return ERR_BASETYPES
;