diff --git a/modules/simpletest/tests/xmlrpc_test/src/Tests/XmlRpcBasicTest.php b/modules/simpletest/tests/xmlrpc_test/src/Tests/XmlRpcBasicTest.php index 33c5bd3..41adee7 100644 --- a/modules/simpletest/tests/xmlrpc_test/src/Tests/XmlRpcBasicTest.php +++ b/modules/simpletest/tests/xmlrpc_test/src/Tests/XmlRpcBasicTest.php @@ -10,20 +10,20 @@ namespace Drupal\xmlrpc_test\Tests; /** * Perform basic XML-RPC tests that do not require addition callbacks. */ -class XmlRpcBasicTest extends \DrupalWebTestCase { +class XmlRpcBasicTest extends XmlRpcTestBase { public static function getInfo() { return array( 'name' => 'XML-RPC basic', 'description' => 'Perform basic XML-RPC tests that do not require additional callbacks.', - 'group' => 'XML-RPC8', + 'group' => 'XML-RPC', ); } /** * Ensure that a basic XML-RPC call with no parameters works. */ - protected function testListMethods() { + public function testListMethods() { // Minimum list of methods that should be included. $minimum = array( 'system.multicall', @@ -34,12 +34,11 @@ class XmlRpcBasicTest extends \DrupalWebTestCase { ); // Invoke XML-RPC call to get list of methods. - $url = url(NULL, array('absolute' => TRUE)) . 'xmlrpc.php'; - $methods = xmlrpc($url, array('system.listMethods' => array())); + $methods = $this->xmlRpcGet(array('system.listMethods' => array())); // Ensure that the minimum methods were found. $count = 0; - foreach ($methods as $method) { + foreach ((array) $methods as $method) { if (in_array($method, $minimum)) { $count++; } @@ -51,9 +50,8 @@ class XmlRpcBasicTest extends \DrupalWebTestCase { /** * Ensure that system.methodSignature returns an array of signatures. */ - protected function testMethodSignature() { - $url = url(NULL, array('absolute' => TRUE)) . 'xmlrpc.php'; - $signature = xmlrpc($url, array('system.methodSignature' => array('system.listMethods'))); + public function testMethodSignature() { + $signature = $this->xmlRpcGet(array('system.methodSignature' => array('system.listMethods'))); $this->assert(is_array($signature) && !empty($signature) && is_array($signature[0]), 'system.methodSignature returns an array of signature arrays.'); } @@ -61,7 +59,7 @@ class XmlRpcBasicTest extends \DrupalWebTestCase { /** * Ensure that XML-RPC correctly handles invalid messages when parsing. */ - protected function testInvalidMessageParsing() { + public function testInvalidMessageParsing() { $invalid_messages = array( array( 'message' => xmlrpc_message(''), @@ -85,4 +83,44 @@ class XmlRpcBasicTest extends \DrupalWebTestCase { $this->assertFalse(xmlrpc_message_parse($assertion['message']), $assertion['assertion']); } } + + /** + * Ensure that XML-RPC correctly handles XML Accept headers. + */ + public function testAcceptHeaders() { + $request_header_sets = array( + // Default. + 'implicit' => array(), + 'text/xml' => array('Accept' => 'text/xml'), + 'application/xml' => array('Accept' => 'application/xml'), + ); + + foreach ($request_header_sets as $accept => $headers) { + try { + $methods = $this->xmlRpcGet(array('system.listMethods' => array()), $headers); + $this->assertTrue(is_array($methods), strtr('@accept accept header is accepted', array('@accept' => $accept))); + } + // @FIXME which exception ? + catch (ClientException $e) { + $this->fail($e); + } + } + } + + /** + * Addresses bug https://www.drupal.org/node/2146833 . + * + * @link http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php + */ + public function testInvalidServer() { + $invalid_endpoint = 'http://example.invalid/xmlrpc.php'; + $result = xmlrpc($invalid_endpoint, array('system.listMethods' => array())); + $this->verboseResult($result); + $this->assertFalse($result, "Calling an unknown host returns an error condition"); + + $this->assertEqual(-32300, xmlrpc_errno(), "Calling an unknown host is reported as a transport error."); + $message = xmlrpc_error_msg(); + $this->assertFalse(empty($message), "Calling an unknown host returns a meaningful error message."); + } + } diff --git a/modules/simpletest/tests/xmlrpc_test/src/Tests/XmlRpcMessagesTest.php b/modules/simpletest/tests/xmlrpc_test/src/Tests/XmlRpcMessagesTest.php index 608e4b5..a9c2125 100644 --- a/modules/simpletest/tests/xmlrpc_test/src/Tests/XmlRpcMessagesTest.php +++ b/modules/simpletest/tests/xmlrpc_test/src/Tests/XmlRpcMessagesTest.php @@ -7,12 +7,17 @@ namespace Drupal\xmlrpc_test\Tests; -class XmlRpcMessagesTest extends \DrupalWebTestCase { +/** + * Tests large messages and method alterations. + * + * @group xmlrpc + */ +class XmlRpcMessagesTest extends XmlRpcTestBase { public static function getInfo() { return array( 'name' => 'XML-RPC message and alteration', 'description' => 'Test large messages and method alterations.', - 'group' => 'XML-RPC8', + 'group' => 'XML-RPC', ); } @@ -23,17 +28,16 @@ class XmlRpcMessagesTest extends \DrupalWebTestCase { /** * Make sure that XML-RPC can transfer large messages. */ - function testSizedMessages() { + public function testSizedMessages() { // These tests can produce up to 128 x 160 words in the XML-RPC message // (see xmlrpc_test_message_sized_in_kb()) with 4 tags used to represent // each. Set a large enough tag limit to allow this to be tested. variable_set('xmlrpc_message_maximum_tag_count', 100000); - $xml_url = url(NULL, array('absolute' => TRUE)) . 'xmlrpc.php'; $sizes = array(8, 80, 160); foreach ($sizes as $size) { $xml_message_l = xmlrpc_test_message_sized_in_kb($size); - $xml_message_r = xmlrpc($xml_url, array('messages.messageSizedInKB' => array($size))); + $xml_message_r = $this->xmlRpcGet(array('messages.messageSizedInKB' => array($size))); $this->assertEqual($xml_message_l, $xml_message_r, format_string('XML-RPC messages.messageSizedInKB of %s Kb size received', array('%s' => $size))); } @@ -42,21 +46,72 @@ class XmlRpcMessagesTest extends \DrupalWebTestCase { /** * Ensure that hook_xmlrpc_alter() can hide even builtin methods. */ - protected function testAlterListMethods() { - - // Ensure xmlrpc_test_xmlrpc_alter() is disabled and retrieve regular list of methods. + public function testAlterListMethods() { + // Ensure xmlrpc_test_xmlrpc_alter() is disabled and retrieve regular list + // of methods. variable_set('xmlrpc_test_xmlrpc_alter', FALSE); - $url = url(NULL, array('absolute' => TRUE)) . 'xmlrpc.php'; - $methods1 = xmlrpc($url, array('system.listMethods' => array())); + $methods1 = $this->xmlRpcGet(array('system.listMethods' => array())); // Enable the alter hook and retrieve the list of methods again. variable_set('xmlrpc_test_xmlrpc_alter', TRUE); - $methods2 = xmlrpc($url, array('system.listMethods' => array())); + $methods2 = $this->xmlRpcGet(array('system.listMethods' => array())); $diff = array_diff($methods1, $methods2); $this->assertTrue(is_array($diff) && !empty($diff), 'Method list is altered by hook_xmlrpc_alter'); $removed = reset($diff); - $this->assertEqual($removed, 'system.methodSignature', 'Hiding builting system.methodSignature with hook_xmlrpc_alter works'); + $this->assertEqual($removed, 'system.methodSignature', 'Hiding builtin system.methodSignature with hook_xmlrpc_alter works'); + } + + /** + * Ensure that XML-RPC client sets correct encoding in request http headers. + */ + public function testRequestContentTypeDefinition() { + $headers = xmlrpc($this->getEndpoint(), array('test.headerEcho' => array())); + $this->assertIdentical($headers['Content-Type'], 'text/xml; charset=utf-8'); + } + + /** + * Check XML-RPC client and server encoding information. + * + * Ensure that XML-RPC client sets correct processing instructions for XML + * documents. + * + * Ensure that XML-RPC server sets correct encoding in response http headers + * and processing instructions for XML documents. + */ + public function ZtestRequestAndResponseEncodingDefinitions() { + $url = $this->getEndpoint(); + $client = \Drupal::httpClient(); + + // We can't use the xmlrpc() function here, because we have to access the + // full Guzzle response. + module_load_include('inc', 'xmlrpc'); + $xmlrpc_request = xmlrpc_request('system.listMethods', array()); + + $headers = ['Content-Type' => 'text/xml; charset=utf-8']; + $request = new Request('POST', $url, $headers, $xmlrpc_request->xml); + // These may not be initialized in some exception cases. + $data = NULL; + $content_type = NULL; + try { + $response = $client->send($request); + $data = $response->getBody(); + $content_type = $response->getHeader('Content-Type'); + $content_type = reset($content_type); + } + catch (RequestException $e) { + $this->fail($e->getMessage(), '"Normal" exception'); + } + catch (\Exception $e) { + $this->fail($e->getMessage(), 'Unexpected exception'); + } + + // The request string starts with the XML processing instruction. + $this->assertIdentical(0, strpos($request->getBody(), ''), 'Request Processing Instruction is "<?xml version="1.0" encoding="utf-8" ?>"'); + + // The response body has to start with the xml processing instruction. + $this->assertIdentical(strpos($data, ''), 0, 'Response Processing Instruction is "<?xml version="1.0" encoding="utf-8" ?>"'); + $this->assertIdentical($content_type, 'text/xml; charset=utf-8'); } } diff --git a/modules/simpletest/tests/xmlrpc_test/src/Tests/XmlRpcTestBase.php b/modules/simpletest/tests/xmlrpc_test/src/Tests/XmlRpcTestBase.php new file mode 100644 index 0000000..3d09b15 --- /dev/null +++ b/modules/simpletest/tests/xmlrpc_test/src/Tests/XmlRpcTestBase.php @@ -0,0 +1,86 @@ +verbose) { + return; + } + + if ($result === FALSE) { + $this->verbose(format_string('Result:
@result

Errno: @errno
Message: @message', array( + '@result' => var_export($result, TRUE), + '@errno' => xmlrpc_errno(), + '@message' => xmlrpc_error_msg(), + ))); + } + else { + $this->verbose('
' . var_export($result, TRUE) . '
'); + } + } + + /** + * Invokes xmlrpc method. + * + * @param array $args + * An associative array whose keys are the methods to call and whose values + * are the arguments to pass to the respective method. If multiple methods + * are specified, a system.multicall is performed. + * @param array $headers + * (optional) An array of headers to pass along. + * + * @return mixed + * The result of xmlrpc() function call. + * + * @see xmlrpc() + */ + protected function xmlRpcGet(array $args, array $headers = []) { + $url = $this->getEndpoint(); + $result = xmlrpc($url, $args, $headers); + $this->verboseResult($result); + return $result; + } + + /** + * Returns the URI of the server XML-RPC endpoint. + * + * @return string + * The server endpoint URI. + */ + public function getEndpoint() { + if (!isset($this->endPoint)) { + $uri = url(NULL, array('absolute' => TRUE)) . 'xmlrpc.php'; + $this->endPoint = $uri; + } + + return $this->endPoint; + } + +} diff --git a/modules/simpletest/tests/xmlrpc_test/src/Tests/XmlRpcValidatorTest.php b/modules/simpletest/tests/xmlrpc_test/src/Tests/XmlRpcValidatorTest.php index dfc3bb2..3972e81 100644 --- a/modules/simpletest/tests/xmlrpc_test/src/Tests/XmlRpcValidatorTest.php +++ b/modules/simpletest/tests/xmlrpc_test/src/Tests/XmlRpcValidatorTest.php @@ -7,12 +7,20 @@ namespace Drupal\xmlrpc_test\Tests; -class XmlRpcValidatorTest extends \DrupalWebTestCase { +use Drupal\simpletest\WebTestBase; + +/** + * Test validation according to the XML-RPC.com validation suite. + * + * See the xmlrpc validator1 + * specification. + */ +class XmlRpcValidatorTest extends XmlRpcTestBase { public static function getInfo() { return array( 'name' => 'XML-RPC validator', 'description' => 'See the xmlrpc validator1 specification.', - 'group' => 'XML-RPC8', + 'group' => 'XML-RPC', ); } @@ -23,39 +31,47 @@ class XmlRpcValidatorTest extends \DrupalWebTestCase { /** * Run validator1 tests. */ - function testValidator1() { - $xml_url = url(NULL, array('absolute' => TRUE)) . 'xmlrpc.php'; + public function testValidator() { srand(); mt_srand(); - $array_1 = array(array('curly' => mt_rand(-100, 100)), - array('curly' => mt_rand(-100, 100)), - array('larry' => mt_rand(-100, 100)), - array('larry' => mt_rand(-100, 100)), - array('moe' => mt_rand(-100, 100)), - array('moe' => mt_rand(-100, 100)), - array('larry' => mt_rand(-100, 100))); + $array_1 = array( + array('curly' => mt_rand(-100, 100)), + array('curly' => mt_rand(-100, 100)), + array('larry' => mt_rand(-100, 100)), + array('larry' => mt_rand(-100, 100)), + array('moe' => mt_rand(-100, 100)), + array('moe' => mt_rand(-100, 100)), + array('larry' => mt_rand(-100, 100)), + ); shuffle($array_1); - $l_res_1 = xmlrpc_test_arrayOfStructsTest($array_1); - $r_res_1 = xmlrpc($xml_url, array('validator1.arrayOfStructsTest' => array($array_1))); + $l_res_1 = xmlrpc_test_array_of_structs_test($array_1); + $r_res_1 = $this->xmlRpcGet(array('validator1.arrayOfStructsTest' => array($array_1))); $this->assertIdentical($l_res_1, $r_res_1); $string_2 = 't\'&>>zf"md>yr>xlcev">>uai"np&s>>q\'&b<>"&&&'; - $l_res_2 = xmlrpc_test_countTheEntities($string_2); - $r_res_2 = xmlrpc($xml_url, array('validator1.countTheEntities' => array($string_2))); + $l_res_2 = xmlrpc_test_count_the_entities($string_2); + $r_res_2 = $this->xmlRpcGet(array('validator1.countTheEntities' => array($string_2))); $this->assertIdentical($l_res_2, $r_res_2); - $struct_3 = array('moe' => mt_rand(-100, 100), 'larry' => mt_rand(-100, 100), 'curly' => mt_rand(-100, 100), 'homer' => mt_rand(-100, 100)); - $l_res_3 = xmlrpc_test_easyStructTest($struct_3); - $r_res_3 = xmlrpc($xml_url, array('validator1.easyStructTest' => array($struct_3))); + $struct_3 = array( + 'moe' => mt_rand(-100, 100), + 'larry' => mt_rand(-100, 100), + 'curly' => mt_rand(-100, 100), + 'homer' => mt_rand(-100, 100), + ); + $l_res_3 = xmlrpc_test_easy_struct_test($struct_3); + $r_res_3 = $this->xmlRpcGet(array('validator1.easyStructTest' => array($struct_3))); $this->assertIdentical($l_res_3, $r_res_3); - $struct_4 = array('sub1' => array('bar' => 13), - 'sub2' => 14, - 'sub3' => array('foo' => 1, 'baz' => 2), - 'sub4' => array('ss' => array('sss' => array('ssss' => 'sssss')))); - $l_res_4 = xmlrpc_test_echoStructTest($struct_4); - $r_res_4 = xmlrpc($xml_url, array('validator1.echoStructTest' => array($struct_4))); + $struct_4 = array( + 'sub1' => array('bar' => 13), + 'sub2' => 14, + 'sub3' => array('foo' => 1, 'baz' => 2), + 'sub4' => array('ss' => array('sss' => array('ssss' => 'sssss'))), + ); + $l_res_4 = xmlrpc_test_echo_struct_test($struct_4); + $r_res_4 = $this->xmlRpcGet(array('validator1.echoStructTest' => array($struct_4))); $this->assertIdentical($l_res_4, $r_res_4); $int_5 = mt_rand(-100, 100); @@ -64,10 +80,19 @@ class XmlRpcValidatorTest extends \DrupalWebTestCase { $double_5 = (double)(mt_rand(-1000, 1000) / 100); $time_5 = REQUEST_TIME; $base64_5 = $this->randomName(100); - $l_res_5 = xmlrpc_test_manyTypesTest($int_5, $bool_5, $string_5, $double_5, xmlrpc_date($time_5), $base64_5); + $l_res_5 = xmlrpc_test_many_types_test($int_5, $bool_5, $string_5, $double_5, xmlrpc_date($time_5), $base64_5); // See http://drupal.org/node/37766 why this currently fails $l_res_5[5] = $l_res_5[5]->data; - $r_res_5 = xmlrpc($xml_url, array('validator1.manyTypesTest' => array($int_5, $bool_5, $string_5, $double_5, xmlrpc_date($time_5), xmlrpc_base64($base64_5)))); + $r_res_5 = $this->xmlRpcGet(array( + 'validator1.manyTypesTest' => array( + $int_5, + $bool_5, + $string_5, + $double_5, + xmlrpc_date($time_5), + xmlrpc_base64($base64_5), + ), + )); // @todo Contains objects, objects are not equal. $this->assertEqual($l_res_5, $r_res_5); @@ -77,8 +102,8 @@ class XmlRpcValidatorTest extends \DrupalWebTestCase { $array_6[] = $this->randomName(mt_rand(8, 12)); } - $l_res_6 = xmlrpc_test_moderateSizeArrayCheck($array_6); - $r_res_6 = xmlrpc($xml_url, array('validator1.moderateSizeArrayCheck' => array($array_6))); + $l_res_6 = xmlrpc_test_moderate_size_array_check($array_6); + $r_res_6 = $this->xmlRpcGet(array('validator1.moderateSizeArrayCheck' => array($array_6))); $this->assertIdentical($l_res_6, $r_res_6); $struct_7 = array(); @@ -94,14 +119,13 @@ class XmlRpcValidatorTest extends \DrupalWebTestCase { } } } - $l_res_7 = xmlrpc_test_nestedStructTest($struct_7); - $r_res_7 = xmlrpc($xml_url, array('validator1.nestedStructTest' => array($struct_7))); + $l_res_7 = xmlrpc_test_nested_struct_test($struct_7); + $r_res_7 = $this->xmlRpcGet(array('validator1.nestedStructTest' => array($struct_7))); $this->assertIdentical($l_res_7, $r_res_7); - $int_8 = mt_rand(-100, 100); - $l_res_8 = xmlrpc_test_simpleStructReturnTest($int_8); - $r_res_8 = xmlrpc($xml_url, array('validator1.simpleStructReturnTest' => array($int_8))); + $l_res_8 = xmlrpc_test_simple_struct_return_test($int_8); + $r_res_8 = $this->xmlRpcGet(array('validator1.simpleStructReturnTest' => array($int_8))); $this->assertIdentical($l_res_8, $r_res_8); /* Now test multicall */ @@ -110,13 +134,30 @@ class XmlRpcValidatorTest extends \DrupalWebTestCase { $x['validator1.countTheEntities'] = array($string_2); $x['validator1.easyStructTest'] = array($struct_3); $x['validator1.echoStructTest'] = array($struct_4); - $x['validator1.manyTypesTest'] = array($int_5, $bool_5, $string_5, $double_5, xmlrpc_date($time_5), xmlrpc_base64($base64_5)); + $x['validator1.manyTypesTest'] = array( + $int_5, + $bool_5, + $string_5, + $double_5, + xmlrpc_date($time_5), + xmlrpc_base64($base64_5), + ); $x['validator1.moderateSizeArrayCheck'] = array($array_6); $x['validator1.nestedStructTest'] = array($struct_7); $x['validator1.simpleStructReturnTest'] = array($int_8); - $a_l_res = array($l_res_1, $l_res_2, $l_res_3, $l_res_4, $l_res_5, $l_res_6, $l_res_7, $l_res_8); - $a_r_res = xmlrpc($xml_url, $x); + $a_l_res = array( + $l_res_1, + $l_res_2, + $l_res_3, + $l_res_4, + $l_res_5, + $l_res_6, + $l_res_7, + $l_res_8, + ); + $a_r_res = $this->xmlRpcGet($x); $this->assertEqual($a_l_res, $a_r_res); } + } diff --git a/modules/simpletest/tests/xmlrpc_test/xmlrpc_test.module b/modules/simpletest/tests/xmlrpc_test/xmlrpc_test.module index db8f113..0a80759 100644 --- a/modules/simpletest/tests/xmlrpc_test/xmlrpc_test.module +++ b/modules/simpletest/tests/xmlrpc_test/xmlrpc_test.module @@ -1,6 +1,6 @@ substr_count($string, '<'), 'ctRightAngleBrackets' => substr_count($string, '>'), @@ -20,28 +20,28 @@ function xmlrpc_test_countTheEntities($string) { ); } -function xmlrpc_test_easyStructTest($array) { +function xmlrpc_test_easy_struct_test($array) { return $array["curly"] + $array["moe"] + $array["larry"]; } -function xmlrpc_test_echoStructTest($array) { +function xmlrpc_test_echo_struct_test($array) { return $array; } -function xmlrpc_test_manyTypesTest($number, $boolean, $string, $double, $dateTime, $base64) { +function xmlrpc_test_many_types_test($number, $boolean, $string, $double, $dateTime, $base64) { $timestamp = gmmktime($dateTime->hour, $dateTime->minute, $dateTime->second, $dateTime->month, $dateTime->day, $dateTime->year); return array($number, $boolean, $string, $double, xmlrpc_date($timestamp), xmlrpc_Base64($base64)); } -function xmlrpc_test_moderateSizeArrayCheck($array) { +function xmlrpc_test_moderate_size_array_check($array) { return array_shift($array) . array_pop($array); } -function xmlrpc_test_nestedStructTest($array) { +function xmlrpc_test_nested_struct_test($array) { return $array["2000"]["04"]["01"]["larry"] + $array["2000"]["04"]["01"]["moe"] + $array["2000"]["04"]["01"]["curly"]; } -function xmlrpc_test_simpleStructReturnTest($number) { +function xmlrpc_test_simple_struct_return_test($number) { return array("times10" => ($number*10), "times100" => ($number*100), "times1000" => ($number*1000)); }