PageRenderTime 75ms CodeModel.GetById 3ms app.highlight 62ms RepoModel.GetById 1ms app.codeStats 1ms

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