blob: 4b5b841187c51cc339e0272b923624ab7cdd259e [file] [log] [blame]
Roger Meier213a6642010-10-27 12:30:11 +00001
2/* test a C client with a C++ server */
3
4#include <signal.h>
5#include <sys/types.h>
6#include <sys/wait.h>
7#include <protocol/TBinaryProtocol.h>
8#include <protocol/TDebugProtocol.h>
9#include <server/TSimpleServer.h>
10#include <transport/TServerSocket.h>
11#include "ThriftTest.h"
12#include "ThriftTest_types.h"
13
14#include <iostream>
15
16using namespace std;
17using namespace boost;
18
19using namespace apache::thrift;
20using namespace apache::thrift::concurrency;
21using namespace apache::thrift::protocol;
22using namespace apache::thrift::transport;
23using namespace apache::thrift::server;
24
25using namespace thrift::test;
26
27#define TEST_PORT 9980
28
29// Extra functions required for ThriftTest_types to work
30namespace thrift { namespace test {
31
32bool Insanity::operator<(thrift::test::Insanity const& other) const {
33 using apache::thrift::ThriftDebugString;
34 return ThriftDebugString(*this) < ThriftDebugString(other);
35}
36
37}}
38
39class TestHandler : public ThriftTestIf {
40 public:
41 TestHandler() {}
42
43 void testVoid() {
44 printf("[C -> C++] testVoid()\n");
45 }
46
47 void testString(string& out, const string &thing) {
48 printf("[C -> C++] testString(\"%s\")\n", thing.c_str());
49 out = thing;
50 }
51
52 int8_t testByte(const int8_t thing) {
53 printf("[C -> C++] testByte(%d)\n", (int)thing);
54 return thing;
55 }
56 int32_t testI32(const int32_t thing) {
57 printf("[C -> C++] testI32(%d)\n", thing);
58 return thing;
59 }
60
61 int64_t testI64(const int64_t thing) {
62 printf("[C -> C++] testI64(%lld)\n", thing);
63 return thing;
64 }
65
66 double testDouble(const double thing) {
67 printf("[C -> C++] testDouble(%lf)\n", thing);
68 return thing;
69 }
70
71 void testStruct(Xtruct& out, const Xtruct &thing) {
72 printf("[C -> C++] testStruct({\"%s\", %d, %d, %lld})\n", thing.string_thing.c_str(), (int)thing.byte_thing, thing.i32_thing, thing.i64_thing);
73 out = thing;
74 }
75
76 void testNest(Xtruct2& out, const Xtruct2& nest) {
77 const Xtruct &thing = nest.struct_thing;
78 printf("[C -> C++] testNest({%d, {\"%s\", %d, %d, %lld}, %d})\n", (int)nest.byte_thing, thing.string_thing.c_str(), (int)thing.byte_thing, thing.i32_thing, thing.i64_thing, nest.i32_thing);
79 out = nest;
80 }
81
82 void testMap(map<int32_t, int32_t> &out, const map<int32_t, int32_t> &thing) {
83 printf("[C -> C++] testMap({");
84 map<int32_t, int32_t>::const_iterator m_iter;
85 bool first = true;
86 for (m_iter = thing.begin(); m_iter != thing.end(); ++m_iter) {
87 if (first) {
88 first = false;
89 } else {
90 printf(", ");
91 }
92 printf("%d => %d", m_iter->first, m_iter->second);
93 }
94 printf("})\n");
95 out = thing;
96 }
97
98 void testSet(set<int32_t> &out, const set<int32_t> &thing) {
99 printf("[C -> C++] testSet({");
100 set<int32_t>::const_iterator s_iter;
101 bool first = true;
102 for (s_iter = thing.begin(); s_iter != thing.end(); ++s_iter) {
103 if (first) {
104 first = false;
105 } else {
106 printf(", ");
107 }
108 printf("%d", *s_iter);
109 }
110 printf("})\n");
111 out = thing;
112 }
113
114 void testList(vector<int32_t> &out, const vector<int32_t> &thing) {
115 printf("[C -> C++] testList({");
116 vector<int32_t>::const_iterator l_iter;
117 bool first = true;
118 for (l_iter = thing.begin(); l_iter != thing.end(); ++l_iter) {
119 if (first) {
120 first = false;
121 } else { printf(", ");
122 }
123 printf("%d", *l_iter);
124 }
125 printf("})\n");
126 out = thing;
127 }
128
129 Numberz::type testEnum(const Numberz::type thing) {
130 printf("[C -> C++] testEnum(%d)\n", thing);
131 return thing;
132 }
133
134 UserId testTypedef(const UserId thing) {
135 printf("[C -> C++] testTypedef(%lld)\n", thing);
136 return thing; }
137
138 void testMapMap(map<int32_t, map<int32_t,int32_t> > &mapmap, const int32_t hello) {
139 printf("[C -> C++] testMapMap(%d)\n", hello);
140
141 map<int32_t,int32_t> pos;
142 map<int32_t,int32_t> neg;
143 for (int i = 1; i < 5; i++) {
144 pos.insert(make_pair(i,i));
145 neg.insert(make_pair(-i,-i));
146 }
147
148 mapmap.insert(make_pair(4, pos));
149 mapmap.insert(make_pair(-4, neg));
150
151 }
152
153 void testInsanity(map<UserId, map<Numberz::type,Insanity> > &insane, const Insanity &argument) {
154 printf("[C -> C++] testInsanity()\n");
155
156 Xtruct hello;
157 hello.string_thing = "Hello2";
158 hello.byte_thing = 2;
159 hello.i32_thing = 2;
160 hello.i64_thing = 2;
161
162 Xtruct goodbye;
163 goodbye.string_thing = "Goodbye4";
164 goodbye.byte_thing = 4;
165 goodbye.i32_thing = 4;
166 goodbye.i64_thing = 4;
167
168 Insanity crazy;
169 crazy.userMap.insert(make_pair(Numberz::EIGHT, 8));
170 crazy.xtructs.push_back(goodbye);
171
172 Insanity looney;
173 crazy.userMap.insert(make_pair(Numberz::FIVE, 5));
174 crazy.xtructs.push_back(hello);
175
176 map<Numberz::type, Insanity> first_map;
177 map<Numberz::type, Insanity> second_map;
178
179 first_map.insert(make_pair(Numberz::TWO, crazy));
180 first_map.insert(make_pair(Numberz::THREE, crazy));
181
182 second_map.insert(make_pair(Numberz::SIX, looney));
183
184 insane.insert(make_pair(1, first_map));
185 insane.insert(make_pair(2, second_map));
186
187 printf("return");
188 printf(" = {");
189 map<UserId, map<Numberz::type,Insanity> >::const_iterator i_iter;
190 for (i_iter = insane.begin(); i_iter != insane.end(); ++i_iter) {
191 printf("%lld => {", i_iter->first);
192 map<Numberz::type,Insanity>::const_iterator i2_iter;
193 for (i2_iter = i_iter->second.begin();
194 i2_iter != i_iter->second.end();
195 ++i2_iter) {
196 printf("%d => {", i2_iter->first);
197 map<Numberz::type, UserId> userMap = i2_iter->second.userMap;
198 map<Numberz::type, UserId>::const_iterator um;
199 printf("{");
200 for (um = userMap.begin(); um != userMap.end(); ++um) {
201 printf("%d => %lld, ", um->first, um->second);
202 }
203 printf("}, ");
204
205 vector<Xtruct> xtructs = i2_iter->second.xtructs;
206 vector<Xtruct>::const_iterator x;
207 printf("{");
208 for (x = xtructs.begin(); x != xtructs.end(); ++x) {
209 printf("{\"%s\", %d, %d, %lld}, ", x->string_thing.c_str(), (int)x->byte_thing, x->i32_thing, x->i64_thing);
210 }
211 printf("}");
212
213 printf("}, ");
214 }
215 printf("}, ");
216 }
217 printf("}\n");
218
219
220 }
221
222 void testMulti(Xtruct &hello, const int8_t arg0, const int32_t arg1, const int64_t arg2, const std::map<int16_t, std::string> &arg3, const Numberz::type arg4, const UserId arg5) {
223 printf("[C -> C++] testMulti()\n");
224
225 hello.string_thing = "Hello2";
226 hello.byte_thing = arg0;
227 hello.i32_thing = arg1;
228 hello.i64_thing = (int64_t)arg2;
229 }
230
231 void testException(const std::string &arg)
232 throw(Xception, apache::thrift::TException)
233 {
234 printf("[C -> C++] testException(%s)\n", arg.c_str());
235 if (arg.compare("Xception") == 0) {
236 Xception e;
237 e.errorCode = 1001;
238 e.message = arg;
239 throw e;
240 } else if (arg.compare("ApplicationException") == 0) {
241 apache::thrift::TException e;
242 throw e;
243 } else {
244 Xtruct result;
245 result.string_thing = arg;
246 return;
247 }
248 }
249
250 void testMultiException(Xtruct &result, const std::string &arg0, const std::string &arg1) throw(Xception, Xception2) {
251
252 printf("[C -> C++] testMultiException(%s, %s)\n", arg0.c_str(), arg1.c_str());
253
254 if (arg0.compare("Xception") == 0) {
255 Xception e;
256 e.errorCode = 1001;
257 e.message = "This is an Xception";
258 throw e;
259 } else if (arg0.compare("Xception2") == 0) {
260 Xception2 e;
261 e.errorCode = 2002;
262 e.struct_thing.string_thing = "This is an Xception2";
263 throw e;
264 } else {
265 result.string_thing = arg1;
266 return;
267 }
268 }
269
270 void testOneway(int sleepFor) {
271 printf("testOneway(%d): Sleeping...\n", sleepFor);
272 sleep(sleepFor);
273 printf("testOneway(%d): done sleeping!\n", sleepFor);
274 }
275};
276
277// C CLIENT
278extern "C" {
279
280#include "t_test_thrift_test.h"
281#include "t_test_thrift_test_types.h"
282#include "transport/thrift_socket.h"
283#include "protocol/thrift_protocol.h"
284#include "protocol/thrift_binary_protocol.h"
285
286static void
287test_thrift_client (void)
288{
289 ThriftSocket *tsocket = NULL;
290 ThriftBinaryProtocol *protocol = NULL;
291 TTestThriftTestClient *client = NULL;
292 TTestThriftTestIf *iface = NULL;
293 GError *error = NULL;
294 gchar *string = NULL;
295 gint8 byte = 0;
296 gint16 i16 = 0;
297 gint32 i32 = 0, another_i32 = 56789;
298 gint64 i64 = 0;
299 double dbl = 0.0;
300 TTestXtruct *xtruct_in, *xtruct_out;
301 TTestXtruct2 *xtruct2_in, *xtruct2_out;
302 GHashTable *map_in = NULL, *map_out = NULL;
303 GHashTable *set_in = NULL, *set_out = NULL;
304 GArray *list_in = NULL, *list_out = NULL;
305 TTestNumberz enum_in, enum_out;
306 TTestUserId user_id_in, user_id_out;
307 GHashTable *insanity_in = NULL;
308 TTestXtruct *xtruct1, *xtruct2;
309 TTestInsanity *insanity_out = NULL;
310 TTestXtruct *multi_in = NULL;
311 GHashTable *multi_map_out = NULL;
312 TTestXception *xception = NULL;
313 TTestXception2 *xception2 = NULL;
314
315 // initialize gobject
316 g_type_init ();
317
318 // create a C client
319 tsocket = (ThriftSocket *) g_object_new (THRIFT_TYPE_SOCKET,
320 "hostname", "localhost",
321 "port", TEST_PORT, NULL);
322 protocol = (ThriftBinaryProtocol *) g_object_new (THRIFT_TYPE_BINARY_PROTOCOL,
323 "transport",
324 tsocket, NULL);
325 client = (TTestThriftTestClient *) g_object_new (T_TEST_TYPE_THRIFT_TEST_CLIENT, "input_protocol", protocol, "output_protocol", protocol, NULL);
326 iface = T_TEST_THRIFT_TEST_IF (client);
327
328 // open and send
329 thrift_transport_open (THRIFT_TRANSPORT(tsocket), NULL);
330
331 assert (t_test_thrift_test_client_test_void (iface, &error) == TRUE);
332 assert (error == NULL);
333
334 assert (t_test_thrift_test_client_test_string (iface, &string, "test123", &error) == TRUE);
335 assert (strcmp (string, "test123") == 0);
336 g_free (string);
337 assert (error == NULL);
338
339 assert (t_test_thrift_test_client_test_byte (iface, &byte, (gint8) 5, &error) == TRUE);
340 assert (byte == 5);
341 assert (error == NULL);
342
343 assert (t_test_thrift_test_client_test_i32 (iface, &i32, 123, &error) == TRUE);
344 assert (i32 == 123);
345 assert (error == NULL);
346
347 assert (t_test_thrift_test_client_test_i64 (iface, &i64, 12345, &error) == TRUE);
348 assert (i64 == 12345);
349 assert (error == NULL);
350
351 assert (t_test_thrift_test_client_test_double (iface, &dbl, 5.6, &error) == TRUE);
352 assert (dbl == 5.6);
353 assert (error == NULL);
354
355 xtruct_out = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, NULL);
356 xtruct_out->byte_thing = 1;
357 xtruct_out->__isset_byte_thing = TRUE;
358 xtruct_out->i32_thing = 15;
359 xtruct_out->__isset_i32_thing = TRUE;
360 xtruct_out->i64_thing = 151;
361 xtruct_out->__isset_i64_thing = TRUE;
362 xtruct_out->string_thing = g_strdup ("abc123");
363 xtruct_out->__isset_string_thing = TRUE;
364 assert (t_test_thrift_test_client_test_struct (iface, &xtruct_in, xtruct_out, &error) == TRUE);
365 assert (error == NULL);
366
367 xtruct2_out = (TTestXtruct2 *) g_object_new (T_TEST_TYPE_XTRUCT2, NULL);
368 xtruct2_out->byte_thing = 1;
369 xtruct2_out->__isset_byte_thing = TRUE;
370 xtruct2_out->struct_thing = xtruct_out;
371 xtruct2_out->__isset_struct_thing = TRUE;
372 xtruct2_out->i32_thing = 123;
373 xtruct2_out->__isset_i32_thing = TRUE;
374 assert (t_test_thrift_test_client_test_nest (iface, &xtruct2_in, xtruct2_out, &error) == TRUE);
375 assert (error == NULL);
376
377 g_object_unref (xtruct2_out);
378 g_object_unref (xtruct2_in);
379 g_free (xtruct_out->string_thing);
380 g_object_unref (xtruct_out);
381 g_object_unref (xtruct_in);
382
383 map_out = g_hash_table_new (NULL, NULL);
384 map_in = g_hash_table_new (NULL, NULL); g_hash_table_insert (map_out, &i32, &i32);
385 assert (t_test_thrift_test_client_test_map (iface, &map_in, map_out, &error) == TRUE);
386 assert (error == NULL);
387 g_hash_table_destroy (map_out);
388 g_hash_table_destroy (map_in);
389
390 set_out = g_hash_table_new (NULL, NULL);
391 set_in = g_hash_table_new (NULL, NULL);
392 g_hash_table_insert (set_out, &i32, &i32);
393 assert (t_test_thrift_test_client_test_set (iface, &set_in, set_out, &error) == TRUE);
394 assert (error == NULL);
395 g_hash_table_destroy (set_out);
396 g_hash_table_destroy (set_in);
397
398 list_out = g_array_new(TRUE, TRUE, sizeof(gint32));
399 list_in = g_array_new(TRUE, TRUE, sizeof(gint32));
400 another_i32 = 456;
401 g_array_append_val (list_out, i32);
402 g_array_append_val (list_out, another_i32);
403 assert (t_test_thrift_test_client_test_list (iface, &list_in, list_out, &error) == TRUE);
404 assert (error == NULL);
405 g_array_free (list_out, TRUE);
406 g_array_free (list_in, TRUE);
407
408 enum_out = T_TEST_NUMBERZ_ONE;
409 assert (t_test_thrift_test_client_test_enum (iface, &enum_in, enum_out, &error) == TRUE);
410 assert (enum_in == enum_out);
411 assert (error == NULL);
412
413 user_id_out = 12345;
414 assert (t_test_thrift_test_client_test_typedef (iface, &user_id_in, user_id_out, &error) == TRUE);
415 assert (user_id_in == user_id_out);
416 assert (error == NULL);
417
418 map_in = g_hash_table_new (NULL, NULL);
419 assert (t_test_thrift_test_client_test_map_map (iface, &map_in, i32, &error) == TRUE);
420 assert (error == NULL);
421 g_hash_table_destroy (map_in);
422
423 // insanity
424 insanity_out = (TTestInsanity *) g_object_new (T_TEST_TYPE_INSANITY, NULL);
425 insanity_out->userMap = g_hash_table_new (NULL, NULL);
426 g_hash_table_insert (insanity_out->userMap, &enum_out, &user_id_out);
427
428 xtruct1 = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, NULL);
429 xtruct1->byte_thing = 1;
430 xtruct1->__isset_byte_thing = TRUE;
431 xtruct1->i32_thing = 15;
432 xtruct1->__isset_i32_thing = TRUE;
433 xtruct1->i64_thing = 151;
434 xtruct1->__isset_i64_thing = TRUE;
435 xtruct1->string_thing = g_strdup ("abc123");
436 xtruct1->__isset_string_thing = TRUE;
437 xtruct2 = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, NULL);
438 xtruct2->byte_thing = 1;
439 xtruct2->__isset_byte_thing = TRUE;
440 xtruct2->i32_thing = 15;
441 xtruct2->__isset_i32_thing = TRUE;
442 xtruct2->i64_thing = 151;
443 xtruct2->__isset_i64_thing = TRUE;
444 xtruct2->string_thing = g_strdup ("abc123");
445 xtruct2->__isset_string_thing = TRUE;
446
447 insanity_out->xtructs = g_ptr_array_new ();
448 insanity_in = g_hash_table_new (NULL, NULL);
449 g_ptr_array_add (insanity_out->xtructs, xtruct1);
450 g_ptr_array_add (insanity_out->xtructs, xtruct2);
451 assert (t_test_thrift_test_client_test_insanity (iface, &insanity_in, insanity_out, &error) == TRUE);
452
453 g_hash_table_unref (insanity_in);
454 g_ptr_array_free (insanity_out->xtructs, TRUE);
455 g_free (xtruct1->string_thing);
456 g_free (xtruct2->string_thing);
457 g_object_unref (xtruct1);
458 g_object_unref (xtruct2);
459
460 multi_map_out = g_hash_table_new (NULL, NULL);
461 string = g_strdup ("abc123");
462 g_hash_table_insert (multi_map_out, &i16, string);
463 assert (t_test_thrift_test_client_test_multi (iface, &multi_in, byte, i32, i64, multi_map_out, enum_out, user_id_out, &error) == TRUE);
464 assert (multi_in->i32_thing == i32);
465 assert (multi_in->i64_thing == i64);
466 g_object_unref (multi_in);
467 g_hash_table_unref (multi_map_out);
468 g_free (string);
469
470 assert (t_test_thrift_test_client_test_exception (iface, "Xception", &xception, &error) == FALSE);
471 assert (xception->errorCode == 1001);
472 g_error_free (error);
473 error = NULL;
474
475 assert (t_test_thrift_test_client_test_exception (iface, "ApplicationException", &xception, &error) == FALSE);
476 g_error_free (error);
477 error = NULL;
478 g_object_unref (xception);
479 xception = NULL;
480
481 assert (t_test_thrift_test_client_test_exception (iface, "Test", &xception, &error) == TRUE);
482 assert (error == NULL);
483
484 assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, "Xception", NULL, &xception, &xception2, &error) == FALSE);
485 assert (xception->errorCode == 1001);
486 g_error_free (error);
487 error = NULL;
488 g_object_unref (xception);
489 xception = NULL;
490 xception2 = NULL;
491
492 assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, "Xception2", NULL, &xception, &xception2, &error) == FALSE);
493 assert (xception2->errorCode == 2002);
494 g_error_free (error);
495 error = NULL;
496 g_object_unref (xception2);
497 xception2 = NULL;
498
499 assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, NULL , NULL, &xception, &xception2, &error) == TRUE);
500 assert (error == NULL);
501
502 assert (t_test_thrift_test_client_test_oneway (iface, 1, &error) == TRUE);
503 assert (error == NULL);
504
505 /* sleep to let the oneway call go through */
506 sleep (5);
507
508 thrift_transport_close (THRIFT_TRANSPORT(tsocket), NULL);
509 g_object_unref (client);
510 g_object_unref (protocol);
511 g_object_unref (tsocket);
512}
513
514
515} /* extern "C" */
516
517
518static void
519bailout (int signum)
520{
521 exit (1);
522}
523
524int
525main (int argc, char **argv)
526{
527 int status;
528 int pid = fork ();
529 assert (pid >= 0);
530
531 if (pid == 0) /* child */
532 {
533 shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
534 shared_ptr<TestHandler> testHandler(new TestHandler());
535 shared_ptr<ThriftTestProcessor> testProcessor(new ThriftTestProcessor(testHandler));
536 shared_ptr<TServerSocket> serverSocket(new TServerSocket(TEST_PORT));
537 shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
538 TSimpleServer simpleServer(testProcessor, serverSocket, transportFactory, protocolFactory);
539 signal (SIGALRM, bailout);
540 alarm (60);
541 simpleServer.serve();
542 } else {
543 sleep (1);
544 test_thrift_client ();
545 kill (pid, SIGINT);
546 wait (&status) == pid;
547 }
548
549 return 0;
550}
551