RequestTest.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. <?php defined('SYSPATH') OR die('Kohana bootstrap needs to be included before tests run');
  2. /**
  3. * Unit tests for request class
  4. *
  5. * @group kohana
  6. * @group kohana.core
  7. * @group kohana.core.request
  8. *
  9. * @package Kohana
  10. * @category Tests
  11. * @author Kohana Team
  12. * @author BRMatt <[email protected]>
  13. * @copyright (c) 2008-2012 Kohana Team
  14. * @license http://kohanaframework.org/license
  15. */
  16. class Kohana_RequestTest extends Unittest_TestCase
  17. {
  18. protected $_inital_request;
  19. // @codingStandardsIgnoreStart
  20. public function setUp()
  21. // @codingStandardsIgnoreEnd
  22. {
  23. parent::setUp();
  24. $this->_initial_request = Request::$initial;
  25. Request::$initial = new Request('/');
  26. }
  27. // @codingStandardsIgnoreStart
  28. public function tearDown()
  29. // @codingStandardsIgnoreEnd
  30. {
  31. Request::$initial = $this->_initial_request;
  32. parent::tearDown();
  33. }
  34. public function test_initial()
  35. {
  36. $this->setEnvironment(array(
  37. 'Request::$initial' => NULL,
  38. 'Request::$client_ip' => NULL,
  39. 'Request::$user_agent' => NULL,
  40. '_SERVER' => array(
  41. 'HTTPS' => NULL,
  42. 'PATH_INFO' => '/',
  43. 'HTTP_REFERER' => 'http://example.com/',
  44. 'HTTP_USER_AGENT' => 'whatever (Mozilla 5.0/compatible)',
  45. 'REMOTE_ADDR' => '127.0.0.1',
  46. 'REQUEST_METHOD' => 'GET',
  47. 'HTTP_X_REQUESTED_WITH' => 'ajax-or-something',
  48. ),
  49. '_GET' => array(),
  50. '_POST' => array(),
  51. ));
  52. $request = Request::factory();
  53. $this->assertEquals(Request::$initial, $request);
  54. $this->assertEquals(Request::$client_ip, '127.0.0.1');
  55. $this->assertEquals(Request::$user_agent, 'whatever (Mozilla 5.0/compatible)');
  56. $this->assertEquals($request->protocol(), 'HTTP/1.1');
  57. $this->assertEquals($request->referrer(), 'http://example.com/');
  58. $this->assertEquals($request->requested_with(), 'ajax-or-something');
  59. $this->assertEquals($request->query(), array());
  60. $this->assertEquals($request->post(), array());
  61. }
  62. /**
  63. * Tests that the allow_external flag prevents an external request.
  64. *
  65. * @return null
  66. */
  67. public function test_disable_external_tests()
  68. {
  69. $this->setEnvironment(
  70. array(
  71. 'Request::$initial' => NULL,
  72. )
  73. );
  74. $request = new Request('http://www.google.com/', array(), FALSE);
  75. $this->assertEquals(FALSE, $request->is_external());
  76. }
  77. /**
  78. * Provides the data for test_create()
  79. * @return array
  80. */
  81. public function provider_create()
  82. {
  83. return array(
  84. array('foo/bar', 'Request_Client_Internal'),
  85. array('http://google.com', 'Request_Client_External'),
  86. );
  87. }
  88. /**
  89. * Ensures the create class is created with the correct client
  90. *
  91. * @test
  92. * @dataProvider provider_create
  93. */
  94. public function test_create($uri, $client_class)
  95. {
  96. $request = Request::factory($uri);
  97. $this->assertInstanceOf($client_class, $request->client());
  98. }
  99. /**
  100. * Ensure that parameters can be read
  101. *
  102. * @test
  103. */
  104. public function test_param()
  105. {
  106. $route = new Route('(<controller>(/<action>(/<id>)))');
  107. $uri = 'foo/bar/id';
  108. $request = Request::factory($uri, NULL, TRUE, array($route));
  109. // We need to execute the request before it has matched a route
  110. try
  111. {
  112. $request->execute();
  113. }
  114. catch (Exception $e) {}
  115. $this->assertArrayHasKey('id', $request->param());
  116. $this->assertArrayNotHasKey('foo', $request->param());
  117. $this->assertEquals($request->uri(), $uri);
  118. // Ensure the params do not contain contamination from controller, action, route, uri etc etc
  119. $params = $request->param();
  120. // Test for illegal components
  121. $this->assertArrayNotHasKey('controller', $params);
  122. $this->assertArrayNotHasKey('action', $params);
  123. $this->assertArrayNotHasKey('directory', $params);
  124. $this->assertArrayNotHasKey('uri', $params);
  125. $this->assertArrayNotHasKey('route', $params);
  126. $route = new Route('(<uri>)', array('uri' => '.+'));
  127. $route->defaults(array('controller' => 'foobar', 'action' => 'index'));
  128. $request = Request::factory('foobar', NULL, TRUE, array($route));
  129. // We need to execute the request before it has matched a route
  130. try
  131. {
  132. $request->execute();
  133. }
  134. catch (Exception $e) {}
  135. $this->assertSame('foobar', $request->param('uri'));
  136. }
  137. /**
  138. * Tests Request::method()
  139. *
  140. * @test
  141. */
  142. public function test_method()
  143. {
  144. $request = Request::factory('foo/bar');
  145. $this->assertEquals($request->method(), 'GET');
  146. $this->assertEquals(($request->method('post') === $request), TRUE);
  147. $this->assertEquals(($request->method() === 'POST'), TRUE);
  148. }
  149. /**
  150. * Tests Request::route()
  151. *
  152. * @test
  153. */
  154. public function test_route()
  155. {
  156. $request = Request::factory(''); // This should always match something, no matter what changes people make
  157. // We need to execute the request before it has matched a route
  158. try
  159. {
  160. $request->execute();
  161. }
  162. catch (Exception $e) {}
  163. $this->assertInstanceOf('Route', $request->route());
  164. }
  165. /**
  166. * Tests Request::route()
  167. *
  168. * @test
  169. */
  170. public function test_route_is_not_set_before_execute()
  171. {
  172. $request = Request::factory(''); // This should always match something, no matter what changes people make
  173. // The route should be NULL since the request has not been executed yet
  174. $this->assertEquals($request->route(), NULL);
  175. }
  176. /**
  177. * Tests Request::accept_type()
  178. *
  179. * @test
  180. * @covers Request::accept_type
  181. */
  182. public function test_accept_type()
  183. {
  184. $this->assertEquals(array('*/*' => 1), Request::accept_type());
  185. }
  186. /**
  187. * Provides test data for Request::accept_lang()
  188. * @return array
  189. */
  190. public function provider_accept_lang()
  191. {
  192. return array(
  193. array('en-us', 1, array('_SERVER' => array('HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5'))),
  194. array('en-us', 1, array('_SERVER' => array('HTTP_ACCEPT_LANGUAGE' => 'en-gb'))),
  195. array('en-us', 1, array('_SERVER' => array('HTTP_ACCEPT_LANGUAGE' => 'sp-sp;q=0.5')))
  196. );
  197. }
  198. /**
  199. * Tests Request::accept_lang()
  200. *
  201. * @test
  202. * @covers Request::accept_lang
  203. * @dataProvider provider_accept_lang
  204. * @param array $params Query string
  205. * @param string $expected Expected result
  206. * @param array $enviroment Set environment
  207. */
  208. public function test_accept_lang($params, $expected, $enviroment)
  209. {
  210. $this->setEnvironment($enviroment);
  211. $this->assertEquals(
  212. $expected,
  213. Request::accept_lang($params)
  214. );
  215. }
  216. /**
  217. * Provides test data for Request::url()
  218. * @return array
  219. */
  220. public function provider_url()
  221. {
  222. return array(
  223. array(
  224. 'foo/bar',
  225. 'http',
  226. 'http://localhost/kohana/foo/bar'
  227. ),
  228. array(
  229. 'foo',
  230. 'http',
  231. 'http://localhost/kohana/foo'
  232. ),
  233. );
  234. }
  235. /**
  236. * Tests Request::url()
  237. *
  238. * @test
  239. * @dataProvider provider_url
  240. * @covers Request::url
  241. * @param string $uri the uri to use
  242. * @param string $protocol the protocol to use
  243. * @param array $expected The string we expect
  244. */
  245. public function test_url($uri, $protocol, $expected)
  246. {
  247. if ( ! isset($_SERVER['argc']))
  248. {
  249. $_SERVER['argc'] = 1;
  250. }
  251. $this->setEnvironment(array(
  252. 'Kohana::$base_url' => '/kohana/',
  253. '_SERVER' => array('HTTP_HOST' => 'localhost', 'argc' => $_SERVER['argc']),
  254. 'Kohana::$index_file' => FALSE,
  255. ));
  256. $this->assertEquals(Request::factory($uri)->url($protocol), $expected);
  257. }
  258. /**
  259. * Data provider for test_set_protocol() test
  260. *
  261. * @return array
  262. */
  263. public function provider_set_protocol()
  264. {
  265. return array(
  266. array(
  267. 'http/1.1',
  268. 'HTTP/1.1',
  269. ),
  270. array(
  271. 'ftp',
  272. 'FTP',
  273. ),
  274. array(
  275. 'hTTp/1.0',
  276. 'HTTP/1.0',
  277. ),
  278. );
  279. }
  280. /**
  281. * Tests the protocol() method
  282. *
  283. * @dataProvider provider_set_protocol
  284. *
  285. * @return null
  286. */
  287. public function test_set_protocol($protocol, $expected)
  288. {
  289. $request = Request::factory();
  290. // Set the supplied protocol
  291. $result = $request->protocol($protocol);
  292. // Test the set value
  293. $this->assertSame($expected, $request->protocol());
  294. // Test the return value
  295. $this->assertTrue($request instanceof $result);
  296. }
  297. /**
  298. * Provides data for test_post_max_size_exceeded()
  299. *
  300. * @return array
  301. */
  302. public function provider_post_max_size_exceeded()
  303. {
  304. // Get the post max size
  305. $post_max_size = Num::bytes(ini_get('post_max_size'));
  306. return array(
  307. array(
  308. $post_max_size+200000,
  309. TRUE
  310. ),
  311. array(
  312. $post_max_size-20,
  313. FALSE
  314. ),
  315. array(
  316. $post_max_size,
  317. FALSE
  318. )
  319. );
  320. }
  321. /**
  322. * Tests the post_max_size_exceeded() method
  323. *
  324. * @dataProvider provider_post_max_size_exceeded
  325. *
  326. * @param int content_length
  327. * @param bool expected
  328. * @return void
  329. */
  330. public function test_post_max_size_exceeded($content_length, $expected)
  331. {
  332. // Ensure the request method is set to POST
  333. Request::$initial->method(HTTP_Request::POST);
  334. // Set the content length
  335. $_SERVER['CONTENT_LENGTH'] = $content_length;
  336. // Test the post_max_size_exceeded() method
  337. $this->assertSame(Request::post_max_size_exceeded(), $expected);
  338. }
  339. /**
  340. * Provides data for test_uri_only_trimed_on_internal()
  341. *
  342. * @return array
  343. */
  344. public function provider_uri_only_trimed_on_internal()
  345. {
  346. $old_request = Request::$initial;
  347. Request::$initial = new Request(TRUE);
  348. $result = array(
  349. array(
  350. new Request('http://www.google.com'),
  351. 'http://www.google.com'
  352. ),
  353. array(
  354. new Request('http://www.google.com/'),
  355. 'http://www.google.com/'
  356. ),
  357. array(
  358. new Request('foo/bar/'),
  359. 'foo/bar'
  360. ),
  361. array(
  362. new Request('foo/bar'),
  363. 'foo/bar'
  364. ),
  365. array(
  366. new Request('/'),
  367. '/'
  368. ),
  369. array(
  370. new Request(''),
  371. '/'
  372. )
  373. );
  374. Request::$initial = $old_request;
  375. return $result;
  376. }
  377. /**
  378. * Tests that the uri supplied to Request is only trimed
  379. * for internal requests.
  380. *
  381. * @dataProvider provider_uri_only_trimed_on_internal
  382. *
  383. * @return void
  384. */
  385. public function test_uri_only_trimed_on_internal(Request $request, $expected)
  386. {
  387. $this->assertSame($request->uri(), $expected);
  388. }
  389. /**
  390. * Data provider for test_options_set_to_external_client()
  391. *
  392. * @return array
  393. */
  394. public function provider_options_set_to_external_client()
  395. {
  396. $provider = array(
  397. array(
  398. array(
  399. CURLOPT_PROXYPORT => 8080,
  400. CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
  401. CURLOPT_VERBOSE => TRUE
  402. ),
  403. array(
  404. CURLOPT_PROXYPORT => 8080,
  405. CURLOPT_PROXYTYPE => CURLPROXY_HTTP,
  406. CURLOPT_VERBOSE => TRUE
  407. )
  408. )
  409. );
  410. return $provider;
  411. }
  412. /**
  413. * Test for Request_Client_External::options() to ensure options
  414. * can be set to the external client (for cURL and PECL_HTTP)
  415. *
  416. * @dataProvider provider_options_set_to_external_client
  417. *
  418. * @param array settings
  419. * @param array expected
  420. * @return void
  421. */
  422. public function test_options_set_to_external_client($settings, $expected)
  423. {
  424. $request_client = Request_Client_External::factory(array(), 'Request_Client_Curl');
  425. // Test for empty array
  426. $this->assertSame(array(), $request_client->options());
  427. // Test that set works as expected
  428. $this->assertSame($request_client->options($settings), $request_client);
  429. // Test that each setting is present and returned
  430. foreach ($expected as $key => $value)
  431. {
  432. $this->assertSame($request_client->options($key), $value);
  433. }
  434. }
  435. /**
  436. * Provides data for test_headers_get()
  437. *
  438. * @return array
  439. */
  440. public function provider_headers_get()
  441. {
  442. $x_powered_by = 'Kohana Unit Test';
  443. $content_type = 'application/x-www-form-urlencoded';
  444. return array(
  445. array(
  446. $request = Request::factory('foo/bar')
  447. ->headers(array(
  448. 'x-powered-by' => $x_powered_by,
  449. 'content-type' => $content_type
  450. )
  451. ),
  452. array(
  453. 'x-powered-by' => $x_powered_by,
  454. 'content-type' => $content_type
  455. )
  456. )
  457. );
  458. }
  459. /**
  460. * Tests getting headers from the Request object
  461. *
  462. * @dataProvider provider_headers_get
  463. *
  464. * @param Request request to test
  465. * @param array headers to test against
  466. * @return void
  467. */
  468. public function test_headers_get($request, $headers)
  469. {
  470. foreach ($headers as $key => $expected_value)
  471. {
  472. $this->assertSame( (string) $request->headers($key), $expected_value);
  473. }
  474. }
  475. /**
  476. * Provides data for test_headers_set
  477. *
  478. * @return array
  479. */
  480. public function provider_headers_set()
  481. {
  482. return array(
  483. array(
  484. Request::factory(),
  485. array(
  486. 'content-type' => 'application/x-www-form-urlencoded',
  487. 'x-test-header' => 'foo'
  488. ),
  489. "Content-Type: application/x-www-form-urlencoded\r\nX-Test-Header: foo\r\n\r\n"
  490. ),
  491. array(
  492. Request::factory(),
  493. array(
  494. 'content-type' => 'application/json',
  495. 'x-powered-by' => 'kohana'
  496. ),
  497. "Content-Type: application/json\r\nX-Powered-By: kohana\r\n\r\n"
  498. )
  499. );
  500. }
  501. /**
  502. * Tests the setting of headers to the request object
  503. *
  504. * @dataProvider provider_headers_set
  505. *
  506. * @param Request request object
  507. * @param array header(s) to set to the request object
  508. * @param string expected http header
  509. * @return void
  510. */
  511. public function test_headers_set(Request $request, $headers, $expected)
  512. {
  513. $request->headers($headers);
  514. $this->assertSame($expected, (string) $request->headers());
  515. }
  516. /**
  517. * Provides test data for test_query_parameter_parsing()
  518. *
  519. * @return array
  520. */
  521. public function provider_query_parameter_parsing()
  522. {
  523. return array(
  524. array(
  525. new Request('foo/bar'),
  526. array(
  527. 'foo' => 'bar',
  528. 'sna' => 'fu'
  529. ),
  530. array(
  531. 'foo' => 'bar',
  532. 'sna' => 'fu'
  533. ),
  534. ),
  535. array(
  536. new Request('foo/bar?john=wayne&peggy=sue'),
  537. array(
  538. 'foo' => 'bar',
  539. 'sna' => 'fu'
  540. ),
  541. array(
  542. 'john' => 'wayne',
  543. 'peggy' => 'sue',
  544. 'foo' => 'bar',
  545. 'sna' => 'fu'
  546. ),
  547. ),
  548. array(
  549. new Request('http://host.tld/foo/bar?john=wayne&peggy=sue'),
  550. array(
  551. 'foo' => 'bar',
  552. 'sna' => 'fu'
  553. ),
  554. array(
  555. 'john' => 'wayne',
  556. 'peggy' => 'sue',
  557. 'foo' => 'bar',
  558. 'sna' => 'fu'
  559. ),
  560. ),
  561. );
  562. }
  563. /**
  564. * Tests that query parameters are parsed correctly
  565. *
  566. * @dataProvider provider_query_parameter_parsing
  567. *
  568. * @param Request request
  569. * @param array query
  570. * @param array expected
  571. * @return void
  572. */
  573. public function test_query_parameter_parsing(Request $request, $query, $expected)
  574. {
  575. foreach ($query as $key => $value)
  576. {
  577. $request->query($key, $value);
  578. }
  579. $this->assertSame($expected, $request->query());
  580. }
  581. /**
  582. * Provides data for test_client
  583. *
  584. * @return array
  585. */
  586. public function provider_client()
  587. {
  588. $internal_client = new Request_Client_Internal;
  589. $external_client = new Request_Client_Stream;
  590. return array(
  591. array(
  592. new Request('http://kohanaframework.org'),
  593. $internal_client,
  594. $internal_client
  595. ),
  596. array(
  597. new Request('foo/bar'),
  598. $external_client,
  599. $external_client
  600. )
  601. );
  602. }
  603. /**
  604. * Tests the getter/setter for request client
  605. *
  606. * @dataProvider provider_client
  607. *
  608. * @param Request $request
  609. * @param Request_Client $client
  610. * @param Request_Client $expected
  611. * @return void
  612. */
  613. public function test_client(Request $request, Request_Client $client, Request_Client $expected)
  614. {
  615. $request->client($client);
  616. $this->assertSame($expected, $request->client());
  617. }
  618. /**
  619. * Tests that the Request constructor passes client params on to the
  620. * Request_Client once created.
  621. */
  622. public function test_passes_client_params()
  623. {
  624. $request = Request::factory('http://example.com/', array(
  625. 'follow' => TRUE,
  626. 'strict_redirect' => FALSE
  627. ));
  628. $client = $request->client();
  629. $this->assertEquals($client->follow(), TRUE);
  630. $this->assertEquals($client->strict_redirect(), FALSE);
  631. }
  632. } // End Kohana_RequestTest
  633. class Controller_Kohana_RequestTest_Dummy extends Controller
  634. {
  635. public function action_index()
  636. {
  637. }
  638. } // End Kohana_RequestTest