統計
| ブランチ: | リビジョン:

pictcode / lib / Cake / Test / Case / Network / CakeResponseTest.php @ 635eef61

履歴 | 表示 | アノテート | ダウンロード (55.651 KB)

1
<?php
2
/**
3
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
4
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
5
 *
6
 * Licensed under The MIT License
7
 * For full copyright and license information, please see the LICENSE.txt
8
 * Redistributions of files must retain the above copyright notice.
9
 *
10
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
11
 * @link          http://cakephp.org CakePHP(tm) Project
12
 * @package       Cake.Test.Case.Network
13
 * @since         CakePHP(tm) v 2.0
14
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
15
 */
16

    
17
App::uses('CakeResponse', 'Network');
18
App::uses('CakeRequest', 'Network');
19

    
20
/**
21
 * Class CakeResponseTest
22
 *
23
 * @package       Cake.Test.Case.Network
24
 */
25
class CakeResponseTest extends CakeTestCase {
26

    
27
/**
28
 * Setup for tests
29
 *
30
 * @return void
31
 */
32
        public function setUp() {
33
                parent::setUp();
34
                ob_start();
35
        }
36

    
37
/**
38
 * Cleanup after tests
39
 *
40
 * @return void
41
 */
42
        public function tearDown() {
43
                parent::tearDown();
44
                ob_end_clean();
45
        }
46

    
47
/**
48
 * Tests the request object constructor
49
 *
50
 * @return void
51
 */
52
        public function testConstruct() {
53
                $response = new CakeResponse();
54
                $this->assertNull($response->body());
55
                $this->assertEquals('UTF-8', $response->charset());
56
                $this->assertEquals('text/html', $response->type());
57
                $this->assertEquals(200, $response->statusCode());
58

    
59
                $options = array(
60
                        'body' => 'This is the body',
61
                        'charset' => 'my-custom-charset',
62
                        'type' => 'mp3',
63
                        'status' => '203'
64
                );
65
                $response = new CakeResponse($options);
66
                $this->assertEquals('This is the body', $response->body());
67
                $this->assertEquals('my-custom-charset', $response->charset());
68
                $this->assertEquals('audio/mpeg', $response->type());
69
                $this->assertEquals(203, $response->statusCode());
70

    
71
                $options = array(
72
                        'body' => 'This is the body',
73
                        'charset' => 'my-custom-charset',
74
                        'type' => 'mp3',
75
                        'status' => '422',
76
                        'statusCodes' => array(
77
                                422 => 'Unprocessable Entity'
78
                        )
79
                );
80
                $response = new CakeResponse($options);
81
                $this->assertEquals($options['body'], $response->body());
82
                $this->assertEquals($options['charset'], $response->charset());
83
                $this->assertEquals($response->getMimeType($options['type']), $response->type());
84
                $this->assertEquals($options['status'], $response->statusCode());
85
        }
86

    
87
/**
88
 * Tests the body method
89
 *
90
 * @return void
91
 */
92
        public function testBody() {
93
                $response = new CakeResponse();
94
                $this->assertNull($response->body());
95
                $response->body('Response body');
96
                $this->assertEquals('Response body', $response->body());
97
                $this->assertEquals('Changed Body', $response->body('Changed Body'));
98
        }
99

    
100
/**
101
 * Tests the charset method
102
 *
103
 * @return void
104
 */
105
        public function testCharset() {
106
                $response = new CakeResponse();
107
                $this->assertEquals('UTF-8', $response->charset());
108
                $response->charset('iso-8859-1');
109
                $this->assertEquals('iso-8859-1', $response->charset());
110
                $this->assertEquals('UTF-16', $response->charset('UTF-16'));
111
        }
112

    
113
/**
114
 * Tests the statusCode method
115
 *
116
 * @expectedException CakeException
117
 * @return void
118
 */
119
        public function testStatusCode() {
120
                $response = new CakeResponse();
121
                $this->assertEquals(200, $response->statusCode());
122
                $response->statusCode(404);
123
                $this->assertEquals(404, $response->statusCode());
124
                $this->assertEquals(500, $response->statusCode(500));
125

    
126
                //Throws exception
127
                $response->statusCode(1001);
128
        }
129

    
130
/**
131
 * Tests the type method
132
 *
133
 * @return void
134
 */
135
        public function testType() {
136
                $response = new CakeResponse();
137
                $this->assertEquals('text/html', $response->type());
138
                $response->type('pdf');
139
                $this->assertEquals('application/pdf', $response->type());
140
                $this->assertEquals('application/crazy-mime', $response->type('application/crazy-mime'));
141
                $this->assertEquals('application/json', $response->type('json'));
142
                $this->assertEquals('text/vnd.wap.wml', $response->type('wap'));
143
                $this->assertEquals('application/vnd.wap.xhtml+xml', $response->type('xhtml-mobile'));
144
                $this->assertEquals('text/csv', $response->type('csv'));
145

    
146
                $response->type(array('keynote' => 'application/keynote', 'bat' => 'application/bat'));
147
                $this->assertEquals('application/keynote', $response->type('keynote'));
148
                $this->assertEquals('application/bat', $response->type('bat'));
149

    
150
                $this->assertFalse($response->type('wackytype'));
151
        }
152

    
153
/**
154
 * Tests the header method
155
 *
156
 * @return void
157
 */
158
        public function testHeader() {
159
                $response = new CakeResponse();
160
                $headers = array();
161
                $this->assertEquals($headers, $response->header());
162

    
163
                $response->header('Location', 'http://example.com');
164
                $headers += array('Location' => 'http://example.com');
165
                $this->assertEquals($headers, $response->header());
166

    
167
                //Headers with the same name are overwritten
168
                $response->header('Location', 'http://example2.com');
169
                $headers = array('Location' => 'http://example2.com');
170
                $this->assertEquals($headers, $response->header());
171

    
172
                $response->header(array('WWW-Authenticate' => 'Negotiate'));
173
                $headers += array('WWW-Authenticate' => 'Negotiate');
174
                $this->assertEquals($headers, $response->header());
175

    
176
                $response->header(array('WWW-Authenticate' => 'Not-Negotiate'));
177
                $headers['WWW-Authenticate'] = 'Not-Negotiate';
178
                $this->assertEquals($headers, $response->header());
179

    
180
                $response->header(array('Age' => 12, 'Allow' => 'GET, HEAD'));
181
                $headers += array('Age' => 12, 'Allow' => 'GET, HEAD');
182
                $this->assertEquals($headers, $response->header());
183

    
184
                // String headers are allowed
185
                $response->header('Content-Language: da');
186
                $headers += array('Content-Language' => 'da');
187
                $this->assertEquals($headers, $response->header());
188

    
189
                $response->header('Content-Language: da');
190
                $headers += array('Content-Language' => 'da');
191
                $this->assertEquals($headers, $response->header());
192

    
193
                $response->header(array('Content-Encoding: gzip', 'Vary: *', 'Pragma' => 'no-cache'));
194
                $headers += array('Content-Encoding' => 'gzip', 'Vary' => '*', 'Pragma' => 'no-cache');
195
                $this->assertEquals($headers, $response->header());
196

    
197
                $response->header('Access-Control-Allow-Origin', array('domain1', 'domain2'));
198
                $headers += array('Access-Control-Allow-Origin' => array('domain1', 'domain2'));
199
                $this->assertEquals($headers, $response->header());
200
        }
201

    
202
/**
203
 * Tests the send method
204
 *
205
 * @return void
206
 */
207
        public function testSend() {
208
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', '_setCookies'));
209
                $response->header(array(
210
                        'Content-Language' => 'es',
211
                        'WWW-Authenticate' => 'Negotiate',
212
                        'Access-Control-Allow-Origin' => array('domain1', 'domain2'),
213
                ));
214
                $response->body('the response body');
215
                $response->expects($this->once())->method('_sendContent')->with('the response body');
216
                $response->expects($this->at(0))->method('_setCookies');
217
                $response->expects($this->at(1))
218
                        ->method('_sendHeader')->with('HTTP/1.1 200 OK');
219
                $response->expects($this->at(2))
220
                        ->method('_sendHeader')->with('Content-Language', 'es');
221
                $response->expects($this->at(3))
222
                        ->method('_sendHeader')->with('WWW-Authenticate', 'Negotiate');
223
                $response->expects($this->at(4))
224
                        ->method('_sendHeader')->with('Access-Control-Allow-Origin', 'domain1');
225
                $response->expects($this->at(5))
226
                        ->method('_sendHeader')->with('Access-Control-Allow-Origin', 'domain2');
227
                $response->expects($this->at(6))
228
                        ->method('_sendHeader')->with('Content-Length', 17);
229
                $response->expects($this->at(7))
230
                        ->method('_sendHeader')->with('Content-Type', 'text/html; charset=UTF-8');
231
                $response->send();
232
        }
233

    
234
/**
235
 * Data provider for content type tests.
236
 *
237
 * @return array
238
 */
239
        public static function charsetTypeProvider() {
240
                return array(
241
                        array('mp3', 'audio/mpeg'),
242
                        array('js', 'application/javascript; charset=UTF-8'),
243
                        array('json', 'application/json; charset=UTF-8'),
244
                        array('xml', 'application/xml; charset=UTF-8'),
245
                        array('txt', 'text/plain; charset=UTF-8'),
246
                );
247
        }
248

    
249
/**
250
 * Tests the send method and changing the content type
251
 *
252
 * @dataProvider charsetTypeProvider
253
 * @return void
254
 */
255
        public function testSendChangingContentType($original, $expected) {
256
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', '_setCookies'));
257
                $response->type($original);
258
                $response->body('the response body');
259
                $response->expects($this->once())->method('_sendContent')->with('the response body');
260
                $response->expects($this->at(0))->method('_setCookies');
261
                $response->expects($this->at(1))
262
                        ->method('_sendHeader')->with('HTTP/1.1 200 OK');
263
                $response->expects($this->at(2))
264
                        ->method('_sendHeader')->with('Content-Length', 17);
265
                $response->expects($this->at(3))
266
                        ->method('_sendHeader')->with('Content-Type', $expected);
267
                $response->send();
268
        }
269

    
270
/**
271
 * Tests the send method and changing the content type to JS without adding the charset
272
 *
273
 * @return void
274
 */
275
        public function testSendChangingContentTypeWithoutCharset() {
276
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', '_setCookies'));
277
                $response->type('js');
278
                $response->charset('');
279

    
280
                $response->body('var $foo = "bar";');
281
                $response->expects($this->once())->method('_sendContent')->with('var $foo = "bar";');
282
                $response->expects($this->at(0))->method('_setCookies');
283
                $response->expects($this->at(1))
284
                        ->method('_sendHeader')->with('HTTP/1.1 200 OK');
285
                $response->expects($this->at(2))
286
                        ->method('_sendHeader')->with('Content-Length', 17);
287
                $response->expects($this->at(3))
288
                        ->method('_sendHeader')->with('Content-Type', 'application/javascript');
289
                $response->send();
290
        }
291

    
292
/**
293
 * Tests the send method and changing the content type
294
 *
295
 * @return void
296
 */
297
        public function testSendWithLocation() {
298
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', '_setCookies'));
299
                $response->header('Location', 'http://www.example.com');
300
                $response->expects($this->at(0))->method('_setCookies');
301
                $response->expects($this->at(1))
302
                        ->method('_sendHeader')->with('HTTP/1.1 302 Found');
303
                $response->expects($this->at(2))
304
                        ->method('_sendHeader')->with('Location', 'http://www.example.com');
305
                $response->expects($this->at(3))
306
                        ->method('_sendHeader')->with('Content-Type', 'text/html; charset=UTF-8');
307
                $response->send();
308
        }
309

    
310
/**
311
 * Tests the disableCache method
312
 *
313
 * @return void
314
 */
315
        public function testDisableCache() {
316
                $response = new CakeResponse();
317
                $expected = array(
318
                        'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT',
319
                        'Last-Modified' => gmdate("D, d M Y H:i:s") . " GMT",
320
                        'Cache-Control' => 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'
321
                );
322
                $response->disableCache();
323
                $this->assertEquals($expected, $response->header());
324
        }
325

    
326
/**
327
 * Tests the cache method
328
 *
329
 * @return void
330
 */
331
        public function testCache() {
332
                $response = new CakeResponse();
333
                $since = time();
334
                $time = new DateTime('+1 day', new DateTimeZone('UTC'));
335
                $response->expires('+1 day');
336
                $expected = array(
337
                        'Date' => gmdate("D, j M Y G:i:s ", $since) . 'GMT',
338
                        'Last-Modified' => gmdate("D, j M Y H:i:s ", $since) . 'GMT',
339
                        'Expires' => $time->format('D, j M Y H:i:s') . ' GMT',
340
                        'Cache-Control' => 'public, max-age=' . ($time->format('U') - time())
341
                );
342
                $response->cache($since);
343
                $this->assertEquals($expected, $response->header());
344

    
345
                $response = new CakeResponse();
346
                $since = time();
347
                $time = '+5 day';
348
                $expected = array(
349
                        'Date' => gmdate("D, j M Y G:i:s ", $since) . 'GMT',
350
                        'Last-Modified' => gmdate("D, j M Y H:i:s ", $since) . 'GMT',
351
                        'Expires' => gmdate("D, j M Y H:i:s", strtotime($time)) . " GMT",
352
                        'Cache-Control' => 'public, max-age=' . (strtotime($time) - time())
353
                );
354
                $response->cache($since, $time);
355
                $this->assertEquals($expected, $response->header());
356

    
357
                $response = new CakeResponse();
358
                $since = time();
359
                $time = time();
360
                $expected = array(
361
                        'Date' => gmdate("D, j M Y G:i:s ", $since) . 'GMT',
362
                        'Last-Modified' => gmdate("D, j M Y H:i:s ", $since) . 'GMT',
363
                        'Expires' => gmdate("D, j M Y H:i:s", $time) . " GMT",
364
                        'Cache-Control' => 'public, max-age=0'
365
                );
366
                $response->cache($since, $time);
367
                $this->assertEquals($expected, $response->header());
368
        }
369

    
370
/**
371
 * Tests the compress method
372
 *
373
 * @return void
374
 */
375
        public function testCompress() {
376
                if (PHP_SAPI !== 'cli') {
377
                        $this->markTestSkipped('The response compression can only be tested in cli.');
378
                }
379

    
380
                $response = new CakeResponse();
381
                if (ini_get("zlib.output_compression") === '1' || !extension_loaded("zlib")) {
382
                        $this->assertFalse($response->compress());
383
                        $this->markTestSkipped('Is not possible to test output compression');
384
                }
385

    
386
                $_SERVER['HTTP_ACCEPT_ENCODING'] = '';
387
                $result = $response->compress();
388
                $this->assertFalse($result);
389

    
390
                $_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip';
391
                $result = $response->compress();
392
                $this->assertTrue($result);
393
                $this->assertTrue(in_array('ob_gzhandler', ob_list_handlers()));
394

    
395
                ob_get_clean();
396
        }
397

    
398
/**
399
 * Tests the httpCodes method
400
 *
401
 * @expectedException CakeException
402
 * @return void
403
 */
404
        public function testHttpCodes() {
405
                $response = new CakeResponse();
406
                $result = $response->httpCodes();
407
                $this->assertEquals(41, count($result));
408

    
409
                $result = $response->httpCodes(100);
410
                $expected = array(100 => 'Continue');
411
                $this->assertEquals($expected, $result);
412

    
413
                $codes = array(
414
                        381 => 'Unicorn Moved',
415
                        555 => 'Unexpected Minotaur'
416
                );
417

    
418
                $result = $response->httpCodes($codes);
419
                $this->assertTrue($result);
420
                $this->assertEquals(43, count($response->httpCodes()));
421

    
422
                $result = $response->httpCodes(381);
423
                $expected = array(381 => 'Unicorn Moved');
424
                $this->assertEquals($expected, $result);
425

    
426
                $codes = array(404 => 'Sorry Bro');
427
                $result = $response->httpCodes($codes);
428
                $this->assertTrue($result);
429
                $this->assertEquals(43, count($response->httpCodes()));
430

    
431
                $result = $response->httpCodes(404);
432
                $expected = array(404 => 'Sorry Bro');
433
                $this->assertEquals($expected, $result);
434

    
435
                //Throws exception
436
                $response->httpCodes(array(
437
                        0 => 'Nothing Here',
438
                        -1 => 'Reverse Infinity',
439
                        12345 => 'Universal Password',
440
                        'Hello' => 'World'
441
                ));
442
        }
443

    
444
/**
445
 * Tests the download method
446
 *
447
 * @return void
448
 */
449
        public function testDownload() {
450
                $response = new CakeResponse();
451
                $expected = array(
452
                        'Content-Disposition' => 'attachment; filename="myfile.mp3"'
453
                );
454
                $response->download('myfile.mp3');
455
                $this->assertEquals($expected, $response->header());
456
        }
457

    
458
/**
459
 * Tests the mapType method
460
 *
461
 * @return void
462
 */
463
        public function testMapType() {
464
                $response = new CakeResponse();
465
                $this->assertEquals('wav', $response->mapType('audio/x-wav'));
466
                $this->assertEquals('pdf', $response->mapType('application/pdf'));
467
                $this->assertEquals('xml', $response->mapType('text/xml'));
468
                $this->assertEquals('html', $response->mapType('*/*'));
469
                $this->assertEquals('csv', $response->mapType('application/vnd.ms-excel'));
470
                $expected = array('json', 'xhtml', 'css');
471
                $result = $response->mapType(array('application/json', 'application/xhtml+xml', 'text/css'));
472
                $this->assertEquals($expected, $result);
473
        }
474

    
475
/**
476
 * Tests the outputCompressed method
477
 *
478
 * @return void
479
 */
480
        public function testOutputCompressed() {
481
                $response = new CakeResponse();
482

    
483
                $_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip';
484
                $result = $response->outputCompressed();
485
                $this->assertFalse($result);
486

    
487
                $_SERVER['HTTP_ACCEPT_ENCODING'] = '';
488
                $result = $response->outputCompressed();
489
                $this->assertFalse($result);
490

    
491
                if (!extension_loaded("zlib")) {
492
                        $this->markTestSkipped('Skipping further tests for outputCompressed as zlib extension is not loaded');
493
                }
494
                if (PHP_SAPI !== 'cli') {
495
                        $this->markTestSkipped('Testing outputCompressed method with compression enabled done only in cli');
496
                }
497

    
498
                if (ini_get("zlib.output_compression") !== '1') {
499
                        ob_start('ob_gzhandler');
500
                }
501
                $_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip';
502
                $result = $response->outputCompressed();
503
                $this->assertTrue($result);
504

    
505
                $_SERVER['HTTP_ACCEPT_ENCODING'] = '';
506
                $result = $response->outputCompressed();
507
                $this->assertFalse($result);
508
                if (ini_get("zlib.output_compression") !== '1') {
509
                        ob_get_clean();
510
                }
511
        }
512

    
513
/**
514
 * Tests the send and setting of Content-Length
515
 *
516
 * @return void
517
 */
518
        public function testSendContentLength() {
519
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
520
                $response->body('the response body');
521
                $response->expects($this->once())->method('_sendContent')->with('the response body');
522
                $response->expects($this->at(0))
523
                        ->method('_sendHeader')->with('HTTP/1.1 200 OK');
524
                $response->expects($this->at(2))
525
                        ->method('_sendHeader')->with('Content-Type', 'text/html; charset=UTF-8');
526
                $response->expects($this->at(1))
527
                        ->method('_sendHeader')->with('Content-Length', strlen('the response body'));
528
                $response->send();
529

    
530
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
531
                $body = '長い長い長いSubjectの場合はfoldingするのが正しいんだけどいったいどうなるんだろう?';
532
                $response->body($body);
533
                $response->expects($this->once())->method('_sendContent')->with($body);
534
                $response->expects($this->at(0))
535
                        ->method('_sendHeader')->with('HTTP/1.1 200 OK');
536
                $response->expects($this->at(2))
537
                        ->method('_sendHeader')->with('Content-Type', 'text/html; charset=UTF-8');
538
                $response->expects($this->at(1))
539
                        ->method('_sendHeader')->with('Content-Length', 116);
540
                $response->send();
541

    
542
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', 'outputCompressed'));
543
                $body = '長い長い長いSubjectの場合はfoldingするのが正しいんだけどいったいどうなるんだろう?';
544
                $response->body($body);
545
                $response->expects($this->once())->method('outputCompressed')->will($this->returnValue(true));
546
                $response->expects($this->once())->method('_sendContent')->with($body);
547
                $response->expects($this->exactly(2))->method('_sendHeader');
548
                $response->send();
549

    
550
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', 'outputCompressed'));
551
                $body = 'hwy';
552
                $response->body($body);
553
                $response->header('Content-Length', 1);
554
                $response->expects($this->never())->method('outputCompressed');
555
                $response->expects($this->once())->method('_sendContent')->with($body);
556
                $response->expects($this->at(1))
557
                                ->method('_sendHeader')->with('Content-Length', 1);
558
                $response->send();
559

    
560
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
561
                $body = 'content';
562
                $response->statusCode(301);
563
                $response->body($body);
564
                $response->expects($this->once())->method('_sendContent')->with($body);
565
                $response->expects($this->exactly(2))->method('_sendHeader');
566
                $response->send();
567

    
568
                ob_start();
569
                $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
570
                $goofyOutput = 'I am goofily sending output in the controller';
571
                echo $goofyOutput;
572
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
573
                $body = '長い長い長いSubjectの場合はfoldingするのが正しいんだけどいったいどうなるんだろう?';
574
                $response->body($body);
575
                $response->expects($this->once())->method('_sendContent')->with($body);
576
                $response->expects($this->at(0))
577
                        ->method('_sendHeader')->with('HTTP/1.1 200 OK');
578
                $response->expects($this->at(1))
579
                        ->method('_sendHeader')->with('Content-Length', strlen($goofyOutput) + 116);
580
                $response->expects($this->at(2))
581
                        ->method('_sendHeader')->with('Content-Type', 'text/html; charset=UTF-8');
582
                $response->send();
583
                ob_end_clean();
584
        }
585

    
586
/**
587
 * Tests getting/setting the protocol
588
 *
589
 * @return void
590
 */
591
        public function testProtocol() {
592
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
593
                $response->protocol('HTTP/1.0');
594
                $this->assertEquals('HTTP/1.0', $response->protocol());
595
                $response->expects($this->at(0))
596
                        ->method('_sendHeader')->with('HTTP/1.0 200 OK');
597
                $response->send();
598
        }
599

    
600
/**
601
 * Tests getting/setting the Content-Length
602
 *
603
 * @return void
604
 */
605
        public function testLength() {
606
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
607
                $response->length(100);
608
                $this->assertEquals(100, $response->length());
609
                $response->expects($this->at(1))
610
                        ->method('_sendHeader')->with('Content-Length', 100);
611
                $response->send();
612

    
613
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
614
                $response->length(false);
615
                $this->assertFalse($response->length());
616
                $response->expects($this->exactly(2))
617
                        ->method('_sendHeader');
618
                $response->send();
619
        }
620

    
621
/**
622
 * Tests that the response body is unset if the status code is 304 or 204
623
 *
624
 * @return void
625
 */
626
        public function testUnmodifiedContent() {
627
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
628
                $response->body('This is a body');
629
                $response->statusCode(204);
630
                $response->expects($this->once())
631
                        ->method('_sendContent')->with('');
632
                $response->send();
633
                $this->assertFalse(array_key_exists('Content-Type', $response->header()));
634

    
635
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
636
                $response->body('This is a body');
637
                $response->statusCode(304);
638
                $response->expects($this->once())
639
                        ->method('_sendContent')->with('');
640
                $response->send();
641

    
642
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
643
                $response->body('This is a body');
644
                $response->statusCode(200);
645
                $response->expects($this->once())
646
                        ->method('_sendContent')->with('This is a body');
647
                $response->send();
648
        }
649

    
650
/**
651
 * Tests setting the expiration date
652
 *
653
 * @return void
654
 */
655
        public function testExpires() {
656
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
657
                $now = new DateTime('now', new DateTimeZone('America/Los_Angeles'));
658
                $response->expires($now);
659
                $now->setTimeZone(new DateTimeZone('UTC'));
660
                $this->assertEquals($now->format('D, j M Y H:i:s') . ' GMT', $response->expires());
661
                $response->expects($this->at(1))
662
                        ->method('_sendHeader')->with('Expires', $now->format('D, j M Y H:i:s') . ' GMT');
663
                $response->send();
664

    
665
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
666
                $now = time();
667
                $response->expires($now);
668
                $this->assertEquals(gmdate('D, j M Y H:i:s', $now) . ' GMT', $response->expires());
669
                $response->expects($this->at(1))
670
                        ->method('_sendHeader')->with('Expires', gmdate('D, j M Y H:i:s', $now) . ' GMT');
671
                $response->send();
672

    
673
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
674
                $time = new DateTime('+1 day', new DateTimeZone('UTC'));
675
                $response->expires('+1 day');
676
                $this->assertEquals($time->format('D, j M Y H:i:s') . ' GMT', $response->expires());
677
                $response->expects($this->at(1))
678
                        ->method('_sendHeader')->with('Expires', $time->format('D, j M Y H:i:s') . ' GMT');
679
                $response->send();
680
        }
681

    
682
/**
683
 * Tests setting the modification date
684
 *
685
 * @return void
686
 */
687
        public function testModified() {
688
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
689
                $now = new DateTime('now', new DateTimeZone('America/Los_Angeles'));
690
                $response->modified($now);
691
                $now->setTimeZone(new DateTimeZone('UTC'));
692
                $this->assertEquals($now->format('D, j M Y H:i:s') . ' GMT', $response->modified());
693
                $response->expects($this->at(1))
694
                        ->method('_sendHeader')->with('Last-Modified', $now->format('D, j M Y H:i:s') . ' GMT');
695
                $response->send();
696

    
697
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
698
                $now = time();
699
                $response->modified($now);
700
                $this->assertEquals(gmdate('D, j M Y H:i:s', $now) . ' GMT', $response->modified());
701
                $response->expects($this->at(1))
702
                        ->method('_sendHeader')->with('Last-Modified', gmdate('D, j M Y H:i:s', $now) . ' GMT');
703
                $response->send();
704

    
705
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
706
                $time = new DateTime('+1 day', new DateTimeZone('UTC'));
707
                $response->modified('+1 day');
708
                $this->assertEquals($time->format('D, j M Y H:i:s') . ' GMT', $response->modified());
709
                $response->expects($this->at(1))
710
                        ->method('_sendHeader')->with('Last-Modified', $time->format('D, j M Y H:i:s') . ' GMT');
711
                $response->send();
712
        }
713

    
714
/**
715
 * Tests setting of public/private Cache-Control directives
716
 *
717
 * @return void
718
 */
719
        public function testSharable() {
720
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
721
                $this->assertNull($response->sharable());
722
                $response->sharable(true);
723
                $headers = $response->header();
724
                $this->assertEquals('public', $headers['Cache-Control']);
725
                $response->expects($this->at(1))
726
                        ->method('_sendHeader')->with('Cache-Control', 'public');
727
                $response->send();
728

    
729
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
730
                $response->sharable(false);
731
                $headers = $response->header();
732
                $this->assertEquals('private', $headers['Cache-Control']);
733
                $response->expects($this->at(1))
734
                        ->method('_sendHeader')->with('Cache-Control', 'private');
735
                $response->send();
736

    
737
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
738
                $response->sharable(true);
739
                $headers = $response->header();
740
                $this->assertEquals('public', $headers['Cache-Control']);
741
                $response->sharable(false);
742
                $headers = $response->header();
743
                $this->assertEquals('private', $headers['Cache-Control']);
744
                $response->expects($this->at(1))
745
                        ->method('_sendHeader')->with('Cache-Control', 'private');
746
                $response->send();
747
                $this->assertFalse($response->sharable());
748
                $response->sharable(true);
749
                $this->assertTrue($response->sharable());
750

    
751
                $response = new CakeResponse;
752
                $response->sharable(true, 3600);
753
                $headers = $response->header();
754
                $this->assertEquals('public, max-age=3600', $headers['Cache-Control']);
755

    
756
                $response = new CakeResponse;
757
                $response->sharable(false, 3600);
758
                $headers = $response->header();
759
                $this->assertEquals('private, max-age=3600', $headers['Cache-Control']);
760
                $response->send();
761
        }
762

    
763
/**
764
 * Tests setting of max-age Cache-Control directive
765
 *
766
 * @return void
767
 */
768
        public function testMaxAge() {
769
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
770
                $this->assertNull($response->maxAge());
771
                $response->maxAge(3600);
772
                $this->assertEquals(3600, $response->maxAge());
773
                $headers = $response->header();
774
                $this->assertEquals('max-age=3600', $headers['Cache-Control']);
775
                $response->expects($this->at(1))
776
                        ->method('_sendHeader')->with('Cache-Control', 'max-age=3600');
777
                $response->send();
778

    
779
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
780
                $response->maxAge(3600);
781
                $response->sharable(false);
782
                $headers = $response->header();
783
                $this->assertEquals('max-age=3600, private', $headers['Cache-Control']);
784
                $response->expects($this->at(1))
785
                        ->method('_sendHeader')->with('Cache-Control', 'max-age=3600, private');
786
                $response->send();
787
        }
788

    
789
/**
790
 * Tests setting of s-maxage Cache-Control directive
791
 *
792
 * @return void
793
 */
794
        public function testSharedMaxAge() {
795
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
796
                $this->assertNull($response->maxAge());
797
                $response->sharedMaxAge(3600);
798
                $this->assertEquals(3600, $response->sharedMaxAge());
799
                $headers = $response->header();
800
                $this->assertEquals('s-maxage=3600', $headers['Cache-Control']);
801
                $response->expects($this->at(1))
802
                        ->method('_sendHeader')->with('Cache-Control', 's-maxage=3600');
803
                $response->send();
804

    
805
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
806
                $response->sharedMaxAge(3600);
807
                $response->sharable(true);
808
                $headers = $response->header();
809
                $this->assertEquals('s-maxage=3600, public', $headers['Cache-Control']);
810
                $response->expects($this->at(1))
811
                        ->method('_sendHeader')->with('Cache-Control', 's-maxage=3600, public');
812
                $response->send();
813
        }
814

    
815
/**
816
 * Tests setting of must-revalidate Cache-Control directive
817
 *
818
 * @return void
819
 */
820
        public function testMustRevalidate() {
821
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
822
                $this->assertFalse($response->mustRevalidate());
823
                $response->mustRevalidate(true);
824
                $this->assertTrue($response->mustRevalidate());
825
                $headers = $response->header();
826
                $this->assertEquals('must-revalidate', $headers['Cache-Control']);
827
                $response->expects($this->at(1))
828
                        ->method('_sendHeader')->with('Cache-Control', 'must-revalidate');
829
                $response->send();
830
                $response->mustRevalidate(false);
831
                $this->assertFalse($response->mustRevalidate());
832

    
833
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
834
                $response->sharedMaxAge(3600);
835
                $response->mustRevalidate(true);
836
                $headers = $response->header();
837
                $this->assertEquals('s-maxage=3600, must-revalidate', $headers['Cache-Control']);
838
                $response->expects($this->at(1))
839
                        ->method('_sendHeader')->with('Cache-Control', 's-maxage=3600, must-revalidate');
840
                $response->send();
841
        }
842

    
843
/**
844
 * Tests getting/setting the Vary header
845
 *
846
 * @return void
847
 */
848
        public function testVary() {
849
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
850
                $response->vary('Accept-encoding');
851
                $this->assertEquals(array('Accept-encoding'), $response->vary());
852
                $response->expects($this->at(1))
853
                        ->method('_sendHeader')->with('Vary', 'Accept-encoding');
854
                $response->send();
855

    
856
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
857
                $response->vary(array('Accept-language', 'Accept-encoding'));
858
                $response->expects($this->at(1))
859
                        ->method('_sendHeader')->with('Vary', 'Accept-language, Accept-encoding');
860
                $response->send();
861
                $this->assertEquals(array('Accept-language', 'Accept-encoding'), $response->vary());
862
        }
863

    
864
/**
865
 * Tests getting/setting the Etag header
866
 *
867
 * @return void
868
 */
869
        public function testEtag() {
870
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
871
                $response->etag('something');
872
                $this->assertEquals('"something"', $response->etag());
873
                $response->expects($this->at(1))
874
                        ->method('_sendHeader')->with('Etag', '"something"');
875
                $response->send();
876

    
877
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
878
                $response->etag('something', true);
879
                $this->assertEquals('W/"something"', $response->etag());
880
                $response->expects($this->at(1))
881
                        ->method('_sendHeader')->with('Etag', 'W/"something"');
882
                $response->send();
883
        }
884

    
885
/**
886
 * Tests that the response is able to be marked as not modified
887
 *
888
 * @return void
889
 */
890
        public function testNotModified() {
891
                $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent'));
892
                $response->body('something');
893
                $response->statusCode(200);
894
                $response->length(100);
895
                $response->modified('now');
896
                $response->notModified();
897

    
898
                $this->assertEmpty($response->header());
899
                $this->assertEmpty($response->body());
900
                $this->assertEquals(304, $response->statusCode());
901
        }
902

    
903
/**
904
 * Test checkNotModified method
905
 *
906
 * @return void
907
 */
908
        public function testCheckNotModifiedByEtagStar() {
909
                $_SERVER['HTTP_IF_NONE_MATCH'] = '*';
910
                $response = $this->getMock('CakeResponse', array('notModified'));
911
                $response->etag('something');
912
                $response->expects($this->once())->method('notModified');
913
                $response->checkNotModified(new CakeRequest);
914
        }
915

    
916
/**
917
 * Test checkNotModified method
918
 *
919
 * @return void
920
 */
921
        public function testCheckNotModifiedByEtagExact() {
922
                $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"';
923
                $response = $this->getMock('CakeResponse', array('notModified'));
924
                $response->etag('something', true);
925
                $response->expects($this->once())->method('notModified');
926
                $this->assertTrue($response->checkNotModified(new CakeRequest));
927
        }
928

    
929
/**
930
 * Test checkNotModified method
931
 *
932
 * @return void
933
 */
934
        public function testCheckNotModifiedByEtagAndTime() {
935
                $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"';
936
                $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
937
                $response = $this->getMock('CakeResponse', array('notModified'));
938
                $response->etag('something', true);
939
                $response->modified('2012-01-01 00:00:00');
940
                $response->expects($this->once())->method('notModified');
941
                $this->assertTrue($response->checkNotModified(new CakeRequest));
942
        }
943

    
944
/**
945
 * Test checkNotModified method
946
 *
947
 * @return void
948
 */
949
        public function testCheckNotModifiedByEtagAndTimeMismatch() {
950
                $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"';
951
                $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
952
                $response = $this->getMock('CakeResponse', array('notModified'));
953
                $response->etag('something', true);
954
                $response->modified('2012-01-01 00:00:01');
955
                $response->expects($this->never())->method('notModified');
956
                $this->assertFalse($response->checkNotModified(new CakeRequest));
957
        }
958

    
959
/**
960
 * Test checkNotModified method
961
 *
962
 * @return void
963
 */
964
        public function testCheckNotModifiedByEtagMismatch() {
965
                $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something-else", "other"';
966
                $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
967
                $response = $this->getMock('CakeResponse', array('notModified'));
968
                $response->etag('something', true);
969
                $response->modified('2012-01-01 00:00:00');
970
                $response->expects($this->never())->method('notModified');
971
                $this->assertFalse($response->checkNotModified(new CakeRequest));
972
        }
973

    
974
/**
975
 * Test checkNotModified method
976
 *
977
 * @return void
978
 */
979
        public function testCheckNotModifiedByTime() {
980
                $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
981
                $response = $this->getMock('CakeResponse', array('notModified'));
982
                $response->modified('2012-01-01 00:00:00');
983
                $response->expects($this->once())->method('notModified');
984
                $this->assertTrue($response->checkNotModified(new CakeRequest));
985
        }
986

    
987
/**
988
 * Test checkNotModified method
989
 *
990
 * @return void
991
 */
992
        public function testCheckNotModifiedNoHints() {
993
                $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"';
994
                $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
995
                $response = $this->getMock('CakeResponse', array('notModified'));
996
                $response->expects($this->never())->method('notModified');
997
                $this->assertFalse($response->checkNotModified(new CakeRequest));
998
        }
999

    
1000
/**
1001
 * Test cookie setting
1002
 *
1003
 * @return void
1004
 */
1005
        public function testCookieSettings() {
1006
                $response = new CakeResponse();
1007
                $cookie = array(
1008
                        'name' => 'CakeTestCookie[Testing]'
1009
                );
1010
                $response->cookie($cookie);
1011
                $expected = array(
1012
                        'name' => 'CakeTestCookie[Testing]',
1013
                        'value' => '',
1014
                        'expire' => 0,
1015
                        'path' => '/',
1016
                        'domain' => '',
1017
                        'secure' => false,
1018
                        'httpOnly' => false);
1019
                $result = $response->cookie('CakeTestCookie[Testing]');
1020
                $this->assertEquals($expected, $result);
1021

    
1022
                $cookie = array(
1023
                        'name' => 'CakeTestCookie[Testing2]',
1024
                        'value' => '[a,b,c]',
1025
                        'expire' => 1000,
1026
                        'path' => '/test',
1027
                        'secure' => true
1028
                );
1029
                $response->cookie($cookie);
1030
                $expected = array(
1031
                        'CakeTestCookie[Testing]' => array(
1032
                                'name' => 'CakeTestCookie[Testing]',
1033
                                'value' => '',
1034
                                'expire' => 0,
1035
                                'path' => '/',
1036
                                'domain' => '',
1037
                                'secure' => false,
1038
                                'httpOnly' => false
1039
                        ),
1040
                        'CakeTestCookie[Testing2]' => array(
1041
                                'name' => 'CakeTestCookie[Testing2]',
1042
                                'value' => '[a,b,c]',
1043
                                'expire' => 1000,
1044
                                'path' => '/test',
1045
                                'domain' => '',
1046
                                'secure' => true,
1047
                                'httpOnly' => false
1048
                        )
1049
                );
1050

    
1051
                $result = $response->cookie();
1052
                $this->assertEquals($expected, $result);
1053

    
1054
                $cookie = $expected['CakeTestCookie[Testing]'];
1055
                $cookie['value'] = 'test';
1056
                $response->cookie($cookie);
1057
                $expected = array(
1058
                        'CakeTestCookie[Testing]' => array(
1059
                                'name' => 'CakeTestCookie[Testing]',
1060
                                'value' => 'test',
1061
                                'expire' => 0,
1062
                                'path' => '/',
1063
                                'domain' => '',
1064
                                'secure' => false,
1065
                                'httpOnly' => false
1066
                        ),
1067
                        'CakeTestCookie[Testing2]' => array(
1068
                                'name' => 'CakeTestCookie[Testing2]',
1069
                                'value' => '[a,b,c]',
1070
                                'expire' => 1000,
1071
                                'path' => '/test',
1072
                                'domain' => '',
1073
                                'secure' => true,
1074
                                'httpOnly' => false
1075
                        )
1076
                );
1077

    
1078
                $result = $response->cookie();
1079
                $this->assertEquals($expected, $result);
1080
        }
1081

    
1082
/**
1083
 * Test CORS
1084
 *
1085
 * @dataProvider corsData
1086
 * @param CakeRequest $request
1087
 * @param string $origin
1088
 * @param string|array $domains
1089
 * @param string|array $methods
1090
 * @param string|array $headers
1091
 * @param string|bool $expectedOrigin
1092
 * @param string|bool $expectedMethods
1093
 * @param string|bool $expectedHeaders
1094
 * @return void
1095
 */
1096
        public function testCors($request, $origin, $domains, $methods, $headers, $expectedOrigin, $expectedMethods = false, $expectedHeaders = false) {
1097
                $_SERVER['HTTP_ORIGIN'] = $origin;
1098

    
1099
                $response = $this->getMock('CakeResponse', array('header'));
1100

    
1101
                $method = $response->expects(!$expectedOrigin ? $this->never() : $this->at(0))->method('header');
1102
                $expectedOrigin && $method->with('Access-Control-Allow-Origin', $expectedOrigin ? $expectedOrigin : $this->anything());
1103

    
1104
                $i = 1;
1105
                if ($expectedMethods) {
1106
                        $response->expects($this->at($i++))
1107
                                ->method('header')
1108
                                ->with('Access-Control-Allow-Methods', $expectedMethods ? $expectedMethods : $this->anything());
1109
                }
1110
                if ($expectedHeaders) {
1111
                        $response->expects($this->at($i++))
1112
                                ->method('header')
1113
                                ->with('Access-Control-Allow-Headers', $expectedHeaders ? $expectedHeaders : $this->anything());
1114
                }
1115

    
1116
                $response->cors($request, $domains, $methods, $headers);
1117
                unset($_SERVER['HTTP_ORIGIN']);
1118
        }
1119

    
1120
/**
1121
 * Feed for testCors
1122
 *
1123
 * @return array
1124
 */
1125
        public function corsData() {
1126
                $fooRequest = new CakeRequest();
1127

    
1128
                $secureRequest = $this->getMock('CakeRequest', array('is'));
1129
                $secureRequest->expects($this->any())
1130
                        ->method('is')
1131
                        ->with('ssl')
1132
                        ->will($this->returnValue(true));
1133

    
1134
                return array(
1135
                        array($fooRequest, null, '*', '', '', false, false),
1136
                        array($fooRequest, 'http://www.foo.com', '*', '', '', '*', false),
1137
                        array($fooRequest, 'http://www.foo.com', 'www.foo.com', '', '', 'http://www.foo.com', false),
1138
                        array($fooRequest, 'http://www.foo.com', '*.foo.com', '', '', 'http://www.foo.com', false),
1139
                        array($fooRequest, 'http://www.foo.com', 'http://*.foo.com', '', '', 'http://www.foo.com', false),
1140
                        array($fooRequest, 'http://www.foo.com', 'https://www.foo.com', '', '', false, false),
1141
                        array($fooRequest, 'http://www.foo.com', 'https://*.foo.com', '', '', false, false),
1142
                        array($fooRequest, 'http://www.foo.com', array('*.bar.com', '*.foo.com'), '', '', 'http://www.foo.com', false),
1143

    
1144
                        array($secureRequest, 'https://www.bar.com', 'www.bar.com', '', '', 'https://www.bar.com', false),
1145
                        array($secureRequest, 'https://www.bar.com', 'http://www.bar.com', '', '', false, false),
1146
                        array($secureRequest, 'https://www.bar.com', '*.bar.com', '', '', 'https://www.bar.com', false),
1147

    
1148
                        array($fooRequest, 'http://www.foo.com', '*', 'GET', '', '*', 'GET'),
1149
                        array($fooRequest, 'http://www.foo.com', '*.foo.com', 'GET', '', 'http://www.foo.com', 'GET'),
1150
                        array($fooRequest, 'http://www.foo.com', '*.foo.com', array('GET', 'POST'), '', 'http://www.foo.com', 'GET, POST'),
1151

    
1152
                        array($fooRequest, 'http://www.foo.com', '*', '', 'X-CakePHP', '*', false, 'X-CakePHP'),
1153
                        array($fooRequest, 'http://www.foo.com', '*', '', array('X-CakePHP', 'X-MyApp'), '*', false, 'X-CakePHP, X-MyApp'),
1154
                        array($fooRequest, 'http://www.foo.com', '*', array('GET', 'OPTIONS'), array('X-CakePHP', 'X-MyApp'), '*', 'GET, OPTIONS', 'X-CakePHP, X-MyApp'),
1155
                );
1156
        }
1157

    
1158
/**
1159
 * testFileNotFound
1160
 *
1161
 * @expectedException NotFoundException
1162
 * @return void
1163
 */
1164
        public function testFileNotFound() {
1165
                $response = new CakeResponse();
1166
                $response->file('/some/missing/folder/file.jpg');
1167
        }
1168

    
1169
/**
1170
 * test file with ../
1171
 *
1172
 * @expectedException NotFoundException
1173
 * @expectedExceptionMessage The requested file contains `..` and will not be read.
1174
 * @return void
1175
 */
1176
        public function testFileWithForwardSlashPathTraversal() {
1177
                $response = new CakeResponse();
1178
                $response->file('my/../cat.gif');
1179
        }
1180

    
1181
/**
1182
 * test file with ..\
1183
 *
1184
 * @expectedException NotFoundException
1185
 * @expectedExceptionMessage The requested file contains `..` and will not be read.
1186
 * @return void
1187
 */
1188
        public function testFileWithBackwardSlashPathTraversal() {
1189
                $response = new CakeResponse();
1190
                $response->file('my\..\cat.gif');
1191
        }
1192

    
1193
/**
1194
 * Although unlikely, a file may contain dots in its filename.
1195
 * This should be allowed, as long as the dots doesn't specify a path (../ or ..\)
1196
 *
1197
 * @expectedException NotFoundException
1198
 * @execptedExceptionMessageRegExp #The requested file .+my/Some..cat.gif was not found or not readable#
1199
 * @return void
1200
 */
1201
        public function testFileWithDotsInFilename() {
1202
                $response = new CakeResponse();
1203
                $response->file('my/Some..cat.gif');
1204
        }
1205

    
1206
/**
1207
 * testFile method
1208
 *
1209
 * @return void
1210
 */
1211
        public function testFile() {
1212
                $response = $this->getMock('CakeResponse', array(
1213
                        'header',
1214
                        'type',
1215
                        '_sendHeader',
1216
                        '_setContentType',
1217
                        '_isActive',
1218
                        '_clearBuffer',
1219
                        '_flushBuffer'
1220
                ));
1221

    
1222
                $response->expects($this->exactly(1))
1223
                        ->method('type')
1224
                        ->with('css')
1225
                        ->will($this->returnArgument(0));
1226

    
1227
                $response->expects($this->at(1))
1228
                        ->method('header')
1229
                        ->with('Accept-Ranges', 'bytes');
1230

    
1231
                $response->expects($this->at(2))
1232
                        ->method('header')
1233
                        ->with('Content-Length', 38);
1234

    
1235
                $response->expects($this->once())->method('_clearBuffer');
1236
                $response->expects($this->once())->method('_flushBuffer');
1237

    
1238
                $response->expects($this->exactly(1))
1239
                        ->method('_isActive')
1240
                        ->will($this->returnValue(true));
1241

    
1242
                $response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css');
1243

    
1244
                ob_start();
1245
                $result = $response->send();
1246
                $output = ob_get_clean();
1247
                $this->assertEquals("/* this is the test asset css file */\n", $output);
1248
                $this->assertNotSame(false, $result);
1249
        }
1250

    
1251
/**
1252
 * testFileWithUnknownFileTypeGeneric method
1253
 *
1254
 * @return void
1255
 */
1256
        public function testFileWithUnknownFileTypeGeneric() {
1257
                $currentUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
1258
                $_SERVER['HTTP_USER_AGENT'] = 'Some generic browser';
1259

    
1260
                $response = $this->getMock('CakeResponse', array(
1261
                        'header',
1262
                        'type',
1263
                        'download',
1264
                        '_sendHeader',
1265
                        '_setContentType',
1266
                        '_isActive',
1267
                        '_clearBuffer',
1268
                        '_flushBuffer'
1269
                ));
1270

    
1271
                $response->expects($this->exactly(1))
1272
                        ->method('type')
1273
                        ->with('ini')
1274
                        ->will($this->returnValue(false));
1275

    
1276
                $response->expects($this->once())
1277
                        ->method('download')
1278
                        ->with('no_section.ini');
1279

    
1280
                $response->expects($this->at(2))
1281
                        ->method('header')
1282
                        ->with('Content-Transfer-Encoding', 'binary');
1283

    
1284
                $response->expects($this->at(3))
1285
                        ->method('header')
1286
                        ->with('Accept-Ranges', 'bytes');
1287

    
1288
                $response->expects($this->at(4))
1289
                        ->method('header')
1290
                        ->with('Content-Length', 35);
1291

    
1292
                $response->expects($this->once())->method('_clearBuffer');
1293
                $response->expects($this->once())->method('_flushBuffer');
1294

    
1295
                $response->expects($this->exactly(1))
1296
                        ->method('_isActive')
1297
                        ->will($this->returnValue(true));
1298

    
1299
                $response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'no_section.ini');
1300

    
1301
                ob_start();
1302
                $result = $response->send();
1303
                $output = ob_get_clean();
1304
                $this->assertEquals("some_key = some_value\nbool_key = 1\n", $output);
1305
                $this->assertNotSame(false, $result);
1306
                if ($currentUserAgent !== null) {
1307
                        $_SERVER['HTTP_USER_AGENT'] = $currentUserAgent;
1308
                }
1309
        }
