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

/tests/functional/WindowsAzure/Table/TableServiceFunctionalTest.php

http://github.com/WindowsAzure/azure-sdk-for-php
PHP | 1577 lines | 1049 code | 168 blank | 360 comment | 138 complexity | bead9d0f87f1db91a1f942c366259422 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  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\Table
  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\Table;
  24. use Tests\Functional\WindowsAzure\Table\FakeTableInfoEntry;
  25. use Tests\Functional\WindowsAzure\Table\MutatePivot;
  26. use WindowsAzure\Common\Internal\Utilities;
  27. use WindowsAzure\Common\ServiceException;
  28. use WindowsAzure\Common\Configuration;
  29. use WindowsAzure\Common\Models\Logging;
  30. use WindowsAzure\Common\Models\Metrics;
  31. use WindowsAzure\Common\Models\RetentionPolicy;
  32. use WindowsAzure\Common\Models\ServiceProperties;
  33. use WindowsAzure\Table\Models\BatchError;
  34. use WindowsAzure\Table\Models\BatchOperations;
  35. use WindowsAzure\Table\Models\BatchResult;
  36. use WindowsAzure\Table\Models\DeleteEntityOptions;
  37. use WindowsAzure\Table\Models\EdmType;
  38. use WindowsAzure\Table\Models\Entity;
  39. use WindowsAzure\Table\Models\GetEntityResult;
  40. use WindowsAzure\Table\Models\GetServicePropertiesResult;
  41. use WindowsAzure\Table\Models\GetTableResult;
  42. use WindowsAzure\Table\Models\InsertEntityResult;
  43. use WindowsAzure\Table\Models\Property;
  44. use WindowsAzure\Table\Models\Query;
  45. use WindowsAzure\Table\Models\QueryEntitiesOptions;
  46. use WindowsAzure\Table\Models\QueryEntitiesResult;
  47. use WindowsAzure\Table\Models\QueryTablesOptions;
  48. use WindowsAzure\Table\Models\QueryTablesResult;
  49. use WindowsAzure\Table\Models\TableServiceOptions;
  50. use WindowsAzure\Table\Models\UpdateEntityResult;
  51. use WindowsAzure\Table\Models\Filters\Filter;
  52. class OpType {
  53. const deleteEntity = 'deleteEntity';
  54. const insertEntity = 'insertEntity';
  55. const insertOrMergeEntity = 'insertOrMergeEntity';
  56. const insertOrReplaceEntity = 'insertOrReplaceEntity';
  57. const mergeEntity = 'mergeEntity';
  58. const updateEntity = 'updateEntity';
  59. public static function values() {
  60. return array('deleteEntity', 'insertEntity', 'insertOrMergeEntity', 'insertOrReplaceEntity', 'mergeEntity', 'updateEntity');
  61. }
  62. }
  63. class ConcurType {
  64. const NoKeyMatch = 'NoKeyMatch';
  65. const KeyMatchNoEtag = 'KeyMatchNoEtag';
  66. const KeyMatchEtagMismatch = 'KeyMatchEtagMismatch';
  67. const KeyMatchEtagMatch = 'KeyMatchEtagMatch';
  68. public static function values() {
  69. return array('NoKeyMatch', 'KeyMatchNoEtag', 'KeyMatchEtagMismatch', 'KeyMatchEtagMatch');
  70. }
  71. }
  72. class BatchWorkerConfig {
  73. public $opType;
  74. public $concurType;
  75. public $mutatePivot;
  76. public $ent;
  77. public $options;
  78. }
  79. class TableServiceFunctionalTest extends FunctionalTestBase {
  80. /**
  81. * @covers WindowsAzure\Table\TableRestProxy::getServiceProperties
  82. * @covers WindowsAzure\Table\TableRestProxy::setServiceProperties
  83. */
  84. public function testGetServicePropertiesNoOptions() {
  85. $serviceProperties = TableServiceFunctionalTestData::getDefaultServiceProperties();
  86. $shouldReturn = false;
  87. try {
  88. $this->restProxy->setServiceProperties($serviceProperties);
  89. $this->assertFalse(Configuration::isEmulated(), 'Should succeed when not running in emulator');
  90. } catch (ServiceException $e) {
  91. // Expect failure in emulator, as v1.6 doesn't support this method
  92. if (Configuration::isEmulated()) {
  93. $this->assertEquals(400, $e->getCode(), 'getCode');
  94. $shouldReturn = true;
  95. } else {
  96. throw $e;
  97. }
  98. }
  99. if($shouldReturn) {
  100. return;
  101. }
  102. $this->getServicePropertiesWorker(null);
  103. }
  104. /**
  105. * @covers WindowsAzure\Table\TableRestProxy::getServiceProperties
  106. * @covers WindowsAzure\Table\TableRestProxy::setServiceProperties
  107. */
  108. public function testGetServiceProperties() {
  109. $serviceProperties = TableServiceFunctionalTestData::getDefaultServiceProperties();
  110. try {
  111. $this->restProxy->setServiceProperties($serviceProperties);
  112. $this->assertFalse(Configuration::isEmulated(), 'Should succeed when not running in emulator');
  113. } catch (ServiceException $e) {
  114. // Expect failure in emulator, as v1.6 doesn't support this method
  115. if (Configuration::isEmulated()) {
  116. $this->assertEquals(400, $e->getCode(), 'getCode');
  117. } else {
  118. throw $e;
  119. }
  120. }
  121. }
  122. /**
  123. * @covers WindowsAzure\Table\TableRestProxy::getServiceProperties
  124. */
  125. private function getServicePropertiesWorker($options) {
  126. self::println( 'Trying $options: ' . self::tmptostring($options));
  127. $effOptions = (is_null($options) ? new TableServiceOptions() : $options);
  128. try {
  129. $ret = (is_null($options) ? $this->restProxy->getServiceProperties() : $this->restProxy->getServiceProperties($effOptions));
  130. $this->assertFalse(Configuration::isEmulated(), 'Should succeed when not running in emulator');
  131. $this->verifyServicePropertiesWorker($ret, null);
  132. }
  133. catch (ServiceException $e) {
  134. if (Configuration::isEmulated()) {
  135. // Expect failure in emulator, as v1.6 doesn't support this method
  136. $this->assertEquals(400, $e->getCode(), 'getCode');
  137. } else {
  138. $this->assertEquals(500, $e->getCode(), 'getCode');
  139. }
  140. }
  141. }
  142. private function verifyServicePropertiesWorker($ret, $serviceProperties) {
  143. if (is_null($serviceProperties)) {
  144. $serviceProperties = TableServiceFunctionalTestData::getDefaultServiceProperties();
  145. }
  146. $sp = $ret->getValue();
  147. $this->assertNotNull($sp, 'getValue should be non-null');
  148. $l = $sp->getLogging();
  149. $this->assertNotNull($l, 'getValue()->getLogging() should be non-null');
  150. $this->assertEquals($serviceProperties->getLogging()->getVersion(), $l->getVersion(), 'getValue()->getLogging()->getVersion');
  151. $this->assertEquals($serviceProperties->getLogging()->getDelete(), $l->getDelete(), 'getValue()->getLogging()->getDelete');
  152. $this->assertEquals($serviceProperties->getLogging()->getRead(), $l->getRead(), 'getValue()->getLogging()->getRead');
  153. $this->assertEquals($serviceProperties->getLogging()->getWrite(), $l->getWrite(), 'getValue()->getLogging()->getWrite');
  154. $r = $l->getRetentionPolicy();
  155. $this->assertNotNull($r, 'getValue()->getLogging()->getRetentionPolicy should be non-null');
  156. $this->assertEquals($serviceProperties->getLogging()->getRetentionPolicy()->getDays(), $r->getDays(), 'getValue()->getLogging()->getRetentionPolicy()->getDays');
  157. $m = $sp->getMetrics();
  158. $this->assertNotNull($m, 'getValue()->getMetrics() should be non-null');
  159. $this->assertEquals($serviceProperties->getMetrics()->getVersion(), $m->getVersion(), 'getValue()->getMetrics()->getVersion');
  160. $this->assertEquals($serviceProperties->getMetrics()->getEnabled(), $m->getEnabled(), 'getValue()->getMetrics()->getEnabled');
  161. $this->assertEquals($serviceProperties->getMetrics()->getIncludeAPIs(), $m->getIncludeAPIs(), 'getValue()->getMetrics()->getIncludeAPIs');
  162. $r = $m->getRetentionPolicy();
  163. $this->assertNotNull($r, 'getValue()->getMetrics()->getRetentionPolicy should be non-null');
  164. $this->assertEquals($serviceProperties->getMetrics()->getRetentionPolicy()->getDays(), $r->getDays(), 'getValue()->getMetrics()->getRetentionPolicy()->getDays');
  165. }
  166. /**
  167. * @covers WindowsAzure\Table\TableRestProxy::getServiceProperties
  168. * @covers WindowsAzure\Table\TableRestProxy::setServiceProperties
  169. */
  170. public function testSetServicePropertiesNoOptions() {
  171. $serviceProperties = TableServiceFunctionalTestData::getDefaultServiceProperties();
  172. $this->setServicePropertiesWorker($serviceProperties, null);
  173. }
  174. /**
  175. * @covers WindowsAzure\Table\TableRestProxy::getServiceProperties
  176. * @covers WindowsAzure\Table\TableRestProxy::setServiceProperties
  177. */
  178. public function testSetServiceProperties() {
  179. $interestingServiceProperties = TableServiceFunctionalTestData::getInterestingServiceProperties();
  180. foreach($interestingServiceProperties as $serviceProperties) {
  181. $options = new TableServiceOptions();
  182. $this->setServicePropertiesWorker($serviceProperties, $options);
  183. }
  184. if (!Configuration::isEmulated()) {
  185. $serviceProperties = TableServiceFunctionalTestData::getDefaultServiceProperties();
  186. $this->restProxy->setServiceProperties($serviceProperties);
  187. }
  188. }
  189. /**
  190. * @covers WindowsAzure\Table\TableRestProxy::getServiceProperties
  191. * @covers WindowsAzure\Table\TableRestProxy::setServiceProperties
  192. */
  193. private function setServicePropertiesWorker($serviceProperties, $options) {
  194. try {
  195. if (is_null($options)) {
  196. $this->restProxy->setServiceProperties($serviceProperties);
  197. } else {
  198. $this->restProxy->setServiceProperties($serviceProperties, $options);
  199. }
  200. $this->assertFalse(Configuration::isEmulated(), 'Should succeed when not running in emulator');
  201. $ret = (is_null($options) ? $this->restProxy->getServiceProperties() : $this->restProxy->getServiceProperties($options));
  202. $this->verifyServicePropertiesWorker($ret, $serviceProperties);
  203. } catch (ServiceException $e) {
  204. if (Configuration::isEmulated()) {
  205. $this->assertEquals(400, $e->getCode(), 'getCode');
  206. } else {
  207. throw $e;
  208. }
  209. }
  210. }
  211. /**
  212. * @covers WindowsAzure\Table\TableRestProxy::queryTables
  213. */
  214. public function testQueryTablesNoOptions() {
  215. $this->queryTablesWorker(null);
  216. }
  217. /**
  218. * @covers WindowsAzure\Table\TableRestProxy::queryTables
  219. */
  220. public function testQueryTables() {
  221. $interestingqueryTablesOptions = TableServiceFunctionalTestData::getInterestingQueryTablesOptions();
  222. foreach($interestingqueryTablesOptions as $options) {
  223. $this->queryTablesWorker($options);
  224. }
  225. }
  226. /**
  227. * @covers WindowsAzure\Table\TableRestProxy::queryTables
  228. */
  229. private function queryTablesWorker($options) {
  230. try {
  231. $ret = (is_null($options) ? $this->restProxy->queryTables() : $this->restProxy->queryTables($options));
  232. if (is_null($options)) {
  233. $options = new QueryTablesOptions();
  234. }
  235. if ((!is_null($options->getTop()) && $options->getTop() <= 0)) {
  236. if (Configuration::isEmulated()) {
  237. $this->assertEquals(0, count($ret->getTables()), "should be no tables");
  238. } else {
  239. $this->fail('Expect non-positive Top in $options to throw');
  240. }
  241. }
  242. $this->verifyqueryTablesWorker($ret, $options);
  243. }
  244. catch (ServiceException $e) {
  245. if ((!is_null($options->getTop()) && $options->getTop() <= 0) && !Configuration::isEmulated()) {
  246. $this->assertEquals(400, $e->getCode(), 'getCode');
  247. }
  248. else {
  249. throw $e;
  250. }
  251. }
  252. }
  253. private function verifyqueryTablesWorker($ret, $options) {
  254. $this->assertNotNull($ret->getTables(), 'getTables');
  255. $effectivePrefix = $options->getPrefix();
  256. if (is_null($effectivePrefix)) {
  257. $effectivePrefix = '';
  258. }
  259. $expectedFilter = $options->getFilter();
  260. if (TableServiceFunctionalTestUtils::isEqNotInTopLevel($expectedFilter)) {
  261. // This seems wrong, but appears to be a bug in the $service itself.
  262. // So working around the limitation.
  263. $expectedFilter = TableServiceFunctionalTestUtils::cloneRemoveEqNotInTopLevel($expectedFilter);
  264. }
  265. $expectedData = array();
  266. foreach(TableServiceFunctionalTestData::$TEST_TABLE_NAMES as $s) {
  267. if (substr($s, 0, strlen($effectivePrefix)) == $effectivePrefix) {
  268. $fte = new FakeTableInfoEntry();
  269. $fte->TableName = $s;
  270. array_push($expectedData, $fte);
  271. }
  272. }
  273. if (!is_null($options->getNextTableName())) {
  274. $tmpExpectedData = array();
  275. $foundNext = false;
  276. foreach($expectedData as $s) {
  277. if ($s == $options->getNextTableName()) {
  278. $foundNext = true;
  279. }
  280. if (!$foundNext) {
  281. continue;
  282. }
  283. if (substr($s, 0, strlen($effectivePrefix)) == $effectivePrefix) {
  284. $fte = new FakeTableInfoEntry();
  285. $fte->TableName = $s;
  286. array_push($expectedData, $fte);
  287. }
  288. }
  289. $expectedData = $tmpExpectedData;
  290. }
  291. $expectedData = TableServiceFunctionalTestUtils::filterList($expectedFilter, $expectedData);
  292. $effectiveTop = (is_null($options->getTop()) ? 100000 : $options->getTop());
  293. $expectedCount = min($effectiveTop, count($expectedData));
  294. $tables = $ret->getTables();
  295. for ($i = 0; $i < $expectedCount; $i++) {
  296. $expected = $expectedData[$i]->TableName;
  297. // Assume there are other tables. Make sure the expected ones are there.
  298. $foundNext = false;
  299. foreach($tables as $actual) {
  300. if ($expected == $actual) {
  301. $foundNext = true;
  302. break;
  303. }
  304. }
  305. $this->assertTrue($foundNext, $expected . ' should be in getTables');
  306. }
  307. }
  308. /**
  309. * @covers WindowsAzure\Table\TableRestProxy::createTable
  310. * @covers WindowsAzure\Table\TableRestProxy::deleteTable
  311. * @covers WindowsAzure\Table\TableRestProxy::queryTables
  312. */
  313. public function testCreateTableNoOptions() {
  314. $this->createTableWorker(null);
  315. }
  316. /**
  317. * @covers WindowsAzure\Table\TableRestProxy::createTable
  318. * @covers WindowsAzure\Table\TableRestProxy::deleteTable
  319. * @covers WindowsAzure\Table\TableRestProxy::queryTables
  320. */
  321. public function testCreateTable() {
  322. $options = new TableServiceOptions();
  323. $this->createTableWorker($options);
  324. }
  325. /**
  326. * @covers WindowsAzure\Table\TableRestProxy::createTable
  327. * @covers WindowsAzure\Table\TableRestProxy::deleteTable
  328. * @covers WindowsAzure\Table\TableRestProxy::queryTables
  329. */
  330. private function createTableWorker($options) {
  331. $table = TableServiceFunctionalTestData::getInterestingTableName();
  332. $created = false;
  333. // Make sure that the list of all applicable Tables is correctly updated.
  334. $qto = new QueryTablesOptions();
  335. if (!Configuration::isEmulated()) {
  336. // The emulator has problems with some queries,
  337. // but full Azure allow this to be more efficient:
  338. $qto->setPrefix(TableServiceFunctionalTestData::$testUniqueId);
  339. }
  340. $qsStart = $this->restProxy->queryTables($qto);
  341. if (is_null($options)) {
  342. $this->restProxy->createTable($table);
  343. }
  344. else {
  345. $this->restProxy->createTable($table, $options);
  346. }
  347. $created = true;
  348. if (is_null($options)) {
  349. $options = new TableServiceOptions();
  350. }
  351. // Make sure that the list of all applicable Tables is correctly updated.
  352. $qs = $this->restProxy->queryTables($qto);
  353. if ($created) {
  354. $this->restProxy->deleteTable($table);
  355. }
  356. $this->assertEquals(count($qsStart->getTables()) + 1, count($qs->getTables()), 'After adding one, with Prefix=(\'' . TableServiceFunctionalTestData::$testUniqueId . '\'), then count(Tables)');
  357. }
  358. /**
  359. * @covers WindowsAzure\Table\TableRestProxy::createTable
  360. * @covers WindowsAzure\Table\TableRestProxy::deleteTable
  361. * @covers WindowsAzure\Table\TableRestProxy::queryTables
  362. */
  363. public function testDeleteTableNoOptions() {
  364. $this->deleteTableWorker(null);
  365. }
  366. /**
  367. * @covers WindowsAzure\Table\TableRestProxy::createTable
  368. * @covers WindowsAzure\Table\TableRestProxy::deleteTable
  369. * @covers WindowsAzure\Table\TableRestProxy::queryTables
  370. */
  371. public function testDeleteTable() {
  372. $options = new TableServiceOptions();
  373. $this->deleteTableWorker($options);
  374. }
  375. /**
  376. * @covers WindowsAzure\Table\TableRestProxy::createTable
  377. * @covers WindowsAzure\Table\TableRestProxy::deleteTable
  378. * @covers WindowsAzure\Table\TableRestProxy::queryTables
  379. */
  380. private function deleteTableWorker($options) {
  381. $Table = TableServiceFunctionalTestData::getInterestingTableName();
  382. // Make sure that the list of all applicable Tables is correctly updated.
  383. $qto = new QueryTablesOptions();
  384. if (!Configuration::isEmulated()) {
  385. // The emulator has problems with some queries,
  386. // but full Azure allow this to be more efficient:
  387. $qto->setPrefix(TableServiceFunctionalTestData::$testUniqueId);
  388. }
  389. $qsStart = $this->restProxy->queryTables($qto);
  390. // Make sure there is something to delete.
  391. $this->restProxy->createTable($Table);
  392. // Make sure that the list of all applicable Tables is correctly updated.
  393. $qs = $this->restProxy->queryTables($qto);
  394. $this->assertEquals(count($qsStart->getTables()) + 1, count($qs->getTables()), 'After adding one, with Prefix=(\'' . TableServiceFunctionalTestData::$testUniqueId . '\'), then count Tables');
  395. $deleted = false;
  396. if (is_null($options)) {
  397. $this->restProxy->deleteTable($Table);
  398. }
  399. else {
  400. $this->restProxy->deleteTable($Table, $options);
  401. }
  402. $deleted = true;
  403. if (is_null($options)) {
  404. $options = new TableServiceOptions();
  405. }
  406. // Make sure that the list of all applicable Tables is correctly updated.
  407. $qs = $this->restProxy->queryTables($qto);
  408. if (!$deleted) {
  409. $this->println('Test didn\'t delete the $Table, so try again more simply');
  410. // Try again. If it doesn't work, not much else to try.
  411. $this->restProxy->deleteTable($Table);
  412. }
  413. $this->assertEquals(count($qsStart->getTables()), count($qs->getTables()),'After adding then deleting one, with Prefix=(\'' . TableServiceFunctionalTestData::$testUniqueId . '\'), then count(Tables)');
  414. }
  415. /**
  416. * @covers WindowsAzure\Table\TableRestProxy::createTable
  417. * @covers WindowsAzure\Table\TableRestProxy::deleteTable
  418. * @covers WindowsAzure\Table\TableRestProxy::getTable
  419. */
  420. public function testGetTableNoOptions() {
  421. $this->getTableWorker(null);
  422. }
  423. /**
  424. * @covers WindowsAzure\Table\TableRestProxy::createTable
  425. * @covers WindowsAzure\Table\TableRestProxy::deleteTable
  426. * @covers WindowsAzure\Table\TableRestProxy::getTable
  427. */
  428. public function testGetTable() {
  429. $options = new TableServiceOptions();
  430. $this->getTableWorker($options);
  431. }
  432. /**
  433. * @covers WindowsAzure\Table\TableRestProxy::createTable
  434. * @covers WindowsAzure\Table\TableRestProxy::deleteTable
  435. * @covers WindowsAzure\Table\TableRestProxy::getTable
  436. */
  437. private function getTableWorker($options) {
  438. $table = TableServiceFunctionalTestData::getInterestingTableName();
  439. $created = false;
  440. $this->restProxy->createTable($table);
  441. $created = true;
  442. $ret = (is_null($options) ? $this->restProxy->getTable($table) : $this->restProxy->getTable($table, $options));
  443. if (is_null($options)) {
  444. $options = new TableServiceOptions();
  445. }
  446. $this->verifygetTableWorker($ret, $table);
  447. if ($created) {
  448. $this->restProxy->deleteTable($table);
  449. }
  450. }
  451. private function verifygetTableWorker($ret, $tableName) {
  452. $this->assertNotNull($ret, 'getTableEntry');
  453. $this->assertEquals($tableName, $ret->getName(), 'getTableEntry->Name');
  454. }
  455. /**
  456. * @covers WindowsAzure\Table\TableRestProxy::getEntity
  457. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  458. */
  459. public function testGetEntity() {
  460. $ents = TableServiceFunctionalTestData::getInterestingEntities();
  461. foreach($ents as $ent) {
  462. $options = new TableServiceOptions();
  463. $this->getEntityWorker($ent, true, $options);
  464. }
  465. }
  466. /**
  467. * @covers WindowsAzure\Table\TableRestProxy::getEntity
  468. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  469. */
  470. private function getEntityWorker($ent, $isGood, $options) {
  471. $table = $this->getCleanTable();
  472. try {
  473. // Upload the entity.
  474. $this->restProxy->insertEntity($table, $ent);
  475. $qer = (is_null($options) ? $this->restProxy->getEntity($table, $ent->getPartitionKey(), $ent->getRowKey()) : $this->restProxy->getEntity($table, $ent->getPartitionKey(), $ent->getRowKey(), $options));
  476. if (is_null($options)) {
  477. $options = new TableServiceOptions();
  478. }
  479. $this->assertNotNull($qer->getEntity(), 'getEntity()');
  480. $this->verifygetEntityWorker($ent, $qer->getEntity());
  481. }
  482. catch (ServiceException $e) {
  483. if (!$isGood) {
  484. $this->assertEquals(400, $e->getCode(), 'getCode');
  485. }
  486. else if (is_null($ent->getPartitionKey()) || is_null($ent->getRowKey())) {
  487. $this->assertEquals(400, $e->getCode(), 'getCode');
  488. }
  489. else {
  490. throw $e;
  491. }
  492. }
  493. $this->clearTable($table);
  494. }
  495. private function verifygetEntityWorker($ent, $entReturned) {
  496. $expectedProps = array();
  497. foreach($ent->getProperties() as $pname => $actualProp) {
  498. if (is_null($actualProp) || !is_null($actualProp->getValue())) {
  499. $cloneProp = null;
  500. if (!is_null($actualProp)) {
  501. $cloneProp = new Property();
  502. $cloneProp->setEdmType($actualProp->getEdmType());
  503. $cloneProp->setValue($actualProp->getValue());
  504. }
  505. $expectedProps[$pname] = $cloneProp;
  506. }
  507. }
  508. // Compare the entities to make sure they match.
  509. $this->assertEquals($ent->getPartitionKey(), $entReturned->getPartitionKey(), 'getPartitionKey');
  510. $this->assertEquals($ent->getRowKey(), $entReturned->getRowKey(), 'getRowKey');
  511. $this->assertNotNull($entReturned->getEtag(), 'getEtag');
  512. if (!is_null($ent->getEtag())) {
  513. $this->assertEquals($ent->getEtag(), $entReturned->getEtag(), 'getEtag');
  514. }
  515. $this->assertNotNull($entReturned->getTimestamp(), 'getTimestamp');
  516. if (is_null($ent->getTimestamp())) {
  517. // This property will come back, so need to account for it.
  518. $expectedProps['Timestamp'] = null;
  519. }
  520. else {
  521. $this->assertEquals($ent->getTimestamp(), $entReturned->getTimestamp(), 'getTimestamp');
  522. }
  523. $this->assertNotNull($ent->getProperties(), 'getProperties');
  524. $nullCount = 0;
  525. foreach($entReturned->getProperties() as $pname => $actualProp) {
  526. if (is_null($actualProp->getValue())) {
  527. $nullCount++;
  528. }
  529. }
  530. // Need to skip null values from the count.
  531. $this->assertEquals(count($expectedProps) + $nullCount, count($entReturned->getProperties()), 'getProperties()');
  532. foreach($entReturned->getProperties() as $pname => $actualProp) {
  533. $this->println($actualProp->getEdmType() . ':' . (is_null($actualProp->getValue()) ? 'NULL' :
  534. ($actualProp->getValue() instanceof \DateTime ? "date" : $actualProp->getValue())));
  535. }
  536. foreach($entReturned->getProperties() as $pname => $actualProp) {
  537. $expectedProp = Utilities::tryGetValue($expectedProps, $pname, null);
  538. $this->assertNotNull($actualProp, 'getProperties[\'' . $pname . '\']');
  539. if (!is_null($expectedProp)) {
  540. $this->compareProperties($pname, $actualProp, $expectedProp);
  541. }
  542. $this->assertEquals($entReturned->getProperty($pname), $actualProp, 'getProperty(\'' . $pname . '\')');
  543. $this->assertEquals($entReturned->getPropertyValue($pname), $actualProp->getValue(), 'getPropertyValue(\'' . $pname . '\')');
  544. }
  545. }
  546. /**
  547. * @covers WindowsAzure\Table\TableRestProxy::deleteEntity
  548. * @covers WindowsAzure\Table\TableRestProxy::getEntity
  549. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  550. */
  551. public function testDeleteEntity() {
  552. $ents = TableServiceFunctionalTestData::getSimpleEntities(3);
  553. for ($useEtag = 0; $useEtag <= 2; $useEtag++) {
  554. foreach($ents as $ent) {
  555. $options = new DeleteEntityOptions();
  556. $this->deleteEntityWorker($ent, $useEtag, $options);
  557. }
  558. }
  559. }
  560. /**
  561. * @covers WindowsAzure\Table\TableRestProxy::deleteEntity
  562. * @covers WindowsAzure\Table\TableRestProxy::getEntity
  563. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  564. */
  565. private function deleteEntityWorker($ent, $useEtag, $options) {
  566. $table = $this->getCleanTable();
  567. try {
  568. // Upload the entity.
  569. $ier = $this->restProxy->insertEntity($table, $ent);
  570. if ($useEtag == 1) {
  571. $options->setEtag($ier->getEntity()->getEtag());
  572. }
  573. else if ($useEtag == 2) {
  574. $options->setEtag('W/"datetime\'2012-03-05T21%3A46%3A25->5385467Z\'"');
  575. }
  576. $this->restProxy->deleteEntity($table, $ent->getPartitionKey(), $ent->getRowKey(), $options);
  577. if ($useEtag == 2) {
  578. $this->fail('Expect bad etag throws');
  579. }
  580. // Check that the entity really is gone
  581. $gotError = false;
  582. try {
  583. $this->restProxy->getEntity($table, $ent->getPartitionKey(), $ent->getRowKey());
  584. }
  585. catch (ServiceException $e2) {
  586. $gotError = ($e2->getCode() == 404);
  587. }
  588. $this->assertTrue($gotError, 'Expect error when entity is deleted');
  589. }
  590. catch (ServiceException $e) {
  591. if ($useEtag == 2) {
  592. $this->assertEquals(412, $e->getCode(), 'getCode');
  593. }
  594. else {
  595. throw $e;
  596. }
  597. }
  598. $this->clearTable($table);
  599. }
  600. /**
  601. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  602. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  603. */
  604. public function testInsertEntity() {
  605. $ents = TableServiceFunctionalTestData::getInterestingEntities();
  606. foreach($ents as $ent) {
  607. $options = new TableServiceOptions();
  608. $this->insertEntityWorker($ent, true, $options);
  609. }
  610. }
  611. /**
  612. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  613. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  614. */
  615. public function testInsertBadEntity() {
  616. $ents = TableServiceFunctionalTestData::getInterestingBadEntities();
  617. foreach($ents as $ent) {
  618. $options = new TableServiceOptions();
  619. try {
  620. $this->insertEntityWorker($ent, true, $options);
  621. $this->fail('this call should fail');
  622. } catch (\InvalidArgumentException $e) {
  623. $this->assertEquals(0, $e->getCode(), 'getCode');
  624. $this->assertTrue(true, 'got expected exception');
  625. }
  626. }
  627. }
  628. /**
  629. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  630. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  631. */
  632. public function testInsertEntityBoolean() {
  633. foreach(TableServiceFunctionalTestData::getInterestingGoodBooleans() as $o) {
  634. $ent = new Entity();
  635. $ent->setPartitionKey(TableServiceFunctionalTestData::getNewKey());
  636. $ent->setRowKey(TableServiceFunctionalTestData::getNewKey());
  637. $ent->addProperty('BOOLEAN', EdmType::BOOLEAN, $o);
  638. $this->insertEntityWorker($ent, true, null, $o);
  639. }
  640. }
  641. /**
  642. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  643. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  644. */
  645. public function testInsertEntityBooleanNegative() {
  646. foreach(TableServiceFunctionalTestData::getInterestingBadBooleans() as $o) {
  647. $ent = new Entity();
  648. $ent->setPartitionKey(TableServiceFunctionalTestData::getNewKey());
  649. $ent->setRowKey(TableServiceFunctionalTestData::getNewKey());
  650. try {
  651. $ent->addProperty('BOOLEAN', EdmType::BOOLEAN, $o);
  652. $this->fail('Should get an exception when trying to parse this value');
  653. $this->insertEntityWorker($ent, false, null, $o);
  654. } catch (\Exception $e) {
  655. $this->assertEquals(0, $e->getCode(), 'getCode');
  656. $this->assertTrue(true, 'got expected exception');
  657. }
  658. }
  659. }
  660. /**
  661. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  662. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  663. */
  664. public function testInsertEntityDate() {
  665. foreach(TableServiceFunctionalTestData::getInterestingGoodDates() as $o) {
  666. $ent = new Entity();
  667. $ent->setPartitionKey(TableServiceFunctionalTestData::getNewKey());
  668. $ent->setRowKey(TableServiceFunctionalTestData::getNewKey());
  669. $ent->addProperty('DATETIME', EdmType::DATETIME, $o);
  670. $this->insertEntityWorker($ent, true, null, $o);
  671. }
  672. }
  673. /**
  674. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  675. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  676. */
  677. public function testInsertEntityDateNegative() {
  678. foreach(TableServiceFunctionalTestData::getInterestingBadDates() as $o) {
  679. $ent = new Entity();
  680. $ent->setPartitionKey(TableServiceFunctionalTestData::getNewKey());
  681. $ent->setRowKey(TableServiceFunctionalTestData::getNewKey());
  682. try {
  683. $ent->addProperty('DATETIME', EdmType::DATETIME, $o);
  684. $this->fail('Should get an exception when trying to parse this value');
  685. $this->insertEntityWorker($ent, false, null, $o);
  686. } catch (\Exception $e) {
  687. $this->assertEquals(0, $e->getCode(), 'getCode');
  688. $this->assertTrue(true, 'got expected exception');
  689. }
  690. }
  691. }
  692. /**
  693. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  694. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  695. */
  696. public function testInsertEntityDouble() {
  697. foreach(TableServiceFunctionalTestData::getInterestingGoodDoubles() as $o) {
  698. $ent = new Entity();
  699. $ent->setPartitionKey(TableServiceFunctionalTestData::getNewKey());
  700. $ent->setRowKey(TableServiceFunctionalTestData::getNewKey());
  701. $ent->addProperty('DOUBLE', EdmType::DOUBLE, $o);
  702. $this->insertEntityWorker($ent, true, null, $o);
  703. }
  704. }
  705. /**
  706. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  707. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  708. */
  709. public function testInsertEntityDoubleNegative() {
  710. foreach(TableServiceFunctionalTestData::getInterestingBadDoubles() as $o) {
  711. $ent = new Entity();
  712. $ent->setPartitionKey(TableServiceFunctionalTestData::getNewKey());
  713. $ent->setRowKey(TableServiceFunctionalTestData::getNewKey());
  714. try {
  715. $ent->addProperty('DOUBLE', EdmType::DOUBLE, $o);
  716. $this->fail('Should get an exception when trying to parse this value');
  717. $this->insertEntityWorker($ent, false, null, $o);
  718. } catch (\Exception $e) {
  719. $this->assertEquals(0, $e->getCode(), 'getCode');
  720. $this->assertTrue(true, 'got expected exception');
  721. }
  722. }
  723. }
  724. /**
  725. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  726. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  727. */
  728. public function testInsertEntityGuid() {
  729. foreach(TableServiceFunctionalTestData::getInterestingGoodGuids() as $o) {
  730. $ent = new Entity();
  731. $ent->setPartitionKey(TableServiceFunctionalTestData::getNewKey());
  732. $ent->setRowKey(TableServiceFunctionalTestData::getNewKey());
  733. $ent->addProperty('GUID', EdmType::GUID, $o);
  734. $this->insertEntityWorker($ent, true, null, $o);
  735. }
  736. }
  737. /**
  738. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  739. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  740. */
  741. public function testInsertEntityGuidNegative() {
  742. foreach(TableServiceFunctionalTestData::getInterestingBadGuids() as $o) {
  743. $ent = new Entity();
  744. $ent->setPartitionKey(TableServiceFunctionalTestData::getNewKey());
  745. $ent->setRowKey(TableServiceFunctionalTestData::getNewKey());
  746. try {
  747. $ent->addProperty('GUID', EdmType::GUID, $o);
  748. $this->fail('Should get an exception when trying to parse this value');
  749. $this->insertEntityWorker($ent, false, null, $o);
  750. } catch (\Exception $e) {
  751. $this->assertEquals(0, $e->getCode(), 'getCode');
  752. $this->assertTrue(true, 'got expected exception');
  753. }
  754. }
  755. }
  756. /**
  757. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  758. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  759. */
  760. public function testInsertEntityInt() {
  761. foreach(TableServiceFunctionalTestData::getInterestingGoodInts() as $o) {
  762. $ent = new Entity();
  763. $ent->setPartitionKey(TableServiceFunctionalTestData::getNewKey());
  764. $ent->setRowKey(TableServiceFunctionalTestData::getNewKey());
  765. $ent->addProperty('INT32', EdmType::INT32, $o);
  766. $this->insertEntityWorker($ent, true, null, $o);
  767. }
  768. }
  769. /**
  770. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  771. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  772. */
  773. public function testInsertEntityIntNegative() {
  774. foreach(TableServiceFunctionalTestData::getInterestingBadInts() as $o) {
  775. $ent = new Entity();
  776. $ent->setPartitionKey(TableServiceFunctionalTestData::getNewKey());
  777. $ent->setRowKey(TableServiceFunctionalTestData::getNewKey());
  778. try {
  779. $ent->addProperty('INT32', EdmType::INT32, $o);
  780. $this->fail('Should get an exception when trying to parse this value');
  781. $this->insertEntityWorker($ent, false, null, $o);
  782. } catch (\Exception $e) {
  783. $this->assertEquals(0, $e->getCode(), 'getCode');
  784. $this->assertTrue(true, 'got expected exception');
  785. }
  786. }
  787. }
  788. /**
  789. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  790. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  791. */
  792. public function testInsertEntityLong() {
  793. foreach(TableServiceFunctionalTestData::getInterestingGoodLongs() as $o) {
  794. $ent = new Entity();
  795. $ent->setPartitionKey(TableServiceFunctionalTestData::getNewKey());
  796. $ent->setRowKey(TableServiceFunctionalTestData::getNewKey());
  797. $ent->addProperty('INT64', EdmType::INT64, $o);
  798. $this->insertEntityWorker($ent, true, null, $o);
  799. }
  800. }
  801. /**
  802. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  803. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  804. */
  805. public function testInsertEntityLongNegative() {
  806. foreach(TableServiceFunctionalTestData::getInterestingBadLongs() as $o) {
  807. $ent = new Entity();
  808. $ent->setPartitionKey(TableServiceFunctionalTestData::getNewKey());
  809. $ent->setRowKey(TableServiceFunctionalTestData::getNewKey());
  810. try {
  811. $ent->addProperty('INT64', EdmType::INT64, $o);
  812. $this->fail('Should get an exception when trying to parse this value');
  813. $this->insertEntityWorker($ent, false, null, $o);
  814. } catch (\Exception $e) {
  815. $this->assertEquals(0, $e->getCode(), 'getCode');
  816. $this->assertTrue(true, 'got expected exception');
  817. }
  818. }
  819. }
  820. /**
  821. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  822. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  823. */
  824. public function testInsertEntityBinary() {
  825. foreach(TableServiceFunctionalTestData::getInterestingGoodBinaries() as $o) {
  826. $ent = new Entity();
  827. $ent->setPartitionKey(TableServiceFunctionalTestData::getNewKey());
  828. $ent->setRowKey(TableServiceFunctionalTestData::getNewKey());
  829. $ent->addProperty('BINARY', EdmType::BINARY, $o);
  830. $this->insertEntityWorker($ent, true, null, $o);
  831. }
  832. }
  833. /**
  834. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  835. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  836. */
  837. public function testInsertEntityBinaryNegative() {
  838. foreach(TableServiceFunctionalTestData::getInterestingBadBinaries() as $o) {
  839. $ent = new Entity();
  840. $ent->setPartitionKey(TableServiceFunctionalTestData::getNewKey());
  841. $ent->setRowKey(TableServiceFunctionalTestData::getNewKey());
  842. try {
  843. $ent->addProperty('BINARY', EdmType::BINARY, $o);
  844. $this->fail('Should get an exception when trying to parse this value');
  845. $this->insertEntityWorker($ent, false, null, $o);
  846. } catch (\Exception $e) {
  847. $this->assertEquals(0, $e->getCode(), 'getCode');
  848. $this->assertTrue(true, 'got expected exception');
  849. }
  850. }
  851. }
  852. /**
  853. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  854. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  855. */
  856. public function testInsertEntityString() {
  857. foreach(TableServiceFunctionalTestData::getInterestingGoodStrings() as $o) {
  858. $ent = new Entity();
  859. $ent->setPartitionKey(TableServiceFunctionalTestData::getNewKey());
  860. $ent->setRowKey(TableServiceFunctionalTestData::getNewKey());
  861. $ent->addProperty('STRING', EdmType::STRING, $o);
  862. $this->insertEntityWorker($ent, true, null, $o);
  863. }
  864. }
  865. /**
  866. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  867. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  868. */
  869. private function insertEntityWorker($ent, $isGood, $options, $specialValue = null) {
  870. $table = $this->getCleanTable();
  871. try {
  872. $ret = (is_null($options) ? $this->restProxy->insertEntity($table, $ent) : $this->restProxy->insertEntity($table, $ent, $options));
  873. if (is_null($options)) {
  874. $options = new TableServiceOptions();
  875. }
  876. // Check that the message matches
  877. $this->assertNotNull($ret->getEntity(), 'getEntity()');
  878. $this->verifyinsertEntityWorker($ent, $ret->getEntity());
  879. if (is_null($ent->getPartitionKey()) || is_null($ent->getRowKey())) {
  880. $this->fail('Expect missing keys throw');
  881. }
  882. if (!$isGood) {
  883. $this->fail('Expect bad values to throw: ' . self::tmptostring($specialValue));
  884. }
  885. // Check that the message matches
  886. $qer = $this->restProxy->queryEntities($table);
  887. $this->assertNotNull($qer->getEntities(), 'getEntities()');
  888. $this->assertEquals(1, count($qer->getEntities()), 'getEntities() count');
  889. $entReturned = $qer->getEntities();
  890. $entReturned = $entReturned[0];
  891. $this->assertNotNull($entReturned, 'getEntities()[0]');
  892. $this->verifyinsertEntityWorker($ent, $entReturned);
  893. }
  894. catch (ServiceException $e) {
  895. if (!$isGood) {
  896. $this->assertEquals(400, $e->getCode(), 'getCode');
  897. }
  898. else if (is_null($ent->getPartitionKey()) || is_null($ent->getRowKey())) {
  899. $this->assertEquals(400, $e->getCode(), 'getCode');
  900. }
  901. else {
  902. throw $e;
  903. }
  904. }
  905. $this->clearTable($table);
  906. }
  907. /**
  908. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  909. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  910. * @covers WindowsAzure\Table\TableRestProxy::updateEntity
  911. */
  912. public function testUpdateEntity() {
  913. $ents = TableServiceFunctionalTestData::getSimpleEntities(2);
  914. foreach(MutatePivot::values() as $mutatePivot) {
  915. foreach($ents as $initialEnt) {
  916. $options = new TableServiceOptions();
  917. $ent = TableServiceFunctionalTestUtils::cloneEntity($initialEnt);
  918. TableServiceFunctionalTestUtils::mutateEntity($ent, $mutatePivot);
  919. $this->updateEntityWorker($initialEnt, $ent, $options);
  920. }
  921. }
  922. }
  923. /**
  924. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  925. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  926. * @covers WindowsAzure\Table\TableRestProxy::updateEntity
  927. */
  928. private function updateEntityWorker($initialEnt, $ent, $options) {
  929. $table = $this->getCleanTable();
  930. // Upload the entity.
  931. $this->restProxy->insertEntity($table, $initialEnt);
  932. if (is_null($options)) {
  933. $this->restProxy->updateEntity($table, $ent);
  934. }
  935. else {
  936. $this->restProxy->updateEntity($table, $ent, $options);
  937. }
  938. if (is_null($options)) {
  939. $options = new TableServiceOptions();
  940. }
  941. // Check that the message matches
  942. $qer = $this->restProxy->queryEntities($table);
  943. $this->assertNotNull($qer->getEntities(), 'getEntities()');
  944. $this->assertEquals(1, count($qer->getEntities()), 'getEntities()');
  945. $entReturned = $qer->getEntities();
  946. $entReturned = $entReturned[0];
  947. $this->assertNotNull($entReturned, 'getEntities()[0]');
  948. $this->verifyinsertEntityWorker($ent, $entReturned);
  949. $this->clearTable($table);
  950. }
  951. /**
  952. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  953. * @covers WindowsAzure\Table\TableRestProxy::mergeEntity
  954. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  955. */
  956. public function testMergeEntity() {
  957. $ents = TableServiceFunctionalTestData::getSimpleEntities(2);
  958. foreach(MutatePivot::values() as $mutatePivot) {
  959. foreach($ents as $initialEnt) {
  960. $options = new TableServiceOptions();
  961. $ent = TableServiceFunctionalTestUtils::cloneEntity($initialEnt);
  962. TableServiceFunctionalTestUtils::mutateEntity($ent, $mutatePivot);
  963. $this->mergeEntityWorker($initialEnt, $ent, $options);
  964. }
  965. }
  966. }
  967. /**
  968. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  969. * @covers WindowsAzure\Table\TableRestProxy::mergeEntity
  970. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  971. */
  972. private function mergeEntityWorker($initialEnt, $ent, $options) {
  973. $table = $this->getCleanTable();
  974. // Upload the entity.
  975. $this->restProxy->insertEntity($table, $initialEnt);
  976. if (is_null($options)) {
  977. $this->restProxy->mergeEntity($table, $ent);
  978. }
  979. else {
  980. $this->restProxy->mergeEntity($table, $ent, $options);
  981. }
  982. if (is_null($options)) {
  983. $options = new TableServiceOptions();
  984. }
  985. // Check that the message matches
  986. $qer = $this->restProxy->queryEntities($table);
  987. $this->assertNotNull($qer->getEntities(), 'getEntities()');
  988. $this->assertEquals(1, count($qer->getEntities()), 'getEntities() count');
  989. $entReturned = $qer->getEntities();
  990. $entReturned = $entReturned[0];
  991. $this->assertNotNull($entReturned, 'getEntities()[0]');
  992. $this->verifymergeEntityWorker($initialEnt, $ent, $entReturned);
  993. $this->clearTable($table);
  994. }
  995. /**
  996. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  997. * @covers WindowsAzure\Table\TableRestProxy::insertOrReplaceEntity
  998. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  999. */
  1000. public function testInsertOrReplaceEntity() {
  1001. $ents = TableServiceFunctionalTestData::getSimpleEntities(2);
  1002. foreach(MutatePivot::values() as $mutatePivot) {
  1003. foreach($ents as $initialEnt) {
  1004. $options = new TableServiceOptions();
  1005. $ent = TableServiceFunctionalTestUtils::cloneEntity($initialEnt);
  1006. TableServiceFunctionalTestUtils::mutateEntity($ent, $mutatePivot);
  1007. try {
  1008. $this->insertOrReplaceEntityWorker($initialEnt, $ent, $options);
  1009. $this->assertFalse(Configuration::isEmulated(), 'Should succeed when not running in emulator');
  1010. } catch (ServiceException $e) {
  1011. // Expect failure in emulator, as v1.6 doesn't support this method
  1012. if (Configuration::isEmulated()) {
  1013. $this->assertEquals(400, $e->getCode(), 'getCode');
  1014. } else {
  1015. throw $e;
  1016. }
  1017. }
  1018. }
  1019. }
  1020. }
  1021. /**
  1022. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  1023. * @covers WindowsAzure\Table\TableRestProxy::insertOrReplaceEntity
  1024. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  1025. */
  1026. private function insertOrReplaceEntityWorker($initialEnt, $ent, $options) {
  1027. $table = $this->getCleanTable();
  1028. // Upload the entity.
  1029. $this->restProxy->insertEntity($table, $initialEnt);
  1030. if (is_null($options)) {
  1031. $this->restProxy->insertOrReplaceEntity($table, $ent);
  1032. }
  1033. else {
  1034. $this->restProxy->insertOrReplaceEntity($table, $ent, $options);
  1035. }
  1036. if (is_null($options)) {
  1037. $options = new TableServiceOptions();
  1038. }
  1039. // Check that the message matches
  1040. $qer = $this->restProxy->queryEntities($table);
  1041. $this->assertNotNull($qer->getEntities(), 'getEntities()');
  1042. $this->assertEquals(1, count($qer->getEntities()), 'getEntities() count');
  1043. $entReturned = $qer->getEntities();
  1044. $entReturned = $entReturned[0];
  1045. $this->assertNotNull($entReturned, 'getEntities()[0]');
  1046. $this->verifyinsertEntityWorker($ent, $entReturned);
  1047. $this->clearTable($table);
  1048. }
  1049. /**
  1050. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  1051. * @covers WindowsAzure\Table\TableRestProxy::insertOrMergeEntity
  1052. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  1053. */
  1054. public function testInsertOrMergeEntity() {
  1055. $ents = TableServiceFunctionalTestData::getSimpleEntities(2);
  1056. foreach(MutatePivot::values() as $mutatePivot) {
  1057. foreach($ents as $initialEnt) {
  1058. $options = new TableServiceOptions();
  1059. $ent = TableServiceFunctionalTestUtils::cloneEntity($initialEnt);
  1060. TableServiceFunctionalTestUtils::mutateEntity($ent, $mutatePivot);
  1061. try {
  1062. $this->insertOrMergeEntityWorker($initialEnt, $ent, $options);
  1063. $this->assertFalse(Configuration::isEmulated(), 'Should succeed when not running in emulator');
  1064. } catch (ServiceException $e) {
  1065. // Expect failure in emulator, as v1.6 doesn't support this method
  1066. if (Configuration::isEmulated()) {
  1067. $this->assertEquals(400, $e->getCode(), 'getCode');
  1068. } else {
  1069. throw $e;
  1070. }
  1071. }
  1072. }
  1073. }
  1074. }
  1075. /**
  1076. * @covers WindowsAzure\Table\TableRestProxy::insertEntity
  1077. * @covers WindowsAzure\Table\TableRestProxy::insertOrMergeEntity
  1078. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  1079. */
  1080. private function insertOrMergeEntityWorker($initialEnt, $ent, $options) {
  1081. $table = $this->getCleanTable();
  1082. // Upload the entity.
  1083. $this->restProxy->insertEntity($table, $initialEnt);
  1084. if (is_null($options)) {
  1085. $this->restProxy->insertOrMergeEntity($table, $ent);
  1086. }
  1087. else {
  1088. $this->restProxy->insertOrMergeEntity($tab

Large files files are truncated, but you can click here to view the full file