PageRenderTime 54ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/codes-php/phpjakarta/tests/functional/WindowsAzure/Blob/BlobServiceFunctionalTest.php

http://bukuphpjs.codeplex.com
PHP | 2393 lines | 1530 code | 289 blank | 574 comment | 336 complexity | 63d1c1187f615ad4cb9e8a4c8e14a70a MD5 | raw file
Possible License(s): Apache-2.0, MIT, LGPL-2.1
  1. <?php
  2. /**
  3. * LICENSE: Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. * http://www.apache.org/licenses/LICENSE-2.0
  7. *
  8. * Unless required by applicable law or agreed to in writing, software
  9. * distributed under the License is distributed on an "AS IS" BASIS,
  10. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. * See the License for the specific language governing permissions and
  12. * limitations under the License.
  13. *
  14. * PHP version 5
  15. *
  16. * @category Microsoft
  17. * @package Tests\Functional\WindowsAzure\Blob
  18. * @author Azure PHP SDK <azurephpsdk@microsoft.com>
  19. * @copyright 2012 Microsoft Corporation
  20. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
  21. * @link https://github.com/windowsazure/azure-sdk-for-php
  22. */
  23. namespace Tests\Functional\WindowsAzure\Blob;
  24. use Tests\Framework\TestResources;
  25. use WindowsAzure\Blob\Models\BlobServiceOptions;
  26. use WindowsAzure\Blob\Models\CopyBlobOptions;
  27. use WindowsAzure\Blob\Models\CreateBlobSnapshotOptions;
  28. use WindowsAzure\Blob\Models\CreateContainerOptions;
  29. use WindowsAzure\Blob\Models\DeleteBlobOptions;
  30. use WindowsAzure\Blob\Models\DeleteContainerOptions;
  31. use WindowsAzure\Blob\Models\GetBlobMetadataOptions;
  32. use WindowsAzure\Blob\Models\GetBlobOptions;
  33. use WindowsAzure\Blob\Models\GetBlobPropertiesOptions;
  34. use WindowsAzure\Blob\Models\ListBlobsOptions;
  35. use WindowsAzure\Blob\Models\ListContainersOptions;
  36. use WindowsAzure\Blob\Models\PublicAccessType;
  37. use WindowsAzure\Blob\Models\SetBlobMetadataOptions;
  38. use WindowsAzure\Blob\Models\SetContainerMetadataOptions;
  39. use WindowsAzure\Common\ServiceException;
  40. use WindowsAzure\Common\Internal\Resources;
  41. use WindowsAzure\Common\Internal\StorageServiceSettings;
  42. use WindowsAzure\Common\Internal\Utilities;
  43. class BlobServiceFunctionalTest extends FunctionalTestBase
  44. {
  45. /**
  46. * @covers WindowsAzure\Blob\BlobRestProxy::getServiceProperties
  47. */
  48. public function testGetServicePropertiesNoOptions()
  49. {
  50. $serviceProperties = BlobServiceFunctionalTestData::getDefaultServiceProperties();
  51. $shouldReturn = false;
  52. try {
  53. $this->restProxy->setServiceProperties($serviceProperties);
  54. $this->assertFalse($this->isEmulated(), 'Should succeed when not running in emulator');
  55. } catch (ServiceException $e) {
  56. // Expect failure in emulator, as v1.6 doesn't support this method
  57. if ($this->isEmulated()) {
  58. $this->assertEquals(TestResources::STATUS_BAD_REQUEST, $e->getCode(), 'getCode');
  59. $shouldReturn = true;
  60. } else {
  61. throw $e;
  62. }
  63. }
  64. if($shouldReturn) {
  65. return;
  66. }
  67. $this->getServicePropertiesWorker(null);
  68. }
  69. /**
  70. * @covers WindowsAzure\Blob\BlobRestProxy::getServiceProperties
  71. */
  72. public function testGetServiceProperties()
  73. {
  74. $serviceProperties = BlobServiceFunctionalTestData::getDefaultServiceProperties();
  75. $shouldReturn = false;
  76. try {
  77. $this->restProxy->setServiceProperties($serviceProperties);
  78. $this->assertFalse($this->isEmulated(), 'Should succeed when not running in emulator');
  79. } catch (ServiceException $e) {
  80. // Expect failure in emulator, as v1.6 doesn't support this method
  81. if ($this->isEmulated()) {
  82. $this->assertEquals(TestResources::STATUS_BAD_REQUEST, $e->getCode(), 'getCode');
  83. $shouldReturn = true;
  84. } else {
  85. throw $e;
  86. }
  87. }
  88. if($shouldReturn) {
  89. return;
  90. }
  91. // Now look at the combos.
  92. $interestingTimeouts = BlobServiceFunctionalTestData::getInterestingTimeoutValues();
  93. foreach($interestingTimeouts as $timeout) {
  94. $options = new BlobServiceOptions();
  95. $options->setTimeout($timeout);
  96. $this->getServicePropertiesWorker($options);
  97. }
  98. }
  99. /**
  100. * @covers WindowsAzure\Blob\BlobRestProxy::getServiceProperties
  101. */
  102. private function getServicePropertiesWorker($options)
  103. {
  104. $effOptions = (is_null($options) ? new BlobServiceOptions() : $options);
  105. try {
  106. $ret = (is_null($options) ? $this->restProxy->getServiceProperties() : $this->restProxy->getServiceProperties($effOptions));
  107. if (!is_null($effOptions->getTimeout()) && $effOptions->getTimeout() < 1) {
  108. $this->True('Expect negative timeouts in $options to throw', false);
  109. } else {
  110. $this->assertFalse($this->isEmulated(), 'Should succeed when not running in emulator');
  111. }
  112. $this->verifyServicePropertiesWorker($ret, null);
  113. } catch (ServiceException $e) {
  114. if ($this->isEmulated()) {
  115. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  116. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'getCode');
  117. } else {
  118. // Expect failure in emulator, as v1.6 doesn't support this method
  119. $this->assertEquals(TestResources::STATUS_BAD_REQUEST, $e->getCode(), 'getCode');
  120. }
  121. } else {
  122. if (is_null($effOptions->getTimeout()) || $effOptions->getTimeout() >= 1) {
  123. throw $e;
  124. } else {
  125. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'getCode');
  126. }
  127. }
  128. }
  129. }
  130. private function verifyServicePropertiesWorker($ret, $serviceProperties)
  131. {
  132. if (is_null($serviceProperties)) {
  133. $serviceProperties = BlobServiceFunctionalTestData::getDefaultServiceProperties();
  134. }
  135. $sp = $ret->getValue();
  136. $this->assertNotNull($sp, 'getValue should be non-null');
  137. $l = $sp->getLogging();
  138. $this->assertNotNull($l, 'getValue()->getLogging() should be non-null');
  139. $this->assertEquals($serviceProperties->getLogging()->getVersion(), $l->getVersion(), 'getValue()->getLogging()->getVersion');
  140. $this->assertEquals($serviceProperties->getLogging()->getDelete(), $l->getDelete(), 'getValue()->getLogging()->getDelete');
  141. $this->assertEquals($serviceProperties->getLogging()->getRead(), $l->getRead(), 'getValue()->getLogging()->getRead');
  142. $this->assertEquals($serviceProperties->getLogging()->getWrite(), $l->getWrite(), 'getValue()->getLogging()->getWrite');
  143. $r = $l->getRetentionPolicy();
  144. $this->assertNotNull($r, 'getValue()->getLogging()->getRetentionPolicy should be non-null');
  145. $this->assertEquals($serviceProperties->getLogging()->getRetentionPolicy()->getDays(), $r->getDays(), 'getValue()->getLogging()->getRetentionPolicy()->getDays');
  146. $m = $sp->getMetrics();
  147. $this->assertNotNull($m, 'getValue()->getMetrics() should be non-null');
  148. $this->assertEquals($serviceProperties->getMetrics()->getVersion(), $m->getVersion(), 'getValue()->getMetrics()->getVersion');
  149. $this->assertEquals($serviceProperties->getMetrics()->getEnabled(), $m->getEnabled(), 'getValue()->getMetrics()->getEnabled');
  150. $this->assertEquals($serviceProperties->getMetrics()->getIncludeAPIs(), $m->getIncludeAPIs(), 'getValue()->getMetrics()->getIncludeAPIs');
  151. $r = $m->getRetentionPolicy();
  152. $this->assertNotNull($r, 'getValue()->getMetrics()->getRetentionPolicy should be non-null');
  153. $this->assertEquals($serviceProperties->getMetrics()->getRetentionPolicy()->getDays(), $r->getDays(), 'getValue()->getMetrics()->getRetentionPolicy()->getDays');
  154. }
  155. /**
  156. * @covers WindowsAzure\Blob\BlobRestProxy::getServiceProperties
  157. * @covers WindowsAzure\Blob\BlobRestProxy::setServiceProperties
  158. */
  159. public function testSetServicePropertiesNoOptions()
  160. {
  161. $serviceProperties = BlobServiceFunctionalTestData::getDefaultServiceProperties();
  162. $this->setServicePropertiesWorker($serviceProperties, null);
  163. }
  164. /**
  165. * @covers WindowsAzure\Blob\BlobRestProxy::getServiceProperties
  166. * @covers WindowsAzure\Blob\BlobRestProxy::setServiceProperties
  167. */
  168. public function testSetServiceProperties()
  169. {
  170. $interestingServiceProperties = BlobServiceFunctionalTestData::getInterestingServiceProperties();
  171. foreach($interestingServiceProperties as $serviceProperties) {
  172. $interestingTimeouts = BlobServiceFunctionalTestData::getInterestingTimeoutValues();
  173. foreach($interestingTimeouts as $timeout) {
  174. $options = new BlobServiceOptions();
  175. $options->setTimeout($timeout);
  176. $this->setServicePropertiesWorker($serviceProperties, $options);
  177. }
  178. }
  179. if (!$this->isEmulated()) {
  180. $this->restProxy->setServiceProperties($interestingServiceProperties[0]);
  181. }
  182. }
  183. /**
  184. * @covers WindowsAzure\Blob\BlobRestProxy::getServiceProperties
  185. * @covers WindowsAzure\Blob\BlobRestProxy::setServiceProperties
  186. */
  187. private function setServicePropertiesWorker($serviceProperties, $options)
  188. {
  189. try {
  190. if (is_null($options)) {
  191. $this->restProxy->setServiceProperties($serviceProperties);
  192. } else {
  193. $this->restProxy->setServiceProperties($serviceProperties, $options);
  194. }
  195. if (is_null($options)) {
  196. $options = new BlobServiceOptions();
  197. }
  198. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  199. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  200. } else {
  201. $this->assertFalse($this->isEmulated(), 'Should succeed when not running in emulator');
  202. }
  203. $ret = (is_null($options) ? $this->restProxy->getServiceProperties() : $this->restProxy->getServiceProperties($options));
  204. $this->verifyServicePropertiesWorker($ret, $serviceProperties);
  205. } catch (ServiceException $e) {
  206. if (is_null($options)) {
  207. $options = new BlobServiceOptions();
  208. }
  209. if ($this->isEmulated()) {
  210. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  211. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'getCode');
  212. } else {
  213. $this->assertEquals(TestResources::STATUS_BAD_REQUEST, $e->getCode(), 'getCode');
  214. }
  215. } else {
  216. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  217. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'getCode');
  218. } else {
  219. throw $e;
  220. }
  221. }
  222. }
  223. }
  224. /**
  225. * @covers WindowsAzure\Blob\BlobRestProxy::listContainers
  226. */
  227. public function testListContainersNoOptions()
  228. {
  229. $this->listContainersWorker(null);
  230. }
  231. /**
  232. * @covers WindowsAzure\Blob\BlobRestProxy::listContainers
  233. */
  234. public function testListContainers()
  235. {
  236. $interestingListContainersOptions = BlobServiceFunctionalTestData::getInterestingListContainersOptions();
  237. foreach($interestingListContainersOptions as $options) {
  238. $this->listContainersWorker($options);
  239. }
  240. }
  241. /**
  242. * @covers WindowsAzure\Blob\BlobRestProxy::listContainers
  243. */
  244. private function listContainersWorker($options)
  245. {
  246. $finished = false;
  247. while (!$finished) {
  248. try {
  249. $ret = (is_null($options) ? $this->restProxy->listContainers() : $this->restProxy->listContainers($options));
  250. if (is_null($options)) {
  251. $options = new ListContainersOptions();
  252. }
  253. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  254. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  255. }
  256. $this->verifyListContainersWorker($ret, $options);
  257. if (strlen($ret->getNextMarker()) == 0) {
  258. $finished = true;
  259. } else {
  260. $options->setMarker($ret->getNextMarker());
  261. }
  262. } catch (ServiceException $e) {
  263. $finished = true;
  264. if (is_null($options->getTimeout()) || $options->getTimeout() >= 1) {
  265. throw $e;
  266. } else {
  267. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'getCode');
  268. }
  269. }
  270. }
  271. }
  272. private function verifyListContainersWorker($ret, $options)
  273. {
  274. // Cannot really check the next marker. Just make sure it is not null.
  275. $this->assertEquals($options->getMarker(), $ret->getMarker(), 'getMarker');
  276. $this->assertEquals($options->getMaxResults(), $ret->getMaxResults(), 'getMaxResults');
  277. $this->assertEquals($options->getPrefix(), $ret->getPrefix(), 'getPrefix');
  278. $this->assertNotNull($ret->getContainers(), 'getBlobs');
  279. if ($options->getMaxResults() == 0) {
  280. $this->assertEquals(0, strlen($ret->getNextMarker()), 'When MaxResults is 0, expect getNextMarker (' . strlen($ret->getNextMarker()) . ')to be ');
  281. if (!is_null($options->getPrefix()) && $options->getPrefix() == (BlobServiceFunctionalTestData::$nonExistBlobPrefix)) {
  282. $this->assertEquals(0, count($ret->getContainers()), 'when MaxResults=0 and Prefix=(\'' . $options->getPrefix() . '\'), then Blobs length');
  283. } else if (!is_null($options->getPrefix()) && $options->getPrefix() == (BlobServiceFunctionalTestData::$testUniqueId)) {
  284. $this->assertEquals(count(BlobServiceFunctionalTestData::$testContainerNames), count($ret->getContainers()), 'when MaxResults=0 and Prefix=(\'' . $options->getPrefix() . '\'), then Blobs length');
  285. } else {
  286. // Do not know how many there should be
  287. }
  288. } else if (strlen($ret->getNextMarker()) == 0) {
  289. $this->assertTrue(count($ret->getContainers()) <= $options->getMaxResults(), 'when NextMarker (\'' . $ret->getNextMarker() . '\')==\'\', Blobs length (' . count($ret->getContainers()) . ') should be <= MaxResults (' . $options->getMaxResults() . ')');
  290. if (BlobServiceFunctionalTestData::$nonExistBlobPrefix == $options->getPrefix()) {
  291. $this->assertEquals(0, count($ret->getContainers()), 'when no next marker and Prefix=(\'' . $options->getPrefix() . '\'), then Blobs length');
  292. } else if (BlobServiceFunctionalTestData::$testUniqueId ==$options->getPrefix()) {
  293. // Need to futz with the mod because you are allowed to get MaxResults items returned.
  294. $expectedCount = count(BlobServiceFunctionalTestData::$testContainerNames) % $options->getMaxResults();
  295. if (!$this->isEmulated()) {
  296. $expectedCount += 1;
  297. }
  298. $this->assertEquals(
  299. $expectedCount,
  300. count($ret->getContainers()),
  301. 'when no next marker and Prefix=(\'' . $options->getPrefix() . '\'), then Blobs length');
  302. } else {
  303. // Do not know how many there should be
  304. }
  305. } else {
  306. $this->assertEquals(
  307. count($ret->getContainers()),
  308. $options->getMaxResults(),
  309. 'when NextMarker (' . $ret->getNextMarker() . ')!=\'\', Blobs length (' . count($ret->getContainers()) . ') should be == MaxResults (' . $options->getMaxResults() . ')');
  310. if (!is_null($options->getPrefix()) && $options->getPrefix() == BlobServiceFunctionalTestData::$nonExistBlobPrefix) {
  311. $this->assertTrue(false, 'when a next marker and Prefix=(\'' . $options->getPrefix() . '\'), impossible');
  312. }
  313. }
  314. }
  315. /**
  316. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  317. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  318. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerMetadata
  319. * @covers WindowsAzure\Blob\BlobRestProxy::listContainers
  320. */
  321. public function testCreateContainerNoOptions()
  322. {
  323. $this->createContainerWorker(null);
  324. }
  325. /**
  326. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  327. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  328. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerMetadata
  329. * @covers WindowsAzure\Blob\BlobRestProxy::listContainers
  330. */
  331. public function testCreateContainer()
  332. {
  333. $interestingCreateContainerOptions = BlobServiceFunctionalTestData::getInterestingCreateContainerOptions();
  334. foreach($interestingCreateContainerOptions as $options) {
  335. $this->createContainerWorker($options);
  336. }
  337. }
  338. /**
  339. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  340. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  341. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerMetadata
  342. * @covers WindowsAzure\Blob\BlobRestProxy::listContainers
  343. */
  344. private function createContainerWorker($options)
  345. {
  346. $container = BlobServiceFunctionalTestData::getInterestingContainerName();
  347. $created = false;
  348. try {
  349. if (is_null($options)) {
  350. $this->restProxy->createContainer($container);
  351. } else {
  352. $this->restProxy->createContainer($container, $options);
  353. }
  354. $created = true;
  355. if (is_null($options)) {
  356. $options = new CreateContainerOptions();
  357. }
  358. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  359. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  360. }
  361. // Now check that the $container was $created correctly.
  362. // Make sure that the list of all applicable containers is correctly updated.
  363. $opts = new ListContainersOptions();
  364. $opts->setPrefix(BlobServiceFunctionalTestData::$testUniqueId);
  365. $qs = $this->restProxy->listContainers($opts);
  366. $this->assertEquals(count($qs->getContainers()), count(BlobServiceFunctionalTestData::$testContainerNames) + 1, 'After adding one, with Prefix=(\'' . BlobServiceFunctionalTestData::$testUniqueId . '\'), then Containers length');
  367. // Check the metadata on the container
  368. $ret = $this->restProxy->getContainerMetadata($container);
  369. $this->verifyCreateContainerWorker($ret, $options);
  370. $this->restProxy->deleteContainer($container);
  371. } catch (ServiceException $e) {
  372. if (is_null($options)) {
  373. $options = new CreateContainerOptions();
  374. }
  375. if (is_null($options->getTimeout()) || $options->getTimeout() >= 1) {
  376. throw $e;
  377. } else {
  378. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'getCode');
  379. }
  380. }
  381. if ($created) {
  382. try {
  383. $this->restProxy->deleteContainer($container);
  384. } catch (ServiceException $e) {
  385. // Ignore.
  386. }
  387. }
  388. }
  389. private function verifyCreateContainerWorker($ret, $options)
  390. {
  391. if (is_null($options->getMetadata())) {
  392. $this->assertNotNull($ret->getMetadata(), 'container Metadata');
  393. $this->assertEquals(0, count($ret->getMetadata()), 'count container Metadata');
  394. } else {
  395. $this->assertNotNull($ret->getMetadata(), 'container Metadata');
  396. $this->assertEquals(count($options->getMetadata()), count($ret->getMetadata()), 'Metadata');
  397. $retMetadata = $ret->getMetadata();
  398. foreach($options->getMetadata() as $key => $value) {
  399. $this->assertEquals($value, $retMetadata[$key], 'Metadata(' . $key . ')');
  400. }
  401. }
  402. }
  403. /**
  404. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  405. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  406. * @covers WindowsAzure\Blob\BlobRestProxy::listContainers
  407. */
  408. public function testDeleteContainerNoOptions()
  409. {
  410. $this->deleteContainerWorker(null);
  411. }
  412. /**
  413. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  414. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  415. * @covers WindowsAzure\Blob\BlobRestProxy::listContainers
  416. */
  417. public function testDeleteContainer()
  418. {
  419. $interestingDeleteContainerOptions = BlobServiceFunctionalTestData::getInterestingDeleteContainerOptions();
  420. foreach($interestingDeleteContainerOptions as $options) {
  421. $this->deleteContainerWorker($options);
  422. }
  423. }
  424. /**
  425. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  426. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  427. * @covers WindowsAzure\Blob\BlobRestProxy::listContainers
  428. */
  429. private function deleteContainerWorker($options)
  430. {
  431. $container = BlobServiceFunctionalTestData::getInterestingContainerName();
  432. // Make sure there is something to delete.
  433. $this->restProxy->createContainer($container);
  434. // Make sure that the list of all applicable containers is correctly updated.
  435. $opts = new ListContainersOptions();
  436. $opts->setPrefix(BlobServiceFunctionalTestData::$testUniqueId);
  437. $qs = $this->restProxy->listContainers($opts);
  438. $this->assertEquals(
  439. count($qs->getContainers()),
  440. count(BlobServiceFunctionalTestData::$testContainerNames) + 1,
  441. 'After adding one, with Prefix=(\'' . BlobServiceFunctionalTestData::$testUniqueId . '\'), then Containers length');
  442. $deleted = false;
  443. try {
  444. if (is_null($options)) {
  445. $this->restProxy->deleteContainer($container);
  446. } else {
  447. $this->restProxy->deleteContainer($container, $options);
  448. }
  449. $deleted = true;
  450. if (is_null($options)) {
  451. $options = new DeleteContainerOptions();
  452. }
  453. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  454. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  455. }
  456. if (!$this->isEmulated() &&
  457. !BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  458. $this->assertTrue(false, 'Failing access condition should throw');
  459. }
  460. // Make sure that the list of all applicable containers is correctly updated.
  461. $opts = new ListContainersOptions();
  462. $opts->setPrefix(BlobServiceFunctionalTestData::$testUniqueId);
  463. $qs = $this->restProxy->listContainers($opts);
  464. $this->assertEquals(
  465. count($qs->getContainers()),
  466. count(BlobServiceFunctionalTestData::$testContainerNames),
  467. 'After adding then deleting one, with Prefix=(\'' . BlobServiceFunctionalTestData::$testUniqueId . '\'), then Containers length');
  468. // Nothing else interesting to check for the $options.
  469. } catch (ServiceException $e) {
  470. if (is_null($options)) {
  471. $options = new DeleteContainerOptions();
  472. }
  473. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  474. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'getCode');
  475. } else if (!$this->isEmulated() && !BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  476. $this->assertEquals(TestResources::STATUS_PRECONDITION_FAILED, $e->getCode(), 'getCode');
  477. } else {
  478. throw $e;
  479. }
  480. }
  481. if (!$deleted) {
  482. // Try again. If it does not work, not much else to try.
  483. $this->restProxy->deleteContainer($container);
  484. }
  485. }
  486. /**
  487. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  488. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  489. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerMetadata
  490. * @covers WindowsAzure\Blob\BlobRestProxy::setContainerMetadata
  491. */
  492. public function testGetContainerMetadataNoOptions()
  493. {
  494. $metadata = BlobServiceFunctionalTestData::getNiceMetadata();
  495. $this->getContainerMetadataWorker(null, $metadata);
  496. }
  497. /**
  498. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  499. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  500. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerMetadata
  501. * @covers WindowsAzure\Blob\BlobRestProxy::setContainerMetadata
  502. */
  503. public function testGetContainerMetadata()
  504. {
  505. $interestingTimeouts = BlobServiceFunctionalTestData::getInterestingTimeoutValues();
  506. $metadata = BlobServiceFunctionalTestData::getNiceMetadata();
  507. foreach($interestingTimeouts as $timeout) {
  508. $options = new BlobServiceOptions();
  509. $options->setTimeout($timeout);
  510. $this->getContainerMetadataWorker($options, $metadata);
  511. }
  512. }
  513. /**
  514. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  515. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  516. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerMetadata
  517. * @covers WindowsAzure\Blob\BlobRestProxy::setContainerMetadata
  518. */
  519. private function getContainerMetadataWorker($options, $metadata)
  520. {
  521. $container = BlobServiceFunctionalTestData::getInterestingContainerName();
  522. // Make sure there is something to test
  523. $this->restProxy->createContainer($container);
  524. $this->restProxy->setContainerMetadata($container, $metadata);
  525. try {
  526. $res = (is_null($options) ? $this->restProxy->getContainerMetadata($container) : $this->restProxy->getContainerMetadata($container, $options));
  527. if (is_null($options)) {
  528. $options = new BlobServiceOptions();
  529. }
  530. if (!is_null($options->getTimeout()) && $options->getTimeout() <= 0) {
  531. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  532. }
  533. $this->verifyGetContainerMetadataWorker($res, $metadata);
  534. } catch (ServiceException $e) {
  535. if (is_null($options->getTimeout()) || $options->getTimeout() > 0) {
  536. throw $e;
  537. } else {
  538. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'getCode');
  539. }
  540. }
  541. // Clean up.
  542. $this->restProxy->deleteContainer($container);
  543. }
  544. private function verifyGetContainerMetadataWorker($ret, $metadata)
  545. {
  546. $this->assertNotNull($ret->getMetadata(), 'container Metadata');
  547. $this->assertNotNull($ret->getETag(), 'container getETag');
  548. $this->assertNotNull($ret->getLastModified(), 'container getLastModified');
  549. $this->assertEquals(count($metadata), count($ret->getMetadata()), 'Metadata');
  550. $md = $ret->getMetadata();
  551. foreach($metadata as $key => $value) {
  552. $this->assertEquals($value, $md[$key], 'Metadata(' . $key . ')');
  553. }
  554. // Make sure the last modified date is within 10 seconds
  555. $now = new \DateTime();
  556. $this->assertTrue(
  557. BlobServiceFunctionalTestData::diffInTotalSeconds($ret->getLastModified(), $now) < 10,
  558. 'Last modified date (' . $ret->getLastModified()->format(\DateTime::RFC1123) . ')'.
  559. ' should be within 10 seconds of $now (' . $now->format(\DateTime::RFC1123) . ')');
  560. }
  561. /**
  562. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  563. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  564. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerMetadata
  565. * @covers WindowsAzure\Blob\BlobRestProxy::setContainerMetadata
  566. */
  567. public function testSetContainerMetadataNoOptions()
  568. {
  569. $interestingMetadata = BlobServiceFunctionalTestData::getInterestingMetadata();
  570. foreach($interestingMetadata as $metadata) {
  571. $this->setContainerMetadataWorker(null, $metadata);
  572. }
  573. }
  574. /**
  575. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  576. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  577. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerMetadata
  578. * @covers WindowsAzure\Blob\BlobRestProxy::setContainerMetadata
  579. */
  580. public function testSetContainerMetadata()
  581. {
  582. $interestingSetContainerMetadataOptions = BlobServiceFunctionalTestData::getSetContainerMetadataOptions();
  583. $interestingMetadata = BlobServiceFunctionalTestData::getInterestingMetadata();
  584. foreach($interestingSetContainerMetadataOptions as $options) {
  585. foreach($interestingMetadata as $metadata) {
  586. $this->setContainerMetadataWorker($options, $metadata);
  587. }
  588. }
  589. }
  590. /**
  591. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  592. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  593. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerMetadata
  594. * @covers WindowsAzure\Blob\BlobRestProxy::setContainerMetadata
  595. */
  596. private function setContainerMetadataWorker($options, $metadata)
  597. {
  598. $container = BlobServiceFunctionalTestData::getInterestingContainerName();
  599. // Make sure there is something to test
  600. $this->restProxy->createContainer($container);
  601. $firstkey = '';
  602. if (!is_null($metadata) && count($metadata) > 0) {
  603. $firstkey = array_keys($metadata);
  604. $firstkey = $firstkey[0];
  605. }
  606. try {
  607. try {
  608. // And put in some metadata
  609. if (is_null($options)) {
  610. $this->restProxy->setContainerMetadata($container, $metadata);
  611. } else {
  612. $this->restProxy->setContainerMetadata($container, $metadata, $options);
  613. }
  614. if (is_null($options)) {
  615. $options = new SetContainerMetadataOptions();
  616. }
  617. $this->assertFalse(
  618. Utilities::startsWith($firstkey, '<'),
  619. 'Should get HTTP request error if the metadata is invalid');
  620. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  621. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  622. }
  623. // setMetadata only honors If-Modified-Since
  624. if (!$this->isEmulated() &&
  625. !BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())
  626. && (!is_null($options->getAccessCondition())
  627. && $options->getAccessCondition()->getHeader() != Resources::IF_UNMODIFIED_SINCE)) {
  628. $this->assertTrue(false, 'Expect failing access condition to throw');
  629. }
  630. $res = $this->restProxy->getContainerMetadata($container);
  631. $this->verifyGetContainerMetadataWorker($res, $metadata);
  632. } catch (\HTTP_Request2_LogicException $e) {
  633. $this->assertTrue(
  634. Utilities::startsWith($firstkey, '<'),
  635. 'Should get HTTP request error only if the metadata is invalid');
  636. }
  637. } catch (ServiceException $e) {
  638. if (!$this->isEmulated() &&
  639. !BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition()) &&
  640. (!is_null($options->getAccessCondition()) &&
  641. $options->getAccessCondition()->getHeader() != Resources::IF_UNMODIFIED_SINCE)) {
  642. // setMetadata only honors If-Modified-Since
  643. $this->assertEquals(TestResources::STATUS_PRECONDITION_FAILED, $e->getCode(), 'getCode');
  644. } else if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  645. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'getCode');
  646. } else {
  647. throw $e;
  648. }
  649. }
  650. // Clean up.
  651. $this->restProxy->deleteContainer($container);
  652. }
  653. /**
  654. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  655. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  656. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerProperties
  657. * @covers WindowsAzure\Blob\BlobRestProxy::setContainerMetadata
  658. */
  659. public function testGetContainerPropertiesNoOptions()
  660. {
  661. $metadata = BlobServiceFunctionalTestData::getNiceMetadata();
  662. $this->getContainerPropertiesWorker(null, $metadata);
  663. }
  664. /**
  665. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  666. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  667. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerProperties
  668. * @covers WindowsAzure\Blob\BlobRestProxy::setContainerMetadata
  669. */
  670. public function testGetContainerProperties()
  671. {
  672. $interestingTimeouts = BlobServiceFunctionalTestData::getInterestingTimeoutValues();
  673. $metadata = BlobServiceFunctionalTestData::getNiceMetadata();
  674. foreach($interestingTimeouts as $timeout) {
  675. $options = new BlobServiceOptions();
  676. $options->setTimeout($timeout);
  677. $this->getContainerPropertiesWorker($options, $metadata);
  678. }
  679. }
  680. /**
  681. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  682. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  683. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerProperties
  684. * @covers WindowsAzure\Blob\BlobRestProxy::setContainerMetadata
  685. */
  686. private function getContainerPropertiesWorker($options, $metadata)
  687. {
  688. $container = BlobServiceFunctionalTestData::getInterestingContainerName();
  689. // Make sure there is something to test
  690. $this->restProxy->createContainer($container);
  691. $this->restProxy->setContainerMetadata($container, $metadata);
  692. try {
  693. $res = (is_null($options) ? $this->restProxy->getContainerProperties($container) : $this->restProxy->getContainerProperties($container, $options));
  694. if (is_null($options)) {
  695. $options = new BlobServiceOptions();
  696. }
  697. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  698. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  699. }
  700. $this->verifyGetContainerMetadataWorker($res, $metadata);
  701. } catch (ServiceException $e) {
  702. if (is_null($options->getTimeout()) || $options->getTimeout() >= 1) {
  703. throw $e;
  704. } else {
  705. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'getCode');
  706. }
  707. }
  708. // Clean up.
  709. $this->restProxy->deleteContainer($container);
  710. }
  711. /**
  712. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  713. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  714. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerACL
  715. */
  716. public function testGetContainerACLNoOptions()
  717. {
  718. $this->getContainerACLWorker(null);
  719. }
  720. /**
  721. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  722. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  723. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerACL
  724. */
  725. public function testGetContainerACL()
  726. {
  727. $interestingTimeouts = BlobServiceFunctionalTestData::getInterestingTimeoutValues();
  728. foreach($interestingTimeouts as $timeout) {
  729. $options = new BlobServiceOptions();
  730. $options->setTimeout($timeout);
  731. $this->getContainerACLWorker($options);
  732. }
  733. }
  734. /**
  735. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  736. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  737. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerACL
  738. */
  739. private function getContainerACLWorker($options)
  740. {
  741. $container = BlobServiceFunctionalTestData::getInterestingContainerName();
  742. // Make sure there is something to test
  743. $this->restProxy->createContainer($container);
  744. try {
  745. $res = (is_null($options) ? $this->restProxy->getContainerACL($container) : $this->restProxy->getContainerACL($container, $options));
  746. if (is_null($options)) {
  747. $options = new BlobServiceOptions();
  748. }
  749. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  750. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  751. }
  752. $this->verifyGetContainerACLWorker($res);
  753. } catch (ServiceException $e) {
  754. if (is_null($options->getTimeout()) || $options->getTimeout() >= 1) {
  755. throw $e;
  756. } else {
  757. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'getCode');
  758. }
  759. }
  760. // Clean up.
  761. $this->restProxy->deleteContainer($container);
  762. }
  763. private function verifyGetContainerACLWorker($ret)
  764. {
  765. $this->assertNotNull($ret->getContainerACL(), '$ret->getContainerACL');
  766. $this->assertNotNull($ret->getETag(), '$ret->getETag');
  767. $this->assertNotNull($ret->getLastModified(), '$ret->getLastModified');
  768. $this->assertNull($ret->getContainerACL()->getPublicAccess(), '$ret->getContainerACL->getPublicAccess');
  769. $this->assertNotNull($ret->getContainerACL()->getSignedIdentifiers(), '$ret->getContainerACL->getSignedIdentifiers');
  770. // Make sure the last modified date is within 10 seconds
  771. $now = new \DateTime();
  772. $this->assertTrue(BlobServiceFunctionalTestData::diffInTotalSeconds(
  773. $ret->getLastModified(),
  774. $now) < 10000,
  775. 'Last modified date (' . $ret->getLastModified()->format(\DateTime::RFC1123) . ') ' .
  776. 'should be within 10 seconds of $now (' . $now->format(\DateTime::RFC1123) . ')');
  777. }
  778. /**
  779. * @covers WindowsAzure\Blob\BlobRestProxy::createBlockBlob
  780. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  781. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  782. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerACL
  783. * @covers WindowsAzure\Blob\BlobRestProxy::setContainerACL
  784. */
  785. public function testSetContainerACLNoOptions()
  786. {
  787. $interestingACL = BlobServiceFunctionalTestData::getInterestingACL();
  788. foreach($interestingACL as $acl) {
  789. $this->setContainerACLWorker(null, $acl);
  790. }
  791. }
  792. /**
  793. * @covers WindowsAzure\Blob\BlobRestProxy::createBlockBlob
  794. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  795. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  796. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerACL
  797. * @covers WindowsAzure\Blob\BlobRestProxy::setContainerACL
  798. */
  799. public function testSetContainerACL()
  800. {
  801. $interestingACL = BlobServiceFunctionalTestData::getInterestingACL();
  802. $interestingTimeouts = BlobServiceFunctionalTestData::getInterestingTimeoutValues();
  803. foreach($interestingTimeouts as $timeout) {
  804. foreach($interestingACL as $acl) {
  805. $options = new BlobServiceOptions();
  806. $options->setTimeout($timeout);
  807. $this->setContainerACLWorker($options, $acl);
  808. }
  809. }
  810. }
  811. /**
  812. * @covers WindowsAzure\Blob\BlobRestProxy::createBlockBlob
  813. * @covers WindowsAzure\Blob\BlobRestProxy::createContainer
  814. * @covers WindowsAzure\Blob\BlobRestProxy::deleteContainer
  815. * @covers WindowsAzure\Blob\BlobRestProxy::getContainerACL
  816. * @covers WindowsAzure\Blob\BlobRestProxy::setContainerACL
  817. */
  818. private function setContainerACLWorker($options, $acl)
  819. {
  820. $container = BlobServiceFunctionalTestData::getInterestingContainerName();
  821. // Make sure there is something to test
  822. $this->restProxy->createContainer($container);
  823. $blobContent = uniqid();
  824. $this->restProxy->createBlockBlob($container, 'test', $blobContent);
  825. try {
  826. if (is_null($options)) {
  827. $this->restProxy->setContainerACL($container, $acl);
  828. $this->restProxy->setContainerACL($container, $acl);
  829. } else {
  830. $this->restProxy->setContainerACL($container, $acl, $options);
  831. $this->restProxy->setContainerACL($container, $acl, $options);
  832. }
  833. if (is_null($options)) {
  834. $options = new BlobServiceOptions();
  835. }
  836. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  837. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  838. }
  839. $res = $this->restProxy->getContainerACL($container);
  840. $this->verifySetContainerACLWorker($res, $container, $acl, $blobContent);
  841. } catch (ServiceException $e) {
  842. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  843. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'getCode');
  844. } else {
  845. throw $e;
  846. }
  847. }
  848. // Clean up.
  849. $this->restProxy->deleteContainer($container);
  850. }
  851. private function verifySetContainerACLWorker($ret, $container, $acl, $blobContent)
  852. {
  853. $this->assertNotNull($ret->getContainerACL(), '$ret->getContainerACL');
  854. $this->assertNotNull($ret->getETag(), '$ret->getContainerACL->getETag');
  855. $now = new \DateTime();
  856. $this->assertTrue(BlobServiceFunctionalTestData::diffInTotalSeconds(
  857. $ret->getLastModified(),
  858. $now) < 10000,
  859. 'Last modified date (' . $ret->getLastModified()->format(\DateTime::RFC1123) . ') ' .
  860. 'should be within 10 seconds of $now (' . $now->format(\DateTime::RFC1123) . ')');
  861. $this->assertNotNull($ret->getContainerACL()->getSignedIdentifiers(), '$ret->getContainerACL->getSignedIdentifiers');
  862. $this->assertEquals((is_null($acl->getPublicAccess()) ? '' : $acl->getPublicAccess()), $ret->getContainerACL()->getPublicAccess(), '$ret->getContainerACL->getPublicAccess');
  863. $expIds = $acl->getSignedIdentifiers();
  864. $actIds = $ret->getContainerACL()->getSignedIdentifiers();
  865. $this->assertEquals(count($expIds), count($actIds), '$ret->getContainerACL->getSignedIdentifiers');
  866. for ($i = 0; $i < count($expIds); $i++) {
  867. $expId = $expIds[$i];
  868. $actId = $actIds[$i];
  869. $this->assertEquals($expId->getId(), $actId->getId(), 'SignedIdentifiers['+$i+']->getId');
  870. $this->assertEquals(
  871. $expId->getAccessPolicy()->getPermission(),
  872. $actId->getAccessPolicy()->getPermission(),
  873. 'SignedIdentifiers['+$i+']->getAccessPolicy->getPermission');
  874. $this->assertTrue(BlobServiceFunctionalTestData::diffInTotalSeconds(
  875. $expId->getAccessPolicy()->getStart(),
  876. $actId->getAccessPolicy()->getStart()) < 1,
  877. 'SignedIdentifiers['+$i+']->getAccessPolicy->getStart should match within 1 second, ' .
  878. 'exp=' . $expId->getAccessPolicy()->getStart()->format(\DateTime::RFC1123) . ', ' .
  879. 'act=' . $actId->getAccessPolicy()->getStart()->format(\DateTime::RFC1123));
  880. $this->assertTrue(BlobServiceFunctionalTestData::diffInTotalSeconds(
  881. $expId->getAccessPolicy()->getExpiry(),
  882. $actId->getAccessPolicy()->getExpiry()) < 1,
  883. 'SignedIdentifiers['+$i+']->getAccessPolicy->getExpiry should match within 1 second, ' .
  884. 'exp=' . $expId->getAccessPolicy()->getExpiry()->format(\DateTime::RFC1123) . ', ' .
  885. 'act=' . $actId->getAccessPolicy()->getExpiry()->format(\DateTime::RFC1123));
  886. }
  887. if (!$this->isEmulated()) {
  888. $settings = StorageServiceSettings::createFromConnectionString($this->connectionString);
  889. $containerAddress = $settings->getBlobEndpointUri() . '/' . $container;
  890. $blobListAddress = $containerAddress . '?restype=container&comp=list';
  891. $blobAddress = $containerAddress . '/test';
  892. $canDownloadBlobList = $this->canDownloadFromUrl($blobListAddress,
  893. "<?xml version=\"1.0\" encoding=\"utf-8\"?" . "><EnumerationResults");
  894. $canDownloadBlob = $this->canDownloadFromUrl($blobAddress, $blobContent);
  895. if (!is_null($acl->getPublicAccess()) && $acl->getPublicAccess() == PublicAccessType::CONTAINER_AND_BLOBS) {
  896. // Full public read access: Container and blob data can be read via anonymous request.
  897. // Clients can enumerate blobs within the $container via anonymous request,
  898. // but cannot enumerate containers within the storage account.
  899. $this->assertTrue($canDownloadBlobList, '$canDownloadBlobList when ' . $acl->getPublicAccess());
  900. $this->assertTrue($canDownloadBlob, '$canDownloadBlob when ' . $acl->getPublicAccess());
  901. } else if (!is_null($acl->getPublicAccess()) && $acl->getPublicAccess() == PublicAccessType::BLOBS_ONLY) {
  902. // Public read access for blobs only: Blob data within this container
  903. // can be read via anonymous request, but $container data is not available.
  904. // Clients cannot enumerate blobs within the $container via anonymous request.
  905. $this->assertFalse($canDownloadBlobList, '$canDownloadBlobList when ' . $acl->getPublicAccess());
  906. $this->assertTrue($canDownloadBlob, '$canDownloadBlob when ' . $acl->getPublicAccess());
  907. } else {
  908. // No public read access: Container and blob data can be read by the account owner only.
  909. $this->assertFalse($canDownloadBlobList, '$canDownloadBlobList when ' . $acl->getPublicAccess());
  910. $this->assertFalse($canDownloadBlob, '$canDownloadBlob when ' . $acl->getPublicAccess());
  911. }
  912. }
  913. }
  914. private function canDownloadFromUrl($blobAddress, $expectedStartingValue)
  915. {
  916. $url = parse_url($blobAddress);
  917. $host = $url['host'];
  918. $fp = fsockopen($host, '80');
  919. $request = 'GET ' . $blobAddress . ' HTTP/1.1' . "\r\n" . 'Host: ' . $host ."\r\n\r\n";
  920. fputs($fp, $request);
  921. $value = fread($fp, 1000);
  922. fclose($fp);
  923. return strpos($value, $expectedStartingValue) !== false;
  924. }
  925. /**
  926. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  927. */
  928. public function testListBlobsNoOptions()
  929. {
  930. $container = BlobServiceFunctionalTestData::getContainerName();
  931. $this->listBlobsWorker($container, null);
  932. }
  933. // This fails because the service returns the container list
  934. // instead of the blob list. In principle, the service can
  935. // distinguish between the two, because this is of the
  936. // format:
  937. // /?restype=container&comp=list
  938. // whereas the container list has this format:
  939. // /?comp=list
  940. // /**
  941. // * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  942. // */
  943. // public function testListBlobsNoOptionsRoot()
  944. // {
  945. // $container = null;
  946. // $this->listBlobsWorker($container, null);
  947. // }
  948. /**
  949. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  950. */
  951. public function testListBlobsNoOptionsExplicitRoot()
  952. {
  953. $container = '$root';
  954. $this->listBlobsWorker($container, null);
  955. }
  956. /**
  957. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  958. */
  959. public function testListBlobs()
  960. {
  961. $interestingListBlobsOptions = BlobServiceFunctionalTestData::getInterestingListBlobsOptions();
  962. $container = BlobServiceFunctionalTestData::getContainerName();
  963. foreach($interestingListBlobsOptions as $options) {
  964. $this->listBlobsWorker($container, $options);
  965. }
  966. }
  967. /**
  968. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  969. */
  970. private function listBlobsWorker($container, $options)
  971. {
  972. $finished = false;
  973. while (!$finished) {
  974. try {
  975. $ret = (is_null($options) ? $this->restProxy->listBlobs($container) : $this->restProxy->listBlobs($container, $options));
  976. if (is_null($options)) {
  977. $options = new ListBlobsOptions();
  978. }
  979. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  980. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  981. }
  982. $this->verifyListBlobsWorker($ret, $options);
  983. if (strlen($ret->getNextMarker()) == 0) {
  984. $finished = true;
  985. } else {
  986. $options->setMarker($ret->getNextMarker());
  987. }
  988. } catch (ServiceException $e) {
  989. $finished = true;
  990. if (is_null($options->getTimeout()) || $options->getTimeout() >= 1) {
  991. throw $e;
  992. } else {
  993. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'getCode');
  994. }
  995. }
  996. }
  997. }
  998. private function verifyListBlobsWorker($ret, $options)
  999. {
  1000. $this->assertEquals($options->getMarker(), $ret->getMarker(), 'getMarker');
  1001. $this->assertEquals($options->getMaxResults(), $ret->getMaxResults(), 'getMaxResults');
  1002. $this->assertEquals($options->getPrefix(), $ret->getPrefix(), 'getPrefix');
  1003. $this->assertNotNull($ret->getBlobs(), 'getBlobs');
  1004. if ($options->getMaxResults() == 0) {
  1005. $this->assertEquals(0, strlen($ret->getNextMarker()), 'When MaxResults is 0, expect getNextMarker (' . strlen($ret->getNextMarker()) . ')to be ');
  1006. if (!is_null($options->getPrefix()) && $options->getPrefix() == (BlobServiceFunctionalTestData::$nonExistBlobPrefix)) {
  1007. $this->assertEquals(0, count($ret->getBlobs()), 'when MaxResults=0 and Prefix=(\'' . $options->getPrefix() . '\'), then Blobs length');
  1008. } else if (!is_null($options->getPrefix()) && $options->getPrefix() == (BlobServiceFunctionalTestData::$testUniqueId)) {
  1009. $this->assertEquals(0, count($ret->getBlobs()), 'when MaxResults=0 and Prefix=(\'' . $options->getPrefix() . '\'), then Blobs length');
  1010. } else {
  1011. // Do not know how many there should be
  1012. }
  1013. } else if (strlen($ret->getNextMarker()) == 0) {
  1014. $this->assertTrue(
  1015. count($ret->getBlobs()) <= $options->getMaxResults(),
  1016. 'when NextMarker (\'' . $ret->getNextMarker() . '\')==\'\', Blobs length (' . count($ret->getBlobs()) . ') should be <= MaxResults (' . $options->getMaxResults() . ')');
  1017. if (BlobServiceFunctionalTestData::$nonExistBlobPrefix == $options->getPrefix()) {
  1018. $this->assertEquals(
  1019. 0,
  1020. count($ret->getBlobs()),
  1021. 'when no next marker and Prefix=(\'' . $options->getPrefix() . '\'), then Blobs length');
  1022. } else if (BlobServiceFunctionalTestData::$testUniqueId == $options->getPrefix()) {
  1023. // Need to futz with the mod because you are allowed to get MaxResults items returned.
  1024. $this->assertEquals(
  1025. 0,
  1026. count($ret->getBlobs()) % $options->getMaxResults(),
  1027. 'when no next marker and Prefix=(\'' . $options->getPrefix() . '\'), then Blobs length');
  1028. } else {
  1029. // Do not know how many there should be
  1030. }
  1031. } else {
  1032. $this->assertEquals(count($ret->getBlobs()), $options->getMaxResults(), 'when NextMarker (' . $ret->getNextMarker() . ')!=\'\', Blobs length (' . count($ret->getBlobs()) . ') should be == MaxResults (' . $options->getMaxResults() . ')');
  1033. if (!is_null($options->getPrefix()) && $options->getPrefix() == (BlobServiceFunctionalTestData::$nonExistBlobPrefix)) {
  1034. $this->assertTrue(false, 'when a next marker and Prefix=(\'' . $options->getPrefix() . '\'), impossible');
  1035. }
  1036. }
  1037. }
  1038. /**
  1039. * @covers WindowsAzure\Blob\BlobRestProxy::createBlockBlob
  1040. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1041. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobMetadata
  1042. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1043. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1044. */
  1045. public function testGetBlobMetadataNoOptions()
  1046. {
  1047. $container = BlobServiceFunctionalTestData::getContainerName();
  1048. $this->getBlobMetadataWorker($container, null);
  1049. }
  1050. /**
  1051. * @covers WindowsAzure\Blob\BlobRestProxy::createBlockBlob
  1052. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1053. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobMetadata
  1054. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1055. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1056. */
  1057. public function testGetBlobMetadataNoOptionsRoot()
  1058. {
  1059. $container = null;
  1060. $this->getBlobMetadataWorker($container, null);
  1061. }
  1062. /**
  1063. * @covers WindowsAzure\Blob\BlobRestProxy::createBlockBlob
  1064. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1065. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobMetadata
  1066. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1067. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1068. */
  1069. public function testGetBlobMetadataNoOptionsExplicitRoot()
  1070. {
  1071. $container = '$root';
  1072. $this->getBlobMetadataWorker($container, null);
  1073. }
  1074. /**
  1075. * @covers WindowsAzure\Blob\BlobRestProxy::createBlockBlob
  1076. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1077. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobMetadata
  1078. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1079. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1080. */
  1081. public function testGetBlobMetadata()
  1082. {
  1083. $container = BlobServiceFunctionalTestData::getContainerName();
  1084. $interestingTimeouts = BlobServiceFunctionalTestData::getInterestingTimeoutValues();
  1085. foreach($interestingTimeouts as $timeout) {
  1086. $options = new GetBlobMetadataOptions();
  1087. $options->setTimeout($timeout);
  1088. $this->getBlobMetadataWorker($container, $options);
  1089. }
  1090. }
  1091. /**
  1092. * @covers WindowsAzure\Blob\BlobRestProxy::createBlockBlob
  1093. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1094. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobMetadata
  1095. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1096. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1097. */
  1098. private function getBlobMetadataWorker($container, $options)
  1099. {
  1100. $blob = BlobServiceFunctionalTestData::getInterestingBlobName();
  1101. // Make sure there is something to test
  1102. $createBlockBlobResult = $this->restProxy->createBlockBlob($container, $blob, "");
  1103. $properties = BlobServiceFunctionalTestData::getNiceMetadata();
  1104. $this->restProxy->setBlobMetadata($container, $blob, $properties);
  1105. if (!is_null($options)) {
  1106. BlobServiceFunctionalTestData::fixETagAccessCondition($options->getAccessCondition(), $createBlockBlobResult->getETag());
  1107. }
  1108. try {
  1109. $res = (is_null($options) ? $this->restProxy->getBlobMetadata($container, $blob) : $this->restProxy->getBlobMetadata($container, $blob, $options));
  1110. if (is_null($options)) {
  1111. $options = new GetBlobMetadataOptions();
  1112. }
  1113. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  1114. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  1115. }
  1116. if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  1117. $this->assertTrue(false, 'Failing temporal access condition should throw');
  1118. }
  1119. if (!BlobServiceFunctionalTestData::passETagAccessCondition($options->getAccessCondition())) {
  1120. $this->assertTrue(false, 'Failing etag access condition should throw');
  1121. }
  1122. $this->verifyGetBlobMetadataWorker($res, $properties);
  1123. } catch (ServiceException $e) {
  1124. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  1125. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'bad timeout: getCode');
  1126. } else if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  1127. $this->assertEquals(TestResources::STATUS_PRECONDITION_FAILED, $e->getCode(), 'bad temporal access condition: getCode');
  1128. } else if (!BlobServiceFunctionalTestData::passETagAccessCondition($options->getAccessCondition())) {
  1129. $this->assertEquals(TestResources::STATUS_PRECONDITION_FAILED, $e->getCode(), 'bad etag access condition: getCode');
  1130. } else {
  1131. throw $e;
  1132. }
  1133. }
  1134. // Clean up.
  1135. $this->restProxy->deleteBlob($container, $blob);
  1136. }
  1137. private function verifyGetBlobMetadataWorker($res, $metadata)
  1138. {
  1139. $this->assertNotNull($res->getMetadata(), 'blob Metadata');
  1140. $this->assertNotNull($res->getETag(), 'blob getETag');
  1141. $this->assertNotNull($res->getLastModified(), 'blob getLastModified');
  1142. $this->assertEquals(count($metadata), count($res->getMetadata()), 'Metadata');
  1143. $retMetadata = $res->getMetadata();
  1144. foreach($metadata as $key => $value) {
  1145. $this->assertEquals($value, $retMetadata[$key], 'Metadata(' . $key . ')');
  1146. }
  1147. // Make sure the last modified date is within 10 seconds
  1148. $now = new \DateTime();
  1149. $this->assertTrue(BlobServiceFunctionalTestData::diffInTotalSeconds(
  1150. $res->getLastModified(),
  1151. $now) < 10000,
  1152. 'Last modified date (' . $res->getLastModified()->format(\DateTime::RFC1123) . ') ' .
  1153. 'should be within 10 seconds of $now (' . $now->format(\DateTime::RFC1123) . ')');
  1154. }
  1155. /**
  1156. * @covers WindowsAzure\Blob\BlobRestProxy::createBlockBlob
  1157. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1158. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobMetadata
  1159. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1160. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1161. */
  1162. public function testSetBlobMetadataNoOptions()
  1163. {
  1164. $container = BlobServiceFunctionalTestData::getContainerName();
  1165. $interestingMetadata = BlobServiceFunctionalTestData::getInterestingMetadata();
  1166. foreach($interestingMetadata as $properties) {
  1167. $this->setBlobMetadataWorker($container, null, $properties);
  1168. }
  1169. }
  1170. /**
  1171. * @covers WindowsAzure\Blob\BlobRestProxy::createBlockBlob
  1172. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1173. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobMetadata
  1174. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1175. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1176. */
  1177. public function testSetBlobMetadataNoOptionsRoot()
  1178. {
  1179. $container = null;
  1180. $interestingMetadata = BlobServiceFunctionalTestData::getInterestingMetadata();
  1181. foreach($interestingMetadata as $properties) {
  1182. $this->setBlobMetadataWorker($container, null, $properties);
  1183. }
  1184. }
  1185. /**
  1186. * @covers WindowsAzure\Blob\BlobRestProxy::createBlockBlob
  1187. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1188. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobMetadata
  1189. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1190. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1191. */
  1192. public function testSetBlobMetadataNoOptionsExplicitRoot()
  1193. {
  1194. $container = '$root';
  1195. $interestingMetadata = BlobServiceFunctionalTestData::getInterestingMetadata();
  1196. foreach($interestingMetadata as $properties) {
  1197. $this->setBlobMetadataWorker($container, null, $properties);
  1198. }
  1199. }
  1200. /**
  1201. * @covers WindowsAzure\Blob\BlobRestProxy::createBlockBlob
  1202. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1203. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobMetadata
  1204. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1205. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1206. */
  1207. public function testSetBlobMetadata()
  1208. {
  1209. $container = BlobServiceFunctionalTestData::getContainerName();
  1210. $interestingSetBlobMetadataOptions = BlobServiceFunctionalTestData::getSetBlobMetadataOptions();
  1211. $interestingMetadata = BlobServiceFunctionalTestData::getInterestingMetadata();
  1212. foreach($interestingSetBlobMetadataOptions as $options) {
  1213. foreach($interestingMetadata as $properties) {
  1214. $this->setBlobMetadataWorker($container, $options, $properties);
  1215. }
  1216. }
  1217. }
  1218. /**
  1219. * @covers WindowsAzure\Blob\BlobRestProxy::createBlockBlob
  1220. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1221. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobMetadata
  1222. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1223. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1224. */
  1225. private function setBlobMetadataWorker($container, $options, $metadata)
  1226. {
  1227. $blob = BlobServiceFunctionalTestData::getInterestingBlobName();
  1228. // Make sure there is something to test
  1229. $createBlockBlobResult = $this->restProxy->createBlockBlob($container, $blob, "");
  1230. if (!is_null($options)) {
  1231. BlobServiceFunctionalTestData::fixETagAccessCondition($options->getAccessCondition(), $createBlockBlobResult->getETag());
  1232. }
  1233. $firstkey = '';
  1234. if (!is_null($metadata) && count($metadata) > 0) {
  1235. $firstkey = array_keys($metadata);
  1236. $firstkey = $firstkey[0];
  1237. }
  1238. try {
  1239. try {
  1240. // And put in some properties
  1241. $res = (is_null($options) ? $this->restProxy->setBlobMetadata($container, $blob, $metadata) : $this->restProxy->setBlobMetadata($container, $blob, $metadata, $options));
  1242. if (is_null($options)) {
  1243. $options = new SetBlobMetadataOptions();
  1244. }
  1245. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  1246. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  1247. }
  1248. if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  1249. $this->assertTrue(false, 'Failing access condition should throw');
  1250. }
  1251. if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  1252. $this->assertTrue(false, 'Expect failing access condition to throw');
  1253. }
  1254. if (Utilities::startsWith($firstkey, '<')) {
  1255. $this->assertTrue(false, 'Should get HTTP request error if the metadata is invalid');
  1256. }
  1257. $this->verifySetBlobMetadataWorker($res);
  1258. $res2 = $this->restProxy->getBlobMetadata($container, $blob);
  1259. $this->verifyGetBlobMetadataWorker($res2, $metadata);
  1260. } catch (\HTTP_Request2_LogicException $e) {
  1261. $this->assertTrue(
  1262. Utilities::startsWith($firstkey, '<'),
  1263. 'Should get HTTP request error only if the metadata is invalid');
  1264. }
  1265. } catch (ServiceException $e) {
  1266. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  1267. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'bad timeout: getCode');
  1268. } else if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  1269. $this->assertEquals(TestResources::STATUS_PRECONDITION_FAILED, $e->getCode(), 'bad temporal access condition: getCode');
  1270. } else if (!BlobServiceFunctionalTestData::passETagAccessCondition($options->getAccessCondition())) {
  1271. $this->assertEquals(TestResources::STATUS_PRECONDITION_FAILED, $e->getCode(), 'bad etag access condition: getCode');
  1272. } else {
  1273. throw $e;
  1274. }
  1275. }
  1276. // Clean up.
  1277. $this->restProxy->deleteBlob($container, $blob);
  1278. }
  1279. private function verifySetBlobMetadataWorker($res)
  1280. {
  1281. $this->assertNotNull($res->getETag(), 'blob getETag');
  1282. $this->assertNotNull($res->getLastModified(), 'blob getLastModified');
  1283. // Make sure the last modified date is within 10 seconds
  1284. $now = new \DateTime();
  1285. $this->assertTrue(BlobServiceFunctionalTestData::diffInTotalSeconds(
  1286. $res->getLastModified(),
  1287. $now) < 10000,
  1288. 'Last modified date (' . $res->getLastModified()->format(\DateTime::RFC1123) . ') ' .
  1289. 'should be within 10 seconds of $now (' . $now->format(\DateTime::RFC1123) . ')');
  1290. }
  1291. /**
  1292. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1293. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1294. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1295. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1296. */
  1297. public function testGetBlobPropertiesNoOptions()
  1298. {
  1299. $container = BlobServiceFunctionalTestData::getContainerName();
  1300. $this->getBlobPropertiesWorker($container, null);
  1301. }
  1302. /**
  1303. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1304. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1305. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1306. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1307. */
  1308. public function testGetBlobPropertiesNoOptionsRoot()
  1309. {
  1310. $container = null;
  1311. $this->getBlobPropertiesWorker($container, null);
  1312. }
  1313. /**
  1314. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1315. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1316. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1317. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1318. */
  1319. public function testGetBlobPropertiesNoOptionsExplicitRoot()
  1320. {
  1321. $container = '$root';
  1322. $this->getBlobPropertiesWorker($container, null);
  1323. }
  1324. /**
  1325. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1326. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1327. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1328. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1329. */
  1330. public function testGetBlobProperties()
  1331. {
  1332. $container = BlobServiceFunctionalTestData::getContainerName();
  1333. $interestingGetBlobPropertiesOptions = BlobServiceFunctionalTestData::getGetBlobPropertiesOptions();
  1334. foreach($interestingGetBlobPropertiesOptions as $options) {
  1335. $this->getBlobPropertiesWorker($container, $options);
  1336. }
  1337. }
  1338. /**
  1339. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1340. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1341. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1342. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1343. */
  1344. private function getBlobPropertiesWorker($container, $options)
  1345. {
  1346. $blob = BlobServiceFunctionalTestData::getInterestingBlobName();
  1347. // Make sure there is something to test
  1348. $createPageBlobResult = $this->restProxy->createPageBlob($container, $blob, 512);
  1349. $metadata = BlobServiceFunctionalTestData::getNiceMetadata();
  1350. $this->restProxy->setBlobMetadata($container, $blob, $metadata);
  1351. // Do not set the properties, there should be default properties.
  1352. if (!is_null($options)) {
  1353. BlobServiceFunctionalTestData::fixETagAccessCondition($options->getAccessCondition(), $createPageBlobResult->getETag());
  1354. }
  1355. try {
  1356. $res = (is_null($options) ? $this->restProxy->getBlobProperties($container, $blob) : $this->restProxy->getBlobProperties($container, $blob, $options));
  1357. if (is_null($options)) {
  1358. $options = new GetBlobPropertiesOptions();
  1359. }
  1360. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  1361. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  1362. }
  1363. if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  1364. $this->assertTrue(false, 'Failing temporal access condition should throw');
  1365. }
  1366. $this->verifyGetBlobPropertiesWorker($res, $metadata, null);
  1367. } catch (ServiceException $e) {
  1368. if (!is_null($options->getAccessCondition()) &&
  1369. !$this->hasSecureEndpoint() &&
  1370. $e->getCode() == TestResources::STATUS_FORBIDDEN) {
  1371. // Proxies can eat the access condition headers of
  1372. // unsecured (http) requests, which causes the authentication
  1373. // to fail, with a 403:Forbidden. There is nothing much that
  1374. // can be done about this, other than ignore it.
  1375. } else if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  1376. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'bad timeout: getCode');
  1377. } else if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  1378. if ($options->getAccessCondition()->getHeader() == Resources::IF_MODIFIED_SINCE) {
  1379. $this->assertEquals(TestResources::STATUS_NOT_MODIFIED, $e->getCode(), 'bad temporal access condition IF_MODIFIED_SINCE: getCode');
  1380. } else {
  1381. $this->assertEquals(TestResources::STATUS_PRECONDITION_FAILED, $e->getCode(), 'bad temporal access condition: getCode');
  1382. }
  1383. } else {
  1384. throw $e;
  1385. }
  1386. }
  1387. // Clean up.
  1388. $this->restProxy->deleteBlob($container, $blob);
  1389. }
  1390. private function verifyGetBlobPropertiesWorker($res, $metadata, $properties)
  1391. {
  1392. /* The semantics for updating a blob's properties are as follows:
  1393. *
  1394. * * A page blob's sequence number is updated only if the request meets either of the
  1395. * following conditions:
  1396. *
  1397. * * The request sets the x-ms-sequence-number-action to max or update, and also
  1398. * specifies a value for the x-ms-blob-sequence-number header.
  1399. * * The request sets the x-ms-sequence-number-action to increment, indicating that
  1400. * the service should increment the sequence number by one.
  1401. *
  1402. * * A page blob's size is modified only if the request specifies a value for the
  1403. * x-ms-content-length header.
  1404. *
  1405. * * If a request sets only x-ms-blob-sequence-number and/or x-ms-content-length, and
  1406. * no other properties, then none of the blob's other properties are modified.
  1407. *
  1408. * * If any one or more of the following properties is set in the request, then all of
  1409. * these properties are set together. If a value is not provided for a given property
  1410. * when at least one of the properties listed below is set, then that property will be
  1411. * cleared for the blob.
  1412. *
  1413. * * x-ms-blob-cache-control
  1414. * * x-ms-blob-content-type
  1415. * * x-ms-blob-content-md5
  1416. * * x-ms-blob-content-encoding
  1417. * * x-ms-blob-content-language
  1418. */
  1419. $this->assertNotNull($res->getMetadata(), 'blob Metadata');
  1420. if (is_null($metadata)) {
  1421. $this->assertEquals(0, count($res->getMetadata()), 'Metadata');
  1422. } else {
  1423. $this->assertEquals(count($metadata), count($res->getMetadata()), 'Metadata');
  1424. $resMetadata = $res->getMetadata();
  1425. foreach($metadata as $key => $value) {
  1426. $this->assertEquals($value, $resMetadata[$key], 'Metadata(' . $key . ')');
  1427. }
  1428. }
  1429. $this->assertNotNull($res->getProperties(), 'blob Properties');
  1430. $this->assertNotNull($res->getProperties()->getETag(), 'blob getProperties->getETag');
  1431. $this->assertNotNull($res->getProperties()->getLastModified(), 'blob getProperties->getLastModified');
  1432. $this->assertEquals('PageBlob', $res->getProperties()->getBlobType(), 'blob getProperties->getBlobType');
  1433. $this->assertEquals('unlocked', $res->getProperties()->getLeaseStatus(), 'blob getProperties->getLeaseStatus');
  1434. if (is_null($properties) || !is_null($properties->getBlobContentLength()) || !is_null($properties->getSequenceNumber())) {
  1435. $this->assertNull($res->getProperties()->getCacheControl(), 'blob getProperties->getCacheControl');
  1436. $this->assertEquals('application/octet-stream', $res->getProperties()->getContentType(), 'blob getProperties->getContentType');
  1437. $this->assertNull($res->getProperties()->getContentMD5(), 'blob getProperties->getContentMD5');
  1438. $this->assertNull($res->getProperties()->getContentEncoding(), 'blob getProperties->getContentEncoding');
  1439. $this->assertNull($res->getProperties()->getContentLanguage(), 'blob getProperties->getContentLanguage');
  1440. } else {
  1441. $this->assertEquals($properties->getBlobCacheControl(), $res->getProperties()->getCacheControl(), 'blob getProperties->getCacheControl');
  1442. $this->assertEquals($properties->getBlobContentType(), $res->getProperties()->getContentType(), 'blob getProperties->getContentType');
  1443. $this->assertEquals($properties->getBlobContentMD5(), $res->getProperties()->getContentMD5(), 'blob getProperties->getContentMD5');
  1444. $this->assertEquals($properties->getBlobContentEncoding(), $res->getProperties()->getContentEncoding(), 'blob getProperties->getContentEncoding');
  1445. $this->assertEquals($properties->getBLobContentLanguage(), $res->getProperties()->getContentLanguage(), 'blob getProperties->getContentLanguage');
  1446. }
  1447. if (is_null($properties) || is_null($properties->getBlobContentLength())) {
  1448. $this->assertEquals(512, $res->getProperties()->getContentLength(), 'blob getProperties->getContentLength');
  1449. } else {
  1450. $this->assertEquals($properties->getBlobContentLength(), $res->getProperties()->getContentLength(), 'blob getProperties->getContentLength');
  1451. }
  1452. if (is_null($properties) || is_null($properties->getSequenceNumber())) {
  1453. $this->assertEquals(0, $res->getProperties()->getSequenceNumber(), 'blob getProperties->getSequenceNumber');
  1454. } else {
  1455. $this->assertEquals($properties->getSequenceNumber(), $res->getProperties()->getSequenceNumber(), 'blob getProperties->getSequenceNumber');
  1456. }
  1457. // Make sure the last modified date is within 10 seconds
  1458. $now = new \DateTime();
  1459. $this->assertTrue(BlobServiceFunctionalTestData::diffInTotalSeconds(
  1460. $res->getProperties()->getLastModified(),
  1461. $now) < 10000,
  1462. 'Last modified date (' . $res->getProperties()->getLastModified()->format(\DateTime::RFC1123) . ') ' .
  1463. 'should be within 10 seconds of $now (' . $now->format(\DateTime::RFC1123) . ')');
  1464. }
  1465. /**
  1466. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1467. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1468. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1469. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobProperties
  1470. */
  1471. public function testSetBlobProperties()
  1472. {
  1473. $container = BlobServiceFunctionalTestData::getContainerName();
  1474. $interestingSetBlobPropertiesOptions = BlobServiceFunctionalTestData::getSetBlobPropertiesOptions();
  1475. foreach($interestingSetBlobPropertiesOptions as $properties) {
  1476. $this->setBlobPropertiesWorker($container, $properties);
  1477. }
  1478. }
  1479. /**
  1480. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1481. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1482. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1483. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobProperties
  1484. */
  1485. public function testSetBlobPropertiesRoot()
  1486. {
  1487. $container = null;
  1488. $interestingSetBlobPropertiesOptions = BlobServiceFunctionalTestData::getSetBlobPropertiesOptions();
  1489. $this->setBlobPropertiesWorker($container, $interestingSetBlobPropertiesOptions[2]);
  1490. }
  1491. /**
  1492. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1493. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1494. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1495. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobProperties
  1496. */
  1497. public function testSetBlobPropertiesExplicitRoot()
  1498. {
  1499. $container = '$root';
  1500. $interestingSetBlobPropertiesOptions = BlobServiceFunctionalTestData::getSetBlobPropertiesOptions();
  1501. $this->setBlobPropertiesWorker($container, $interestingSetBlobPropertiesOptions[2]);
  1502. }
  1503. /**
  1504. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1505. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1506. * @covers WindowsAzure\Blob\BlobRestProxy::getBlobProperties
  1507. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobProperties
  1508. */
  1509. private function setBlobPropertiesWorker($container, $properties)
  1510. {
  1511. $blob = BlobServiceFunctionalTestData::getInterestingBlobName();
  1512. // Make sure there is something to test
  1513. $createPageBlobResult = $this->restProxy->createPageBlob($container, $blob, 512);
  1514. BlobServiceFunctionalTestData::fixETagAccessCondition($properties->getAccessCondition(), $createPageBlobResult->getETag());
  1515. try {
  1516. // And put in some properties
  1517. $res = $this->restProxy->setBlobProperties($container, $blob, $properties);
  1518. if (!is_null($properties->getTimeout()) && $properties->getTimeout() < 1) {
  1519. $this->assertTrue(false, 'Expect negative timeouts in options to throw');
  1520. }
  1521. if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($properties->getAccessCondition())) {
  1522. $this->assertTrue(false, 'Failing access condition should throw');
  1523. }
  1524. if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($properties->getAccessCondition())) {
  1525. $this->assertTrue(false, 'Expect failing access condition to throw');
  1526. }
  1527. $this->verifySetBlobPropertiesWorker($res);
  1528. $res2 = $this->restProxy->getBlobProperties($container, $blob);
  1529. $this->verifyGetBlobPropertiesWorker($res2, null, $properties);
  1530. } catch (ServiceException $e) {
  1531. if (!is_null($properties->getTimeout()) && $properties->getTimeout() < 1) {
  1532. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'bad timeout: getCode');
  1533. } else if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($properties->getAccessCondition())) {
  1534. $this->assertEquals(TestResources::STATUS_PRECONDITION_FAILED, $e->getCode(), 'bad temporal access condition: getCode');
  1535. } else if (!BlobServiceFunctionalTestData::passETagAccessCondition($properties->getAccessCondition())) {
  1536. $this->assertEquals(TestResources::STATUS_PRECONDITION_FAILED, $e->getCode(), 'bad etag access condition: getCode');
  1537. } else {
  1538. }
  1539. }
  1540. // Clean up.
  1541. $this->restProxy->deleteBlob($container, $blob);
  1542. }
  1543. private function verifySetBlobPropertiesWorker($res)
  1544. {
  1545. $this->assertNotNull($res->getETag(), 'blob getETag');
  1546. $this->assertNotNull($res->getLastModified(), 'blob getLastModified');
  1547. $this->assertNotNull($res->getSequenceNumber(), 'blob getSequenceNumber');
  1548. $this->assertEquals(0, $res->getSequenceNumber(), 'blob getSequenceNumber');
  1549. // Make sure the last modified date is within 10 seconds
  1550. $now = new \DateTime();
  1551. $this->assertTrue(BlobServiceFunctionalTestData::diffInTotalSeconds(
  1552. $res->getLastModified(),
  1553. $now) < 10000,
  1554. 'Last modified date (' . $res->getLastModified()->format(\DateTime::RFC1123) . ') ' .
  1555. 'should be within 10 seconds of $now (' . $now->format(\DateTime::RFC1123) . ')');
  1556. }
  1557. /**
  1558. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1559. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1560. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1561. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1562. */
  1563. public function testGetBlob_NoOptions()
  1564. {
  1565. $container = BlobServiceFunctionalTestData::getContainerName();
  1566. $this->getBlobWorker(null, $container);
  1567. }
  1568. /**
  1569. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1570. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1571. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1572. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1573. */
  1574. public function testGetBlob_NoOptionsExplicitRoot()
  1575. {
  1576. $this->getBlobWorker(null, '$root');
  1577. }
  1578. /**
  1579. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1580. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1581. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1582. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1583. */
  1584. public function testGetBlob_NoOptionsRoot()
  1585. {
  1586. $this->getBlobWorker(null, '');
  1587. }
  1588. /**
  1589. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1590. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1591. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1592. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1593. */
  1594. public function testGetBlob_AllOptions()
  1595. {
  1596. $container = BlobServiceFunctionalTestData::getContainerName();
  1597. $interestingGetBlobOptions = BlobServiceFunctionalTestData::getGetBlobOptions();
  1598. foreach($interestingGetBlobOptions as $options) {
  1599. $this->getBlobWorker($options, $container);
  1600. }
  1601. }
  1602. /**
  1603. * @covers WindowsAzure\Blob\BlobRestProxy::createBlobSnapshot
  1604. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1605. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1606. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1607. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1608. */
  1609. private function getBlobWorker($options, $container)
  1610. {
  1611. $blob = BlobServiceFunctionalTestData::getInterestingBlobName();
  1612. // Make sure there is something to test
  1613. $dataSize = 512;
  1614. $this->restProxy->createPageBlob($container, $blob, $dataSize);
  1615. $metadata = BlobServiceFunctionalTestData::getNiceMetadata();
  1616. $sbmd = $this->restProxy->setBlobMetadata($container, $blob, $metadata);
  1617. $snapshot = $this->restProxy->createBlobSnapshot($container, $blob);
  1618. $this->restProxy->createBlobSnapshot($container, $blob);
  1619. if (!is_null($options)) {
  1620. BlobServiceFunctionalTestData::fixETagAccessCondition($options->getAccessCondition(), $sbmd->getETag());
  1621. $options->setSnapshot(is_null($options->getSnapshot()) ? null : $snapshot->getSnapshot());
  1622. }
  1623. try {
  1624. $res = (is_null($options) ? $this->restProxy->getBlob($container, $blob) : $this->restProxy->getBlob($container, $blob, $options));
  1625. if (is_null($options)) {
  1626. $options = new GetBlobOptions();
  1627. }
  1628. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  1629. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  1630. }
  1631. if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  1632. $this->assertTrue(false, 'Expect failing temporal access condition should throw');
  1633. }
  1634. if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  1635. $this->assertTrue(false, 'Expect failing etag access condition to throw');
  1636. }
  1637. if ($options->getComputeRangeMD5() && is_null($options->getRangeStart())) {
  1638. $this->assertTrue(false, 'Expect compute range MD5 to fail if range not set');
  1639. }
  1640. $this->verifyGetBlobWorker($res, $options, $dataSize, $metadata);
  1641. } catch (ServiceException $e) {
  1642. if (!is_null($options->getAccessCondition()) &&
  1643. !$this->hasSecureEndpoint() &&
  1644. $e->getCode() == TestResources::STATUS_FORBIDDEN) {
  1645. // Proxies can eat the access condition headers of
  1646. // unsecured (http) requests, which causes the authentication
  1647. // to fail, with a 403:Forbidden. There is nothing much that
  1648. // can be done about this, other than ignore it.
  1649. } else if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  1650. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'bad timeout: getCode');
  1651. } else if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  1652. if ($options->getAccessCondition()->getHeader() == Resources::IF_MODIFIED_SINCE) {
  1653. $this->assertEquals(TestResources::STATUS_NOT_MODIFIED, $e->getCode(), 'bad temporal access condition IF_MODIFIED_SINCE: getCode');
  1654. } else {
  1655. $this->assertEquals(TestResources::STATUS_PRECONDITION_FAILED, $e->getCode(), 'bad temporal access condition IF_UNMODIFIED_SINCE: getCode');
  1656. }
  1657. } else if (!BlobServiceFunctionalTestData::passETagAccessCondition($options->getAccessCondition())) {
  1658. $this->assertEquals(TestResources::STATUS_PRECONDITION_FAILED, $e->getCode(), 'bad etag access condition: getCode');
  1659. } else if ($options->getComputeRangeMD5() && is_null($options->getRangeStart())) {
  1660. $this->assertEquals(TestResources::STATUS_BAD_REQUEST, $e->getCode(), 'Expect compute range MD5 to fail when range not set: getCode');
  1661. } else {
  1662. throw $e;
  1663. }
  1664. }
  1665. // Clean up.
  1666. $this->restProxy->deleteBlob($container, $blob);
  1667. }
  1668. private function verifyGetBlobWorker($res, $options, $dataSize, $metadata)
  1669. {
  1670. $this->assertNotNull($res, 'result');
  1671. $content = stream_get_contents($res->getContentStream());
  1672. $rangeSize = $dataSize;
  1673. if (!is_null($options->getRangeEnd())) {
  1674. $rangeSize = (int) $options->getRangeEnd() + 1;
  1675. }
  1676. if (!is_null($options->getRangeStart())) {
  1677. $rangeSize -= $options->getRangeStart();
  1678. } else {
  1679. // One might expect that not specifying the start would just take the
  1680. // first $rangeEnd bytes, but instead the Azure service ignores
  1681. // the malformed Range headers.
  1682. $rangeSize = $dataSize;
  1683. }
  1684. $this->assertEquals($rangeSize, strlen($content), '$content length and range');
  1685. if ($options->getComputeRangeMD5()) {
  1686. // Compute the MD5 from the stream.
  1687. $md5 = base64_encode(md5($content, true));
  1688. $this->assertEquals($md5, $res->getProperties()->getContentMD5(), 'asked for MD5, result->getProperties()->getContentMD5');
  1689. } else {
  1690. $this->assertNull($res->getProperties()->getContentMD5(), 'did not ask for MD5, result->getProperties()->getContentMD5');
  1691. }
  1692. $this->assertNotNull($res->getMetadata(), 'blob Metadata');
  1693. $resMetadata = $res->getMetadata();
  1694. $this->assertEquals(count($metadata), count($resMetadata), 'Metadata');
  1695. foreach($metadata as $key => $value) {
  1696. $this->assertEquals($value, $resMetadata[$key], 'Metadata(' . $key . ')');
  1697. }
  1698. // Rest of the properties are tested elsewhere.
  1699. }
  1700. /**
  1701. * @covers WindowsAzure\Blob\BlobRestProxy::createBlobSnapshot
  1702. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1703. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1704. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1705. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  1706. */
  1707. public function testDeleteBlobNoOptions()
  1708. {
  1709. $container = BlobServiceFunctionalTestData::getContainerName();
  1710. $this->deleteBlobWorker(null, $container);
  1711. }
  1712. /**
  1713. * @covers WindowsAzure\Blob\BlobRestProxy::createBlobSnapshot
  1714. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1715. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1716. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1717. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  1718. */
  1719. public function testDeleteBlobNoOptionsExplicitRoot()
  1720. {
  1721. $this->deleteBlobWorker(null, '$root');
  1722. }
  1723. /**
  1724. * @covers WindowsAzure\Blob\BlobRestProxy::createBlobSnapshot
  1725. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1726. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1727. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1728. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  1729. */
  1730. public function testDeleteBlobNoOptionsRoot()
  1731. {
  1732. $this->deleteBlobWorker(null, '');
  1733. }
  1734. /**
  1735. * @covers WindowsAzure\Blob\BlobRestProxy::createBlobSnapshot
  1736. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1737. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1738. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1739. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  1740. */
  1741. public function testDeleteBlob()
  1742. {
  1743. $container = BlobServiceFunctionalTestData::getContainerName();
  1744. $interestingDeleteBlobOptions = BlobServiceFunctionalTestData::getDeleteBlobOptions();
  1745. foreach($interestingDeleteBlobOptions as $options) {
  1746. $this->deleteBlobWorker($options, $container);
  1747. }
  1748. }
  1749. /**
  1750. * @covers WindowsAzure\Blob\BlobRestProxy::createBlobSnapshot
  1751. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1752. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1753. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1754. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  1755. */
  1756. private function deleteBlobWorker($options, $container)
  1757. {
  1758. $blob = BlobServiceFunctionalTestData::getInterestingBlobName();
  1759. // Make sure there is something to test
  1760. $dataSize = 512;
  1761. $this->restProxy->createPageBlob($container, $blob, $dataSize);
  1762. $snapshot = $this->restProxy->createBlobSnapshot($container, $blob);
  1763. $this->restProxy->createBlobSnapshot($container, $blob);
  1764. $blobinfo = $this->restProxy->getBlob($container, $blob);
  1765. if (!is_null($options)) {
  1766. BlobServiceFunctionalTestData::fixETagAccessCondition($options->getAccessCondition(), $blobinfo->getProperties()->getETag());
  1767. $options->setSnapshot(is_null($options->getSnapshot()) ? null : $snapshot->getSnapshot());
  1768. }
  1769. $deleted = false;
  1770. try {
  1771. if (is_null($options)) {
  1772. $this->restProxy->deleteBlob($container, $blob);
  1773. } else {
  1774. $this->restProxy->deleteBlob($container, $blob, $options);
  1775. }
  1776. $deleted = true;
  1777. if (is_null($options)) {
  1778. $options = new DeleteBlobOptions();
  1779. }
  1780. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  1781. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  1782. }
  1783. if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  1784. $this->assertTrue(false, 'Expect failing temporal access condition should throw');
  1785. }
  1786. if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  1787. $this->assertTrue(false, 'Expect failing etag access condition to throw');
  1788. }
  1789. $listOptions = new ListBlobsOptions();
  1790. $listOptions->setIncludeSnapshots(true);
  1791. $listOptions->setPrefix($blob);
  1792. $listBlobsResult = $this->restProxy->listBlobs($container == '' ? '$root' : $container, $listOptions);
  1793. $blobs = $listBlobsResult->getBlobs();
  1794. $this->verifyDeleteBlobWorker($options, $blobs);
  1795. } catch (ServiceException $e) {
  1796. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  1797. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'bad timeout: deleteHttpStatusCode');
  1798. } else if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  1799. $this->assertEquals(TestResources::STATUS_PRECONDITION_FAILED, $e->getCode(), 'bad temporal access condition IF_UNMODIFIED_SINCE: deleteHttpStatusCode');
  1800. } else if (!BlobServiceFunctionalTestData::passETagAccessCondition($options->getAccessCondition())) {
  1801. $this->assertEquals(TestResources::STATUS_PRECONDITION_FAILED, $e->getCode(), 'bad etag access condition: deleteHttpStatusCode');
  1802. } else {
  1803. throw $e;
  1804. }
  1805. }
  1806. // Clean up.
  1807. if (!$deleted) {
  1808. $this->restProxy->deleteBlob($container, $blob);
  1809. }
  1810. }
  1811. private function verifyDeleteBlobWorker($options, $blobs)
  1812. {
  1813. if (!is_null($options->getSnapshot())) {
  1814. $this->assertEquals(2, count($blobs), 'when give a snapshot, $blobs with same name as main blob');
  1815. } else if ($options->getDeleteSnaphotsOnly()) {
  1816. $this->assertEquals(1, count($blobs), 'when getDeleteSnaphotsOnly=true, $blobs with same name as main blob');
  1817. } else {
  1818. $this->assertEquals(0, count($blobs), 'when getDeleteSnaphotsOnly=false, blob with same name as main blob');
  1819. }
  1820. }
  1821. /**
  1822. * @covers WindowsAzure\Blob\BlobRestProxy::createBlobSnapshot
  1823. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1824. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1825. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1826. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  1827. */
  1828. public function testCreateBlobSnapshotNoOptionsContainer()
  1829. {
  1830. $container = BlobServiceFunctionalTestData::getContainerName();
  1831. $this->createBlobSnapshotWorker(null, $container);
  1832. }
  1833. /**
  1834. * @covers WindowsAzure\Blob\BlobRestProxy::createBlobSnapshot
  1835. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1836. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1837. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1838. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  1839. */
  1840. public function testCreateBlobSnapshotNoOptionsExplicitRoot()
  1841. {
  1842. $this->createBlobSnapshotWorker(null, '$root');
  1843. }
  1844. /**
  1845. * @covers WindowsAzure\Blob\BlobRestProxy::createBlobSnapshot
  1846. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1847. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1848. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1849. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  1850. */
  1851. public function testCreateBlobSnapshotNoOptionsRoot()
  1852. {
  1853. $this->createBlobSnapshotWorker(null, '');
  1854. }
  1855. /**
  1856. * @covers WindowsAzure\Blob\BlobRestProxy::createBlobSnapshot
  1857. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1858. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1859. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1860. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  1861. */
  1862. public function testCreateBlobSnapshotAllOptions()
  1863. {
  1864. $container = BlobServiceFunctionalTestData::getContainerName();
  1865. $interestingCreateBlobSnapshotOptions = BlobServiceFunctionalTestData::getCreateBlobSnapshotOptions();
  1866. foreach($interestingCreateBlobSnapshotOptions as $options) {
  1867. $this->createBlobSnapshotWorker($options, $container);
  1868. }
  1869. }
  1870. /**
  1871. * @covers WindowsAzure\Blob\BlobRestProxy::createBlobSnapshot
  1872. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1873. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1874. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1875. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  1876. */
  1877. private function createBlobSnapshotWorker($options, $container)
  1878. {
  1879. $blob = BlobServiceFunctionalTestData::getInterestingBlobName();
  1880. // Make sure there is something to test
  1881. $dataSize = 512;
  1882. $this->restProxy->createPageBlob($container, $blob, $dataSize);
  1883. $snapshot1 = $this->restProxy->createBlobSnapshot($container, $blob);
  1884. if (!is_null($options)) {
  1885. BlobServiceFunctionalTestData::fixETagAccessCondition($options->getAccessCondition(), $snapshot1->getETag());
  1886. }
  1887. try {
  1888. $res = (is_null($options) ? $this->restProxy->createBlobSnapshot($container, $blob) : $this->restProxy->createBlobSnapshot($container, $blob, $options));
  1889. if (is_null($options)) {
  1890. $options = new CreateBlobSnapshotOptions();
  1891. }
  1892. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  1893. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  1894. }
  1895. if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  1896. $this->assertTrue(false, 'Expect failing temporal access condition should throw');
  1897. }
  1898. if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  1899. $this->assertTrue(false, 'Expect failing etag access condition to throw');
  1900. }
  1901. $listOptions = new ListBlobsOptions();
  1902. $listOptions->setIncludeSnapshots(true);
  1903. $listOptions->setPrefix($blob);
  1904. $listBlobsResult = $this->restProxy->listBlobs($container == '' ? '$root' : $container, $listOptions);
  1905. $blobs = $listBlobsResult->getBlobs();
  1906. $getBlobOptions = new GetBlobOptions();
  1907. $getBlobOptions->setSnapshot($res->getSnapshot());
  1908. $getBlobResult = $this->restProxy->getBlob($container, $blob, $getBlobOptions);
  1909. $this->verifyCreateBlobSnapshotWorker($res, $options, $blobs, $getBlobResult);
  1910. } catch (ServiceException $e) {
  1911. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  1912. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'bad timeout: deleteHttpStatusCode');
  1913. } else if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  1914. $this->assertEquals(TestResources::STATUS_PRECONDITION_FAILED, $e->getCode(), 'bad temporal access condition IF_UNMODIFIED_SINCE: deleteHttpStatusCode');
  1915. } else if (!BlobServiceFunctionalTestData::passETagAccessCondition($options->getAccessCondition())) {
  1916. $this->assertEquals(TestResources::STATUS_PRECONDITION_FAILED, $e->getCode(), 'bad etag access condition: deleteHttpStatusCode');
  1917. } else {
  1918. throw $e;
  1919. }
  1920. }
  1921. // Clean up.
  1922. $this->restProxy->deleteBlob($container, $blob);
  1923. }
  1924. private function verifyCreateBlobSnapshotWorker($res, $options, $blobs, $getBlobResult)
  1925. {
  1926. $now = new \DateTime();
  1927. $this->assertNotNull($res->getETag(), 'result etag');
  1928. $snapshotDate = new \DateTime($res->getSnapshot());
  1929. // Make sure the last modified date is within 10 seconds
  1930. $this->assertTrue(
  1931. BlobServiceFunctionalTestData::diffInTotalSeconds($snapshotDate, $now) < 10,
  1932. 'Last modified date (' . $snapshotDate->format(\DateTime::RFC1123) . ')'.
  1933. ' should be within 10 seconds of $now (' . $now->format(\DateTime::RFC1123) . ')');
  1934. // Make sure the last modified date is within 10 seconds
  1935. $this->assertTrue(
  1936. BlobServiceFunctionalTestData::diffInTotalSeconds($res->getLastModified(), $now) < 10,
  1937. 'Last modified date (' . $res->getLastModified()->format(\DateTime::RFC1123) . ')'.
  1938. ' should be within 10 seconds of $now (' . $now->format(\DateTime::RFC1123) . ')');
  1939. $this->assertEquals(3, count($blobs), 'Should end up with 3 $blobs with same name as main blob');
  1940. $this->assertNotNull($getBlobResult->getMetadata(), 'blob Metadata');
  1941. $this->assertEquals(count($options->getMetadata()), count($getBlobResult->getMetadata()), 'Metadata');
  1942. $retMetadata = $getBlobResult->getMetadata();
  1943. if (!is_null($options->getMetadata())) {
  1944. foreach($options->getMetadata() as $key => $value) {
  1945. $this->assertEquals($value, $retMetadata[$key], 'Metadata(' . $key . ')');
  1946. }
  1947. }
  1948. }
  1949. /**
  1950. * @covers WindowsAzure\Blob\BlobRestProxy::copyBlob
  1951. * @covers WindowsAzure\Blob\BlobRestProxy::createBlobSnapshot
  1952. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1953. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1954. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1955. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  1956. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1957. */
  1958. public function testCopyBlobNoOptions()
  1959. {
  1960. $sourceContainers = array(
  1961. BlobServiceFunctionalTestData::$testContainerNames[0],
  1962. '$root',
  1963. '');
  1964. $destContainers = array(
  1965. BlobServiceFunctionalTestData::$testContainerNames[1],
  1966. '$root',
  1967. '');
  1968. foreach($sourceContainers as $sourceContainer) {
  1969. foreach($destContainers as $destContainer) {
  1970. $this->copyBlobWorker(null, $sourceContainer, $destContainer);
  1971. }
  1972. }
  1973. }
  1974. /**
  1975. * @covers WindowsAzure\Blob\BlobRestProxy::copyBlob
  1976. * @covers WindowsAzure\Blob\BlobRestProxy::createBlobSnapshot
  1977. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1978. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1979. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1980. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  1981. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  1982. */
  1983. public function testCopyBlobAllOptions()
  1984. {
  1985. $sourceContainer = BlobServiceFunctionalTestData::$testContainerNames[0];
  1986. $destContainer = BlobServiceFunctionalTestData::$testContainerNames[1];
  1987. $interestingCopyBlobOptions = BlobServiceFunctionalTestData::getCopyBlobOptions();
  1988. foreach($interestingCopyBlobOptions as $options) {
  1989. $this->copyBlobWorker($options, $sourceContainer, $destContainer);
  1990. }
  1991. }
  1992. /**
  1993. * @covers WindowsAzure\Blob\BlobRestProxy::copyBlob
  1994. * @covers WindowsAzure\Blob\BlobRestProxy::createBlobSnapshot
  1995. * @covers WindowsAzure\Blob\BlobRestProxy::createPageBlob
  1996. * @covers WindowsAzure\Blob\BlobRestProxy::deleteBlob
  1997. * @covers WindowsAzure\Blob\BlobRestProxy::getBlob
  1998. * @covers WindowsAzure\Blob\BlobRestProxy::listBlobs
  1999. * @covers WindowsAzure\Blob\BlobRestProxy::setBlobMetadata
  2000. */
  2001. private function copyBlobWorker($options, $sourceContainer, $destContainer)
  2002. {
  2003. $sourceBlob = BlobServiceFunctionalTestData::getInterestingBlobName();
  2004. $destBlob = BlobServiceFunctionalTestData::getInterestingBlobName();
  2005. // Make sure there is something to test
  2006. $sourceDataSize = 512;
  2007. $this->restProxy->createPageBlob($sourceContainer, $sourceBlob, $sourceDataSize);
  2008. // TODO: Just get etag from createBlockBlob https://github->com/WindowsAzure/azure-sdk-for-java/issues/74
  2009. $destDataSize = 2048;
  2010. $this->restProxy->createPageBlob($destContainer, $destBlob, $destDataSize);
  2011. $destBlobInfo = $this->restProxy->getBlob($destContainer, $destBlob);
  2012. $this->restProxy->createBlobSnapshot($destContainer, $destBlob);
  2013. $metadata = BlobServiceFunctionalTestData::getNiceMetadata();
  2014. $this->restProxy->setBlobMetadata($sourceContainer, $sourceBlob, $metadata);
  2015. $snapshot = $this->restProxy->createBlobSnapshot($sourceContainer, $sourceBlob);
  2016. if (!is_null($options)) {
  2017. BlobServiceFunctionalTestData::fixETagAccessCondition($options->getSourceAccessCondition(), $snapshot->getETag());
  2018. BlobServiceFunctionalTestData::fixETagAccessCondition($options->getAccessCondition(), $destBlobInfo->getProperties()->getETag());
  2019. $options->setSourceSnapshot(is_null($options->getSourceSnapshot()) ? null : $snapshot->getSnapshot());
  2020. }
  2021. try {
  2022. if (is_null($options)) {
  2023. $this->restProxy->copyBlob($destContainer, $destBlob, $sourceContainer, $sourceBlob);
  2024. } else {
  2025. $this->restProxy->copyBlob($destContainer, $destBlob, $sourceContainer, $sourceBlob, $options);
  2026. }
  2027. if (is_null($options)) {
  2028. $options = new CopyBlobOptions();
  2029. }
  2030. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  2031. $this->assertTrue(false, 'Expect negative timeouts in $options to throw');
  2032. }
  2033. if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getSourceAccessCondition())) {
  2034. $this->assertTrue(false, 'Expect failing source temporal access condition should throw');
  2035. }
  2036. if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getSourceAccessCondition())) {
  2037. $this->assertTrue(false, 'Expect failing source etag access condition to throw');
  2038. }
  2039. if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  2040. $this->assertTrue(false, 'Expect failing dest temporal access condition should throw');
  2041. }
  2042. if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  2043. $this->assertTrue(false, 'Expect failing dest etag access condition to throw');
  2044. }
  2045. $listOptions = new ListBlobsOptions();
  2046. $listOptions->setIncludeSnapshots(true);
  2047. $listOptions->setPrefix($destBlob);
  2048. $listBlobsResult = $this->restProxy->listBlobs($destContainer == '' ? '$root' : $destContainer, $listOptions);
  2049. $blobs = $listBlobsResult->getBlobs();
  2050. $getBlobResult = $this->restProxy->getBlob($destContainer, $destBlob);
  2051. $this->verifyCopyBlobWorker($options, $blobs, $getBlobResult, $sourceDataSize, $metadata);
  2052. } catch (ServiceException $e) {
  2053. if (is_null($options)) {
  2054. $options = new CopyBlobOptions();
  2055. }
  2056. if (!is_null($options->getTimeout()) && $options->getTimeout() < 1) {
  2057. $this->assertEquals(500, $e->getCode(), 'bad timeout: deleteHttpStatusCode');
  2058. } else if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getSourceAccessCondition())) {
  2059. $this->assertEquals(412, $e->getCode(), 'bad source temporal access condition IF_UNMODIFIED_SINCE: deleteHttpStatusCode');
  2060. } else if (!BlobServiceFunctionalTestData::passETagAccessCondition($options->getSourceAccessCondition())) {
  2061. $this->assertEquals(412, $e->getCode(), 'bad source etag access condition: deleteHttpStatusCode');
  2062. } else if (!BlobServiceFunctionalTestData::passTemporalAccessCondition($options->getAccessCondition())) {
  2063. $this->assertEquals(412, $e->getCode(), 'bad dest temporal access condition IF_UNMODIFIED_SINCE: deleteHttpStatusCode');
  2064. } else if (!BlobServiceFunctionalTestData::passETagAccessCondition($options->getAccessCondition())) {
  2065. $this->assertEquals(412, $e->getCode(), 'bad dest etag access condition: deleteHttpStatusCode');
  2066. } else {
  2067. throw $e;
  2068. }
  2069. }
  2070. // Clean up.
  2071. $this->restProxy->deleteBlob($sourceContainer, $sourceBlob);
  2072. $this->restProxy->deleteBlob($destContainer, $destBlob);
  2073. }
  2074. private function verifyCopyBlobWorker($options, $blobs, $getBlobResult, $sourceDataSize, $metadata)
  2075. {
  2076. $this->assertEquals(2, count($blobs), 'Should end up with 2 blob with same name as dest blob, snapshot and copied blob');
  2077. $this->assertEquals($sourceDataSize, $getBlobResult->getProperties()->getContentLength(), 'Dest length should be the same as the source length');
  2078. $this->assertNotNull($getBlobResult->getMetadata(), 'blob Metadata');
  2079. $expectedMetadata = (count($options->getMetadata()) == 0 ? $metadata : $options->getMetadata());
  2080. $resMetadata = $getBlobResult->getMetadata();
  2081. $this->assertEquals(count($expectedMetadata), count($resMetadata), 'Metadata');
  2082. foreach($expectedMetadata as $key => $value) {
  2083. $this->assertEquals($value, $resMetadata[strtolower($key)], 'Metadata(' . $key . ')');
  2084. }
  2085. // Make sure the last modified date is within 10 seconds
  2086. $now = new \DateTime();
  2087. $this->assertTrue(
  2088. BlobServiceFunctionalTestData::diffInTotalSeconds($getBlobResult->getProperties()->getLastModified(), $now) < 10,
  2089. 'Last modified date (' . $getBlobResult->getProperties()->getLastModified()->format(\DateTime::RFC1123) . ')'.
  2090. ' should be within 10 seconds of $now (' . $now->format(\DateTime::RFC1123) . ')');
  2091. }
  2092. // createBlockBlob
  2093. // createBlobBlock
  2094. // commitBlobBlocks
  2095. // listBlobBlocks
  2096. // createPageBlob
  2097. // createBlobPages
  2098. // clearBlobPages
  2099. // listBlobRegions
  2100. // acquireLease
  2101. // renewLease
  2102. // releaseLease
  2103. // breakLease
  2104. }