1310

    
1311
/**
1312
 * testFileWithUnknownFileTypeOpera method
1313
 *
1314
 * @return void
1315
 */
1316
        public function testFileWithUnknownFileTypeOpera() {
1317
                $currentUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
1318
                $_SERVER['HTTP_USER_AGENT'] = 'Opera/9.80 (Windows NT 6.0; U; en) Presto/2.8.99 Version/11.10';
1319

    
1320
                $response = $this->getMock('CakeResponse', array(
1321
                        'header',
1322
                        'type',
1323
                        'download',
1324
                        '_sendHeader',
1325
                        '_setContentType',
1326
                        '_isActive',
1327
                        '_clearBuffer',
1328
                        '_flushBuffer'
1329
                ));
1330

    
1331
                $response->expects($this->at(0))
1332
                        ->method('type')
1333
                        ->with('ini')
1334
                        ->will($this->returnValue(false));
1335

    
1336
                $response->expects($this->at(1))
1337
                        ->method('type')
1338
                        ->with('application/octet-stream')
1339
                        ->will($this->returnValue(false));
1340

    
1341
                $response->expects($this->once())
1342
                        ->method('download')
1343
                        ->with('no_section.ini');
1344

    
1345
                $response->expects($this->at(3))
1346
                        ->method('header')
1347
                        ->with('Content-Transfer-Encoding', 'binary');
1348

    
1349
                $response->expects($this->at(4))
1350
                        ->method('header')
1351
                        ->with('Accept-Ranges', 'bytes');
1352

    
1353
                $response->expects($this->at(5))
1354
                        ->method('header')
1355
                        ->with('Content-Length', 35);
1356

    
1357
                $response->expects($this->once())->method('_clearBuffer');
1358
                $response->expects($this->once())->method('_flushBuffer');
1359
                $response->expects($this->exactly(1))
1360
                        ->method('_isActive')
1361
                        ->will($this->returnValue(true));
1362

    
1363
                $response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'no_section.ini');
