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

/OData Producer for PHP/Tests/UriProcessor/UriProcessorTest.php

#
PHP | 2461 lines | 1975 code | 149 blank | 337 comment | 134 complexity | 5840980579cbdb4b484766a33ca79aa8 MD5 | raw file

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

  1. <?php
  2. /**
  3. * Mainly test UriProcessor, but also do some partial test for DataService class.
  4. */
  5. use ODataProducer\UriProcessor\QueryProcessor\ExpandProjectionParser\ProjectionNode;
  6. use ODataProducer\UriProcessor\QueryProcessor\ExpandProjectionParser\ExpandedProjectionNode;
  7. use ODataProducer\UriProcessor\QueryProcessor\ExpandProjectionParser\RootProjectionNode;
  8. use ODataProducer\UriProcessor\QueryProcessor\AnonymousFunction;
  9. use ODataProducer\UriProcessor\QueryProcessor\OrderByParser\OrderBySubPathSegment;
  10. use ODataProducer\UriProcessor\QueryProcessor\OrderByParser\OrderByPathSegment;
  11. use ODataProducer\UriProcessor\QueryProcessor\SkipTokenParser\InternalSkipTokenInfo;
  12. use ODataProducer\UriProcessor\QueryProcessor\SkipTokenParser\SkipTokenInfo;
  13. use ODataProducer\UriProcessor\QueryProcessor\ExpressionParser\InternalFilterInfo;
  14. use ODataProducer\UriProcessor\QueryProcessor\OrderByParser\InternalOrderByInfo;
  15. use ODataProducer\UriProcessor\RequestCountOption;
  16. use ODataProducer\Configuration\DataServiceProtocolVersion;
  17. use ODataProducer\UriProcessor\ResourcePathProcessor\SegmentParser\RequestTargetKind;
  18. use ODataProducer\UriProcessor\ResourcePathProcessor\SegmentParser\RequestTargetSource;
  19. use ODataProducer\Providers\Metadata\Type\Int32;
  20. use ODataProducer\Providers\Metadata\Type\DateTime;
  21. use ODataProducer\Common\Url;
  22. use ODataProducer\Common\Version;
  23. use ODataProducer\Common\ODataException;
  24. require_once 'PHPUnit\Framework\Assert.php';
  25. require_once 'PHPUnit\Framework\Test.php';
  26. require_once 'PHPUnit\Framework\SelfDescribing.php';
  27. require_once 'PHPUnit\Framework\TestCase.php';
  28. require_once 'PHPUnit\Framework\TestSuite.php';
  29. require_once 'ODataProducer\Common\ClassAutoLoader.php';
  30. require_once (dirname(__FILE__) . "\.\..\Resources\NorthWindMetadata.php");
  31. require_once (dirname(__FILE__) . "\.\..\Resources\NorthWindDataServiceV1.php");
  32. require_once (dirname(__FILE__) . "\.\..\Resources\NorthWindDataService.php");
  33. require_once (dirname(__FILE__) . "\.\..\Resources\NorthWindDataServiceV3.php");
  34. require_once (dirname(__FILE__) . "\.\..\Resources\DataServiceHost2.php");
  35. ODataProducer\Common\ClassAutoLoader::register();
  36. class TestUriProcessor extends PHPUnit_Framework_TestCase
  37. {
  38. protected function setUp()
  39. {
  40. }
  41. /**
  42. * The request uri should be based on the service uri specified in the configuration.
  43. */
  44. /**public function testRequestUriWithInvalidBaseUri()
  45. {
  46. try {
  47. $hostInfo = array('AbsoluteRequestUri' =>
  48. new Url('http://localhost:8083/NorthWindDataService.svc'),
  49. 'AbsoluteServiceUri' =>
  50. new Url('http://localhost:8083/XX/NorthWindDataService.svc'),
  51. 'QueryString' =>
  52. null);
  53. $host = new DataServiceHost2($hostInfo);
  54. $dataService = new NorthWindDataService2();
  55. $dataService->setHost($host);
  56. $exceptionThrown = false;
  57. try {
  58. $dataService->handleRequest();
  59. } catch (ODataException $odataException) {
  60. $exceptionThrown = true;
  61. $this->assertStringStartsWith("The URI 'http://localhost:8083/NorthWindDataService.svc' is not ", $odataException->getMessage());
  62. }
  63. if (!$exceptionThrown) {
  64. $this->fail('An expected ODataException for invalid base uri in the request uri has not been thrown');
  65. }
  66. } catch (\Exception $exception) {
  67. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  68. }
  69. }**/
  70. /**
  71. * Test with request uri where RequestTargetKind is NONE. RequestTargetKind will be
  72. * NONE for service directory, metadata and batch.
  73. */
  74. public function testUriProcessorWithRequestUriOfNoneTargetSourceKind()
  75. {
  76. try {
  77. //Request for service directory
  78. $hostInfo = array('AbsoluteRequestUri' =>
  79. new Url('http://localhost:8083/NorthWindDataService.svc'),
  80. 'AbsoluteServiceUri' =>
  81. new Url('http://localhost:8083/NorthWindDataService.svc'),
  82. 'QueryString' =>
  83. null);
  84. $host = new DataServiceHost2($hostInfo);
  85. $dataService = new NorthWindDataService2();
  86. $dataService->setHost($host);
  87. $exceptionThrown = false;
  88. $uriProcessor = $dataService->handleRequest();
  89. $requestDescripton = $uriProcessor->getRequestDescription();
  90. $this->assertEquals($requestDescripton->getTargetSource(), RequestTargetSource::NONE);
  91. $this->assertEquals($requestDescripton->getTargetKind(), RequestTargetKind::SERVICE_DIRECTORY);
  92. // Context is a singleton class reset it
  93. $host->getWebOperationContext()->resetWebContextInternal();
  94. //Request for metadata
  95. $hostInfo = array('AbsoluteRequestUri' =>
  96. new Url('http://localhost:8083/NorthWindDataService.svc/$metadata'),
  97. 'AbsoluteServiceUri' =>
  98. new Url('http://localhost:8083/NorthWindDataService.svc'),
  99. 'QueryString' =>
  100. null);
  101. $host = new DataServiceHost2($hostInfo);
  102. $dataService = new NorthWindDataService2();
  103. $dataService->setHost($host);
  104. $exceptionThrown = false;
  105. $requestDescripton = $uriProcessor = null;
  106. $uriProcessor = $dataService->handleRequest();
  107. $requestDescripton = $uriProcessor->getRequestDescription();
  108. $this->assertEquals($requestDescripton->getTargetSource(), RequestTargetSource::NONE);
  109. $this->assertEquals($requestDescripton->getTargetKind(), RequestTargetKind::METADATA);
  110. // Context is a singleton class reset it
  111. $host->getWebOperationContext()->resetWebContextInternal();
  112. //Request for batch
  113. $hostInfo = array('AbsoluteRequestUri' =>
  114. new Url('http://localhost:8083/NorthWindDataService.svc/$batch'),
  115. 'AbsoluteServiceUri' =>
  116. new Url('http://localhost:8083/NorthWindDataService.svc'),
  117. 'QueryString' =>
  118. null);
  119. $host = new DataServiceHost2($hostInfo);
  120. $dataService = new NorthWindDataService2();
  121. $dataService->setHost($host);
  122. $exceptionThrown = false;
  123. $uriProcessor = $dataService->handleRequest();
  124. $requestDescripton = $uriProcessor->getRequestDescription();
  125. $this->assertEquals($requestDescripton->getTargetSource(), RequestTargetSource::NONE);
  126. $this->assertEquals($requestDescripton->getTargetKind(), RequestTargetKind::BATCH);
  127. // Context is a singleton class reset it
  128. $host->getWebOperationContext()->resetWebContextInternal();
  129. } catch (\Exception $exception) {
  130. if ($host != null) {
  131. $host->getWebOperationContext()->resetWebContextInternal();
  132. }
  133. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  134. }
  135. }
  136. /**
  137. * Test request uri for row count ($count)
  138. * DataServiceVersion and MaxDataServiceVersion should be >= 2.0 for $count
  139. */
  140. public function testUriProcessorForCountRequest1()
  141. {
  142. try {
  143. //Test $count with DataServiceVersion < 2.0
  144. $hostInfo = array('AbsoluteRequestUri' => new Url('http://localhost:8083/NorthWindDataService.svc/Customers/$count'),
  145. 'AbsoluteServiceUri' => new Url('http://localhost:8083/NorthWindDataService.svc'),
  146. 'QueryString' => null,
  147. 'DataServiceVersion' => new Version(1, 0),
  148. 'MaxDataServiceVersion' => new Version(2, 0));
  149. $host = new DataServiceHost2($hostInfo);
  150. $dataService = new NorthWindDataService2();
  151. $dataService->setHost($host);
  152. $exceptionThrown = false;
  153. try {
  154. $uriProcessor = $dataService->handleRequest();
  155. } catch (ODataException $odataException) {
  156. $exceptionThrown = true;
  157. $this->assertStringStartsWith("Request version '1.0' is not supported for the request payload. The only supported version is '2.0", $odataException->getMessage());
  158. }
  159. if (!$exceptionThrown) {
  160. $this->fail('An expected ODataException for failure of capability negoitation over DataServiceVersion has not been thrown');
  161. }
  162. // Context is a singleton class reset it
  163. $host->getWebOperationContext()->resetWebContextInternal();
  164. //Test $count with MaxDataServiceVersion < 2.0
  165. $hostInfo = array('AbsoluteRequestUri' => new Url('http://localhost:8083/NorthWindDataService.svc/Customers/$count'),
  166. 'AbsoluteServiceUri' => new Url('http://localhost:8083/NorthWindDataService.svc'),
  167. 'QueryString' => null,
  168. 'DataServiceVersion' => new Version(2, 0),
  169. 'MaxDataServiceVersion' => new Version(1, 0));
  170. $host = new DataServiceHost2($hostInfo);
  171. $dataService = new NorthWindDataService2();
  172. $dataService->setHost($host);
  173. $exceptionThrown = false;
  174. try {
  175. $uriProcessor = $dataService->handleRequest();
  176. } catch (ODataException $odataException) {
  177. $exceptionThrown = true;
  178. $this->assertStringStartsWith("Request version '1.0' is not supported for the request payload. The only supported version is '2.0", $odataException->getMessage());
  179. }
  180. if (!$exceptionThrown) {
  181. $this->fail('An expected ODataException for failure of capability negoitation over MaxDataServiceVersion has not been thrown');
  182. }
  183. $host->getWebOperationContext()->resetWebContextInternal();
  184. } catch (\Exception $exception) {
  185. if ($host != null) {
  186. $host->getWebOperationContext()->resetWebContextInternal();
  187. }
  188. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  189. }
  190. }
  191. /**
  192. * Test request uri for row count ($count)
  193. * $count is a version 2 feature so service devloper should use protocol version 2.0
  194. */
  195. public function testUriProcessorForCountRequest2()
  196. {
  197. try {
  198. $hostInfo = array('AbsoluteRequestUri' => new Url('http://localhost:8083/NorthWindDataService.svc/Customers/$count'),
  199. 'AbsoluteServiceUri' => new Url('http://localhost:8083/NorthWindDataService.svc'),
  200. 'QueryString' => null,
  201. 'DataServiceVersion' => new Version(2, 0),
  202. 'MaxDataServiceVersion' => new Version(2, 0));
  203. $host = new DataServiceHost2($hostInfo);
  204. $dataService = new NorthWindDataServiceV1();
  205. $dataService->setHost($host);
  206. $exceptionThrown = false;
  207. try {
  208. $uriProcessor = $dataService->handleRequest();
  209. } catch (ODataException $odataException) {
  210. $exceptionThrown = true;
  211. $this->assertStringStartsWith("The response requires that version 2.0 of the protocol be used, but the MaxProtocolVersion of the data service is set to 1.0", $odataException->getMessage());
  212. }
  213. if (!$exceptionThrown) {
  214. $this->fail('An expected ODataException for failure of capability negoitation due to V1 configuration has not been thrown');
  215. }
  216. $host->getWebOperationContext()->resetWebContextInternal();
  217. } catch (\Exception $exception) {
  218. if ($host != null) {
  219. $host->getWebOperationContext()->resetWebContextInternal();
  220. }
  221. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  222. }
  223. }
  224. /**
  225. * Test request uri for row count ($count)
  226. *
  227. * Suppose $top option is absent, still
  228. * RequestDescription::topCount will be set if the resource targetted by the
  229. * uri has paging enabled, if RequestDescription::topCount
  230. * is set then internal orderby info will be generated. But if the request
  231. * is for raw count for a resource collection then paging is not applicable
  232. * for that, so topCount will be null and internal orderby info will not be
  233. * generated.
  234. */
  235. public function testUriProcessorForCountRequest3()
  236. {
  237. try {
  238. $hostInfo = array('AbsoluteRequestUri' => new Url('http://localhost:8083/NorthWindDataService.svc/Customers/$count'),
  239. 'AbsoluteServiceUri' => new Url('http://localhost:8083/NorthWindDataService.svc'),
  240. 'QueryString' => null,
  241. 'DataServiceVersion' => new Version(2, 0),
  242. 'MaxDataServiceVersion' => new Version(2, 0));
  243. $host = new DataServiceHost2($hostInfo);
  244. $dataService = new NorthWindDataService2();
  245. $dataService->setHost($host);
  246. $exceptionThrown = false;
  247. $uriProcessor = $dataService->handleRequest();
  248. $requestDescription = $uriProcessor->getRequestDescription();
  249. $this->assertTrue(!is_null($requestDescription));
  250. $this->assertTrue(is_null($requestDescription->getInternalOrderByInfo()));
  251. $host->getWebOperationContext()->resetWebContextInternal();
  252. } catch (\Exception $exception) {
  253. if ($host != null) {
  254. $host->getWebOperationContext()->resetWebContextInternal();
  255. }
  256. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  257. }
  258. }
  259. /**
  260. * Test request uri for row count ($count)
  261. *
  262. * $orderby option can be applied to a $count request.
  263. */
  264. public function testUriProcessorForCountRequest4()
  265. {
  266. try {
  267. $hostInfo = array('AbsoluteRequestUri' => new Url('http://localhost:8083/NorthWindDataService.svc/Customers/$count'),
  268. 'AbsoluteServiceUri' => new Url('http://localhost:8083/NorthWindDataService.svc'),
  269. 'QueryString' => '$orderby=Country',
  270. 'DataServiceVersion' => new Version(2, 0),
  271. 'MaxDataServiceVersion' => new Version(2, 0));
  272. $host = new DataServiceHost2($hostInfo);
  273. $dataService = new NorthWindDataService2();
  274. $dataService->setHost($host);
  275. $exceptionThrown = false;
  276. $uriProcessor = $dataService->handleRequest();
  277. $requestDescription = $uriProcessor->getRequestDescription();
  278. $this->assertTrue(!is_null($requestDescription));
  279. $internalOrderByInfo = $requestDescription->getInternalOrderByInfo();
  280. $this->assertTrue(!is_null($internalOrderByInfo));
  281. $object = $internalOrderByInfo->getDummyObject();
  282. $this->assertTrue(!is_null($object));
  283. $this->assertTrue($object instanceof Customer2);
  284. $host->getWebOperationContext()->resetWebContextInternal();
  285. } catch (\Exception $exception) {
  286. if ($host != null) {
  287. $host->getWebOperationContext()->resetWebContextInternal();
  288. }
  289. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  290. }
  291. }
  292. /**
  293. * Test request uri for row count ($count)
  294. *
  295. * $skip and $top options can be applied to $count request, this cause
  296. * processor to generate internalorderinfo.
  297. */
  298. public function testUriProcessorForCountRequest5()
  299. {
  300. try {
  301. $hostInfo = array('AbsoluteRequestUri' => new Url('http://localhost:8083/NorthWindDataService.svc/Customers/$count'),
  302. 'AbsoluteServiceUri' => new Url('http://localhost:8083/NorthWindDataService.svc'),
  303. 'QueryString' => '$skip=2&$top=4',
  304. 'DataServiceVersion' => new Version(2, 0),
  305. 'MaxDataServiceVersion' => new Version(2, 0));
  306. $host = new DataServiceHost2($hostInfo);
  307. $dataService = new NorthWindDataService2();
  308. $dataService->setHost($host);
  309. $exceptionThrown = false;
  310. $uriProcessor = $dataService->handleRequest();
  311. $requestDescription = $uriProcessor->getRequestDescription();
  312. $this->assertTrue(!is_null($requestDescription));
  313. $this->assertEquals($requestDescription->getTopCount(), 4);
  314. $this->assertEquals($requestDescription->getSkipCount(), 2);
  315. $internalOrderByInfo = $requestDescription->getInternalOrderByInfo();
  316. $this->assertTrue(!is_null($internalOrderByInfo));
  317. $object = $internalOrderByInfo->getDummyObject();
  318. $this->assertTrue(!is_null($object));
  319. $this->assertTrue($object instanceof Customer2);
  320. $host->getWebOperationContext()->resetWebContextInternal();
  321. } catch (\Exception $exception) {
  322. if ($host != null) {
  323. $host->getWebOperationContext()->resetWebContextInternal();
  324. }
  325. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  326. }
  327. }
  328. /**
  329. * Test request uri for row count ($count)
  330. *
  331. * $skip and/or $top options along with $orderby option cause internalOrderInfo
  332. * to include sorter functions using keys + paths in the $orderby clause
  333. */
  334. public function testUriProcessorForCountRequest6()
  335. {
  336. try {
  337. $hostInfo = array('AbsoluteRequestUri' => new Url('http://localhost:8083/NorthWindDataService.svc/Customers/$count'),
  338. 'AbsoluteServiceUri' => new Url('http://localhost:8083/NorthWindDataService.svc'),
  339. 'QueryString' => '$skip=2&$top=4&$orderby=Country',
  340. 'DataServiceVersion' => new Version(2, 0),
  341. 'MaxDataServiceVersion' => new Version(2, 0));
  342. $host = new DataServiceHost2($hostInfo);
  343. $dataService = new NorthWindDataService2();
  344. $dataService->setHost($host);
  345. $exceptionThrown = false;
  346. $uriProcessor = $dataService->handleRequest();
  347. $requestDescription = $uriProcessor->getRequestDescription();
  348. $this->assertTrue(!is_null($requestDescription));
  349. $this->assertEquals($requestDescription->getTopCount(), 4);
  350. $this->assertEquals($requestDescription->getSkipCount(), 2);
  351. $internalOrderByInfo = $requestDescription->getInternalOrderByInfo();
  352. $this->assertTrue(!is_null($internalOrderByInfo));
  353. $object = $internalOrderByInfo->getDummyObject();
  354. $this->assertTrue(!is_null($object));
  355. $this->assertTrue($object instanceof Customer2);
  356. $pathSegments = $internalOrderByInfo->getOrderByPathSegments();
  357. $this->assertTrue(!is_null($pathSegments));
  358. $this->assertTrue(is_array($pathSegments));
  359. $this->assertEquals(count($pathSegments), 3);
  360. $this->assertTrue($pathSegments[0] instanceof OrderByPathSegment);
  361. $subPathSegments = $pathSegments[0]->getSubPathSegments();
  362. $this->assertTrue(!is_null($subPathSegments));
  363. $this->assertTrue(is_array($subPathSegments));
  364. $this->assertEquals(count($subPathSegments), 1);
  365. $this->assertTrue($subPathSegments[0] instanceof OrderBySubPathSegment);
  366. $this->assertEquals($subPathSegments[0]->getName(), 'Country');
  367. $this->assertTrue($pathSegments[1] instanceof OrderByPathSegment);
  368. $subPathSegments = $pathSegments[1]->getSubPathSegments();
  369. $this->assertTrue(!is_null($subPathSegments));
  370. $this->assertTrue(is_array($subPathSegments));
  371. $this->assertEquals(count($subPathSegments), 1);
  372. $this->assertTrue($subPathSegments[0] instanceof OrderBySubPathSegment);
  373. $this->assertEquals($subPathSegments[0]->getName(), 'CustomerID');
  374. $this->assertTrue($pathSegments[2] instanceof OrderByPathSegment);
  375. $subPathSegments = $pathSegments[2]->getSubPathSegments();
  376. $this->assertTrue(!is_null($subPathSegments));
  377. $this->assertTrue(is_array($subPathSegments));
  378. $this->assertEquals(count($subPathSegments), 1);
  379. $this->assertTrue($subPathSegments[0] instanceof OrderBySubPathSegment);
  380. $this->assertEquals($subPathSegments[0]->getName(), 'CustomerGuid');
  381. $host->getWebOperationContext()->resetWebContextInternal();
  382. } catch (\Exception $exception) {
  383. if ($host != null) {
  384. $host->getWebOperationContext()->resetWebContextInternal();
  385. }
  386. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  387. }
  388. }
  389. /**
  390. * Test request uri for row count ($count)
  391. * $skiptoken is not applicable for $count request, as it requires
  392. * paging and paging is not applicable for $count request
  393. */
  394. public function testUriProcessorForCountRequest7()
  395. {
  396. try {
  397. $hostInfo = array('AbsoluteRequestUri' => new Url('http://localhost:8083/NorthWindDataService.svc/Customers/$count'),
  398. 'AbsoluteServiceUri' => new Url('http://localhost:8083/NorthWindDataService.svc'),
  399. 'QueryString' => '$top=1&$skiptoken=\'ALFKI\',guid\'05b242e752eb46bd8f0e6568b72cd9a5\'',
  400. 'DataServiceVersion' => new Version(2, 0),
  401. 'MaxDataServiceVersion' => new Version(2, 0));
  402. $host = new DataServiceHost2($hostInfo);
  403. $dataService = new NorthWindDataService2();
  404. $dataService->setHost($host);
  405. $exceptionThrown = false;
  406. try {
  407. $uriProcessor = $dataService->handleRequest();
  408. } catch (ODataException $odataException) {
  409. $exceptionThrown = true;
  410. $this->assertStringStartsWith("Query option \$skiptoken cannot be applied to the requested resource", $odataException->getMessage());
  411. }
  412. if (!$exceptionThrown) {
  413. $this->fail('An expected ODataException for applying $skiptoken on $count has not been thrown');
  414. }
  415. $host->getWebOperationContext()->resetWebContextInternal();
  416. } catch (\Exception $exception) {
  417. if ($host != null) {
  418. $host->getWebOperationContext()->resetWebContextInternal();
  419. }
  420. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  421. }
  422. }
  423. /**
  424. * Test request uri for row count ($count)
  425. *
  426. * $filter is applicable for $count segment.
  427. */
  428. public function testUriProcessorForCountRequest8()
  429. {
  430. try {
  431. $hostInfo = array('AbsoluteRequestUri' => new Url('http://localhost:8083/NorthWindDataService.svc/Customers/$count'),
  432. 'AbsoluteServiceUri' => new Url('http://localhost:8083/NorthWindDataService.svc'),
  433. 'QueryString' => '$filter=Country eq \'USA\'',
  434. 'DataServiceVersion' => new Version(2, 0),
  435. 'MaxDataServiceVersion' => new Version(2, 0));
  436. $host = new DataServiceHost2($hostInfo);
  437. $dataService = new NorthWindDataService2();
  438. $dataService->setHost($host);
  439. $uriProcessor = $dataService->handleRequest();
  440. $requestDescription = $uriProcessor->getRequestDescription();
  441. $this->assertTrue(!is_null($requestDescription));
  442. $internalFilterInfo = $requestDescription->getInternalFilterInfo();
  443. $this->assertTrue(!is_null($internalFilterInfo));
  444. $filterInfo = $internalFilterInfo->getFilterInfo();
  445. $this->assertTrue(!is_null($filterInfo));
  446. $this->assertTrue(is_null($filterInfo->getNavigationPropertiesUsed()));
  447. $filterFunction = $internalFilterInfo->getFilterFunction();
  448. $this->assertTrue(!is_null($filterFunction));
  449. $this->assertTrue($filterFunction instanceof AnonymousFunction);
  450. $host->getWebOperationContext()->resetWebContextInternal();
  451. } catch (\Exception $exception) {
  452. if ($host != null) {
  453. $host->getWebOperationContext()->resetWebContextInternal();
  454. }
  455. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  456. }
  457. }
  458. /**
  459. * Test request uri for row count ($count)
  460. *
  461. * $select and $expand options are applicable for $count segment.
  462. * but when we do query execution we will ignore them.
  463. */
  464. public function testUriProcessorForCountRequest9()
  465. {
  466. try {
  467. $hostInfo = array('AbsoluteRequestUri' => new Url('http://localhost:8083/NorthWindDataService.svc/Customers/$count'),
  468. 'AbsoluteServiceUri' => new Url('http://localhost:8083/NorthWindDataService.svc'),
  469. 'QueryString' => '$select=Country&$expand=Orders',
  470. 'DataServiceVersion' => new Version(2, 0),
  471. 'MaxDataServiceVersion' => new Version(2, 0));
  472. $host = new DataServiceHost2($hostInfo);
  473. $dataService = new NorthWindDataService2();
  474. $dataService->setHost($host);
  475. $uriProcessor = $dataService->handleRequest();
  476. $requestDescription = $uriProcessor->getRequestDescription();
  477. $this->assertTrue(!is_null($requestDescription));
  478. $projectionTreeRoot = $requestDescription->getRootProjectionNode();
  479. $this->assertTrue(!is_null($projectionTreeRoot));
  480. $this->assertTrue($projectionTreeRoot instanceof RootProjectionNode);
  481. //There will be one child node for 'Country', 'Orders' wont be included
  482. //as its not selected
  483. $childNodes = $projectionTreeRoot->getChildNodes();
  484. $this->assertTrue(!is_null($childNodes));
  485. $this->assertTrue(is_array($childNodes));
  486. $this->assertEquals(count($childNodes), 1);
  487. $this->assertTrue(array_key_exists('Country', $childNodes));
  488. $this->assertTrue($childNodes['Country'] instanceof ProjectionNode);
  489. $host->getWebOperationContext()->resetWebContextInternal();
  490. } catch (\Exception $exception) {
  491. if ($host != null) {
  492. $host->getWebOperationContext()->resetWebContextInternal();
  493. }
  494. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  495. }
  496. }
  497. /**
  498. * Test request uri for row count ($count)
  499. * $count with $inlinecount not allowed
  500. */
  501. public function testUriProcessorForCountWithInline()
  502. {
  503. try {
  504. $hostInfo = array('AbsoluteRequestUri' => new Url('http://localhost:8083/NorthWindDataService.svc/Customers/$count'),
  505. 'AbsoluteServiceUri' => new Url('http://localhost:8083/NorthWindDataService.svc'),
  506. 'QueryString' => '$inlinecount=allpages',
  507. 'DataServiceVersion' => new Version(2, 0),
  508. 'MaxDataServiceVersion' => new Version(2, 0));
  509. $host = new DataServiceHost2($hostInfo);
  510. $dataService = new NorthWindDataService2();
  511. $dataService->setHost($host);
  512. $exceptionThrown = false;
  513. try {
  514. $uriProcessor = $dataService->handleRequest();
  515. } catch (ODataException $odataException) {
  516. $exceptionThrown = true;
  517. $this->assertStringStartsWith("\$inlinecount cannot be applied to the resource segment \$count", $odataException->getMessage());
  518. }
  519. if (!$exceptionThrown) {
  520. $this->fail('An expected ODataException for applying $skiptoken on $count has not been thrown');
  521. }
  522. $host->getWebOperationContext()->resetWebContextInternal();
  523. } catch (\Exception $exception) {
  524. if ($host != null) {
  525. $host->getWebOperationContext()->resetWebContextInternal();
  526. }
  527. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  528. }
  529. }
  530. /**
  531. * If paging is enabled for a resource set, then the uri
  532. * processor should generate orderinfo irrespective of
  533. * whether $top or $orderby is specified or not.
  534. *
  535. * Request DataServiceVersion => 1.0
  536. * Request MaxDataServiceVersion => 2.0
  537. */
  538. public function testUriProcessorForResourcePageInfo1()
  539. {
  540. try {
  541. //Test for generation of orderinfo for resource set
  542. //with request DataServiceVersion 1.0
  543. $hostInfo = array('AbsoluteRequestUri' => new Url('http://localhost:8083/NorthWindDataService.svc/Customers'),
  544. 'AbsoluteServiceUri' => new Url('http://localhost:8083/NorthWindDataService.svc'),
  545. 'QueryString' => null,
  546. 'DataServiceVersion' => new Version(1, 0),
  547. 'MaxDataServiceVersion' => new Version(2, 0));
  548. $host = new DataServiceHost2($hostInfo);
  549. $dataService = new NorthWindDataService2();
  550. $dataService->setHost($host);
  551. $uriProcessor = $dataService->handleRequest();
  552. $requestDescription = $uriProcessor->getRequestDescription();
  553. $this->assertTrue(!is_null($requestDescription));
  554. //Page size is 5, so take count is 5
  555. $this->assertEquals($requestDescription->getTopCount(), 5);
  556. //order info is required for pagination
  557. $internalOrderByInfo = $requestDescription->getInternalOrderByInfo();
  558. $this->assertTrue(!is_null($internalOrderByInfo));
  559. $pathSegments = $internalOrderByInfo->getOrderByPathSegments();
  560. $this->assertTrue(!is_null($pathSegments));
  561. $this->assertTrue(is_array($pathSegments));
  562. //Customer has two keys
  563. $this->assertEquals(count($pathSegments), 2);
  564. $this->assertTrue($pathSegments[0] instanceof OrderByPathSegment);
  565. $subPathSegments = $pathSegments[0]->getSubPathSegments();
  566. $this->assertTrue(!is_null($subPathSegments));
  567. $this->assertTrue(is_array($subPathSegments));
  568. $this->assertEquals(count($subPathSegments), 1);
  569. $this->assertTrue($subPathSegments[0] instanceof OrderBySubPathSegment);
  570. $this->assertEquals($subPathSegments[0]->getName(), 'CustomerID');
  571. $this->assertTrue($pathSegments[1] instanceof OrderByPathSegment);
  572. $subPathSegments = $pathSegments[1]->getSubPathSegments();
  573. $this->assertTrue(!is_null($subPathSegments));
  574. $this->assertTrue(is_array($subPathSegments));
  575. $this->assertEquals(count($subPathSegments), 1);
  576. $this->assertTrue($subPathSegments[0] instanceof OrderBySubPathSegment);
  577. $this->assertEquals($subPathSegments[0]->getName(), 'CustomerGuid');
  578. $host->getWebOperationContext()->resetWebContextInternal();
  579. } catch (\Exception $exception) {
  580. if ($host != null) {
  581. $host->getWebOperationContext()->resetWebContextInternal();
  582. }
  583. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  584. }
  585. }
  586. /**
  587. * If paging is enabled for a resource set, then the uri
  588. * processor should generate orderinfo irrespective of
  589. * whether $top or $orderby is specified or not.
  590. *
  591. * Request DataServiceVersion => 1.0
  592. * Request MaxDataServiceVersion => 1.0
  593. *
  594. * This will fail as paging requires version 2.0 or above
  595. */
  596. public function testUriProcessorForResourcePageInfo2()
  597. {
  598. try {
  599. //Test for generation of orderinfo for resource set
  600. //with request DataServiceVersion 1.0
  601. $hostInfo = array('AbsoluteRequestUri' => new Url('http://localhost:8083/NorthWindDataService.svc/Customers'),
  602. 'AbsoluteServiceUri' => new Url('http://localhost:8083/NorthWindDataService.svc'),
  603. 'QueryString' => null,
  604. 'DataServiceVersion' => new Version(1, 0),
  605. 'MaxDataServiceVersion' => new Version(1, 0));
  606. $host = new DataServiceHost2($hostInfo);
  607. $dataService = new NorthWindDataService2();
  608. $dataService->setHost($host);
  609. $exceptionThrown = false;
  610. try {
  611. $uriProcessor = $dataService->handleRequest();
  612. } catch (ODataException $odataException) {
  613. $exceptionThrown = true;
  614. $this->assertStringStartsWith("Request version '1.0' is not supported for the request payload. The only supported version is '2.0'", $odataException->getMessage());
  615. }
  616. if (!$exceptionThrown) {
  617. $this->fail('An expected ODataException due to capability negotiation has not been thrown (paged result but client\'s max supportedd version is 1.0)');
  618. }
  619. $host->getWebOperationContext()->resetWebContextInternal();
  620. } catch (\Exception $exception) {
  621. if ($host != null) {
  622. $host->getWebOperationContext()->resetWebContextInternal();
  623. }
  624. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  625. }
  626. }
  627. /**
  628. * Paging is enabled only for resource set, so with resource set
  629. * reference there will not be any paginginfo.
  630. */
  631. public function testUriProcessorForResourcePageInfo3()
  632. {
  633. try {
  634. //Test for generation of orderinfo for resource set
  635. //with request DataServiceVersion 1.0
  636. $hostInfo = array('AbsoluteRequestUri' => new Url('http://localhost:8083/NorthWindDataService.svc/Orders(123)'),
  637. 'AbsoluteServiceUri' => new Url('http://localhost:8083/NorthWindDataService.svc'),
  638. 'QueryString' => null,
  639. 'DataServiceVersion' => new Version(1, 0),
  640. 'MaxDataServiceVersion' => new Version(2, 0));
  641. $host = new DataServiceHost2($hostInfo);
  642. $dataService = new NorthWindDataService2();
  643. $dataService->setHost($host);
  644. $uriProcessor = $dataService->handleRequest();
  645. $requestDescription = $uriProcessor->getRequestDescription();
  646. $this->assertTrue(!is_null($requestDescription));
  647. //Page is not appliable for single resouce
  648. $this->assertEquals($requestDescription->getTopCount(), null);
  649. //order info wont be generated as resource is not applicable for pagination
  650. $internalOrderByInfo = $requestDescription->getInternalOrderByInfo();
  651. $this->assertTrue(is_null($internalOrderByInfo));
  652. $host->getWebOperationContext()->resetWebContextInternal();
  653. } catch (\Exception $exception) {
  654. if ($host != null) {
  655. $host->getWebOperationContext()->resetWebContextInternal();
  656. }
  657. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  658. }
  659. }
  660. /**
  661. * If paging is enabled for a resource set, then $link request for that resource set
  662. * will also paged
  663. * e.g. http://host/service.svc/Customers('A')/$links/Orders
  664. * here if paging is enabled for Orders then prcoessor must generate orderbyinfo for
  665. * this.
  666. */
  667. public function testUriProcessorForResourcePageInfo4()
  668. {
  669. try {
  670. //Test for generation of orderinfo for resource set in $links query
  671. $baseUri = 'http://localhost:8083/NorthWindDataService.svc/';
  672. $resourcePath = 'Customers(CustomerID=\'ALFKI\', CustomerGuid=guid\'05b242e752eb46bd8f0e6568b72cd9a5\')/$links/Orders';
  673. $hostInfo = array('AbsoluteRequestUri' => new Url($baseUri . $resourcePath),
  674. 'AbsoluteServiceUri' => new Url($baseUri),
  675. 'QueryString' => null,
  676. 'DataServiceVersion' => new Version(1, 0),
  677. 'MaxDataServiceVersion' => new Version(2, 0));
  678. $host = new DataServiceHost2($hostInfo);
  679. $dataService = new NorthWindDataService2();
  680. $dataService->setHost($host);
  681. $uriProcessor = $dataService->handleRequest();
  682. $requestDescription = $uriProcessor->getRequestDescription();
  683. $this->assertTrue(!is_null($requestDescription));
  684. //Page size is 5, so take count is 5
  685. $this->assertEquals($requestDescription->getTopCount(), 5);
  686. //order info is required for pagination
  687. $internalOrderByInfo = $requestDescription->getInternalOrderByInfo();
  688. $this->assertTrue(!is_null($internalOrderByInfo));
  689. $pathSegments = $internalOrderByInfo->getOrderByPathSegments();
  690. $this->assertTrue(!is_null($pathSegments));
  691. $this->assertTrue(is_array($pathSegments));
  692. //Order has one key
  693. $this->assertEquals(count($pathSegments), 1);
  694. $this->assertTrue($pathSegments[0] instanceof OrderByPathSegment);
  695. $subPathSegments = $pathSegments[0]->getSubPathSegments();
  696. $this->assertTrue(!is_null($subPathSegments));
  697. $this->assertTrue(is_array($subPathSegments));
  698. $this->assertEquals(count($subPathSegments), 1);
  699. $this->assertTrue($subPathSegments[0] instanceof OrderBySubPathSegment);
  700. $this->assertEquals($subPathSegments[0]->getName(), 'OrderID');
  701. $host->getWebOperationContext()->resetWebContextInternal();
  702. } catch (\Exception $exception) {
  703. if ($host != null) {
  704. $host->getWebOperationContext()->resetWebContextInternal();
  705. }
  706. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  707. }
  708. }
  709. /**
  710. * $orderby option can be applied to $links resource set
  711. */
  712. public function testUriProcessorForLinksResourceSet1()
  713. {
  714. try {
  715. $baseUri = 'http://localhost:8083/NorthWindDataService.svc/';
  716. $resourcePath = 'Customers(CustomerID=\'ALFKI\', CustomerGuid=guid\'05b242e752eb46bd8f0e6568b72cd9a5\')/$links/Orders';
  717. $hostInfo = array('AbsoluteRequestUri' => new Url($baseUri . $resourcePath),
  718. 'AbsoluteServiceUri' => new Url($baseUri),
  719. 'QueryString' => '$orderby=ShipName asc, OrderDate desc',
  720. 'DataServiceVersion' => new Version(2, 0),
  721. 'MaxDataServiceVersion' => new Version(2, 0));
  722. $host = new DataServiceHost2($hostInfo);
  723. $dataService = new NorthWindDataService2();
  724. $dataService->setHost($host);
  725. $uriProcessor = $dataService->handleRequest();
  726. $requestDescription = $uriProcessor->getRequestDescription();
  727. $this->assertTrue(!is_null($requestDescription));
  728. $this->assertEquals($requestDescription->isSingleResult(), false);
  729. //Page size is 5, so take count is 5 means you will get only 5 links for a request
  730. $this->assertEquals($requestDescription->getTopCount(), 5);
  731. //Paging requires ordering, the result should be ordered like
  732. //Note: additional ordering constraint
  733. //
  734. //SELECT links(d.orderID) FROM Customers JOIN Orders WHERE CustomerID='ALFKI' AND
  735. //CustomerGuid=guid'05b242e752eb46bd8f0e6568b72cd9a5' ORDER BY
  736. //d.ShipName ASC, d.OrderDate DESC, d.OrderID ASC
  737. $internalOrderByInfo = $requestDescription->getInternalOrderByInfo();
  738. $this->assertTrue(!is_null($internalOrderByInfo));
  739. $pathSegments = $internalOrderByInfo->getOrderByPathSegments();
  740. $this->assertTrue(!is_null($pathSegments));
  741. $this->assertTrue(is_array($pathSegments));
  742. $this->assertEquals(count($pathSegments), 3);
  743. $this->assertTrue($pathSegments[0] instanceof OrderByPathSegment);
  744. $subPathSegments = $pathSegments[0]->getSubPathSegments();
  745. $this->assertTrue($pathSegments[0]->isAscending());
  746. $this->assertTrue(!is_null($subPathSegments));
  747. $this->assertTrue(is_array($subPathSegments));
  748. $this->assertEquals(count($subPathSegments), 1);
  749. $this->assertTrue($subPathSegments[0] instanceof OrderBySubPathSegment);
  750. $this->assertEquals($subPathSegments[0]->getName(), 'ShipName');
  751. $this->assertTrue($pathSegments[1] instanceof OrderByPathSegment);
  752. $this->assertFalse($pathSegments[1]->isAscending());
  753. $subPathSegments = $pathSegments[1]->getSubPathSegments();
  754. $this->assertTrue(!is_null($subPathSegments));
  755. $this->assertTrue(is_array($subPathSegments));
  756. $this->assertEquals(count($subPathSegments), 1);
  757. $this->assertTrue($subPathSegments[0] instanceof OrderBySubPathSegment);
  758. $this->assertEquals($subPathSegments[0]->getName(), 'OrderDate');
  759. $this->assertTrue($pathSegments[2] instanceof OrderByPathSegment);
  760. $this->assertTrue($pathSegments[2]->isAscending());
  761. $subPathSegments = $pathSegments[2]->getSubPathSegments();
  762. $this->assertTrue(!is_null($subPathSegments));
  763. $this->assertTrue(is_array($subPathSegments));
  764. $this->assertEquals(count($subPathSegments), 1);
  765. $this->assertTrue($subPathSegments[0] instanceof OrderBySubPathSegment);
  766. $this->assertEquals($subPathSegments[0]->getName(), 'OrderID');
  767. $host->getWebOperationContext()->resetWebContextInternal();
  768. } catch (\Exception $exception) {
  769. if ($host != null) {
  770. $host->getWebOperationContext()->resetWebContextInternal();
  771. }
  772. $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
  773. }
  774. }
  775. /**
  776. * $skiptoken option can be applied to $links resource set
  777. */
  778. public function testUriProcessorForLinksResourceSet2()
  779. {
  780. try {
  781. //Test with skiptoken that corrosponds to default ordering key
  782. $baseUri = 'http://localhost:8083/NorthWindDataService.svc/';
  783. $resourcePath = 'Customers(CustomerID=\'ALFKI\', CustomerGuid=guid\'05b242e752eb46bd8f0e6568b72cd9a5\')/$links/Orders';
  784. $hostInfo = array('AbsoluteRequestUri' => new Url($baseUri . $resourcePath),
  785. 'AbsoluteServiceUri' => new Url($baseUri),
  786. 'QueryString' => '$skiptoken=123',
  787. 'DataServiceVersion' => new Version(2, 0),
  788. 'MaxDataServiceVersion' => new Version(2, 0));
  789. $host = new DataServiceHost2($hostInfo);
  790. $dataService = new NorthWindDataService2();
  791. $dataService->setHost($host);
  792. $uriProcessor = $dataService->handleRequest();
  793. $requestDescription = $uriProcessor->getRequestDescription();
  794. $this->assertTrue(!is_null($requestDescription));
  795. $this->assertEquals($requestDescription->isSingleResult(), false);
  796. //Page size is 5, so take count is 5 means you will get only 5 links for a request
  797. $this->assertEquals($requestDescription->getTopCount(), 5);
  798. //paging requires ordering
  799. $internalOrderByInfo = $requestDescription->getInternalOrderByInfo();
  800. $this->assertTrue(!is_null($internalOrderByInfo));
  801. $pathSegments = $internalOrderByInfo->getOrderByPathSegments();
  802. $this->assertTrue(!is_null($pathSegments));
  803. $this->assertTrue(is_array($pathSegments));
  804. $this->assertEquals(count($pathSegments), 1);
  805. $this->assertTrue($pathSegments[0] instanceof OrderByPathSegment);
  806. $subPathSegments = $pathSegments[0]->getSubPathSegments();
  807. $this->assertTrue($pathSegments[0]->isAscending());
  808. $this->assertTrue(!is_null($subPathSegments));
  809. $this->assertTrue(is_array($subPathSegments));
  810. $this->assertEquals(count($subPathSegments), 1);
  811. $this->assertTrue($subPathSegments[0] instanceof OrderBySubPathSegment);
  812. $this->assertEquals($subPathSegments[0]->getName(), 'OrderID');
  813. //check the skiptoken details
  814. $internalSkiptokenInfo = $requestDescription->getInternalSkipTokenInfo();
  815. $this->assertTrue(!is_null($internalSkiptokenInfo));
  816. $this->assertTrue($internalSkiptokenInfo instanceof InternalSkipTokenInfo);
  817. $skipTokenInfo = $internalSkiptokenInfo->getSkipTokenInfo();
  818. $this->assertTrue(!is_null($skipTokenInfo));
  819. $this->assertTrue($skipTokenInfo instanceof SkipTokenInfo);
  820. $orderByValuesInSkipToken = $skipTokenInfo->getOrderByKeysInToken();
  821. $this->assertTrue(!is_null($orderByValuesInSkipToken));
  822. $this->assertTrue(is_array($orderByValuesInSkipToken));
  823. $this->assertEquals(count($orderByValuesInSkipToken), 1);
  824. $this->assertTrue(!is_null($orderByValuesInSkipToken[0]));
  825. $this->assertTrue(is_array($orderByValuesInSkipToken[0]));
  826. $this->assertEquals(count($orderByValuesInSkipToken[0]), 2);
  827. $this->assertEquals($orderByValuesInSkipToken[0][0], 123);
  828. $this->assertTrue(is_object($orderByValuesInSkipToken[0][1]));
  829. $this->assertTrue($orderByValuesInSkipToken[0][1] instanceof Int32);
  830. $host->getWebOperationContext()->resetWebContextInternal();
  831. //Test with skiptoken that corrosponds to explict ordering keys
  832. $baseUri = 'http://localhost:8083/NorthWindDataService.svc/';
  833. $resourcePath = 'Customers(CustomerID=\'ALFKI\', CustomerGuid=guid\'05b242e752eb46bd8f0e6568b72cd9a5\')/$links/Orders';
  834. $hostInfo = array('AbsoluteRequestUri' => new Url($baseUri . $resourcePath),
  835. 'AbsoluteServiceUri' => new Url($baseUri),
  836. 'QueryString' => '$orderby=OrderID asc, OrderDate desc&$skiptoken=123, datetime\'2000-11-11\'',
  837. 'DataServiceVersion' => new Version(2, 0),
  838. 'MaxDataServiceVersion' => new Version(2, 0));
  839. $host = new DataServiceHost2($hostInfo);
  840. $dataService = new NorthWindDataService2();
  841. $dataService->setHost($host);
  842. $uriProcessor = $dataService->handleRequest();
  843. $requestDescription = $uriProcessor->getRequestDescription();
  844. $this->assertTrue(!is_null($requestDescription));
  845. $this->assertEquals($requestDescription->isSingleResult(), false);
  846. //Page size is 5, so take count is 5 means you will get only 5 links for a request
  847. $this->assertEquals($requestDescription->getTopCount(), 5);
  848. //paging requires ordering
  849. $internalOrderByInfo = $requestDescription->getInternalOrderByInfo();
  850. $this->assertTrue(!is_null($internalOrderByInfo));
  851. $pathSegments = $internalOrderByInfo->getOrderByPathSegments();
  852. $this->assertTrue(!is_null($pathSegments));
  853. $this->assertTrue(is_array($pathSegments));
  854. $this->assertEquals(count($pathSegments), 2);
  855. $this->assertTrue($pathSegments[0] instanceof OrderByPathSegment);
  856. $subPathSegments = $pathSegments[0]->getSubPathSegments();
  857. $this->assertTrue($pathSegments[0]->isAscending());
  858. $this->assertTrue(!is_null($subPathSegments));
  859. $this->assertTrue(is_array($subPathSegments));
  860. $this->assertEquals(count($subPathSegments), 1);
  861. $this->assertTrue($subPathSegments[0

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