1
0

InstallerTest.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace Test;
  8. use OC\App\AppStore\Fetcher\AppFetcher;
  9. use OC\Archive\ZIP;
  10. use OC\Installer;
  11. use OCP\App\IAppManager;
  12. use OCP\Http\Client\IClient;
  13. use OCP\Http\Client\IClientService;
  14. use OCP\IConfig;
  15. use OCP\ITempManager;
  16. use Psr\Log\LoggerInterface;
  17. /**
  18. * Class InstallerTest
  19. *
  20. * @package Test
  21. * @group DB
  22. */
  23. class InstallerTest extends TestCase {
  24. private static $appid = 'testapp';
  25. private $appstore;
  26. /** @var AppFetcher|\PHPUnit\Framework\MockObject\MockObject */
  27. private $appFetcher;
  28. /** @var IClientService|\PHPUnit\Framework\MockObject\MockObject */
  29. private $clientService;
  30. /** @var ITempManager|\PHPUnit\Framework\MockObject\MockObject */
  31. private $tempManager;
  32. /** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */
  33. private $logger;
  34. /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
  35. private $config;
  36. protected function setUp(): void {
  37. parent::setUp();
  38. $this->appFetcher = $this->createMock(AppFetcher::class);
  39. $this->clientService = $this->createMock(IClientService::class);
  40. $this->tempManager = $this->createMock(ITempManager::class);
  41. $this->logger = $this->createMock(LoggerInterface::class);
  42. $this->config = $this->createMock(IConfig::class);
  43. $config = \OC::$server->getConfig();
  44. $this->appstore = $config->setSystemValue('appstoreenabled', true);
  45. $config->setSystemValue('appstoreenabled', true);
  46. $installer = new Installer(
  47. \OC::$server->get(AppFetcher::class),
  48. \OC::$server->get(IClientService::class),
  49. \OC::$server->getTempManager(),
  50. \OC::$server->get(LoggerInterface::class),
  51. $config,
  52. false
  53. );
  54. $installer->removeApp(self::$appid);
  55. }
  56. protected function getInstaller() {
  57. return new Installer(
  58. $this->appFetcher,
  59. $this->clientService,
  60. $this->tempManager,
  61. $this->logger,
  62. $this->config,
  63. false
  64. );
  65. }
  66. protected function tearDown(): void {
  67. $installer = new Installer(
  68. \OC::$server->get(AppFetcher::class),
  69. \OC::$server->get(IClientService::class),
  70. \OC::$server->getTempManager(),
  71. \OC::$server->get(LoggerInterface::class),
  72. \OC::$server->getConfig(),
  73. false
  74. );
  75. $installer->removeApp(self::$appid);
  76. \OC::$server->getConfig()->setSystemValue('appstoreenabled', $this->appstore);
  77. parent::tearDown();
  78. }
  79. public function testInstallApp(): void {
  80. // Read the current version of the app to check for bug #2572
  81. \OCP\Server::get(IAppManager::class)->getAppVersion('testapp', true);
  82. // Extract app
  83. $pathOfTestApp = __DIR__ . '/../data/testapp.zip';
  84. $tar = new ZIP($pathOfTestApp);
  85. $tar->extract(\OC_App::getInstallPath());
  86. // Install app
  87. $installer = new Installer(
  88. \OC::$server->get(AppFetcher::class),
  89. \OC::$server->get(IClientService::class),
  90. \OC::$server->getTempManager(),
  91. \OC::$server->get(LoggerInterface::class),
  92. \OC::$server->getConfig(),
  93. false
  94. );
  95. $this->assertNull(\OC::$server->getConfig()->getAppValue('testapp', 'enabled', null), 'Check that the app is not listed before installation');
  96. $this->assertSame('testapp', $installer->installApp(self::$appid));
  97. $this->assertSame('no', \OC::$server->getConfig()->getAppValue('testapp', 'enabled', null), 'Check that the app is listed after installation');
  98. $this->assertSame('0.9', \OC::$server->getConfig()->getAppValue('testapp', 'installed_version'));
  99. $installer->removeApp(self::$appid);
  100. }
  101. public function updateArrayProvider() {
  102. return [
  103. // Update available
  104. [
  105. [
  106. [
  107. 'id' => 'files',
  108. 'releases' => [
  109. [
  110. 'version' => '1111.0'
  111. ],
  112. ],
  113. ],
  114. ],
  115. '1111.0',
  116. ],
  117. // No update available
  118. [
  119. [
  120. [
  121. 'id' => 'files',
  122. 'releases' => [
  123. [
  124. 'version' => '1.0'
  125. ],
  126. ],
  127. ],
  128. ],
  129. false,
  130. ],
  131. ];
  132. }
  133. /**
  134. * @dataProvider updateArrayProvider
  135. * @param array $appArray
  136. * @param string|bool $updateAvailable
  137. */
  138. public function testIsUpdateAvailable(array $appArray, $updateAvailable): void {
  139. $this->appFetcher
  140. ->expects($this->once())
  141. ->method('get')
  142. ->willReturn($appArray);
  143. $installer = $this->getInstaller();
  144. $this->assertSame($updateAvailable, $installer->isUpdateAvailable('files'));
  145. $this->assertSame($updateAvailable, $installer->isUpdateAvailable('files'), 'Cached result should be returned and fetcher should be only called once');
  146. }
  147. public function testDownloadAppWithRevokedCertificate(): void {
  148. $this->expectException(\Exception::class);
  149. $this->expectExceptionMessage('Certificate "4112" has been revoked');
  150. $appArray = [
  151. [
  152. 'id' => 'news',
  153. 'certificate' => '-----BEGIN CERTIFICATE-----
  154. MIIEAjCCAuoCAhAQMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
  155. VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
  156. MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
  157. dXRob3JpdHkwHhcNMTYxMDAzMTMyNDM3WhcNMjcwMTA5MTMyNDM3WjASMRAwDgYD
  158. VQQDDAdwYXNzbWFuMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApEt+
  159. KZGs+WqdZkHZflzqk+ophYWB8qB47XCzy+xdTGPFM84/9wXltRPbcQQWJJl5aOx0
  160. FPbsyTGhIt/IYZ2Vl0XrDRJjsaxzPcrofrwpJ2tqforXjGohl6mZUBA0ESzFiPzT
  161. SAZe8E14+Jk8rbF/ecrkqcWf2cTMV3Qfu9YvJo8WVs4lHc95r1F+Nalh/OLkHkzb
  162. fYPno2Z5cco6U7BXunFQG2gqy3wWQwmlhDxh5fwrCoFzPWm7WhwSyK+eMoSDz+Vp
  163. 3kmtyijsqnda0zA9bfNzgW26czbJaObbnkdtDC2nfoAWXndlS/5YRI8yHd9miB5C
  164. u1OC8LUWToDGNa9+FOxBSj7Nk6iyjbVfRXcTqThdkVZdOOPaBRMsL9R4UYywCbhA
  165. yGNiQ0ahfXD8MZSb08rlQg8tAtcUZW1sYQcbtMGnu8OyC5J7N1efzv5mys4+9hBS
  166. 5ECeyCuQTuOkF4H/XS2BMSFZWF2xh7wzhMLca+5yauDW4i8baFEv74QTeY1DADgI
  167. Lz29NJ6z9xYzEnPesjNrwIcJwIjV52EkdLTi+EIf83UjXLQdwDbLxu76qxqP7K0I
  168. oMmwbl7UNA0wzq7nmgRhvqhow5RoCaSJjTz0EYQVSa1xelwiKeJiSKj2G9Mgt5Ms
  169. Miuy3C3VAGvQJ2ocILPGOt54oVeNRFLpnCo1e3sCAwEAATANBgkqhkiG9w0BAQsF
  170. AAOCAQEAkGYtg21rGpUVT/AokGUfI0PeyYAkcXKy2yuBAzfRk+uIXnRR0vK+OMpx
  171. shBoYGR3JEGUHZcMTRh8wjAZ0wuyYlQONtJbFFF3bCfODXxCsw0Vm8/Ms+KCmE4Z
  172. SyQafWEQf1sdqNw4VS4DYS2mlpDgAl+U9UY6HQKuT3+GFIxCsQSdS0GTaiYVKPVE
  173. p/eKou739h+5dM4FEhIYZX+7PWlHmX6wPCFAjgNu3kiRGmF6LKmCNNXTySATEP86
  174. tczQMzLtVdTg5z8XMi//6TkAPxRPjYi8Vef/s2mLo7KystTmofxI/HZePSieJ9tj
  175. gLgK8d8sKL60JMmKHN3boHrsThKBVA==
  176. -----END CERTIFICATE-----',
  177. ],
  178. ];
  179. $this->appFetcher
  180. ->expects($this->once())
  181. ->method('get')
  182. ->willReturn($appArray);
  183. $installer = $this->getInstaller();
  184. $installer->downloadApp('news');
  185. }
  186. public function testDownloadAppWithNotNextcloudCertificate(): void {
  187. $this->expectException(\Exception::class);
  188. $this->expectExceptionMessage('App with id news has a certificate not issued by a trusted Code Signing Authority');
  189. $appArray = [
  190. [
  191. 'id' => 'news',
  192. 'certificate' => '-----BEGIN CERTIFICATE-----
  193. MIID8TCCAdkCAhAAMA0GCSqGSIb3DQEBCwUAMG0xCzAJBgNVBAYTAlVTMQ8wDQYD
  194. VQQIDAZCb3N0b24xFjAUBgNVBAoMDW93bkNsb3VkIEluYy4xNTAzBgNVBAMMLG93
  195. bkNsb3VkIENvZGUgU2lnbmluZyBJbnRlcm1lZGlhdGUgQXV0aG9yaXR5MB4XDTE2
  196. MDIwMzE3NTE0OVoXDTI2MDEzMTE3NTE0OVowDzENMAsGA1UEAwwEY29yZTCCASIw
  197. DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPHdSljnHI+ueQd27UyWPO9n4Lqt
  198. bK0kdekiC3si7Mee7uXXJaGuqXJozHEZYB1LIFLdCU/itCxEk9hyLcyNzeT+nRT/
  199. zDuOYdbLgCj7/A5bX+u3jc29UlCYybSFchfMdvn7a0njCna4dE+73b4yEj16tS2h
  200. S1EUygSzgicWlJqMD3Z9Qc+zLEpdhq9oDdDB8HURi2NW4KzIraVncSH+zF1QduOh
  201. nERDnF8x48D3FLdTxGA0W/Kg4gYsq4NRvU6g3DJNdp4YfqRSFMmLFDCgzDuhan7D
  202. wgRlI9NAeHbnyoUPtrDBUceI7shIbC/i87xk9ptqV0AyFonkJtK6lWwZjNkCAwEA
  203. ATANBgkqhkiG9w0BAQsFAAOCAgEAAMgymqZE1YaHYlRGwvTE7gGDY3gmFOMaxQL4
  204. E5m0CnkBz4BdIPRsQFFdOv3l/MIWkw5ED3vUB925VpQZYFSiEuv5NbnlPaHZlIMI
  205. n8AV/sTP5jue3LhtAN4EM63xNBhudAT6wVsvGwOuQOx9Xv+ptO8Po7sTuNYP0CMH
  206. EOQN+/q8tYlSm2VW+dAlaJ+zVZwZldhVjL+lSH4E9ktWn3PmgNQeKfcnJISUbus6
  207. ZtsYDF/X96/Z2ZQvMXOKksgvU6XlvIxllcyebC9Bxe/h0D63GCO2tqN5CWQzIIqn
  208. apUynPX8BlLaaExqYGERwlUi/yOGaUVPUjEPVehviOQYgAqxlrkJk1dWeCrwUori
  209. CXpi+IUYkidfgiJ9F88M3ElpwqIaXp7G3/4oHBuE2u6M+L+1/vqPJeTCAWUxxpJE
  210. yYmM+db6D4TySFpQPENNzPS8bpR6T8w2hRumkldC42HrnyJJbpjOieTXhXzjdPvZ
  211. IEP9JGtkhB2du6nBF2MNAq2TqRXpcfQrQEbnQ13aV9bl+roTwwO+SOWK/wgvdOMI
  212. STQ0Xk0sTGlmQjPYPkibVceaWMR3sX4cNt5c33YhJys5jxHoAh42km4nN9tfykR5
  213. crl5lBlKjXh2GP0+omSO3x1jX4+iQPCW2TWoyKkUdLu/hGHG2w8RrTeme+kATECH
  214. YSu356M=
  215. -----END CERTIFICATE-----',
  216. ],
  217. ];
  218. $this->appFetcher
  219. ->expects($this->once())
  220. ->method('get')
  221. ->willReturn($appArray);
  222. $installer = $this->getInstaller();
  223. $installer->downloadApp('news');
  224. }
  225. public function testDownloadAppWithDifferentCN(): void {
  226. $this->expectException(\Exception::class);
  227. $this->expectExceptionMessage('App with id news has a cert issued to passman');
  228. $appArray = [
  229. [
  230. 'id' => 'news',
  231. 'certificate' => '-----BEGIN CERTIFICATE-----
  232. MIIEAjCCAuoCAhDUMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
  233. VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
  234. MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
  235. dXRob3JpdHkwHhcNMTkwMTMwMTMwMjA5WhcNMjkwNTA3MTMwMjA5WjASMRAwDgYD
  236. VQQDDAdwYXNzbWFuMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwT1/
  237. hO/RSUkj0T9a879LPjy4c5V7FBDffEh6H/n1aiOEzofr8vqP3wJ4ZLwIvpZIZNFC
  238. CY4HjBTIgk+QOlAv2oV2w/8XxkSQ708H3m99GFNRQg9EztjiIeKn7y1HhFOeiVaF
  239. Eq6R1Tnre8cjzv6/yf1f1EFpPY3ptCefUjdLfpU/YrPhFxGLS+n5hyr8b6EszqKm
  240. 6NhGI09sd1Wb1y8o+dtQIQr24gWeo3l3QGLxjcJQqHCxE38rGdTNd04qDEm69BMD
  241. Kjk4/JmUBBOn0svg9IAks+4nDnpr3IABfcnKYlmAucVEMNMYfA6kXXWEALsE2yo9
  242. 8Y7GeV8En5Ztn4w3Pt2HMNpJV2m7MWWocSbF+ocp8oJ0cIEcthBubiE2kJhdPi5a
  243. Yo5Bwh54hx53an+XfiDn+bfidvNz5TsJtmZykB84gLcdBQyMHrZcDcD6g74KdW3X
  244. du/AnNUlJujhIU0fsw3UUPB845Q8XjbsIK5WhgaQeXJum8HXnXWkEfh6mE4j9l2Z
  245. 6FJVe8fQlF5lspn6z3qYsWlYRalD3N9Qxy3vpRgCAYTPc3D+fbVP9KJw1cWux1+O
  246. 0X/hNWMDOTenhgyQS+mqhRvdWq71mFjP/RXjOSfED3ipFamPofCz9QC7EERtvZPE
  247. Pr8tBnbxnyTbAOQrN9N2mA9UJbOhk2l5kCSkDpMCAwEAATANBgkqhkiG9w0BAQsF
  248. AAOCAQEAdVaizjIBQLGFo3uzOVAjh5IoFt/DBiSjVYOOt4HacWDDkRKOmQp3AJaA
  249. Zecbd+tF7OsIqrBzbbfK7wp1+y1pLrPNFQghhk7gVxBP9LscLQ1JmDK2vHv9rLAg
  250. d/gv90gf3HVeRQWntAhGTqtiSZkafcXJIRCM4GygoPy2zxeWeCTt85yEbQnuGZ4Z
  251. qtWS/yyJR5ZQEwYG7jFWRxaZicuUdWBhlUMafRUxzjxBhsQplGKSI66eFQ5VtB7L
  252. u/spPSSVhaun5BA1FlphB2TkgnzlCmxJa63nFY045e/Jq+IKMcqqZl/092gbI2EQ
  253. 5EpZaQ1l6H5DBXwrz58a8WTPC2Mu8g==
  254. -----END CERTIFICATE-----',
  255. ],
  256. ];
  257. $this->appFetcher
  258. ->expects($this->once())
  259. ->method('get')
  260. ->willReturn($appArray);
  261. $installer = $this->getInstaller();
  262. $installer->downloadApp('news');
  263. }
  264. public function testDownloadAppWithInvalidSignature(): void {
  265. $this->expectException(\Exception::class);
  266. $this->expectExceptionMessage('App with id passman has invalid signature');
  267. $appArray = [
  268. [
  269. 'id' => 'passman',
  270. 'certificate' => '-----BEGIN CERTIFICATE-----
  271. MIIEAjCCAuoCAhDUMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
  272. VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
  273. MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
  274. dXRob3JpdHkwHhcNMTkwMTMwMTMwMjA5WhcNMjkwNTA3MTMwMjA5WjASMRAwDgYD
  275. VQQDDAdwYXNzbWFuMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwT1/
  276. hO/RSUkj0T9a879LPjy4c5V7FBDffEh6H/n1aiOEzofr8vqP3wJ4ZLwIvpZIZNFC
  277. CY4HjBTIgk+QOlAv2oV2w/8XxkSQ708H3m99GFNRQg9EztjiIeKn7y1HhFOeiVaF
  278. Eq6R1Tnre8cjzv6/yf1f1EFpPY3ptCefUjdLfpU/YrPhFxGLS+n5hyr8b6EszqKm
  279. 6NhGI09sd1Wb1y8o+dtQIQr24gWeo3l3QGLxjcJQqHCxE38rGdTNd04qDEm69BMD
  280. Kjk4/JmUBBOn0svg9IAks+4nDnpr3IABfcnKYlmAucVEMNMYfA6kXXWEALsE2yo9
  281. 8Y7GeV8En5Ztn4w3Pt2HMNpJV2m7MWWocSbF+ocp8oJ0cIEcthBubiE2kJhdPi5a
  282. Yo5Bwh54hx53an+XfiDn+bfidvNz5TsJtmZykB84gLcdBQyMHrZcDcD6g74KdW3X
  283. du/AnNUlJujhIU0fsw3UUPB845Q8XjbsIK5WhgaQeXJum8HXnXWkEfh6mE4j9l2Z
  284. 6FJVe8fQlF5lspn6z3qYsWlYRalD3N9Qxy3vpRgCAYTPc3D+fbVP9KJw1cWux1+O
  285. 0X/hNWMDOTenhgyQS+mqhRvdWq71mFjP/RXjOSfED3ipFamPofCz9QC7EERtvZPE
  286. Pr8tBnbxnyTbAOQrN9N2mA9UJbOhk2l5kCSkDpMCAwEAATANBgkqhkiG9w0BAQsF
  287. AAOCAQEAdVaizjIBQLGFo3uzOVAjh5IoFt/DBiSjVYOOt4HacWDDkRKOmQp3AJaA
  288. Zecbd+tF7OsIqrBzbbfK7wp1+y1pLrPNFQghhk7gVxBP9LscLQ1JmDK2vHv9rLAg
  289. d/gv90gf3HVeRQWntAhGTqtiSZkafcXJIRCM4GygoPy2zxeWeCTt85yEbQnuGZ4Z
  290. qtWS/yyJR5ZQEwYG7jFWRxaZicuUdWBhlUMafRUxzjxBhsQplGKSI66eFQ5VtB7L
  291. u/spPSSVhaun5BA1FlphB2TkgnzlCmxJa63nFY045e/Jq+IKMcqqZl/092gbI2EQ
  292. 5EpZaQ1l6H5DBXwrz58a8WTPC2Mu8g==
  293. -----END CERTIFICATE-----',
  294. 'releases' => [
  295. [
  296. 'download' => 'https://example.com',
  297. 'signature' => 'MySignature',
  298. ],
  299. [
  300. 'download' => 'https://nextcloud.com',
  301. ],
  302. ],
  303. ],
  304. ];
  305. $this->appFetcher
  306. ->expects($this->once())
  307. ->method('get')
  308. ->willReturn($appArray);
  309. $realTmpFile = \OC::$server->getTempManager()->getTemporaryFile('.tar.gz');
  310. copy(__DIR__ . '/../data/testapp.tar.gz', $realTmpFile);
  311. $this->tempManager
  312. ->expects($this->once())
  313. ->method('getTemporaryFile')
  314. ->with('.tar.gz')
  315. ->willReturn($realTmpFile);
  316. $client = $this->createMock(IClient::class);
  317. $client
  318. ->expects($this->once())
  319. ->method('get')
  320. ->with('https://example.com', ['sink' => $realTmpFile, 'timeout' => 120]);
  321. $this->clientService
  322. ->expects($this->once())
  323. ->method('newClient')
  324. ->willReturn($client);
  325. $installer = $this->getInstaller();
  326. $installer->downloadApp('passman');
  327. }
  328. public function testDownloadAppWithMoreThanOneFolderDownloaded(): void {
  329. $this->expectException(\Exception::class);
  330. $this->expectExceptionMessage('Extracted app testapp has more than 1 folder');
  331. $appArray = [
  332. [
  333. 'id' => 'testapp',
  334. 'certificate' => '-----BEGIN CERTIFICATE-----
  335. MIIEAjCCAuoCAhAbMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
  336. VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
  337. MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
  338. dXRob3JpdHkwHhcNMTYxMDMxMTgxNTI2WhcNMjcwMjA2MTgxNTI2WjASMRAwDgYD
  339. VQQDEwd0ZXN0YXBwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqa0x
  340. FcVa0YcO/ABqSNdbf7Bzp2PBBJzVM9gI4/HzzBKU/NY9/RibBBpNjAIWEFAbTI4j
  341. ilFSoxHDQ8HrboFOeKCrOIdp9ATQ8SnYVNIQ12Ym3LA/XxcG0gG0H7DeS9C0uACe
  342. svN8fwD1wnKnLLU9GBzO77jwYkneed85wwKG4waHd3965gxQWq0N5gnYS0TTn7Yr
  343. l1veRiw+ryefXvfWI0cN1WBZJ/4XAkwVlpG1HP60AunIpcwn9bfG4XCka+7x26E4
  344. 6Hw0Ot7D7j0yzVzimJDPB2h2buEtPVd6m+oNPueVvKGta+p6cEEaHlFVh2Pa9DI+
  345. me3nb6aXE2kABWXav3BmK18A5Rg4ZY4VFYvmHmxkOhT/ulGZRqy6TccL/optqs52
  346. KQ6P0e5dfmhLeoCvJObD+ZYKv+kJCRFtX1Hve/R4IHG6XSFKUfrRjyor9b6TX2L/
  347. l2vV0mFjmy4g3l05vWHg1Edtq7M29S/xNA3/hF29NjBq6NoMbLGcBtFced1iK07Z
  348. yHLjXRZRfURP671Svqqg8pjxuDqkJ2vIj/Vpod4kF2jeiZYXcfmNKhEhxpkccSe0
  349. dI6p76Ne7XSUpf8yCPiSnWZLadqKZdEulcB4SlrZO2+/pycgqrqihofDrvDeWeeg
  350. gQyvbZZKl4ylRNj6IRKnosKLVXNqMHQxLmxLHeUCAwEAATANBgkqhkiG9w0BAQsF
  351. AAOCAQEALkKQwa40HfuP4Q6ShwBFJbXLyodIAXCT014kBVjReDKNl5oHtMXRjPxj
  352. nj9doKu+3bLNuLCv9uU3H5+t/GFogReV3Av3z/fCqJ6wHv/KX+lacj31dWXZGD8G
  353. z+RYibrxKkPN0V6q1mSvkg3hJOOE+/4FPIdc8PNlgratv3WS4dT8QwGSUavHW2Kx
  354. 89nIdnwtLEFpgML/bTG0dm8BH57xER8LCYixW1VmpV6A4IsoKVsnB7KUCRTK3iUJ
  355. Zh8Xg8UMNrOtXc1Wx1Wmjaa4ZE9dY6/KkU2ny2UWyDHKU/9VE8QQ4HN93gxU4+H7
  356. cUg0V1uAxqUvKytKkMfcyPWsz/AINA==
  357. -----END CERTIFICATE-----',
  358. 'releases' => [
  359. [
  360. 'download' => 'https://example.com',
  361. 'signature' => 'h8H3tUy2dDlwrV/hY/ZxqYqe8Vue+IINluLtAt1HxX2cjz3vdoVHJRINRkMYYcdz
  362. VlndvHyKdqJHDAACphR8tVV6EFrPermn7gEgWk7a51LbUM7sAN7RV7ijEooUo+TQ
  363. jNW9Ch48Wg3jvebMwWNr5t5U4MEXTP5f0YX/kxvkJoUrG3a3spt7ziEuHaq8IPvt
  364. Jj/JSDFhvRNpom7yNNcI1Ijoq8yC11sg7RJBNfrHdGPHPZVz2SyBiY9OcvgGSpUU
  365. bfvzhIZDCl/RRi5fs39jLLupAP69Ez6+jylNXEMsNwM0YL5+egSXFtkCvgOw8UBg
  366. ZqNZZojcS22acuvHRnoa6PDDhwHdCH+zpifXSOhSQvue5n6q+FVX6aeD1LnCQkYB
  367. D2wvNyZWwdADJtvDj03DKhm21g+TPy63XC94q4IqvjQ94pV8U+qrBBfkQ62NGjaC
  368. oOU6y5sEmQeAdVRpWVo0Hewmjp4Adoj5JRwuqCVEynTC6DXHs3HvHxYlmib1F05a
  369. GqEhdDmOHsxNaeJ08Hlptq5yLv3+0wEdtriVjgAZNVduHG1F1FkhPIrDHaB6pd67
  370. 0AFvO/pZgMSHDRHD+safBgaLb5dBZ895Qvudbq3RQevVnO+YZQYZkpmjoF/+TQ7/
  371. YwDVP+QmNRzx72jtqAN/Kc3CvQ9nkgYhU65B95aX0xA=',
  372. ],
  373. [
  374. 'download' => 'https://nextcloud.com',
  375. ],
  376. ],
  377. ],
  378. ];
  379. $this->appFetcher
  380. ->expects($this->once())
  381. ->method('get')
  382. ->willReturn($appArray);
  383. $realTmpFile = \OC::$server->getTempManager()->getTemporaryFile('.tar.gz');
  384. copy(__DIR__ . '/../data/testapp1.tar.gz', $realTmpFile);
  385. $this->tempManager
  386. ->expects($this->once())
  387. ->method('getTemporaryFile')
  388. ->with('.tar.gz')
  389. ->willReturn($realTmpFile);
  390. $realTmpFolder = \OC::$server->getTempManager()->getTemporaryFolder();
  391. mkdir($realTmpFolder . '/testfolder');
  392. $this->tempManager
  393. ->expects($this->once())
  394. ->method('getTemporaryFolder')
  395. ->willReturn($realTmpFolder);
  396. $client = $this->createMock(IClient::class);
  397. $client
  398. ->expects($this->once())
  399. ->method('get')
  400. ->with('https://example.com', ['sink' => $realTmpFile, 'timeout' => 120]);
  401. $this->clientService
  402. ->expects($this->once())
  403. ->method('newClient')
  404. ->willReturn($client);
  405. $installer = $this->getInstaller();
  406. $installer->downloadApp('testapp');
  407. }
  408. public function testDownloadAppWithMismatchingIdentifier(): void {
  409. $this->expectException(\Exception::class);
  410. $this->expectExceptionMessage('App for id testapp has a wrong app ID in info.xml: testapp1');
  411. $appArray = [
  412. [
  413. 'id' => 'testapp',
  414. 'certificate' => '-----BEGIN CERTIFICATE-----
  415. MIIEAjCCAuoCAhAbMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
  416. VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
  417. MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
  418. dXRob3JpdHkwHhcNMTYxMDMxMTgxNTI2WhcNMjcwMjA2MTgxNTI2WjASMRAwDgYD
  419. VQQDEwd0ZXN0YXBwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqa0x
  420. FcVa0YcO/ABqSNdbf7Bzp2PBBJzVM9gI4/HzzBKU/NY9/RibBBpNjAIWEFAbTI4j
  421. ilFSoxHDQ8HrboFOeKCrOIdp9ATQ8SnYVNIQ12Ym3LA/XxcG0gG0H7DeS9C0uACe
  422. svN8fwD1wnKnLLU9GBzO77jwYkneed85wwKG4waHd3965gxQWq0N5gnYS0TTn7Yr
  423. l1veRiw+ryefXvfWI0cN1WBZJ/4XAkwVlpG1HP60AunIpcwn9bfG4XCka+7x26E4
  424. 6Hw0Ot7D7j0yzVzimJDPB2h2buEtPVd6m+oNPueVvKGta+p6cEEaHlFVh2Pa9DI+
  425. me3nb6aXE2kABWXav3BmK18A5Rg4ZY4VFYvmHmxkOhT/ulGZRqy6TccL/optqs52
  426. KQ6P0e5dfmhLeoCvJObD+ZYKv+kJCRFtX1Hve/R4IHG6XSFKUfrRjyor9b6TX2L/
  427. l2vV0mFjmy4g3l05vWHg1Edtq7M29S/xNA3/hF29NjBq6NoMbLGcBtFced1iK07Z
  428. yHLjXRZRfURP671Svqqg8pjxuDqkJ2vIj/Vpod4kF2jeiZYXcfmNKhEhxpkccSe0
  429. dI6p76Ne7XSUpf8yCPiSnWZLadqKZdEulcB4SlrZO2+/pycgqrqihofDrvDeWeeg
  430. gQyvbZZKl4ylRNj6IRKnosKLVXNqMHQxLmxLHeUCAwEAATANBgkqhkiG9w0BAQsF
  431. AAOCAQEALkKQwa40HfuP4Q6ShwBFJbXLyodIAXCT014kBVjReDKNl5oHtMXRjPxj
  432. nj9doKu+3bLNuLCv9uU3H5+t/GFogReV3Av3z/fCqJ6wHv/KX+lacj31dWXZGD8G
  433. z+RYibrxKkPN0V6q1mSvkg3hJOOE+/4FPIdc8PNlgratv3WS4dT8QwGSUavHW2Kx
  434. 89nIdnwtLEFpgML/bTG0dm8BH57xER8LCYixW1VmpV6A4IsoKVsnB7KUCRTK3iUJ
  435. Zh8Xg8UMNrOtXc1Wx1Wmjaa4ZE9dY6/KkU2ny2UWyDHKU/9VE8QQ4HN93gxU4+H7
  436. cUg0V1uAxqUvKytKkMfcyPWsz/AINA==
  437. -----END CERTIFICATE-----',
  438. 'releases' => [
  439. [
  440. 'download' => 'https://example.com',
  441. 'signature' => 'h8H3tUy2dDlwrV/hY/ZxqYqe8Vue+IINluLtAt1HxX2cjz3vdoVHJRINRkMYYcdz
  442. VlndvHyKdqJHDAACphR8tVV6EFrPermn7gEgWk7a51LbUM7sAN7RV7ijEooUo+TQ
  443. jNW9Ch48Wg3jvebMwWNr5t5U4MEXTP5f0YX/kxvkJoUrG3a3spt7ziEuHaq8IPvt
  444. Jj/JSDFhvRNpom7yNNcI1Ijoq8yC11sg7RJBNfrHdGPHPZVz2SyBiY9OcvgGSpUU
  445. bfvzhIZDCl/RRi5fs39jLLupAP69Ez6+jylNXEMsNwM0YL5+egSXFtkCvgOw8UBg
  446. ZqNZZojcS22acuvHRnoa6PDDhwHdCH+zpifXSOhSQvue5n6q+FVX6aeD1LnCQkYB
  447. D2wvNyZWwdADJtvDj03DKhm21g+TPy63XC94q4IqvjQ94pV8U+qrBBfkQ62NGjaC
  448. oOU6y5sEmQeAdVRpWVo0Hewmjp4Adoj5JRwuqCVEynTC6DXHs3HvHxYlmib1F05a
  449. GqEhdDmOHsxNaeJ08Hlptq5yLv3+0wEdtriVjgAZNVduHG1F1FkhPIrDHaB6pd67
  450. 0AFvO/pZgMSHDRHD+safBgaLb5dBZ895Qvudbq3RQevVnO+YZQYZkpmjoF/+TQ7/
  451. YwDVP+QmNRzx72jtqAN/Kc3CvQ9nkgYhU65B95aX0xA=',
  452. ],
  453. [
  454. 'download' => 'https://nextcloud.com',
  455. ],
  456. ],
  457. ],
  458. ];
  459. $this->appFetcher
  460. ->expects($this->once())
  461. ->method('get')
  462. ->willReturn($appArray);
  463. $realTmpFile = \OC::$server->getTempManager()->getTemporaryFile('.tar.gz');
  464. copy(__DIR__ . '/../data/testapp1.tar.gz', $realTmpFile);
  465. $this->tempManager
  466. ->expects($this->once())
  467. ->method('getTemporaryFile')
  468. ->with('.tar.gz')
  469. ->willReturn($realTmpFile);
  470. $realTmpFolder = \OC::$server->getTempManager()->getTemporaryFolder();
  471. $this->tempManager
  472. ->expects($this->once())
  473. ->method('getTemporaryFolder')
  474. ->willReturn($realTmpFolder);
  475. $client = $this->createMock(IClient::class);
  476. $client
  477. ->expects($this->once())
  478. ->method('get')
  479. ->with('https://example.com', ['sink' => $realTmpFile, 'timeout' => 120]);
  480. $this->clientService
  481. ->expects($this->once())
  482. ->method('newClient')
  483. ->willReturn($client);
  484. $installer = $this->getInstaller();
  485. $installer->downloadApp('testapp');
  486. }
  487. public function testDownloadAppSuccessful(): void {
  488. $appArray = [
  489. [
  490. 'id' => 'testapp',
  491. 'certificate' => '-----BEGIN CERTIFICATE-----
  492. MIIEAjCCAuoCAhAbMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
  493. VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
  494. MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
  495. dXRob3JpdHkwHhcNMTYxMDMxMTgxNTI2WhcNMjcwMjA2MTgxNTI2WjASMRAwDgYD
  496. VQQDEwd0ZXN0YXBwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqa0x
  497. FcVa0YcO/ABqSNdbf7Bzp2PBBJzVM9gI4/HzzBKU/NY9/RibBBpNjAIWEFAbTI4j
  498. ilFSoxHDQ8HrboFOeKCrOIdp9ATQ8SnYVNIQ12Ym3LA/XxcG0gG0H7DeS9C0uACe
  499. svN8fwD1wnKnLLU9GBzO77jwYkneed85wwKG4waHd3965gxQWq0N5gnYS0TTn7Yr
  500. l1veRiw+ryefXvfWI0cN1WBZJ/4XAkwVlpG1HP60AunIpcwn9bfG4XCka+7x26E4
  501. 6Hw0Ot7D7j0yzVzimJDPB2h2buEtPVd6m+oNPueVvKGta+p6cEEaHlFVh2Pa9DI+
  502. me3nb6aXE2kABWXav3BmK18A5Rg4ZY4VFYvmHmxkOhT/ulGZRqy6TccL/optqs52
  503. KQ6P0e5dfmhLeoCvJObD+ZYKv+kJCRFtX1Hve/R4IHG6XSFKUfrRjyor9b6TX2L/
  504. l2vV0mFjmy4g3l05vWHg1Edtq7M29S/xNA3/hF29NjBq6NoMbLGcBtFced1iK07Z
  505. yHLjXRZRfURP671Svqqg8pjxuDqkJ2vIj/Vpod4kF2jeiZYXcfmNKhEhxpkccSe0
  506. dI6p76Ne7XSUpf8yCPiSnWZLadqKZdEulcB4SlrZO2+/pycgqrqihofDrvDeWeeg
  507. gQyvbZZKl4ylRNj6IRKnosKLVXNqMHQxLmxLHeUCAwEAATANBgkqhkiG9w0BAQsF
  508. AAOCAQEALkKQwa40HfuP4Q6ShwBFJbXLyodIAXCT014kBVjReDKNl5oHtMXRjPxj
  509. nj9doKu+3bLNuLCv9uU3H5+t/GFogReV3Av3z/fCqJ6wHv/KX+lacj31dWXZGD8G
  510. z+RYibrxKkPN0V6q1mSvkg3hJOOE+/4FPIdc8PNlgratv3WS4dT8QwGSUavHW2Kx
  511. 89nIdnwtLEFpgML/bTG0dm8BH57xER8LCYixW1VmpV6A4IsoKVsnB7KUCRTK3iUJ
  512. Zh8Xg8UMNrOtXc1Wx1Wmjaa4ZE9dY6/KkU2ny2UWyDHKU/9VE8QQ4HN93gxU4+H7
  513. cUg0V1uAxqUvKytKkMfcyPWsz/AINA==
  514. -----END CERTIFICATE-----',
  515. 'releases' => [
  516. [
  517. 'download' => 'https://example.com',
  518. 'signature' => 'O5UWFRnSx4mSdEX83Uh9u7KW+Gl1OWU4uaFg6aYY19zc+lWP4rKCbAUH7Jo1Bohf
  519. qxQbhXs4cMqGmoL8dW4zeFUqSJCRk52LA+ciLezjPFv275q+BxEgyWOylLnbhBaz
  520. +v6lXLaeG0J/ry8wEdg+rwP8FCYPsvKlXSVbFjgubvCR/owKJJf5iL0B93noBwBN
  521. jfbcxi7Kh16HAKy6f/gVZ6hf/4Uo7iEFMCPEHjidope+ejUpqbd8XhQg5/yh7TQ7
  522. VKR7pkdDG2eFr5c3CpaECdNg5ZIGRbQNJHBXHT/wliorWpYJtwtNAQJ4xC635gLP
  523. 4klkKN4XtSj8bJUaJC6aaksLFgRSeKXaYAHai/XP6BkeyNzlSbsmyZk8cZbySx8F
  524. gVOzPok1c94UGT57FjeW5eqRjtmzbYivQdP89Ouz6et7PY69yOCqiRFQanrqzwoX
  525. MPLX6f5V9tCJtlH6ztmEcDROfvuVc0U3rEhqx2hphoyo+MZrPFpdcJL8KkIdMKbY
  526. 7yQWrsV7QvAzygAOFsC0TlSNJbmMCljouUk9di4CUZ+xsQ6n6TZtE7gsdljlKjPS
  527. 3Ys+e3V1HUaVzv8SaSmKwjRoQxQxHWLtXpJS2Yq+i+gq7LuC+aStzxAzV/h2plDW
  528. 358picx/PobNDi71Q97+/CAOq+4wDOwhKwls7lwudIs=',
  529. ],
  530. [
  531. 'download' => 'https://nextcloud.com',
  532. ],
  533. ],
  534. ],
  535. ];
  536. $this->appFetcher
  537. ->expects($this->once())
  538. ->method('get')
  539. ->willReturn($appArray);
  540. $realTmpFile = \OC::$server->getTempManager()->getTemporaryFile('.tar.gz');
  541. copy(__DIR__ . '/../data/testapp.tar.gz', $realTmpFile);
  542. $this->tempManager
  543. ->expects($this->once())
  544. ->method('getTemporaryFile')
  545. ->with('.tar.gz')
  546. ->willReturn($realTmpFile);
  547. $realTmpFolder = \OC::$server->getTempManager()->getTemporaryFolder();
  548. $this->tempManager
  549. ->expects($this->once())
  550. ->method('getTemporaryFolder')
  551. ->willReturn($realTmpFolder);
  552. $client = $this->createMock(IClient::class);
  553. $client
  554. ->expects($this->once())
  555. ->method('get')
  556. ->with('https://example.com', ['sink' => $realTmpFile, 'timeout' => 120]);
  557. $this->clientService
  558. ->expects($this->once())
  559. ->method('newClient')
  560. ->willReturn($client);
  561. $installer = $this->getInstaller();
  562. $installer->downloadApp('testapp');
  563. $this->assertTrue(file_exists(__DIR__ . '/../../apps/testapp/appinfo/info.xml'));
  564. $this->assertEquals('0.9', \OC_App::getAppVersionByPath(__DIR__ . '/../../apps/testapp/'));
  565. }
  566. public function testDownloadAppWithDowngrade(): void {
  567. // Use previous test to download the application in version 0.9
  568. $this->testDownloadAppSuccessful();
  569. // Reset mocks
  570. $this->appFetcher = $this->createMock(AppFetcher::class);
  571. $this->clientService = $this->createMock(IClientService::class);
  572. $this->tempManager = $this->createMock(ITempManager::class);
  573. $this->expectException(\Exception::class);
  574. $this->expectExceptionMessage('App for id testapp has version 0.9 and tried to update to lower version 0.8');
  575. $appArray = [
  576. [
  577. 'id' => 'testapp',
  578. 'certificate' => '-----BEGIN CERTIFICATE-----
  579. MIIEAjCCAuoCAhAbMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
  580. VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
  581. MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
  582. dXRob3JpdHkwHhcNMTYxMDMxMTgxNTI2WhcNMjcwMjA2MTgxNTI2WjASMRAwDgYD
  583. VQQDEwd0ZXN0YXBwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqa0x
  584. FcVa0YcO/ABqSNdbf7Bzp2PBBJzVM9gI4/HzzBKU/NY9/RibBBpNjAIWEFAbTI4j
  585. ilFSoxHDQ8HrboFOeKCrOIdp9ATQ8SnYVNIQ12Ym3LA/XxcG0gG0H7DeS9C0uACe
  586. svN8fwD1wnKnLLU9GBzO77jwYkneed85wwKG4waHd3965gxQWq0N5gnYS0TTn7Yr
  587. l1veRiw+ryefXvfWI0cN1WBZJ/4XAkwVlpG1HP60AunIpcwn9bfG4XCka+7x26E4
  588. 6Hw0Ot7D7j0yzVzimJDPB2h2buEtPVd6m+oNPueVvKGta+p6cEEaHlFVh2Pa9DI+
  589. me3nb6aXE2kABWXav3BmK18A5Rg4ZY4VFYvmHmxkOhT/ulGZRqy6TccL/optqs52
  590. KQ6P0e5dfmhLeoCvJObD+ZYKv+kJCRFtX1Hve/R4IHG6XSFKUfrRjyor9b6TX2L/
  591. l2vV0mFjmy4g3l05vWHg1Edtq7M29S/xNA3/hF29NjBq6NoMbLGcBtFced1iK07Z
  592. yHLjXRZRfURP671Svqqg8pjxuDqkJ2vIj/Vpod4kF2jeiZYXcfmNKhEhxpkccSe0
  593. dI6p76Ne7XSUpf8yCPiSnWZLadqKZdEulcB4SlrZO2+/pycgqrqihofDrvDeWeeg
  594. gQyvbZZKl4ylRNj6IRKnosKLVXNqMHQxLmxLHeUCAwEAATANBgkqhkiG9w0BAQsF
  595. AAOCAQEALkKQwa40HfuP4Q6ShwBFJbXLyodIAXCT014kBVjReDKNl5oHtMXRjPxj
  596. nj9doKu+3bLNuLCv9uU3H5+t/GFogReV3Av3z/fCqJ6wHv/KX+lacj31dWXZGD8G
  597. z+RYibrxKkPN0V6q1mSvkg3hJOOE+/4FPIdc8PNlgratv3WS4dT8QwGSUavHW2Kx
  598. 89nIdnwtLEFpgML/bTG0dm8BH57xER8LCYixW1VmpV6A4IsoKVsnB7KUCRTK3iUJ
  599. Zh8Xg8UMNrOtXc1Wx1Wmjaa4ZE9dY6/KkU2ny2UWyDHKU/9VE8QQ4HN93gxU4+H7
  600. cUg0V1uAxqUvKytKkMfcyPWsz/AINA==
  601. -----END CERTIFICATE-----',
  602. 'releases' => [
  603. [
  604. 'download' => 'https://example.com',
  605. 'signature' => 'KMSao4cKdMIYxeT8Bm4lrmSeIQnk7YzJZh+Vz+4LVSBwF+OMmcujryQuWLXmbPfg
  606. 4hGI9zS025469VNjUoCprn01H8NBq3O1cXz+ewG1oxYWMMQFZDkOtUQ+XZ27b91t
  607. y0l45H6C8j0sTeSrUb/LCjrdm+buUygkhC2RZxCI6tLi4rYWj0MiqDz98XkbB3te
  608. pW3ZND6mG6Jxn1fnd35paqZ/+URMftoLQ4K+6vJoBVGnug9nk1RpGLouICI0zCrz
  609. YPTsBHo0s2mPvQQ/ASacWYmSe5R6r5JCzNeGMpViGCqCYPbwuebgqK079s2zvSF9
  610. mSLAm2Tk6gCM29N8Vdfr6ppCvIbuNzlLU/dGdYHAILgxEsm/odZjt1Fhs4lOo3A5
  611. 9ToaNl5+qOEkggwfE/QqceHAY2soW9V5d9izhTCDgXmxpPpPXkwPPTz04ZUpi1Yc
  612. OdZZOswbEcc2jUC5T7a7Tnp0uBOkdqat6jB4oMGwU1ldYLCGRyy546cPPTXJw5kH
  613. 9WfeKJ/mavrSLVa7QqZ4RCcMigmijT1kdqbaEh05IZNrzs6VDcS2EIrbDX8SGXUk
  614. uDDkPXZEXqNDEjyONfDXVRLiqDa52Gg+I4vW/l/4ZOFgAWdZkqPPuZFaqzZpsJXm
  615. JXhrdaWDZ8fzpUjugrtC3qslsqL0dzgU37anS3HwrT8=',
  616. ],
  617. [
  618. 'download' => 'https://nextcloud.com',
  619. ],
  620. ],
  621. ],
  622. ];
  623. $this->appFetcher
  624. ->expects($this->once())
  625. ->method('get')
  626. ->willReturn($appArray);
  627. $realTmpFile = \OC::$server->getTempManager()->getTemporaryFile('.tar.gz');
  628. copy(__DIR__ . '/../data/testapp.0.8.tar.gz', $realTmpFile);
  629. $this->tempManager
  630. ->expects($this->once())
  631. ->method('getTemporaryFile')
  632. ->with('.tar.gz')
  633. ->willReturn($realTmpFile);
  634. $realTmpFolder = \OC::$server->getTempManager()->getTemporaryFolder();
  635. $this->tempManager
  636. ->expects($this->once())
  637. ->method('getTemporaryFolder')
  638. ->willReturn($realTmpFolder);
  639. $client = $this->createMock(IClient::class);
  640. $client
  641. ->expects($this->once())
  642. ->method('get')
  643. ->with('https://example.com', ['sink' => $realTmpFile, 'timeout' => 120]);
  644. $this->clientService
  645. ->expects($this->once())
  646. ->method('newClient')
  647. ->willReturn($client);
  648. $this->assertTrue(file_exists(__DIR__ . '/../../apps/testapp/appinfo/info.xml'));
  649. $this->assertEquals('0.9', \OC_App::getAppVersionByPath(__DIR__ . '/../../apps/testapp/'));
  650. $installer = $this->getInstaller();
  651. $installer->downloadApp('testapp');
  652. $this->assertTrue(file_exists(__DIR__ . '/../../apps/testapp/appinfo/info.xml'));
  653. $this->assertEquals('0.8', \OC_App::getAppVersionByPath(__DIR__ . '/../../apps/testapp/'));
  654. }
  655. }