PageRenderTime 98ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/cake/tests/cases/libs/http_socket.test.php

https://github.com/msadouni/cakephp2x
PHP | 1463 lines | 1000 code | 185 blank | 278 comment | 7 complexity | e516a7d2ec2542348bbbe7f16a282a87 MD5 | raw file
  1. <?php
  2. /**
  3. * HttpSocketTest file
  4. *
  5. * Long description for file
  6. *
  7. * PHP Version 5.x
  8. *
  9. * CakePHP(tm) Tests <https://trac.cakephp.org/wiki/Developement/TestSuite>
  10. * Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. *
  12. * Licensed under The Open Group Test Suite License
  13. * Redistributions of files must retain the above copyright notice.
  14. *
  15. * @copyright Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
  16. * @link https://trac.cakephp.org/wiki/Developement/TestSuite CakePHP(tm) Tests
  17. * @package cake
  18. * @subpackage cake.tests.cases.libs
  19. * @since CakePHP(tm) v 1.2.0.4206
  20. * @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
  21. */
  22. App::import('Core', 'HttpSocket');
  23. class TestHttpSocket extends HttpSocket {
  24. /**
  25. * Convenience method for testing protected method
  26. *
  27. * @param mixed $uri URI (see {@link _parseUri()})
  28. * @return array Current configuration settings
  29. */
  30. function configUri($uri = null) {
  31. return parent::_configUri($uri);
  32. }
  33. /**
  34. * Convenience method for testing protected method
  35. *
  36. * @param string $uri URI to parse
  37. * @param mixed $base If true use default URI config, otherwise indexed array to set 'scheme', 'host', 'port', etc.
  38. * @return array Parsed URI
  39. */
  40. function parseUri($uri = null, $base = array()) {
  41. return parent::_parseUri($uri, $base);
  42. }
  43. /**
  44. * Convenience method for testing protected method
  45. *
  46. * @param array $uri A $uri array, or uses $this->config if left empty
  47. * @param string $uriTemplate The Uri template/format to use
  48. * @return string A fully qualified URL formated according to $uriTemplate
  49. */
  50. function buildUri($uri = array(), $uriTemplate = '%scheme://%user:%pass@%host:%port/%path?%query#%fragment') {
  51. return parent::_buildUri($uri, $uriTemplate);
  52. }
  53. /**
  54. * Convenience method for testing protected method
  55. *
  56. * @param array $header Header to build
  57. * @return string Header built from array
  58. */
  59. function buildHeader($header, $mode = 'standard') {
  60. return parent::_buildHeader($header, $mode);
  61. }
  62. /**
  63. * Convenience method for testing protected method
  64. *
  65. * @param string $message Message to parse
  66. * @return array Parsed message (with indexed elements such as raw, status, header, body)
  67. */
  68. function parseResponse($message) {
  69. return parent::_parseResponse($message);
  70. }
  71. /**
  72. * Convenience method for testing protected method
  73. *
  74. * @param array $header Header as an indexed array (field => value)
  75. * @return array Parsed header
  76. */
  77. function parseHeader($header) {
  78. return parent::_parseHeader($header);
  79. }
  80. /**
  81. * Convenience method for testing protected method
  82. *
  83. * @param mixed $query A query string to parse into an array or an array to return directly "as is"
  84. * @return array The $query parsed into a possibly multi-level array. If an empty $query is given, an empty array is returned.
  85. */
  86. function parseQuery($query) {
  87. return parent::_parseQuery($query);
  88. }
  89. /**
  90. * Convenience method for testing protected method
  91. *
  92. * @param string $body A string continaing the body to decode
  93. * @param mixed $encoding Can be false in case no encoding is being used, or a string representing the encoding
  94. * @return mixed Array or false
  95. */
  96. function decodeBody($body, $encoding = 'chunked') {
  97. return parent::_decodeBody($body, $encoding);
  98. }
  99. /**
  100. * Convenience method for testing protected method
  101. *
  102. * @param string $body A string continaing the chunked body to decode
  103. * @return mixed Array or false
  104. */
  105. function decodeChunkedBody($body) {
  106. return parent::_decodeChunkedBody($body);
  107. }
  108. /**
  109. * Convenience method for testing protected method
  110. *
  111. * @param array $request Needs to contain a 'uri' key. Should also contain a 'method' key, otherwise defaults to GET.
  112. * @param string $versionToken The version token to use, defaults to HTTP/1.1
  113. * @return string Request line
  114. */
  115. function buildRequestLine($request = array(), $versionToken = 'HTTP/1.1') {
  116. return parent::_buildRequestLine($request, $versionToken);
  117. }
  118. /**
  119. * Convenience method for testing protected method
  120. *
  121. * @param boolean $hex true to get them as HEX values, false otherwise
  122. * @return array Escape chars
  123. */
  124. function tokenEscapeChars($hex = true, $chars = null) {
  125. return parent::_tokenEscapeChars($hex, $chars);
  126. }
  127. /**
  128. * Convenience method for testing protected method
  129. *
  130. * @param string $token Token to escape
  131. * @return string Escaped token
  132. */
  133. function EscapeToken($token, $chars = null) {
  134. return parent::_escapeToken($token, $chars);
  135. }
  136. /**
  137. * Convenience method for testing protected method
  138. *
  139. * @param string $token Token to unescape
  140. * @return string Unescaped token
  141. */
  142. function unescapeToken($token, $chars = null) {
  143. return parent::_unescapeToken($token, $chars);
  144. }
  145. }
  146. /**
  147. * HttpSocketTest class
  148. *
  149. * @package cake
  150. * @subpackage cake.tests.cases.libs
  151. */
  152. class HttpSocketTest extends CakeTestCase {
  153. /**
  154. * Socket property
  155. *
  156. * @var mixed null
  157. * @access public
  158. */
  159. var $Socket = null;
  160. /**
  161. * RequestSocket property
  162. *
  163. * @var mixed null
  164. * @access public
  165. */
  166. var $RequestSocket = null;
  167. /**
  168. * This function sets up a TestHttpSocket instance we are going to use for testing
  169. *
  170. * @access public
  171. * @return void
  172. */
  173. function setUp() {
  174. if (!class_exists('MockHttpSocket')) {
  175. Mock::generatePartial('TestHttpSocket', 'MockHttpSocket', array('read', 'write', 'connect'));
  176. Mock::generatePartial('TestHttpSocket', 'MockHttpSocketRequests', array('read', 'write', 'connect', 'request'));
  177. }
  178. $this->Socket = new MockHttpSocket();
  179. $this->RequestSocket = new MockHttpSocketRequests();
  180. }
  181. /**
  182. * We use this function to clean up after the test case was executed
  183. *
  184. * @access public
  185. * @return void
  186. */
  187. function tearDown() {
  188. unset($this->Socket, $this->RequestSocket);
  189. }
  190. /**
  191. * Test that HttpSocket::configUri works properly with different types of arguments
  192. *
  193. * @access public
  194. * @return void
  195. */
  196. function testConfigUri() {
  197. $this->Socket->reset();
  198. $r = $this->Socket->configUri('https://bob:secret@www.cakephp.org:23/?query=foo');
  199. $expected = array(
  200. 'persistent' => false,
  201. 'host' => 'www.cakephp.org',
  202. 'protocol' => 'tcp',
  203. 'port' => 23,
  204. 'timeout' => 30,
  205. 'request' => array(
  206. 'uri' => array(
  207. 'scheme' => 'https',
  208. 'host' => 'www.cakephp.org',
  209. 'port' => 23
  210. ),
  211. 'auth' => array(
  212. 'method' => 'Basic',
  213. 'user' => 'bob',
  214. 'pass' => 'secret'
  215. ),
  216. 'cookies' => array(),
  217. )
  218. );
  219. $this->assertIdentical($this->Socket->config, $expected);
  220. $this->assertIdentical($r, $expected);
  221. $r = $this->Socket->configUri(array('host' => 'www.foo-bar.org'));
  222. $expected['host'] = 'www.foo-bar.org';
  223. $expected['request']['uri']['host'] = 'www.foo-bar.org';
  224. $this->assertIdentical($this->Socket->config, $expected);
  225. $this->assertIdentical($r, $expected);
  226. $r = $this->Socket->configUri('http://www.foo.com');
  227. $expected = array(
  228. 'persistent' => false,
  229. 'host' => 'www.foo.com',
  230. 'protocol' => 'tcp',
  231. 'port' => 80,
  232. 'timeout' => 30,
  233. 'request' => array(
  234. 'uri' => array(
  235. 'scheme' => 'http',
  236. 'host' => 'www.foo.com',
  237. 'port' => 80
  238. ),
  239. 'auth' => array(
  240. 'method' => 'Basic',
  241. 'user' => null,
  242. 'pass' => null
  243. ),
  244. 'cookies' => array()
  245. )
  246. );
  247. $this->assertIdentical($this->Socket->config, $expected);
  248. $this->assertIdentical($r, $expected);
  249. $r = $this->Socket->configUri('/this-is-broken');
  250. $this->assertIdentical($this->Socket->config, $expected);
  251. $this->assertIdentical($r, false);
  252. $r = $this->Socket->configUri(false);
  253. $this->assertIdentical($this->Socket->config, $expected);
  254. $this->assertIdentical($r, false);
  255. }
  256. /**
  257. * Tests that HttpSocket::request (the heart of the HttpSocket) is working properly.
  258. *
  259. * @access public
  260. * @return void
  261. */
  262. function testRequest() {
  263. $this->Socket->reset();
  264. $response = $this->Socket->request(true);
  265. $this->assertFalse($response);
  266. $tests = array(
  267. 0 => array(
  268. 'request' => 'http://www.cakephp.org/?foo=bar',
  269. 'expectation' => array(
  270. 'config' => array(
  271. 'persistent' => false,
  272. 'host' => 'www.cakephp.org',
  273. 'protocol' => 'tcp',
  274. 'port' => 80,
  275. 'timeout' => 30,
  276. 'request' => array(
  277. 'uri' => array (
  278. 'scheme' => 'http',
  279. 'host' => 'www.cakephp.org',
  280. 'port' => 80,
  281. ),
  282. 'auth' => array(
  283. 'method' => 'Basic',
  284. 'user' => null,
  285. 'pass' => null
  286. ),
  287. 'cookies' => array(),
  288. ),
  289. ),
  290. 'request' => array(
  291. 'method' => 'GET',
  292. 'uri' => array(
  293. 'scheme' => 'http',
  294. 'host' => 'www.cakephp.org',
  295. 'port' => 80,
  296. 'user' => null,
  297. 'pass' => null,
  298. 'path' => '/',
  299. 'query' => array('foo' => 'bar'),
  300. 'fragment' => null
  301. ),
  302. 'auth' => array(
  303. 'method' => 'Basic',
  304. 'user' => null,
  305. 'pass' => null
  306. ),
  307. 'version' => '1.1',
  308. 'body' => '',
  309. 'line' => "GET /?foo=bar HTTP/1.1\r\n",
  310. 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n",
  311. 'raw' => "",
  312. 'cookies' => array()
  313. )
  314. )
  315. ),
  316. 1 => array(
  317. 'request' => array(
  318. 'uri' => array(
  319. 'host' => 'www.cakephp.org',
  320. 'query' => '?foo=bar'
  321. )
  322. )
  323. ),
  324. 2 => array(
  325. 'request' => 'www.cakephp.org/?foo=bar'
  326. ),
  327. 3 => array(
  328. 'request' => array('host' => '192.168.0.1', 'uri' => 'http://www.cakephp.org/?foo=bar'),
  329. 'expectation' => array(
  330. 'request' => array(
  331. 'uri' => array('host' => 'www.cakephp.org')
  332. ),
  333. 'config' => array(
  334. 'request' => array(
  335. 'uri' => array('host' => 'www.cakephp.org')
  336. ),
  337. 'host' => '192.168.0.1'
  338. )
  339. )
  340. ),
  341. 'reset4' => array(
  342. 'request.uri.query' => array()
  343. ),
  344. 4 => array(
  345. 'request' => array('header' => array('Foo@woo' => 'bar-value')),
  346. 'expectation' => array(
  347. 'request' => array(
  348. 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nFoo\"@\"woo: bar-value\r\n",
  349. 'line' => "GET / HTTP/1.1\r\n"
  350. )
  351. )
  352. ),
  353. 5 => array(
  354. 'request' => array('header' => array('Foo@woo' => 'bar-value', 'host' => 'foo.com'), 'uri' => 'http://www.cakephp.org/'),
  355. 'expectation' => array(
  356. 'request' => array(
  357. 'header' => "Host: foo.com\r\nConnection: close\r\nUser-Agent: CakePHP\r\nFoo\"@\"woo: bar-value\r\n"
  358. ),
  359. 'config' => array(
  360. 'host' => 'www.cakephp.org'
  361. )
  362. )
  363. ),
  364. 6 => array(
  365. 'request' => array('header' => "Foo: bar\r\n"),
  366. 'expectation' => array(
  367. 'request' => array(
  368. 'header' => "Foo: bar\r\n"
  369. )
  370. )
  371. ),
  372. 7 => array(
  373. 'request' => array('header' => "Foo: bar\r\n", 'uri' => 'http://www.cakephp.org/search?q=http_socket#ignore-me'),
  374. 'expectation' => array(
  375. 'request' => array(
  376. 'uri' => array(
  377. 'path' => '/search',
  378. 'query' => array('q' => 'http_socket'),
  379. 'fragment' => 'ignore-me'
  380. ),
  381. 'line' => "GET /search?q=http_socket HTTP/1.1\r\n"
  382. )
  383. )
  384. ),
  385. 'reset8' => array(
  386. 'request.uri.query' => array()
  387. ),
  388. 8 => array(
  389. 'request' => array('method' => 'POST', 'uri' => 'http://www.cakephp.org/posts/add', 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today')),
  390. 'expectation' => array(
  391. 'request' => array(
  392. 'method' => 'POST',
  393. 'uri' => array(
  394. 'path' => '/posts/add',
  395. 'fragment' => null
  396. ),
  397. 'body' => "name=HttpSocket-is-released&date=today",
  398. 'line' => "POST /posts/add HTTP/1.1\r\n",
  399. 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\n",
  400. 'raw' => "name=HttpSocket-is-released&date=today"
  401. )
  402. )
  403. ),
  404. 9 => array(
  405. 'request' => array('method' => 'POST', 'uri' => 'https://www.cakephp.org/posts/add', 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today')),
  406. 'expectation' => array(
  407. 'config' => array(
  408. 'port' => 443,
  409. 'request' => array(
  410. 'uri' => array(
  411. 'scheme' => 'https',
  412. 'port' => 443
  413. )
  414. )
  415. ),
  416. 'request' => array(
  417. 'uri' => array(
  418. 'scheme' => 'https',
  419. 'port' => 443
  420. )
  421. )
  422. )
  423. ),
  424. 10 => array(
  425. 'request' => array(
  426. 'method' => 'POST',
  427. 'uri' => 'https://www.cakephp.org/posts/add',
  428. 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today'),
  429. 'cookies' => array('foo' => array('value' => 'bar'))
  430. ),
  431. 'expectation' => array(
  432. 'request' => array(
  433. 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\nCookie: foo=bar\r\n",
  434. 'cookies' => array(
  435. 'foo' => array('value' => 'bar'),
  436. )
  437. )
  438. )
  439. )
  440. );
  441. $expectation = array();
  442. foreach ($tests as $i => $test) {
  443. if (strpos($i, 'reset') === 0) {
  444. foreach ($test as $path => $val) {
  445. $expectation = Set::insert($expectation, $path, $val);
  446. }
  447. continue;
  448. }
  449. if (isset($test['expectation'])) {
  450. $expectation = Set::merge($expectation, $test['expectation']);
  451. }
  452. $this->Socket->request($test['request']);
  453. $raw = $expectation['request']['raw'];
  454. $expectation['request']['raw'] = $expectation['request']['line'].$expectation['request']['header']."\r\n".$raw;
  455. $r = array('config' => $this->Socket->config, 'request' => $this->Socket->request);
  456. $v = $this->assertIdentical($r, $expectation, '%s in test #'.$i.' ');
  457. $expectation['request']['raw'] = $raw;
  458. }
  459. $this->Socket->reset();
  460. $request = array('method' => 'POST', 'uri' => 'http://www.cakephp.org/posts/add', 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today'));
  461. $response = $this->Socket->request($request);
  462. $this->assertIdentical($this->Socket->request['body'], "name=HttpSocket-is-released&date=today");
  463. $request = array('uri' => '*', 'method' => 'GET');
  464. $this->expectError(new PatternExpectation('/activate quirks mode/i'));
  465. $response = $this->Socket->request($request);
  466. $this->assertFalse($response);
  467. $this->assertFalse($this->Socket->response);
  468. $this->Socket->reset();
  469. $request = array('uri' => 'htpp://www.cakephp.org/');
  470. $this->Socket->setReturnValue('connect', true);
  471. $this->Socket->setReturnValue('read', false);
  472. $this->Socket->_mock->_call_counts['read'] = 0;
  473. $number = mt_rand(0, 9999999);
  474. $serverResponse = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n<h1>Hello, your lucky number is " . $number . "</h1>";
  475. $this->Socket->setReturnValueAt(0, 'read', $serverResponse);
  476. $this->Socket->expect('write', array("GET / HTTP/1.1\r\nHost: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n\r\n"));
  477. $response = $this->Socket->request($request);
  478. $this->assertIdentical($response, "<h1>Hello, your lucky number is " . $number . "</h1>");
  479. $this->Socket->reset();
  480. $serverResponse = "HTTP/1.x 200 OK\r\nSet-Cookie: foo=bar\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n<h1>This is a cookie test!</h1>";
  481. unset($this->Socket->_mock->_actions->_at['read']);
  482. unset($this->Socket->_mock->_return_sequence['read']);
  483. $this->Socket->_mock->_call_counts['read'] = 0;
  484. $this->Socket->setReturnValueAt(0, 'read', $serverResponse);
  485. $this->Socket->reset();
  486. $this->Socket->request($request);
  487. $result = $this->Socket->response['cookies'];
  488. $expect = array(
  489. 'foo' => array(
  490. 'value' => 'bar'
  491. )
  492. );
  493. $this->assertEqual($result, $expect);
  494. $this->assertEqual($this->Socket->config['request']['cookies'], $expect);
  495. $this->assertFalse($this->Socket->isConnected());
  496. }
  497. /**
  498. * testUrl method
  499. *
  500. * @access public
  501. * @return void
  502. */
  503. function testUrl() {
  504. $this->Socket->reset(true);
  505. $this->assertIdentical($this->Socket->url(true), false);
  506. $url = $this->Socket->url('www.cakephp.org');
  507. $this->assertIdentical($url, 'http://www.cakephp.org/');
  508. $url = $this->Socket->url('https://www.cakephp.org/posts/add');
  509. $this->assertIdentical($url, 'https://www.cakephp.org/posts/add');
  510. $url = $this->Socket->url('http://www.cakephp/search?q=socket', '/%path?%query');
  511. $this->assertIdentical($url, '/search?q=socket');
  512. $this->Socket->config['request']['uri']['host'] = 'bakery.cakephp.org';
  513. $url = $this->Socket->url();
  514. $this->assertIdentical($url, 'http://bakery.cakephp.org/');
  515. $this->Socket->configUri('http://www.cakephp.org');
  516. $url = $this->Socket->url('/search?q=bar');
  517. $this->assertIdentical($url, 'http://www.cakephp.org/search?q=bar');
  518. $url = $this->Socket->url(array('host' => 'www.foobar.org', 'query' => array('q' => 'bar')));
  519. $this->assertIdentical($url, 'http://www.foobar.org/?q=bar');
  520. $url = $this->Socket->url(array('path' => '/supersearch', 'query' => array('q' => 'bar')));
  521. $this->assertIdentical($url, 'http://www.cakephp.org/supersearch?q=bar');
  522. $this->Socket->configUri('http://www.google.com');
  523. $url = $this->Socket->url('/search?q=socket');
  524. $this->assertIdentical($url, 'http://www.google.com/search?q=socket');
  525. $url = $this->Socket->url();
  526. $this->assertIdentical($url, 'http://www.google.com/');
  527. $this->Socket->configUri('https://www.google.com');
  528. $url = $this->Socket->url('/search?q=socket');
  529. $this->assertIdentical($url, 'https://www.google.com/search?q=socket');
  530. $this->Socket->reset();
  531. $this->Socket->configUri('www.google.com:443');
  532. $url = $this->Socket->url('/search?q=socket');
  533. $this->assertIdentical($url, 'https://www.google.com/search?q=socket');
  534. $this->Socket->reset();
  535. $this->Socket->configUri('www.google.com:8080');
  536. $url = $this->Socket->url('/search?q=socket');
  537. $this->assertIdentical($url, 'http://www.google.com:8080/search?q=socket');
  538. }
  539. /**
  540. * testGet method
  541. *
  542. * @access public
  543. * @return void
  544. */
  545. function testGet() {
  546. $this->RequestSocket->reset();
  547. $this->RequestSocket->expect('request', a(array('method' => 'GET', 'uri' => 'http://www.google.com/')));
  548. $this->RequestSocket->get('http://www.google.com/');
  549. $this->RequestSocket->expect('request', a(array('method' => 'GET', 'uri' => 'http://www.google.com/?foo=bar')));
  550. $this->RequestSocket->get('http://www.google.com/', array('foo' => 'bar'));
  551. $this->RequestSocket->expect('request', a(array('method' => 'GET', 'uri' => 'http://www.google.com/?foo=bar')));
  552. $this->RequestSocket->get('http://www.google.com/', 'foo=bar');
  553. $this->RequestSocket->expect('request', a(array('method' => 'GET', 'uri' => 'http://www.google.com/?foo=23&foobar=42')));
  554. $this->RequestSocket->get('http://www.google.com/?foo=bar', array('foobar' => '42', 'foo' => '23'));
  555. $this->RequestSocket->expect('request', a(array('method' => 'GET', 'uri' => 'http://www.google.com/', 'auth' => array('user' => 'foo', 'pass' => 'bar'))));
  556. $this->RequestSocket->get('http://www.google.com/', null, array('auth' => array('user' => 'foo', 'pass' => 'bar')));
  557. }
  558. /**
  559. * testPostPutDelete method
  560. *
  561. * @access public
  562. * @return void
  563. */
  564. function testPostPutDelete() {
  565. $this->RequestSocket->reset();
  566. foreach (array('POST', 'PUT', 'DELETE') as $method) {
  567. $this->RequestSocket->expect('request', a(array('method' => $method, 'uri' => 'http://www.google.com/', 'body' => array())));
  568. $this->RequestSocket->{strtolower($method)}('http://www.google.com/');
  569. $this->RequestSocket->expect('request', a(array('method' => $method, 'uri' => 'http://www.google.com/', 'body' => array('Foo' => 'bar'))));
  570. $this->RequestSocket->{strtolower($method)}('http://www.google.com/', array('Foo' => 'bar'));
  571. $this->RequestSocket->expect('request', a(array('method' => $method, 'uri' => 'http://www.google.com/', 'body' => null, 'line' => 'Hey Server')));
  572. $this->RequestSocket->{strtolower($method)}('http://www.google.com/', null, array('line' => 'Hey Server'));
  573. }
  574. }
  575. /**
  576. * testParseResponse method
  577. *
  578. * @access public
  579. * @return void
  580. */
  581. function testParseResponse() {
  582. $this->Socket->reset();
  583. $r = $this->Socket->parseResponse(array('foo' => 'bar'));
  584. $this->assertIdentical($r, array('foo' => 'bar'));
  585. $r = $this->Socket->parseResponse(true);
  586. $this->assertIdentical($r, false);
  587. $r = $this->Socket->parseResponse("HTTP Foo\r\nBar: La");
  588. $this->assertIdentical($r, false);
  589. $tests = array(
  590. 'simple-request' => array(
  591. 'response' => array(
  592. 'status-line' => "HTTP/1.x 200 OK\r\n",
  593. 'header' => "Date: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\n",
  594. 'body' => "<h1>Hello World</h1>\r\n<p>It's good to be html</p>"
  595. )
  596. , 'expectations' => array(
  597. 'status.http-version' => 'HTTP/1.x',
  598. 'status.code' => 200,
  599. 'status.reason-phrase' => 'OK',
  600. 'header' => $this->Socket->parseHeader("Date: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\n"),
  601. 'body' => "<h1>Hello World</h1>\r\n<p>It's good to be html</p>"
  602. )
  603. ),
  604. 'no-header' => array(
  605. 'response' => array(
  606. 'status-line' => "HTTP/1.x 404 OK\r\n",
  607. 'header' => null,
  608. )
  609. , 'expectations' => array(
  610. 'status.code' => 404,
  611. 'header' => array()
  612. )
  613. ),
  614. 'chunked' => array(
  615. 'response' => array(
  616. 'header' => "Transfer-Encoding: chunked\r\n",
  617. 'body' => "19\r\nThis is a chunked message\r\n0\r\n"
  618. ),
  619. 'expectations' => array(
  620. 'body' => "This is a chunked message",
  621. 'header' => $this->Socket->parseHeader("Transfer-Encoding: chunked\r\n")
  622. )
  623. ),
  624. 'enitity-header' => array(
  625. 'response' => array(
  626. 'body' => "19\r\nThis is a chunked message\r\n0\r\nFoo: Bar\r\n"
  627. ),
  628. 'expectations' => array(
  629. 'header' => $this->Socket->parseHeader("Transfer-Encoding: chunked\r\nFoo: Bar\r\n")
  630. )
  631. ),
  632. 'enitity-header-combine' => array(
  633. 'response' => array(
  634. 'header' => "Transfer-Encoding: chunked\r\nFoo: Foobar\r\n"
  635. ),
  636. 'expectations' => array(
  637. 'header' => $this->Socket->parseHeader("Transfer-Encoding: chunked\r\nFoo: Foobar\r\nFoo: Bar\r\n")
  638. )
  639. )
  640. );
  641. $testResponse = array();
  642. $expectations = array();
  643. foreach ($tests as $name => $test) {
  644. $testResponse = array_merge($testResponse, $test['response']);
  645. $testResponse['response'] = $testResponse['status-line'].$testResponse['header']."\r\n".$testResponse['body'];
  646. $r = $this->Socket->parseResponse($testResponse['response']);
  647. $expectations = array_merge($expectations, $test['expectations']);
  648. foreach ($expectations as $property => $expectedVal) {
  649. $val = Set::extract($r, $property);
  650. $this->assertIdentical($val, $expectedVal, 'Test "'.$name.'": response.'.$property.' - %s');
  651. }
  652. foreach (array('status-line', 'header', 'body', 'response') as $field) {
  653. $this->assertIdentical($r['raw'][$field], $testResponse[$field], 'Test response.raw.'.$field.': %s');
  654. }
  655. }
  656. }
  657. /**
  658. * testDecodeBody method
  659. *
  660. * @access public
  661. * @return void
  662. */
  663. function testDecodeBody() {
  664. $this->Socket->reset();
  665. $r = $this->Socket->decodeBody(true);
  666. $this->assertIdentical($r, false);
  667. $r = $this->Socket->decodeBody('Foobar', false);
  668. $this->assertIdentical($r, array('body' => 'Foobar', 'header' => false));
  669. $encodings = array(
  670. 'chunked' => array(
  671. 'encoded' => "19\r\nThis is a chunked message\r\n0\r\n",
  672. 'decoded' => array('body' => "This is a chunked message", 'header' => false)
  673. ),
  674. 'foo-coded' => array(
  675. 'encoded' => '!Foobar!',
  676. 'decoded' => array('body' => '!Foobar!', 'header' => false),
  677. 'error' => new PatternExpectation('/unknown encoding: foo-coded/i')
  678. )
  679. );
  680. foreach ($encodings as $encoding => $sample) {
  681. if (isset($sample['error'])) {
  682. $this->expectError($sample['error']);
  683. }
  684. $r = $this->Socket->decodeBody($sample['encoded'], $encoding);
  685. $this->assertIdentical($r, $sample['decoded']);
  686. if (isset($sample['error'])) {
  687. $this->Socket->quirksMode = true;
  688. $r = $this->Socket->decodeBody($sample['encoded'], $encoding);
  689. $this->assertIdentical($r, $sample['decoded']);
  690. $this->Socket->quirksMode = false;
  691. }
  692. }
  693. }
  694. /**
  695. * testDecodeChunkedBody method
  696. *
  697. * @access public
  698. * @return void
  699. */
  700. function testDecodeChunkedBody() {
  701. $this->Socket->reset();
  702. $r = $this->Socket->decodeChunkedBody(true);
  703. $this->assertIdentical($r, false);
  704. $encoded = "19\r\nThis is a chunked message\r\n0\r\n";
  705. $decoded = "This is a chunked message";
  706. $r = $this->Socket->decodeChunkedBody($encoded);
  707. $this->assertIdentical($r['body'], $decoded);
  708. $this->assertIdentical($r['header'], false);
  709. $encoded = "19 \r\nThis is a chunked message\r\n0\r\n";
  710. $r = $this->Socket->decodeChunkedBody($encoded);
  711. $this->assertIdentical($r['body'], $decoded);
  712. $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n0\r\n";
  713. $decoded = "This is a chunked message\nThat is cool\n";
  714. $r = $this->Socket->decodeChunkedBody($encoded);
  715. $this->assertIdentical($r['body'], $decoded);
  716. $this->assertIdentical($r['header'], false);
  717. $encoded = "19\r\nThis is a chunked message\r\nE;foo-chunk=5\r\n\nThat is cool\n\r\n0\r\n";
  718. $r = $this->Socket->decodeChunkedBody($encoded);
  719. $this->assertIdentical($r['body'], $decoded);
  720. $this->assertIdentical($r['header'], false);
  721. $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n0\r\nfoo-header: bar\r\ncake: PHP\r\n\r\n";
  722. $r = $this->Socket->decodeChunkedBody($encoded);
  723. $this->assertIdentical($r['body'], $decoded);
  724. $this->assertIdentical($r['header'], array('Foo-Header' => 'bar', 'Cake' => 'PHP'));
  725. $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n";
  726. $this->expectError(new PatternExpectation('/activate quirks mode/i'));
  727. $r = $this->Socket->decodeChunkedBody($encoded);
  728. $this->assertIdentical($r, false);
  729. $this->Socket->quirksMode = true;
  730. $r = $this->Socket->decodeChunkedBody($encoded);
  731. $this->assertIdentical($r['body'], $decoded);
  732. $this->assertIdentical($r['header'], false);
  733. $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\nfoo-header: bar\r\ncake: PHP\r\n\r\n";
  734. $r = $this->Socket->decodeChunkedBody($encoded);
  735. $this->assertIdentical($r['body'], $decoded);
  736. $this->assertIdentical($r['header'], array('Foo-Header' => 'bar', 'Cake' => 'PHP'));
  737. }
  738. /**
  739. * testBuildRequestLine method
  740. *
  741. * @access public
  742. * @return void
  743. */
  744. function testBuildRequestLine() {
  745. $this->Socket->reset();
  746. $this->expectError(new PatternExpectation('/activate quirks mode/i'));
  747. $r = $this->Socket->buildRequestLine('Foo');
  748. $this->assertIdentical($r, false);
  749. $this->Socket->quirksMode = true;
  750. $r = $this->Socket->buildRequestLine('Foo');
  751. $this->assertIdentical($r, 'Foo');
  752. $this->Socket->quirksMode = false;
  753. $r = $this->Socket->buildRequestLine(true);
  754. $this->assertIdentical($r, false);
  755. $r = $this->Socket->buildRequestLine(array('foo' => 'bar', 'method' => 'foo'));
  756. $this->assertIdentical($r, false);
  757. $r = $this->Socket->buildRequestLine(array('method' => 'GET', 'uri' => 'http://www.cakephp.org/search?q=socket'));
  758. $this->assertIdentical($r, "GET /search?q=socket HTTP/1.1\r\n");
  759. $request = array(
  760. 'method' => 'GET',
  761. 'uri' => array(
  762. 'path' => '/search',
  763. 'query' => array('q' => 'socket')
  764. )
  765. );
  766. $r = $this->Socket->buildRequestLine($request);
  767. $this->assertIdentical($r, "GET /search?q=socket HTTP/1.1\r\n");
  768. unset($request['method']);
  769. $r = $this->Socket->buildRequestLine($request);
  770. $this->assertIdentical($r, "GET /search?q=socket HTTP/1.1\r\n");
  771. $r = $this->Socket->buildRequestLine($request, 'CAKE-HTTP/0.1');
  772. $this->assertIdentical($r, "GET /search?q=socket CAKE-HTTP/0.1\r\n");
  773. $request = array('method' => 'OPTIONS', 'uri' => '*');
  774. $r = $this->Socket->buildRequestLine($request);
  775. $this->assertIdentical($r, "OPTIONS * HTTP/1.1\r\n");
  776. $request['method'] = 'GET';
  777. $this->expectError(new PatternExpectation('/activate quirks mode/i'));
  778. $r = $this->Socket->buildRequestLine($request);
  779. $this->assertIdentical($r, false);
  780. $this->expectError(new PatternExpectation('/activate quirks mode/i'));
  781. $r = $this->Socket->buildRequestLine("GET * HTTP/1.1\r\n");
  782. $this->assertIdentical($r, false);
  783. $this->Socket->quirksMode = true;
  784. $r = $this->Socket->buildRequestLine($request);
  785. $this->assertIdentical($r, "GET * HTTP/1.1\r\n");
  786. $r = $this->Socket->buildRequestLine("GET * HTTP/1.1\r\n");
  787. $this->assertIdentical($r, "GET * HTTP/1.1\r\n");
  788. }
  789. /**
  790. * Asserts that HttpSocket::parseUri is working properly
  791. *
  792. * @access public
  793. * @return void
  794. */
  795. function testParseUri() {
  796. $this->Socket->reset();
  797. $uri = $this->Socket->parseUri(array('invalid' => 'uri-string'));
  798. $this->assertIdentical($uri, false);
  799. $uri = $this->Socket->parseUri(array('invalid' => 'uri-string'), array('host' => 'somehost'));
  800. $this->assertIdentical($uri, array('host' => 'somehost', 'invalid' => 'uri-string'));
  801. $uri = $this->Socket->parseUri(false);
  802. $this->assertIdentical($uri, false);
  803. $uri = $this->Socket->parseUri('/my-cool-path');
  804. $this->assertIdentical($uri, array('path' => '/my-cool-path'));
  805. $uri = $this->Socket->parseUri('http://bob:foo123@www.cakephp.org:40/search?q=dessert#results');
  806. $this->assertIdentical($uri, array(
  807. 'scheme' => 'http',
  808. 'host' => 'www.cakephp.org',
  809. 'port' => 40,
  810. 'user' => 'bob',
  811. 'pass' => 'foo123',
  812. 'path' => '/search',
  813. 'query' => array('q' => 'dessert'),
  814. 'fragment' => 'results'
  815. ));
  816. $uri = $this->Socket->parseUri('http://www.cakephp.org/');
  817. $this->assertIdentical($uri, array(
  818. 'scheme' => 'http',
  819. 'host' => 'www.cakephp.org',
  820. 'path' => '/',
  821. ));
  822. $uri = $this->Socket->parseUri('http://www.cakephp.org', true);
  823. $this->assertIdentical($uri, array(
  824. 'scheme' => 'http',
  825. 'host' => 'www.cakephp.org',
  826. 'port' => 80,
  827. 'user' => null,
  828. 'pass' => null,
  829. 'path' => '/',
  830. 'query' => array(),
  831. 'fragment' => null
  832. ));
  833. $uri = $this->Socket->parseUri('https://www.cakephp.org', true);
  834. $this->assertIdentical($uri, array(
  835. 'scheme' => 'https',
  836. 'host' => 'www.cakephp.org',
  837. 'port' => 443,
  838. 'user' => null,
  839. 'pass' => null,
  840. 'path' => '/',
  841. 'query' => array(),
  842. 'fragment' => null
  843. ));
  844. $uri = $this->Socket->parseUri('www.cakephp.org:443/query?foo', true);
  845. $this->assertIdentical($uri, array(
  846. 'scheme' => 'https',
  847. 'host' => 'www.cakephp.org',
  848. 'port' => 443,
  849. 'user' => null,
  850. 'pass' => null,
  851. 'path' => '/query',
  852. 'query' => array('foo' => ""),
  853. 'fragment' => null
  854. ));
  855. $uri = $this->Socket->parseUri('http://www.cakephp.org', array('host' => 'piephp.org', 'user' => 'bob', 'fragment' => 'results'));
  856. $this->assertIdentical($uri, array(
  857. 'host' => 'www.cakephp.org',
  858. 'user' => 'bob',
  859. 'fragment' => 'results',
  860. 'scheme' => 'http'
  861. ));
  862. $uri = $this->Socket->parseUri('https://www.cakephp.org', array('scheme' => 'http', 'port' => 23));
  863. $this->assertIdentical($uri, array(
  864. 'scheme' => 'https',
  865. 'port' => 23,
  866. 'host' => 'www.cakephp.org'
  867. ));
  868. $uri = $this->Socket->parseUri('www.cakephp.org:59', array('scheme' => array('http', 'https'), 'port' => 80));
  869. $this->assertIdentical($uri, array(
  870. 'scheme' => 'http',
  871. 'port' => 59,
  872. 'host' => 'www.cakephp.org'
  873. ));
  874. $uri = $this->Socket->parseUri(array('scheme' => 'http', 'host' => 'www.google.com', 'port' => 8080), array('scheme' => array('http', 'https'), 'host' => 'www.google.com', 'port' => array(80, 443)));
  875. $this->assertIdentical($uri, array(
  876. 'scheme' => 'http',
  877. 'host' => 'www.google.com',
  878. 'port' => 8080,
  879. ));
  880. $uri = $this->Socket->parseUri('http://www.cakephp.org/?param1=value1&param2=value2%3Dvalue3');
  881. $this->assertIdentical($uri, array(
  882. 'scheme' => 'http',
  883. 'host' => 'www.cakephp.org',
  884. 'path' => '/',
  885. 'query' => array(
  886. 'param1' => 'value1',
  887. 'param2' => 'value2=value3'
  888. )
  889. ));
  890. $uri = $this->Socket->parseUri('http://www.cakephp.org/?param1=value1&param2=value2=value3');
  891. $this->assertIdentical($uri, array(
  892. 'scheme' => 'http',
  893. 'host' => 'www.cakephp.org',
  894. 'path' => '/',
  895. 'query' => array(
  896. 'param1' => 'value1',
  897. 'param2' => 'value2=value3'
  898. )
  899. ));
  900. }
  901. /**
  902. * Tests that HttpSocket::buildUri can turn all kinds of uri arrays (and strings) into fully or partially qualified URI's
  903. *
  904. * @access public
  905. * @return void
  906. */
  907. function testBuildUri() {
  908. $this->Socket->reset();
  909. $r = $this->Socket->buildUri(true);
  910. $this->assertIdentical($r, false);
  911. $r = $this->Socket->buildUri('foo.com');
  912. $this->assertIdentical($r, 'http://foo.com/');
  913. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org'));
  914. $this->assertIdentical($r, 'http://www.cakephp.org/');
  915. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'scheme' => 'https'));
  916. $this->assertIdentical($r, 'https://www.cakephp.org/');
  917. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'port' => 23));
  918. $this->assertIdentical($r, 'http://www.cakephp.org:23/');
  919. $r = $this->Socket->buildUri(array('path' => 'www.google.com/search', 'query' => 'q=cakephp'));
  920. $this->assertIdentical($r, 'http://www.google.com/search?q=cakephp');
  921. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'scheme' => 'https', 'port' => 79));
  922. $this->assertIdentical($r, 'https://www.cakephp.org:79/');
  923. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'path' => 'foo'));
  924. $this->assertIdentical($r, 'http://www.cakephp.org/foo');
  925. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'path' => '/foo'));
  926. $this->assertIdentical($r, 'http://www.cakephp.org/foo');
  927. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'path' => '/search', 'query' => array('q' => 'HttpSocket')));
  928. $this->assertIdentical($r, 'http://www.cakephp.org/search?q=HttpSocket');
  929. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'fragment' => 'bar'));
  930. $this->assertIdentical($r, 'http://www.cakephp.org/#bar');
  931. $r = $this->Socket->buildUri(array(
  932. 'scheme' => 'https',
  933. 'host' => 'www.cakephp.org',
  934. 'port' => 25,
  935. 'user' => 'bob',
  936. 'pass' => 'secret',
  937. 'path' => '/cool',
  938. 'query' => array('foo' => 'bar'),
  939. 'fragment' => 'comment'
  940. ));
  941. $this->assertIdentical($r, 'https://bob:secret@www.cakephp.org:25/cool?foo=bar#comment');
  942. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'fragment' => 'bar'), '%fragment?%host');
  943. $this->assertIdentical($r, 'bar?www.cakephp.org');
  944. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org'), '%fragment???%host');
  945. $this->assertIdentical($r, '???www.cakephp.org');
  946. $r = $this->Socket->buildUri(array('path' => '*'), '/%path?%query');
  947. $this->assertIdentical($r, '*');
  948. $r = $this->Socket->buildUri(array('scheme' => 'foo', 'host' => 'www.cakephp.org'));
  949. $this->assertIdentical($r, 'foo://www.cakephp.org:80/');
  950. }
  951. /**
  952. * Asserts that HttpSocket::parseQuery is working properly
  953. *
  954. * @access public
  955. * @return void
  956. */
  957. function testParseQuery() {
  958. $this->Socket->reset();
  959. $query = $this->Socket->parseQuery(array('framework' => 'cakephp'));
  960. $this->assertIdentical($query, array('framework' => 'cakephp'));
  961. $query = $this->Socket->parseQuery('');
  962. $this->assertIdentical($query, array());
  963. $query = $this->Socket->parseQuery('framework=cakephp');
  964. $this->assertIdentical($query, array('framework' => 'cakephp'));
  965. $query = $this->Socket->parseQuery('?framework=cakephp');
  966. $this->assertIdentical($query, array('framework' => 'cakephp'));
  967. $query = $this->Socket->parseQuery('a&b&c');
  968. $this->assertIdentical($query, array('a' => '', 'b' => '', 'c' => ''));
  969. $query = $this->Socket->parseQuery('value=12345');
  970. $this->assertIdentical($query, array('value' => '12345'));
  971. $query = $this->Socket->parseQuery('a[0]=foo&a[1]=bar&a[2]=cake');
  972. $this->assertIdentical($query, array('a' => array(0 => 'foo', 1 => 'bar', 2 => 'cake')));
  973. $query = $this->Socket->parseQuery('a[]=foo&a[]=bar&a[]=cake');
  974. $this->assertIdentical($query, array('a' => array(0 => 'foo', 1 => 'bar', 2 => 'cake')));
  975. $query = $this->Socket->parseQuery('a]][[=foo&[]=bar&]]][]=cake');
  976. $this->assertIdentical($query, array('a]][[' => 'foo', 0 => 'bar', ']]]' => array('cake')));
  977. $query = $this->Socket->parseQuery('a[][]=foo&a[][]=bar&a[][]=cake');
  978. $expectedQuery = array(
  979. 'a' => array(
  980. 0 => array(
  981. 0 => 'foo'
  982. ),
  983. 1 => array(
  984. 0 => 'bar'
  985. ),
  986. array(
  987. 0 => 'cake'
  988. )
  989. )
  990. );
  991. $this->assertIdentical($query, $expectedQuery);
  992. $query = $this->Socket->parseQuery('a[][]=foo&a[bar]=php&a[][]=bar&a[][]=cake');
  993. $expectedQuery = array(
  994. 'a' => array(
  995. 0 => array(
  996. 0 => 'foo'
  997. ),
  998. 'bar' => 'php',
  999. 1 => array(
  1000. 0 => 'bar'
  1001. ),
  1002. array(
  1003. 0 => 'cake'
  1004. )
  1005. )
  1006. );
  1007. $this->assertIdentical($query, $expectedQuery);
  1008. $query = $this->Socket->parseQuery('user[]=jim&user[3]=tom&user[]=bob');
  1009. $expectedQuery = array(
  1010. 'user' => array(
  1011. 0 => 'jim',
  1012. 3 => 'tom',
  1013. 4 => 'bob'
  1014. )
  1015. );
  1016. $this->assertIdentical($query, $expectedQuery);
  1017. $queryStr = 'user[0]=foo&user[0][items][]=foo&user[0][items][]=bar&user[][name]=jim&user[1][items][personal][]=book&user[1][items][personal][]=pen&user[1][items][]=ball&user[count]=2&empty';
  1018. $query = $this->Socket->parseQuery($queryStr);
  1019. $expectedQuery = array(
  1020. 'user' => array(
  1021. 0 => array(
  1022. 'items' => array(
  1023. 'foo',
  1024. 'bar'
  1025. )
  1026. ),
  1027. 1 => array(
  1028. 'name' => 'jim',
  1029. 'items' => array(
  1030. 'personal' => array(
  1031. 'book'
  1032. , 'pen'
  1033. ),
  1034. 'ball'
  1035. )
  1036. ),
  1037. 'count' => '2'
  1038. ),
  1039. 'empty' => ''
  1040. );
  1041. $this->assertIdentical($query, $expectedQuery);
  1042. }
  1043. /**
  1044. * Tests that HttpSocket::buildHeader can turn a given $header array into a proper header string according to
  1045. * HTTP 1.1 specs.
  1046. *
  1047. * @access public
  1048. * @return void
  1049. */
  1050. function testBuildHeader() {
  1051. $this->Socket->reset();
  1052. $r = $this->Socket->buildHeader(true);
  1053. $this->assertIdentical($r, false);
  1054. $r = $this->Socket->buildHeader('My raw header');
  1055. $this->assertIdentical($r, 'My raw header');
  1056. $r = $this->Socket->buildHeader(array('Host' => 'www.cakephp.org'));
  1057. $this->assertIdentical($r, "Host: www.cakephp.org\r\n");
  1058. $r = $this->Socket->buildHeader(array('Host' => 'www.cakephp.org', 'Connection' => 'Close'));
  1059. $this->assertIdentical($r, "Host: www.cakephp.org\r\nConnection: Close\r\n");
  1060. $r = $this->Socket->buildHeader(array('People' => array('Bob', 'Jim', 'John')));
  1061. $this->assertIdentical($r, "People: Bob,Jim,John\r\n");
  1062. $r = $this->Socket->buildHeader(array('Multi-Line-Field' => "This is my\r\nMulti Line field"));
  1063. $this->assertIdentical($r, "Multi-Line-Field: This is my\r\n Multi Line field\r\n");
  1064. $r = $this->Socket->buildHeader(array('Multi-Line-Field' => "This is my\r\n Multi Line field"));
  1065. $this->assertIdentical($r, "Multi-Line-Field: This is my\r\n Multi Line field\r\n");
  1066. $r = $this->Socket->buildHeader(array('Multi-Line-Field' => "This is my\r\n\tMulti Line field"));
  1067. $this->assertIdentical($r, "Multi-Line-Field: This is my\r\n\tMulti Line field\r\n");
  1068. $r = $this->Socket->buildHeader(array('Test@Field' => "My value"));
  1069. $this->assertIdentical($r, "Test\"@\"Field: My value\r\n");
  1070. }
  1071. /**
  1072. * Test that HttpSocket::parseHeader can take apart a given (and valid) $header string and turn it into an array.
  1073. *
  1074. * @access public
  1075. * @return void
  1076. */
  1077. function testParseHeader() {
  1078. $this->Socket->reset();
  1079. $r = $this->Socket->parseHeader(array('foo' => 'Bar', 'fOO-bAr' => 'quux'));
  1080. $this->assertIdentical($r, array('Foo' => 'Bar', 'Foo-Bar' => 'quux'));
  1081. $r = $this->Socket->parseHeader(true);
  1082. $this->assertIdentical($r, false);
  1083. $header = "Host: cakephp.org\t\r\n";
  1084. $r = $this->Socket->parseHeader($header);
  1085. $expected = array(
  1086. 'Host' => 'cakephp.org'
  1087. );
  1088. $this->assertIdentical($r, $expected);
  1089. $header = "Date:Sat, 07 Apr 2007 10:10:25 GMT\r\nX-Powered-By: PHP/5.1.2\r\n";
  1090. $r = $this->Socket->parseHeader($header);
  1091. $expected = array(
  1092. 'Date' => 'Sat, 07 Apr 2007 10:10:25 GMT'
  1093. , 'X-Powered-By' => 'PHP/5.1.2'
  1094. );
  1095. $this->assertIdentical($r, $expected);
  1096. $header = "people: Jim,John\r\nfoo-LAND: Bar\r\ncAKe-PHP: rocks\r\n";
  1097. $r = $this->Socket->parseHeader($header);
  1098. $expected = array(
  1099. 'People' => 'Jim,John'
  1100. , 'Foo-Land' => 'Bar'
  1101. , 'Cake-Php' => 'rocks'
  1102. );
  1103. $this->assertIdentical($r, $expected);
  1104. $header = "People: Jim,John,Tim\r\nPeople: Lisa,Tina,Chelsea\r\n";
  1105. $r = $this->Socket->parseHeader($header);
  1106. $expected = array(
  1107. 'People' => array('Jim,John,Tim', 'Lisa,Tina,Chelsea')
  1108. );
  1109. $this->assertIdentical($r, $expected);
  1110. $header = "Multi-Line: I am a \r\nmulti line\t\r\nfield value.\r\nSingle-Line: I am not\r\n";
  1111. $r = $this->Socket->parseHeader($header);
  1112. $expected = array(
  1113. 'Multi-Line' => "I am a\r\nmulti line\r\nfield value."
  1114. , 'Single-Line' => 'I am not'
  1115. );
  1116. $this->assertIdentical($r, $expected);
  1117. $header = "Esc\"@\"ped: value\r\n";
  1118. $r = $this->Socket->parseHeader($header);
  1119. $expected = array(
  1120. 'Esc@ped' => 'value'
  1121. );
  1122. $this->assertIdentical($r, $expected);
  1123. }
  1124. /**
  1125. * testParseCookies method
  1126. *
  1127. * @access public
  1128. * @return void
  1129. */
  1130. function testParseCookies() {
  1131. $header = array(
  1132. 'Set-Cookie' => array(
  1133. 'foo=bar',
  1134. 'people=jim,jack,johnny";";Path=/accounts',
  1135. 'google=not=nice'
  1136. ),
  1137. 'Transfer-Encoding' => 'chunked',
  1138. 'Date' => 'Sun, 18 Nov 2007 18:57:42 GMT',
  1139. );
  1140. $cookies = $this->Socket->parseCookies($header);
  1141. $expected = array(
  1142. 'foo' => array(
  1143. 'value' => 'bar'
  1144. ),
  1145. 'people' => array(
  1146. 'value' => 'jim,jack,johnny";"',
  1147. 'path' => '/accounts',
  1148. ),
  1149. 'google' => array(
  1150. 'value' => 'not=nice',
  1151. )
  1152. );
  1153. $this->assertEqual($cookies, $expected);
  1154. $header['Set-Cookie'][] = 'cakephp=great; Secure';
  1155. $expected['cakephp'] = array('value' => 'great', 'secure' => true);
  1156. $cookies = $this->Socket->parseCookies($header);
  1157. $this->assertEqual($cookies, $expected);
  1158. $header['Set-Cookie'] = 'foo=bar';
  1159. unset($expected['people'], $expected['cakephp'], $expected['google']);
  1160. $cookies = $this->Socket->parseCookies($header);
  1161. $this->assertEqual($cookies, $expected);
  1162. }
  1163. /**
  1164. * testBuildCookies method
  1165. *
  1166. * @return void
  1167. * @access public
  1168. * @todo Test more scenarios
  1169. */
  1170. function testBuildCookies() {
  1171. $cookies = array(
  1172. 'foo' => array(
  1173. 'value' => 'bar'
  1174. ),
  1175. 'people' => array(
  1176. 'value' => 'jim,jack,johnny;',
  1177. 'path' => '/accounts'
  1178. )
  1179. );
  1180. $expect = "Cookie: foo=bar\r\nCookie: people=jim,jack,johnny\";\"\r\n";
  1181. $result = $this->Socket->buildCookies($cookies);
  1182. $this->assertEqual($result, $expect);
  1183. }
  1184. /**
  1185. * Test that HttpSocket::escapeToken is escaping all characters as descriped in RFC 2616 (HTTP 1.1 specs)
  1186. *
  1187. * @access public
  1188. * @return void
  1189. */
  1190. function testEscapeToken() {
  1191. $this->Socket->reset();
  1192. $this->assertIdentical($this->Socket->escapeToken('Foo'), 'Foo');
  1193. /*
  1194. * @todo Ensure that these tests are covered elsewhere in public methods
  1195. * $escape = $this->Socket->__tokenEscapeChars(false);
  1196. * foreach ($escape as $char) {
  1197. * $token = 'My-special-'.$char.'-Token';
  1198. * $escapedToken = $this->Socket->escapeToken($token);
  1199. * $expectedToken = 'My-special-"'.$char.'"-Token';
  1200. *
  1201. * $this->assertIdentical($escapedToken, $expectedToken, 'Test token escaping for ASCII '.ord($char));
  1202. * }
  1203. */
  1204. $token = 'Extreme-:Token- -"@-test';
  1205. $escapedToken = $this->Socket->escapeToken($token);
  1206. $expectedToken = 'Extreme-":"Token-" "-""""@"-test';
  1207. $this->assertIdentical($expectedToken, $escapedToken);
  1208. }
  1209. /**
  1210. * Test that escaped token strings are properly unescaped by HttpSocket::unescapeToken
  1211. *
  1212. * @access public
  1213. * @return void
  1214. */
  1215. function testUnescapeToken() {
  1216. $this->Socket->reset();
  1217. $this->assertIdentical($this->Socket->unescapeToken('Foo'), 'Foo');
  1218. /*
  1219. * @todo Ensure that these tests are covered elsewhere in public methods
  1220. * $escape = $this->Socket->__tokenEscapeChars(false);
  1221. * foreach ($escape as $char) {
  1222. * $token = 'My-special-"'.$char.'"-Token';
  1223. * $unescapedToken = $this->Socket->unescapeToken($token);
  1224. * $expectedToken = 'My-special-'.$char.'-Token';
  1225. *
  1226. * $this->assertIdentical($unescapedToken, $expectedToken, 'Test token unescaping for ASCII '.ord($char));
  1227. * }
  1228. */
  1229. $token = 'Extreme-":"Token-" "-""""@"-test';
  1230. $escapedToken = $this->Socket->unescapeToken($token);
  1231. $expectedToken = 'Extreme-:Token- -"@-test';
  1232. $this->assertIdentical($expectedToken, $escapedToken);
  1233. }
  1234. /**
  1235. * This tests asserts HttpSocket::reset() resets a HttpSocket instance to it's initial state (before Object::__construct
  1236. * got executed)
  1237. *
  1238. * @access public
  1239. * @return void
  1240. */
  1241. function testReset() {
  1242. $this->Socket->reset();
  1243. $initialState = get_class_vars('HttpSocket');
  1244. foreach ($initialState as $property => $value) {
  1245. $this->Socket->{$property} = 'Overwritten';
  1246. }
  1247. $return = $this->Socket->reset();
  1248. foreach ($initialState as $property => $value) {
  1249. $this->assertIdentical($this->Socket->{$property}, $value);
  1250. }
  1251. $this->assertIdentical($return, true);
  1252. }
  1253. /**
  1254. * This tests asserts HttpSocket::reset(false) resets certain HttpSocket properties to their initial state (before
  1255. * Object::__construct got executed).
  1256. *
  1257. * @access public
  1258. * @return void
  1259. */
  1260. function testPartialReset() {
  1261. $this->Socket->reset();
  1262. $partialResetProperties = array('request', 'response');
  1263. $initialState = get_class_vars('HttpSocket');
  1264. foreach ($initialState as $property => $value) {
  1265. $this->Socket->{$property} = 'Overwritten';
  1266. }
  1267. $return = $this->Socket->reset(false);
  1268. foreach ($initialState as $property => $originalValue) {
  1269. if (in_array($property, $partialResetProperties)) {
  1270. $this->assertIdentical($this->Socket->{$property}, $originalValue);
  1271. } else {
  1272. $this->assertIdentical($this->Socket->{$property}, 'Overwritten');
  1273. }
  1274. }
  1275. $this->assertIdentical($return, true);
  1276. }
  1277. }
  1278. ?>