FetcherBase.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  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 OC\Files\AppData\AppData;
  24. use OC\Files\AppData\Factory;
  25. use OCP\AppFramework\Utility\ITimeFactory;
  26. use OCP\Files\IAppData;
  27. use OCP\Files\NotFoundException;
  28. use OCP\Files\SimpleFS\ISimpleFile;
  29. use OCP\Files\SimpleFS\ISimpleFolder;
  30. use OCP\Http\Client\IClient;
  31. use OCP\Http\Client\IClientService;
  32. use OCP\Http\Client\IResponse;
  33. use OCP\IConfig;
  34. use OCP\ILogger;
  35. use Test\TestCase;
  36. abstract class FetcherBase extends TestCase {
  37. /** @var Factory|\PHPUnit_Framework_MockObject_MockObject */
  38. protected $appDataFactory;
  39. /** @var IAppData|\PHPUnit_Framework_MockObject_MockObject */
  40. protected $appData;
  41. /** @var IClientService|\PHPUnit_Framework_MockObject_MockObject */
  42. protected $clientService;
  43. /** @var ITimeFactory|\PHPUnit_Framework_MockObject_MockObject */
  44. protected $timeFactory;
  45. /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
  46. protected $config;
  47. /** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */
  48. protected $logger;
  49. /** @var Fetcher */
  50. protected $fetcher;
  51. /** @var string */
  52. protected $fileName;
  53. /** @var string */
  54. protected $endpoint;
  55. protected function setUp(): void {
  56. parent::setUp();
  57. $this->appDataFactory = $this->createMock(Factory::class);
  58. $this->appData = $this->createMock(AppData::class);
  59. $this->appDataFactory->expects($this->once())
  60. ->method('get')
  61. ->with('appstore')
  62. ->willReturn($this->appData);
  63. $this->clientService = $this->createMock(IClientService::class);
  64. $this->timeFactory = $this->createMock(ITimeFactory::class);
  65. $this->config = $this->createMock(IConfig::class);
  66. $this->logger = $this->createMock(ILogger::class);
  67. }
  68. public function testGetWithAlreadyExistingFileAndUpToDateTimestampAndVersion() {
  69. $this->config
  70. ->expects($this->at(0))
  71. ->method('getSystemValue')
  72. ->with('appstoreenabled', true)
  73. ->willReturn(true);
  74. $this->config
  75. ->expects($this->at(1))
  76. ->method('getSystemValue')
  77. ->with('has_internet_connection', true)
  78. ->willReturn(true);
  79. $this->config
  80. ->expects($this->at(2))
  81. ->method('getSystemValue')
  82. ->with(
  83. $this->equalTo('version'),
  84. $this->anything()
  85. )->willReturn('11.0.0.2');
  86. $folder = $this->createMock(ISimpleFolder::class);
  87. $file = $this->createMock(ISimpleFile::class);
  88. $this->appData
  89. ->expects($this->once())
  90. ->method('getFolder')
  91. ->with('/')
  92. ->willReturn($folder);
  93. $folder
  94. ->expects($this->once())
  95. ->method('getFile')
  96. ->with($this->fileName)
  97. ->willReturn($file);
  98. $file
  99. ->expects($this->once())
  100. ->method('getContent')
  101. ->willReturn('{"timestamp":1200,"data":[{"id":"MyApp"}],"ncversion":"11.0.0.2"}');
  102. $this->timeFactory
  103. ->expects($this->once())
  104. ->method('getTime')
  105. ->willReturn(1499);
  106. $expected = [
  107. [
  108. 'id' => 'MyApp',
  109. ],
  110. ];
  111. $this->assertSame($expected, $this->fetcher->get());
  112. }
  113. public function testGetWithNotExistingFileAndUpToDateTimestampAndVersion() {
  114. $this->config
  115. ->expects($this->at(0))
  116. ->method('getSystemValue')
  117. ->with('appstoreenabled', true)
  118. ->willReturn(true);
  119. $this->config
  120. ->expects($this->at(1))
  121. ->method('getSystemValue')
  122. ->with('has_internet_connection', true)
  123. ->willReturn(true);
  124. $this->config
  125. ->expects($this->at(2))
  126. ->method('getSystemValue')
  127. ->with('appstoreenabled', true)
  128. ->willReturn(true);
  129. $this->config
  130. ->expects($this->at(3))
  131. ->method('getSystemValue')
  132. ->with('appstoreurl', 'https://apps.nextcloud.com/api/v1')
  133. ->willReturn('https://apps.nextcloud.com/api/v1');
  134. $this->config
  135. ->expects($this->at(4))
  136. ->method('getSystemValue')
  137. ->with(
  138. $this->equalTo('version'),
  139. $this->anything()
  140. )->willReturn('11.0.0.2');
  141. $folder = $this->createMock(ISimpleFolder::class);
  142. $file = $this->createMock(ISimpleFile::class);
  143. $this->appData
  144. ->expects($this->once())
  145. ->method('getFolder')
  146. ->with('/')
  147. ->willReturn($folder);
  148. $folder
  149. ->expects($this->at(0))
  150. ->method('getFile')
  151. ->with($this->fileName)
  152. ->willThrowException(new NotFoundException());
  153. $folder
  154. ->expects($this->at(1))
  155. ->method('newFile')
  156. ->with($this->fileName)
  157. ->willReturn($file);
  158. $client = $this->createMock(IClient::class);
  159. $this->clientService
  160. ->expects($this->once())
  161. ->method('newClient')
  162. ->willReturn($client);
  163. $response = $this->createMock(IResponse::class);
  164. $client
  165. ->expects($this->once())
  166. ->method('get')
  167. ->with($this->endpoint)
  168. ->willReturn($response);
  169. $response
  170. ->expects($this->once())
  171. ->method('getBody')
  172. ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]');
  173. $response->method('getHeader')
  174. ->with($this->equalTo('ETag'))
  175. ->willReturn('"myETag"');
  176. $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1502,"ncversion":"11.0.0.2","ETag":"\"myETag\""}';
  177. $file
  178. ->expects($this->at(0))
  179. ->method('putContent')
  180. ->with($fileData);
  181. $file
  182. ->expects($this->at(1))
  183. ->method('getContent')
  184. ->willReturn($fileData);
  185. $this->timeFactory
  186. ->expects($this->at(0))
  187. ->method('getTime')
  188. ->willReturn(1502);
  189. $expected = [
  190. [
  191. 'id' => 'MyNewApp',
  192. 'foo' => 'foo',
  193. ],
  194. [
  195. 'id' => 'bar',
  196. ],
  197. ];
  198. $this->assertSame($expected, $this->fetcher->get());
  199. }
  200. public function testGetWithAlreadyExistingFileAndOutdatedTimestamp() {
  201. $this->config->method('getSystemValue')
  202. ->willReturnCallback(function($key, $default) {
  203. if ($key === 'appstoreenabled') {
  204. return true;
  205. } else if ($key === 'version') {
  206. return '11.0.0.2';
  207. } else {
  208. return $default;
  209. }
  210. });
  211. $folder = $this->createMock(ISimpleFolder::class);
  212. $file = $this->createMock(ISimpleFile::class);
  213. $this->appData
  214. ->expects($this->once())
  215. ->method('getFolder')
  216. ->with('/')
  217. ->willReturn($folder);
  218. $folder
  219. ->expects($this->once())
  220. ->method('getFile')
  221. ->with($this->fileName)
  222. ->willReturn($file);
  223. $file
  224. ->expects($this->at(0))
  225. ->method('getContent')
  226. ->willReturn('{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}},"ncversion":"11.0.0.2"}');
  227. $this->timeFactory
  228. ->expects($this->at(0))
  229. ->method('getTime')
  230. ->willReturn(4801);
  231. $client = $this->createMock(IClient::class);
  232. $this->clientService
  233. ->expects($this->once())
  234. ->method('newClient')
  235. ->willReturn($client);
  236. $response = $this->createMock(IResponse::class);
  237. $client
  238. ->expects($this->once())
  239. ->method('get')
  240. ->with(
  241. $this->equalTo($this->endpoint),
  242. $this->equalTo([
  243. 'timeout' => 60,
  244. 'headers' => [
  245. 'Accept-Encoding' => 'gzip',
  246. ]
  247. ])
  248. )
  249. ->willReturn($response);
  250. $response
  251. ->expects($this->once())
  252. ->method('getBody')
  253. ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]');
  254. $response->method('getHeader')
  255. ->with($this->equalTo('ETag'))
  256. ->willReturn('"myETag"');
  257. $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1502,"ncversion":"11.0.0.2","ETag":"\"myETag\""}';
  258. $file
  259. ->expects($this->at(1))
  260. ->method('putContent')
  261. ->with($fileData);
  262. $file
  263. ->expects($this->at(2))
  264. ->method('getContent')
  265. ->willReturn($fileData);
  266. $this->timeFactory
  267. ->expects($this->at(1))
  268. ->method('getTime')
  269. ->willReturn(1502);
  270. $expected = [
  271. [
  272. 'id' => 'MyNewApp',
  273. 'foo' => 'foo',
  274. ],
  275. [
  276. 'id' => 'bar',
  277. ],
  278. ];
  279. $this->assertSame($expected, $this->fetcher->get());
  280. }
  281. public function testGetWithAlreadyExistingFileAndNoVersion() {
  282. $this->config
  283. ->expects($this->at(0))
  284. ->method('getSystemValue')
  285. ->with('appstoreenabled', true)
  286. ->willReturn(true);
  287. $this->config
  288. ->expects($this->at(1))
  289. ->method('getSystemValue')
  290. ->with('has_internet_connection', true)
  291. ->willReturn(true);
  292. $this->config
  293. ->expects($this->at(2))
  294. ->method('getSystemValue')
  295. ->with('appstoreenabled', true)
  296. ->willReturn(true);
  297. $this->config
  298. ->expects($this->at(3))
  299. ->method('getSystemValue')
  300. ->with('appstoreurl', 'https://apps.nextcloud.com/api/v1')
  301. ->willReturn('https://apps.nextcloud.com/api/v1');
  302. $this->config
  303. ->expects($this->at(4))
  304. ->method('getSystemValue')
  305. ->with(
  306. $this->equalTo('version'),
  307. $this->anything()
  308. )->willReturn('11.0.0.2');
  309. $folder = $this->createMock(ISimpleFolder::class);
  310. $file = $this->createMock(ISimpleFile::class);
  311. $this->appData
  312. ->expects($this->once())
  313. ->method('getFolder')
  314. ->with('/')
  315. ->willReturn($folder);
  316. $folder
  317. ->expects($this->once())
  318. ->method('getFile')
  319. ->with($this->fileName)
  320. ->willReturn($file);
  321. $file
  322. ->expects($this->at(0))
  323. ->method('getContent')
  324. ->willReturn('{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}}');
  325. $this->timeFactory
  326. ->expects($this->at(0))
  327. ->method('getTime')
  328. ->willReturn(1201);
  329. $client = $this->createMock(IClient::class);
  330. $this->clientService
  331. ->expects($this->once())
  332. ->method('newClient')
  333. ->willReturn($client);
  334. $response = $this->createMock(IResponse::class);
  335. $client
  336. ->expects($this->once())
  337. ->method('get')
  338. ->with(
  339. $this->equalTo($this->endpoint),
  340. $this->equalTo([
  341. 'timeout' => 60,
  342. 'headers' => [
  343. 'Accept-Encoding' => 'gzip',
  344. ]
  345. ])
  346. )
  347. ->willReturn($response);
  348. $response
  349. ->expects($this->once())
  350. ->method('getBody')
  351. ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]');
  352. $response->method('getHeader')
  353. ->with($this->equalTo('ETag'))
  354. ->willReturn('"myETag"');
  355. $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1201,"ncversion":"11.0.0.2","ETag":"\"myETag\""}';
  356. $file
  357. ->expects($this->at(1))
  358. ->method('putContent')
  359. ->with($fileData);
  360. $file
  361. ->expects($this->at(2))
  362. ->method('getContent')
  363. ->willReturn($fileData);
  364. $expected = [
  365. [
  366. 'id' => 'MyNewApp',
  367. 'foo' => 'foo',
  368. ],
  369. [
  370. 'id' => 'bar',
  371. ],
  372. ];
  373. $this->assertSame($expected, $this->fetcher->get());
  374. }
  375. public function testGetWithAlreadyExistingFileAndOutdatedVersion() {
  376. $this->config
  377. ->expects($this->at(0))
  378. ->method('getSystemValue')
  379. ->with('appstoreenabled', true)
  380. ->willReturn(true);
  381. $this->config
  382. ->expects($this->at(1))
  383. ->method('getSystemValue')
  384. ->with('has_internet_connection', true)
  385. ->willReturn(true);
  386. $this->config
  387. ->expects($this->at(2))
  388. ->method('getSystemValue')
  389. ->with('appstoreenabled', true)
  390. ->willReturn(true);
  391. $this->config
  392. ->expects($this->at(3))
  393. ->method('getSystemValue')
  394. ->with('appstoreurl', 'https://apps.nextcloud.com/api/v1')
  395. ->willReturn('https://apps.nextcloud.com/api/v1');
  396. $this->config
  397. ->expects($this->at(4))
  398. ->method('getSystemValue')
  399. ->with(
  400. $this->equalTo('version'),
  401. $this->anything()
  402. )->willReturn('11.0.0.2');
  403. $folder = $this->createMock(ISimpleFolder::class);
  404. $file = $this->createMock(ISimpleFile::class);
  405. $this->appData
  406. ->expects($this->once())
  407. ->method('getFolder')
  408. ->with('/')
  409. ->willReturn($folder);
  410. $folder
  411. ->expects($this->once())
  412. ->method('getFile')
  413. ->with($this->fileName)
  414. ->willReturn($file);
  415. $file
  416. ->expects($this->at(0))
  417. ->method('getContent')
  418. ->willReturn('{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}},"ncversion":"11.0.0.1"');
  419. $this->timeFactory
  420. ->method('getTime')
  421. ->willReturn(1201);
  422. $client = $this->createMock(IClient::class);
  423. $this->clientService
  424. ->expects($this->once())
  425. ->method('newClient')
  426. ->willReturn($client);
  427. $response = $this->createMock(IResponse::class);
  428. $client
  429. ->expects($this->once())
  430. ->method('get')
  431. ->with(
  432. $this->equalTo($this->endpoint),
  433. $this->equalTo([
  434. 'timeout' => 60,
  435. 'headers' => [
  436. 'Accept-Encoding' => 'gzip',
  437. ]
  438. ])
  439. )
  440. ->willReturn($response);
  441. $response
  442. ->expects($this->once())
  443. ->method('getBody')
  444. ->willReturn('[{"id":"MyNewApp", "foo": "foo"}, {"id":"bar"}]');
  445. $response->method('getHeader')
  446. ->with($this->equalTo('ETag'))
  447. ->willReturn('"myETag"');
  448. $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1201,"ncversion":"11.0.0.2","ETag":"\"myETag\""}';
  449. $file
  450. ->expects($this->at(1))
  451. ->method('putContent')
  452. ->with($fileData);
  453. $file
  454. ->expects($this->at(2))
  455. ->method('getContent')
  456. ->willReturn($fileData);
  457. $expected = [
  458. [
  459. 'id' => 'MyNewApp',
  460. 'foo' => 'foo',
  461. ],
  462. [
  463. 'id' => 'bar',
  464. ],
  465. ];
  466. $this->assertSame($expected, $this->fetcher->get());
  467. }
  468. public function testGetWithExceptionInClient() {
  469. $this->config->method('getSystemValue')
  470. ->willReturnCallback(function($key, $default) {
  471. if ($key === 'appstoreenabled') {
  472. return true;
  473. } else {
  474. return $default;
  475. }
  476. });
  477. $folder = $this->createMock(ISimpleFolder::class);
  478. $file = $this->createMock(ISimpleFile::class);
  479. $this->appData
  480. ->expects($this->once())
  481. ->method('getFolder')
  482. ->with('/')
  483. ->willReturn($folder);
  484. $folder
  485. ->expects($this->once())
  486. ->method('getFile')
  487. ->with($this->fileName)
  488. ->willReturn($file);
  489. $file
  490. ->expects($this->at(0))
  491. ->method('getContent')
  492. ->willReturn('{"timestamp":1200,"data":{"MyApp":{"id":"MyApp"}}}');
  493. $client = $this->createMock(IClient::class);
  494. $this->clientService
  495. ->expects($this->once())
  496. ->method('newClient')
  497. ->willReturn($client);
  498. $client
  499. ->expects($this->once())
  500. ->method('get')
  501. ->with(
  502. $this->equalTo($this->endpoint),
  503. $this->equalTo([
  504. 'timeout' => 60,
  505. 'headers' => [
  506. 'Accept-Encoding' => 'gzip',
  507. ]
  508. ])
  509. )
  510. ->willThrowException(new \Exception());
  511. $this->assertSame([], $this->fetcher->get());
  512. }
  513. public function testGetMatchingETag() {
  514. $this->config->method('getSystemValue')
  515. ->willReturnCallback(function($key, $default) {
  516. if ($key === 'appstoreenabled') {
  517. return true;
  518. } else if ($key === 'version') {
  519. return '11.0.0.2';
  520. } else {
  521. return $default;
  522. }
  523. });
  524. $folder = $this->createMock(ISimpleFolder::class);
  525. $file = $this->createMock(ISimpleFile::class);
  526. $this->appData
  527. ->expects($this->once())
  528. ->method('getFolder')
  529. ->with('/')
  530. ->willReturn($folder);
  531. $folder
  532. ->expects($this->once())
  533. ->method('getFile')
  534. ->with($this->fileName)
  535. ->willReturn($file);
  536. $origData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}';
  537. $file
  538. ->expects($this->at(0))
  539. ->method('getContent')
  540. ->willReturn($origData);
  541. $this->timeFactory
  542. ->expects($this->at(0))
  543. ->method('getTime')
  544. ->willReturn(4801);
  545. $this->timeFactory
  546. ->expects($this->at(1))
  547. ->method('getTime')
  548. ->willReturn(4802);
  549. $client = $this->createMock(IClient::class);
  550. $this->clientService
  551. ->expects($this->once())
  552. ->method('newClient')
  553. ->willReturn($client);
  554. $response = $this->createMock(IResponse::class);
  555. $client
  556. ->expects($this->once())
  557. ->method('get')
  558. ->with(
  559. $this->equalTo($this->endpoint),
  560. $this->equalTo([
  561. 'timeout' => 60,
  562. 'headers' => [
  563. 'Accept-Encoding' => 'gzip',
  564. 'If-None-Match' => '"myETag"',
  565. ]
  566. ])
  567. )->willReturn($response);
  568. $response->method('getStatusCode')
  569. ->willReturn(304);
  570. $newData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":4802,"ncversion":"11.0.0.2","ETag":"\"myETag\""}';
  571. $file
  572. ->expects($this->at(1))
  573. ->method('putContent')
  574. ->with($newData);
  575. $file
  576. ->expects($this->at(2))
  577. ->method('getContent')
  578. ->willReturn($newData);
  579. $expected = [
  580. [
  581. 'id' => 'MyNewApp',
  582. 'foo' => 'foo',
  583. ],
  584. [
  585. 'id' => 'bar',
  586. ],
  587. ];
  588. $this->assertSame($expected, $this->fetcher->get());
  589. }
  590. public function testGetNoMatchingETag() {
  591. $this->config->method('getSystemValue')
  592. ->willReturnCallback(function($key, $default) {
  593. if ($key === 'appstoreenabled') {
  594. return true;
  595. } else if ($key === 'version') {
  596. return '11.0.0.2';
  597. } else {
  598. return $default;
  599. }
  600. });
  601. $folder = $this->createMock(ISimpleFolder::class);
  602. $file = $this->createMock(ISimpleFile::class);
  603. $this->appData
  604. ->expects($this->once())
  605. ->method('getFolder')
  606. ->with('/')
  607. ->willReturn($folder);
  608. $folder
  609. ->expects($this->at(0))
  610. ->method('getFile')
  611. ->with($this->fileName)
  612. ->willReturn($file);
  613. $file
  614. ->expects($this->at(0))
  615. ->method('getContent')
  616. ->willReturn('{"data":[{"id":"MyOldApp","abc":"def"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}');
  617. $client = $this->createMock(IClient::class);
  618. $this->clientService
  619. ->expects($this->once())
  620. ->method('newClient')
  621. ->willReturn($client);
  622. $response = $this->createMock(IResponse::class);
  623. $client
  624. ->expects($this->once())
  625. ->method('get')
  626. ->with(
  627. $this->equalTo($this->endpoint),
  628. $this->equalTo([
  629. 'timeout' => 60,
  630. 'headers' => [
  631. 'Accept-Encoding' => 'gzip',
  632. 'If-None-Match' => '"myETag"',
  633. ]
  634. ])
  635. )
  636. ->willReturn($response);
  637. $response->method('getStatusCode')
  638. ->willReturn(200);
  639. $response
  640. ->expects($this->once())
  641. ->method('getBody')
  642. ->willReturn('[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}]');
  643. $response->method('getHeader')
  644. ->with($this->equalTo('ETag'))
  645. ->willReturn('"newETag"');
  646. $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":4802,"ncversion":"11.0.0.2","ETag":"\"newETag\""}';
  647. $file
  648. ->expects($this->at(1))
  649. ->method('putContent')
  650. ->with($fileData);
  651. $file
  652. ->expects($this->at(2))
  653. ->method('getContent')
  654. ->willReturn($fileData);
  655. $this->timeFactory
  656. ->expects($this->at(0))
  657. ->method('getTime')
  658. ->willReturn(4801);
  659. $this->timeFactory
  660. ->expects($this->at(1))
  661. ->method('getTime')
  662. ->willReturn(4802);
  663. $expected = [
  664. [
  665. 'id' => 'MyNewApp',
  666. 'foo' => 'foo',
  667. ],
  668. [
  669. 'id' => 'bar',
  670. ],
  671. ];
  672. $this->assertSame($expected, $this->fetcher->get());
  673. }
  674. public function testFetchAfterUpgradeNoETag() {
  675. $this->config->method('getSystemValue')
  676. ->willReturnCallback(function($key, $default) {
  677. if ($key === 'appstoreenabled') {
  678. return true;
  679. } else if ($key === 'version') {
  680. return '11.0.0.3';
  681. } else {
  682. return $default;
  683. }
  684. });
  685. $folder = $this->createMock(ISimpleFolder::class);
  686. $file = $this->createMock(ISimpleFile::class);
  687. $this->appData
  688. ->expects($this->once())
  689. ->method('getFolder')
  690. ->with('/')
  691. ->willReturn($folder);
  692. $folder
  693. ->expects($this->at(0))
  694. ->method('getFile')
  695. ->with($this->fileName)
  696. ->willReturn($file);
  697. $file
  698. ->expects($this->at(0))
  699. ->method('getContent')
  700. ->willReturn('{"data":[{"id":"MyOldApp","abc":"def"}],"timestamp":1200,"ncversion":"11.0.0.2","ETag":"\"myETag\""}');
  701. $client = $this->createMock(IClient::class);
  702. $this->clientService
  703. ->expects($this->once())
  704. ->method('newClient')
  705. ->willReturn($client);
  706. $response = $this->createMock(IResponse::class);
  707. $client
  708. ->expects($this->once())
  709. ->method('get')
  710. ->with(
  711. $this->equalTo($this->endpoint),
  712. $this->equalTo([
  713. 'timeout' => 60,
  714. 'headers' => [
  715. 'Accept-Encoding' => 'gzip',
  716. ],
  717. ])
  718. )
  719. ->willReturn($response);
  720. $response->method('getStatusCode')
  721. ->willReturn(200);
  722. $response
  723. ->expects($this->once())
  724. ->method('getBody')
  725. ->willReturn('[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}]');
  726. $response->method('getHeader')
  727. ->with($this->equalTo('ETag'))
  728. ->willReturn('"newETag"');
  729. $fileData = '{"data":[{"id":"MyNewApp","foo":"foo"},{"id":"bar"}],"timestamp":1501,"ncversion":"11.0.0.3","ETag":"\"newETag\""}';
  730. $file
  731. ->expects($this->at(1))
  732. ->method('putContent')
  733. ->with($fileData);
  734. $file
  735. ->expects($this->at(2))
  736. ->method('getContent')
  737. ->willReturn($fileData);
  738. $this->timeFactory
  739. ->expects($this->once())
  740. ->method('getTime')
  741. ->willReturn(1501);
  742. $expected = [
  743. [
  744. 'id' => 'MyNewApp',
  745. 'foo' => 'foo',
  746. ],
  747. [
  748. 'id' => 'bar',
  749. ],
  750. ];
  751. $this->assertSame($expected, $this->fetcher->get());
  752. }
  753. }