1364

    
1365
                ob_start();
1366
                $result = $response->send();
1367
                $output = ob_get_clean();
1368
                $this->assertEquals("some_key = some_value\nbool_key = 1\n", $output);
1369
                $this->assertNotSame(false, $result);
1370
                if ($currentUserAgent !== null) {
1371
                        $_SERVER['HTTP_USER_AGENT'] = $currentUserAgent;
1372
                }
1373
        }
1374

    
1375
/**
1376
 * testFileWithUnknownFileTypeIE method
1377
 *
1378
 * @return void
1379
 */
1380
        public function testFileWithUnknownFileTypeIE() {
1381
                $currentUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
1382
                $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; Media Center PC 4.0; SLCC1; .NET CLR 3.0.04320)';
1383

    
1384
                $response = $this->getMock('CakeResponse', array(
1385
                        'header',
1386
                        'type',
1387
                        'download',
1388
                        '_sendHeader',
1389
                        '_setContentType',
1390
                        '_isActive',
1391
                        '_clearBuffer',
1392
                        '_flushBuffer'
1393
                ));
1394

    
1395
                $response->expects($this->at(0))
1396
                        ->method('type')
1397
                        ->with('ini')
1398
                        ->will($this->returnValue(false));
1399

    
1400
                $response->expects($this->at(1))
