3 include_once __DIR__ . '/../lib/xmlrpc.inc';
4 include_once __DIR__ . '/../lib/xmlrpc_wrappers.inc';
6 include_once __DIR__ . '/parse_args.php';
8 include_once __DIR__ . '/PolyfillTestCase.php';
10 use PHPUnit\Extensions\SeleniumCommon\RemoteCoverage;
11 use PHPUnit\Framework\TestResult;
12 use PHPUnit\Runner\BaseTestRunner;
15 * Tests which involve interaction between the client and the server.
16 * They are run against the server found in demo/server.php
18 class LocalhostTest extends PhpXmlRpc_PolyfillTestCase
20 /** @var xmlrpc_client $client */
21 protected $client = null;
22 protected $method = 'http';
23 protected $timeout = 10;
24 protected $request_compression = null;
25 protected $accepted_compression = '';
26 protected $args = array();
28 protected static $failed_tests = array();
31 /** @var boolean $collectCodeCoverageInformation */
32 protected $collectCodeCoverageInformation;
33 protected $coverageScriptUrl;
36 * @todo instead of overriding fail via _fail, implement Yoast\PHPUnitPolyfills\TestListeners\TestListenerDefaultImplementation
38 public static function _fail($message = '')
40 // save in a static var that this particular test has failed
41 // (but only if not called from subclass objects / multitests)
42 if (function_exists('debug_backtrace') && strtolower(get_called_class()) == 'localhosttests') {
43 $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
44 for ($i = 0; $i < count($trace); $i++) {
45 if (strpos($trace[$i]['function'], 'test') === 0) {
46 self::$failed_tests[$trace[$i]['function']] = true;
52 parent::_fail($message);
56 * Reimplemented to allow us to collect code coverage info from the target server.
57 * Code taken from PHPUnit_Extensions_Selenium2TestCase
59 * @param TestResult $result
63 * @todo instead of overriding run via _run, try to achieve this by implementing Yoast\PHPUnitPolyfills\TestListeners\TestListenerDefaultImplementation
65 public function _run($result = NULL)
67 $this->testId = get_class($this) . '__' . $this->getName();
69 if ($result === NULL) {
70 $result = $this->createResult();
73 $this->collectCodeCoverageInformation = $result->getCollectCodeCoverageInformation();
75 parent::_run($result);
77 if ($this->collectCodeCoverageInformation) {
78 $coverage = new RemoteCoverage(
79 $this->coverageScriptUrl,
82 $result->getCodeCoverage()->append(
83 $coverage->get(), $this
87 // do not call this before to give the time to the Listeners to run
88 //$this->getStrategy()->endOfTest($this->session);
93 public function set_up()
95 $this->args = argParser::getArgs();
97 $server = explode(':', $this->args['HTTPSERVER']);
98 if (count($server) > 1) {
99 $this->client = new xmlrpc_client($this->args['HTTPURI'], $server[0], $server[1]);
101 $this->client = new xmlrpc_client($this->args['HTTPURI'], $this->args['HTTPSERVER']);
104 $this->client->setDebug($this->args['DEBUG']);
105 $this->client->request_compression = $this->request_compression;
106 $this->client->accepted_compression = $this->accepted_compression;
108 $this->coverageScriptUrl = 'http://' . $this->args['HTTPSERVER'] . '/' . str_replace( '/demo/server/server.php', 'tests/phpunit_coverage.php', $this->args['HTTPURI'] );
110 if ($this->args['DEBUG'] == 1)
114 protected function tear_down()
116 if ($this->args['DEBUG'] != 1)
118 $out = ob_get_clean();
119 $status = $this->getStatus();
120 if ($status == BaseTestRunner::STATUS_ERROR
121 || $status == BaseTestRunner::STATUS_FAILURE) {
127 * @param PhpXmlRpc\Request|array $msg
128 * @param int|array $errorCode
129 * @param bool $returnResponse
130 * @return mixed|\PhpXmlRpc\Response|\PhpXmlRpc\Response[]|\PhpXmlRpc\Value|string|null
132 protected function send($msg, $errorCode = 0, $returnResponse = false)
134 if ($this->collectCodeCoverageInformation) {
135 $this->client->setCookie('PHPUNIT_SELENIUM_TEST_ID', $this->testId);
138 $r = $this->client->send($msg, $this->timeout, $this->method);
139 // for multicall, return directly array of responses
143 if (is_array($errorCode)) {
144 $this->assertContains($r->faultCode(), $errorCode, 'Error ' . $r->faultCode() . ' connecting to server: ' . $r->faultString());
146 $this->assertEquals($errorCode, $r->faultCode(), 'Error ' . $r->faultCode() . ' connecting to server: ' . $r->faultString());
148 if (!$r->faultCode()) {
149 if ($returnResponse) {
160 * Adds (and replaces) query params to the url currently used by the client
163 protected function addQueryParams($data)
165 $query = parse_url($this->client->path, PHP_URL_QUERY);
166 parse_str($query, $vars);
167 $query = http_build_query(array_merge($vars, $data));
168 $this->client->path = parse_url($this->client->path, PHP_URL_PATH) . '?' . $query;
171 public function testString()
173 $sendString = "here are 3 \"entities\": < > & " .
174 "and here's a dollar sign: \$pretendvarname and a backslash too: " . chr(92) .
175 " - isn't that great? \\\"hackery\\\" at it's best " .
176 " also don't want to miss out on \$item[0]. " .
177 "The real weird stuff follows: CRLF here" . chr(13) . chr(10) .
178 "a simple CR here" . chr(13) .
179 "a simple LF here" . chr(10) .
180 "and then LFCR" . chr(10) . chr(13) .
181 "last but not least weird names: G" . chr(252) . "nter, El" . chr(232) . "ne, and an xml comment closing tag: -->";
182 $m = new xmlrpcmsg('examples.stringecho', array(
183 new xmlrpcval($sendString, 'string'),
185 $v = $this->send($m);
187 // when sending/receiving non-US-ASCII encoded strings, XML says cr-lf can be normalized.
188 // so we relax our tests...
189 $l1 = strlen($sendString);
190 $l2 = strlen($v->scalarval());
192 $this->assertEquals($sendString, $v->scalarval());
194 $this->assertEquals(str_replace(array("\r\n", "\r"), array("\n", "\n"), $sendString), $v->scalarval());
199 public function testLatin1String()
202 "last but not least weird names: G" . chr(252) . "nter, El" . chr(232) . "ne";
203 $x = '<?xml version="1.0" encoding="ISO-8859-1"?><methodCall><methodName>examples.stringecho</methodName><params><param><value>'.
205 '</value></param></params></methodCall>';
206 $v = $this->send($x);
208 $this->assertEquals($sendString, $v->scalarval());
212 public function testExoticCharsetsRequests()
214 // note that we should disable this call also when mbstring is missing server-side
215 if (!function_exists('mb_convert_encoding')) {
216 $this->markTestSkipped('Miss mbstring extension to test exotic charsets');
219 $sendString = 'κόσμε'; // Greek word 'kosme'. NB: NOT a valid ISO8859 string!
220 $str = '<?xml version="1.0" encoding="_ENC_"?>
222 <methodName>examples.stringecho</methodName>
225 <value><string>'.$sendString.'</string></value>
230 PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'UTF-8';
231 // we have to set the encoding declaration either in the http header or xml prolog, as mb_detect_encoding
232 // (used on the server side) will fail recognizing these 2 charsets
233 $v = $this->send(mb_convert_encoding(str_replace('_ENC_', 'UCS-4', $str), 'UCS-4', 'UTF-8'));
234 $this->assertEquals($sendString, $v->scalarval());
235 $v = $this->send(mb_convert_encoding(str_replace('_ENC_', 'UTF-16', $str), 'UTF-16', 'UTF-8'));
236 $this->assertEquals($sendString, $v->scalarval());
237 PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'ISO-8859-1';
240 public function testExoticCharsetsRequests2()
242 // note that we should disable this call also when mbstring is missing server-side
243 if (!function_exists('mb_convert_encoding')) {
244 $this->markTestSkipped('Miss mbstring extension to test exotic charsets');
247 $sendString = '安室奈美恵'; // No idea what this means :-) NB: NOT a valid ISO8859 string!
248 $str = '<?xml version="1.0"?>
250 <methodName>examples.stringecho</methodName>
253 <value><string>'.$sendString.'</string></value>
258 PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'UTF-8';
259 // no encoding declaration either in the http header or xml prolog, let mb_detect_encoding
260 // (used on the server side) sort it out
261 $this->addQueryParams(array('DETECT_ENCODINGS' => array('EUC-JP', 'UTF-8')));
262 $v = $this->send(mb_convert_encoding($str, 'EUC-JP', 'UTF-8'));
263 $this->assertEquals($sendString, $v->scalarval());
264 PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'ISO-8859-1';
267 public function testExoticCharsetsRequests3()
269 // note that we should disable this call also when mbstring is missing server-side
270 if (!function_exists('mb_convert_encoding')) {
271 $this->markTestSkipped('Miss mbstring extension to test exotic charsets');
274 $sendString = utf8_decode('élève');
275 $str = '<?xml version="1.0"?>
277 <methodName>examples.stringecho</methodName>
280 <value><string>'.$sendString.'</string></value>
285 // no encoding declaration either in the http header or xml prolog, let mb_detect_encoding
286 // (used on the server side) sort it out
287 $this->addQueryParams(array('DETECT_ENCODINGS' => array('ISO-8859-1', 'UTF-8')));
288 $v = $this->send($str);
289 $this->assertEquals($sendString, $v->scalarval());
292 /*public function testLatin1Method()
294 $f = new xmlrpcmsg("tests.iso88591methodname." . chr(224) . chr(252) . chr(232), array(
295 new xmlrpcval('hello')
297 $v = $this->send($f);
299 $this->assertEquals('hello', $v->scalarval());
303 public function testUtf8Method()
305 PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'UTF-8';
306 $m = new xmlrpcmsg("tests.utf8methodname." . 'κόσμε', array(
307 new xmlrpcval('hello')
309 $v = $this->send($m);
311 $this->assertEquals('hello', $v->scalarval());
313 PhpXmlRpc\PhpXmlRpc::$xmlrpc_internalencoding = 'ISO-8859-1';
316 public function testAddingDoubles()
318 // note that rounding errors mean we
319 // keep precision to sensible levels here ;-)
322 $m = new xmlrpcmsg('examples.addtwodouble', array(
323 new xmlrpcval($a, 'double'),
324 new xmlrpcval($b, 'double'),
326 $v = $this->send($m);
328 $this->assertEquals($a + $b, $v->scalarval());
332 public function testAdding()
334 $m = new xmlrpcmsg('examples.addtwo', array(
335 new xmlrpcval(12, 'int'),
336 new xmlrpcval(-23, 'int'),
338 $v = $this->send($m);
340 $this->assertEquals(12 - 23, $v->scalarval());
344 public function testInvalidNumber()
346 $m = new xmlrpcmsg('examples.addtwo', array(
347 new xmlrpcval('fred', 'int'),
348 new xmlrpcval("\"; exec('ls')", 'int'),
350 $v = $this->send($m);
351 /// @todo a fault condition should be generated here
352 /// by the server, which we pick up on
354 $this->assertEquals(0, $v->scalarval());
358 public function testBoolean()
360 $m = new xmlrpcmsg('examples.invertBooleans', array(
362 new xmlrpcval(true, 'boolean'),
363 new xmlrpcval(false, 'boolean'),
364 new xmlrpcval(1, 'boolean'),
365 new xmlrpcval(0, 'boolean')
370 $v = $this->send($m);
372 $sz = $v->arraysize();
374 for ($i = 0; $i < $sz; $i++) {
375 $b = $v->arraymem($i);
376 if ($b->scalarval()) {
382 $this->assertEquals($answer, $got);
386 public function testBase64()
388 $sendString = 'Mary had a little lamb,
389 Whose fleece was white as snow,
390 And everywhere that Mary went
391 the lamb was sure to go.
393 Mary had a little lamb
394 She tied it to a pylon
395 Ten thousand volts went down its back
396 And turned it into nylon';
397 $m = new xmlrpcmsg('examples.decode64', array(
398 new xmlrpcval($sendString, 'base64'),
400 $v = $this->send($m);
402 if (strlen($sendString) == strlen($v->scalarval())) {
403 $this->assertEquals($sendString, $v->scalarval());
405 $this->assertEquals(str_replace(array("\r\n", "\r"), array("\n", "\n"), $sendString), $v->scalarval());
410 public function testDateTime()
413 $t1 = new xmlrpcval($time, 'dateTime.iso8601');
414 $t2 = new xmlrpcval(iso8601_encode($time), 'dateTime.iso8601');
415 $this->assertEquals($t1->serialize(), $t2->serialize());
416 if (class_exists('DateTime')) {
417 $datetime = new DateTime();
418 // skip this test for php 5.2. It is a bit harder there to build a DateTime from unix timestamp with proper TZ info
419 if (is_callable(array($datetime, 'setTimestamp'))) {
420 $t3 = new xmlrpcval($datetime->setTimestamp($time), 'dateTime.iso8601');
421 $this->assertEquals($t1->serialize(), $t3->serialize());
426 public function testCountEntities()
428 $sendString = "h'fd>onc>>l>>rw&bpu>q>e<v&gxs<ytjzkami<";
429 $m = new xmlrpcmsg('validator1.countTheEntities', array(
430 new xmlrpcval($sendString, 'string'),
432 $v = $this->send($m);
436 $expect_array = array('ctLeftAngleBrackets', 'ctRightAngleBrackets', 'ctAmpersands', 'ctApostrophes', 'ctQuotes');
437 foreach($expect_array as $val) {
438 $b = $v->structmem($val);
439 $got .= $b->me['int'];
441 $this->assertEquals($expected, $got);
445 public function _multicall_msg($method, $params)
447 $struct['methodName'] = new xmlrpcval($method, 'string');
448 $struct['params'] = new xmlrpcval($params, 'array');
450 return new xmlrpcval($struct, 'struct');
453 public function testServerMulticall()
455 // We manually construct a system.multicall() call to ensure
456 // that the server supports it.
458 // NB: This test will NOT pass if server does not support system.multicall.
460 // Based on http://xmlrpc-c.sourceforge.net/hacks/test_multicall.py
461 $good1 = $this->_multicall_msg(
463 array(php_xmlrpc_encode('system.listMethods')));
464 $bad = $this->_multicall_msg(
466 array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
467 $recursive = $this->_multicall_msg(
469 array(new xmlrpcval(array(), 'array')));
470 $good2 = $this->_multicall_msg(
471 'system.methodSignature',
472 array(php_xmlrpc_encode('system.listMethods')));
473 $arg = new xmlrpcval(
474 array($good1, $bad, $recursive, $good2),
478 $m = new xmlrpcmsg('system.multicall', array($arg));
479 $v = $this->send($m);
481 //$this->assertTrue($r->faultCode() == 0, "fault from system.multicall");
482 $this->assertTrue($v->arraysize() == 4, "bad number of return values");
484 $r1 = $v->arraymem(0);
486 $r1->kindOf() == 'array' && $r1->arraysize() == 1,
487 "did not get array of size 1 from good1"
490 $r2 = $v->arraymem(1);
492 $r2->kindOf() == 'struct',
496 $r3 = $v->arraymem(2);
498 $r3->kindOf() == 'struct',
499 "recursive system.multicall did not fail"
502 $r4 = $v->arraymem(3);
504 $r4->kindOf() == 'array' && $r4->arraysize() == 1,
505 "did not get array of size 1 from good2"
510 public function testClientMulticall1()
512 // NB: This test will NOT pass if server does not support system.multicall.
514 $noMultiCall = $this->client->no_multicall;
515 $this->client->no_multicall = false;
517 $good1 = new xmlrpcmsg('system.methodHelp',
518 array(php_xmlrpc_encode('system.listMethods')));
519 $bad = new xmlrpcmsg('test.nosuch',
520 array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
521 $recursive = new xmlrpcmsg('system.multicall',
522 array(new xmlrpcval(array(), 'array')));
523 $good2 = new xmlrpcmsg('system.methodSignature',
524 array(php_xmlrpc_encode('system.listMethods'))
527 $r = $this->send(array($good1, $bad, $recursive, $good2));
529 $this->assertTrue(count($r) == 4, "wrong number of return values");
532 $this->assertTrue($r[0]->faultCode() == 0, "fault from good1");
533 if (!$r[0]->faultCode()) {
534 $val = $r[0]->value();
536 $val->kindOf() == 'scalar' && $val->scalartyp() == 'string',
537 "good1 did not return string"
540 $this->assertTrue($r[1]->faultCode() != 0, "no fault from bad");
541 $this->assertTrue($r[2]->faultCode() != 0, "no fault from recursive system.multicall");
542 $this->assertTrue($r[3]->faultCode() == 0, "fault from good2");
543 if (!$r[3]->faultCode()) {
544 $val = $r[3]->value();
545 $this->assertTrue($val->kindOf() == 'array', "good2 did not return array");
547 // This is the only assert in this test which should fail
548 // if the test server does not support system.multicall.
549 $this->assertTrue($this->client->no_multicall == false,
550 "server does not support system.multicall"
553 $this->client->no_multicall = $noMultiCall;
556 public function testClientMulticall2()
558 // NB: This test will NOT pass if server does not support system.multicall.
560 $noMultiCall = $this->client->no_multicall;
561 $this->client->no_multicall = true;
563 $good1 = new xmlrpcmsg('system.methodHelp',
564 array(php_xmlrpc_encode('system.listMethods')));
565 $bad = new xmlrpcmsg('test.nosuch',
566 array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
567 $recursive = new xmlrpcmsg('system.multicall',
568 array(new xmlrpcval(array(), 'array')));
569 $good2 = new xmlrpcmsg('system.methodSignature',
570 array(php_xmlrpc_encode('system.listMethods'))
573 $r = $this->send(array($good1, $bad, $recursive, $good2));
575 $this->assertTrue(count($r) == 4, "wrong number of return values");
578 $this->assertTrue($r[0]->faultCode() == 0, "fault from good1");
579 if (!$r[0]->faultCode()) {
580 $val = $r[0]->value();
582 $val->kindOf() == 'scalar' && $val->scalartyp() == 'string',
583 "good1 did not return string");
585 $this->assertTrue($r[1]->faultCode() != 0, "no fault from bad");
586 $this->assertTrue($r[2]->faultCode() == 0, "fault from (non recursive) system.multicall");
587 $this->assertTrue($r[3]->faultCode() == 0, "fault from good2");
588 if (!$r[3]->faultCode()) {
589 $val = $r[3]->value();
590 $this->assertTrue($val->kindOf() == 'array', "good2 did not return array");
593 $this->client->no_multicall = $noMultiCall;
596 public function testClientMulticall3()
598 // NB: This test will NOT pass if server does not support system.multicall.
600 $noMultiCall = $this->client->no_multicall;
601 $returnType = $this->client->return_type;
603 $this->client->return_type = 'phpvals';
604 $this->client->no_multicall = false;
606 $good1 = new xmlrpcmsg('system.methodHelp',
607 array(php_xmlrpc_encode('system.listMethods')));
608 $bad = new xmlrpcmsg('test.nosuch',
609 array(php_xmlrpc_encode(1), php_xmlrpc_encode(2)));
610 $recursive = new xmlrpcmsg('system.multicall',
611 array(new xmlrpcval(array(), 'array')));
612 $good2 = new xmlrpcmsg('system.methodSignature',
613 array(php_xmlrpc_encode('system.listMethods'))
616 $r = $this->send(array($good1, $bad, $recursive, $good2));
618 $this->assertTrue(count($r) == 4, "wrong number of return values");
620 $this->assertTrue($r[0]->faultCode() == 0, "fault from good1");
621 if (!$r[0]->faultCode()) {
622 $val = $r[0]->value();
624 is_string($val), "good1 did not return string");
626 $this->assertTrue($r[1]->faultCode() != 0, "no fault from bad");
627 $this->assertTrue($r[2]->faultCode() != 0, "no fault from recursive system.multicall");
628 $this->assertTrue($r[3]->faultCode() == 0, "fault from good2");
629 if (!$r[3]->faultCode()) {
630 $val = $r[3]->value();
631 $this->assertTrue(is_array($val), "good2 did not return array");
634 $this->client->return_type = $returnType;
635 $this->client->no_multicall = $noMultiCall;
638 public function testCatchWarnings()
640 $m = new xmlrpcmsg('tests.generatePHPWarning', array(
641 new xmlrpcval('whatever', 'string'),
643 $v = $this->send($m);
645 $this->assertEquals(true, $v->scalarval());
649 public function testCatchExceptions()
651 $m = new xmlrpcmsg('tests.raiseException', array(
652 new xmlrpcval('whatever', 'string'),
654 $v = $this->send($m, $GLOBALS['xmlrpcerr']['server_error']);
655 $this->addQueryParams(array('EXCEPTION_HANDLING' => 1));
656 $v = $this->send($m, 1); // the error code of the expected exception
657 $this->addQueryParams(array('EXCEPTION_HANDLING' => 2));
658 // depending on whether display_errors is ON or OFF on the server, we will get back a different error here,
659 // as php will generate an http status code of either 200 or 500...
660 $v = $this->send($m, array($GLOBALS['xmlrpcerr']['invalid_return'], $GLOBALS['xmlrpcerr']['http_error']));
663 public function testZeroParams()
665 $m = new xmlrpcmsg('system.listMethods');
666 $v = $this->send($m);
669 public function testNullParams()
671 $m = new xmlrpcmsg('tests.getStateName.12', array(
672 new xmlrpcval('whatever', 'null'),
673 new xmlrpcval(23, 'int'),
675 $v = $this->send($m);
677 $this->assertEquals('Michigan', $v->scalarval());
679 $m = new xmlrpcmsg('tests.getStateName.12', array(
680 new xmlrpcval(23, 'int'),
681 new xmlrpcval('whatever', 'null'),
683 $v = $this->send($m);
685 $this->assertEquals('Michigan', $v->scalarval());
687 $m = new xmlrpcmsg('tests.getStateName.12', array(
688 new xmlrpcval(23, 'int')
690 $v = $this->send($m, array($GLOBALS['xmlrpcerr']['incorrect_params']));
693 public function testCodeInjectionServerSide()
695 $m = new xmlrpcmsg('system.MethodHelp');
696 $m->payload = "<?xml version=\"1.0\"?><methodCall><methodName>validator1.echoStructTest</methodName><params><param><value><struct><member><name>','')); echo('gotcha!'); die(); //</name></member></struct></value></param></params></methodCall>";
697 $v = $this->send($m);
699 $this->assertEquals(0, $v->structsize());
703 public function testServerWrappedFunction()
705 $m = new xmlrpcmsg('tests.getStateName.2', array(
706 new xmlrpcval(23, 'int'),
708 $v = $this->send($m);
709 $this->assertEquals('Michigan', $v->scalarval());
711 // this generates an exception in the function which was wrapped, which is by default wrapped in a known error response
712 $m = new xmlrpcmsg('tests.getStateName.2', array(
713 new xmlrpcval(0, 'int'),
715 $v = $this->send($m, $GLOBALS['xmlrpcerr']['server_error']);
717 // check if the generated function dispatch map is fine, by checking if the server registered it
718 $m = new xmlrpcmsg('system.methodSignature', array(
719 new xmlrpcval('tests.getStateName.2'),
721 $v = $this->send($m);
722 $encoder = new \PhpXmlRpc\Encoder();
723 $this->assertEquals(array(array('string', 'int')), $encoder->decode($v));
726 public function testServerWrappedFunctionAsSource()
728 $m = new xmlrpcmsg('tests.getStateName.6', array(
729 new xmlrpcval(23, 'int'),
731 $v = $this->send($m);
732 $this->assertEquals('Michigan', $v->scalarval());
734 // this generates an exception in the function which was wrapped, which is by default wrapped in a known error response
735 $m = new xmlrpcmsg('tests.getStateName.6', array(
736 new xmlrpcval(0, 'int'),
738 $v = $this->send($m, $GLOBALS['xmlrpcerr']['server_error']);
741 public function testServerWrappedObjectMethods()
743 $m = new xmlrpcmsg('tests.getStateName.3', array(
744 new xmlrpcval(23, 'int'),
746 $v = $this->send($m);
747 $this->assertEquals('Michigan', $v->scalarval());
749 $m = new xmlrpcmsg('tests.getStateName.4', array(
750 new xmlrpcval(23, 'int'),
752 $v = $this->send($m);
753 $this->assertEquals('Michigan', $v->scalarval());
755 $m = new xmlrpcmsg('tests.getStateName.5', array(
756 new xmlrpcval(23, 'int'),
758 $v = $this->send($m);
759 $this->assertEquals('Michigan', $v->scalarval());
761 $m = new xmlrpcmsg('tests.getStateName.7', array(
762 new xmlrpcval(23, 'int'),
764 $v = $this->send($m);
765 $this->assertEquals('Michigan', $v->scalarval());
767 $m = new xmlrpcmsg('tests.getStateName.8', array(
768 new xmlrpcval(23, 'int'),
770 $v = $this->send($m);
771 $this->assertEquals('Michigan', $v->scalarval());
773 $m = new xmlrpcmsg('tests.getStateName.9', array(
774 new xmlrpcval(23, 'int'),
776 $v = $this->send($m);
777 $this->assertEquals('Michigan', $v->scalarval());
780 public function testServerWrappedObjectMethodsAsSource()
782 $m = new xmlrpcmsg('tests.getStateName.7', array(
783 new xmlrpcval(23, 'int'),
785 $v = $this->send($m);
786 $this->assertEquals('Michigan', $v->scalarval());
788 $m = new xmlrpcmsg('tests.getStateName.8', array(
789 new xmlrpcval(23, 'int'),
791 $v = $this->send($m);
792 $this->assertEquals('Michigan', $v->scalarval());
794 $m = new xmlrpcmsg('tests.getStateName.9', array(
795 new xmlrpcval(23, 'int'),
797 $v = $this->send($m);
798 $this->assertEquals('Michigan', $v->scalarval());
801 public function testServerClosure()
803 $m = new xmlrpcmsg('tests.getStateName.10', array(
804 new xmlrpcval(23, 'int'),
806 $v = $this->send($m);
807 $this->assertEquals('Michigan', $v->scalarval());
810 public function testServerWrappedClosure()
812 $m = new xmlrpcmsg('tests.getStateName.11', array(
813 new xmlrpcval(23, 'int'),
815 $v = $this->send($m);
816 $this->assertEquals('Michigan', $v->scalarval());
819 public function testServerWrappedClass()
821 $m = new xmlrpcmsg('tests.xmlrpcServerMethodsContainer.findState', array(
822 new xmlrpcval(23, 'int'),
824 $v = $this->send($m);
825 $this->assertEquals('Michigan', $v->scalarval());
828 public function testWrappedMethod()
830 // make a 'deep client copy' as the original one might have many properties set
831 $func = wrap_xmlrpc_method($this->client, 'examples.getStateName', array('simple_client_copy' => 0));
832 if ($func == false) {
833 $this->fail('Registration of examples.getStateName failed');
836 // work around bug in current (or old?) version of phpunit when reporting the error
837 /*if (is_object($v)) {
838 $v = var_export($v, true);
840 $this->assertEquals('Michigan', $v);
844 public function testWrappedMethodAsSource()
846 // make a 'deep client copy' as the original one might have many properties set
847 $func = wrap_xmlrpc_method($this->client, 'examples.getStateName', array('simple_client_copy' => 0, 'return_source' => true));
848 if ($func == false) {
849 $this->fail('Registration of examples.getStateName failed');
851 eval($func['source']);
852 $func = $func['function'];
854 // work around bug in current (or old?) version of phpunit when reporting the error
855 /*if (is_object($v)) {
856 $v = var_export($v, true);
858 $this->assertEquals('Michigan', $v);
862 public function testWrappedClass()
864 // make a 'deep client copy' as the original one might have many properties set
865 // also for speed only wrap one method of the whole server
866 $class = wrap_xmlrpc_server($this->client, array('simple_client_copy' => 0, 'method_filter' => '/examples\.getStateName/' ));
868 $this->fail('Registration of remote server failed');
871 if (!is_callable(array($obj, 'examples_getStateName'))) {
872 $this->fail('Registration of remote server failed to import method "examples_getStateName"');
874 $v = $obj->examples_getStateName(23);
875 // work around bug in current (or old?) version of phpunit when reporting the error
876 /*if (is_object($v)) {
877 $v = var_export($v, true);
879 $this->assertEquals('Michigan', $v);
884 public function testTransferOfObjectViaWrapping()
886 // make a 'deep client copy' as the original one might have many properties set
887 $func = wrap_xmlrpc_method($this->client, 'tests.returnPhpObject', array('simple_client_copy' => 0,
888 'decode_php_objs' => true));
889 if ($func == false) {
890 $this->fail('Registration of tests.returnPhpObject failed');
893 $obj = new stdClass();
894 $obj->hello = 'world';
895 $this->assertEquals($obj, $v);
899 public function testGetCookies()
901 // let server set to us some cookies we tell it
904 'c2' => array('value' => 'c2'),
905 'c3' => array('value' => 'c3', 'expires' => time() + 60 * 60 * 24 * 30),
906 'c4' => array('value' => 'c4', 'expires' => time() + 60 * 60 * 24 * 30, 'path' => '/'),
907 'c5' => array('value' => 'c5', 'expires' => time() + 60 * 60 * 24 * 30, 'path' => '/', 'domain' => 'localhost'),
909 $cookiesval = php_xmlrpc_encode($cookies);
910 $m = new xmlrpcmsg('examples.setcookies', array($cookiesval));
911 $r = $this->send($m, 0, true);
914 $this->assertEquals(1, $v->scalarval());
915 // now check if we decoded the cookies as we had set them
916 $rcookies = $r->cookies();
917 // remove extra cookies which might have been set by proxies
918 foreach ($rcookies as $c => $v) {
919 if (!in_array($c, array('c2', 'c3', 'c4', 'c5'))) {
920 unset($rcookies[$c]);
922 // Seems like we get this when using php-fpm and php 5.5+ ...
923 if (isset($rcookies[$c]['Max-Age'])) {
924 unset($rcookies[$c]['Max-Age']);
927 foreach ($cookies as $c => $v) {
928 // format for date string in cookies: 'Mon, 31 Oct 2005 13:50:56 GMT'
929 // but PHP versions differ on that, some use 'Mon, 31-Oct-2005 13:50:56 GMT'...
930 if (isset($v['expires'])) {
931 if (isset($rcookies[$c]['expires']) && strpos($rcookies[$c]['expires'], '-')) {
932 $cookies[$c]['expires'] = gmdate('D, d\-M\-Y H:i:s \G\M\T', $cookies[$c]['expires']);
934 $cookies[$c]['expires'] = gmdate('D, d M Y H:i:s \G\M\T', $cookies[$c]['expires']);
939 $this->assertEquals($cookies, $rcookies);
943 public function testSetCookies()
945 // let server set to us some cookies we tell it
950 'c3' => '!@#$%^&*()_+|}{":?><,./\';[]\\=-',
952 $m = new xmlrpcmsg('examples.getcookies', array());
953 foreach ($cookies as $cookie => $val) {
954 $this->client->setCookie($cookie, $val);
955 $cookies[$cookie] = (string)$cookies[$cookie];
957 $r = $this->client->send($m, $this->timeout, $this->method);
958 $this->assertEquals(0, $r->faultCode(), 'Error ' . $r->faultCode() . ' connecting to server: ' . $r->faultString());
959 if (!$r->faultCode()) {
961 $v = php_xmlrpc_decode($v);
963 // take care for the extra cookie used for coverage collection
964 if (isset($v['PHPUNIT_SELENIUM_TEST_ID'])) {
965 unset($v['PHPUNIT_SELENIUM_TEST_ID']);
968 // on IIS and Apache getallheaders returns something slightly different...
969 $this->assertEquals($cookies, $v);
973 public function testServerComments()
975 $m = new xmlrpcmsg('tests.xmlrpcServerMethodsContainer.debugMessageGenerator', array(
976 new xmlrpcval('hello world', 'string'),
978 $r = $this->send($m, 0, true);
979 $this->assertStringContainsString('hello world', $r->raw_data);
982 public function testSendTwiceSameMsg()
984 $m = new xmlrpcmsg('examples.stringecho', array(
985 new xmlrpcval('hello world', 'string'),
987 $v1 = $this->send($m);
988 $v2 = $this->send($m);
990 $this->assertEquals($v1, $v2);