PageRenderTime 53ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/codes-php/phpjakarta/tests/functional/WindowsAzure/Table/TableServiceFunctionalQueryTest.php

http://bukuphpjs.codeplex.com
PHP | 671 lines | 484 code | 101 blank | 86 comment | 45 complexity | 634a67adc6378456b91b77e150ff5b14 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\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\Framework\TestResources;
  25. use WindowsAzure\Common\ServiceException;
  26. use WindowsAzure\Table\Models\BatchOperations;
  27. use WindowsAzure\Table\Models\EdmType;
  28. use WindowsAzure\Table\Models\Entity;
  29. use WindowsAzure\Table\Models\Query;
  30. use WindowsAzure\Table\Models\QueryEntitiesOptions;
  31. use WindowsAzure\Table\Models\Filters\Filter;
  32. class TableServiceFunctionalQueryTest extends FunctionalTestBase
  33. {
  34. private static $entitiesInTable;
  35. private static $Partitions = array('Alpha', 'Bravo', 'Charlie', 'Delta', 'Echo');
  36. private static $curPartition;
  37. private static $curRowKey;
  38. public static function setUpBeforeClass()
  39. {
  40. parent::setUpBeforeClass();
  41. $table = TableServiceFunctionalTestData::$testTableNames[0];
  42. self::$entitiesInTable = self::getEntitiesToQueryOver();
  43. $baseWithRestProxy = new FunctionalTestBase();
  44. $baseWithRestProxy->setUp();
  45. $parts = array();
  46. foreach(self::$entitiesInTable as $entity) {
  47. if (array_key_exists($entity->getPartitionKey(), $parts) === false) {
  48. $parts[$entity->getPartitionKey()] = array();
  49. }
  50. array_push($parts[$entity->getPartitionKey()], $entity);
  51. }
  52. foreach($parts as $part) {
  53. $batch = new BatchOperations();
  54. foreach($part as $entity) {
  55. $batch->addInsertEntity($table, $entity);
  56. }
  57. $baseWithRestProxy->restProxy->batch($batch);
  58. }
  59. }
  60. private static function getNewEntity()
  61. {
  62. if (is_null(self::$curPartition) || self::$curPartition == count(self::$Partitions) - 1) {
  63. self::$curPartition = 0;
  64. self::$curRowKey = TableServiceFunctionalTestData::getNewKey();
  65. } else {
  66. self::$curPartition++;
  67. }
  68. $entity = new Entity();
  69. $entity->setPartitionKey(self::$Partitions[self::$curPartition]);
  70. $entity->setRowKey(self::$curRowKey);
  71. return $entity;
  72. }
  73. private static function getEntitiesToQueryOver()
  74. {
  75. $ret = array();
  76. array_push($ret, self::getNewEntity());
  77. $entity = self::getNewEntity();
  78. $entity->addProperty('BOOLEAN', EdmType::BOOLEAN, true);
  79. array_push($ret, $entity);
  80. $entity = self::getNewEntity();
  81. $entity->addProperty('BOOLEAN', EdmType::BOOLEAN, false);
  82. array_push($ret, $entity);
  83. $entity = self::getNewEntity();
  84. $entity->addProperty('DATETIME', EdmType::DATETIME, new \DateTime());
  85. array_push($ret, $entity);
  86. $entity = self::getNewEntity();
  87. $entity->addProperty('DATETIME', EdmType::DATETIME, new \DateTime('2012-01-02'));
  88. array_push($ret, $entity);
  89. $entity = self::getNewEntity();
  90. $entity->addProperty('DOUBLE', EdmType::DOUBLE, 2.71828183);
  91. array_push($ret, $entity);
  92. $entity = self::getNewEntity();
  93. $entity->addProperty('DOUBLE', EdmType::DOUBLE, 3.14159265);
  94. array_push($ret, $entity);
  95. $entity = self::getNewEntity();
  96. $entity->addProperty('GUID', EdmType::GUID, '90ab64d6-d3f8-49ec-b837-b8b5b6367b74');
  97. array_push($ret, $entity);
  98. $entity = self::getNewEntity();
  99. $entity->addProperty('GUID', EdmType::GUID, '00000000-1111-2222-3333-444444444444');
  100. array_push($ret, $entity);
  101. $entity = self::getNewEntity();
  102. $entity->addProperty('INT32', EdmType::INT32, 23);
  103. array_push($ret, $entity);
  104. $entity = self::getNewEntity();
  105. $entity->addProperty('INT32', EdmType::INT32, 42);
  106. array_push($ret, $entity);
  107. $entity = self::getNewEntity();
  108. $entity->addProperty('INT64', EdmType::INT64, '-1');
  109. array_push($ret, $entity);
  110. $entity = self::getNewEntity();
  111. $entity->addProperty('INT64', EdmType::INT64, strval(TableServiceFunctionalTestData::LONG_BIG_VALUE));
  112. array_push($ret, $entity);
  113. $entity = self::getNewEntity();
  114. $entity->addProperty('STRING', EdmType::STRING, 'foo');
  115. array_push($ret, $entity);
  116. $entity = self::getNewEntity();
  117. $entity->addProperty('STRING', EdmType::STRING, 'o hai');
  118. array_push($ret, $entity);
  119. $entity = self::getNewEntity();
  120. $e = self::getNewEntity();
  121. $e->addProperty('test', EdmType::BOOLEAN, true);
  122. $e->addProperty('test2', EdmType::STRING, 'value');
  123. $e->addProperty('test3', EdmType::INT32, 3);
  124. $e->addProperty('test4', EdmType::INT64, '12345678901');
  125. $e->addProperty('test5', EdmType::DATETIME, new \DateTime());
  126. array_push($ret, $e);
  127. $booleans = TableServiceFunctionalTestData::getInterestingGoodBooleans();
  128. $dates = TableServiceFunctionalTestData::getInterestingGoodDates();
  129. $doubles = TableServiceFunctionalTestData::getInterestingGoodDoubles();
  130. $guids = TableServiceFunctionalTestData::getInterestingGoodGuids();
  131. $ints = TableServiceFunctionalTestData::getInterestingGoodInts();
  132. $longs = TableServiceFunctionalTestData::getInterestingGoodLongs();
  133. $binaries = TableServiceFunctionalTestData::getInterestingGoodBinaries();
  134. $strings = TableServiceFunctionalTestData::getInterestingGoodStrings();
  135. // The random here is not to generate random values, but to
  136. // get a good mix of values in the table entities.
  137. mt_srand(123);
  138. for ($i = 0; $i < 20; $i++) {
  139. $e = self::getNewEntity();
  140. TableServiceFunctionalTestData::addProperty($e, 'BINARY', EdmType::BINARY, $binaries);
  141. TableServiceFunctionalTestData::addProperty($e, 'BOOLEAN', EdmType::BOOLEAN, $booleans);
  142. TableServiceFunctionalTestData::addProperty($e, 'DATETIME', EdmType::DATETIME, $dates);
  143. TableServiceFunctionalTestData::addProperty($e, 'DOUBLE', EdmType::DOUBLE, $doubles);
  144. TableServiceFunctionalTestData::addProperty($e, 'GUID', EdmType::GUID, $guids);
  145. TableServiceFunctionalTestData::addProperty($e, 'INT32', EdmType::INT32, $ints);
  146. TableServiceFunctionalTestData::addProperty($e, 'INT64', EdmType::INT64, $longs);
  147. TableServiceFunctionalTestData::addProperty($e, 'STRING', EdmType::STRING, $strings);
  148. array_push($ret, $e);
  149. }
  150. return $ret;
  151. }
  152. public static function getInterestingQueryEntitiesOptions()
  153. {
  154. $ret = array();
  155. $e = self::$entitiesInTable[count(self::$entitiesInTable) - 3];
  156. $options = new QueryEntitiesOptions();
  157. array_push($ret, $options);
  158. $options = new QueryEntitiesOptions();
  159. $query = new Query();
  160. $options->setQuery($query);
  161. array_push($ret, $options);
  162. $options = new QueryEntitiesOptions();
  163. $query = new Query();
  164. $query->setTop(2);
  165. $options->setQuery($query);
  166. array_push($ret, $options);
  167. $options = new QueryEntitiesOptions();
  168. $query = new Query();
  169. $query->setTop(-2);
  170. $options->setQuery($query);
  171. array_push($ret, $options);
  172. $options = new QueryEntitiesOptions();
  173. $query = new Query();
  174. $query->addSelectField('TableName');
  175. $options->setQuery($query);
  176. array_push($ret, $options);
  177. $options = new QueryEntitiesOptions();
  178. $query = new Query();
  179. $filter = Filter::applyPropertyName('BOOLEAN');
  180. $query->setFilter($filter);
  181. $options->setQuery($query);
  182. array_push($ret, $options);
  183. $options = new QueryEntitiesOptions();
  184. $query = new Query();
  185. $filter = Filter::applyConstant(false, EdmType::BOOLEAN);
  186. $query->setFilter($filter);
  187. $options->setQuery($query);
  188. array_push($ret, $options);
  189. $options = new QueryEntitiesOptions();
  190. $query = new Query();
  191. $filter = Filter::applyEq(Filter::applyConstant(23, EdmType::INT32), Filter::applyPropertyName('INT32'));
  192. $query->setFilter($filter);
  193. $options->setQuery($query);
  194. array_push($ret, $options);
  195. $options = new QueryEntitiesOptions();
  196. $query = new Query();
  197. $filter = Filter::applyNe(Filter::applyConstant(23, EdmType::INT32), Filter::applyPropertyName('INT32'));
  198. $query->setFilter($filter);
  199. $options->setQuery($query);
  200. array_push($ret, $options);
  201. $options = new QueryEntitiesOptions();
  202. $query = new Query();
  203. $filter = Filter::applyNot(Filter::applyEq(Filter::applyConstant(23, EdmType::INT32), Filter::applyPropertyName('INT32')));
  204. $query->setFilter($filter);
  205. $options->setQuery($query);
  206. array_push($ret, $options);
  207. $options = new QueryEntitiesOptions();
  208. $options->setNextPartitionKey($e->getPartitionKey());
  209. $options->setNextRowKey($e->getRowKey());
  210. array_push($ret, $options);
  211. // Ask for an entity that does not exist.
  212. $options = new QueryEntitiesOptions();
  213. $options->setNextPartitionKey(self::$Partitions[2] . 'X');
  214. $options->setNextRowKey($e->getRowKey() . 'X');
  215. array_push($ret, $options);
  216. return $ret;
  217. }
  218. public static function getInterestingQueryEntitiesOptionsOfDepth($depth)
  219. {
  220. $ret = array();
  221. // The random here is not to generate random values, but to
  222. // get a good mix of values in the table entities.
  223. mt_srand(456 + $depth);
  224. for ($i = 1; $i < 20; $i++) {
  225. $filter = self::generateFilterWithBooleanParameters($depth, 0);
  226. $options = new QueryEntitiesOptions();
  227. $query = new Query();
  228. $query->setFilter($filter);
  229. $options->setQuery($query);
  230. array_push($ret, $options);
  231. }
  232. return $ret;
  233. }
  234. private static function generateFilterWithBooleanParameters($targetDepth, $depth)
  235. {
  236. // Use the filter grammar to construct a tree.
  237. // The random here is not to generate random values, but to
  238. // get a good mix of values in the table entities.
  239. // TODO: Treat raw string special
  240. if ($depth == $targetDepth) {
  241. switch (mt_rand(0,2)) {
  242. case 0:
  243. return self::generateBinaryFilterWithAnyParameters();
  244. case 1:
  245. return Filter::applyConstant(mt_rand(0,1) == 1, EdmType::BOOLEAN);
  246. case 2:
  247. $e = self::getEntityFromTable();
  248. $boolPropNames = array();
  249. foreach($e->getProperties() as $key => $p) {
  250. if ($p->getEdmType() == EdmType::BOOLEAN) {
  251. array_push($boolPropNames, $key);
  252. }
  253. }
  254. if (count($boolPropNames) == 0) {
  255. return Filter::applyConstant(mt_rand(0,1) == 1, EdmType::BOOLEAN);
  256. } else {
  257. $key = $boolPropNames[mt_rand(0, count($boolPropNames) - 1)];
  258. return Filter::applyPropertyName($key);
  259. }
  260. default:
  261. return null;
  262. }
  263. } else {
  264. switch (mt_rand(0,8)) {
  265. case 0:
  266. case 1:
  267. case 2:
  268. case 3:
  269. return Filter::applyAnd(
  270. self::generateFilterWithBooleanParameters($targetDepth, $depth + 1),
  271. self::generateFilterWithBooleanParameters($targetDepth, $depth + 1));
  272. case 4:
  273. case 5:
  274. case 6:
  275. case 7:
  276. return Filter::applyOr(
  277. self::generateFilterWithBooleanParameters($targetDepth, $depth + 1),
  278. self::generateFilterWithBooleanParameters($targetDepth, $depth + 1));
  279. case 8:
  280. return Filter::applyNot(self::generateFilterWithBooleanParameters($targetDepth, $depth + 1));
  281. default:
  282. return null;
  283. }
  284. }
  285. }
  286. private static function generateBinaryFilterWithAnyParameters()
  287. {
  288. // get a good mix of values in the table entities.
  289. // Pull out one of the constants.
  290. $e = self::getEntityFromTable();
  291. $keys = array_keys($e->getProperties());
  292. $propId = mt_rand(0, count($keys) - 1);
  293. $key = $keys[$propId];
  294. $prop = $e->getProperty($key);
  295. $f1 = Filter::applyConstant($prop->getValue(), $prop->getEdmType());
  296. $f2 = Filter::applyPropertyName($key);
  297. if (mt_rand(0,1) == 1) {
  298. // Try swapping.
  299. $t = $f1;
  300. $f1 = $f2;
  301. $f2 = $t;
  302. }
  303. return self::getBinaryFilterFromIndex(mt_rand(0, 5), $f1, $f2);
  304. }
  305. private static function getEntityFromTable()
  306. {
  307. $entId = mt_rand(0, count(self::$entitiesInTable) - 1);
  308. $e = self::$entitiesInTable[$entId];
  309. return $e;
  310. }
  311. private static function getBinaryFilterFromIndex($index, $f1, $f2)
  312. {
  313. switch ($index) {
  314. case 0: return Filter::applyEq($f1, $f2);
  315. case 1: return Filter::applyGe($f1, $f2);
  316. case 2: return Filter::applyGt($f1, $f2);
  317. case 3: return Filter::applyLe($f1, $f2);
  318. case 4: return Filter::applyLt($f1, $f2);
  319. case 5: return Filter::applyNe($f1, $f2);
  320. default: return null;
  321. }
  322. }
  323. /**
  324. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  325. */
  326. public function testQueryEntities()
  327. {
  328. // The emulator has problems with non-standard queries tested here.
  329. $this->skipIfEmulated();
  330. $interestingqueryEntitiesOptions = self::getInterestingQueryEntitiesOptions();
  331. foreach($interestingqueryEntitiesOptions as $options) {
  332. $this->queryEntitiesWorker($options);
  333. }
  334. }
  335. /**
  336. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  337. */
  338. public function testQueryEntitiesBooleanLevel1()
  339. {
  340. // The emulator has problems with non-standard queries tested here.
  341. $this->skipIfEmulated();
  342. $interestingqueryEntitiesOptions = self::addBinaryFilter('BOOLEAN', EdmType::BOOLEAN, TableServiceFunctionalTestData::getInterestingGoodBooleans());
  343. foreach($interestingqueryEntitiesOptions as $options) {
  344. $this->queryEntitiesWorker($options);
  345. }
  346. }
  347. /**
  348. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  349. */
  350. public function testQueryEntitiesDateTimeLevel1()
  351. {
  352. // The emulator has problems with non-standard queries tested here.
  353. $this->skipIfEmulated();
  354. $interestingqueryEntitiesOptions = self::addBinaryFilter('DATETIME', EdmType::DATETIME, TableServiceFunctionalTestData::getInterestingGoodDates());
  355. foreach($interestingqueryEntitiesOptions as $options) {
  356. $this->queryEntitiesWorker($options);
  357. }
  358. }
  359. /**
  360. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  361. */
  362. public function testQueryEntitiesDoubleLevel1()
  363. {
  364. // The emulator has problems with non-standard queries tested here.
  365. $this->skipIfEmulated();
  366. $interestingqueryEntitiesOptions = self::addBinaryFilter('DOUBLE', EdmType::DOUBLE, TableServiceFunctionalTestData::getInterestingGoodDoubles());
  367. foreach($interestingqueryEntitiesOptions as $options) {
  368. $this->queryEntitiesWorker($options);
  369. }
  370. }
  371. /**
  372. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  373. */
  374. public function testQueryEntitiesGuidLevel1()
  375. {
  376. // The emulator has problems with non-standard queries tested here.
  377. $this->skipIfEmulated();
  378. $interestingqueryEntitiesOptions = self::addBinaryFilter('GUID', EdmType::GUID, TableServiceFunctionalTestData::getInterestingGoodGuids());
  379. foreach($interestingqueryEntitiesOptions as $options) {
  380. $this->queryEntitiesWorker($options);
  381. }
  382. }
  383. /**
  384. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  385. */
  386. public function testQueryEntitiesIntLevel1()
  387. {
  388. // The emulator has problems with non-standard queries tested here.
  389. $this->skipIfEmulated();
  390. $interestingqueryEntitiesOptions = self::addBinaryFilter('INT32', EdmType::INT32, TableServiceFunctionalTestData::getInterestingGoodInts());
  391. foreach($interestingqueryEntitiesOptions as $options) {
  392. $this->queryEntitiesWorker($options);
  393. }
  394. }
  395. /**
  396. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  397. */
  398. public function testQueryEntitiesLongLevel1()
  399. {
  400. // The emulator has problems with non-standard queries tested here.
  401. $this->skipIfEmulated();
  402. $interestingqueryEntitiesOptions = self::addBinaryFilter('INT64', EdmType::INT64, TableServiceFunctionalTestData::getInterestingGoodLongs());
  403. foreach($interestingqueryEntitiesOptions as $options) {
  404. $this->queryEntitiesWorker($options);
  405. }
  406. }
  407. /**
  408. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  409. */
  410. public function testQueryEntitiesStringLevel1()
  411. {
  412. // The emulator has problems with non-standard queries tested here.
  413. $this->skipIfEmulated();
  414. $interestingqueryEntitiesOptions = self::addBinaryFilter('STRING', EdmType::STRING, TableServiceFunctionalTestData::getInterestingGoodStrings());
  415. foreach($interestingqueryEntitiesOptions as $options) {
  416. $this->queryEntitiesWorker($options);
  417. }
  418. }
  419. /**
  420. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  421. */
  422. public function testQueryEntitiesBinaryLevel1()
  423. {
  424. // The emulator has problems with non-standard queries tested here.
  425. $this->skipIfEmulated();
  426. $interestingqueryEntitiesOptions = self::addBinaryFilter('BINARY', EdmType::BINARY, TableServiceFunctionalTestData::getInterestingGoodBinaries());
  427. foreach($interestingqueryEntitiesOptions as $options) {
  428. $this->queryEntitiesWorker($options);
  429. }
  430. }
  431. /**
  432. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  433. */
  434. public function testQueryEntitiesLevel2()
  435. {
  436. // The emulator has problems with non-standard queries tested here.
  437. $this->skipIfEmulated();
  438. $interestingqueryEntitiesOptions = self::getInterestingQueryEntitiesOptionsOfDepth(2);
  439. foreach($interestingqueryEntitiesOptions as $options) {
  440. $this->queryEntitiesWorker($options);
  441. }
  442. }
  443. /**
  444. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  445. */
  446. public function testQueryEntitiesLevel3()
  447. {
  448. // The emulator has problems with non-standard queries tested here.
  449. $this->skipIfEmulated();
  450. $interestingqueryEntitiesOptions = self::getInterestingQueryEntitiesOptionsOfDepth(3);
  451. foreach($interestingqueryEntitiesOptions as $options) {
  452. $this->queryEntitiesWorker($options);
  453. }
  454. }
  455. /**
  456. * @covers WindowsAzure\Table\TableRestProxy::queryEntities
  457. */
  458. private function queryEntitiesWorker($options)
  459. {
  460. $table = TableServiceFunctionalTestData::$testTableNames[0];
  461. try {
  462. $ret = (is_null($options) ? $this->restProxy->queryEntities($table) : $this->restProxy->queryEntities($table, $options));
  463. if (is_null($options)) {
  464. $options = new QueryEntitiesOptions();
  465. }
  466. if (!is_null($options->getQuery()) && !is_null($options->getQuery()->getTop()) && $options->getQuery()->getTop() <= 0) {
  467. $this->assertTrue(false, 'Expect non-positive Top in $options->query to throw');
  468. }
  469. $this->verifyqueryEntitiesWorker($ret, $options);
  470. // In principle, should check if there is a continuation, then use it.
  471. // However, the user cannot easily control when this happens, so I'm
  472. // not sure how useful it is.
  473. // To test that scenario, set NextTable in the $options.
  474. } catch (ServiceException $e) {
  475. if (!is_null($options->getQuery()) && !is_null($options->getQuery()->getTop()) && $options->getQuery()->getTop() <= 0) {
  476. $this->assertEquals(TestResources::STATUS_BAD_REQUEST, $e->getCode(), 'getCode');
  477. } else {
  478. $this->assertEquals(TestResources::STATUS_INTERNAL_SERVER_ERROR, $e->getCode(), 'getCode');
  479. }
  480. }
  481. }
  482. private function verifyqueryEntitiesWorker($ret, $options)
  483. {
  484. $this->assertNotNull($ret->getEntities(), 'getTables');
  485. $expectedData = array();
  486. foreach(self::$entitiesInTable as $e) {
  487. array_push($expectedData, $e);
  488. }
  489. sort($expectedData);
  490. $projected = false;
  491. if (!is_null($options->getNextPartitionKey()) && !is_null($options->getNextRowKey())) {
  492. $expectedDataTmp = array();
  493. foreach($expectedData as $e) {
  494. if ( ($e->getPartitionKey() > $options->getNextPartitionKey()) ||
  495. (($e->getPartitionKey() == $options->getNextPartitionKey()) &&
  496. ($e->getRowKey() >= $options->getNextRowKey()))) {
  497. array_push($expectedDataTmp, $e);
  498. }
  499. }
  500. $expectedData = $expectedDataTmp;
  501. }
  502. $q = $options->getQuery();
  503. $expectedFilter = $q->getFilter();
  504. $projected = (count($q->getSelectFields()) != 0);
  505. $expectedData = TableServiceFunctionalTestUtils::filterEntityList($expectedFilter, $expectedData);
  506. if (!is_null($q->getTop()) && $q->getTop() < count($expectedData)) {
  507. $expectedDataTmp = array();
  508. for ($i = 0; $i < $q->getTop(); $i++) {
  509. array_push($expectedDataTmp, $expectedData[$i]);
  510. }
  511. $expectedData = $expectedDataTmp;
  512. }
  513. $this->compareEntityLists($ret->getEntities(), $expectedData, $projected);
  514. }
  515. private function compareEntityLists($actualData, $expectedData, $projected)
  516. {
  517. // Need to sort the lists.
  518. $actualData = self::sortEntitiesByCompositeKey($actualData);
  519. $expectedData = self::sortEntitiesByCompositeKey($expectedData);
  520. $this->assertEquals(count($expectedData), count($actualData), 'count(getEntities)');
  521. for ($i = 0; $i < count($expectedData); $i++) {
  522. $e1 = $expectedData[$i];
  523. $e2 = $actualData[$i];
  524. if (!$projected) {
  525. $this->assertTrue(
  526. ($e1->getPartitionKey() == $e2->getPartitionKey()) && ($e1->getRowKey() == $e2->getRowKey()),
  527. '(' . $e1->getPartitionKey() . ',' . $e1->getRowKey() . ') == (' . $e2->getPartitionKey() . ',' . $e2->getRowKey() . ')');
  528. }
  529. // Don't need to verify the whole entities, done elsewhere
  530. }
  531. }
  532. private static function addBinaryFilter($name, $edmType, $values)
  533. {
  534. $counter = 0;
  535. $ret = array();
  536. foreach($values as $o) {
  537. $f = self::getBinaryFilterFromIndex($counter, Filter::applyPropertyName($name), Filter::applyConstant($o, $edmType));
  538. $q = new Query();
  539. $q->setFilter($f);
  540. $qeo = new QueryEntitiesOptions();
  541. $qeo->setQuery($q);
  542. array_push($ret, $qeo);
  543. $counter = ($counter + 1) % 6;
  544. }
  545. return $ret;
  546. }
  547. public static function sortEntitiesByCompositeKey($originalArray)
  548. {
  549. $tmpArray = array();
  550. $isordered = true;
  551. $prevIndex = '/';
  552. foreach($originalArray as $e) {
  553. $index = $e->getPartitionKey() . '/' . $e->getRowKey();
  554. $tmpArray[$index] = $e;
  555. if ($isordered) {
  556. $isordered = $prevIndex <= $index;
  557. }
  558. $prevIndex = $index;
  559. }
  560. if ($isordered) {
  561. return $originalArray;
  562. }
  563. ksort($tmpArray);
  564. $ret = array();
  565. foreach($tmpArray as $e) {
  566. array_push($ret, $e);
  567. }
  568. return $ret;
  569. }
  570. }