1401
                        ->method('type')
1402
                        ->with('application/force-download')
1403
                        ->will($this->returnValue(false));
1404

    
1405
                $response->expects($this->once())
1406
                        ->method('download')
1407
                        ->with('config.ini');
1408

    
1409
                $response->expects($this->at(3))
1410
                        ->method('header')
1411
                        ->with('Content-Transfer-Encoding', 'binary');
1412

    
1413
                $response->expects($this->at(4))
1414
                        ->method('header')
1415
                        ->with('Accept-Ranges', 'bytes');
1416

    
1417
                $response->expects($this->at(5))
1418
                        ->method('header')
1419
                        ->with('Content-Length', 35);
1420

    
1421
                $response->expects($this->once())->method('_clearBuffer');
1422
                $response->expects($this->once())->method('_flushBuffer');
1423
                $response->expects($this->exactly(1))
1424
                        ->method('_isActive')
1425
                        ->will($this->returnValue(true));
1426

    
1427
                $response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'no_section.ini', array(
1428
                        'name' => 'config.ini'
1429
                ));
1430

    
1431
                ob_start();
1432
                $result = $response->send();
1433
                $output = ob_get_clean();
1434
                $this->assertEquals("some_key = some_value\nbool_key = 1\n", $output);
1435
                $this->assertNotSame(false, $result);
