diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0b29ddb906e..2472029cafa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -120,11 +120,11 @@ jobs: mkdir -p ./lib/php/test/Resources/packages/phpvo mkdir -p ./lib/php/test/Resources/packages/phpjs mkdir -p ./lib/php/test/Resources/packages/phpcm - compiler/cpp/thrift --gen php -r --out ./lib/php/test/Resources/packages/php lib/php/test/Resources/ThriftTest.thrift - compiler/cpp/thrift --gen php:validate -r --out ./lib/php/test/Resources/packages/phpv lib/php/test/Resources/ThriftTest.thrift - compiler/cpp/thrift --gen php:validate,oop -r --out ./lib/php/test/Resources/packages/phpvo lib/php/test/Resources/ThriftTest.thrift - compiler/cpp/thrift --gen php:json -r --out ./lib/php/test/Resources/packages/phpjs lib/php/test/Resources/ThriftTest.thrift - compiler/cpp/thrift --gen php:classmap,server,rest -r --out ./lib/php/test/Resources/packages/phpcm lib/php/test/Resources/ThriftTest.thrift + compiler/cpp/thrift --gen php:nsglobal="Basic" -r --out ./lib/php/test/Resources/packages/php lib/php/test/Resources/ThriftTest.thrift + compiler/cpp/thrift --gen php:validate,nsglobal="Validate" -r --out ./lib/php/test/Resources/packages/phpv lib/php/test/Resources/ThriftTest.thrift + compiler/cpp/thrift --gen php:validate,oop,nsglobal="ValidateOop" -r --out ./lib/php/test/Resources/packages/phpvo lib/php/test/Resources/ThriftTest.thrift + compiler/cpp/thrift --gen php:json,nsglobal="Json" -r --out ./lib/php/test/Resources/packages/phpjs lib/php/test/Resources/ThriftTest.thrift + compiler/cpp/thrift --gen php:classmap,server,rest,nsglobal="Classmap" -r --out ./lib/php/test/Resources/packages/phpcm lib/php/test/Resources/ThriftTest.thrift - name: Run Tests run: vendor/bin/phpunit -c lib/php/phpunit.xml diff --git a/lib/php/lib/Protocol/TCompactProtocol.php b/lib/php/lib/Protocol/TCompactProtocol.php index 1af2a274a24..ebe32e52819 100644 --- a/lib/php/lib/Protocol/TCompactProtocol.php +++ b/lib/php/lib/Protocol/TCompactProtocol.php @@ -154,6 +154,7 @@ public function readVarint(&$result) $shift += 7; } + #unreachable statement return $idx; } diff --git a/lib/php/lib/Protocol/TJSONProtocol.php b/lib/php/lib/Protocol/TJSONProtocol.php index e1412cc3acb..cfd3c8b2b53 100644 --- a/lib/php/lib/Protocol/TJSONProtocol.php +++ b/lib/php/lib/Protocol/TJSONProtocol.php @@ -23,6 +23,7 @@ namespace Thrift\Protocol; +use Thrift\Exception\TException; use Thrift\Type\TType; use Thrift\Exception\TProtocolException; use Thrift\Protocol\JSON\BaseContext; @@ -186,8 +187,6 @@ public function reset() $this->reader_ = new LookaheadReader($this); } - private $tmpbuf_ = array(4); - public function readJSONSyntaxChar($b) { $ch = $this->reader_->read(); @@ -197,68 +196,6 @@ public function readJSONSyntaxChar($b) } } - private function hexVal($s) - { - for ($i = 0; $i < strlen($s); $i++) { - $ch = substr($s, $i, 1); - - if (!($ch >= "a" && $ch <= "f") && !($ch >= "0" && $ch <= "9")) { - throw new TProtocolException("Expected hex character " . $ch, TProtocolException::INVALID_DATA); - } - } - - return hexdec($s); - } - - private function hexChar($val) - { - return dechex($val); - } - - private function hasJSONUnescapedUnicode() - { - if (PHP_MAJOR_VERSION > 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4)) { - return true; - } - - return false; - } - - private function unescapedUnicode($str) - { - if ($this->hasJSONUnescapedUnicode()) { - return json_encode($str, JSON_UNESCAPED_UNICODE); - } - - $json = json_encode($str); - - /* - * Unescaped character outside the Basic Multilingual Plane - * High surrogate: 0xD800 - 0xDBFF - * Low surrogate: 0xDC00 - 0xDFFF - */ - $json = preg_replace_callback( - '/\\\\u(d[89ab][0-9a-f]{2})\\\\u(d[cdef][0-9a-f]{2})/i', - function ($matches) { - return mb_convert_encoding(pack('H*', $matches[1] . $matches[2]), 'UTF-8', 'UTF-16BE'); - }, - $json - ); - - /* - * Unescaped characters within the Basic Multilingual Plane - */ - $json = preg_replace_callback( - '/\\\\u([0-9a-f]{4})/i', - function ($matches) { - return mb_convert_encoding(pack('H*', $matches[1]), 'UTF-8', 'UTF-16BE'); - }, - $json - ); - - return $json; - } - private function writeJSONString($b) { $this->context_->write(); @@ -267,7 +204,7 @@ private function writeJSONString($b) $this->trans_->write(self::QUOTE); } - $this->trans_->write($this->unescapedUnicode($b)); + $this->trans_->write(json_encode($b, JSON_UNESCAPED_UNICODE)); if (is_numeric($b) && $this->context_->escapeNum()) { $this->trans_->write(self::QUOTE); @@ -297,6 +234,7 @@ private function writeJSONDouble($num) $this->trans_->write(self::QUOTE); } + #TODO add compatibility with NAN and INF $this->trans_->write(json_encode($num)); if ($this->context_->escapeNum()) { @@ -304,14 +242,6 @@ private function writeJSONDouble($num) } } - private function writeJSONBase64($data) - { - $this->context_->write(); - $this->trans_->write(self::QUOTE); - $this->trans_->write(json_encode(base64_encode($data))); - $this->trans_->write(self::QUOTE); - } - private function writeJSONObjectStart() { $this->context_->write(); @@ -481,18 +411,6 @@ private function readJSONDouble() } } - private function readJSONBase64() - { - $arr = $this->readJSONString(false); - $data = base64_decode($arr, true); - - if ($data === false) { - throw new TProtocolException("Invalid base64 data " . $arr, TProtocolException::INVALID_DATA); - } - - return $data; - } - private function readJSONObjectStart() { $this->context_->read(); diff --git a/lib/php/lib/Protocol/TSimpleJSONProtocol.php b/lib/php/lib/Protocol/TSimpleJSONProtocol.php index 1cf1f640745..22f17423bc4 100644 --- a/lib/php/lib/Protocol/TSimpleJSONProtocol.php +++ b/lib/php/lib/Protocol/TSimpleJSONProtocol.php @@ -115,6 +115,7 @@ private function writeJSONDouble($num) $this->trans_->write(self::QUOTE); } + #TODO add compatibility with NAN and INF $this->trans_->write(json_encode((float)$num)); if ($isMapKey) { diff --git a/lib/php/phpunit.xml b/lib/php/phpunit.xml index 2cbea95d345..58e8f5dc2a9 100644 --- a/lib/php/phpunit.xml +++ b/lib/php/phpunit.xml @@ -18,7 +18,7 @@ under the License. --> - + ./test/Unit + + ./test/Integration + diff --git a/lib/php/test/Fixtures/Fixtures.php b/lib/php/test/Fixtures/Fixtures.php deleted file mode 100644 index d48be4061c8..00000000000 --- a/lib/php/test/Fixtures/Fixtures.php +++ /dev/null @@ -1,192 +0,0 @@ -<><"; - - self::$testArgs['testString3'] = - "string that ends in double-backslash \\\\"; - - self::$testArgs['testUnicodeStringWithNonBMP'] = - "สวัสดี/𝒯"; - - self::$testArgs['testDouble'] = 3.1415926535898; - - // TODO: add testBinary() call - - self::$testArgs['testByte'] = 0x01; - - self::$testArgs['testI32'] = pow(2, 30); - - if (PHP_INT_SIZE == 8) { - self::$testArgs['testI64'] = pow(2, 60); - } else { - self::$testArgs['testI64'] = "1152921504606847000"; - } - - self::$testArgs['testStruct'] = - new Xtruct( - array( - 'string_thing' => 'worked', - 'byte_thing' => 0x01, - 'i32_thing' => pow(2, 30), - 'i64_thing' => self::$testArgs['testI64'] - ) - ); - - self::$testArgs['testNestNested'] = - new Xtruct( - array( - 'string_thing' => 'worked', - 'byte_thing' => 0x01, - 'i32_thing' => pow(2, 30), - 'i64_thing' => self::$testArgs['testI64'] - ) - ); - - self::$testArgs['testNest'] = - new Xtruct2( - array( - 'byte_thing' => 0x01, - 'struct_thing' => self::$testArgs['testNestNested'], - 'i32_thing' => pow(2, 15) - ) - ); - - self::$testArgs['testMap'] = - array( - 7 => 77, - 8 => 88, - 9 => 99 - ); - - self::$testArgs['testStringMap'] = - array( - "a" => "123", - "a b" => "with spaces ", - "same" => "same", - "0" => "numeric key", - "longValue" => self::$testArgs['testString1'], - self::$testArgs['testString1'] => "long key" - ); - - self::$testArgs['testSet'] = array(1 => true, 5 => true, 6 => true); - - self::$testArgs['testList'] = array(1, 2, 3); - - self::$testArgs['testEnum'] = Numberz::ONE; - - self::$testArgs['testTypedef'] = 69; - - self::$testArgs['testMapMapExpectedResult'] = - array( - 4 => array( - 1 => 1, - 2 => 2, - 3 => 3, - 4 => 4, - ), - -4 => array( - -4 => -4, - -3 => -3, - -2 => -2, - -1 => -1 - ) - ); - - // testInsanity ... takes a few steps to set up! - - $xtruct1 = - new Xtruct( - array( - 'string_thing' => 'Goodbye4', - 'byte_thing' => 4, - 'i32_thing' => 4, - 'i64_thing' => 4 - ) - ); - - $xtruct2 = - new Xtruct( - array( - 'string_thing' => 'Hello2', - 'byte_thing' => 2, - 'i32_thing' => 2, - 'i64_thing' => 2 - ) - ); - - $userMap = - array( - Numberz::FIVE => 5, - Numberz::EIGHT => 8 - ); - - $insanity2 = - new Insanity( - array( - 'userMap' => $userMap, - 'xtructs' => array($xtruct1, $xtruct2) - ) - ); - - $insanity3 = $insanity2; - - $insanity6 = - new Insanity( - array( - 'userMap' => null, - 'xtructs' => null - ) - ); - - self::$testArgs['testInsanityExpectedResult'] = - array( - "1" => array( - Numberz::TWO => $insanity2, - Numberz::THREE => $insanity3 - ), - "2" => array( - Numberz::SIX => $insanity6 - ) - ); - } -} diff --git a/lib/php/test/Fixtures/TJSONProtocolFixtures.php b/lib/php/test/Fixtures/TJSONProtocolFixtures.php deleted file mode 100644 index 77fb270a796..00000000000 --- a/lib/php/test/Fixtures/TJSONProtocolFixtures.php +++ /dev/null @@ -1,72 +0,0 @@ -<><"}}'; - - self::$testArgsJSON['testString3'] = '{"1":{"str":"string that ends in double-backslash \\\\\\\\"}}'; - - self::$testArgsJSON['testUnicodeStringWithNonBMP'] = '{"1":{"str":"สวัสดี\/𝒯"}}'; - - self::$testArgsJSON['testDouble'] = '{"1":{"dbl":3.1415926535898}}'; - - self::$testArgsJSON['testByte'] = '{"1":{"i8":1}}'; - - self::$testArgsJSON['testI32'] = '{"1":{"i32":1073741824}}'; - - if (PHP_INT_SIZE == 8) { - self::$testArgsJSON['testI64'] = '{"1":{"i64":' . pow(2, 60) . '}}'; - self::$testArgsJSON['testStruct'] = '{"1":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":' . pow(2, 60) . '}}}}'; - self::$testArgsJSON['testNest'] = '{"1":{"rec":{"1":{"i8":1},"2":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":' . pow(2, 60) . '}}},"3":{"i32":32768}}}}'; - } else { - self::$testArgsJSON['testI64'] = '{"1":{"i64":1152921504606847000}}'; - self::$testArgsJSON['testStruct'] = '{"1":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":1152921504606847000}}}}'; - self::$testArgsJSON['testNest'] = '{"1":{"rec":{"1":{"i8":1},"2":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":1152921504606847000}}},"3":{"i32":32768}}}}'; - } - - self::$testArgsJSON['testMap'] = '{"1":{"map":["i32","i32",3,{"7":77,"8":88,"9":99}]}}'; - - self::$testArgsJSON['testStringMap'] = '{"1":{"map":["str","str",6,{"a":"123","a b":"with spaces ","same":"same","0":"numeric key","longValue":"Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e","Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e":"long key"}]}}'; - - self::$testArgsJSON['testSet'] = '{"1":{"set":["i32",3,1,5,6]}}'; - - self::$testArgsJSON['testList'] = '{"1":{"lst":["i32",3,1,2,3]}}'; - - self::$testArgsJSON['testEnum'] = '{"1":{"i32":1}}'; - - self::$testArgsJSON['testTypedef'] = '{"1":{"i64":69}}'; - - self::$testArgsJSON['testMapMap'] = '{"0":{"map":["i32","map",2,{"4":["i32","i32",4,{"1":1,"2":2,"3":3,"4":4}],"-4":["i32","i32",4,{"-4":-4,"-3":-3,"-2":-2,"-1":-1}]}]}}'; - - self::$testArgsJSON['testInsanity'] = '{"0":{"map":["i64","map",2,{"1":["i32","rec",2,{"2":{"1":{"map":["i32","i64",2,{"5":5,"8":8}]},"2":{"lst":["rec",2,{"1":{"str":"Goodbye4"},"4":{"i8":4},"9":{"i32":4},"11":{"i64":4}},{"1":{"str":"Hello2"},"4":{"i8":2},"9":{"i32":2},"11":{"i64":2}}]}},"3":{"1":{"map":["i32","i64",2,{"5":5,"8":8}]},"2":{"lst":["rec",2,{"1":{"str":"Goodbye4"},"4":{"i8":4},"9":{"i32":4},"11":{"i64":4}},{"1":{"str":"Hello2"},"4":{"i8":2},"9":{"i32":2},"11":{"i64":2}}]}}}],"2":["i32","rec",1,{"6":{}}]}]}}'; - } -} diff --git a/lib/php/test/Fixtures/TSimpleJSONProtocolFixtures.php b/lib/php/test/Fixtures/TSimpleJSONProtocolFixtures.php deleted file mode 100644 index 0281a879b7e..00000000000 --- a/lib/php/test/Fixtures/TSimpleJSONProtocolFixtures.php +++ /dev/null @@ -1,65 +0,0 @@ -<><"}'; - - self::$testArgsJSON['testDouble'] = '{"thing":3.1415926535898}'; - - self::$testArgsJSON['testByte'] = '{"thing":1}'; - - self::$testArgsJSON['testI32'] = '{"thing":1073741824}'; - - if (PHP_INT_SIZE == 8) { - self::$testArgsJSON['testI64'] = '{"thing":' . pow(2, 60) . '}'; - self::$testArgsJSON['testStruct'] = '{"thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":' . pow(2, 60) . '}}'; - self::$testArgsJSON['testNest'] = '{"thing":{"byte_thing":1,"struct_thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":' . pow(2, 60) . '},"i32_thing":32768}}'; - } else { - self::$testArgsJSON['testI64'] = '{"thing":1152921504606847000}'; - - self::$testArgsJSON['testStruct'] = '{"thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":1152921504606847000}}'; - self::$testArgsJSON['testNest'] = '{"thing":{"byte_thing":1,"struct_thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":1152921504606847000},"i32_thing":32768}}'; - } - - self::$testArgsJSON['testMap'] = '{"thing":{"7":77,"8":88,"9":99}}'; - - self::$testArgsJSON['testStringMap'] = '{"thing":{"a":"123","a b":"with spaces ","same":"same","0":"numeric key","longValue":"Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e","Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e":"long key"}}'; - - self::$testArgsJSON['testSet'] = '{"thing":[1,5,6]}'; - - self::$testArgsJSON['testList'] = '{"thing":[1,2,3]}'; - - self::$testArgsJSON['testEnum'] = '{"thing":1}'; - - self::$testArgsJSON['testTypedef'] = '{"thing":69}'; - } -} diff --git a/lib/php/test/Unit/BaseValidatorTest.php b/lib/php/test/Integration/BaseValidatorTest.php similarity index 76% rename from lib/php/test/Unit/BaseValidatorTest.php rename to lib/php/test/Integration/BaseValidatorTest.php index 4404e72ce98..ae9d5844d2e 100644 --- a/lib/php/test/Unit/BaseValidatorTest.php +++ b/lib/php/test/Integration/BaseValidatorTest.php @@ -19,7 +19,7 @@ * under the License. */ -namespace Test\Thrift\Unit; +namespace Test\Thrift\Integration; use PHPUnit\Framework\TestCase; use Thrift\Exception\TProtocolException; @@ -28,38 +28,41 @@ abstract class BaseValidatorTest extends TestCase { + abstract public function getNsGlobal(); + public function testEmptyStructValidator() { - $this->assertNoReadValidator('ThriftTest\EmptyStruct'); - $this->assertNoWriteValidator('ThriftTest\EmptyStruct'); + $this->assertNoReadValidator($this->getNsGlobal() . '\ThriftTest\EmptyStruct'); + $this->assertNoWriteValidator($this->getNsGlobal() . '\ThriftTest\EmptyStruct'); } public function testBonkValidator() { - $this->assertNoReadValidator('ThriftTest\Bonk'); - $this->assertHasWriteValidator('ThriftTest\Bonk'); + $this->assertNoReadValidator($this->getNsGlobal() . '\ThriftTest\Bonk'); + $this->assertHasWriteValidator($this->getNsGlobal() . '\ThriftTest\Bonk'); } public function testStructAValidator() { - $this->assertHasReadValidator('ThriftTest\StructA'); - $this->assertHasWriteValidator('ThriftTest\StructA'); + $this->assertHasReadValidator($this->getNsGlobal() . '\ThriftTest\StructA'); + $this->assertHasWriteValidator($this->getNsGlobal() . '\ThriftTest\StructA'); } public function testUnionOfStringsValidator() { - $this->assertNoWriteValidator('TestValidators\UnionOfStrings'); + $this->assertNoWriteValidator($this->getNsGlobal() . '\TestValidators\UnionOfStrings'); } public function testServiceResultValidator() { - $this->assertNoReadValidator('TestValidators\TestService_test_result'); - $this->assertNoWriteValidator('TestValidators\TestService_test_result'); + $this->assertNoReadValidator($this->getNsGlobal() . '\TestValidators\TestService_test_result'); + $this->assertNoWriteValidator($this->getNsGlobal() . '\TestValidators\TestService_test_result'); } public function testReadEmpty() { - $bonk = new \ThriftTest\Bonk(); + $className = $this->getNsGlobal() . '\ThriftTest\Bonk'; + $bonk = new $className(); $transport = new TMemoryBuffer("\000"); $protocol = new TBinaryProtocol($transport); $bonk->read($protocol); @@ -68,7 +71,8 @@ public function testReadEmpty() public function testWriteEmpty() { - $bonk = new \ThriftTest\Bonk(); + $className = $this->getNsGlobal() . '\ThriftTest\Bonk'; + $bonk = new $className(); $transport = new TMemoryBuffer(); $protocol = new TBinaryProtocol($transport); try { @@ -83,7 +87,8 @@ public function testWriteEmpty() public function testWriteWithMissingRequired() { // Check that we are not able to write StructA with a missing required field - $structa = new \ThriftTest\StructA(); + $className = $this->getNsGlobal() . '\ThriftTest\StructA'; + $structa = new $className(); $transport = new TMemoryBuffer(); $protocol = new TBinaryProtocol($transport); @@ -100,7 +105,8 @@ public function testReadStructA() { $transport = new TMemoryBuffer(base64_decode('CwABAAAAA2FiYwA=')); $protocol = new TBinaryProtocol($transport); - $structa = new \ThriftTest\StructA(); + $className = $this->getNsGlobal() . '\ThriftTest\StructA'; + $structa = new $className(); $structa->read($protocol); $this->assertEquals("abc", $structa->s); } @@ -109,7 +115,8 @@ public function testWriteStructA() { $transport = new TMemoryBuffer(); $protocol = new TBinaryProtocol($transport); - $structa = new \ThriftTest\StructA(); + $className = $this->getNsGlobal() . '\ThriftTest\StructA'; + $structa = new $className(); $structa->s = "abc"; $structa->write($protocol); $writeResult = base64_encode($transport->getBuffer()); diff --git a/lib/php/test/Integration/Lib/ClassLoader/ThriftClassLoaderTest.php b/lib/php/test/Integration/Lib/ClassLoader/ThriftClassLoaderTest.php new file mode 100644 index 00000000000..a43f5c68685 --- /dev/null +++ b/lib/php/test/Integration/Lib/ClassLoader/ThriftClassLoaderTest.php @@ -0,0 +1,139 @@ +getFunctionMock('Thrift\ClassLoader', 'apcu_fetch') + ->expects($useApcu ? $this->any() : $this->never()) + ->with($apcuPrefix . $class) + ->willReturn(false); + + $this->getFunctionMock('Thrift\ClassLoader', 'apcu_store') + ->expects($useApcu ? $this->any() : $this->never()) + ->with($apcuPrefix . $class, $this->anything()) + ->willReturn(true); + + $loader = new ThriftClassLoader($useApcu, $apcuPrefix); + foreach ($definitions as $namespace => $paths) { + $loader->registerDefinition($namespace, $paths); + } + $loader->register(); + + $loader->loadClass($class); + if ($checkInterfaceExist) { + $this->assertTrue(interface_exists($class, false), "->loadClass() loads '$class'"); + } else { + $this->assertTrue(class_exists($class, false), "->loadClass() loads '$class'"); + } + } + + public function registerDefinitionDataProvider() + { + yield 'loadType' => [ + 'definitions' => [ + 'Classmap' => __DIR__ . '/../../../Resources/packages/phpcm', + ], + 'class' => 'Classmap\ThriftTest\Xtruct', + ]; + yield 'loadInterface' => [ + 'definitions' => [ + 'Classmap' => __DIR__ . '/../../../Resources/packages/phpcm', + ], + 'class' => '\Classmap\ThriftTest\ThriftTestIf', + 'checkInterfaceExist' => true, + ]; + yield 'loadClient' => [ + 'definitions' => [ + 'Classmap' => __DIR__ . '/../../../Resources/packages/phpcm', + ], + 'class' => '\Classmap\ThriftTest\ThriftTestClient', + ]; + yield 'loadProcessor' => [ + 'definitions' => [ + 'Classmap' => __DIR__ . '/../../../Resources/packages/phpcm', + ], + 'class' => '\Classmap\ThriftTest\ThriftTestProcessor', + ]; + yield 'loadRest' => [ + 'definitions' => [ + 'Classmap' => __DIR__ . '/../../../Resources/packages/phpcm', + ], + 'class' => '\Classmap\ThriftTest\ThriftTestRest', + ]; + yield 'load_args' => [ + 'definitions' => [ + 'Classmap' => __DIR__ . '/../../../Resources/packages/phpcm', + ], + 'class' => '\Classmap\ThriftTest\ThriftTest_testVoid_args', + ]; + yield 'load_result' => [ + 'definitions' => [ + 'Classmap' => __DIR__ . '/../../../Resources/packages/phpcm', + ], + 'class' => '\Classmap\ThriftTest\ThriftTest_testVoid_result', + ]; + yield 'pathAsArray' => [ + 'definitions' => [ + 'Classmap' => [__DIR__ . '/../../../Resources/packages/phpcm'], + ], + 'class' => 'Classmap\ThriftTest\Xtruct', + ]; + yield 'severalDefinitions' => [ + 'definitions' => [ + 'Classmap\ThriftTest' => [__DIR__ . '/../../../Resources/packages/phpcm'], + 'Classmap\TestValidators' => [__DIR__ . '/../../../Resources/packages/phpcm'], + ], + 'class' => '\Classmap\TestValidators\TestServiceClient', + ]; + yield 'useApcu' => [ + 'definitions' => [ + 'Classmap\ThriftTest' => [__DIR__ . '/../../../Resources/packages/phpcm'], + 'Classmap\TestValidators' => [__DIR__ . '/../../../Resources/packages/phpcm'], + ], + 'class' => '\Classmap\TestValidators\TestServiceClient', + 'checkInterfaceExist' => false, + 'useApcu' => true, + 'apcuPrefix' => 'APCU_PREFIX', + ]; + } +} diff --git a/lib/php/test/Integration/Lib/Protocol/TJSONProtocolTest.php b/lib/php/test/Integration/Lib/Protocol/TJSONProtocolTest.php new file mode 100644 index 00000000000..515cbdb3419 --- /dev/null +++ b/lib/php/test/Integration/Lib/Protocol/TJSONProtocolTest.php @@ -0,0 +1,646 @@ +transport = new TMemoryBuffer(); + $this->protocol = new TJSONProtocol($this->transport); + $this->transport->open(); + } + + public function testMessageReadWrite() + { + $input = new TJSONProtocol(new TMemoryBuffer('[1,"testString",1,0,{"0":{"str":"successResponse"}}]')); + $service = new \Basic\ThriftTest\ThriftTestClient($input, $this->protocol); + $result = $service->testString('test'); + $this->assertSame('successResponse', $result); + } + + /** + * @dataProvider writeDataProvider + */ + public function testWrite( + $argsClassName, + $argsValues, + $expected + ) { + $args = new $argsClassName($argsValues); + $args->write($this->protocol); + + $actual = $this->transport->read(self::BUFFER_SIZE); + + $this->assertEquals($expected, $actual); + } + + public function writeDataProvider() + { + if (!is_dir(__DIR__ . '/../../../Resources/packages/php')) { + throw new \RuntimeException( + 'Before running Integration test suite, you must run the Thrift compiler against the ThriftTest.thrift file in the ./Resources directory.' + ); + } + + yield 'void' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testVoid_args::class, + 'argsValues' => [], + 'expected' => '{}', + ]; + yield 'bool true' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testBool_args::class, + 'argsValues' => [ + 'thing' => true, + ], + 'expected' => '{"1":{"tf":1}}', + ]; + yield 'bool false' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testBool_args::class, + 'argsValues' => [ + 'thing' => false, + ], + 'expected' => '{"1":{"tf":0}}', + ]; + yield 'string1' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testString_args::class, + 'argsValues' => [ + 'thing' => "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語", + ], + 'expected' => '{"1":{"str":"Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ \/ ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe\'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски \/ Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча\/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語"}}', + ]; + yield 'string2' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testString_args::class, + 'argsValues' => [ + 'thing' => "quote: \\\" backslash:" . + " forwardslash-escaped: \\/ " . + " backspace: \b formfeed: \f newline: \n return: \r tab: " . + " now-all-of-them-together: \"\\\/\b\n\r\t" . + " now-a-bunch-of-junk: !@#\$%&()(&%$#{}{}<><><", + ], + 'expected' => '{"1":{"str":"quote: \\\\\" backslash: forwardslash-escaped: \\\\\/ backspace: \\\\b formfeed: \f newline: \n return: \r tab: now-all-of-them-together: \"\\\\\\\\\/\\\\b\n\r\t now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><"}}', + ]; + yield 'string3' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testString_args::class, + 'argsValues' => [ + 'thing' => "string that ends in double-backslash \\\\", + ], + 'expected' => '{"1":{"str":"string that ends in double-backslash \\\\\\\\"}}', + ]; + yield 'string4 testUnicodeStringWithNonBMP' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testString_args::class, + 'argsValues' => [ + 'thing' => "สวัสดี/𝒯", + ], + 'expected' => '{"1":{"str":"สวัสดี\/𝒯"}}', + ]; + yield 'double' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testDouble_args::class, + 'argsValues' => [ + 'thing' => 3.1415926535898, + ], + 'expected' => '{"1":{"dbl":3.1415926535898}}', + ]; + #TODO Should be fixed in future + yield 'double Nan' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testDouble_args::class, + 'argsValues' => [ + 'thing' => NAN, + ], + 'expected' => '{"1":{"dbl":}}', + ]; + #TODO Should be fixed in future + yield 'double Infinity' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testDouble_args::class, + 'argsValues' => [ + 'thing' => INF, + ], + 'expected' => '{"1":{"dbl":}}', + ]; + yield 'byte' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testByte_args::class, + 'argsValues' => [ + 'thing' => 0x01, + ], + 'expected' => '{"1":{"i8":1}}', + ]; + yield 'i32' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testI32_args::class, + 'argsValues' => [ + 'thing' => pow(2, 30), + ], + 'expected' => '{"1":{"i32":1073741824}}', + ]; + if (PHP_INT_SIZE == 8) { + yield 'i64_64Architecture' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testI64_args::class, + 'argsValues' => [ + 'thing' => pow(2, 60), + ], + 'expected' => '{"1":{"i64":' . pow(2, 60) . '}}', + ]; + yield 'struct_64Architecture' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testStruct_args::class, + 'argsValues' => [ + 'thing' => new Xtruct( + [ + 'string_thing' => 'worked', + 'byte_thing' => 0x01, + 'i32_thing' => pow(2, 30), + 'i64_thing' => pow(2, 60), + ] + ), + ], + 'expected' => '{"1":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":' . pow(2, 60) . '}}}}', + ]; + yield 'nest_64Architecture' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testNest_args::class, + 'argsValues' => [ + 'thing' => new Xtruct2( + [ + 'byte_thing' => 0x01, + 'struct_thing' => new Xtruct( + [ + 'string_thing' => 'worked', + 'byte_thing' => 0x01, + 'i32_thing' => pow(2, 30), + 'i64_thing' => pow(2, 60), + ] + ), + 'i32_thing' => pow(2, 15), + ] + ), + ], + 'expected' => '{"1":{"rec":{"1":{"i8":1},"2":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":' . pow(2, 60) . '}}},"3":{"i32":32768}}}}', + ]; + } else { + yield 'i64_32Architecture' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testI64_args::class, + 'argsValues' => [ + 'thing' => "1152921504606847000", + ], + 'expected' => '{"1":{"i64":1152921504606847000}}', + ]; + yield 'struct_32Architecture' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testStruct_args::class, + 'argsValues' => [ + 'thing' => new Xtruct( + [ + 'string_thing' => 'worked', + 'byte_thing' => 0x01, + 'i32_thing' => pow(2, 30), + 'i64_thing' => pow(2, 60), + ] + ), + ], + 'expected' => '{"1":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":1152921504606847000}}}}', + ]; + yield 'nest_32Architecture' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testNest_args::class, + 'argsValues' => [ + 'thing' => new Xtruct2( + [ + 'byte_thing' => 0x01, + 'struct_thing' => new Xtruct( + [ + 'string_thing' => 'worked', + 'byte_thing' => 0x01, + 'i32_thing' => pow(2, 30), + 'i64_thing' => '1152921504606847000', + ] + ), + 'i32_thing' => pow(2, 15), + ] + ), + ], + 'expected' => '{"1":{"rec":{"1":{"i8":1},"2":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":1152921504606847000}}},"3":{"i32":32768}}}}', + ]; + } + yield 'map' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testMap_args::class, + 'argsValues' => [ + 'thing' => [ + 7 => 77, + 8 => 88, + 9 => 99, + ], + ], + 'expected' => '{"1":{"map":["i32","i32",3,{"7":77,"8":88,"9":99}]}}', + ]; + yield 'stringMap' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testStringMap_args::class, + 'argsValues' => [ + 'thing' => [ + "a" => "123", + "a b" => "with spaces ", + "same" => "same", + "0" => "numeric key", + "longValue" => "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語", + "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語" => "long key", + ], + ], + 'expected' => '{"1":{"map":["str","str",6,{"a":"123","a b":"with spaces ","same":"same","0":"numeric key","longValue":"Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ \/ ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe\'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски \/ Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча\/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語","Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ \/ ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe\'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски \/ Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча\/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語":"long key"}]}}', + ]; + yield 'set' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testSet_args::class, + 'argsValues' => [ + 'thing' => [1 => true, 5 => true, 6 => true], + ], + 'expected' => '{"1":{"set":["i32",3,1,5,6]}}', + ]; + yield 'list' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testList_args::class, + 'argsValues' => [ + 'thing' => [1, 2, 3], + ], + 'expected' => '{"1":{"lst":["i32",3,1,2,3]}}', + ]; + yield 'enum' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testEnum_args::class, + 'argsValues' => [ + 'thing' => \Basic\ThriftTest\Numberz::SIX, + ], + 'expected' => '{"1":{"i32":6}}', + ]; + yield 'typedef' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testTypedef_args::class, + 'argsValues' => [ + 'thing' => 69, + ], + 'expected' => '{"1":{"i64":69}}', + ]; + } + + /** + * @dataProvider readDataProvider + */ + public function testRead( + $buffer, + $argsClassName, + $argsPropertyName, + $expectedValue, + $expectedResult + ): void { + $this->transport->write($buffer); + $args = new $argsClassName(); + $result = $args->read($this->protocol); + + $this->assertEquals($expectedResult, $result); + + if (is_null($argsPropertyName)) { + $this->assertNull($argsPropertyName); + } elseif (is_float($expectedValue) && is_nan($expectedValue)) { + $this->assertNan($args->{$argsPropertyName}); + } elseif (is_float($expectedValue) && is_infinite($expectedValue)) { + $this->assertEquals($expectedValue, $args->{$argsPropertyName}); + } else { + $this->assertEquals($expectedValue, $args->{$argsPropertyName}); + } + } + + public function readDataProvider() + { + yield 'void' => [ + 'buffer' => '{}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testVoid_args::class, + 'argsPropertyName' => null, + 'expectedValue' => null, + 'expectedResult' => 0, + ]; + yield 'bool true' => [ + 'buffer' => '{"1":{"tf":1}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testBool_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => true, + 'expectedResult' => 1, + ]; + yield 'bool false' => [ + 'buffer' => '{"1":{"tf":0}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testBool_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => false, + 'expectedResult' => 1, + ]; + yield 'string1' => [ + 'buffer' => '{"1":{"str":"Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ \/ ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe\'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски \/ Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча\/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語"}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testString_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語", + 'expectedResult' => 1, + ]; + yield 'string2' => [ + 'buffer' => '{"1":{"str":"quote: \\\\\" backslash: forwardslash-escaped: \\\\\/ backspace: \\\\b formfeed: \f newline: \n return: \r tab: now-all-of-them-together: \"\\\\\\\\\/\\\\b\n\r\t now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><"}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testString_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => "quote: \\\" backslash:" . + " forwardslash-escaped: \\/ " . + " backspace: \b formfeed: \f newline: \n return: \r tab: " . + " now-all-of-them-together: \"\\\/\b\n\r\t" . + " now-a-bunch-of-junk: !@#\$%&()(&%$#{}{}<><><", + 'expectedResult' => 1, + ]; + yield 'string3' => [ + 'buffer' => '{"1":{"str":"string that ends in double-backslash \\\\\\\\"}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testString_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => "string that ends in double-backslash \\\\", + 'expectedResult' => 1, + ]; + yield 'string4' => [ + 'buffer' => '{"1":{"str":"สวัสดี\/𝒯"}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testString_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => "สวัสดี/𝒯", + 'expectedResult' => 1, + ]; + yield 'double' => [ + 'buffer' => '{"1":{"dbl":3.1415926535898}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testDouble_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => 3.1415926535898, + 'expectedResult' => 1, + ]; + yield 'double Nan' => [ + 'buffer' => '{"1":{"dbl":"NaN"}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testDouble_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => NAN, + 'expectedResult' => 1, + ]; + yield 'double Infinity' => [ + 'buffer' => '{"1":{"dbl":"Infinity"}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testDouble_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => INF, + 'expectedResult' => 1, + ]; + yield 'byte' => [ + 'buffer' => '{"1":{"i8":1}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testByte_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => 0x01, + 'expectedResult' => 1, + ]; + yield 'i32' => [ + 'buffer' => '{"1":{"i32":1073741824}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testI32_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => pow(2, 30), + 'expectedResult' => 1, + ]; + if (PHP_INT_SIZE == 8) { + yield 'i64_64Architecture' => [ + 'buffer' => '{"1":{"i64":' . pow(2, 60) . '}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testI64_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => pow(2, 60), + 'expectedResult' => 1, + ]; + yield 'struct_64Architecture' => [ + 'buffer' => '{"1":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":' . pow(2, 60) . '}}}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testStruct_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => new Xtruct( + array( + 'string_thing' => 'worked', + 'byte_thing' => 0x01, + 'i32_thing' => pow(2, 30), + 'i64_thing' => pow(2, 60), + ) + ), + 'expectedResult' => 4, + ]; + yield 'nest_64Architecture' => [ + 'buffer' => '{"1":{"rec":{"1":{"i8":1},"2":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":' . pow(2, 60) . '}}},"3":{"i32":32768}}}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testNest_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => new Xtruct2( + array( + 'byte_thing' => 0x01, + 'struct_thing' => new Xtruct( + array( + 'string_thing' => 'worked', + 'byte_thing' => 0x01, + 'i32_thing' => pow(2, 30), + 'i64_thing' => pow(2, 60), + ) + ), + 'i32_thing' => pow(2, 15) + ) + ), + 'expectedResult' => 6, + ]; + } else { + yield 'i64_32Architecture' => [ + 'buffer' => '{"1":{"i64":1152921504606847000}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testI64_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => "1152921504606847000", + 'expectedResult' => 1, + ]; + yield 'struct_32Architecture' => [ + 'buffer' => '{"1":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":1152921504606847000}}}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testStruct_args::class, + 'expectedValue' => new Xtruct( + array( + 'string_thing' => 'worked', + 'byte_thing' => 0x01, + 'i32_thing' => pow(2, 30), + 'i64_thing' => "1152921504606847000", + ) + ), + 'expectedResult' => 4, + ]; + yield 'nest_32Architecture' => [ + 'buffer' => '{"1":{"rec":{"1":{"i8":1},"2":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":1152921504606847000}}},"3":{"i32":32768}}}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testNest_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => new Xtruct2( + array( + 'byte_thing' => 0x01, + 'struct_thing' => new Xtruct( + array( + 'string_thing' => 'worked', + 'byte_thing' => 0x01, + 'i32_thing' => pow(2, 30), + 'i64_thing' => "1152921504606847000", + ) + ), + 'i32_thing' => pow(2, 15) + ) + ), + 'expectedResult' => 6, + ]; + } + yield 'map' => [ + 'buffer' => '{"1":{"map":["i32","i32",3,{"7":77,"8":88,"9":99}]}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testMap_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => [ + 7 => 77, + 8 => 88, + 9 => 99 + ], + 'expectedResult' => 6, + ]; + yield 'stringMap' => [ + 'buffer' => '{"1":{"map":["str","str",6,{"a":"123","a b":"with spaces ","same":"same","0":"numeric key","longValue":"Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e","Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e":"long key"}]}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testStringMap_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => [ + "a" => "123", + "a b" => "with spaces ", + "same" => "same", + "0" => "numeric key", + "longValue" => "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語", + "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語" => "long key" + ], + 'expectedResult' => 12, + ]; + yield 'set' => [ + 'buffer' => '{"1":{"set":["i32",3,1,5,6]}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testSet_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => [1 => true, 5 => true, 6 => true], + 'expectedResult' => 4, + ]; + yield 'list' => [ + 'buffer' => '{"1":{"lst":["i32",3,1,2,3]}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testList_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => [1, 2, 3], + 'expectedResult' => 4, + ]; + yield 'enum' => [ + 'buffer' => '{"1":{"i32":6}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testEnum_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => Numberz::SIX, + 'expectedResult' => 1, + ]; + yield 'typedef' => [ + 'buffer' => '{"1":{"i64":69}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testTypedef_args::class, + 'argsPropertyName' => 'thing', + 'expectedValue' => 69, + 'expectedResult' => 1, + ]; + yield 'mapmap' => [ + 'buffer' => '{"0":{"map":["i32","map",2,{"4":["i32","i32",4,{"1":1,"2":2,"3":3,"4":4}],"-4":["i32","i32",4,{"-4":-4,"-3":-3,"-2":-2,"-1":-1}]}]}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testMapMap_result::class, + 'argsPropertyName' => 'success', + 'expectedValue' => [ + 4 => [ + 1 => 1, + 2 => 2, + 3 => 3, + 4 => 4, + ], + -4 => [ + -4 => -4, + -3 => -3, + -2 => -2, + -1 => -1 + ] + ], + 'expectedResult' => 18, + ]; + + $xtruct1 = new Xtruct( + [ + 'string_thing' => 'Goodbye4', + 'byte_thing' => 4, + 'i32_thing' => 4, + 'i64_thing' => 4, + ] + ); + + $xtruct2 = new Xtruct( + [ + 'string_thing' => 'Hello2', + 'byte_thing' => 2, + 'i32_thing' => 2, + 'i64_thing' => 2, + ] + ); + + $userMap = [Numberz::FIVE => 5, Numberz::EIGHT => 8]; + + $insanity2 = new Insanity( + [ + 'userMap' => $userMap, + 'xtructs' => [$xtruct1, $xtruct2], + ] + ); + + $insanity3 = $insanity2; + + $insanity6 = + new Insanity( + [ + 'userMap' => null, + 'xtructs' => null, + ] + ); + yield 'insanity' => [ + 'buffer' => '{"0":{"map":["i64","map",2,{"1":["i32","rec",2,{"2":{"1":{"map":["i32","i64",2,{"5":5,"8":8}]},"2":{"lst":["rec",2,{"1":{"str":"Goodbye4"},"4":{"i8":4},"9":{"i32":4},"11":{"i64":4}},{"1":{"str":"Hello2"},"4":{"i8":2},"9":{"i32":2},"11":{"i64":2}}]}},"3":{"1":{"map":["i32","i64",2,{"5":5,"8":8}]},"2":{"lst":["rec",2,{"1":{"str":"Goodbye4"},"4":{"i8":4},"9":{"i32":4},"11":{"i64":4}},{"1":{"str":"Hello2"},"4":{"i8":2},"9":{"i32":2},"11":{"i64":2}}]}}}],"2":["i32","rec",1,{"6":{}}]}]}}', + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testInsanity_result::class, + 'argsPropertyName' => 'success', + 'expectedValue' => [ + "1" => [ + Numberz::TWO => $insanity2, + Numberz::THREE => $insanity3, + ], + "2" => [ + Numberz::SIX => $insanity6, + ], + ], + 'expectedResult' => 31, + ]; + } +} diff --git a/lib/php/test/Integration/Lib/Protocol/TSimpleJSONProtocolTest.php b/lib/php/test/Integration/Lib/Protocol/TSimpleJSONProtocolTest.php new file mode 100644 index 00000000000..e108ffcb7f5 --- /dev/null +++ b/lib/php/test/Integration/Lib/Protocol/TSimpleJSONProtocolTest.php @@ -0,0 +1,319 @@ +transport = new TMemoryBuffer(); + $this->protocol = new TSimpleJSONProtocol($this->transport); + $this->transport->open(); + } + + public function testMessageWrite() + { + $input = new TJSONProtocol(new TMemoryBuffer('[1,"testString",1,0,{"0":{"str":"successResponse"}}]')); + $service = new \Basic\ThriftTest\ThriftTestClient($input, $this->protocol); + $result = $service->testString('test'); + $this->assertSame('successResponse', $result); + $this->assertSame('["testString",1,0,{"thing":"test"}]', $this->protocol->getTransport()->getBuffer()); + } + + /** + * @dataProvider writeDataProvider + */ + public function testWrite( + $argsClassName, + $argsValues, + $expected + ) { + $args = new $argsClassName($argsValues); + $args->write($this->protocol); + + $actual = $this->transport->read(self::BUFFER_SIZE); + + $this->assertEquals($expected, $actual); + } + + public function writeDataProvider() + { + if (!is_dir(__DIR__ . '/../../../Resources/packages/php')) { + throw new \RuntimeException( + 'Before running Integration test suite, you must run the Thrift compiler against the ThriftTest.thrift file in the ./Resources directory.' + ); + } + + yield 'void' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testVoid_args::class, + 'argsValues' => [], + 'expected' => '{}', + ]; + yield 'bool true' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testBool_args::class, + 'argsValues' => [ + 'thing' => true, + ], + 'expected' => '{"thing":1}', + ]; + yield 'bool false' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testBool_args::class, + 'argsValues' => [ + 'thing' => false, + ], + 'expected' => '{"thing":0}', + ]; + yield 'string1' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testString_args::class, + 'argsValues' => [ + 'thing' => "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語", + ], + 'expected' => '{"thing":"Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e"}', + ]; + yield 'string2' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testString_args::class, + 'argsValues' => [ + 'thing' => "quote: \\\" backslash:" . + " forwardslash-escaped: \\/ " . + " backspace: \b formfeed: \f newline: \n return: \r tab: " . + " now-all-of-them-together: \"\\\/\b\n\r\t" . + " now-a-bunch-of-junk: !@#\$%&()(&%$#{}{}<><><", + ], + 'expected' => '{"thing":"quote: \\\\\" backslash: forwardslash-escaped: \\\\\/ backspace: \\\\b formfeed: \f newline: \n return: \r tab: now-all-of-them-together: \"\\\\\\\\\/\\\\b\n\r\t now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><"}', + ]; + + yield 'string3' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testString_args::class, + 'argsValues' => [ + 'thing' => "string that ends in double-backslash \\\\", + ], + 'expected' => '{"thing":"string that ends in double-backslash \\\\\\\\"}', + ]; + yield 'string4 testUnicodeStringWithNonBMP' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testString_args::class, + 'argsValues' => [ + 'thing' => "สวัสดี/𝒯", + ], + 'expected' => '{"thing":"\u0e2a\u0e27\u0e31\u0e2a\u0e14\u0e35\/\ud835\udcaf"}', + ]; + yield 'double' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testDouble_args::class, + 'argsValues' => [ + 'thing' => 3.1415926535898, + ], + 'expected' => '{"thing":3.1415926535898}', + ]; + #TODO Should be fixed in future + yield 'double Nan' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testDouble_args::class, + 'argsValues' => [ + 'thing' => NAN, + ], + 'expected' => '{"thing":}', + ]; + #TODO Should be fixed in future + yield 'double Infinity' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testDouble_args::class, + 'argsValues' => [ + 'thing' => INF, + ], + 'expected' => '{"thing":}', + ]; + yield 'byte' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testByte_args::class, + 'argsValues' => [ + 'thing' => 0x01, + ], + 'expected' => '{"thing":1}', + ]; + yield 'i32' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testI32_args::class, + 'argsValues' => [ + 'thing' => pow(2, 30), + ], + 'expected' => '{"thing":1073741824}', + ]; + if (PHP_INT_SIZE == 8) { + yield 'i64_64Architecture' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testI64_args::class, + 'argsValues' => [ + 'thing' => pow(2, 60), + ], + 'expected' => '{"thing":' . pow(2, 60) . '}', + ]; + yield 'struct_64Architecture' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testStruct_args::class, + 'argsValues' => [ + 'thing' => new Xtruct( + [ + 'string_thing' => 'worked', + 'byte_thing' => 0x01, + 'i32_thing' => pow(2, 30), + 'i64_thing' => pow(2, 60), + ] + ), + ], + 'expected' => '{"thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":' . pow(2, 60) . '}}', + ]; + yield 'nest_64Architecture' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testNest_args::class, + 'argsValues' => [ + 'thing' => new Xtruct2( + [ + 'byte_thing' => 0x01, + 'struct_thing' => new Xtruct( + [ + 'string_thing' => 'worked', + 'byte_thing' => 0x01, + 'i32_thing' => pow(2, 30), + 'i64_thing' => pow(2, 60), + ] + ), + 'i32_thing' => pow(2, 15), + ] + ), + ], + 'expected' => '{"thing":{"byte_thing":1,"struct_thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":' . pow(2, 60) . '},"i32_thing":32768}}', + ]; + } else { + yield 'i64_32Architecture' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testI64_args::class, + 'argsValues' => [ + 'thing' => "1152921504606847000", + ], + 'expected' => '{"thing":1152921504606847000}', + ]; + yield 'struct_32Architecture' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testStruct_args::class, + 'argsValues' => [ + 'thing' => new Xtruct( + [ + 'string_thing' => 'worked', + 'byte_thing' => 0x01, + 'i32_thing' => pow(2, 30), + 'i64_thing' => pow(2, 60), + ] + ), + ], + 'expected' => '{"thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":1152921504606847000}}', + ]; + yield 'nest_32Architecture' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testNest_args::class, + 'argsValues' => [ + 'thing' => new Xtruct2( + [ + 'byte_thing' => 0x01, + 'struct_thing' => new Xtruct( + [ + 'string_thing' => 'worked', + 'byte_thing' => 0x01, + 'i32_thing' => pow(2, 30), + 'i64_thing' => '1152921504606847000', + ] + ), + 'i32_thing' => pow(2, 15), + ] + ), + ], + 'expected' => '{"thing":{"byte_thing":1,"struct_thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":1152921504606847000},"i32_thing":32768}}', + ]; + } + yield 'map' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testMap_args::class, + 'argsValues' => [ + 'thing' => [ + 7 => 77, + 8 => 88, + 9 => 99, + ], + ], + 'expected' => '{"thing":{"7":77,"8":88,"9":99}}', + ]; + yield 'stringMap' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testStringMap_args::class, + 'argsValues' => [ + 'thing' => [ + "a" => "123", + "a b" => "with spaces ", + "same" => "same", + "0" => "numeric key", + "longValue" => "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語", + "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語" => "long key" + ], + ], + 'expected' => '{"thing":{"a":"123","a b":"with spaces ","same":"same","0":"numeric key","longValue":"Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e","Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e":"long key"}}', + ]; + yield 'set' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testSet_args::class, + 'argsValues' => [ + 'thing' => [1 => true, 5 => true, 6 => true], + ], + 'expected' => '{"thing":[1,5,6]}', + ]; + yield 'list' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testList_args::class, + 'argsValues' => [ + 'thing' => [1, 2, 3], + ], + 'expected' => '{"thing":[1,2,3]}', + ]; + yield 'enum' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testEnum_args::class, + 'argsValues' => [ + 'thing' => \Basic\ThriftTest\Numberz::SIX, + ], + 'expected' => '{"thing":6}', + ]; + yield 'typedef' => [ + 'argsClassName' => \Basic\ThriftTest\ThriftTest_testTypedef_args::class, + 'argsValues' => [ + 'thing' => 69, + ], + 'expected' => '{"thing":69}', + ]; + } +} diff --git a/lib/php/test/Unit/BinarySerializerTest.php b/lib/php/test/Integration/Lib/Serializer/BinarySerializerTest.php similarity index 66% rename from lib/php/test/Unit/BinarySerializerTest.php rename to lib/php/test/Integration/Lib/Serializer/BinarySerializerTest.php index 744ca7ad130..44eef937c51 100644 --- a/lib/php/test/Unit/BinarySerializerTest.php +++ b/lib/php/test/Integration/Lib/Serializer/BinarySerializerTest.php @@ -19,35 +19,26 @@ * under the License. */ -namespace Test\Thrift\Unit; +namespace Test\Thrift\Integration\Lib\Serializer; use PHPUnit\Framework\TestCase; -use Thrift\ClassLoader\ThriftClassLoader; use Thrift\Serializer\TBinarySerializer; /*** * This test suite depends on running the compiler against the ./Resources/ThriftTest.thrift file: - * lib/php/test$ ../../../compiler/cpp/thrift --gen php -r --out ./Resources/packages/php ./Resources/ThriftTest.thrift + * lib/php/test$ ../../../compiler/cpp/thrift --gen php:nsglobal="Basic" -r --out ./Resources/packages/php ./Resources/ThriftTest.thrift */ class BinarySerializerTest extends TestCase { - public function setUp(): void - { - $loader = new ThriftClassLoader(); - $loader->registerNamespace('ThriftTest', __DIR__ . '/../Resources/packages/php'); - $loader->registerDefinition('ThriftTest', __DIR__ . '/../Resources/packages/php'); - $loader->register(); - } - /** * We try to serialize and deserialize a random object to make sure no exceptions are thrown. * @see THRIFT-1579 */ public function testBinarySerializer() { - $struct = new \ThriftTest\Xtruct(array('string_thing' => 'abc')); - $serialized = TBinarySerializer::serialize($struct, 'ThriftTest\\Xtruct'); - $deserialized = TBinarySerializer::deserialize($serialized, 'ThriftTest\\Xtruct'); + $struct = new \Basic\ThriftTest\Xtruct(array('string_thing' => 'abc')); + $serialized = TBinarySerializer::serialize($struct, '\\Basic\\ThriftTest\\Xtruct'); + $deserialized = TBinarySerializer::deserialize($serialized, '\\Basic\\ThriftTest\\Xtruct'); $this->assertEquals($struct, $deserialized); } } diff --git a/lib/php/test/Unit/JsonSerializeTest.php b/lib/php/test/Integration/Lib/Serializer/JsonSerializeTest.php similarity index 71% rename from lib/php/test/Unit/JsonSerializeTest.php rename to lib/php/test/Integration/Lib/Serializer/JsonSerializeTest.php index 66e4d5e376f..d3fe3f78cc1 100644 --- a/lib/php/test/Unit/JsonSerializeTest.php +++ b/lib/php/test/Integration/Lib/Serializer/JsonSerializeTest.php @@ -19,7 +19,7 @@ * under the License. */ -namespace Test\Thrift\Unit; +namespace Test\Thrift\Integration\Lib\Serializer; use PHPUnit\Framework\TestCase; use stdClass; @@ -27,21 +27,13 @@ /*** * This test suite depends on running the compiler against the ./Resources/ThriftTest.thrift file: - * lib/php/test$ ../../../compiler/cpp/thrift --gen php:json -r --out ./Resources/packages/phpjs ./Resources/ThriftTest.thrift + * lib/php/test$ ../../../compiler/cpp/thrift --gen php:json,nsglobal="Json" -r --out ./Resources/packages/phpjs ./Resources/ThriftTest.thrift */ class JsonSerializeTest extends TestCase { - protected function setUp(): void - { - $loader = new ThriftClassLoader(); - $loader->registerNamespace('ThriftTest', __DIR__ . '/../Resources/packages/phpjs'); - $loader->registerDefinition('ThriftTest', __DIR__ . '/../Resources/packages/phpjs'); - $loader->register(); - } - public function testEmptyStruct() { - $empty = new \ThriftTest\EmptyStruct(array('non_existing_key' => 'bar')); + $empty = new \Json\ThriftTest\EmptyStruct(array('non_existing_key' => 'bar')); $this->assertEquals(new stdClass(), json_decode(json_encode($empty))); } @@ -51,7 +43,7 @@ public function testStringsAndInts() 'string_thing' => 'foo', 'i64_thing' => 1234567890, ); - $xtruct = new \ThriftTest\Xtruct($input); + $xtruct = new \Json\ThriftTest\Xtruct($input); // Xtruct's 'i32_thing' and 'byte_thing' fields should not be present here! $expected = new stdClass(); @@ -62,9 +54,9 @@ public function testStringsAndInts() public function testNestedStructs() { - $xtruct2 = new \ThriftTest\Xtruct2(array( + $xtruct2 = new \Json\ThriftTest\Xtruct2(array( 'byte_thing' => 42, - 'struct_thing' => new \ThriftTest\Xtruct(array( + 'struct_thing' => new \Json\ThriftTest\Xtruct(array( 'i32_thing' => 123456, )), )); @@ -79,8 +71,8 @@ public function testNestedStructs() public function testInsanity() { $xinput = array('string_thing' => 'foo'); - $xtruct = new \ThriftTest\Xtruct($xinput); - $insanity = new \ThriftTest\Insanity(array( + $xtruct = new \Json\ThriftTest\Xtruct($xinput); + $insanity = new \Json\ThriftTest\Insanity(array( 'xtructs' => array($xtruct, $xtruct, $xtruct) )); $expected = new stdClass(); @@ -90,8 +82,8 @@ public function testInsanity() public function testNestedLists() { - $bonk = new \ThriftTest\Bonk(array('message' => 'foo')); - $nested = new \ThriftTest\NestedListsBonk(array('bonk' => array(array(array($bonk))))); + $bonk = new \Json\ThriftTest\Bonk(array('message' => 'foo')); + $nested = new \Json\ThriftTest\NestedListsBonk(array('bonk' => array(array(array($bonk))))); $expected = new stdClass(); $expected->bonk = array(array(array((object)array('message' => 'foo')))); $this->assertEquals($expected, json_decode(json_encode($nested))); @@ -99,17 +91,17 @@ public function testNestedLists() public function testMaps() { - $intmap = new \ThriftTest\ThriftTest_testMap_args(['thing' => [0 => 'zero']]); - $emptymap = new \ThriftTest\ThriftTest_testMap_args([]); + $intmap = new \Json\ThriftTest\ThriftTest_testMap_args(['thing' => [0 => 'zero']]); + $emptymap = new \Json\ThriftTest\ThriftTest_testMap_args([]); $this->assertEquals('{"thing":{"0":"zero"}}', json_encode($intmap)); $this->assertEquals('{}', json_encode($emptymap)); } public function testScalarTypes() { - $b = new \ThriftTest\Bools(['im_true' => '1', 'im_false' => '0']); + $b = new \Json\ThriftTest\Bools(['im_true' => '1', 'im_false' => '0']); $this->assertEquals('{"im_true":true,"im_false":false}', json_encode($b)); - $s = new \ThriftTest\StructA(['s' => 42]); + $s = new \Json\ThriftTest\StructA(['s' => 42]); $this->assertEquals('{"s":"42"}', json_encode($s)); } } diff --git a/lib/php/test/Unit/ValidatorTestOop.php b/lib/php/test/Integration/ValidatorOopTest.php similarity index 59% rename from lib/php/test/Unit/ValidatorTestOop.php rename to lib/php/test/Integration/ValidatorOopTest.php index 95581825e0c..c3dce030a2c 100644 --- a/lib/php/test/Unit/ValidatorTestOop.php +++ b/lib/php/test/Integration/ValidatorOopTest.php @@ -19,23 +19,16 @@ * under the License. */ -namespace Test\Thrift\Unit; - -use Thrift\ClassLoader\ThriftClassLoader; +namespace Test\Thrift\Integration; /*** * This test suite depends on running the compiler against the ./Resources/ThriftTest.thrift file: - * lib/php/test$ ../../../compiler/cpp/thrift --gen php:validate,oop -r --out ./Resources/packages/phpvo ./Resources/ThriftTest.thrift + * lib/php/test$ ../../../compiler/cpp/thrift --gen php:validate,oop,nsglobal="ValidateOop" -r --out ./Resources/packages/phpvo ./Resources/ThriftTest.thrift */ -class ValidatorTestOop extends BaseValidatorTest +class ValidatorOopTest extends BaseValidatorTest { - public function setUp(): void + public function getNsGlobal() { - $loader = new ThriftClassLoader(); - $loader->registerNamespace('ThriftTest', __DIR__ . '/../Resources/packages/phpvo'); - $loader->registerDefinition('ThriftTest', __DIR__ . '/../Resources/packages/phpvo'); - $loader->registerNamespace('TestValidators', __DIR__ . '/../Resources/packages/phpvo'); - $loader->registerDefinition('TestValidators', __DIR__ . '/../Resources/packages/phpvo'); - $loader->register(); + return 'ValidateOop'; } } diff --git a/lib/php/test/Unit/ValidatorTest.php b/lib/php/test/Integration/ValidatorTest.php similarity index 62% rename from lib/php/test/Unit/ValidatorTest.php rename to lib/php/test/Integration/ValidatorTest.php index b125424c15e..0d6a697e4eb 100644 --- a/lib/php/test/Unit/ValidatorTest.php +++ b/lib/php/test/Integration/ValidatorTest.php @@ -19,23 +19,16 @@ * under the License. */ -namespace Test\Thrift\Unit; - -use Thrift\ClassLoader\ThriftClassLoader; +namespace Test\Thrift\Integration; /*** * This test suite depends on running the compiler against the ./Resources/ThriftTest.thrift file: - * lib/php/test$ ../../../compiler/cpp/thrift --gen php:validate -r --out ./Resources/packages/phpv ./Resources/ThriftTest.thrift + * lib/php/test$ ../../../compiler/cpp/thrift --gen php:validate,nsglobal="Validate" -r --out ./Resources/packages/phpv ./Resources/ThriftTest.thrift */ class ValidatorTest extends BaseValidatorTest { - public function setUp(): void + public function getNsGlobal() { - $loader = new ThriftClassLoader(); - $loader->registerNamespace('ThriftTest', __DIR__ . '/../Resources/packages/phpv'); - $loader->registerDefinition('ThriftTest', __DIR__ . '/../Resources/packages/phpv'); - $loader->registerNamespace('TestValidators', __DIR__ . '/../Resources/packages/phpv'); - $loader->registerDefinition('TestValidators', __DIR__ . '/../Resources/packages/phpv'); - $loader->register(); + return 'Validate'; } } diff --git a/lib/php/test/Makefile.am b/lib/php/test/Makefile.am index 1e534cad0f4..b6a53256e2b 100644 --- a/lib/php/test/Makefile.am +++ b/lib/php/test/Makefile.am @@ -25,11 +25,11 @@ stubs: Resources/ThriftTest.thrift mkdir -p ./Resources/packages/phpvo mkdir -p ./Resources/packages/phpjs mkdir -p ./Resources/packages/phpcm - $(THRIFT) --gen php -r --out ./Resources/packages/php Resources/ThriftTest.thrift - $(THRIFT) --gen php:validate -r --out ./Resources/packages/phpv Resources/ThriftTest.thrift - $(THRIFT) --gen php:validate,oop -r --out ./Resources/packages/phpvo Resources/ThriftTest.thrift - $(THRIFT) --gen php:json -r --out ./Resources/packages/phpjs Resources/ThriftTest.thrift - $(THRIFT) --gen php:classmap,server,rest -r --out ./Resources/packages/phpcm Resources/ThriftTest.thrift + $(THRIFT) --gen php:nsglobal="Basic" -r --out ./Resources/packages/php Resources/ThriftTest.thrift + $(THRIFT) --gen php:validate,nsglobal="Validate" -r --out ./Resources/packages/phpv Resources/ThriftTest.thrift + $(THRIFT) --gen php:validate,oop,nsglobal="ValidateOop" -r --out ./Resources/packages/phpvo Resources/ThriftTest.thrift + $(THRIFT) --gen php:json,nsglobal="Json" -r --out ./Resources/packages/phpjs Resources/ThriftTest.thrift + $(THRIFT) --gen php:classmap,server,rest,nsglobal="Classmap" -r --out ./Resources/packages/phpcm Resources/ThriftTest.thrift deps: $(top_srcdir)/composer.json composer install --working-dir=$(top_srcdir) diff --git a/lib/php/test/Unit/Lib/ClassLoader/ThriftClassLoaderTest.php b/lib/php/test/Unit/Lib/ClassLoader/ThriftClassLoaderTest.php index 46ed2ec69c0..d99edfa2e7b 100644 --- a/lib/php/test/Unit/Lib/ClassLoader/ThriftClassLoaderTest.php +++ b/lib/php/test/Unit/Lib/ClassLoader/ThriftClassLoaderTest.php @@ -25,10 +25,6 @@ use PHPUnit\Framework\TestCase; use Thrift\ClassLoader\ThriftClassLoader; -/*** - * This test depends on running the compiler against the ./Resources/ThriftTest.thrift file: - * lib/php/test$ ../../../compiler/cpp/thrift --gen php:classmap,server,rest -r --out ./Resources/packages/phpcm ./Resources/ThriftTest.thrift - */ class ThriftClassLoaderTest extends TestCase { use PHPMock; @@ -111,108 +107,4 @@ public function registerNamespaceDataProvider() 'apcuPrefix' => 'APCU_PREFIX', ]; } - - /** - * @dataProvider registerDefinitionDataProvider - */ - public function testRegisterDefinition( - $definitions, - $class, - $checkInterfaceExist = false, - $useApcu = false, - $apcuPrefix = null - ) { - $this->getFunctionMock('Thrift\ClassLoader', 'apcu_fetch') - ->expects($useApcu ? $this->once() : $this->never()) - ->with($apcuPrefix . $class) - ->willReturn(false); - - $this->getFunctionMock('Thrift\ClassLoader', 'apcu_store') - ->expects($useApcu ? $this->once() : $this->never()) - ->with($apcuPrefix . $class, $this->anything()) - ->willReturn(true); - - $loader = new ThriftClassLoader($useApcu, $apcuPrefix); - foreach ($definitions as $namespace => $paths) { - $loader->registerDefinition($namespace, $paths); - } - $loader->register(); - - $loader->loadClass($class); - if ($checkInterfaceExist) { - $this->assertTrue(interface_exists($class, false), "->loadClass() loads '$class'"); - } else { - $this->assertTrue(class_exists($class, false), "->loadClass() loads '$class'"); - } - } - - public function registerDefinitionDataProvider() - { - yield 'loadType' => [ - 'definitions' => [ - 'ThriftTest' => __DIR__ . '/../../../Resources/packages/phpcm', - ], - 'class' => 'ThriftTest\Xtruct', - ]; - yield 'loadInterface' => [ - 'definitions' => [ - 'ThriftTest' => __DIR__ . '/../../../Resources/packages/phpcm', - ], - 'class' => '\ThriftTest\ThriftTestIf', - 'checkInterfaceExist' => true, - ]; - yield 'loadClient' => [ - 'definitions' => [ - 'ThriftTest' => __DIR__ . '/../../../Resources/packages/phpcm', - ], - 'class' => '\ThriftTest\ThriftTestClient', - ]; - yield 'loadProcessor' => [ - 'definitions' => [ - 'ThriftTest' => __DIR__ . '/../../../Resources/packages/phpcm', - ], - 'class' => '\ThriftTest\ThriftTestProcessor', - ]; - yield 'loadRest' => [ - 'definitions' => [ - 'ThriftTest' => __DIR__ . '/../../../Resources/packages/phpcm', - ], - 'class' => '\ThriftTest\ThriftTestRest', - ]; - yield 'load_args' => [ - 'definitions' => [ - 'ThriftTest' => __DIR__ . '/../../../Resources/packages/phpcm', - ], - 'class' => '\ThriftTest\ThriftTest_testVoid_args', - ]; - yield 'load_result' => [ - 'definitions' => [ - 'ThriftTest' => __DIR__ . '/../../../Resources/packages/phpcm', - ], - 'class' => '\ThriftTest\ThriftTest_testVoid_result', - ]; - yield 'pathAsArray' => [ - 'definitions' => [ - 'ThriftTest' => [__DIR__ . '/../../../Resources/packages/phpcm'], - ], - 'class' => 'ThriftTest\Xtruct', - ]; - yield 'severalDefinitions' => [ - 'definitions' => [ - 'ThriftTest' => [__DIR__ . '/../../../Resources/packages/phpcm'], - 'TestValidators' => [__DIR__ . '/../../../Resources/packages/phpcm'], - ], - 'class' => '\TestValidators\TestServiceClient', - ]; - yield 'useApcu' => [ - 'definitions' => [ - 'ThriftTest' => [__DIR__ . '/../../../Resources/packages/phpcm'], - 'TestValidators' => [__DIR__ . '/../../../Resources/packages/phpcm'], - ], - 'class' => '\TestValidators\TestServiceClient', - 'checkInterfaceExist' => false, - 'useApcu' => true, - 'apcuPrefix' => 'APCU_PREFIX', - ]; - } } diff --git a/lib/php/test/Unit/Lib/Protocol/TBinaryProtocolAcceleratedTest.php b/lib/php/test/Unit/Lib/Protocol/TBinaryProtocolAcceleratedTest.php new file mode 100644 index 00000000000..4a82a5af040 --- /dev/null +++ b/lib/php/test/Unit/Lib/Protocol/TBinaryProtocolAcceleratedTest.php @@ -0,0 +1,73 @@ +assertInstanceOf($expectedTransport, $protocol->getTransport()); + } + + public function constructDataProvider() + { + yield 'not buffered transport' => [ + 'transport' => new TMemoryBuffer(), + 'expectedTransport' => TMemoryBuffer::class, + ]; + yield 'buffered transport' => [ + 'transport' => new TSocket(), + 'expectedTransport' => TBufferedTransport::class, + ]; + } + + /** + * @dataProvider strictParamsDataProvider + */ + public function testStrictParams($strictRead, $strictWrite) + { + $protocol = new TBinaryProtocolAccelerated(new TMemoryBuffer(), $strictRead, $strictWrite); + $this->assertEquals($strictRead, $protocol->isStrictRead()); + $this->assertEquals($strictWrite, $protocol->isStrictWrite()); + } + + public function strictParamsDataProvider() + { + yield 'strict read and write' => [true, true]; + yield 'not strict read and write' => [false, false]; + yield 'strict read and not strict write' => [true, false]; + yield 'not strict read and strict write' => [false, true]; + } +} diff --git a/lib/php/test/Unit/Lib/Protocol/TBinaryProtocolTest.php b/lib/php/test/Unit/Lib/Protocol/TBinaryProtocolTest.php new file mode 100644 index 00000000000..2648b556315 --- /dev/null +++ b/lib/php/test/Unit/Lib/Protocol/TBinaryProtocolTest.php @@ -0,0 +1,1009 @@ +createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, $strictWrite); + + $transport->expects($this->exactly(count($writeCallsParams))) + ->method('write') + ->withConsecutive(...$writeCallsParams) + ->willReturnOnConsecutiveCalls(...$writeCallsResults); + + $result = $protocol->writeMessageBegin($name, $type, $seqid); + $this->assertEquals($expectedResult, $result); + } + + public function writeMessageBeginDataProvider() + { + $type = TType::STRING; + $seqid = 555; + + yield 'strictWrite=true' => [ + 'strictWrite' => true, + 'name' => 'testName', + 'type' => $type, + 'seqid' => $seqid, + 'writeCallsParams' => [ + [pack('N', self::VERSION_1 | $type), 4], #writeI32 + [pack('N', strlen('testName')), 4], #writeStringLen + ['testName', 8], #writeString + [pack('N', $seqid), 4], #writeI32 + ], + 'writeCallsResults' => [ + 4, + 4, + 8, + 4, + ], + 'expectedResult' => 20, + ]; + + yield 'strictWrite=false' => [ + 'strictWrite' => false, + 'name' => 'testName', + 'type' => $type, + 'seqid' => $seqid, + 'writeCallsParams' => [ + [pack('N', strlen('testName')), 4], #writeStringLen + ['testName', 8], #writeString + [pack('c', $type), 1], #writeByte + [pack('N', $seqid), 4], #writeI32 + ], + 'writeCallsResults' => [ + 4, + 8, + 1, + 4, + ], + 'expectedResult' => 17, + ]; + } + + public function testWriteMessageEnd() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $this->assertEquals(0, $protocol->writeMessageEnd()); + } + + public function testWriteStructBegin() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $this->assertEquals(0, $protocol->writeStructBegin('testName')); + } + + public function testWriteStructEnd() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $this->assertEquals(0, $protocol->writeStructEnd()); + } + + public function testWriteFieldBegin() + { + $fieldName = 'testName'; + $fieldType = TType::STRING; + $fieldId = 555; + + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->exactly(2)) + ->method('write') + ->withConsecutive( + ...[ + [pack('c', $fieldType), 1], #writeByte + [pack('n', $fieldId), 2], #writeI16 + ] + )->willReturnOnConsecutiveCalls([1, 2]); + + $this->assertEquals(3, $protocol->writeFieldBegin($fieldName, $fieldType, $fieldId)); + } + + public function testWriteFieldEnd() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $this->assertEquals(0, $protocol->writeFieldEnd()); + } + + public function testWriteFieldStop() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->once()) + ->method('write') + ->with(pack('c', TType::STOP), 1) #writeByte + ->willReturn(1); + + $this->assertEquals(1, $protocol->writeFieldStop()); + } + + public function testWriteMapBegin() + { + $keyType = TType::I32; + $valType = TType::STRING; + $size = 99; + + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->exactly(3)) + ->method('write') + ->withConsecutive( + ...[ + [pack('c', $keyType), 1], #writeByte + [pack('c', $valType), 1], #writeByte + [pack('N', $size), 4], #writeI32 + ] + )->willReturnOnConsecutiveCalls([1, 1, 4]); + + $this->assertEquals(6, $protocol->writeMapBegin($keyType, $valType, $size)); + } + + public function testWriteMapEnd() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $this->assertEquals(0, $protocol->writeMapEnd()); + } + + public function testWriteListBegin() + { + $elemType = TType::I32; + $size = 99; + + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->exactly(2)) + ->method('write') + ->withConsecutive( + ...[ + [pack('c', $elemType), 1], #writeByte + [pack('N', $size), 4], #writeI32 + ] + )->willReturnOnConsecutiveCalls([1, 4]); + + $this->assertEquals(5, $protocol->writeListBegin($elemType, $size)); + } + + public function testWriteListEnd() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $this->assertEquals(0, $protocol->writeListEnd()); + } + + public function testWriteSetBegin() + { + $elemType = TType::I32; + $size = 99; + + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->exactly(2)) + ->method('write') + ->withConsecutive( + ...[ + [pack('c', $elemType), 1], #writeByte + [pack('N', $size), 4], #writeI32 + ] + )->willReturnOnConsecutiveCalls([1, 4]); + + $this->assertEquals(5, $protocol->writeSetBegin($elemType, $size)); + } + + public function testWriteSetEnd() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $this->assertEquals(0, $protocol->writeSetEnd()); + } + + public function testWriteBool() + { + $value = true; + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->once()) + ->method('write') + ->with(pack('c', (int)$value), 1) #writeByte + ->willReturn(1); + + $this->assertEquals(1, $protocol->writeBool($value)); + } + + public function testWriteByte() + { + $value = 1; + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->once()) + ->method('write') + ->with(pack('c', $value), 1) #writeByte + ->willReturn(1); + + $this->assertEquals(1, $protocol->writeByte($value)); + } + + public function testWriteI16() + { + $value = 1; + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->once()) + ->method('write') + ->with(pack('n', $value), 2) #writeI16 + ->willReturn(2); + + $this->assertEquals(2, $protocol->writeI16($value)); + } + + public function testWriteI32() + { + $value = 1; + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->once()) + ->method('write') + ->with(pack('N', $value), 4) #writeI32 + ->willReturn(4); + + $this->assertEquals(4, $protocol->writeI32($value)); + } + + public function testWriteI64For32BitArchitecture() + { + if (PHP_INT_SIZE !== 4) { + $this->markTestSkipped('Test is only for 32 bit architecture'); + } + $value = 1; + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $neg = $value < 0; + + if ($neg) { + $value *= -1; + } + + $hi = (int)($value / 4294967296); + $lo = (int)$value; + + if ($neg) { + $hi = ~$hi; + $lo = ~$lo; + if (($lo & (int)0xffffffff) == (int)0xffffffff) { + $lo = 0; + $hi++; + } else { + $lo++; + } + } + + $transport + ->expects($this->once()) + ->method('write') + ->with(pack('N2', $hi, $lo), 8) #writeI64 + ->willReturn(4); + + $this->assertEquals(8, $protocol->writeI64($value)); + } + + public function testWriteI64For64BitArchitecture() + { + if (PHP_INT_SIZE == 4) { + $this->markTestSkipped('Test is only for 64 bit architecture'); + } + $value = 1; + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $hi = $value >> 32; + $lo = $value & 0xFFFFFFFF; + + $transport + ->expects($this->once()) + ->method('write') + ->with(pack('N2', $hi, $lo), 8) #writeI64 + ->willReturn(8); + + $this->assertEquals(8, $protocol->writeI64($value)); + } + + public function testWriteDouble() + { + $value = 1; + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->once()) + ->method('write') + ->with(strrev(pack('d', $value)), 8) #writeDouble + ->willReturn(8); + + $this->assertEquals(8, $protocol->writeDouble($value)); + } + + public function testWriteString() + { + $value = 'string'; + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->exactly(2)) + ->method('write') + ->withConsecutive( + ...[ + [pack('N', strlen($value))], #writeI32, + [$value, strlen($value)], #write, + ] + )->willReturnOnConsecutiveCalls([4, 6]); + + $this->assertEquals(10, $protocol->writeString($value)); + } + + /** + * @dataProvider readMessageBeginDataProvider + */ + public function testReadMessageBegin( + $strictRead, + $readCallsParams, + $readCallsResults, + $expectedReadLengthResult, + $expectedName, + $expectedType, + $expectedSeqid, + $expectedException = null, + $expectedExceptionMessage = null, + $expectedExceptionCode = null + ) { + if ($expectedException) { + $this->expectException($expectedException); + $this->expectExceptionMessage($expectedExceptionMessage); + $this->expectExceptionCode($expectedExceptionCode); + } + + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, $strictRead, true); + + $transport->expects($this->exactly(count($readCallsParams))) + ->method('readAll') + ->withConsecutive(...$readCallsParams) + ->willReturnOnConsecutiveCalls(...$readCallsResults); + + $result = $protocol->readMessageBegin($name, $type, $seqid); + $this->assertEquals($expectedReadLengthResult, $result); + $this->assertEquals($expectedName, $name); + $this->assertEquals($expectedType, $type); + $this->assertEquals($expectedSeqid, $seqid); + } + + public function readMessageBeginDataProvider() + { + yield 'strictRead=true' => [ + 'strictRead' => true, + 'readCallsParams' => [ + [4], #readI32 + [4], #readStringLen + [8], #readString + [4], #readI32 + ], + 'readCallsResults' => [ + pack('N', 0x80010000 | TType::STRING), #version + pack('N', strlen('testName')), + 'testName', + pack('N', 555), + ], + 'expectedReadLengthResult' => 20, + 'expectedName' => 'testName', + 'expectedType' => TType::STRING, + 'expectedSeqid' => 555, + ]; + + yield 'incorrect version' => [ + 'strictRead' => true, + 'readCallsParams' => [ + [4], #readI32 + ], + 'readCallsResults' => [ + pack('N', 0x80000000 | TType::STRING), #version + ], + 'expectedReadLengthResult' => 4, + 'expectedName' => '', + 'expectedType' => 0, + 'expectedSeqid' => 0, + 'expectedException' => TProtocolException::class, + 'expectedExceptionMessage' => 'Bad version identifier: -2147483637', + 'expectedExceptionCode' => TProtocolException::BAD_VERSION, + ]; + + yield 'strictRead=false' => [ + 'strictRead' => false, + 'readCallsParams' => [ + [4], #readStringLen + [8], #readString + [1], #readByte + [4], #readI32 + ], + 'readCallsResults' => [ + pack('N', strlen('testName')), + 'testName', + pack('c', TType::STRING), + pack('N', 555), + ], + 'expectedReadLengthResult' => 17, + 'expectedName' => 'testName', + 'expectedType' => TType::STRING, + 'expectedSeqid' => 555, + ]; + + yield 'strictRead=true without version' => [ + 'strictRead' => true, + 'readCallsParams' => [ + [4], #readStringLen + ], + 'readCallsResults' => [ + pack('N', strlen('testName')), + ], + 'expectedReadLengthResult' => 17, + 'expectedName' => 'testName', + 'expectedType' => TType::STRING, + 'expectedSeqid' => 555, + 'expectedException' => TProtocolException::class, + 'expectedExceptionMessage' => 'No version identifier, old protocol client?', + 'expectedExceptionCode' => TProtocolException::BAD_VERSION, + ]; + } + + public function testReadMessageEnd() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $this->assertEquals(0, $protocol->readMessageEnd()); + } + + public function testReadStructBegin() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $this->assertEquals(0, $protocol->readStructBegin($name)); + $this->assertEquals('', $name); + } + + public function testReadStructEnd() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $this->assertEquals(0, $protocol->readStructEnd()); + } + + /** + * @dataProvider readFieldBeginDataProvider + */ + public function testReadFieldBegin( + $storedFieldType, + $readCallsParams, + $readCallsResults, + $expectedResult, + $expectedName, + $expectedFieldType, + $expectedFieldId + ) { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->exactly(count($readCallsParams))) + ->method('readAll') + ->withConsecutive(...$readCallsParams) + ->willReturnOnConsecutiveCalls(...$readCallsResults); + + $this->assertEquals($expectedResult, $protocol->readFieldBegin($name, $fieldType, $fieldId)); + $this->assertEquals($expectedName, $name); + $this->assertEquals($expectedFieldType, $fieldType); + $this->assertEquals($expectedFieldId, $fieldId); + } + + public function readFieldBeginDataProvider() + { + yield 'default' => [ + 'storedFieldType' => TType::STRING, + 'readCallsParams' => [ + [1], #readByte + [2], #readI16 + ], + 'readCallsResults' => [ + pack('c', TType::STRING), + pack('n', 555), + ], + 'expectedResult' => 3, + 'exprectedName' => '', + 'expectedFieldType' => TType::STRING, + 'expectedFieldId' => 555, + ]; + + yield 'stop field' => [ + 'storedFieldType' => TType::STOP, + 'readCallsParams' => [ + [1], #readByte + ], + 'readCallsResults' => [ + pack('c', TType::STOP), + ], + 'expectedResult' => 1, + 'exprectedName' => '', + 'expectedFieldType' => 0, + 'expectedFieldId' => 0, + ]; + } + + public function testReadFieldEnd() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $this->assertEquals(0, $protocol->readFieldEnd()); + } + + public function testReadMapBegin() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->exactly(3)) + ->method('readAll') + ->withConsecutive( + ...[ + [1], #readByte + [1], #readByte + [4], #readI32 + ] + )->willReturnOnConsecutiveCalls( + pack('c', TType::I32), + pack('c', TType::STRING), + pack('N', 555) + ); + + $this->assertEquals(6, $protocol->readMapBegin($keyType, $valType, $size)); + $this->assertEquals(TType::I32, $keyType); + $this->assertEquals(TType::STRING, $valType); + $this->assertEquals(555, $size); + } + + public function testReadMapEnd() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $this->assertEquals(0, $protocol->readMapEnd()); + } + + public function testReadListBegin() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->exactly(2)) + ->method('readAll') + ->withConsecutive( + ...[ + [1], #readByte + [4], #readI32 + ] + )->willReturnOnConsecutiveCalls( + pack('c', TType::I32), + pack('N', 555) + ); + + $this->assertEquals(5, $protocol->readListBegin($elemType, $size)); + $this->assertEquals(TType::I32, $elemType); + $this->assertEquals(555, $size); + } + + public function testReadListEnd() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $this->assertEquals(0, $protocol->readListEnd()); + } + + public function testReadSetBegin() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->exactly(2)) + ->method('readAll') + ->withConsecutive( + ...[ + [1], #readByte + [4], #readI32 + ] + )->willReturnOnConsecutiveCalls( + pack('c', TType::I32), + pack('N', 555) + ); + + $this->assertEquals(5, $protocol->readSetBegin($elemType, $size)); + $this->assertEquals(TType::I32, $elemType); + $this->assertEquals(555, $size); + } + + public function testReadSetEnd() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $this->assertEquals(0, $protocol->readSetEnd()); + } + + public function testReadBool() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->once()) + ->method('readAll') + ->with(1) #readByte + ->willReturn(pack('c', 1)); + + $this->assertEquals(1, $protocol->readBool($value)); + $this->assertTrue($value); + } + + public function testReadByte() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->once()) + ->method('readAll') + ->with(1) #readByte + ->willReturn(pack('c', 1)); + + $this->assertEquals(1, $protocol->readByte($value)); + $this->assertEquals(1, $value); + } + + /** + * @dataProvider readI16DataProvider + */ + public function testReadI16( + $storedValue, + $expectedValue + ) { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->once()) + ->method('readAll') + ->with(2) #readI16 + ->willReturn(pack('n', $storedValue)); + + $this->assertEquals(2, $protocol->readI16($value)); + $this->assertEquals($expectedValue, $value); + } + + public function readI16DataProvider() + { + yield 'positive' => [1, 1]; + yield 'negative' => [-1, -1]; + } + + /** + * @dataProvider readI16DataProvider + */ + public function testReadI32( + $storedValue, + $expectedValue + ) { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->once()) + ->method('readAll') + ->with(4) #readI32 + ->willReturn(pack('N', $storedValue)); + + $this->assertEquals(4, $protocol->readI32($value)); + $this->assertEquals($expectedValue, $value); + } + + public function readI32DataProvider() + { + yield 'positive' => [1, 1]; + yield 'negative' => [-1, -1]; + } + + /** + * @dataProvider readI64For32BitArchitectureDataProvider + */ + public function testReadI64For32BitArchitecture( + $storedValue, + $expectedValue + ) { + if (PHP_INT_SIZE !== 4) { + $this->markTestSkipped('Test is only for 32 bit architecture'); + } + + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $neg = $storedValue < 0; + + if ($neg) { + $storedValue *= -1; + } + + $hi = (int)($storedValue / 4294967296); + $lo = (int)$storedValue; + + if ($neg) { + $hi = ~$hi; + $lo = ~$lo; + if (($lo & (int)0xffffffff) == (int)0xffffffff) { + $lo = 0; + $hi++; + } else { + $lo++; + } + } + + $transport + ->expects($this->once()) + ->method('write') + ->with(pack('N2', $hi, $lo), 8) #writeI64 + ->willReturn(4); + + $this->assertEquals(8, $protocol->readI64($value)); + $this->assertEquals($expectedValue, $value); + } + + public function readI64For32BitArchitectureDataProvider() + { + $storedValueRepresent = function ($value) { + $neg = $value < 0; + + if ($neg) { + $value *= -1; + } + + $hi = (int)($value / 4294967296); + $lo = (int)$value; + + if ($neg) { + $hi = ~$hi; + $lo = ~$lo; + if (($lo & (int)0xffffffff) == (int)0xffffffff) { + $lo = 0; + $hi++; + } else { + $lo++; + } + } + + return pack('N2', $hi, $lo); + }; + + yield 'positive' => [ + 'storedValue' => $storedValueRepresent(1), + 'expectedValue' => 1, + ]; + + yield 'max' => [ + 'storedValue' => $storedValueRepresent(PHP_INT_MAX), + 'expectedValue' => PHP_INT_MAX, + ]; + + yield 'min' => [ + 'storedValue' => $storedValueRepresent(PHP_INT_MIN), + 'expectedValue' => PHP_INT_MIN, + ]; + + yield 'negative' => [ + 'storedValue' => $storedValueRepresent(-1), + 'expectedValue' => -1, + ]; + } + + /** + * @dataProvider readI64For64BitArchitectureDataProvider + */ + public function testReadI64For64BitArchitecture( + $storedValue, + $expectedValue + ) { + if (PHP_INT_SIZE == 4) { + $this->markTestSkipped('Test is only for 64 bit architecture'); + } + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->once()) + ->method('readAll') + ->with(8) #readI64 + ->willReturn($storedValue); + + $this->assertEquals(8, $protocol->readI64($value)); + $this->assertEquals($expectedValue, $value); + } + + public function readI64For64BitArchitectureDataProvider() + { + $storedValueRepresent = function ($value) { + $hi = $value >> 32; + $lo = $value & 0xFFFFFFFF; + + return pack('N2', $hi, $lo); + }; + + yield 'positive' => [ + 'storedValue' => $storedValueRepresent(1), + 'expectedValue' => 1, + ]; + + yield 'max' => [ + 'storedValue' => $storedValueRepresent(PHP_INT_MAX), + 'expectedValue' => PHP_INT_MAX, + ]; + + yield 'min' => [ + 'storedValue' => $storedValueRepresent(PHP_INT_MIN), + 'expectedValue' => PHP_INT_MIN, + ]; + + yield 'negative' => [ + 'storedValue' => $storedValueRepresent(-1), + 'expectedValue' => -1, + ]; + } + + public function testReadDouble() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->once()) + ->method('readAll') + ->with(8) #readDouble + ->willReturn(strrev(pack('d', 789))); + + $this->assertEquals(8, $protocol->readDouble($value)); + $this->assertEquals(789, $value); + } + + /** + * @dataProvider readStringDataProvider + */ + public function testReadString( + $readCallsParams, + $readCallsResults, + $expectedLength, + $expectedValue + ) { + $transport = $this->createMock(TTransport::class); + $protocol = new TBinaryProtocol($transport, false, false); + + $transport + ->expects($this->exactly(count($readCallsParams))) + ->method('readAll') + ->withConsecutive(...$readCallsParams) + ->willReturnOnConsecutiveCalls(...$readCallsResults); + + $this->assertEquals($expectedLength, $protocol->readString($value)); + $this->assertEquals($expectedValue, $value); + } + + public function readStringDataProvider() + { + $storedValue = ''; + yield 'empty' => [ + 'readCallsParams' => [ + [4] + ], + 'readCallsResults' => [ + pack('N', strlen($storedValue)) + ], + 'expectedLength' => 4, + 'expectedValue' => '', + ]; + + $storedValue = 'string'; + yield 'non-empty' => [ + 'readCallsParams' => [ + [4], + [strlen($storedValue)] + ], + 'readCallsResults' => [ + pack('N', strlen($storedValue)), + $storedValue + ], + 'expectedLength' => 10, + 'expectedValue' => 'string', + ]; + } +} diff --git a/lib/php/test/Unit/Lib/Protocol/TCompactProtocolTest.php b/lib/php/test/Unit/Lib/Protocol/TCompactProtocolTest.php new file mode 100644 index 00000000000..95f972cf268 --- /dev/null +++ b/lib/php/test/Unit/Lib/Protocol/TCompactProtocolTest.php @@ -0,0 +1,843 @@ +createMock(TTransport::class)); + $this->assertSame($expected, $protocol->toZigZag($n, $bits)); + } + + public function toZigZagDataProvider() + { + yield ['n' => 0, 'bits' => 16, 'expected' => 0]; + yield ['n' => -1, 'bits' => 16, 'expected' => 1]; + yield ['n' => 1, 'bits' => 16, 'expected' => 2]; + yield ['n' => -2, 'bits' => 16, 'expected' => 3]; + yield ['n' => 2, 'bits' => 16, 'expected' => 4]; + yield ['n' => -1, 'bits' => 32, 'expected' => 1]; + yield ['n' => 1, 'bits' => 32, 'expected' => 2]; + yield ['n' => -1, 'bits' => 64, 'expected' => 1]; + yield ['n' => 1, 'bits' => 64, 'expected' => 2]; + yield ['n' => -0x7fffffff, 'bits' => 64, 'expected' => 4294967293]; + yield ['n' => 0x7fffffff, 'bits' => 64, 'expected' => 4294967294]; + } + + /** + * @dataProvider fromZigZagDataProvider + */ + public function testFromZigZag( + $n, + $expected + ) { + $protocol = new TCompactProtocol($this->createMock(TTransport::class)); + $this->assertSame($expected, $protocol->fromZigZag($n)); + } + + public function fromZigZagDataProvider() + { + yield ['n' => 0, 'expected' => 0]; + yield ['n' => 1, 'expected' => -1]; + yield ['n' => 2, 'expected' => 1]; + yield ['n' => 3, 'expected' => -2]; + yield ['n' => 4, 'expected' => 2]; + yield ['n' => 4294967293, 'expected' => -0x7fffffff]; + yield ['n' => 4294967294, 'expected' => 0x7fffffff]; + } + + /** + * @dataProvider getVarintDataProvider + */ + public function testGetVarint( + $data, + $expected + ) { + $protocol = new TCompactProtocol($this->createMock(TTransport::class)); + $this->assertSame($expected, $protocol->getVarint($data)); + } + + public function getVarintDataProvider() + { + yield ['data' => 0, 'expected' => "\x00"]; + yield ['data' => 1, 'expected' => "\x01"]; + yield ['data' => 97, 'expected' => "a"]; + yield ['data' => 100, 'expected' => "d"]; + yield ['data' => 1000, 'expected' => "\xe8\x07"]; + } + + public function testWriteVarint() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $transport->expects($this->once()) + ->method('write') + ->with("\xe8\x07", 2); + + $protocol->writeVarint(1000); + } + + public function testReadVarint() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $transport->expects($this->exactly(2)) + ->method('readAll') + ->with(1) + ->willReturnOnConsecutiveCalls( + ...[ + "\xe8", + "\x07", + ] + ); + + $this->assertSame(2, $protocol->readVarint($result)); + $this->assertSame(1000, $result); + } + + public function testWriteMessageBegin() + { + $name = 'testName'; + $type = TType::STRING; + $seqid = 1; + + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $transport + ->expects($this->exactly(5)) + ->method('write') + ->withConsecutive( + ...[ + [pack('C', self::PROTOCOL_ID), 1], #protocal id + [pack('C', self::VERSION | ($type << TCompactProtocol::TYPE_SHIFT_AMOUNT)), 1], #version + ["\x01", 1], #seqid + ["\x08", 1], #field name length + ["testName", 8], #field name + ] + )->willReturnOnConsecutiveCalls( + 1, + 1, + 1, + 1, + 8 + ); + + $result = $protocol->writeMessageBegin($name, $type, $seqid); + $this->assertSame(12, $result); + + $ref = new \ReflectionClass($protocol); + $state = $ref->getProperty('state'); + $state->setAccessible(true); + $this->assertSame(self::STATE_VALUE_WRITE, $state->getValue($protocol)); + } + + public function testWriteMessageEnd() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $this->assertSame(0, $protocol->writeMessageEnd()); + $ref = new \ReflectionClass($protocol); + $state = $ref->getProperty('state'); + $state->setAccessible(true); + $this->assertSame(self::STATE_CLEAR, $state->getValue($protocol)); + } + + public function testWriteStruct() + { + $name = 'testName'; + + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + $ref = new \ReflectionClass($protocol); + $state = $ref->getProperty('state'); + $state->setAccessible(true); + $lastFid = $ref->getProperty('lastFid'); + $lastFid->setAccessible(true); + $structs = $ref->getProperty('structs'); + $structs->setAccessible(true); + + $this->assertSame(0, $protocol->writeStructBegin($name)); + $this->assertSame([[self::STATE_CLEAR, 0]], $structs->getValue($protocol)); + $this->assertSame(self::STATE_FIELD_WRITE, $state->getValue($protocol)); + $this->assertSame(0, $lastFid->getValue($protocol)); + + $this->assertSame(0, $protocol->writeStructBegin($name)); + $this->assertSame(self::STATE_FIELD_WRITE, $state->getValue($protocol)); + $this->assertSame(0, $lastFid->getValue($protocol)); + $this->assertSame([[self::STATE_CLEAR, 0], [self::STATE_FIELD_WRITE, 0]], $structs->getValue($protocol)); + + $this->assertSame(0, $protocol->writeStructEnd()); + $this->assertSame(self::STATE_FIELD_WRITE, $state->getValue($protocol)); + $this->assertSame(0, $lastFid->getValue($protocol)); + $this->assertSame([[self::STATE_CLEAR, 0]], $structs->getValue($protocol)); + + $this->assertSame(0, $protocol->writeStructEnd()); + $this->assertSame(self::STATE_CLEAR, $state->getValue($protocol)); + $this->assertSame(0, $lastFid->getValue($protocol)); + $this->assertSame([], $structs->getValue($protocol)); + } + + public function testWriteFieldStop() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $transport->expects($this->once()) + ->method('write') + ->with("\x00", 1); + + $this->assertSame(1, $protocol->writeFieldStop()); + } + + /** + * @dataProvider writeFieldHeaderDataProvider + */ + public function testWriteFieldHeader( + $type, + $fid, + $writeCallParams, + $writeCallResult, + $expectedResult + ) { + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $transport + ->expects($this->exactly(count($writeCallParams))) + ->method('write') + ->withConsecutive(...$writeCallParams) + ->willReturnOnConsecutiveCalls(...$writeCallResult); + + $this->assertSame($expectedResult, $protocol->writeFieldHeader($type, $fid)); + } + + public function writeFieldHeaderDataProvider() + { + yield 'bool' => [ + 'type' => TType::BOOL, + 'fid' => 1, + 'writeCallParams' => [ + ["\x12", 1], #writeUByte(pack('C', ($delta << 4) | $type)), + ], + 'writeCallResult' => [ + 1, + ], + 'expectedResult' => 1, + ]; + yield 'list' => [ + 'type' => TType::LST, + 'fid' => 16, + 'writeCallParams' => [ + ["\x0f", 1], #writeUByte(pack('C', ($delta << 4) | $type)), + [" ", 1], #writeI16($fid), + ], + 'writeCallResult' => [ + 1, + ], + 'expectedResult' => 2, + ]; + } + + /** + * @dataProvider writeFieldBeginDataProvider + */ + public function testWriteFieldBegin( + $fieldName, + $fieldType, + $fieldId, + $writeCallParams, + $writeCallResult, + $expectedState, + $expectedBoolFid, + $expectedLastFid, + $expectedResult + ) { + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $transport + ->expects($this->exactly(count($writeCallParams))) + ->method('write') + ->withConsecutive(...$writeCallParams) + ->willReturnOnConsecutiveCalls(...$writeCallResult); + + $this->assertSame($expectedResult, $protocol->writeFieldBegin($fieldName, $fieldType, $fieldId)); + + $ref = new \ReflectionClass($protocol); + $state = $ref->getProperty('state'); + $state->setAccessible(true); + $boolFid = $ref->getProperty('boolFid'); + $boolFid->setAccessible(true); + $lastFid = $ref->getProperty('lastFid'); + $lastFid->setAccessible(true); + $this->assertSame($expectedState, $state->getValue($protocol)); + $this->assertSame($expectedBoolFid, $boolFid->getValue($protocol)); + $this->assertSame($expectedLastFid, $lastFid->getValue($protocol)); + } + + public function writeFieldBeginDataProvider() + { + yield 'bool' => [ + 'fieldName' => 'testName', + 'fieldType' => TType::BOOL, + 'fieldId' => 1, + 'writeCallParams' => [], + 'writeCallResult' => [], + 'expectedState' => self::STATE_BOOL_WRITE, + 'expectedBoolFid' => 1, + 'expectedLastFid' => 0, + 'expectedResult' => 0, + ]; + yield 'list' => [ + 'fieldName' => 'testName', + 'fieldType' => TType::LST, + 'fieldId' => 1, + 'writeCallParams' => [ + ["\x19", 1], #writeUByte(pack('C', ($delta << 4) | $type)), + ], + 'writeCallResult' => [ + 1, + ], + 'expectedState' => self::STATE_VALUE_WRITE, + 'expectedBoolFid' => null, + 'expectedLastFid' => 1, + 'expectedResult' => 1, + ]; + } + + public function testWriteFieldEnd() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $this->assertSame(0, $protocol->writeFieldEnd()); + + $ref = new \ReflectionClass($protocol); + $state = $ref->getProperty('state'); + $state->setAccessible(true); + $this->assertSame(self::STATE_FIELD_WRITE, $state->getValue($protocol)); + } + + /** + * @dataProvider writeCollectionDataProvider + */ + public function testWriteCollection( + $etype, + $size, + $writeCallParams, + $writeCallResult, + $expectedState, + $expectedContainers, + $expectedResult + ) { + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $transport + ->expects($this->exactly(count($writeCallParams))) + ->method('write') + ->withConsecutive(...$writeCallParams) + ->willReturnOnConsecutiveCalls(...$writeCallResult); + + $this->assertSame($expectedResult, $protocol->writeCollectionBegin($etype, $size)); + + $ref = new \ReflectionClass($protocol); + $state = $ref->getProperty('state'); + $state->setAccessible(true); + $containers = $ref->getProperty('containers'); + $containers->setAccessible(true); + $this->assertSame($expectedState, $state->getValue($protocol)); + $this->assertSame($expectedContainers, $containers->getValue($protocol)); + + $this->assertSame(0, $protocol->writeCollectionEnd()); + $this->assertSame(TCompactProtocol::STATE_CLEAR, $state->getValue($protocol)); + } + + public function writeCollectionDataProvider() + { + yield 'size < 14' => [ + 'etype' => TType::STRING, + 'size' => 1, + 'writeCallParams' => [ + ["\x18", 1], #writeUByte(pack('C', ($size << 4 | self::$ctypes[$etype])), + ], + 'writeCallResult' => [ + 1, + ], + 'expectedState' => self::STATE_CONTAINER_WRITE, + 'expectedContainers' => [ + 0 => 0, + ], + 'expectedResult' => 1, + ]; + yield 'size > 14' => [ + 'etype' => TType::STRING, + 'size' => 16, + 'writeCallParams' => [ + ["\xf8", 1], #writeUByte(pack('C', 0xf0 | self::$ctypes[$etype])), + ["\x10", 1], #writeVarint(16), + ], + 'writeCallResult' => [ + 1, + 1, + ], + 'expectedState' => self::STATE_CONTAINER_WRITE, + 'expectedContainers' => [ + 0 => 0, + ], + 'expectedResult' => 2, + ]; + } + + /** + * @dataProvider writeMapDataProvider + */ + public function testWriteMap( + $keyType, + $valType, + $size, + $writeCallParams, + $writeCallResult, + $expectedContainers, + $expectedResult + ) { + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $transport + ->expects($this->exactly(count($writeCallParams))) + ->method('write') + ->withConsecutive(...$writeCallParams) + ->willReturnOnConsecutiveCalls(...$writeCallResult); + + $this->assertSame($expectedResult, $protocol->writeMapBegin($keyType, $valType, $size)); + + $ref = new \ReflectionClass($protocol); + $containers = $ref->getProperty('containers'); + $containers->setAccessible(true); + $state = $ref->getProperty('state'); + $state->setAccessible(true); + $this->assertSame($expectedContainers, $containers->getValue($protocol)); + $this->assertSame(TCompactProtocol::STATE_CLEAR, $state->getValue($protocol)); + + $this->assertSame(0, $protocol->writeMapEnd()); + $this->assertSame(TCompactProtocol::STATE_CLEAR, $state->getValue($protocol)); + $this->assertSame([], $containers->getValue($protocol)); + } + + public function writeMapDataProvider() + { + yield 'size zero' => [ + 'keyType' => TType::STRING, + 'valType' => TType::STRING, + 'size' => 0, + 'writeCallParams' => [ + ["\x00", 1], #writeByte(0), + ], + 'writeCallResult' => [ + 1, + ], + 'expectedContainers' => [ + 0 => 0, + ], + 'expectedResult' => 1, + ]; + yield 'size non zero' => [ + 'keyType' => TType::STRING, + 'valType' => TType::STRING, + 'size' => 16, + 'writeCallParams' => [ + ["\x10", 1], #writeVarint(16), + ["\x88", 1], #writeUByte(pack('C', self::$ctypes[$key_type] << 4 | self::$ctypes[$val_type])), + ], + 'writeCallResult' => [ + 1, + 1, + ], + 'expectedContainers' => [ + 0 => 0, + ], + 'expectedResult' => 2, + ]; + } + + public function testWriteListBegin() + { + $protocol = $this->createPartialMock(TCompactProtocol::class, ['writeCollectionBegin']); + + $protocol->expects($this->once()) + ->method('writeCollectionBegin') + ->with(TType::STRING, 1) + ->willReturn(1); + + $this->assertSame(1, $protocol->writeListBegin(TType::STRING, 1)); + } + + public function testWriteListEnd() + { + $protocol = $this->createPartialMock(TCompactProtocol::class, ['writeCollectionEnd']); + + $protocol->expects($this->once()) + ->method('writeCollectionEnd') + ->willReturn(1); + + $this->assertSame(1, $protocol->writeListEnd()); + } + + public function testWriteSettBegin() + { + $protocol = $this->createPartialMock(TCompactProtocol::class, ['writeCollectionBegin']); + + $protocol->expects($this->once()) + ->method('writeCollectionBegin') + ->with(TType::STRING, 1) + ->willReturn(1); + + $this->assertSame(1, $protocol->writeSetBegin(TType::STRING, 1)); + } + + public function testWriteSetEnd() + { + $protocol = $this->createPartialMock(TCompactProtocol::class, ['writeCollectionEnd']); + + $protocol->expects($this->once()) + ->method('writeCollectionEnd') + ->willReturn(1); + + $this->assertSame(1, $protocol->writeSetEnd()); + } + + /** + * @dataProvider writeBinaryDataProvider + */ + public function testWriteBool( + $value, + $startState, + $writeCallParams, + $writeCallResult, + $expectedResult, + $expectedException, + $expectedExceptionMessage + ) { + if ($expectedException) { + $this->expectException($expectedException); + $this->expectExceptionMessage($expectedExceptionMessage); + } + + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + if (!is_null($startState)) { + $ref = new \ReflectionClass($protocol); + $state = $ref->getProperty('state'); + $state->setAccessible(true); + $state->setValue($protocol, $startState); + } + + $transport + ->expects($this->exactly(count($writeCallParams))) + ->method('write') + ->withConsecutive(...$writeCallParams) + ->willReturnOnConsecutiveCalls(...$writeCallResult); + + $this->assertSame($expectedResult, $protocol->writeBool($value)); + } + + public function writeBinaryDataProvider() + { + yield 'invalid state' => [ + 'value' => true, + 'startState' => null, + 'writeCallParams' => [], + 'writeCallResult' => [], + 'expectedResult' => 0, + 'expectedException' => TProtocolException::class, + 'expectedExceptionMessage' => 'Invalid state in compact protocol', + ]; + + yield 'true' => [ + 'value' => true, + 'startState' => TCompactProtocol::STATE_BOOL_WRITE, + 'writeCallParams' => [ + ["\x01", 1], #writeByte + ["\x00", 1], #writeI16 + ], + 'writeCallResult' => [ + 1, + 1, + ], + 'expectedResult' => 2, + 'expectedException' => null, + 'expectedExceptionMessage' => null, + ]; + + yield 'false' => [ + 'value' => false, + 'startState' => TCompactProtocol::STATE_BOOL_WRITE, + 'writeCallParams' => [ + ["\x02", 1], #writeByte + ["\x00", 1], #writeI16 + ], + 'writeCallResult' => [ + 1, + 1, + ], + 'expectedResult' => 2, + 'expectedException' => null, + 'expectedExceptionMessage' => null, + ]; + + yield 'container true' => [ + 'value' => true, + 'startState' => TCompactProtocol::STATE_CONTAINER_WRITE, + 'writeCallParams' => [ + ["\x01", 1], #writeByte + ], + 'writeCallResult' => [ + 1, + ], + 'expectedResult' => 1, + 'expectedException' => null, + 'expectedExceptionMessage' => null, + ]; + } + + /** + * @dataProvider writeByteDataProvider + */ + public function testWriteByte( + $value, + $expectedWriteCallParam + ) { + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $transport->expects($this->once()) + ->method('write') + ->with($expectedWriteCallParam, 1); + + $this->assertSame(1, $protocol->writeByte($value)); + } + + public function writeByteDataProvider() + { + yield 'signed' => [ + 'value' => -1, + 'expectedWriteCallParam' => "\xff", + ]; + yield 'unsigned' => [ + 'value' => 1, + 'expectedWriteCallParam' => "\x01", + ]; + yield 'lowercase' => [ + 'value' => 'a', + 'expectedWriteCallParam' => "\x00", + ]; + yield 'upercase' => [ + 'value' => 'A', + 'expectedWriteCallParam' => "\x00", + ]; + } + + /** + * @dataProvider writeUByteDataProvider + */ + public function testWriteUByte( + $value, + $expectedWriteCallParam + ) { + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $transport->expects($this->once()) + ->method('write') + ->with($expectedWriteCallParam, 1); + + $this->assertSame(1, $protocol->writeUByte($value)); + } + + public function writeUByteDataProvider() + { + yield 'signed' => [ + 'value' => -1, + 'expectedWriteCallParam' => "\xff", + ]; + yield 'unsigned' => [ + 'value' => 1, + 'expectedWriteCallParam' => "\x01", + ]; + yield 'lowercase' => [ + 'value' => 'a', + 'expectedWriteCallParam' => "\x00", + ]; + yield 'upercase' => [ + 'value' => 'A', + 'expectedWriteCallParam' => "\x00", + ]; + } + + public function testWriteI16() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $transport->expects($this->once()) + ->method('write') + ->with("\x00", 1); + + $this->assertSame(1, $protocol->writeI16(0)); + } + + public function testWriteI32() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $transport->expects($this->once()) + ->method('write') + ->with("\x00", 1); + + $this->assertSame(1, $protocol->writeI32(0)); + } + + public function testWriteDouble() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $transport->expects($this->once()) + ->method('write') + ->with(pack('d', 0), 8); + + $this->assertSame(8, $protocol->writeDouble(0)); + } + + public function testWriteString() + { + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $transport->expects($this->exactly(2)) + ->method('write') + ->withConsecutive( + ["\x04", 1], + ["test", 4] + ); + + $this->assertSame(5, $protocol->writeString('test')); + } + + /** + * @dataProvider writeI64DataProvider + */ + public function testWriteI64( + $value, + $expectedWriteCallParam, + $expectedResult + ) { + $transport = $this->createMock(TTransport::class); + $protocol = new TCompactProtocol($transport); + + $transport->expects($this->once()) + ->method('write') + ->with(...$expectedWriteCallParam); + + $this->assertSame($expectedResult, $protocol->writeI64($value)); + } + + public function writeI64DataProvider() + { + yield 'simple' => [ + 'value' => 0, + 'expectedWriteCallParam' => ["\x00", 1], + 'expectedResult' => 1, + ]; + yield 'negative' => [ + 'value' => -1, + 'expectedWriteCallParam' => ["\x01", 1], + 'expectedResult' => 1, + ]; + yield 'big' => [ + 'value' => 5000000000, + 'expectedWriteCallParam' => [hex2bin("80c8afa025"), 5], + 'expectedResult' => 5, + ]; + yield 'small' => [ + 'value' => -5000000000, + 'expectedWriteCallParam' => [hex2bin("ffc7afa025"), 5], + 'expectedResult' => 5, + ]; + yield 'max simple' => [ + 'value' => 0xffffffff, + 'expectedWriteCallParam' => [hex2bin("feffffff1f"), 5], + 'expectedResult' => 5, + ]; + } +} diff --git a/lib/php/test/Unit/Lib/Protocol/TMultiplexedProtocolTest.php b/lib/php/test/Unit/Lib/Protocol/TMultiplexedProtocolTest.php new file mode 100644 index 00000000000..970e3a946c6 --- /dev/null +++ b/lib/php/test/Unit/Lib/Protocol/TMultiplexedProtocolTest.php @@ -0,0 +1,85 @@ +createMock(TProtocol::class); + $multiplexedProtocol = new TMultiplexedProtocol($protocol, $serviceName); + + $protocol->expects($this->once()) + ->method('writeMessageBegin') + ->with($expectedName, $type, $seqid); + + $multiplexedProtocol->writeMessageBegin($name, $type, $seqid); + } + + public function writeMessageBeginDataProvider() + { + yield 'messageTypeCall' => [ + 'serviceName' => 'serviceName', + 'name' => 'testName', + 'type' => TMessageType::CALL, + 'seqid' => 1, + 'expectedName' => 'serviceName:testName' + ]; + yield 'messageTypeOneWay' => [ + 'serviceName' => 'serviceName', + 'name' => 'testName', + 'type' => TMessageType::ONEWAY, + 'seqid' => 1, + 'expectedName' => 'serviceName:testName' + ]; + yield 'messageTypeReply' => [ + 'serviceName' => 'serviceName', + 'name' => 'testName', + 'type' => TMessageType::REPLY, + 'seqid' => 1, + 'expectedName' => 'testName' + ]; + yield 'messageTypeException' => [ + 'serviceName' => 'serviceName', + 'name' => 'testName', + 'type' => TMessageType::EXCEPTION, + 'seqid' => 1, + 'expectedName' => 'testName' + ]; + + } +} diff --git a/lib/php/test/Unit/Lib/Protocol/TProtocolDecoratorTest.php b/lib/php/test/Unit/Lib/Protocol/TProtocolDecoratorTest.php new file mode 100644 index 00000000000..e5dbdb36b29 --- /dev/null +++ b/lib/php/test/Unit/Lib/Protocol/TProtocolDecoratorTest.php @@ -0,0 +1,96 @@ +createMock(TProtocol::class); + $decorator = new class ($concreteProtocol) extends TProtocolDecorator { + public function __construct(TProtocol $protocol) + { + parent::__construct($protocol); + } + }; + + $concreteProtocol->expects($this->once()) + ->method($methodName) + ->with(...$methodArguments); + + $decorator->$methodName(...$methodArguments); + } + + public function methodDecorationDataProvider() + { + yield 'writeMessageBegin' => ['writeMessageBegin', ['name', 'type', 'seqid']]; + yield 'writeMessageEnd' => ['writeMessageEnd', []]; + yield 'writeStructBegin' => ['writeStructBegin', ['name']]; + yield 'writeStructEnd' => ['writeStructEnd', []]; + yield 'writeFieldBegin' => ['writeFieldBegin', ['name', 'type', 'id']]; + yield 'writeFieldEnd' => ['writeFieldEnd', []]; + yield 'writeFieldStop' => ['writeFieldStop', []]; + yield 'writeMapBegin' => ['writeMapBegin', ['keyType', 'valType', 'size']]; + yield 'writeMapEnd' => ['writeMapEnd', []]; + yield 'writeListBegin' => ['writeListBegin', ['elemType', 'size']]; + yield 'writeListEnd' => ['writeListEnd', []]; + yield 'writeSetBegin' => ['writeSetBegin', ['elemType', 'size']]; + yield 'writeSetEnd' => ['writeSetEnd', []]; + yield 'writeBool' => ['writeBool', ['value']]; + yield 'writeByte' => ['writeByte', ['value']]; + yield 'writeI16' => ['writeI16', ['value']]; + yield 'writeI32' => ['writeI32', ['value']]; + yield 'writeI64' => ['writeI64', ['value']]; + yield 'writeDouble' => ['writeDouble', ['value']]; + yield 'writeString' => ['writeString', ['value']]; + yield 'readMessageBegin' => ['readMessageBegin', ['name', 'type', 'seqid']]; + yield 'readMessageEnd' => ['readMessageEnd', []]; + yield 'readStructBegin' => ['readStructBegin', ['name']]; + yield 'readStructEnd' => ['readStructEnd', []]; + yield 'readFieldBegin' => ['readFieldBegin', ['name', 'type', 'id']]; + yield 'readFieldEnd' => ['readFieldEnd', []]; + yield 'readMapBegin' => ['readMapBegin', ['keyType', 'valType', 'size']]; + yield 'readMapEnd' => ['readMapEnd', []]; + yield 'readListBegin' => ['readListBegin', ['elemType', 'size']]; + yield 'readListEnd' => ['readListEnd', []]; + yield 'readSetBegin' => ['readSetBegin', ['elemType', 'size']]; + yield 'readSetEnd' => ['readSetEnd', []]; + yield 'readBool' => ['readBool', ['value']]; + yield 'readByte' => ['readByte', ['value']]; + yield 'readI16' => ['readI16', ['value']]; + yield 'readI32' => ['readI32', ['value']]; + yield 'readI64' => ['readI64', ['value']]; + yield 'readDouble' => ['readDouble', ['value']]; + yield 'readString' => ['readString', ['value']]; + } +} diff --git a/lib/php/test/Unit/Lib/Protocol/TSimpleJSONProtocolTest.php b/lib/php/test/Unit/Lib/Protocol/TSimpleJSONProtocolTest.php new file mode 100644 index 00000000000..e4d005a45ae --- /dev/null +++ b/lib/php/test/Unit/Lib/Protocol/TSimpleJSONProtocolTest.php @@ -0,0 +1,133 @@ +expectException(TException::class); + $this->expectExceptionMessage("Not implemented"); + + $transport = $this->createMock(TTransport::class); + $protocol = new TSimpleJSONProtocol($transport); + $protocol->$methodName(...$methodArguments); + } + + public function readDataProvider() + { + yield 'readMessageBegin' => [ + 'methodName' => 'readMessageBegin', + 'methodArguments' => ['name', 'type', 'seqId'], + ]; + yield 'readMessageEnd' => [ + 'methodName' => 'readMessageEnd', + 'methodArguments' => [], + ]; + yield 'readStructBegin' => [ + 'methodName' => 'readStructBegin', + 'methodArguments' => ['name'], + ]; + yield 'readStructEnd' => [ + 'methodName' => 'readStructEnd', + 'methodArguments' => [], + ]; + yield 'readFieldBegin' => [ + 'methodName' => 'readFieldBegin', + 'methodArguments' => ['name', TType::STRING, 1], + ]; + yield 'readFieldEnd' => [ + 'methodName' => 'readFieldEnd', + 'methodArguments' => [], + ]; + yield 'readMapBegin' => [ + 'methodName' => 'readMapBegin', + 'methodArguments' => [TType::STRING, TType::STRING, 1], + ]; + yield 'readMapEnd' => [ + 'methodName' => 'readMapEnd', + 'methodArguments' => [], + ]; + yield 'readListBegin' => [ + 'methodName' => 'readListBegin', + 'methodArguments' => [TType::STRING, 1], + ]; + yield 'readListEnd' => [ + 'methodName' => 'readListEnd', + 'methodArguments' => [], + ]; + yield 'readSetBegin' => [ + 'methodName' => 'readSetBegin', + 'methodArguments' => [TType::STRING, 1], + ]; + yield 'readSetEnd' => [ + 'methodName' => 'readSetEnd', + 'methodArguments' => [], + ]; + yield 'readBool' => [ + 'methodName' => 'readBool', + 'methodArguments' => [true], + ]; + yield 'readByte' => [ + 'methodName' => 'readByte', + 'methodArguments' => [0x01], + ]; + yield 'readI16' => [ + 'methodName' => 'readI16', + 'methodArguments' => [1], + ]; + yield 'readI32' => [ + 'methodName' => 'readI32', + 'methodArguments' => [1], + ]; + yield 'readI64' => [ + 'methodName' => 'readI64', + 'methodArguments' => [1], + ]; + yield 'readDouble' => [ + 'methodName' => 'readDouble', + 'methodArguments' => [0.1], + ]; + yield 'readString' => [ + 'methodName' => 'readString', + 'methodArguments' => ['string'], + ]; + } +} diff --git a/lib/php/test/Unit/Lib/Serializer/TBinarySerializerTest.php b/lib/php/test/Unit/Lib/Serializer/TBinarySerializerTest.php new file mode 100644 index 00000000000..292f261892c --- /dev/null +++ b/lib/php/test/Unit/Lib/Serializer/TBinarySerializerTest.php @@ -0,0 +1,38 @@ +markTestIncomplete('Could not test static function which create instances during execution'); + } + + public function testDeserialize() + { + $this->markTestIncomplete('Could not test static function which create instances during execution'); + } +} diff --git a/lib/php/test/Unit/TJSONProtocolTest.php b/lib/php/test/Unit/TJSONProtocolTest.php deleted file mode 100644 index 9837803708b..00000000000 --- a/lib/php/test/Unit/TJSONProtocolTest.php +++ /dev/null @@ -1,514 +0,0 @@ -registerNamespace('ThriftTest', __DIR__ . '/../Resources/packages/php'); - $loader->registerDefinition('ThriftTest', __DIR__ . '/../Resources/packages/php'); - $loader->register(); - - Fixtures::populateTestArgs(); - TJSONProtocolFixtures::populateTestArgsJSON(); - } - - public function setUp(): void - { - $this->transport = new TMemoryBuffer(); - $this->protocol = new TJSONProtocol($this->transport); - $this->transport->open(); - } - - /** - * WRITE TESTS - */ - public function testVoidWrite() - { - $args = new \ThriftTest\ThriftTest_testVoid_args(); - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testVoid']; - - $this->assertEquals($expected, $actual); - } - - public function testString1Write() - { - $args = new \ThriftTest\ThriftTest_testString_args(); - $args->thing = Fixtures::$testArgs['testString1']; - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testString1']; - - $this->assertEquals($expected, $actual); - } - - public function testString2Write() - { - $args = new \ThriftTest\ThriftTest_testString_args(); - $args->thing = Fixtures::$testArgs['testString2']; - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testString2']; - - $this->assertEquals($expected, $actual); - } - - public function testDoubleWrite() - { - $args = new \ThriftTest\ThriftTest_testDouble_args(); - $args->thing = Fixtures::$testArgs['testDouble']; - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testDouble']; - - $this->assertEquals($expected, $actual); - } - - public function testByteWrite() - { - $args = new \ThriftTest\ThriftTest_testByte_args(); - $args->thing = Fixtures::$testArgs['testByte']; - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testByte']; - - $this->assertEquals($expected, $actual); - } - - public function testI32Write() - { - $args = new \ThriftTest\ThriftTest_testI32_args(); - $args->thing = Fixtures::$testArgs['testI32']; - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testI32']; - - $this->assertEquals($expected, $actual); - } - - public function testI64Write() - { - $args = new \ThriftTest\ThriftTest_testI64_args(); - $args->thing = Fixtures::$testArgs['testI64']; - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testI64']; - - $this->assertEquals($expected, $actual); - } - - public function testStructWrite() - { - $args = new \ThriftTest\ThriftTest_testStruct_args(); - $args->thing = Fixtures::$testArgs['testStruct']; - - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testStruct']; - - $this->assertEquals($expected, $actual); - } - - public function testNestWrite() - { - $args = new \ThriftTest\ThriftTest_testNest_args(); - $args->thing = Fixtures::$testArgs['testNest']; - - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testNest']; - - $this->assertEquals($expected, $actual); - } - - public function testMapWrite() - { - $args = new \ThriftTest\ThriftTest_testMap_args(); - $args->thing = Fixtures::$testArgs['testMap']; - - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testMap']; - - $this->assertEquals($expected, $actual); - } - - public function testStringMapWrite() - { - $args = new \ThriftTest\ThriftTest_testStringMap_args(); - $args->thing = Fixtures::$testArgs['testStringMap']; - - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testStringMap']; - - /* - * The $actual returns unescaped string. - * It is required to to decode then encode it again - * to get the expected escaped unicode. - */ - $this->assertEquals($expected, json_encode(json_decode($actual))); - } - - public function testSetWrite() - { - $args = new \ThriftTest\ThriftTest_testSet_args(); - $args->thing = Fixtures::$testArgs['testSet']; - - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testSet']; - - $this->assertEquals($expected, $actual); - } - - public function testListWrite() - { - $args = new \ThriftTest\ThriftTest_testList_args(); - $args->thing = Fixtures::$testArgs['testList']; - - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testList']; - - $this->assertEquals($expected, $actual); - } - - public function testEnumWrite() - { - $args = new \ThriftTest\ThriftTest_testEnum_args(); - $args->thing = Fixtures::$testArgs['testEnum']; - - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testEnum']; - - $this->assertEquals($expected, $actual); - } - - public function testTypedefWrite() - { - $args = new \ThriftTest\ThriftTest_testTypedef_args(); - $args->thing = Fixtures::$testArgs['testTypedef']; - - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testTypedef']; - - $this->assertEquals($expected, $actual); - } - - /** - * READ TESTS - */ - public function testVoidRead() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testVoid'] - ); - $args = new \ThriftTest\ThriftTest_testVoid_args(); - $result = $args->read($this->protocol); - - $this->assertEquals(0, $result); - } - - public function testString1Read() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testString1'] - ); - $args = new \ThriftTest\ThriftTest_testString_args(); - $args->read($this->protocol); - - $actual = $args->thing; - $expected = Fixtures::$testArgs['testString1']; - - $this->assertEquals($expected, $actual); - } - - public function testString2Read() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testString2'] - ); - $args = new \ThriftTest\ThriftTest_testString_args(); - $args->read($this->protocol); - - $actual = $args->thing; - $expected = Fixtures::$testArgs['testString2']; - - $this->assertEquals($expected, $actual); - } - - public function testString3Write() - { - $args = new \ThriftTest\ThriftTest_testString_args(); - $args->thing = Fixtures::$testArgs['testString3']; - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testString3']; - - $this->assertEquals($expected, $actual); - } - - public function testString4Write() - { - $args = new \ThriftTest\ThriftTest_testString_args(); - $args->thing = Fixtures::$testArgs['testUnicodeStringWithNonBMP']; - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TJSONProtocolFixtures::$testArgsJSON['testUnicodeStringWithNonBMP']; - - $this->assertEquals($expected, $actual); - } - - public function testDoubleRead() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testDouble'] - ); - $args = new \ThriftTest\ThriftTest_testDouble_args(); - $args->read($this->protocol); - - $actual = $args->thing; - $expected = Fixtures::$testArgs['testDouble']; - - $this->assertEquals($expected, $actual); - } - - public function testByteRead() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testByte'] - ); - $args = new \ThriftTest\ThriftTest_testByte_args(); - $args->read($this->protocol); - - $actual = $args->thing; - $expected = Fixtures::$testArgs['testByte']; - - $this->assertEquals($expected, $actual); - } - - public function testI32Read() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testI32'] - ); - $args = new \ThriftTest\ThriftTest_testI32_args(); - $args->read($this->protocol); - - $actual = $args->thing; - $expected = Fixtures::$testArgs['testI32']; - - $this->assertEquals($expected, $actual); - } - - public function testI64Read() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testI64'] - ); - $args = new \ThriftTest\ThriftTest_testI64_args(); - $args->read($this->protocol); - - $actual = $args->thing; - $expected = Fixtures::$testArgs['testI64']; - - $this->assertEquals($expected, $actual); - } - - public function testStructRead() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testStruct'] - ); - $args = new \ThriftTest\ThriftTest_testStruct_args(); - $args->read($this->protocol); - - $actual = $args->thing; - $expected = Fixtures::$testArgs['testStruct']; - - $this->assertEquals($expected, $actual); - } - - public function testNestRead() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testNest'] - ); - $args = new \ThriftTest\ThriftTest_testNest_args(); - $args->read($this->protocol); - - $actual = $args->thing; - $expected = Fixtures::$testArgs['testNest']; - - $this->assertEquals($expected, $actual); - } - - public function testMapRead() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testMap'] - ); - $args = new \ThriftTest\ThriftTest_testMap_args(); - $args->read($this->protocol); - - $actual = $args->thing; - $expected = Fixtures::$testArgs['testMap']; - - $this->assertEquals($expected, $actual); - } - - public function testStringMapRead() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testStringMap'] - ); - $args = new \ThriftTest\ThriftTest_testStringMap_args(); - $args->read($this->protocol); - - $actual = $args->thing; - $expected = Fixtures::$testArgs['testStringMap']; - - $this->assertEquals($expected, $actual); - } - - public function testSetRead() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testSet'] - ); - $args = new \ThriftTest\ThriftTest_testSet_args(); - $args->read($this->protocol); - - $actual = $args->thing; - $expected = Fixtures::$testArgs['testSet']; - - $this->assertEquals($expected, $actual); - } - - public function testListRead() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testList'] - ); - $args = new \ThriftTest\ThriftTest_testList_args(); - $args->read($this->protocol); - - $actual = $args->thing; - $expected = Fixtures::$testArgs['testList']; - - $this->assertEquals($expected, $actual); - } - - public function testEnumRead() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testEnum'] - ); - $args = new \ThriftTest\ThriftTest_testEnum_args(); - $args->read($this->protocol); - - $actual = $args->thing; - $expected = Fixtures::$testArgs['testEnum']; - - $this->assertEquals($expected, $actual); - } - - public function testTypedefRead() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testTypedef'] - ); - $args = new \ThriftTest\ThriftTest_testTypedef_args(); - $args->read($this->protocol); - - $actual = $args->thing; - $expected = Fixtures::$testArgs['testTypedef']; - - $this->assertEquals($expected, $actual); - } - - public function testMapMapRead() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testMapMap'] - ); - $result = new \ThriftTest\ThriftTest_testMapMap_result(); - $result->read($this->protocol); - - $actual = $result->success; - $expected = Fixtures::$testArgs['testMapMapExpectedResult']; - - $this->assertEquals($expected, $actual); - } - - public function testInsanityRead() - { - $this->transport->write( - TJSONProtocolFixtures::$testArgsJSON['testInsanity'] - ); - $result = new \ThriftTest\ThriftTest_testInsanity_result(); - $result->read($this->protocol); - - $actual = $result->success; - $expected = Fixtures::$testArgs['testInsanityExpectedResult']; - - $this->assertEquals($expected, $actual); - } -} diff --git a/lib/php/test/Unit/TSimpleJSONProtocolTest.php b/lib/php/test/Unit/TSimpleJSONProtocolTest.php deleted file mode 100644 index 8e6a6d91743..00000000000 --- a/lib/php/test/Unit/TSimpleJSONProtocolTest.php +++ /dev/null @@ -1,247 +0,0 @@ -registerNamespace('ThriftTest', __DIR__ . '/../Resources/packages/php'); - $loader->registerDefinition('ThriftTest', __DIR__ . '/../Resources/packages/php'); - $loader->register(); - - Fixtures::populateTestArgs(); - TSimpleJSONProtocolFixtures::populateTestArgsSimpleJSON(); - } - - public function setUp(): void - { - $this->transport = new TMemoryBuffer(); - $this->protocol = new TSimpleJSONProtocol($this->transport); - $this->transport->open(); - } - - /** - * WRITE TESTS - */ - public function testVoidWrite() - { - $args = new \ThriftTest\ThriftTest_testVoid_args(); - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testVoid']; - - $this->assertEquals($expected, $actual); - } - - public function testString1Write() - { - $args = new \ThriftTest\ThriftTest_testString_args(); - $args->thing = Fixtures::$testArgs['testString1']; - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testString1']; - - $this->assertEquals($expected, $actual); - } - - public function testString2Write() - { - $args = new \ThriftTest\ThriftTest_testString_args(); - $args->thing = Fixtures::$testArgs['testString2']; - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testString2']; - - $this->assertEquals($expected, $actual); - } - - public function testDoubleWrite() - { - $args = new \ThriftTest\ThriftTest_testDouble_args(); - $args->thing = Fixtures::$testArgs['testDouble']; - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testDouble']; - - $this->assertEquals($expected, $actual); - } - - public function testByteWrite() - { - $args = new \ThriftTest\ThriftTest_testByte_args(); - $args->thing = Fixtures::$testArgs['testByte']; - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testByte']; - - $this->assertEquals($expected, $actual); - } - - public function testI32Write() - { - $args = new \ThriftTest\ThriftTest_testI32_args(); - $args->thing = Fixtures::$testArgs['testI32']; - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testI32']; - - $this->assertEquals($expected, $actual); - } - - public function testI64Write() - { - $args = new \ThriftTest\ThriftTest_testI64_args(); - $args->thing = Fixtures::$testArgs['testI64']; - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testI64']; - - $this->assertEquals($expected, $actual); - } - - public function testStructWrite() - { - $args = new \ThriftTest\ThriftTest_testStruct_args(); - $args->thing = Fixtures::$testArgs['testStruct']; - - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testStruct']; - - $this->assertEquals($expected, $actual); - } - - public function testNestWrite() - { - $args = new \ThriftTest\ThriftTest_testNest_args(); - $args->thing = Fixtures::$testArgs['testNest']; - - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testNest']; - - $this->assertEquals($expected, $actual); - } - - public function testMapWrite() - { - $args = new \ThriftTest\ThriftTest_testMap_args(); - $args->thing = Fixtures::$testArgs['testMap']; - - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testMap']; - - $this->assertEquals($expected, $actual); - } - - public function testStringMapWrite() - { - $args = new \ThriftTest\ThriftTest_testStringMap_args(); - $args->thing = Fixtures::$testArgs['testStringMap']; - - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testStringMap']; - - $this->assertEquals($expected, $actual); - } - - public function testSetWrite() - { - $args = new \ThriftTest\ThriftTest_testSet_args(); - $args->thing = Fixtures::$testArgs['testSet']; - - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testSet']; - - $this->assertEquals($expected, $actual); - } - - public function testListWrite() - { - $args = new \ThriftTest\ThriftTest_testList_args(); - $args->thing = Fixtures::$testArgs['testList']; - - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testList']; - - $this->assertEquals($expected, $actual); - } - - public function testEnumWrite() - { - $args = new \ThriftTest\ThriftTest_testEnum_args(); - $args->thing = Fixtures::$testArgs['testEnum']; - - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testEnum']; - - $this->assertEquals($expected, $actual); - } - - public function testTypedefWrite() - { - $args = new \ThriftTest\ThriftTest_testTypedef_args(); - $args->thing = Fixtures::$testArgs['testTypedef']; - - $args->write($this->protocol); - - $actual = $this->transport->read(Fixtures::$bufsize); - $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testTypedef']; - - $this->assertEquals($expected, $actual); - } -} diff --git a/lib/php/test/bootstrap.php b/lib/php/test/bootstrap.php new file mode 100644 index 00000000000..c6291e51798 --- /dev/null +++ b/lib/php/test/bootstrap.php @@ -0,0 +1,16 @@ +registerNamespace('Basic', __DIR__ . '/Resources/packages/php'); +$loader->registerNamespace('Validate', __DIR__ . '/Resources/packages/phpv'); +$loader->registerNamespace('ValidateOop', __DIR__ . '/Resources/packages/phpvo'); +$loader->registerNamespace('Json', __DIR__ . '/Resources/packages/phpjs'); + +#do not load this namespace here, it will be loaded in ClassLoaderTest +//$loader->registerNamespace('Server', __DIR__ . '/Resources/packages/phpcm'); + +$loader->register(); diff --git a/test/php/Client.php b/test/php/Client.php new file mode 100644 index 00000000000..1cd424126e1 --- /dev/null +++ b/test/php/Client.php @@ -0,0 +1,26 @@ +registerDefinition('ThriftTest', __DIR__ . '/../../lib/php/test/Resources/packages/phpcm'); +$loader->register(); + + +$transport = new THttpClient('localhost', 80); + +$transport->setTimeoutSecs($this->timeoutSec); + +$transport->addHeaders($this->generateAuthHeader()); + +$protocol = new TCompactProtocol($transport); + +$transport->open(); + +$client = new \ThriftTest\ThriftTestClient($protocol); +$client->testVoid(); diff --git a/test/php/Handler.php b/test/php/Handler.php new file mode 100644 index 00000000000..5ca06a21d03 --- /dev/null +++ b/test/php/Handler.php @@ -0,0 +1,114 @@ +registerDefinition('ThriftTest', __DIR__ . '/../../lib/php/test/Resources/packages/phpcm'); +$loader->register(); + +$sslOptions = \stream_context_create( + [ + 'ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + ], + ] +); + +require_once __DIR__ . '/Handler.php'; + +switch ($transport) { + case 'framed': + $serverTransportFactory = new \Thrift\Factory\TFramedTransportFactory(); + break; + default: + $serverTransportFactory = new \Thrift\Factory\TTransportFactory(); +} + +$serverTransport = new \Thrift\Server\TServerSocket('localhost', $port); +$handler = new Handler(); +$processor = new ThriftTest\ThriftTestProcessor($handler); + +$server = new \Thrift\Server\TSimpleServer( + $processor, + $serverTransport, + $serverTransportFactory, + $serverTransportFactory, + new \Thrift\Factory\TBinaryProtocolFactory(), + new \Thrift\Factory\TBinaryProtocolFactory() +); + +echo "Starting the Test server...\n"; +$server->serve(); diff --git a/test/php/test_php.ini b/test/php/test_php.ini index aeb67cbd411..5eecb329618 100644 --- a/test/php/test_php.ini +++ b/test/php/test_php.ini @@ -1,3 +1,3 @@ -extension=thrift_protocol.so -extension=json.so -extension=sockets.so +;extension=thrift_protocol.so +;extension=json.so +;extension=sockets.so diff --git a/test/tests.json b/test/tests.json index 7eb9f65b9dd..91aa767f35c 100644 --- a/test/tests.json +++ b/test/tests.json @@ -539,6 +539,31 @@ }, { "name": "php", + "server": { + "transports": [ + "buffered", + "framed" + ], + "sockets": [ + "ip" + ], + "protocols": [ + "binary", + "binary:accel", + "compact", + "json" + ], + "command": [ + "php", + "-dextension_dir=php_ext_dir", + "--php-ini=test_php.ini", + "--no-php-ini", + "-ddisplay_errors=stderr", + "-dlog_errors=0", + "-derror_reporting=E_ALL", + "TestServer.php" + ] + }, "client": { "timeout": 6, "transports": [