PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/functional/WindowsAzure/Table/TableServiceFunctionalQueryTest.php

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