blob: 5ddfa06012c8f28e838518215bef07aa817f9e33 [file] [log] [blame]
Gavin McDonald0b75e1a2010-10-28 02:12:01 +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
20#include <stdio.h>
21#include <unistd.h>
22#include <sys/time.h>
23#include <protocol/TBinaryProtocol.h>
24#include <transport/TTransportUtils.h>
25#include <transport/TSocket.h>
26
27#include <boost/shared_ptr.hpp>
28#include "ThriftTest.h"
29
30#define __STDC_FORMAT_MACROS
31#include <inttypes.h>
32
33using namespace boost;
34using namespace std;
35using namespace apache::thrift;
36using namespace apache::thrift::protocol;
37using namespace apache::thrift::transport;
38using namespace thrift::test;
39
40//extern uint32_t g_socket_syscalls;
41
42// Current time, microseconds since the epoch
43uint64_t now()
44{
45 long long ret;
46 struct timeval tv;
47
48 gettimeofday(&tv, NULL);
49 ret = tv.tv_sec;
50 ret = ret*1000*1000 + tv.tv_usec;
51 return ret;
52}
53
54int main(int argc, char** argv) {
55 string host = "localhost";
56 int port = 9090;
57 int numTests = 1;
58 bool framed = false;
59
60 for (int i = 0; i < argc; ++i) {
61 if (strcmp(argv[i], "-h") == 0) {
62 char* pch = strtok(argv[++i], ":");
63 if (pch != NULL) {
64 host = string(pch);
65 }
66 pch = strtok(NULL, ":");
67 if (pch != NULL) {
68 port = atoi(pch);
69 }
70 } else if (strcmp(argv[i], "-n") == 0) {
71 numTests = atoi(argv[++i]);
72 } else if (strcmp(argv[i], "-f") == 0) {
73 framed = true;
74 }
75 }
76
77
78 shared_ptr<TTransport> transport;
79
80 shared_ptr<TSocket> socket(new TSocket(host, port));
81
82 if (framed) {
83 shared_ptr<TFramedTransport> framedSocket(new TFramedTransport(socket));
84 transport = framedSocket;
85 } else {
86 shared_ptr<TBufferedTransport> bufferedSocket(new TBufferedTransport(socket));
87 transport = bufferedSocket;
88 }
89
90 shared_ptr<TBinaryProtocol> protocol(new TBinaryProtocol(transport));
91 ThriftTestClient testClient(protocol);
92
93 uint64_t time_min = 0;
94 uint64_t time_max = 0;
95 uint64_t time_tot = 0;
96
97 int test = 0;
98 for (test = 0; test < numTests; ++test) {
99
100 try {
101 transport->open();
102 } catch (TTransportException& ttx) {
103 printf("Connect failed: %s\n", ttx.what());
104 continue;
105 }
106
107 /**
108 * CONNECT TEST
109 */
110 printf("Test #%d, connect %s:%d\n", test+1, host.c_str(), port);
111
112 uint64_t start = now();
113
114 /**
115 * VOID TEST
116 */
117 try {
118 printf("testVoid()");
119 testClient.testVoid();
120 printf(" = void\n");
121 } catch (TApplicationException tax) {
122 printf("%s\n", tax.what());
123 }
124
125 /**
126 * STRING TEST
127 */
128 printf("testString(\"Test\")");
129 string s;
130 testClient.testString(s, "Test");
131 printf(" = \"%s\"\n", s.c_str());
132
133 /**
134 * BYTE TEST
135 */
136 printf("testByte(1)");
137 uint8_t u8 = testClient.testByte(1);
138 printf(" = %d\n", (int)u8);
139
140 /**
141 * I32 TEST
142 */
143 printf("testI32(-1)");
144 int32_t i32 = testClient.testI32(-1);
145 printf(" = %d\n", i32);
146
147 /**
148 * I64 TEST
149 */
150 printf("testI64(-34359738368)");
151 int64_t i64 = testClient.testI64(-34359738368LL);
152 printf(" = %"PRId64"\n", i64);
153
154 /**
155 * DOUBLE TEST
156 */
157 printf("testDouble(-5.2098523)");
158 double dub = testClient.testDouble(-5.2098523);
159 printf(" = %lf\n", dub);
160
161 /**
162 * STRUCT TEST
163 */
164 printf("testStruct({\"Zero\", 1, -3, -5})");
165 Xtruct out;
166 out.string_thing = "Zero";
167 out.byte_thing = 1;
168 out.i32_thing = -3;
169 out.i64_thing = -5;
170 Xtruct in;
171 testClient.testStruct(in, out);
172 printf(" = {\"%s\", %d, %d, %"PRId64"}\n",
173 in.string_thing.c_str(),
174 (int)in.byte_thing,
175 in.i32_thing,
176 in.i64_thing);
177
178 /**
179 * NESTED STRUCT TEST
180 */
181 printf("testNest({1, {\"Zero\", 1, -3, -5}), 5}");
182 Xtruct2 out2;
183 out2.byte_thing = 1;
184 out2.struct_thing = out;
185 out2.i32_thing = 5;
186 Xtruct2 in2;
187 testClient.testNest(in2, out2);
188 in = in2.struct_thing;
189 printf(" = {%d, {\"%s\", %d, %d, %"PRId64"}, %d}\n",
190 in2.byte_thing,
191 in.string_thing.c_str(),
192 (int)in.byte_thing,
193 in.i32_thing,
194 in.i64_thing,
195 in2.i32_thing);
196
197 /**
198 * MAP TEST
199 */
200 map<int32_t,int32_t> mapout;
201 for (int32_t i = 0; i < 5; ++i) {
202 mapout.insert(make_pair(i, i-10));
203 }
204 printf("testMap({");
205 map<int32_t, int32_t>::const_iterator m_iter;
206 bool first = true;
207 for (m_iter = mapout.begin(); m_iter != mapout.end(); ++m_iter) {
208 if (first) {
209 first = false;
210 } else {
211 printf(", ");
212 }
213 printf("%d => %d", m_iter->first, m_iter->second);
214 }
215 printf("})");
216 map<int32_t,int32_t> mapin;
217 testClient.testMap(mapin, mapout);
218 printf(" = {");
219 first = true;
220 for (m_iter = mapin.begin(); m_iter != mapin.end(); ++m_iter) {
221 if (first) {
222 first = false;
223 } else {
224 printf(", ");
225 }
226 printf("%d => %d", m_iter->first, m_iter->second);
227 }
228 printf("}\n");
229
230 /**
231 * SET TEST
232 */
233 set<int32_t> setout;
234 for (int32_t i = -2; i < 3; ++i) {
235 setout.insert(i);
236 }
237 printf("testSet({");
238 set<int32_t>::const_iterator s_iter;
239 first = true;
240 for (s_iter = setout.begin(); s_iter != setout.end(); ++s_iter) {
241 if (first) {
242 first = false;
243 } else {
244 printf(", ");
245 }
246 printf("%d", *s_iter);
247 }
248 printf("})");
249 set<int32_t> setin;
250 testClient.testSet(setin, setout);
251 printf(" = {");
252 first = true;
253 for (s_iter = setin.begin(); s_iter != setin.end(); ++s_iter) {
254 if (first) {
255 first = false;
256 } else {
257 printf(", ");
258 }
259 printf("%d", *s_iter);
260 }
261 printf("}\n");
262
263 /**
264 * LIST TEST
265 */
266 vector<int32_t> listout;
267 for (int32_t i = -2; i < 3; ++i) {
268 listout.push_back(i);
269 }
270 printf("testList({");
271 vector<int32_t>::const_iterator l_iter;
272 first = true;
273 for (l_iter = listout.begin(); l_iter != listout.end(); ++l_iter) {
274 if (first) {
275 first = false;
276 } else {
277 printf(", ");
278 }
279 printf("%d", *l_iter);
280 }
281 printf("})");
282 vector<int32_t> listin;
283 testClient.testList(listin, listout);
284 printf(" = {");
285 first = true;
286 for (l_iter = listin.begin(); l_iter != listin.end(); ++l_iter) {
287 if (first) {
288 first = false;
289 } else {
290 printf(", ");
291 }
292 printf("%d", *l_iter);
293 }
294 printf("}\n");
295
296 /**
297 * ENUM TEST
298 */
299 printf("testEnum(ONE)");
300 Numberz ret = testClient.testEnum(ONE);
301 printf(" = %d\n", ret);
302
303 printf("testEnum(TWO)");
304 ret = testClient.testEnum(TWO);
305 printf(" = %d\n", ret);
306
307 printf("testEnum(THREE)");
308 ret = testClient.testEnum(THREE);
309 printf(" = %d\n", ret);
310
311 printf("testEnum(FIVE)");
312 ret = testClient.testEnum(FIVE);
313 printf(" = %d\n", ret);
314
315 printf("testEnum(EIGHT)");
316 ret = testClient.testEnum(EIGHT);
317 printf(" = %d\n", ret);
318
319 /**
320 * TYPEDEF TEST
321 */
322 printf("testTypedef(309858235082523)");
323 UserId uid = testClient.testTypedef(309858235082523LL);
324 printf(" = %"PRId64"\n", uid);
325
326 /**
327 * NESTED MAP TEST
328 */
329 printf("testMapMap(1)");
330 map<int32_t, map<int32_t, int32_t> > mm;
331 testClient.testMapMap(mm, 1);
332 printf(" = {");
333 map<int32_t, map<int32_t, int32_t> >::const_iterator mi;
334 for (mi = mm.begin(); mi != mm.end(); ++mi) {
335 printf("%d => {", mi->first);
336 map<int32_t, int32_t>::const_iterator mi2;
337 for (mi2 = mi->second.begin(); mi2 != mi->second.end(); ++mi2) {
338 printf("%d => %d, ", mi2->first, mi2->second);
339 }
340 printf("}, ");
341 }
342 printf("}\n");
343
344 /**
345 * INSANITY TEST
346 */
347 Insanity insane;
348 insane.userMap.insert(make_pair(FIVE, 5000));
349 Xtruct truck;
350 truck.string_thing = "Truck";
351 truck.byte_thing = 8;
352 truck.i32_thing = 8;
353 truck.i64_thing = 8;
354 insane.xtructs.push_back(truck);
355 printf("testInsanity()");
356 map<UserId, map<Numberz,Insanity> > whoa;
357 testClient.testInsanity(whoa, insane);
358 printf(" = {");
359 map<UserId, map<Numberz,Insanity> >::const_iterator i_iter;
360 for (i_iter = whoa.begin(); i_iter != whoa.end(); ++i_iter) {
361 printf("%"PRId64" => {", i_iter->first);
362 map<Numberz,Insanity>::const_iterator i2_iter;
363 for (i2_iter = i_iter->second.begin();
364 i2_iter != i_iter->second.end();
365 ++i2_iter) {
366 printf("%d => {", i2_iter->first);
367 map<Numberz, UserId> userMap = i2_iter->second.userMap;
368 map<Numberz, UserId>::const_iterator um;
369 printf("{");
370 for (um = userMap.begin(); um != userMap.end(); ++um) {
371 printf("%d => %"PRId64", ", um->first, um->second);
372 }
373 printf("}, ");
374
375 vector<Xtruct> xtructs = i2_iter->second.xtructs;
376 vector<Xtruct>::const_iterator x;
377 printf("{");
378 for (x = xtructs.begin(); x != xtructs.end(); ++x) {
379 printf("{\"%s\", %d, %d, %"PRId64"}, ",
380 x->string_thing.c_str(),
381 (int)x->byte_thing,
382 x->i32_thing,
383 x->i64_thing);
384 }
385 printf("}");
386
387 printf("}, ");
388 }
389 printf("}, ");
390 }
391 printf("}\n");
392
393 /* test exception */
394
395 try {
396 printf("testClient.testException(\"Xception\") =>");
397 testClient.testException("Xception");
398 printf(" void\nFAILURE\n");
399
400 } catch(Xception& e) {
401 printf(" {%u, \"%s\"}\n", e.errorCode, e.message.c_str());
402 }
403
404 try {
405 printf("testClient.testException(\"success\") =>");
406 testClient.testException("success");
407 printf(" void\n");
408 } catch(...) {
409 printf(" exception\nFAILURE\n");
410 }
411
412 /* test multi exception */
413
414 try {
415 printf("testClient.testMultiException(\"Xception\", \"test 1\") =>");
416 Xtruct result;
417 testClient.testMultiException(result, "Xception", "test 1");
418 printf(" result\nFAILURE\n");
419 } catch(Xception& e) {
420 printf(" {%u, \"%s\"}\n", e.errorCode, e.message.c_str());
421 }
422
423 try {
424 printf("testClient.testMultiException(\"Xception2\", \"test 2\") =>");
425 Xtruct result;
426 testClient.testMultiException(result, "Xception2", "test 2");
427 printf(" result\nFAILURE\n");
428
429 } catch(Xception2& e) {
430 printf(" {%u, {\"%s\"}}\n", e.errorCode, e.struct_thing.string_thing.c_str());
431 }
432
433 try {
434 printf("testClient.testMultiException(\"success\", \"test 3\") =>");
435 Xtruct result;
436 testClient.testMultiException(result, "success", "test 3");
437 printf(" {{\"%s\"}}\n", result.string_thing.c_str());
438 } catch(...) {
439 printf(" exception\nFAILURE\n");
440 }
441
442 /* test oneway void */
443 {
444 printf("testClient.testOneway(3) =>");
445 uint64_t startOneway = now();
446 testClient.testOneway(3);
447 uint64_t elapsed = now() - startOneway;
448 if (elapsed > 200 * 1000) { // 0.2 seconds
449 printf(" FAILURE - took %.2f ms\n", (double)elapsed/1000.0);
450 } else {
451 printf(" success - took %.2f ms\n", (double)elapsed/1000.0);
452 }
453 }
454
455 /**
456 * redo a simple test after the oneway to make sure we aren't "off by one" --
457 * if the server treated oneway void like normal void, this next test will
458 * fail since it will get the void confirmation rather than the correct
459 * result. In this circumstance, the client will throw the exception:
460 *
461 * TApplicationException: Wrong method namea
462 */
463 /**
464 * I32 TEST
465 */
466 printf("re-test testI32(-1)");
467 i32 = testClient.testI32(-1);
468 printf(" = %d\n", i32);
469
470
471 uint64_t stop = now();
472 uint64_t tot = stop-start;
473
474 printf("Total time: %"PRIu64" us\n", stop-start);
475
476 time_tot += tot;
477 if (time_min == 0 || tot < time_min) {
478 time_min = tot;
479 }
480 if (tot > time_max) {
481 time_max = tot;
482 }
483
484 transport->close();
485 }
486
487 // printf("\nSocket syscalls: %u", g_socket_syscalls);
488 printf("\nAll tests done.\n");
489
490 uint64_t time_avg = time_tot / numTests;
491
492 printf("Min time: %"PRIu64" us\n", time_min);
493 printf("Max time: %"PRIu64" us\n", time_max);
494 printf("Avg time: %"PRIu64" us\n", time_avg);
495
496 return 0;
497}