1#!/usr/bin/env perl 2 3# 4# Licensed to the Apache Software Foundation (ASF) under one 5# or more contributor license agreements. See the NOTICE file 6# distributed with this work for additional information 7# regarding copyright ownership. The ASF licenses this file 8# to you under the Apache License, Version 2.0 (the 9# "License"); you may not use this file except in compliance 10# with the License. You may obtain a copy of the License at 11# 12# http://www.apache.org/licenses/LICENSE-2.0 13# 14# Unless required by applicable law or agreed to in writing, 15# software distributed under the License is distributed on an 16# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17# KIND, either express or implied. See the License for the 18# specific language governing permissions and limitations 19# under the License. 20# 21 22use 5.10.0; 23use strict; 24use warnings; 25use Data::Dumper; 26use Getopt::Long qw(GetOptions); 27use Time::HiRes qw(gettimeofday); 28 29use lib '../../lib/perl/lib'; 30use lib 'gen-perl'; 31 32use Thrift; 33use Thrift::BinaryProtocol; 34use Thrift::BufferedTransport; 35use Thrift::FramedTransport; 36use Thrift::MultiplexedProtocol; 37use Thrift::SSLSocket; 38use Thrift::Socket; 39use Thrift::UnixSocket; 40 41use ThriftTest::SecondService; 42use ThriftTest::ThriftTest; 43use ThriftTest::Types; 44 45$|++; 46 47sub usage { 48 print <<"EOF"; 49Usage: $0 [OPTIONS] 50 51Options: (default) 52 --ca CA to validate server with. 53 --cert Certificate to use. 54 Required if using --ssl. 55 --ciphers Acceptable cipher list. 56 --domain-socket <file> Use a unix domain socket. 57 --help Show usage. 58 --key Certificate key. 59 Required if using --ssl. 60 --port <portnum> 9090 Port to use. 61 --protocol {binary} binary Protocol to use. 62 --ssl If present, use SSL. 63 --transport {buffered|framed} buffered Transport to use. 64 65EOF 66} 67 68my %opts = ( 69 'port' => 9090, 70 'protocol' => 'binary', 71 'transport' => 'buffered' 72); 73 74GetOptions(\%opts, qw ( 75 ca=s 76 cert=s 77 ciphers=s 78 key=s 79 domain-socket=s 80 help 81 host=s 82 port=i 83 protocol=s 84 ssl 85 transport=s 86)) || exit 1; 87 88if ($opts{help}) { 89 usage(); 90 exit 0; 91} 92 93my $socket = undef; 94if ($opts{'domain-socket'}) { 95 $socket = Thrift::UnixSocket->new($opts{'domain-socket'}); 96} 97elsif ($opts{ssl}) { 98 $socket = Thrift::SSLSocket->new(\%opts); 99} 100else { 101 $socket = Thrift::Socket->new($opts{host}, $opts{port}); 102} 103 104my $transport; 105if ($opts{transport} eq 'buffered') { 106 $transport = Thrift::BufferedTransport->new($socket, 1024, 1024); 107} 108elsif ($opts{transport} eq 'framed') { 109 $transport = Thrift::FramedTransport->new($socket); 110} 111else { 112 usage(); 113 exit 1; 114} 115 116my $protocol; 117my $protocol2; 118if ($opts{protocol} eq 'binary' || $opts{protocol} eq 'multi') { 119 $protocol = Thrift::BinaryProtocol->new($transport); 120} 121else { 122 usage(); 123 exit 1; 124} 125 126my $secondService = undef; 127if (index($opts{protocol}, 'multi') == 0) { 128 $protocol2 = Thrift::MultiplexedProtocol->new($protocol, 'SecondService'); 129 $protocol = Thrift::MultiplexedProtocol->new($protocol, 'ThriftTest'); 130 $secondService = ThriftTest::SecondServiceClient->new($protocol2); 131} 132 133my $testClient = ThriftTest::ThriftTestClient->new($protocol); 134 135eval { 136 $transport->open(); 137}; 138if($@){ 139 die(Dumper($@)); 140} 141 142use constant ERR_BASETYPES => 1; 143use constant ERR_STRUCTS => 2; 144use constant ERR_CONTAINERS => 4; 145use constant ERR_EXCEPTIONS => 8; 146use constant ERR_PROTOCOL => 16; 147use constant ERR_UNKNOWN => 64; 148 149my $start = gettimeofday(); 150 151# 152# VOID TEST 153# 154print('testVoid()'); 155$testClient->testVoid(); 156print(" = void\n"); 157 158# 159# STRING TEST 160# 161print('testString("Test")'); 162my $s = $testClient->testString('Test'); 163print(qq| = "$s"\n|); 164exit(ERR_BASETYPES) if ($s ne 'Test'); 165 166# 167# MULTIPLEXED TEST 168# 169if (index($opts{protocol}, 'multi') == 0) { 170 print('secondtestString("Test2")'); 171 $s = $secondService->secondtestString('Test2'); 172 print(qq| = "$s"\n|); 173 exit(ERR_PROTOCOL) if ($s ne 'testString("Test2")'); 174} 175 176# 177# BOOL TEST 178# 179print('testBool(1)'); 180my $t = $testClient->testBool(1); 181print(" = $t\n"); 182exit(ERR_BASETYPES) if ($t ne 1); 183print('testBool(0)'); 184my $f = $testClient->testBool(0); 185print(" = $f\n"); 186exit(ERR_BASETYPES) if ($f ne q||); 187 188 189# 190# BYTE TEST 191# 192print('testByte(1)'); 193my $u8 = $testClient->testByte(1); 194print(" = $u8\n"); 195 196# 197# I32 TEST 198# 199print('testI32(-1)'); 200my $i32 = $testClient->testI32(-1); 201print(" = $i32\n"); 202exit(ERR_BASETYPES) if ($i32 ne -1); 203 204# 205# I64 TEST 206# 207print('testI64(-34359738368)'); 208my $i64 = $testClient->testI64(-34359738368); 209print(" = $i64\n"); 210exit(ERR_BASETYPES) if ($i64 ne -34359738368); 211 212# 213# DOUBLE TEST 214# 215print('testDouble(-852.234234234)'); 216my $dub = $testClient->testDouble(-852.234234234); 217print(" = $dub\n"); 218exit(ERR_BASETYPES) if ($dub ne -852.234234234); 219 220# 221# BINARY TEST 222# 223print("testBinary(pack('C*', 0..255))"); 224my $bin = $testClient->testBinary(pack('C*', 0..255)); 225printf(" = %s\n", join ' ', map { sprintf '%02x', $_ } unpack('C*', $bin)); 226exit(ERR_BASETYPES) if ($bin ne pack('C*', 0..255)); 227 228# 229# STRUCT TEST 230# 231print('testStruct({"Zero", 1, -3, -5})'); 232my $out = ThriftTest::Xtruct->new(); 233$out->string_thing('Zero'); 234$out->byte_thing(1); 235$out->i32_thing(-3); 236$out->i64_thing(-5); 237my $in = $testClient->testStruct($out); 238print(' = {"'.$in->string_thing.'", '. 239 $in->byte_thing.', '. 240 $in->i32_thing.', '. 241 $in->i64_thing."}\n"); 242 243# 244# NESTED STRUCT TEST 245# 246print('testNest({1, {"Zero", 1, -3, -5}, 5}'); 247my $out2 = ThriftTest::Xtruct2->new(); 248$out2->byte_thing(1); 249$out2->struct_thing($out); 250$out2->i32_thing(5); 251my $in2 = $testClient->testNest($out2); 252$in = $in2->struct_thing; 253print(' = {'.$in2->byte_thing.', {"'. 254 $in->string_thing.'", '. 255 $in->byte_thing.', '. 256 $in->i32_thing.', '. 257 $in->i64_thing.'}, '. 258 $in2->i32_thing."}\n"); 259 260# 261# MAP TEST 262# 263my $mapout = {}; 264for (my $i = 0; $i < 5; ++$i) { 265 $mapout->{$i} = $i-10; 266} 267print('testMap({'); 268my $first = 1; 269while( my($key,$val) = each %$mapout) { 270 if ($first) { 271 $first = 0; 272 } 273 else { 274 print(', '); 275 } 276 print("$key => $val"); 277} 278print('})'); 279 280 281my $mapin = $testClient->testMap($mapout); 282print(' = {'); 283 284$first = 1; 285while( my($key,$val) = each %$mapin){ 286 if ($first) { 287 $first = 0; 288 } 289 else { 290 print(', '); 291 } 292 print("$key => $val"); 293} 294print("}\n"); 295 296# 297# SET TEST 298# 299my $setout = []; 300for (my $i = -2; $i < 3; ++$i) { 301 push(@$setout, $i); 302} 303 304print('testSet({'.join(',',@$setout).'})'); 305 306my $setin = $testClient->testSet($setout); 307 308print(' = {'.join(',',@$setout)."}\n"); 309 310# 311# LIST TEST 312# 313my $listout = []; 314for (my $i = -2; $i < 3; ++$i) { 315 push(@$listout, $i); 316} 317 318print('testList({'.join(',',@$listout).'})'); 319 320my $listin = $testClient->testList($listout); 321 322print(' = {'.join(',',@$listin)."}\n"); 323 324# 325# ENUM TEST 326# 327print('testEnum(ONE)'); 328my $ret = $testClient->testEnum(ThriftTest::Numberz::ONE); 329print(" = $ret\n"); 330 331print('testEnum(TWO)'); 332$ret = $testClient->testEnum(ThriftTest::Numberz::TWO); 333print(" = $ret\n"); 334 335print('testEnum(THREE)'); 336$ret = $testClient->testEnum(ThriftTest::Numberz::THREE); 337print(" = $ret\n"); 338 339print('testEnum(FIVE)'); 340$ret = $testClient->testEnum(ThriftTest::Numberz::FIVE); 341print(" = $ret\n"); 342 343print('testEnum(EIGHT)'); 344$ret = $testClient->testEnum(ThriftTest::Numberz::EIGHT); 345print(" = $ret\n"); 346 347# 348# TYPEDEF TEST 349# 350print('testTypedef(309858235082523)'); 351my $uid = $testClient->testTypedef(309858235082523); 352print(" = $uid\n"); 353 354# 355# NESTED MAP TEST 356# 357print('testMapMap(1)'); 358my $mm = $testClient->testMapMap(1); 359print(' = {'); 360while( my ($key,$val) = each %$mm) { 361 print("$key => {"); 362 while( my($k2,$v2) = each %$val) { 363 print("$k2 => $v2, "); 364 } 365 print('}, '); 366} 367print("}\n"); 368 369# 370# INSANITY TEST 371# 372my $insane = ThriftTest::Insanity->new(); 373$insane->{userMap}->{ThriftTest::Numberz::FIVE} = 5000; 374my $truck = ThriftTest::Xtruct->new(); 375$truck->string_thing('Hello2'); 376$truck->byte_thing(2); 377$truck->i32_thing(2); 378$truck->i64_thing(2); 379my $truck2 = ThriftTest::Xtruct->new(); 380$truck2->string_thing('Goodbye4'); 381$truck2->byte_thing(4); 382$truck2->i32_thing(4); 383$truck2->i64_thing(4); 384push(@{$insane->{xtructs}}, $truck); 385push(@{$insane->{xtructs}}, $truck2); 386 387print('testInsanity()'); 388my $whoa = $testClient->testInsanity($insane); 389print(' = {'); 390while( my ($key,$val) = each %$whoa) { 391 print("$key => {"); 392 while( my($k2,$v2) = each %$val) { 393 print("$k2 => {"); 394 my $userMap = $v2->{userMap}; 395 print('{'); 396 if (ref($userMap) eq 'HASH') { 397 while( my($k3,$v3) = each %$userMap) { 398 print("$k3 => $v3, "); 399 } 400 } 401 print('}, '); 402 403 my $xtructs = $v2->{xtructs}; 404 print('{'); 405 if (ref($xtructs) eq 'ARRAY') { 406 foreach my $x (@$xtructs) { 407 print('{"'.$x->{string_thing}.'", '. 408 $x->{byte_thing}.', '.$x->{i32_thing}.', '.$x->{i64_thing}.'}, '); 409 } 410 } 411 print('}'); 412 413 print('}, '); 414 } 415 print('}, '); 416} 417print("}\n"); 418 419# 420# EXCEPTION TEST 421# 422print(q|testException('Xception')|); 423eval { 424 $testClient->testException('Xception'); 425 print(" void\nFAILURE\n"); 426}; if($@ && $@->UNIVERSAL::isa('ThriftTest::Xception')) { 427 print(' caught xception '.$@->{errorCode}.': '.$@->{message}."\n"); 428} 429 430 431# 432# Normal tests done. 433# 434my $stop = gettimeofday(); 435my $elp = sprintf('%d',1000*($stop - $start), 0); 436print("Total time: $elp ms\n"); 437 438# 439# Extraneous "I don't trust PHP to pack/unpack integer" tests 440# 441 442# Max I32 443my $num = 2**30 + 2**30 - 1; 444my $num2 = $testClient->testI32($num); 445if ($num != $num2) { 446 print "Missed max32 $num = $num2\n"; 447} 448 449# Min I32 450$num = 0 - 2**31; 451$num2 = $testClient->testI32($num); 452if ($num != $num2) { 453 print "Missed min32 $num = $num2\n"; 454} 455 456# Max Number I can get out of my perl 457$num = 2**40; 458$num2 = $testClient->testI64($num); 459if ($num != $num2) { 460 print "Missed max64 $num = $num2\n"; 461} 462 463# Max Number I can get out of my perl 464$num = 0 - 2**40; 465$num2 = $testClient->testI64($num); 466if ($num != $num2) { 467 print "Missed min64 $num = $num2\n"; 468} 469 470$transport->close(); 471 472 473 474