1436
                if ($currentUserAgent !== null) {
1437
                        $_SERVER['HTTP_USER_AGENT'] = $currentUserAgent;
1438
                }
1439
        }
1440
/**
1441
 * testFileWithUnknownFileNoDownload method
1442
 *
1443
 * @return void
1444
 */
1445
        public function testFileWithUnknownFileNoDownload() {
1446
                $currentUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
1447
                $_SERVER['HTTP_USER_AGENT'] = 'Some generic browser';
1448

    
1449
                $response = $this->getMock('CakeResponse', array(
1450
                        'header',
1451
                        'type',
1452
                        'download',
1453
                        '_sendHeader',
1454
                        '_setContentType',
1455
                        '_isActive',
1456
                        '_clearBuffer',
1457
                        '_flushBuffer'
1458
                ));
1459

    
1460
                $response->expects($this->exactly(1))
1461
                        ->method('type')
1462
                        ->with('ini')
1463
                        ->will($this->returnValue(false));
1464

    
1465
                $response->expects($this->at(1))
1466
                        ->method('header')
1467
                        ->with('Accept-Ranges', 'bytes');
1468

    
1469
                $response->expects($this->never())
1470
                        ->method('download');
1471

    
1472
                $response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'no_section.ini', array(
1473
                        'download' => false
1474
                ));
