| <?php |
| |
| namespace test\php; |
| |
| /** @var \Composer\Autoload\ClassLoader $loader */ |
| $loader = require __DIR__ . '/../../vendor/autoload.php'; |
| |
| use Thrift\ClassLoader\ThriftClassLoader; |
| |
| if (!isset($GEN_DIR)) { |
| $GEN_DIR = 'gen-php'; |
| } |
| if (!isset($MODE)) { |
| $MODE = 'normal'; |
| } |
| |
| |
| if ($GEN_DIR == 'gen-php') { |
| $loader->addPsr4('', $GEN_DIR); |
| } else { |
| $loader = new ThriftClassLoader(); |
| $loader->registerDefinition('ThriftTest', $GEN_DIR); |
| $loader->register(); |
| } |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| /** Include the Thrift base */ |
| /** Include the protocols */ |
| use Thrift\Protocol\TBinaryProtocol; |
| use Thrift\Protocol\TBinaryProtocolAccelerated; |
| use Thrift\Protocol\TCompactProtocol; |
| use Thrift\Protocol\TJSONProtocol; |
| |
| /** Include the socket layer */ |
| use Thrift\Transport\TSocket; |
| use Thrift\Transport\TSocketPool; |
| |
| /** Include the socket layer */ |
| use Thrift\Transport\TFramedTransport; |
| use Thrift\Transport\TBufferedTransport; |
| |
| function makeProtocol($transport, $PROTO) |
| { |
| if ($PROTO == 'binary') { |
| return new TBinaryProtocol($transport); |
| } else if ($PROTO == 'compact') { |
| return new TCompactProtocol($transport); |
| } else if ($PROTO == 'json') { |
| return new TJSONProtocol($transport); |
| } else if ($PROTO == 'accel') { |
| if (!function_exists('thrift_protocol_write_binary')) { |
| echo "Acceleration extension is not loaded\n"; |
| exit(1); |
| } |
| return new TBinaryProtocolAccelerated($transport); |
| } |
| |
| echo "--protocol must be one of {binary|compact|json|accel}\n"; |
| exit(1); |
| } |
| |
| $host = 'localhost'; |
| $port = 9090; |
| |
| if ($argc > 1) { |
| $host = $argv[0]; |
| } |
| |
| if ($argc > 2) { |
| $host = $argv[1]; |
| } |
| |
| foreach ($argv as $arg) { |
| if (substr($arg, 0, 7) == '--port=') { |
| $port = substr($arg, 7); |
| } else if (substr($arg, 0, 12) == '--transport=') { |
| $MODE = substr($arg, 12); |
| } else if (substr($arg, 0, 11) == '--protocol=') { |
| $PROTO = substr($arg, 11); |
| } |
| } |
| |
| $hosts = array('localhost'); |
| |
| $socket = new TSocket($host, $port); |
| $socket = new TSocketPool($hosts, $port); |
| $socket->setDebug(TRUE); |
| |
| if ($MODE == 'inline') { |
| $transport = $socket; |
| $testClient = new \ThriftTest\ThriftTestClient($transport); |
| } else if ($MODE == 'framed') { |
| $framedSocket = new TFramedTransport($socket); |
| $transport = $framedSocket; |
| $protocol = makeProtocol($transport, $PROTO); |
| $testClient = new \ThriftTest\ThriftTestClient($protocol); |
| } else { |
| $bufferedSocket = new TBufferedTransport($socket, 1024, 1024); |
| $transport = $bufferedSocket; |
| $protocol = makeProtocol($transport, $PROTO); |
| $testClient = new \ThriftTest\ThriftTestClient($protocol); |
| } |
| |
| $transport->open(); |
| |
| $start = microtime(true); |
| |
| define('ERR_BASETYPES', 1); |
| define('ERR_STRUCTS', 2); |
| define('ERR_CONTAINERS', 4); |
| define('ERR_EXCEPTIONS', 8); |
| define('ERR_UNKNOWN', 64); |
| $exitcode = 0; |
| /** |
| * VOID TEST |
| */ |
| print_r("testVoid()"); |
| $testClient->testVoid(); |
| print_r(" = void\n"); |
| |
| function roundtrip($testClient, $method, $value) { |
| global $exitcode; |
| print_r("$method($value)"); |
| $ret = $testClient->$method($value); |
| print_r(" = \"$ret\"\n"); |
| if ($value !== $ret) { |
| print_r("*** FAILED ***\n"); |
| $exitcode |= ERR_BASETYPES; |
| } |
| } |
| |
| /** |
| * STRING TEST |
| */ |
| roundtrip($testClient, 'testString', "Test"); |
| |
| /** |
| * BOOL TEST |
| */ |
| roundtrip($testClient, 'testBool', true); |
| roundtrip($testClient, 'testBool', false); |
| |
| /** |
| * BYTE TEST |
| */ |
| roundtrip($testClient, 'testByte', 1); |
| roundtrip($testClient, 'testByte', -1); |
| roundtrip($testClient, 'testByte', 127); |
| roundtrip($testClient, 'testByte', -128); |
| |
| /** |
| * I32 TEST |
| */ |
| roundtrip($testClient, 'testI32', -1); |
| |
| /** |
| * I64 TEST |
| */ |
| roundtrip($testClient, 'testI64', 0); |
| roundtrip($testClient, 'testI64', 1); |
| roundtrip($testClient, 'testI64', -1); |
| roundtrip($testClient, 'testI64', -34359738368); |
| |
| /** |
| * DOUBLE TEST |
| */ |
| roundtrip($testClient, 'testDouble', -852.234234234); |
| |
| /** |
| * BINARY TEST -- TODO |
| */ |
| |
| /** |
| * STRUCT TEST |
| */ |
| print_r("testStruct({\"Zero\", 1, -3, -5})"); |
| $out = new \ThriftTest\Xtruct(); |
| $out->string_thing = "Zero"; |
| $out->byte_thing = 1; |
| $out->i32_thing = -3; |
| $out->i64_thing = -5; |
| $in = $testClient->testStruct($out); |
| print_r(" = {\"".$in->string_thing."\", ". |
| $in->byte_thing.", ". |
| $in->i32_thing.", ". |
| $in->i64_thing."}\n"); |
| |
| if ($in != $out) { |
| echo "**FAILED**\n"; |
| $exitcode |= ERR_STRUCTS; |
| } |
| |
| /** |
| * NESTED STRUCT TEST |
| */ |
| print_r("testNest({1, {\"Zero\", 1, -3, -5}), 5}"); |
| $out2 = new \ThriftTest\Xtruct2(); |
| $out2->byte_thing = 1; |
| $out2->struct_thing = $out; |
| $out2->i32_thing = 5; |
| $in2 = $testClient->testNest($out2); |
| $in = $in2->struct_thing; |
| print_r(" = {".$in2->byte_thing.", {\"". |
| $in->string_thing."\", ". |
| $in->byte_thing.", ". |
| $in->i32_thing.", ". |
| $in->i64_thing."}, ". |
| $in2->i32_thing."}\n"); |
| |
| if ($in2 != $out2) { |
| echo "**FAILED**\n"; |
| $exitcode |= ERR_STRUCTS; |
| } |
| |
| /** |
| * MAP TEST |
| */ |
| $mapout = array(); |
| for ($i = 0; $i < 5; ++$i) { |
| $mapout[$i] = $i-10; |
| } |
| print_r("testMap({"); |
| $first = true; |
| foreach ($mapout as $key => $val) { |
| if ($first) { |
| $first = false; |
| } else { |
| print_r(", "); |
| } |
| print_r("$key => $val"); |
| } |
| print_r("})"); |
| |
| $mapin = $testClient->testMap($mapout); |
| print_r(" = {"); |
| $first = true; |
| foreach ($mapin as $key => $val) { |
| if ($first) { |
| $first = false; |
| } else { |
| print_r(", "); |
| } |
| print_r("$key => $val"); |
| } |
| print_r("}\n"); |
| |
| if ($mapin != $mapout) { |
| echo "**FAILED**\n"; |
| $exitcode |= ERR_CONTAINERS; |
| } |
| |
| $mapout = array(); |
| for ($i = 0; $i < 10; $i++) { |
| $mapout["key$i"] = "val$i"; |
| } |
| print_r('testStringMap({'); |
| $first = true; |
| foreach ($mapout as $key => $val) { |
| if ($first) { |
| $first = false; |
| } else { |
| print_r(", "); |
| } |
| print_r("\"$key\" => \"$val\""); |
| } |
| print_r("})"); |
| $mapin = $testClient->testStringMap($mapout); |
| print_r(" = {"); |
| $first = true; |
| foreach ($mapin as $key => $val) { |
| if ($first) { |
| $first = false; |
| } else { |
| print_r(", "); |
| } |
| print_r("\"$key\" => \"$val\""); |
| } |
| print_r("}\n"); |
| ksort($mapin); |
| if ($mapin != $mapout) { |
| echo "**FAILED**\n"; |
| $exitcode |= ERR_CONTAINERS; |
| } |
| |
| /** |
| * SET TEST |
| */ |
| $setout = array();; |
| for ($i = -2; $i < 3; ++$i) { |
| $setout[$i]= true; |
| } |
| print_r("testSet({"); |
| echo implode(',', array_keys($setout)); |
| print_r("})"); |
| $setin = $testClient->testSet($setout); |
| print_r(" = {"); |
| echo implode(', ', array_keys($setin)); |
| print_r("}\n"); |
| // Order of keys in set does not matter |
| ksort($setin); |
| if ($setout !== $setin) { |
| echo "**FAILED**\n"; |
| $exitcode |= ERR_CONTAINERS; |
| } |
| // Regression test for corrupted array |
| if ($setin[2] !== $setout[2] || is_int($setin[2])) { |
| echo "**FAILED**\n"; |
| $exitcode |= ERR_CONTAINERS; |
| } |
| |
| /** |
| * LIST TEST |
| */ |
| $listout = array(); |
| for ($i = -2; $i < 3; ++$i) { |
| $listout []= $i; |
| } |
| print_r("testList({"); |
| $first = true; |
| foreach ($listout as $val) { |
| if ($first) { |
| $first = false; |
| } else { |
| print_r(", "); |
| } |
| print_r($val); |
| } |
| print_r("})"); |
| $listin = $testClient->testList($listout); |
| print_r(" = {"); |
| $first = true; |
| foreach ($listin as $val) { |
| if ($first) { |
| $first = false; |
| } else { |
| print_r(", "); |
| } |
| print_r($val); |
| } |
| print_r("}\n"); |
| if ($listin !== $listout) { |
| echo "**FAILED**\n"; |
| $exitcode |= ERR_CONTAINERS; |
| } |
| |
| /** |
| * ENUM TEST |
| */ |
| print_r("testEnum(ONE)"); |
| $ret = $testClient->testEnum(\ThriftTest\Numberz::ONE); |
| print_r(" = $ret\n"); |
| if ($ret != \ThriftTest\Numberz::ONE) { |
| echo "**FAILED**\n"; |
| $exitcode |= ERR_STRUCTS; |
| } |
| |
| print_r("testEnum(TWO)"); |
| $ret = $testClient->testEnum(\ThriftTest\Numberz::TWO); |
| print_r(" = $ret\n"); |
| if ($ret != \ThriftTest\Numberz::TWO) { |
| echo "**FAILED**\n"; |
| $exitcode |= ERR_STRUCTS; |
| } |
| |
| print_r("testEnum(THREE)"); |
| $ret = $testClient->testEnum(\ThriftTest\Numberz::THREE); |
| print_r(" = $ret\n"); |
| if ($ret != \ThriftTest\Numberz::THREE) { |
| echo "**FAILED**\n"; |
| $exitcode |= ERR_STRUCTS; |
| } |
| |
| print_r("testEnum(FIVE)"); |
| $ret = $testClient->testEnum(\ThriftTest\Numberz::FIVE); |
| print_r(" = $ret\n"); |
| if ($ret != \ThriftTest\Numberz::FIVE) { |
| echo "**FAILED**\n"; |
| $exitcode |= ERR_STRUCTS; |
| } |
| |
| print_r("testEnum(EIGHT)"); |
| $ret = $testClient->testEnum(\ThriftTest\Numberz::EIGHT); |
| print_r(" = $ret\n"); |
| if ($ret != \ThriftTest\Numberz::EIGHT) { |
| echo "**FAILED**\n"; |
| $exitcode |= ERR_STRUCTS; |
| } |
| |
| /** |
| * TYPEDEF TEST |
| */ |
| print_r("testTypedef(309858235082523)"); |
| $uid = $testClient->testTypedef(309858235082523); |
| print_r(" = $uid\n"); |
| if ($uid !== 309858235082523) { |
| echo "**FAILED**\n"; |
| $exitcode |= ERR_STRUCTS; |
| } |
| |
| /** |
| * NESTED MAP TEST |
| */ |
| print_r("testMapMap(1)"); |
| $mm = $testClient->testMapMap(1); |
| print_r(" = {"); |
| foreach ($mm as $key => $val) { |
| print_r("$key => {"); |
| foreach ($val as $k2 => $v2) { |
| print_r("$k2 => $v2, "); |
| } |
| print_r("}, "); |
| } |
| print_r("}\n"); |
| $expected_mm = [ |
| -4 => [-4 => -4, -3 => -3, -2 => -2, -1 => -1], |
| 4 => [4 => 4, 3 => 3, 2 => 2, 1 => 1], |
| ]; |
| if ($mm != $expected_mm) { |
| echo "**FAILED**\n"; |
| $exitcode |= ERR_CONTAINERS; |
| } |
| |
| /** |
| * INSANITY TEST |
| */ |
| $insane = new \ThriftTest\Insanity(); |
| $insane->userMap[\ThriftTest\Numberz::FIVE] = 5000; |
| $truck = new \ThriftTest\Xtruct(); |
| $truck->string_thing = "Truck"; |
| $truck->byte_thing = 8; |
| $truck->i32_thing = 8; |
| $truck->i64_thing = 8; |
| $insane->xtructs []= $truck; |
| print_r("testInsanity()"); |
| $whoa = $testClient->testInsanity($insane); |
| print_r(" = {"); |
| foreach ($whoa as $key => $val) { |
| print_r("$key => {"); |
| foreach ($val as $k2 => $v2) { |
| print_r("$k2 => {"); |
| $userMap = $v2->userMap; |
| print_r("{"); |
| if (is_array($userMap)) { |
| foreach ($userMap as $k3 => $v3) { |
| print_r("$k3 => $v3, "); |
| } |
| } |
| print_r("}, "); |
| |
| $xtructs = $v2->xtructs; |
| print_r("{"); |
| if (is_array($xtructs)) { |
| foreach ($xtructs as $x) { |
| print_r("{\"".$x->string_thing."\", ". |
| $x->byte_thing.", ".$x->i32_thing.", ".$x->i64_thing."}, "); |
| } |
| } |
| print_r("}"); |
| |
| print_r("}, "); |
| } |
| print_r("}, "); |
| } |
| print_r("}\n"); |
| |
| /** |
| * EXCEPTION TEST |
| */ |
| print_r("testException('Xception')"); |
| try { |
| $testClient->testException('Xception'); |
| print_r(" void\nFAILURE\n"); |
| $exitcode |= ERR_EXCEPTIONS; |
| } catch (\ThriftTest\Xception $x) { |
| print_r(' caught xception '.$x->errorCode.': '.$x->message."\n"); |
| } |
| |
| // Regression test for THRIFT-4263 |
| print_r("testBinarySerializer_Deserialize('foo')"); |
| try { |
| \Thrift\Serializer\TBinarySerializer::deserialize(base64_decode('foo'), \ThriftTest\Xtruct2::class); |
| echo "**FAILED**\n"; |
| $exitcode |= ERR_STRUCTS; |
| } catch (\Thrift\Exception\TTransportException $happy_exception) { |
| // We expected this due to binary data of base64_decode('foo') is less then 4 |
| // bytes and it tries to find thrift version number in the transport by |
| // reading i32() at the beginning. Casting to string validates that |
| // exception is still accessible in memory and not corrupted. Without patch, |
| // PHP will error log that the exception doesn't have any tostring method, |
| // which is a lie due to corrupted memory. |
| for($i=99; $i > 0; $i--) { |
| (string)$happy_exception; |
| } |
| print_r(" SUCCESS\n"); |
| } |
| |
| /** |
| * Normal tests done. |
| */ |
| |
| $stop = microtime(true); |
| $elp = round(1000*($stop - $start), 0); |
| print_r("Total time: $elp ms\n"); |
| |
| /** |
| * Extraneous "I don't trust PHP to pack/unpack integer" tests |
| */ |
| |
| if ($protocol instanceof TBinaryProtocolAccelerated) { |
| // Regression check: check that method name is not double-freed |
| // Method name should not be an interned string. |
| $method_name = "Void"; |
| $method_name = "test$method_name"; |
| |
| $seqid = 0; |
| $args = new \ThriftTest\ThriftTest_testVoid_args(); |
| thrift_protocol_write_binary($protocol, $method_name, \Thrift\Type\TMessageType::CALL, $args, $seqid, $protocol->isStrictWrite()); |
| $testClient->recv_testVoid(); |
| |
| } |
| |
| // Max I32 |
| $num = pow(2, 30) + (pow(2, 30) - 1); |
| roundtrip($testClient, 'testI32', $num); |
| |
| // Min I32 |
| $num = 0 - pow(2, 31); |
| roundtrip($testClient, 'testI32', $num); |
| |
| // Max I64 |
| $num = pow(2, 62) + (pow(2, 62) - 1); |
| roundtrip($testClient, 'testI64', $num); |
| |
| // Min I64 |
| $num = 0 - pow(2, 62) - pow(2, 62); |
| roundtrip($testClient, 'testI64', $num); |
| |
| $transport->close(); |
| exit($exitcode); |