PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/aws/aws-sdk-php/tests/Aws/Tests/S3/StreamWrapperTest.php

https://github.com/lslucas/105fm
PHP | 528 lines | 370 code | 68 blank | 90 comment | 2 complexity | 15e59f578e86203c9dbf2f0b2683074d MD5 | raw file
  1. <?php
  2. /**
  3. * Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License").
  6. * You may not use this file except in compliance with the License.
  7. * A copy of the License is located at
  8. *
  9. * http://aws.amazon.com/apache2.0
  10. *
  11. * or in the "license" file accompanying this file. This file is distributed
  12. * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  13. * express or implied. See the License for the specific language governing
  14. * permissions and limitations under the License.
  15. */
  16. namespace Aws\Tests\S3;
  17. use Aws\S3\S3Client;
  18. use Aws\S3\StreamWrapper;
  19. use Guzzle\Http\Message\Response;
  20. use Guzzle\Http\EntityBody;
  21. /**
  22. * @covers Aws\S3\StreamWrapper
  23. */
  24. class StreamWrapperTest extends \Guzzle\Tests\GuzzleTestCase
  25. {
  26. /**
  27. * @var S3Client
  28. */
  29. protected $client;
  30. public function setUp()
  31. {
  32. $this->client = $this->getServiceBuilder()->get('s3', true);
  33. StreamWrapper::register($this->client);
  34. }
  35. public function tearDown()
  36. {
  37. stream_wrapper_unregister('s3');
  38. }
  39. public function testRegistersStreamWrapper()
  40. {
  41. StreamWrapper::register($this->client);
  42. $this->assertContains('s3', stream_get_wrappers());
  43. // Ensure no error is thrown for registering twice
  44. StreamWrapper::register($this->client);
  45. }
  46. /**
  47. * @expectedException PHPUnit_Framework_Error_Warning
  48. * @expectedExceptionMessage Cannot open a bucket
  49. */
  50. public function testCannotOpenBuckets()
  51. {
  52. fopen('s3://bucket', 'r');
  53. }
  54. /**
  55. * @expectedException PHPUnit_Framework_Error_Warning
  56. * @expectedExceptionMessage simultaneous reading and writing
  57. */
  58. public function testCannotReadWriteStreams()
  59. {
  60. fopen('s3://bucket/key', 'r+');
  61. }
  62. /**
  63. * @expectedException PHPUnit_Framework_Error_Warning
  64. * @expectedExceptionMessage Mode not supported
  65. */
  66. public function testSupportsOnlyReadWriteXA()
  67. {
  68. fopen('s3://bucket/key', 'c');
  69. }
  70. /**
  71. * @expectedException PHPUnit_Framework_Error_Warning
  72. * @expectedExceptionMessage s3://bucket/key already exists on Amazon S3
  73. */
  74. public function testValidatesXMode()
  75. {
  76. $this->setMockResponse($this->client, array(new Response(200)));
  77. fopen('s3://bucket/key', 'x');
  78. }
  79. public function testSuccessfulXMode()
  80. {
  81. $this->setMockResponse($this->client, array(new Response(404), new Response(200)));
  82. $r = fopen('s3://bucket/key', 'x');
  83. fclose($r);
  84. }
  85. /**
  86. * @expectedException RuntimeException
  87. * @expectedExceptionMessage simultaneous reading and writing
  88. */
  89. public function testCanThrowExceptionsInsteadOfErrors()
  90. {
  91. fopen('s3://bucket/key', 'r+', false, stream_context_create(array(
  92. 's3' => array('throw_exceptions' => true)
  93. )));
  94. }
  95. public function testOpensNonSeekableReadStream()
  96. {
  97. $stream = fopen('php://temp', 'r+');
  98. fwrite($stream, 'testing 123');
  99. fseek($stream, 0);
  100. $mock = $this->getMockBuilder('Guzzle\Http\EntityBody')
  101. ->setConstructorArgs(array($stream))
  102. ->setMethods(array('seek'))
  103. ->getMock();
  104. $mock->expects($this->any())
  105. ->method('seek')
  106. ->will($this->returnValue(false));
  107. $f = $this->getMockBuilder('Guzzle\Stream\PhpStreamRequestFactory')
  108. ->setMethods(array('createStream'))
  109. ->getMock();
  110. $f->expects($this->once())
  111. ->method('createStream')
  112. ->will($this->returnValue($mock));
  113. $s = fopen('s3://bucket/ket', 'r', false, stream_context_create(array(
  114. 's3' => array('stream_factory' => $f)
  115. )));
  116. $this->assertEquals(0, ftell($s));
  117. $this->assertFalse(feof($s));
  118. $this->assertEquals('test', fread($s, 4));
  119. $this->assertEquals(4, ftell($s));
  120. $this->assertEquals(-1, fseek($s, 0));
  121. $this->assertEquals('', stream_get_contents($s));
  122. $this->assertTrue(feof($s));
  123. $this->assertTrue(fclose($s));
  124. }
  125. public function testOpensSeekableReadStream()
  126. {
  127. $stream = fopen('php://temp', 'r+');
  128. fwrite($stream, 'testing 123');
  129. fseek($stream, 0);
  130. $mock = $this->getMockBuilder('Guzzle\Http\EntityBody')
  131. ->setConstructorArgs(array($stream))
  132. ->setMethods(array('seek'))
  133. ->getMock();
  134. $mock->expects($this->any())
  135. ->method('seek')
  136. ->will($this->returnValue(false));
  137. $f = $this->getMockBuilder('Guzzle\Stream\PhpStreamRequestFactory')
  138. ->setMethods(array('createStream'))
  139. ->getMock();
  140. $f->expects($this->once())
  141. ->method('createStream')
  142. ->will($this->returnValue($mock));
  143. $s = fopen('s3://bucket/ket', 'r', false, stream_context_create(array(
  144. 's3' => array('stream_factory' => $f, 'seekable' => true)
  145. )));
  146. $this->assertEquals(0, ftell($s));
  147. $this->assertFalse(feof($s));
  148. $this->assertEquals('test', fread($s, 4));
  149. $this->assertEquals(4, ftell($s));
  150. $this->assertEquals(0, fseek($s, 0));
  151. $this->assertEquals('testing 123', stream_get_contents($s));
  152. $this->assertTrue(feof($s));
  153. $this->assertTrue(fclose($s));
  154. }
  155. public function testCanOpenWriteOnlyStreams()
  156. {
  157. $this->setMockResponse($this->client, array(new Response(204)));
  158. $s = fopen('s3://bucket/key', 'w');
  159. $this->assertEquals(4, fwrite($s, 'test'));
  160. $this->assertTrue(fclose($s));
  161. // Ensure that the stream was flushed and sent the upload
  162. $requests = $this->getMockedRequests();
  163. $this->assertEquals(1, count($requests));
  164. $this->assertEquals('PUT', $requests[0]->getMethod());
  165. $this->assertEquals('test', (string) $requests[0]->getBody());
  166. $this->assertEquals(4, (string) $requests[0]->getHeader('Content-Length'));
  167. }
  168. /**
  169. * @expectedException PHPUnit_Framework_Error_Warning
  170. * @expectedExceptionMessage 403 Forbidden
  171. */
  172. public function testTriggersErrorInsteadOfExceptionWhenWriteFlushFails()
  173. {
  174. $this->setMockResponse($this->client, array(new Response(403)));
  175. $s = fopen('s3://bucket/key', 'w');
  176. fwrite($s, 'test');
  177. fclose($s);
  178. }
  179. public function testCanOpenAppendStreamsWithOriginalFile()
  180. {
  181. // Queue the 200 response that will load the original, and queue the 204 flush response
  182. $this->setMockResponse($this->client, array(
  183. new Response(200, null, 'test'),
  184. new Response(204)
  185. ));
  186. $s = fopen('s3://bucket/key', 'a');
  187. $this->assertEquals(4, ftell($s));
  188. $this->assertEquals(3, fwrite($s, 'ing'));
  189. $this->assertTrue(fclose($s));
  190. // Ensure that the stream was flushed and sent the upload
  191. $requests = $this->getMockedRequests();
  192. $this->assertEquals(2, count($requests));
  193. $this->assertEquals('GET', $requests[0]->getMethod());
  194. $this->assertEquals('/key', $requests[0]->getResource());
  195. $this->assertEquals('PUT', $requests[1]->getMethod());
  196. $this->assertEquals('/key', $requests[1]->getResource());
  197. $this->assertEquals('testing', (string) $requests[1]->getBody());
  198. $this->assertEquals(7, (string) $requests[1]->getHeader('Content-Length'));
  199. }
  200. public function testCanOpenAppendStreamsWithMissingFile()
  201. {
  202. $this->setMockResponse($this->client, array(
  203. new Response(404),
  204. new Response(204)
  205. ));
  206. $s = fopen('s3://bucket/key', 'a');
  207. $this->assertEquals(0, ftell($s));
  208. $this->assertTrue(fclose($s));
  209. }
  210. public function testCanUnlinkFiles()
  211. {
  212. $this->setMockResponse($this->client, array(new Response(204)));
  213. $this->assertTrue(unlink('s3://bucket/key'));
  214. $requests = $this->getMockedRequests();
  215. $this->assertEquals(1, count($requests));
  216. $this->assertEquals('DELETE', $requests[0]->getMethod());
  217. $this->assertEquals('/key', $requests[0]->getResource());
  218. $this->assertEquals('bucket.s3.amazonaws.com', $requests[0]->getHost());
  219. }
  220. /**
  221. * @expectedException PHPUnit_Framework_Error_Warning
  222. * @expectedExceptionMessage 403 Forbidden
  223. */
  224. public function testThrowsErrorsWhenUnlinkFails()
  225. {
  226. $this->setMockResponse($this->client, array(new Response(403)));
  227. $this->assertFalse(unlink('s3://bucket/key'));
  228. }
  229. public function testCreatingBucketWithNoBucketReturnsFalse()
  230. {
  231. $this->assertFalse(mkdir('s3://'));
  232. }
  233. public function testCreatingBucketWithKeyReturnsFalse()
  234. {
  235. $this->assertFalse(mkdir('s3://foo/bar'));
  236. }
  237. /**
  238. * @expectedException PHPUnit_Framework_Error_Warning
  239. * @expectedExceptionMessage 403 Forbidden
  240. */
  241. public function testCreatingBucketWithExceptionRaisesError()
  242. {
  243. $this->setMockResponse($this->client, array(new Response(403)));
  244. $this->assertFalse(mkdir('s3://bucket'));
  245. }
  246. public function testCreatingBucketsSetsAclBasedOnPermissions()
  247. {
  248. $this->setMockResponse($this->client, array(new Response(204), new Response(204), new Response(204)));
  249. $this->assertTrue(mkdir('s3://bucket', 0777));
  250. $this->assertTrue(mkdir('s3://bucket', 0601));
  251. $this->assertTrue(mkdir('s3://bucket', 0500));
  252. $requests = $this->getMockedRequests();
  253. $this->assertEquals(3, count($requests));
  254. $this->assertEquals('PUT', $requests[0]->getMethod());
  255. $this->assertEquals('/', $requests[0]->getResource());
  256. $this->assertEquals('bucket.s3.amazonaws.com', $requests[0]->getHost());
  257. $this->assertContains('public-read', (string) $requests[0]);
  258. $this->assertContains('authenticated-read', (string) $requests[1]);
  259. $this->assertContains('private', (string) $requests[2]);
  260. }
  261. /**
  262. * @expectedException PHPUnit_Framework_Error_Warning
  263. * @expectedExceptionMessage Please specify a bucket
  264. */
  265. public function testCannotDeleteS3()
  266. {
  267. rmdir('s3://');
  268. }
  269. /**
  270. * @expectedException PHPUnit_Framework_Error_Warning
  271. * @expectedExceptionMessage rmdir() only supports bucket deletion
  272. */
  273. public function testCannotDeleteKeyPrefix()
  274. {
  275. rmdir('s3://bucket/key');
  276. }
  277. /**
  278. * @expectedException PHPUnit_Framework_Error_Warning
  279. * @expectedExceptionMessage 403 Forbidden
  280. */
  281. public function testRmDirWithExceptionTriggersError()
  282. {
  283. $this->setMockResponse($this->client, array(new Response(403)));
  284. rmdir('s3://bucket');
  285. }
  286. public function testCanDeleteBucketWithRmDir()
  287. {
  288. $this->setMockResponse($this->client, array(new Response(204)));
  289. $this->assertTrue(rmdir('s3://bucket'));
  290. $requests = $this->getMockedRequests();
  291. $this->assertEquals(1, count($requests));
  292. $this->assertEquals('DELETE', $requests[0]->getMethod());
  293. $this->assertEquals('/', $requests[0]->getResource());
  294. $this->assertEquals('bucket.s3.amazonaws.com', $requests[0]->getHost());
  295. }
  296. /**
  297. * @expectedException PHPUnit_Framework_Error_Warning
  298. * @expectedExceptionMessage The Amazon S3 stream wrapper only supports copying objects
  299. */
  300. public function testRenameEnsuresKeyIsSet()
  301. {
  302. rename('s3://foo/bar', 's3://baz');
  303. }
  304. /**
  305. * @expectedException PHPUnit_Framework_Error_Warning
  306. * @expectedExceptionMessage Forbidden
  307. */
  308. public function testRenameWithExceptionThrowsError()
  309. {
  310. $this->setMockResponse($this->client, array(new Response(403)));
  311. rename('s3://foo/bar', 's3://baz/bar');
  312. }
  313. public function testCanRenameObjects()
  314. {
  315. $this->setMockResponse($this->client, array(new Response(204), new Response(204)));
  316. $this->assertTrue(rename('s3://bucket/key', 's3://other/new_key'));
  317. $requests = $this->getMockedRequests();
  318. $this->assertEquals(2, count($requests));
  319. $this->assertEquals('PUT', $requests[0]->getMethod());
  320. $this->assertEquals('/new_key', $requests[0]->getResource());
  321. $this->assertEquals('other.s3.amazonaws.com', $requests[0]->getHost());
  322. $this->assertEquals('/bucket/key', (string) $requests[0]->getHeader('x-amz-copy-source'));
  323. $this->assertEquals('COPY', (string) $requests[0]->getHeader('x-amz-metadata-directive'));
  324. $this->assertEquals('DELETE', $requests[1]->getMethod());
  325. $this->assertEquals('/key', $requests[1]->getResource());
  326. $this->assertEquals('bucket.s3.amazonaws.com', $requests[1]->getHost());
  327. }
  328. public function testCanRenameObjectsWithCustomSettings()
  329. {
  330. $this->setMockResponse($this->client, array(new Response(204), new Response(204)));
  331. $this->assertTrue(rename('s3://bucket/key', 's3://other/new_key', stream_context_create(array(
  332. 's3' => array('MetadataDirective' => 'REPLACE')
  333. ))));
  334. $requests = $this->getMockedRequests();
  335. $this->assertEquals(2, count($requests));
  336. $this->assertEquals('PUT', $requests[0]->getMethod());
  337. $this->assertEquals('/new_key', $requests[0]->getResource());
  338. $this->assertEquals('other.s3.amazonaws.com', $requests[0]->getHost());
  339. $this->assertEquals('/bucket/key', (string) $requests[0]->getHeader('x-amz-copy-source'));
  340. $this->assertEquals('REPLACE', (string) $requests[0]->getHeader('x-amz-metadata-directive'));
  341. }
  342. public function testProvidesDirectoriesForS3()
  343. {
  344. $this->setMockResponse($this->client, array(
  345. 's3/list_objects_page_1',
  346. 's3/list_objects_page_2',
  347. 's3/list_objects_page_3',
  348. 's3/list_objects_page_4',
  349. 's3/list_objects_page_5',
  350. 's3/list_objects_page_1',
  351. 's3/list_objects_page_2',
  352. 's3/list_objects_page_3',
  353. 's3/list_objects_page_4',
  354. 's3/list_objects_page_5'
  355. ));
  356. $c = null;
  357. $this->client->getEventDispatcher()->addListener('client.command.create', function ($e) use (&$c) {
  358. $c = $e['command'];
  359. });
  360. $dir = 's3://bucket/key/';
  361. $r = opendir($dir);
  362. $this->assertInternalType('resource', $r);
  363. // Ensure that the command was created correctly
  364. $this->assertEquals('bucket', $c['Bucket']);
  365. $this->assertEquals('/', $c['Delimiter']);
  366. $this->assertEquals('key/', $c['Prefix']);
  367. $files = array();
  368. while (($file = readdir($r)) !== false) {
  369. $files[] = $file;
  370. }
  371. // This is the order that the mock responses should provide
  372. $expected = array('a', 'b', 'c', 'd', 'e', 'f', 'g');
  373. $this->assertEquals($expected, $files);
  374. $this->assertEquals(5, count($this->getMockedRequests()));
  375. rewinddir($r);
  376. $files = array();
  377. while (($file = readdir($r)) !== false) {
  378. $files[] = $file;
  379. }
  380. $this->assertEquals($expected, $files);
  381. $this->assertEquals(10, count($this->getMockedRequests()));
  382. closedir($r);
  383. }
  384. public function testCanSetDelimiterStreamContext()
  385. {
  386. $this->setMockResponse($this->client, array('s3/list_objects_page_5'));
  387. $c = null;
  388. $this->client->getEventDispatcher()->addListener('client.command.create', function ($e) use (&$c) {
  389. $c = $e['command'];
  390. });
  391. $dir = 's3://bucket';
  392. $r = opendir($dir, stream_context_create(array('s3' => array('delimiter' => ''))));
  393. $this->assertEquals('bucket', $c['Bucket']);
  394. $this->assertEquals('', $c['Delimiter']);
  395. $this->assertEquals('', $c['Prefix']);
  396. closedir($r);
  397. }
  398. public function testStatS3andBuckets()
  399. {
  400. clearstatcache('s3://');
  401. $stat = stat('s3://');
  402. $this->assertEquals(0040777, $stat['mode']);
  403. $this->setMockResponse($this->client, array(new Response(200)));
  404. clearstatcache('s3://bucket');
  405. $stat = stat('s3://bucket');
  406. $this->assertEquals(0040777, $stat['mode']);
  407. }
  408. /**
  409. * @expectedException PHPUnit_Framework_Error_Warning
  410. * @expectedExceptionMessage Forbidden
  411. */
  412. public function testFailingStatTriggersError()
  413. {
  414. $this->setMockResponse($this->client, array(new Response(403)));
  415. clearstatcache('s3://bucket/key');
  416. stat('s3://bucket/key');
  417. }
  418. /**
  419. * @expectedException PHPUnit_Framework_Error_Warning
  420. * @expectedExceptionMessage File or directory not found: s3://bucket
  421. */
  422. public function testBucketNotFoundTriggersError()
  423. {
  424. $this->setMockResponse($this->client, array(new Response(404)));
  425. $this->setMockResponse($this->client, array(new Response(404)));
  426. clearstatcache('s3://bucket');
  427. stat('s3://bucket');
  428. }
  429. public function testStatsRegularObjects()
  430. {
  431. $ts = strtotime('Tuesday, April 9 2013');
  432. $this->setMockResponse($this->client, array(new Response(200, array(
  433. 'Content-Length' => 5,
  434. 'Last-Modified' => gmdate('r', $ts)
  435. ))));
  436. clearstatcache('s3://bucket/key');
  437. $stat = stat('s3://bucket/key');
  438. $this->assertEquals(0100777, $stat['mode']);
  439. $this->assertEquals(5, $stat['size']);
  440. $this->assertEquals($ts, $stat['mtime']);
  441. $this->assertEquals($ts, $stat['ctime']);
  442. }
  443. public function testCanStatPrefix()
  444. {
  445. $this->setMockResponse($this->client, array('s3/head_failure', 's3/list_objects_page_5'));
  446. clearstatcache('s3://bucket/prefix');
  447. $stat = stat('s3://bucket/prefix');
  448. $this->assertEquals(0040777, $stat['mode']);
  449. }
  450. /**
  451. * @expectedException PHPUnit_Framework_Error_Warning
  452. * @expectedExceptionMessage File or directory not found: s3://bucket/prefix
  453. */
  454. public function testCannotStatPrefixWithNoResults()
  455. {
  456. $this->setMockResponse($this->client, array('s3/head_failure', 's3/head_success'));
  457. clearstatcache('s3://bucket/prefix');
  458. stat('s3://bucket/prefix');
  459. }
  460. }