1475

    
1476
                if ($currentUserAgent !== null) {
1477
                        $_SERVER['HTTP_USER_AGENT'] = $currentUserAgent;
1478
                }
1479
        }
1480

    
1481
/**
1482
 * testConnectionAbortedOnBuffering method
1483
 *
1484
 * @return void
1485
 */
1486
        public function testConnectionAbortedOnBuffering() {
1487
                $response = $this->getMock('CakeResponse', array(
1488
                        'header',
1489
                        'type',
1490
                        'download',
1491
                        '_sendHeader',
1492
                        '_setContentType',
1493
                        '_isActive',
1494
                        '_clearBuffer',
1495
                        '_flushBuffer'
1496
                ));
1497

    
1498
                $response->expects($this->any())
1499
                        ->method('type')
1500
                        ->with('css')
1501
                        ->will($this->returnArgument(0));
1502

    
1503
                $response->expects($this->at(0))
1504
                        ->method('_isActive')
1505
                        ->will($this->returnValue(false));
1506

    
1507
                $response->expects($this->once())->method('_clearBuffer');
1508
                $response->expects($this->never())->method('_flushBuffer');
1509

    
1510
                $response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css');
1511

    
1512
                $result = $response->send();
1513
                $this->assertNull($result);
1514
        }
1515

    
1516
/**
1517
 * Test downloading files with UPPERCASE extensions.
1518
 *
1519
 * @return void
1520
 */
