updater.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. <?php
  2. /**
  3. * @author Lukas Reschke <lukas@owncloud.com>
  4. * @author Victor Dubiniuk <dubiniuk@owncloud.com>
  5. *
  6. * @copyright Copyright (c) 2015, ownCloud, Inc.
  7. * @license AGPL-3.0
  8. *
  9. * This code is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License, version 3,
  11. * as published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Affero General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License, version 3,
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>
  20. *
  21. */
  22. namespace OC;
  23. use OCP\IConfig;
  24. use OCP\ILogger;
  25. use OC\IntegrityCheck\Checker;
  26. class UpdaterTest extends \Test\TestCase {
  27. /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
  28. private $config;
  29. /** @var HTTPHelper */
  30. private $httpHelper;
  31. /** @var ILogger */
  32. private $logger;
  33. /** @var Updater */
  34. private $updater;
  35. /** @var Checker */
  36. private $checker;
  37. public function setUp() {
  38. parent::setUp();
  39. $this->config = $this->getMockBuilder('\\OCP\\IConfig')
  40. ->disableOriginalConstructor()
  41. ->getMock();
  42. $this->httpHelper = $this->getMockBuilder('\\OC\\HTTPHelper')
  43. ->disableOriginalConstructor()
  44. ->getMock();
  45. $this->logger = $this->getMockBuilder('\\OCP\\ILogger')
  46. ->disableOriginalConstructor()
  47. ->getMock();
  48. $this->checker = $this->getMockBuilder('\OC\IntegrityCheck\Checker')
  49. ->disableOriginalConstructor()
  50. ->getMock();
  51. $this->updater = new Updater(
  52. $this->httpHelper,
  53. $this->config,
  54. $this->checker,
  55. $this->logger
  56. );
  57. }
  58. /**
  59. * @param string $baseUrl
  60. * @return string
  61. */
  62. private function buildUpdateUrl($baseUrl) {
  63. return $baseUrl . '?version='.implode('x', \OCP\Util::getVersion()).'xinstalledatxlastupdatedatx'.\OC_Util::getChannel().'x'.\OC_Util::getEditionString().'x';
  64. }
  65. /**
  66. * @return array
  67. */
  68. public function versionCompatibilityTestData() {
  69. return [
  70. ['1', '2', '1', true],
  71. ['2', '2', '2', true],
  72. ['6.0.5.0', '6.0.6.0', '5.0', true],
  73. ['5.0.6.0', '7.0.4.0', '6.0', false],
  74. // allow upgrading within the same major release
  75. ['8.0.0.0', '8.0.0.0', '8.0', true],
  76. ['8.0.0.0', '8.0.0.4', '8.0', true],
  77. ['8.0.0.0', '8.0.1.0', '8.0', true],
  78. ['8.0.0.0', '8.0.2.0', '8.0', true],
  79. // does not allow downgrading within the same major release
  80. ['8.0.1.0', '8.0.0.0', '8.0', false],
  81. ['8.0.2.0', '8.0.1.0', '8.0', false],
  82. ['8.0.0.4', '8.0.0.0', '8.0', false],
  83. // allows upgrading within the patch version
  84. ['8.0.0.0', '8.0.0.1', '8.0', true],
  85. ['8.0.0.0', '8.0.0.2', '8.0', true],
  86. // does not allow downgrading within the same major release
  87. ['8.0.0.1', '8.0.0.0', '8.0', false],
  88. ['8.0.0.2', '8.0.0.0', '8.0', false],
  89. // allow upgrading to the next major release
  90. ['8.0.0.0', '8.1.0.0', '8.0', true],
  91. ['8.0.0.0', '8.1.1.0', '8.0', true],
  92. ['8.0.0.0', '8.1.1.5', '8.0', true],
  93. ['8.0.0.2', '8.1.1.5', '8.0', true],
  94. ['8.1.0.0', '8.2.0.0', '8.1', true],
  95. ['8.1.0.2', '8.2.0.4', '8.1', true],
  96. ['8.1.0.5', '8.2.0.1', '8.1', true],
  97. ['8.1.0.0', '8.2.1.0', '8.1', true],
  98. ['8.1.0.2', '8.2.1.5', '8.1', true],
  99. ['8.1.0.5', '8.2.1.1', '8.1', true],
  100. // does not allow downgrading to the previous major release
  101. ['8.1.0.0', '8.0.0.0', '7.0', false],
  102. ['8.1.1.0', '8.0.0.0', '7.0', false],
  103. // does not allow skipping major releases
  104. ['8.0.0.0', '8.2.0.0', '8.1', false],
  105. ['8.0.0.0', '8.2.1.0', '8.1', false],
  106. ['8.0.0.0', '9.0.1.0', '8.2', false],
  107. ['8.0.0.0', '10.0.0.0', '9.3', false],
  108. // allows updating to the next major release
  109. ['8.2.0.0', '9.0.0.0', '8.2', true],
  110. ['8.2.0.0', '9.0.0.0', '8.2', true],
  111. ['8.2.0.0', '9.0.1.0', '8.2', true],
  112. ['8.2.0.0', '9.0.1.1', '8.2', true],
  113. ['8.2.0.2', '9.0.1.1', '8.2', true],
  114. ['8.2.2.0', '9.0.1.0', '8.2', true],
  115. ['8.2.2.2', '9.0.1.1', '8.2', true],
  116. ['9.0.0.0', '9.1.0.0', '9.0', true],
  117. ['9.0.0.0', '9.1.0.2', '9.0', true],
  118. ['9.0.0.2', '9.1.0.1', '9.0', true],
  119. ['9.1.0.0', '9.2.0.0', '9.1', true],
  120. ['9.2.0.0', '9.3.0.0', '9.2', true],
  121. ['9.3.0.0', '10.0.0.0', '9.3', true],
  122. // does not allow updating to the next major release (first number)
  123. ['9.0.0.0', '8.2.0.0', '8.1', false],
  124. // other cases
  125. ['8.0.0.0', '8.1.5.0', '8.0', true],
  126. ['8.2.0.0', '9.0.0.0', '8.2', true],
  127. ['8.2.0.0', '9.1.0.0', '9.0', false],
  128. ['9.0.0.0', '8.1.0.0', '8.0', false],
  129. ['9.0.0.0', '8.0.0.0', '7.0', false],
  130. ['9.1.0.0', '8.0.0.0', '7.0', false],
  131. ['8.2.0.0', '8.1.0.0', '8.0', false],
  132. // With debug enabled
  133. ['8.0.0.0', '8.2.0.0', '8.1', false, true],
  134. ['8.1.0.0', '8.2.0.0', '8.1', true, true],
  135. ['8.2.0.1', '8.2.0.1', '8.1', true, true],
  136. ['8.3.0.0', '8.2.0.0', '8.1', true, true],
  137. ];
  138. }
  139. /**
  140. * @dataProvider versionCompatibilityTestData
  141. *
  142. * @param string $oldVersion
  143. * @param string $newVersion
  144. * @param string $allowedVersion
  145. * @param bool $result
  146. * @param bool $debug
  147. */
  148. public function testIsUpgradePossible($oldVersion, $newVersion, $allowedVersion, $result, $debug = false) {
  149. $this->config->expects($this->any())
  150. ->method('getSystemValue')
  151. ->with('debug', false)
  152. ->willReturn($debug);
  153. $this->assertSame($result, $this->updater->isUpgradePossible($oldVersion, $newVersion, $allowedVersion));
  154. }
  155. public function testSetSimulateStepEnabled() {
  156. $this->updater->setSimulateStepEnabled(true);
  157. $this->assertSame(true, $this->invokePrivate($this->updater, 'simulateStepEnabled'));
  158. $this->updater->setSimulateStepEnabled(false);
  159. $this->assertSame(false, $this->invokePrivate($this->updater, 'simulateStepEnabled'));
  160. }
  161. public function testSetUpdateStepEnabled() {
  162. $this->updater->setUpdateStepEnabled(true);
  163. $this->assertSame(true, $this->invokePrivate($this->updater, 'updateStepEnabled'));
  164. $this->updater->setUpdateStepEnabled(false);
  165. $this->assertSame(false, $this->invokePrivate($this->updater, 'updateStepEnabled'));
  166. }
  167. public function testSetSkip3rdPartyAppsDisable() {
  168. $this->updater->setSkip3rdPartyAppsDisable(true);
  169. $this->assertSame(true, $this->invokePrivate($this->updater, 'skip3rdPartyAppsDisable'));
  170. $this->updater->setSkip3rdPartyAppsDisable(false);
  171. $this->assertSame(false, $this->invokePrivate($this->updater, 'skip3rdPartyAppsDisable'));
  172. }
  173. public function testCheckInCache() {
  174. $expectedResult = [
  175. 'version' => '8.0.4.2',
  176. 'versionstring' => 'ownCloud 8.0.4',
  177. 'url' => 'https://download.owncloud.org/community/owncloud-8.0.4.zip',
  178. 'web' => 'http://doc.owncloud.org/server/8.0/admin_manual/maintenance/upgrade.html',
  179. ];
  180. $this->config
  181. ->expects($this->at(0))
  182. ->method('getAppValue')
  183. ->with('core', 'lastupdatedat')
  184. ->will($this->returnValue(time()));
  185. $this->config
  186. ->expects($this->at(1))
  187. ->method('getAppValue')
  188. ->with('core', 'lastupdateResult')
  189. ->will($this->returnValue(json_encode($expectedResult)));
  190. $this->assertSame($expectedResult, $this->updater->check());
  191. }
  192. public function testCheckWithoutUpdateUrl() {
  193. $expectedResult = [
  194. 'version' => '8.0.4.2',
  195. 'versionstring' => 'ownCloud 8.0.4',
  196. 'url' => 'https://download.owncloud.org/community/owncloud-8.0.4.zip',
  197. 'web' => 'http://doc.owncloud.org/server/8.0/admin_manual/maintenance/upgrade.html',
  198. 'autoupdater' => '0',
  199. ];
  200. $this->config
  201. ->expects($this->at(0))
  202. ->method('getAppValue')
  203. ->with('core', 'lastupdatedat')
  204. ->will($this->returnValue(0));
  205. $this->config
  206. ->expects($this->at(1))
  207. ->method('getSystemValue')
  208. ->with('updater.server.url', 'https://updates.nextcloud.com/updater_server/')
  209. ->willReturnArgument(1);
  210. $this->config
  211. ->expects($this->at(2))
  212. ->method('setAppValue')
  213. ->with('core', 'lastupdatedat', $this->isType('integer'));
  214. $this->config
  215. ->expects($this->at(4))
  216. ->method('getAppValue')
  217. ->with('core', 'installedat')
  218. ->will($this->returnValue('installedat'));
  219. $this->config
  220. ->expects($this->at(5))
  221. ->method('getAppValue')
  222. ->with('core', 'lastupdatedat')
  223. ->will($this->returnValue('lastupdatedat'));
  224. $this->config
  225. ->expects($this->at(6))
  226. ->method('setAppValue')
  227. ->with('core', 'lastupdateResult', json_encode($expectedResult));
  228. $updateXml = '<?xml version="1.0"?>
  229. <owncloud>
  230. <version>8.0.4.2</version>
  231. <versionstring>ownCloud 8.0.4</versionstring>
  232. <url>https://download.owncloud.org/community/owncloud-8.0.4.zip</url>
  233. <web>http://doc.owncloud.org/server/8.0/admin_manual/maintenance/upgrade.html</web>
  234. <autoupdater>0</autoupdater>
  235. </owncloud>';
  236. $this->httpHelper
  237. ->expects($this->once())
  238. ->method('getUrlContent')
  239. ->with($this->buildUpdateUrl('https://updates.nextcloud.com/updater_server/'))
  240. ->will($this->returnValue($updateXml));
  241. $this->assertSame($expectedResult, $this->updater->check());
  242. }
  243. public function testCheckWithInvalidXml() {
  244. $this->config
  245. ->expects($this->at(0))
  246. ->method('getAppValue')
  247. ->with('core', 'lastupdatedat')
  248. ->will($this->returnValue(0));
  249. $this->config
  250. ->expects($this->at(1))
  251. ->method('getSystemValue')
  252. ->with('updater.server.url', 'https://updates.nextcloud.com/updater_server/')
  253. ->willReturnArgument(1);
  254. $this->config
  255. ->expects($this->at(2))
  256. ->method('setAppValue')
  257. ->with('core', 'lastupdatedat', $this->isType('integer'));
  258. $this->config
  259. ->expects($this->at(4))
  260. ->method('getAppValue')
  261. ->with('core', 'installedat')
  262. ->will($this->returnValue('installedat'));
  263. $this->config
  264. ->expects($this->at(5))
  265. ->method('getAppValue')
  266. ->with('core', 'lastupdatedat')
  267. ->will($this->returnValue('lastupdatedat'));
  268. $this->config
  269. ->expects($this->at(6))
  270. ->method('setAppValue')
  271. ->with('core', 'lastupdateResult', 'false');
  272. $updateXml = 'Invalid XML Response!';
  273. $this->httpHelper
  274. ->expects($this->once())
  275. ->method('getUrlContent')
  276. ->with($this->buildUpdateUrl('https://updates.nextcloud.com/updater_server/'))
  277. ->will($this->returnValue($updateXml));
  278. $this->assertSame([], $this->updater->check());
  279. }
  280. public function testCheckWithEmptyValidXmlResponse() {
  281. $expectedResult = [
  282. 'version' => '',
  283. 'versionstring' => '',
  284. 'url' => '',
  285. 'web' => '',
  286. 'autoupdater' => '',
  287. ];
  288. $this->config
  289. ->expects($this->at(0))
  290. ->method('getAppValue')
  291. ->with('core', 'lastupdatedat')
  292. ->will($this->returnValue(0));
  293. $this->config
  294. ->expects($this->at(1))
  295. ->method('getSystemValue')
  296. ->with('updater.server.url', 'https://updates.nextcloud.com/updater_server/')
  297. ->willReturnArgument(1);
  298. $this->config
  299. ->expects($this->at(2))
  300. ->method('setAppValue')
  301. ->with('core', 'lastupdatedat', $this->isType('integer'));
  302. $this->config
  303. ->expects($this->at(4))
  304. ->method('getAppValue')
  305. ->with('core', 'installedat')
  306. ->will($this->returnValue('installedat'));
  307. $this->config
  308. ->expects($this->at(5))
  309. ->method('getAppValue')
  310. ->with('core', 'lastupdatedat')
  311. ->will($this->returnValue('lastupdatedat'));
  312. $updateXml = '<?xml version="1.0"?>
  313. <owncloud>
  314. <version></version>
  315. <versionstring></versionstring>
  316. <url></url>
  317. <web></web>
  318. <autoupdater></autoupdater>
  319. </owncloud>';
  320. $this->httpHelper
  321. ->expects($this->once())
  322. ->method('getUrlContent')
  323. ->with($this->buildUpdateUrl('https://updates.nextcloud.com/updater_server/'))
  324. ->will($this->returnValue($updateXml));
  325. $this->assertSame($expectedResult, $this->updater->check());
  326. }
  327. public function testCheckWithEmptyInvalidXmlResponse() {
  328. $expectedResult = [];
  329. $this->config
  330. ->expects($this->at(0))
  331. ->method('getAppValue')
  332. ->with('core', 'lastupdatedat')
  333. ->will($this->returnValue(0));
  334. $this->config
  335. ->expects($this->at(1))
  336. ->method('getSystemValue')
  337. ->with('updater.server.url', 'https://updates.nextcloud.com/updater_server/')
  338. ->willReturnArgument(1);
  339. $this->config
  340. ->expects($this->at(2))
  341. ->method('setAppValue')
  342. ->with('core', 'lastupdatedat', $this->isType('integer'));
  343. $this->config
  344. ->expects($this->at(4))
  345. ->method('getAppValue')
  346. ->with('core', 'installedat')
  347. ->will($this->returnValue('installedat'));
  348. $this->config
  349. ->expects($this->at(5))
  350. ->method('getAppValue')
  351. ->with('core', 'lastupdatedat')
  352. ->will($this->returnValue('lastupdatedat'));
  353. $this->config
  354. ->expects($this->at(6))
  355. ->method('setAppValue')
  356. ->with('core', 'lastupdateResult', json_encode($expectedResult));
  357. $updateXml = '';
  358. $this->httpHelper
  359. ->expects($this->once())
  360. ->method('getUrlContent')
  361. ->with($this->buildUpdateUrl('https://updates.nextcloud.com/updater_server/'))
  362. ->will($this->returnValue($updateXml));
  363. $this->assertSame($expectedResult, $this->updater->check());
  364. }
  365. }