FetcherBase.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
  4. *
  5. * @license GNU AGPL version 3 or any later version
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Affero General Public License as
  9. * published by the Free Software Foundation, either version 3 of the
  10. * License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. */
  21. namespace Test\App\AppStore\Fetcher;
  22. use OC\App\AppStore\Fetcher\Fetcher;
  23. use OCP\AppFramework\Utility\ITimeFactory;
  24. use OCP\Files\IAppData;
  25. use OCP\Files\NotFoundException;
  26. use OCP\Files\SimpleFS\ISimpleFile;
  27. use OCP\Files\SimpleFS\ISimpleFolder;
  28. use OCP\Http\Client\IClient;
  29. use OCP\Http\Client\IClientService;
  30. use OCP\Http\Client\IResponse;
  31. use OCP\IConfig;
  32. use Test\TestCase;
  33. abstract class FetcherBase extends TestCase {
  34. /** @var IAppData|\PHPUnit_Framework_MockObject_MockObject */
  35. protected $appData;
  36. /** @var IClientService|\PHPUnit_Framework_MockObject_MockObject */
  37. protected $clientService;
  38. /** @var ITimeFactory|\PHPUnit_Framework_MockObject_MockObject */
  39. protected $timeFactory;
  40. /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
  41. protected $config;
  42. /** @var Fetcher */
  43. protected $fetcher;
  44. /** @var string */
  45. protected $fileName;
  46. /** @var string */
  47. protected $endpoint;
  48. public function setUp() {
  49. parent::setUp();
  50. $this->appData = $this->createMock(IAppData::class);
  51. $this->clientService = $this->createMock(IClientService::class);
  52. $this->timeFactory = $this->createMock(ITimeFactory::class);
  53. $this->config = $this->createMock(IConfig::class);
  54. }
  55. public function testGetWithAlreadyExistingFileAndUpToDateTimestampAndVersion() {
  56. $this->config
  57. ->expects($this->at(0))
  58. ->method('getSystemValue')
  59. ->with('appstoreenabled', true)
  60. ->willReturn(true);
  61. $this->config
  62. ->expects($this->at(1))
  63. ->method('getSystemValue')
  64. ->with(
  65. $this->equalTo('version'),
  66. $this->anything()
  67. )->willReturn('11.0.0.2');
  68. $folder = $this->createMock(ISimpleFolder::class);
  69. $file = $this->createMock(ISimpleFile::class);
  70. $this->appData
  71. ->expects($this->once())
  72. ->method('getFolder')
  73. ->with('/')
  74. ->willReturn($folder);
  75. $folder
  76. ->expects($this->once())
  77. ->method('getFile')
  78. ->with($this->fileName)
  79. ->willReturn($file);
  80. $file
  81. ->expects($this->once())
  82. ->method('getContent')
  83. ->willReturn('{"timestamp":1200,"data":[{"id":"MyApp"}],"ncversion":"11.0.0.2"}');
  84. $this->timeFactory
  85. ->expects($this->once())
  86. ->method('getTime')
  87. ->willReturn(1499);
  88. $expected = [
  89. [
  90. 'id' => 'MyApp',
  91. ],
  92. ];
  93. $this->assertSame($expected, $this->fetcher->get());
  94. }
  95. public function testGetWithNotExistingFileAndUpToDateTimestampAndVersion() {
  96. $this->config
  97. ->expects($this->at(0))
  98. ->method('getSystemValue')
  99. ->with('appstoreenabled', true)
  100. ->willReturn(true);
  101. $this->config
  102. ->expects($this->at(1))
  103. ->method('getSystemValue')
  104. ->with('appstoreenabled', true)
  105. ->willReturn(true);
  106. $this->config
  107. ->expects($this->at(2))
  108. ->method('getSystemValue')
  109. ->with(
  110. $this->equalTo('version'),
  111. $this->anything()
  112. )->willReturn('11.0.0.2');
  113. $folder = $this->createMock(ISimpleFolder::class);
  114. $file = $this->createMock(ISimpleFile::class);
  115. $this->appData
  116. ->expects($this->once())
  117. ->method('getFolder')
  118. ->with('/')
  119. ->willReturn($folder);
  120. $folder
  121. ->expects($this->at(0))
  122. ->method('getFile')
  123. ->with($this->fileName)
  124. ->willThrowException(new NotFoundException());
  125. $folder
  126. ->expects($this->at(1))
  127. ->method('newFile')
  128. ->with($this->fileName)
  129. ->willReturn($file);
  130. $client = $this->createMock(IClient::class);
  131. $this->clientService
  132. ->expects($this->once())
  133. ->method('newClient')
  134. ->willReturn($client);
  135. $response = $this->createMock(IResponse::class);
  136. $client
  137. ->expects($this->once())
  138. ->method('get')
  139. ->with($this->endpoint)
  140. ->willReturn($response);
  141. $response
  142. ->expects($this->once())
  143. ->method('getBody')
  144. ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]');
  145. $response->method('getHeader')
  146. ->with($this->equalTo('ETag'))
  147. ->willReturn('"myETag"');
  148. $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1502,"ncversion":"11.0.0.2","ETag":"\"myETag\""}';
  149. $file
  150. ->expects($this->at(0))
  151. ->method('putContent')
  152. ->with($fileData);
  153. $file
  154. ->expects($this->at(1))
  155. ->method('getContent')
  156. ->willReturn($fileData);
  157. $this->timeFactory
  158. ->expects($this->at(0))
  159. ->method('getTime')
  160. ->willReturn(1502);
  161. $expected = [
  162. [
  163. 'id' => 'MyNewApp',
  164. 'foo' => 'foo',
  165. ],
  166. [
  167. 'id' => 'bar',
  168. ],
  169. ];
  170. $this->assertSame($expected, $this->fetcher->get());
  171. }
  172. public function testGetWithAlreadyExistingFileAndOutdatedTimestamp() {
  173. $this->config
  174. ->expects($this->at(0))
  175. ->method('getSystemValue')
  176. ->with('appstoreenabled', true)
  177. ->willReturn(true);
  178. $this->config
  179. ->expects($this->at(1))
  180. ->method('getSystemValue')
  181. ->with('appstoreenabled', true)
  182. ->willReturn(true);
  183. $this->config
  184. ->expects($this->at(2))
  185. ->method('getSystemValue')
  186. ->with(
  187. $this->equalTo('version'),
  188. $this->anything()
  189. )->willReturn('11.0.0.2');
  190. $folder = $this->createMock(ISimpleFolder::class);
  191. $file = $this->createMock(ISimpleFile::class);
  192. $this->appData
  193. ->expects($this->once())
  194. ->method('getFolder')
  195. ->with('/')
  196. ->willReturn($folder);
  197. $folder
  198. ->expects($this->once())
  199. ->method('getFile')
  200. ->with($this->fileName)
  201. ->willReturn($file);
  202. $file
  203. ->expects($this->at(0))
  204. ->method('getContent')
  205. ->willReturn('{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}},"ncversion":"11.0.0.2"}');
  206. $this->timeFactory
  207. ->expects($this->at(0))
  208. ->method('getTime')
  209. ->willReturn(1501);
  210. $client = $this->createMock(IClient::class);
  211. $this->clientService
  212. ->expects($this->once())
  213. ->method('newClient')
  214. ->willReturn($client);
  215. $response = $this->createMock(IResponse::class);
  216. $client
  217. ->expects($this->once())
  218. ->method('get')
  219. ->with($this->endpoint)
  220. ->willReturn($response);
  221. $response
  222. ->expects($this->once())
  223. ->method('getBody')
  224. ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]');
  225. $response->method('getHeader')
  226. ->with($this->equalTo('ETag'))
  227. ->willReturn('"myETag"');
  228. $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1502,"ncversion":"11.0.0.2","ETag":"\"myETag\""}';
  229. $file
  230. ->expects($this->at(1))
  231. ->method('putContent')
  232. ->with($fileData);
  233. $file
  234. ->expects($this->at(2))
  235. ->method('getContent')
  236. ->willReturn($fileData);
  237. $this->timeFactory
  238. ->expects($this->at(1))
  239. ->method('getTime')
  240. ->willReturn(1502);
  241. $expected = [
  242. [
  243. 'id' => 'MyNewApp',
  244. 'foo' => 'foo',
  245. ],
  246. [
  247. 'id' => 'bar',
  248. ],
  249. ];
  250. $this->assertSame($expected, $this->fetcher->get());
  251. }
  252. public function testGetWithAlreadyExistingFileAndNoVersion() {
  253. $this->config
  254. ->expects($this->at(0))
  255. ->method('getSystemValue')
  256. ->with('appstoreenabled', true)
  257. ->willReturn(true);
  258. $this->config
  259. ->expects($this->at(1))
  260. ->method('getSystemValue')
  261. ->with('appstoreenabled', true)
  262. ->willReturn(true);
  263. $this->config
  264. ->expects($this->at(2))
  265. ->method('getSystemValue')
  266. ->with(
  267. $this->equalTo('version'),
  268. $this->anything()
  269. )->willReturn('11.0.0.2');
  270. $folder = $this->createMock(ISimpleFolder::class);
  271. $file = $this->createMock(ISimpleFile::class);
  272. $this->appData
  273. ->expects($this->once())
  274. ->method('getFolder')
  275. ->with('/')
  276. ->willReturn($folder);
  277. $folder
  278. ->expects($this->once())
  279. ->method('getFile')
  280. ->with($this->fileName)
  281. ->willReturn($file);
  282. $file
  283. ->expects($this->at(0))
  284. ->method('getContent')
  285. ->willReturn('{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}}');
  286. $this->timeFactory
  287. ->expects($this->at(0))
  288. ->method('getTime')
  289. ->willReturn(1201);
  290. $client = $this->createMock(IClient::class);
  291. $this->clientService
  292. ->expects($this->once())
  293. ->method('newClient')
  294. ->willReturn($client);
  295. $response = $this->createMock(IResponse::class);
  296. $client
  297. ->expects($this->once())
  298. ->method('get')
  299. ->with($this->endpoint)
  300. ->willReturn($response);
  301. $response
  302. ->expects($this->once())
  303. ->method('getBody')
  304. ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]');
  305. $response->method('getHeader')
  306. ->with($this->equalTo('ETag'))
  307. ->willReturn('"myETag"');
  308. $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1201,"ncversion":"11.0.0.2","ETag":"\"myETag\""}';
  309. $file
  310. ->expects($this->at(1))
  311. ->method('putContent')
  312. ->with($fileData);
  313. $file
  314. ->expects($this->at(2))
  315. ->method('getContent')
  316. ->willReturn($fileData);
  317. $expected = [
  318. [
  319. 'id' => 'MyNewApp',
  320. 'foo' => 'foo',
  321. ],
  322. [
  323. 'id' => 'bar',
  324. ],
  325. ];
  326. $this->assertSame($expected, $this->fetcher->get());
  327. }
  328. public function testGetWithAlreadyExistingFileAndOutdatedVersion() {
  329. $this->config
  330. ->expects($this->at(0))
  331. ->method('getSystemValue')
  332. ->with('appstoreenabled', true)
  333. ->willReturn(true);
  334. $this->config
  335. ->expects($this->at(1))
  336. ->method('getSystemValue')
  337. ->with('appstoreenabled', true)
  338. ->willReturn(true);
  339. $this->config
  340. ->expects($this->at(2))
  341. ->method('getSystemValue')
  342. ->with(
  343. $this->equalTo('version'),
  344. $this->anything()
  345. )->willReturn('11.0.0.2');
  346. $folder = $this->createMock(ISimpleFolder::class);
  347. $file = $this->createMock(ISimpleFile::class);
  348. $this->appData
  349. ->expects($this->once())
  350. ->method('getFolder')
  351. ->with('/')
  352. ->willReturn($folder);
  353. $folder
  354. ->expects($this->once())
  355. ->method('getFile')
  356. ->with($this->fileName)
  357. ->willReturn($file);
  358. $file
  359. ->expects($this->at(0))
  360. ->method('getContent')
  361. ->willReturn('{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}},"ncversion":"11.0.0.1"');
  362. $this->timeFactory
  363. ->method('getTime')
  364. ->willReturn(1201);
  365. $client = $this->createMock(IClient::class);
  366. $this->clientService
  367. ->expects($this->once())
  368. ->method('newClient')
  369. ->willReturn($client);
  370. $response = $this->createMock(IResponse::class);
  371. $client
  372. ->expects($this->once())
  373. ->method('get')
  374. ->with($this->endpoint)
  375. ->willReturn($response);
  376. $response
  377. ->expects($this->once())
  378. ->method('getBody')
  379. ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]');
  380. $response->method('getHeader')
  381. ->with($this->equalTo('ETag'))
  382. ->willReturn('"myETag"');
  383. $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1201,"ncversion":"11.0.0.2","ETag":"\"myETag\""}';
  384. $file
  385. ->expects($this->at(1))
  386. ->method('putContent')
  387. ->with($fileData);
  388. $file
  389. ->expects($this->at(2))
  390. ->method('getContent')
  391. ->willReturn($fileData);
  392. $expected = [
  393. [
  394. 'id' => 'MyNewApp',
  395. 'foo' => 'foo',
  396. ],
  397. [
  398. 'id' => 'bar',
  399. ],
  400. ];
  401. $this->assertSame($expected, $this->fetcher->get());
  402. }
  403. public function testGetWithExceptionInClient() {
  404. $this->config
  405. ->expects($this->at(0))
  406. ->method('getSystemValue')
  407. ->with('appstoreenabled', true)
  408. ->willReturn(true);
  409. $this->config
  410. ->expects($this->at(1))
  411. ->method('getSystemValue')
  412. ->with('appstoreenabled', true)
  413. ->willReturn(true);
  414. $folder = $this->createMock(ISimpleFolder::class);
  415. $file = $this->createMock(ISimpleFile::class);
  416. $this->appData
  417. ->expects($this->once())
  418. ->method('getFolder')
  419. ->with('/')
  420. ->willReturn($folder);
  421. $folder
  422. ->expects($this->once())
  423. ->method('getFile')
  424. ->with($this->fileName)
  425. ->willReturn($file);
  426. $file
  427. ->expects($this->at(0))
  428. ->method('getContent')
  429. ->willReturn('{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}}}');
  430. $this->timeFactory
  431. ->expects($this->at(0))
  432. ->method('getTime')
  433. ->willReturn(1501);
  434. $client = $this->createMock(IClient::class);
  435. $this->clientService
  436. ->expects($this->once())
  437. ->method('newClient')
  438. ->willReturn($client);
  439. $client
  440. ->expects($this->once())
  441. ->method('get')
  442. ->with($this->endpoint)
  443. ->willThrowException(new \Exception());
  444. $this->assertSame([], $this->fetcher->get());
  445. }
  446. public function testGetMatchingETag() {
  447. $this->config
  448. ->expects($this->at(0))
  449. ->method('getSystemValue')
  450. ->with('appstoreenabled', true)
  451. ->willReturn(true);
  452. $this->config
  453. ->expects($this->at(1))
  454. ->method('getSystemValue')
  455. ->with('appstoreenabled', true)
  456. ->willReturn(true);
  457. $this->config
  458. ->expects($this->at(2))
  459. ->method('getSystemValue')
  460. ->with(
  461. $this->equalTo('version'),
  462. $this->anything()
  463. )->willReturn('11.0.0.2');
  464. $folder = $this->createMock(ISimpleFolder::class);
  465. $file = $this->createMock(ISimpleFile::class);
  466. $this->appData
  467. ->expects($this->once())
  468. ->method('getFolder')
  469. ->with('/')
  470. ->willReturn($folder);
  471. $folder
  472. ->expects($this->once())
  473. ->method('getFile')
  474. ->with($this->fileName)
  475. ->willReturn($file);
  476. $origData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}';
  477. $file
  478. ->expects($this->at(0))
  479. ->method('getContent')
  480. ->willReturn($origData);
  481. $this->timeFactory
  482. ->expects($this->at(0))
  483. ->method('getTime')
  484. ->willReturn(1501);
  485. $this->timeFactory
  486. ->expects($this->at(1))
  487. ->method('getTime')
  488. ->willReturn(1502);
  489. $client = $this->createMock(IClient::class);
  490. $this->clientService
  491. ->expects($this->once())
  492. ->method('newClient')
  493. ->willReturn($client);
  494. $response = $this->createMock(IResponse::class);
  495. $client
  496. ->expects($this->once())
  497. ->method('get')
  498. ->with(
  499. $this->equalTo($this->endpoint),
  500. $this->equalTo([
  501. 'headers' => [
  502. 'If-None-Match' => '"myETag"'
  503. ]
  504. ])
  505. )->willReturn($response);
  506. $response->method('getStatusCode')
  507. ->willReturn(304);
  508. $newData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1502,"ncversion":"11.0.0.2","ETag":"\"myETag\""}';
  509. $file
  510. ->expects($this->at(1))
  511. ->method('putContent')
  512. ->with($newData);
  513. $file
  514. ->expects($this->at(2))
  515. ->method('getContent')
  516. ->willReturn($newData);
  517. $expected = [
  518. [
  519. 'id' => 'MyNewApp',
  520. 'foo' => 'foo',
  521. ],
  522. [
  523. 'id' => 'bar',
  524. ],
  525. ];
  526. $this->assertSame($expected, $this->fetcher->get());
  527. }
  528. public function testGetNoMatchingETag() {
  529. $this->config
  530. ->expects($this->at(0))
  531. ->method('getSystemValue')
  532. ->with('appstoreenabled', true)
  533. ->willReturn(true);
  534. $this->config
  535. ->expects($this->at(1))
  536. ->method('getSystemValue')
  537. ->with('appstoreenabled', true)
  538. ->willReturn(true);
  539. $this->config
  540. ->expects($this->at(2))
  541. ->method('getSystemValue')
  542. ->with(
  543. $this->equalTo('version'),
  544. $this->anything()
  545. )->willReturn('11.0.0.2');
  546. $folder = $this->createMock(ISimpleFolder::class);
  547. $file = $this->createMock(ISimpleFile::class);
  548. $this->appData
  549. ->expects($this->once())
  550. ->method('getFolder')
  551. ->with('/')
  552. ->willReturn($folder);
  553. $folder
  554. ->expects($this->at(0))
  555. ->method('getFile')
  556. ->with($this->fileName)
  557. ->willReturn($file);
  558. $file
  559. ->expects($this->at(0))
  560. ->method('getContent')
  561. ->willReturn('{"data":[{"id":"MyOldApp","abc":"def"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}');
  562. $client = $this->createMock(IClient::class);
  563. $this->clientService
  564. ->expects($this->once())
  565. ->method('newClient')
  566. ->willReturn($client);
  567. $response = $this->createMock(IResponse::class);
  568. $client
  569. ->expects($this->once())
  570. ->method('get')
  571. ->with(
  572. $this->equalTo($this->endpoint),
  573. $this->equalTo([
  574. 'headers' => [
  575. 'If-None-Match' => '"myETag"',
  576. ]
  577. ])
  578. )
  579. ->willReturn($response);
  580. $response->method('getStatusCode')
  581. ->willReturn(200);
  582. $response
  583. ->expects($this->once())
  584. ->method('getBody')
  585. ->willReturn('[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}]');
  586. $response->method('getHeader')
  587. ->with($this->equalTo('ETag'))
  588. ->willReturn('"newETag"');
  589. $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1502,"ncversion":"11.0.0.2","ETag":"\"newETag\""}';
  590. $file
  591. ->expects($this->at(1))
  592. ->method('putContent')
  593. ->with($fileData);
  594. $file
  595. ->expects($this->at(2))
  596. ->method('getContent')
  597. ->willReturn($fileData);
  598. $this->timeFactory
  599. ->expects($this->at(0))
  600. ->method('getTime')
  601. ->willReturn(1501);
  602. $this->timeFactory
  603. ->expects($this->at(1))
  604. ->method('getTime')
  605. ->willReturn(1502);
  606. $expected = [
  607. [
  608. 'id' => 'MyNewApp',
  609. 'foo' => 'foo',
  610. ],
  611. [
  612. 'id' => 'bar',
  613. ],
  614. ];
  615. $this->assertSame($expected, $this->fetcher->get());
  616. }
  617. }