1521
        public function testFileUpperExtension() {
1522
                $response = $this->getMock('CakeResponse', array(
1523
                        'header',
1524
                        'type',
1525
                        'download',
1526
                        '_sendHeader',
1527
                        '_setContentType',
1528
                        '_isActive',
1529
                        '_clearBuffer',
1530
                        '_flushBuffer'
1531
                ));
1532

    
1533
                $response->expects($this->any())
1534
                        ->method('type')
1535
                        ->with('jpg')
1536
                        ->will($this->returnArgument(0));
1537

    
1538
                $response->expects($this->at(0))
1539
                        ->method('_isActive')
1540
                        ->will($this->returnValue(true));
1541

    
1542
                $response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'img' . DS . 'test_2.JPG');
1543
        }
1544

    
1545
/**
1546
 * Test downloading files with extension not explicitly set.
1547
 *
1548
 * @return void
1549
 */
1550
        public function testFileExtensionNotSet() {
1551
                $response = $this->getMock('CakeResponse', array(
1552
                        'header',
1553
                        'type',
1554
                        'download',
1555
                        '_sendHeader',
1556
                        '_setContentType',
1557
                        '_isActive',
1558
                        '_clearBuffer',
1559
                        '_flushBuffer'
1560
                ));
1561

    
1562
                $response->expects($this->any())
1563
                        ->method('type')
1564
                        ->with('jpg')
1565
                        ->will($this->returnArgument(0));
1566

    
1567
                $response->expects($this->at(0))
1568
                        ->method('_isActive')
1569
                        ->will($this->returnValue(true));
1570

    
1571
                $response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'img' . DS . 'test_2.JPG');
1572
        }
1573

    
1574
/**
1575
 * A data provider for testing various ranges
1576
 *
1577
 * @return array
1578
 */
1579
        public static function rangeProvider() {
1580
                return array(
1581
                        // suffix-byte-range
1582
                        array(
1583
                                'bytes=-25', 25, 'bytes 13-37/38'
1584
                        ),
1585

    
1586
                        array(
1587
                                'bytes=0-', 38, 'bytes 0-37/38'
1588
                        ),
1589
                        array(
1590
                                'bytes=10-', 28, 'bytes 10-37/38'
1591
                        ),
1592
                        array(
1593
                                'bytes=10-20', 11, 'bytes 10-20/38'
1594
                        ),
1595
                );
1596
        }
1597

    
1598
/**
1599
 * Test the various range offset types.
1600
 *
1601
 * @dataProvider rangeProvider
1602
 * @return void
1603
 */
1604
        public function testFileRangeOffsets($range, $length, $offsetResponse) {
1605
                $_SERVER['HTTP_RANGE'] = $range;
1606
                $response = $this->getMock('CakeResponse', array(
1607
                        'header',
1608
                        'type',
1609
                        '_sendHeader',
1610
                        '_isActive',
1611
                        '_clearBuffer',
1612
                        '_flushBuffer'
1613
                ));
1614

    
1615
                $response->expects($this->at(1))
1616
                        ->method('header')
1617
                        ->with('Content-Disposition', 'attachment; filename="test_asset.css"');
1618

    
1619
                $response->expects($this->at(2))
1620
                        ->method('header')
1621
                        ->with('Content-Transfer-Encoding', 'binary');
1622

    
1623
                $response->expects($this->at(3))
1624
                        ->method('header')
1625
                        ->with('Accept-Ranges', 'bytes');
1626

    
1627
                $response->expects($this->at(4))
1628
                        ->method('header')
1629
                        ->with(array(
1630
                                'Content-Length' => $length,
1631
                                'Content-Range' => $offsetResponse,
1632
                        ));
1633

    
1634
                $response->expects($this->any())
1635
                        ->method('_isActive')
1636
                        ->will($this->returnValue(true));
1637

    
1638
                $response->file(
1639
                        CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css',
1640
                        array('download' => true)
1641
                );
1642

    
1643
                ob_start();
1644
                $result = $response->send();
1645
                ob_get_clean();
1646
        }
