diff --git a/lib/private/updater.php b/lib/private/updater.php index 2894a82338..fa9c1a5176 100644 --- a/lib/private/updater.php +++ b/lib/private/updater.php @@ -74,7 +74,9 @@ class Updater extends BasicEmitter { * @param IConfig $config * @param ILogger $log */ - public function __construct(HTTPHelper $httpHelper, IConfig $config, ILogger $log = null) { + public function __construct(HTTPHelper $httpHelper, + IConfig $config, + ILogger $log = null) { $this->httpHelper = $httpHelper; $this->log = $log; $this->config = $config; @@ -127,12 +129,12 @@ class Updater extends BasicEmitter { } if (is_null($updaterUrl)) { - $updaterUrl = 'https://apps.owncloud.com/updater.php'; + $updaterUrl = 'https://updates.owncloud.com/server/'; } $this->config->setAppValue('core', 'lastupdatedat', time()); - if ($this->config->getAppValue('core', 'installedat', '') == '') { + if ($this->config->getAppValue('core', 'installedat', '') === '') { $this->config->setAppValue('core', 'installedat', microtime(true)); } @@ -147,22 +149,20 @@ class Updater extends BasicEmitter { //fetch xml data from updater $url = $updaterUrl . '?version=' . $versionString; - // set a sensible timeout of 10 sec to stay responsive even if the update server is down. - - $tmp = array(); + $tmp = []; $xml = $this->httpHelper->getUrlContent($url); if ($xml) { $loadEntities = libxml_disable_entity_loader(true); $data = @simplexml_load_string($xml); libxml_disable_entity_loader($loadEntities); if ($data !== false) { - $tmp['version'] = $data->version; - $tmp['versionstring'] = $data->versionstring; - $tmp['url'] = $data->url; - $tmp['web'] = $data->web; + $tmp['version'] = (string)$data->version; + $tmp['versionstring'] = (string)$data->versionstring; + $tmp['url'] = (string)$data->url; + $tmp['web'] = (string)$data->web; } } else { - $data = array(); + $data = []; } // Cache the result @@ -360,7 +360,6 @@ class Updater extends BasicEmitter { include \OC_App::getAppPath($appId) . '/appinfo/preupdate.php'; } - /** * upgrades all apps within a major ownCloud upgrade. Also loads "priority" * (types authentication, filesystem, logging, in that order) afterwards. @@ -411,6 +410,9 @@ class Updater extends BasicEmitter { * ownCloud version. disable them if not. * This is important if you upgrade ownCloud and have non ported 3rd * party apps installed. + * + * @return array + * @throws \Exception */ private function checkAppsRequirements() { $isCoreUpgrade = $this->isCodeUpgrade(); @@ -447,6 +449,9 @@ class Updater extends BasicEmitter { return $disabledApps; } + /** + * @return bool + */ private function isCodeUpgrade() { $installedVersion = $this->config->getSystemValue('version', '0.0.0'); $currentVersion = implode('.', OC_Util::getVersion()); @@ -456,7 +461,11 @@ class Updater extends BasicEmitter { return false; } - private function upgradeAppStoreApps($disabledApps) { + /** + * @param array $disabledApps + * @throws \Exception + */ + private function upgradeAppStoreApps(array $disabledApps) { foreach($disabledApps as $app) { if (OC_Installer::isUpdateAvailable($app)) { $ocsId = \OC::$server->getConfig()->getAppValue($app, 'ocsid', ''); diff --git a/tests/lib/updater.php b/tests/lib/updater.php index 13b45b3d8e..8d6a9d65b2 100644 --- a/tests/lib/updater.php +++ b/tests/lib/updater.php @@ -1,107 +1,347 @@ - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. + * @author Lukas Reschke + * @author Victor Dubiniuk + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * */ namespace OC; -class UpdaterTest extends \Test\TestCase { +use OCP\IConfig; +use OCP\ILogger; - public function versionCompatibilityTestData() { - return array( - array('1.0.0.0', '2.2.0', true), - array('1.1.1.1', '2.0.0', true), - array('5.0.3', '4.0.3', false), - array('12.0.3', '13.4.5', true), - array('1', '2', true), - array('2', '2', true), - array('6.0.5', '6.0.6', true), - array('5.0.6', '7.0.4', false) +class UpdaterTest extends \Test\TestCase { + /** @var IConfig */ + private $config; + /** @var HTTPHelper */ + private $httpHelper; + /** @var ILogger */ + private $logger; + /** @var Updater */ + private $updater; + + public function setUp() { + parent::setUp(); + $this->config = $this->getMockBuilder('\\OCP\\IConfig') + ->disableOriginalConstructor() + ->getMock(); + $this->httpHelper = $this->getMockBuilder('\\OC\\HTTPHelper') + ->disableOriginalConstructor() + ->getMock(); + $this->logger = $this->getMockBuilder('\\OCP\\ILogger') + ->disableOriginalConstructor() + ->getMock(); + + $this->updater = new Updater( + $this->httpHelper, + $this->config, + $this->logger ); } + /** + * @param string $baseUrl + * @return string + */ + private function buildUpdateUrl($baseUrl) { + return $baseUrl . '?version='.implode('x', \OC_Util::getVersion()).'xinstalledatxlastupdatedatx'.\OC_Util::getChannel().'x'.\OC_Util::getEditionString().'x'; + } + + /** + * @return array + */ + public function versionCompatibilityTestData() { + return [ + ['1.0.0.0', '2.2.0', true], + ['1.1.1.1', '2.0.0', true], + ['5.0.3', '4.0.3', false], + ['12.0.3', '13.4.5', true], + ['1', '2', true], + ['2', '2', true], + ['6.0.5', '6.0.6', true], + ['5.0.6', '7.0.4', false], + ]; + } + + public function testSetSimulateStepEnabled() { + $this->updater->setSimulateStepEnabled(true); + $this->assertSame(true, $this->invokePrivate($this->updater, 'simulateStepEnabled')); + $this->updater->setSimulateStepEnabled(false); + $this->assertSame(false, $this->invokePrivate($this->updater, 'simulateStepEnabled')); + } + + public function testSetUpdateStepEnabled() { + $this->updater->setUpdateStepEnabled(true); + $this->assertSame(true, $this->invokePrivate($this->updater, 'updateStepEnabled')); + $this->updater->setUpdateStepEnabled(false); + $this->assertSame(false, $this->invokePrivate($this->updater, 'updateStepEnabled')); + } + + public function testSetSkip3rdPartyAppsDisable() { + $this->updater->setSkip3rdPartyAppsDisable(true); + $this->assertSame(true, $this->invokePrivate($this->updater, 'skip3rdPartyAppsDisable')); + $this->updater->setSkip3rdPartyAppsDisable(false); + $this->assertSame(false, $this->invokePrivate($this->updater, 'skip3rdPartyAppsDisable')); + } + /** * @dataProvider versionCompatibilityTestData + * + * @param string $oldVersion + * @param string $newVersion + * @param bool $result */ public function testIsUpgradePossible($oldVersion, $newVersion, $result) { - $updater = new Updater(\OC::$server->getHTTPHelper(), \OC::$server->getConfig()); + $updater = new Updater($this->httpHelper, $this->config); $this->assertSame($result, $updater->isUpgradePossible($oldVersion, $newVersion)); } - public function testBrokenXmlResponse(){ - $invalidUpdater = $this->getUpdaterMock('OMG!'); - $invalidResult = $invalidUpdater->check(); - $this->assertEmpty($invalidResult); + public function testCheckInCache() { + $expectedResult = [ + 'version' => '8.0.4.2', + 'versionstring' => 'ownCloud 8.0.4', + 'url' => 'https://download.owncloud.org/community/owncloud-8.0.4.zip', + 'web' => 'http://doc.owncloud.org/server/8.0/admin_manual/maintenance/upgrade.html', + ]; + + $this->config + ->expects($this->at(0)) + ->method('getAppValue') + ->with('core', 'lastupdatedat') + ->will($this->returnValue(time())); + $this->config + ->expects($this->at(1)) + ->method('getAppValue') + ->with('core', 'lastupdateResult') + ->will($this->returnValue(json_encode($expectedResult))); + + $this->assertSame($expectedResult, $this->updater->check()); } - public function testEmptyResponse(){ - $emptyUpdater = $this->getUpdaterMock(''); - $emptyResult = $emptyUpdater->check(); - $this->assertEmpty($emptyResult); + public function testCheckWithoutUpdateUrl() { + $expectedResult = [ + 'version' => '8.0.4.2', + 'versionstring' => 'ownCloud 8.0.4', + 'url' => 'https://download.owncloud.org/community/owncloud-8.0.4.zip', + 'web' => 'http://doc.owncloud.org/server/8.0/admin_manual/maintenance/upgrade.html', + ]; - // Error while fetching new contents e.g. too many redirects - $falseUpdater = $this->getUpdaterMock(false); - $falseResult = $falseUpdater->check(); - $this->assertEmpty($falseResult); - } + $this->config + ->expects($this->at(0)) + ->method('getAppValue') + ->with('core', 'lastupdatedat') + ->will($this->returnValue(0)); + $this->config + ->expects($this->at(1)) + ->method('setAppValue') + ->with('core', 'lastupdatedat', time()); + $this->config + ->expects($this->at(3)) + ->method('getAppValue') + ->with('core', 'installedat') + ->will($this->returnValue('installedat')); + $this->config + ->expects($this->at(4)) + ->method('getAppValue') + ->with('core', 'lastupdatedat') + ->will($this->returnValue('lastupdatedat')); + $this->config + ->expects($this->at(5)) + ->method('setAppValue') + ->with('core', 'lastupdateResult', json_encode($expectedResult)); - public function testValidEmptyXmlResponse(){ - $updater = $this->getUpdaterMock( - '' - ); - $result = array_map('strval', $updater->check()); - - $this->assertArrayHasKey('version', $result); - $this->assertArrayHasKey('versionstring', $result); - $this->assertArrayHasKey('url', $result); - $this->assertArrayHasKey('web', $result); - $this->assertEmpty($result['version']); - $this->assertEmpty($result['versionstring']); - $this->assertEmpty($result['url']); - $this->assertEmpty($result['web']); - } - - public function testValidUpdateResponse(){ - $newUpdater = $this->getUpdaterMock( - ' + $updateXml = ' - 7.0.3.4 - ownCloud 7.0.3 - http://download.owncloud.org/community/owncloud-7.0.3.zip - http://owncloud.org/ -' - ); - $newResult = array_map('strval', $newUpdater->check()); + 8.0.4.2 + ownCloud 8.0.4 + https://download.owncloud.org/community/owncloud-8.0.4.zip + http://doc.owncloud.org/server/8.0/admin_manual/maintenance/upgrade.html +'; + $this->httpHelper + ->expects($this->once()) + ->method('getUrlContent') + ->with($this->buildUpdateUrl('https://updates.owncloud.com/server/')) + ->will($this->returnValue($updateXml)); - $this->assertArrayHasKey('version', $newResult); - $this->assertArrayHasKey('versionstring', $newResult); - $this->assertArrayHasKey('url', $newResult); - $this->assertArrayHasKey('web', $newResult); - $this->assertEquals('7.0.3.4', $newResult['version']); - $this->assertEquals('ownCloud 7.0.3', $newResult['versionstring']); - $this->assertEquals('http://download.owncloud.org/community/owncloud-7.0.3.zip', $newResult['url']); - $this->assertEquals('http://owncloud.org/', $newResult['web']); + $this->assertSame($expectedResult, $this->updater->check()); } - protected function getUpdaterMock($content){ - // Invalidate cache - $mockedConfig = $this->getMockBuilder('\OCP\IConfig') - ->disableOriginalConstructor() - ->getMock() - ; + public function testCheckWithInvalidXml() { + $this->config + ->expects($this->at(0)) + ->method('getAppValue') + ->with('core', 'lastupdatedat') + ->will($this->returnValue(0)); + $this->config + ->expects($this->at(1)) + ->method('setAppValue') + ->with('core', 'lastupdatedat', time()); + $this->config + ->expects($this->at(3)) + ->method('getAppValue') + ->with('core', 'installedat') + ->will($this->returnValue('installedat')); + $this->config + ->expects($this->at(4)) + ->method('getAppValue') + ->with('core', 'lastupdatedat') + ->will($this->returnValue('lastupdatedat')); + $this->config + ->expects($this->at(5)) + ->method('setAppValue') + ->with('core', 'lastupdateResult', 'false'); - $clientService = $this->getMock('\OCP\Http\Client\IClientService'); - $mockedHTTPHelper = $this->getMockBuilder('\OC\HTTPHelper') - ->setConstructorArgs([\OC::$server->getConfig(), $clientService]) - ->getMock() - ; + $updateXml = 'Invalid XML Response!'; + $this->httpHelper + ->expects($this->once()) + ->method('getUrlContent') + ->with($this->buildUpdateUrl('https://updates.owncloud.com/server/')) + ->will($this->returnValue($updateXml)); - $mockedHTTPHelper->expects($this->once())->method('getUrlContent')->will($this->returnValue($content)); - - return new Updater($mockedHTTPHelper, $mockedConfig); + $this->assertSame([], $this->updater->check()); } + public function testCheckWithUpdateUrl() { + $expectedResult = [ + 'version' => '8.0.4.2', + 'versionstring' => 'ownCloud 8.0.4', + 'url' => 'https://download.owncloud.org/community/owncloud-8.0.4.zip', + 'web' => 'http://doc.owncloud.org/server/8.0/admin_manual/maintenance/upgrade.html', + ]; + + $this->config + ->expects($this->at(0)) + ->method('getAppValue') + ->with('core', 'lastupdatedat') + ->will($this->returnValue(0)); + $this->config + ->expects($this->at(1)) + ->method('setAppValue') + ->with('core', 'lastupdatedat', time()); + $this->config + ->expects($this->at(3)) + ->method('getAppValue') + ->with('core', 'installedat') + ->will($this->returnValue('installedat')); + $this->config + ->expects($this->at(4)) + ->method('getAppValue') + ->with('core', 'lastupdatedat') + ->will($this->returnValue('lastupdatedat')); + $this->config + ->expects($this->at(5)) + ->method('setAppValue') + ->with('core', 'lastupdateResult', json_encode($expectedResult)); + + $updateXml = ' + + 8.0.4.2 + ownCloud 8.0.4 + https://download.owncloud.org/community/owncloud-8.0.4.zip + http://doc.owncloud.org/server/8.0/admin_manual/maintenance/upgrade.html +'; + $this->httpHelper + ->expects($this->once()) + ->method('getUrlContent') + ->with($this->buildUpdateUrl('https://myupdater.com/')) + ->will($this->returnValue($updateXml)); + + $this->assertSame($expectedResult, $this->updater->check('https://myupdater.com/')); + } + + public function testCheckWithEmptyValidXmlResponse() { + $expectedResult = [ + 'version' => '', + 'versionstring' => '', + 'url' => '', + 'web' => '', + ]; + + $this->config + ->expects($this->at(0)) + ->method('getAppValue') + ->with('core', 'lastupdatedat') + ->will($this->returnValue(0)); + $this->config + ->expects($this->at(1)) + ->method('setAppValue') + ->with('core', 'lastupdatedat', time()); + $this->config + ->expects($this->at(3)) + ->method('getAppValue') + ->with('core', 'installedat') + ->will($this->returnValue('installedat')); + $this->config + ->expects($this->at(4)) + ->method('getAppValue') + ->with('core', 'lastupdatedat') + ->will($this->returnValue('lastupdatedat')); + + $updateXml = ' + + + + + +'; + $this->httpHelper + ->expects($this->once()) + ->method('getUrlContent') + ->with($this->buildUpdateUrl('https://updates.owncloud.com/server/')) + ->will($this->returnValue($updateXml)); + + $this->assertSame($expectedResult, $this->updater->check()); + } + + public function testCheckWithEmptyInvalidXmlResponse() { + $expectedResult = []; + + $this->config + ->expects($this->at(0)) + ->method('getAppValue') + ->with('core', 'lastupdatedat') + ->will($this->returnValue(0)); + $this->config + ->expects($this->at(1)) + ->method('setAppValue') + ->with('core', 'lastupdatedat', time()); + $this->config + ->expects($this->at(3)) + ->method('getAppValue') + ->with('core', 'installedat') + ->will($this->returnValue('installedat')); + $this->config + ->expects($this->at(4)) + ->method('getAppValue') + ->with('core', 'lastupdatedat') + ->will($this->returnValue('lastupdatedat')); + $this->config + ->expects($this->at(5)) + ->method('setAppValue') + ->with('core', 'lastupdateResult', json_encode($expectedResult)); + + $updateXml = ''; + $this->httpHelper + ->expects($this->once()) + ->method('getUrlContent') + ->with($this->buildUpdateUrl('https://updates.owncloud.com/server/')) + ->will($this->returnValue($updateXml)); + + $this->assertSame($expectedResult, $this->updater->check()); + } }