/test/k.test.php

http://konstrukt.googlecode.com/ · PHP · 351 lines · 326 code · 24 blank · 1 comment · 2 complexity · 532ef5820e63df9493b0209da634330b MD5 · raw file

  1. <?php
  2. error_reporting(E_ALL | E_STRICT);
  3. // You need to have simpletest in your include_path
  4. require_once 'simpletest/unit_tester.php';
  5. if (realpath($_SERVER['PHP_SELF']) == __FILE__) {
  6. require_once 'simpletest/autorun.php';
  7. }
  8. require_once '../lib/konstrukt/konstrukt.inc.php';
  9. require_once 'support/mocks.inc.php';
  10. class TestOfGlobalsAccess extends UnitTestCase {
  11. function setUp() {
  12. $this->GET = $_GET;
  13. $_GET = array();
  14. }
  15. function tearDown() {
  16. $_GET = $this->GET;
  17. }
  18. function test_undo_magic_quotes_if_present() {
  19. $g = new k_adapter_SafeGlobalsAccess(new k_charset_Latin1CharsetStrategy(), true);
  20. $_GET = array(
  21. 'name' => "O\\'Reilly"
  22. );
  23. $this->assertEqual($g->query(), array('name' => "O'Reilly"));
  24. }
  25. function test_doesnt_undo_magic_quotes_if_not_present() {
  26. $g = new k_adapter_SafeGlobalsAccess(new k_charset_Latin1CharsetStrategy(), false);
  27. $_GET = array(
  28. 'name' => "O\\'Reilly"
  29. );
  30. $this->assertEqual($g->query(), array('name' => "O\\'Reilly"));
  31. }
  32. function test_unmagic_on_deep_array_doesnt_crash_runtime() {
  33. $g = new k_adapter_SafeGlobalsAccess(new k_charset_Latin1CharsetStrategy(), true);
  34. eval("\$_GET = " . str_repeat("array(", 1024) . "\"O\\\\'Reilly\"" . str_repeat(")", 1024) . ";");
  35. $g->query(); // Note: A failing test will produce a Fatal Error and halt the suite
  36. }
  37. function test_mixed_case_key_doesnt_get_conflated() {
  38. $g = new k_adapter_SafeGlobalsAccess(new k_charset_Latin1CharsetStrategy(), true);
  39. $_GET = array(
  40. 'foo' => "42",
  41. 'Foo' => "1337"
  42. );
  43. $this->assertEqual($g->query(), array('foo' => "42", 'Foo' => "1337"));
  44. }
  45. }
  46. class TestOfFileUpload extends UnitTestCase {
  47. function test_files_array() {
  48. $files = array(
  49. 'userfile' => array(
  50. 'name' => 'test.pdf',
  51. 'tmp_name' => 'tmp85937457',
  52. 'size' => '1024',
  53. 'type' => 'application/pdf',
  54. 'error' => 0,
  55. )
  56. );
  57. $glob = new k_adapter_MockGlobalsAccess(array(), array(), array('SERVER_NAME' => 'localhost', 'SCRIPT_NAME' => '', 'REQUEST_URI' => ''), array(), array(), $files);
  58. $http = new k_HttpRequest(null, null, new k_DefaultIdentityLoader(), null, null, $glob);
  59. $files = $http->file();
  60. $this->assertTrue(is_array($files));
  61. $file = $http->file('userfile');
  62. $this->assertEqual($file->name(), 'test.pdf');
  63. $this->assertEqual($file->type(), 'application/pdf');
  64. $this->assertEqual($file->size(), '1024');
  65. $this->assertEqual($file->key(), 'userfile');
  66. }
  67. function test_normalizing_files_array_when_multiple_files() {
  68. $files = array(
  69. 'userfile' => array(
  70. 'name' => array(
  71. 'test.pdf',
  72. 'test.doc',
  73. ),
  74. 'tmp_name' => array(
  75. 'tmp85937457',
  76. 'tmp45937457',
  77. ),
  78. 'size' => array(
  79. '1024',
  80. '2048',
  81. ),
  82. 'type' => array(
  83. 'application/pdf',
  84. 'application/ms-word',
  85. ),
  86. 'error' => array(
  87. 0,
  88. 0,
  89. )
  90. )
  91. );
  92. $expected = array(
  93. 'userfile' => array(
  94. array(
  95. 'name' => 'test.pdf',
  96. 'tmp_name' => 'tmp85937457',
  97. 'size' => '1024',
  98. 'type' => 'application/pdf',
  99. 'error' => 0,
  100. ),
  101. array(
  102. 'name' => 'test.doc',
  103. 'tmp_name' => 'tmp45937457',
  104. 'size' => '2048',
  105. 'type' => 'application/ms-word',
  106. 'error' => 0,
  107. )
  108. )
  109. );
  110. $g = new k_adapter_SafeGlobalsAccess(new k_charset_Latin1CharsetStrategy(), true);
  111. $normalized = $g->normalizeFiles($files);
  112. $this->assertEqual($expected, $normalized);
  113. }
  114. function test_saving_an_uploaded_file() {
  115. $files = array(
  116. 'userfile' => array(
  117. 'name' => 'test.pdf',
  118. 'tmp_name' => 'tmp85937457',
  119. 'size' => '1024',
  120. 'type' => 'application/pdf',
  121. 'error' => 0,
  122. )
  123. );
  124. $glob = new k_adapter_MockGlobalsAccess(array(), array(), array('SERVER_NAME' => 'localhost', 'SCRIPT_NAME' => '', 'REQUEST_URI' => ''), array(), array(), $files);
  125. $file_access = new k_adapter_MockUploadedFileAccess();
  126. $http = new k_HttpRequest(null, null, new k_DefaultIdentityLoader(), null, null, $glob, null, null, $file_access);
  127. $http->file('userfile')->writeTo('/dev/null');
  128. $this->assertEqual(array(array('tmp85937457', '/dev/null')), $file_access->actions);
  129. }
  130. }
  131. class TestOfDispatching extends UnitTestCase {
  132. function test_root_gives_request_uri_as_subspace() {
  133. $glob = new k_adapter_MockGlobalsAccess(array(), array(), array('SERVER_NAME' => 'localhost'));
  134. $http = new k_HttpRequest('', '/foo/bar', new k_DefaultIdentityLoader(), null, null, $glob);
  135. $this->assertEqual($http->subspace(), "/foo/bar");
  136. }
  137. function test_first_component_has_root_subspace() {
  138. $glob = new k_adapter_MockGlobalsAccess(array(), array(), array('SERVER_NAME' => 'localhost'));
  139. $http = new k_HttpRequest('', '/foo/bar', new k_DefaultIdentityLoader(), null, null, $glob);
  140. $components = new k_DefaultComponentCreator();
  141. $root = $components->create('test_CircularComponent', $http);
  142. $this->assertEqual($root->subspace(), "foo/bar");
  143. }
  144. function test_dispatch() {
  145. $expected = "Dispatching:
  146. name: ''
  147. next: 'foo'
  148. subtype: ''
  149. url: '/web2.0/'
  150. Dispatching:
  151. name: 'foo'
  152. next: 'bar'
  153. subtype: ''
  154. url: '/web2.0/foo'
  155. Dispatching:
  156. name: 'bar'
  157. next: 'cux'
  158. subtype: ''
  159. url: '/web2.0/foo/bar'
  160. Dispatching:
  161. name: 'cux'
  162. next: ''
  163. subtype: ''
  164. url: '/web2.0/foo/bar/cux'
  165. Executing
  166. ";
  167. $glob = new k_adapter_MockGlobalsAccess(array(), array(), array('SERVER_NAME' => 'localhost'));
  168. $http = new k_HttpRequest('/web2.0', '/web2.0/foo/bar/cux', new k_DefaultIdentityLoader(), null, null, $glob);
  169. $components = new k_DefaultComponentCreator();
  170. $root = $components->create('test_CircularComponent', $http);
  171. $result = $root->dispatch();
  172. $this->assertEqual($result, $expected);
  173. $http = new k_HttpRequest('/web2.0', '/web2.0/foo/bar/cux/', new k_DefaultIdentityLoader(), null, null, $glob);
  174. $components = new k_DefaultComponentCreator();
  175. $root = $components->create('test_CircularComponent', $http);
  176. $result = $root->dispatch();
  177. $this->assertEqual($result, $expected);
  178. }
  179. function test_subtype_doesnt_affect_dispatch() {
  180. $expected = "Dispatching:
  181. name: ''
  182. next: 'foo'
  183. subtype: ''
  184. url: '/web2.0/'
  185. Dispatching:
  186. name: 'foo'
  187. next: 'bar'
  188. subtype: 'ninja'
  189. url: '/web2.0/foo.ninja'
  190. Dispatching:
  191. name: 'bar'
  192. next: ''
  193. subtype: ''
  194. url: '/web2.0/foo.ninja/bar'
  195. Executing
  196. ";
  197. $glob = new k_adapter_MockGlobalsAccess(array(), array(), array('SERVER_NAME' => 'localhost'));
  198. $http = new k_HttpRequest('/web2.0', '/foo.ninja/bar', new k_DefaultIdentityLoader(), null, null, $glob);
  199. $components = new k_DefaultComponentCreator();
  200. $root = $components->create('test_CircularComponent', $http);
  201. $result = $root->dispatch();
  202. $this->assertEqual($expected, $result);
  203. }
  204. }
  205. class TestOfHttpRequest extends UnitTestCase {
  206. function createHttp($headers) {
  207. $glob = new k_adapter_MockGlobalsAccess(array(), array(), array('SERVER_NAME' => 'example.org'), $headers);
  208. return new k_HttpRequest('', '', new k_DefaultIdentityLoader(), null, null, $glob);
  209. }
  210. function test_negotiate_returns_first_match_from_accept_header() {
  211. $request = $this->createHttp(array('accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'));
  212. $this->assertEqual($request->negotiateContentType(array('text/html','application/xhtml+xml','application/xml')), 'text/html');
  213. }
  214. function test_negotiate_returns_match_with_highest_rank_from_accept_header() {
  215. $request = $this->createHttp(array('accept' => 'text/html;q=0.1,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'));
  216. $this->assertEqual($request->negotiateContentType(array('text/html','application/xhtml+xml','application/xml')), 'application/xhtml+xml');
  217. }
  218. function test_negotiate_returns_candidate_with_exact_match() {
  219. $request = $this->createHttp(array('accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'));
  220. $this->assertEqual($request->negotiateContentType(array('application/xml')), 'application/xml');
  221. }
  222. function test_negotiate_returns_candidate_with_partial_match() {
  223. $request = $this->createHttp(array('accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'));
  224. $this->assertEqual($request->negotiateContentType(array('application/*')), 'application/*');
  225. }
  226. function test_negotiate_returns_first_candidate_on_no_header() {
  227. $request = $this->createHttp(array('accept' => ''));
  228. $this->assertEqual($request->negotiateContentType(array('text/html')), 'text/html');
  229. }
  230. function test_user_override_overrides_accept_header() {
  231. $request = $this->createHttp(array('accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'));
  232. $this->assertEqual($request->negotiateContentType(array('text/html', 'foo/bar'), 'foo/bar'), 'foo/bar');
  233. }
  234. function test_negotiate_simple_subtype_interpreted_as_major_type() {
  235. $request = $this->createHttp(array('accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'));
  236. $this->assertEqual($request->negotiateContentType(array('text/html', 'foo'), 'foo'), 'foo');
  237. }
  238. function test_negotiate_internet_explorer_headerline() {
  239. $request = $this->createHttp(array('accept' => 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*'));
  240. $this->assertEqual($request->negotiateContentType(array('text/html')), 'text/html');
  241. }
  242. }
  243. class TestOfHttpResponse extends UnitTestCase {
  244. function test_404_response_should_output_custom_content_if_any() {
  245. $output = new k_adapter_DummyOutputAccess();
  246. $response = new k_HtmlResponse("I didn't find it");
  247. $response->setStatus(404);
  248. $response->out($output);
  249. $this->assertEqual(404, $output->http_response_code);
  250. $this->assertEqual("I didn't find it", $output->body);
  251. }
  252. }
  253. class TestOfContentTypeDispathing extends UnitTestCase {
  254. function createComponent($method, $headers = array()) {
  255. $glob = new k_adapter_MockGlobalsAccess(array(), array(), array('SERVER_NAME' => 'localhost', 'REQUEST_METHOD' => $method), $headers);
  256. $http = new k_HttpRequest('', '/', new k_DefaultIdentityLoader(), null, null, $glob);
  257. $components = new k_DefaultComponentCreator();
  258. return $components->create('test_ContentTypeComponent', $http);
  259. }
  260. function test_posting_with_a_content_type_calls_specific_handler() {
  261. $root = $this->createComponent('post', array('content-type' => 'application/json'));
  262. $this->assertEqual("postJson called", $root->dispatch());
  263. }
  264. function test_post_multipart() {
  265. $root = $this->createComponent('post', array('content-type' => 'multipart/form-data; boundary=---------------------------1991290281749441721928095653'));
  266. $this->assertEqual("postMultipart called", $root->dispatch());
  267. }
  268. function test_posting_without_a_content_type_fails_with_not_acceptable_when_there_is_at_least_one_candidate() {
  269. $root = $this->createComponent('post');
  270. try {
  271. $root->dispatch();
  272. $this->fail("Expected exception not caught");
  273. } catch (k_NotAcceptable $ex) {
  274. $this->pass();
  275. }
  276. }
  277. function test_putting_without_a_content_type_fails_with_not_implemented_when_there_are_no_candidates() {
  278. $root = $this->createComponent('put');
  279. try {
  280. $root->dispatch();
  281. $this->fail("Expected exception not caught");
  282. } catch (k_NotImplemented $ex) {
  283. $this->pass();
  284. }
  285. }
  286. function test_a_content_type_with_explicit_charset_utf8_is_treated_transparently() {
  287. $root = $this->createComponent('post', array('content-type' => 'application/json; charset=utf-8'));
  288. $this->assertEqual("postJson called", $root->dispatch());
  289. }
  290. function test_a_content_type_with_explicit_charset_other_than_utf8_raises_an_error() {
  291. $root = $this->createComponent('post', array('content-type' => 'application/json; charset=iso-8859-1'));
  292. try {
  293. $root->dispatch();
  294. $this->fail("Expected exception");
  295. } catch (k_UnsupportedContentTypeCharsetException $ex) {
  296. $this->pass("Exception caught");
  297. }
  298. }
  299. }
  300. class TestOfLanguageLoading {
  301. function createComponent($method, $headers = array()) {
  302. $glob = new k_adapter_MockGlobalsAccess(array(), array(), array('SERVER_NAME' => 'localhost', 'REQUEST_METHOD' => $method), $headers);
  303. $language_loader = new test_LanguageLoader();
  304. $http = new k_HttpRequest('', '/', new k_DefaultIdentityLoader(), $language_loader, null, $glob);
  305. $components = new k_DefaultComponentCreator();
  306. return $components->create('test_ContentTypeComponent', $http);
  307. }
  308. function test_that_a_language_is_loaded() {
  309. $component = $this->createComponent('get');
  310. $language = $component->language();
  311. $this->assertTrue($language instanceof k_Language);
  312. }
  313. }
  314. class TestOfTranslatorLoading {
  315. function createComponent($method, $headers = array()) {
  316. $glob = new k_adapter_MockGlobalsAccess(array(), array(), array('SERVER_NAME' => 'localhost', 'REQUEST_METHOD' => $method), $headers);
  317. $translator_loader = new test_TranslatorLoader();
  318. $http = new k_HttpRequest('', '/', new k_DefaultIdentityLoader(), null, $translator_loader, $glob);
  319. $components = new k_DefaultComponentCreator();
  320. return $components->create('test_ContentTypeComponent', $http);
  321. }
  322. function test_that_a_translator_is_loaded() {
  323. $component = $this->createComponent('get');
  324. $translator = $component->language();
  325. $this->assertTrue($translator instanceof k_Translator);
  326. }
  327. }