1647

    
1648
/**
1649
 * Test fetching ranges from a file.
1650
 *
1651
 * @return void
1652
 */
1653
        public function testFileRange() {
1654
                $_SERVER['HTTP_RANGE'] = 'bytes=8-25';
1655
                $response = $this->getMock('CakeResponse', array(
1656
                        'header',
1657
                        'type',
1658
                        '_sendHeader',
1659
                        '_setContentType',
1660
                        '_isActive',
1661
                        '_clearBuffer',
1662
                        '_flushBuffer'
1663
                ));
1664

    
1665
                $response->expects($this->exactly(1))
1666
                        ->method('type')
1667
                        ->with('css')
1668
                        ->will($this->returnArgument(0));
1669

    
1670
                $response->expects($this->at(1))
1671
                        ->method('header')
1672
                        ->with('Content-Disposition', 'attachment; filename="test_asset.css"');
1673

    
1674
                $response->expects($this->at(2))
1675
                        ->method('header')
1676
                        ->with('Content-Transfer-Encoding', 'binary');
1677

    
1678
                $response->expects($this->at(3))
1679
                        ->method('header')
1680
                        ->with('Accept-Ranges', 'bytes');
1681

    
1682
                $response->expects($this->at(4))
1683
                        ->method('header')
1684
                        ->with(array(
1685
                                'Content-Length' => 18,
1686
                                'Content-Range' => 'bytes 8-25/38',
1687
                        ));
1688

    
1689
                $response->expects($this->once())->method('_clearBuffer');
1690

    
1691
                $response->expects($this->any())
1692
                        ->method('_isActive')
1693
                        ->will($this->returnValue(true));
1694

    
1695
                $response->file(
1696
                        CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css',
1697
                        array('download' => true)
1698
                );
1699

    
1700
                ob_start();
1701
                $result = $response->send();
1702
                $output = ob_get_clean();
1703
                $this->assertEquals(206, $response->statusCode());
1704
                $this->assertEquals("is the test asset ", $output);
1705
                $this->assertNotSame(false, $result);
1706
        }
1707

    
1708
/**
1709
 * Test invalid file ranges.
1710
 *
1711
 * @return void
1712
 */
1713
        public function testFileRangeInvalid() {
1714
                $_SERVER['HTTP_RANGE'] = 'bytes=30-2';
1715
                $response = $this->getMock('CakeResponse', array(
1716
                        'header',
1717
                        'type',
1718
                        '_sendHeader',
1719
                        '_setContentType',
1720
                        '_isActive',
1721
                        '_clearBuffer',
1722
                        '_flushBuffer'
1723
                ));
1724

    
1725
                $response->expects($this->at(1))
1726
                        ->method('header')
1727
                        ->with('Content-Disposition', 'attachment; filename="test_asset.css"');
1728

    
1729
                $response->expects($this->at(2))
1730
                        ->method('header')
1731
                        ->with('Content-Transfer-Encoding', 'binary');
1732

    
1733
                $response->expects($this->at(3))
1734
                        ->method('header')
1735
                        ->with('Accept-Ranges', 'bytes');
1736

    
1737
                $response->expects($this->at(4))
1738
                        ->method('header')
1739
                        ->with(array(
1740
                                'Content-Range' => 'bytes 0-37/38',
1741
                        ));
1742

    
1743
                $response->file(
1744
                        CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css',
1745
                        array('download' => true)
1746
                );
1747

    
1748
                $this->assertEquals(416, $response->statusCode());
1749
                $response->send();
1750
        }
1751

    
1752
/**
1753
 * testFileRangeOffsetsNoDownload method
1754
 *
1755
 * @dataProvider rangeProvider
1756
 * @return void
1757
 */
1758
        public function testFileRangeOffsetsNoDownload($range, $length, $offsetResponse) {
1759
                $_SERVER['HTTP_RANGE'] = $range;
1760
                $response = $this->getMock('CakeResponse', array(
1761
                        'header',
1762
                        'type',
1763
                        '_sendHeader',
1764
                        '_isActive',
1765
                        '_clearBuffer',
1766
                        '_flushBuffer'
1767
                ));
1768

    
1769
                $response->expects($this->at(1))
1770
                        ->method('header')
1771
                        ->with('Accept-Ranges', 'bytes');
1772

    
1773
                $response->expects($this->at(2))
1774
                        ->method('header')
1775
                        ->with(array(
1776
                                'Content-Length' => $length,
1777
                                'Content-Range' => $offsetResponse,
1778
                        ));
1779

    
1780
                $response->expects($this->any())
1781
                        ->method('_isActive')
1782
                        ->will($this->returnValue(true));
1783

    
1784
                $response->file(
1785
                        CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css',
1786
                        array('download' => false)
1787
                );
1788

    
1789
                ob_start();
1790
                $response->send();
1791
                ob_get_clean();
1792
        }
1793

    
1794
/**
1795
 * testFileRangeNoDownload method
1796
 *
1797
 * @return void
1798
 */
1799
        public function testFileRangeNoDownload() {
1800
                $_SERVER['HTTP_RANGE'] = 'bytes=8-25';
1801
                $response = $this->getMock('CakeResponse', array(
1802
                        'header',
1803
                        'type',
1804
                        '_sendHeader',
1805
                        '_setContentType',
1806
                        '_isActive',
1807
                        '_clearBuffer',
1808
                        '_flushBuffer'
1809
                ));
1810

    
1811
                $response->expects($this->exactly(1))
1812
                        ->method('type')
1813
                        ->with('css')
1814
                        ->will($this->returnArgument(0));
1815

    
1816
                $response->expects($this->at(1))
1817
                        ->method('header')
1818
                        ->with('Accept-Ranges', 'bytes');
1819

    
1820
                $response->expects($this->at(2))
1821
                        ->method('header')
1822
                        ->with(array(
1823
                                'Content-Length' => 18,
1824
                                'Content-Range' => 'bytes 8-25/38',
1825
                        ));
1826

    
1827
                $response->expects($this->once())->method('_clearBuffer');
1828

    
1829
                $response->expects($this->any())
1830
                        ->method('_isActive')
1831
                        ->will($this->returnValue(true));
1832

    
1833
                $response->file(
1834
                        CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css',
1835
                        array('download' => false)
1836
                );
1837

    
1838
                ob_start();
1839
                $result = $response->send();
1840
                $output = ob_get_clean();
1841
                $this->assertEquals(206, $response->statusCode());
1842
                $this->assertEquals("is the test asset ", $output);
1843
                $this->assertNotSame(false, $result);
1844
        }
1845

    
1846
/**
1847
 * testFileRangeInvalidNoDownload method
1848
 *
1849
 * @return void
1850
 */
1851
        public function testFileRangeInvalidNoDownload() {
1852
                $_SERVER['HTTP_RANGE'] = 'bytes=30-2';
1853
                $response = $this->getMock('CakeResponse', array(
1854
                        'header',
1855
                        'type',
1856
                        '_sendHeader',
1857
                        '_setContentType',
1858
                        '_isActive',
1859
                        '_clearBuffer',
1860
                        '_flushBuffer'
1861
                ));
1862

    
1863
                $response->expects($this->at(1))
1864
                        ->method('header')
1865
                        ->with('Accept-Ranges', 'bytes');
1866

    
1867
                $response->expects($this->at(2))
1868
                        ->method('header')
1869
                        ->with(array(
1870
                                'Content-Range' => 'bytes 0-37/38',
1871
                        ));
1872

    
1873
                $response->file(
1874
                        CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css',
1875
                        array('download' => false)
1876
                );
1877

    
1878
                $this->assertEquals(416, $response->statusCode());
1879
                $response->send();
1880
        }
1881

    
1882
/**
1883
 * Test the location method.
1884
 *
1885
 * @return void
1886
 */
1887
        public function testLocation() {
1888
                $response = new CakeResponse();
1889
                $this->assertNull($response->location(), 'No header should be set.');
1890
                $this->assertNull($response->location('http://example.org'), 'Setting a location should return null');
1891
                $this->assertEquals('http://example.org', $response->location(), 'Reading a location should return the value.');
1892
        }
1893

    
1894
}