|
@@ -0,0 +1,344 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+declare(strict_types=1);
|
|
|
+
|
|
|
+/**
|
|
|
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
|
|
|
+ *
|
|
|
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
|
|
|
+ *
|
|
|
+ * @license GNU AGPL version 3 or any later version
|
|
|
+ *
|
|
|
+ * This program is free software: you can redistribute it and/or modify
|
|
|
+ * it under the terms of the GNU Affero General Public License as
|
|
|
+ * published by the Free Software Foundation, either version 3 of the
|
|
|
+ * License, or (at your option) any later version.
|
|
|
+ *
|
|
|
+ * 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
|
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
+ *
|
|
|
+ */
|
|
|
+
|
|
|
+namespace Test\Updater;
|
|
|
+
|
|
|
+use OC\Updater\ChangesCheck;
|
|
|
+use OC\Updater\ChangesMapper;
|
|
|
+use OC\Updater\ChangesResult;
|
|
|
+use OCP\Http\Client\IClient;
|
|
|
+use OCP\Http\Client\IClientService;
|
|
|
+use OCP\Http\Client\IResponse;
|
|
|
+use OCP\ILogger;
|
|
|
+use const Solarium\QueryType\Select\Query\Component\Facet\INCLUDE_LOWER;
|
|
|
+use Test\TestCase;
|
|
|
+
|
|
|
+class ChangesCheckTest extends TestCase {
|
|
|
+ /** @var IClientService|\PHPUnit_Framework_MockObject_MockObject */
|
|
|
+ protected $clientService;
|
|
|
+
|
|
|
+ /** @var ChangesCheck */
|
|
|
+ protected $checker;
|
|
|
+
|
|
|
+ /** @var ChangesMapper|\PHPUnit_Framework_MockObject_MockObject */
|
|
|
+ protected $mapper;
|
|
|
+
|
|
|
+ /** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */
|
|
|
+ protected $logger;
|
|
|
+
|
|
|
+ public function setUp() {
|
|
|
+ parent::setUp();
|
|
|
+
|
|
|
+ $this->clientService = $this->createMock(IClientService::class);
|
|
|
+ $this->mapper = $this->createMock(ChangesMapper::class);
|
|
|
+ $this->logger = $this->createMock(ILogger::class);
|
|
|
+
|
|
|
+ $this->checker = new ChangesCheck($this->clientService, $this->mapper, $this->logger);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function statusCodeProvider():array {
|
|
|
+ return [
|
|
|
+ [200, ChangesCheck::RESPONSE_HAS_CONTENT],
|
|
|
+ [304, ChangesCheck::RESPONSE_USE_CACHE],
|
|
|
+ [404, ChangesCheck::RESPONSE_NO_CONTENT],
|
|
|
+ [418, ChangesCheck::RESPONSE_NO_CONTENT],
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @dataProvider statusCodeProvider
|
|
|
+ */
|
|
|
+ public function testEvaluateResponse(int $statusCode, int $expected) {
|
|
|
+ $response = $this->createMock(IResponse::class);
|
|
|
+ $response->expects($this->atLeastOnce())
|
|
|
+ ->method('getStatusCode')
|
|
|
+ ->willReturn($statusCode);
|
|
|
+
|
|
|
+ if(!in_array($statusCode, [200, 304, 404])) {
|
|
|
+ $this->logger->expects($this->once())
|
|
|
+ ->method('debug');
|
|
|
+ }
|
|
|
+
|
|
|
+ $evaluation = $this->invokePrivate($this->checker, 'evaluateResponse', [$response]);
|
|
|
+ $this->assertSame($expected, $evaluation);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function testCacheResultInsert() {
|
|
|
+ $version = '13.0.4';
|
|
|
+ $entry = $this->createMock(ChangesResult::class);
|
|
|
+ $entry->expects($this->exactly(2))
|
|
|
+ ->method('__call')
|
|
|
+ ->withConsecutive(['getVersion'], ['setVersion', [$version]])
|
|
|
+ ->willReturnOnConsecutiveCalls('', null);
|
|
|
+
|
|
|
+ $this->mapper->expects($this->once())
|
|
|
+ ->method('insert');
|
|
|
+ $this->mapper->expects($this->never())
|
|
|
+ ->method('update');
|
|
|
+
|
|
|
+ $this->invokePrivate($this->checker, 'cacheResult', [$entry, $version]);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function testCacheResultUpdate() {
|
|
|
+ $version = '13.0.4';
|
|
|
+ $entry = $this->createMock(ChangesResult::class);
|
|
|
+ $entry->expects($this->once())
|
|
|
+ ->method('__call')
|
|
|
+ ->willReturn($version);
|
|
|
+
|
|
|
+ $this->mapper->expects($this->never())
|
|
|
+ ->method('insert');
|
|
|
+ $this->mapper->expects($this->once())
|
|
|
+ ->method('update');
|
|
|
+
|
|
|
+ $this->invokePrivate($this->checker, 'cacheResult', [$entry, $version]);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function changesXMLProvider(): array {
|
|
|
+ return [
|
|
|
+ [ # 0 - full example
|
|
|
+ '<?xml version="1.0" encoding="utf-8" ?>
|
|
|
+<release xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
|
|
|
+ xsi:noNamespaceSchemaLocation="https://updates.nextcloud.com/changelog_server/schema.xsd"
|
|
|
+ version="13.0.0">
|
|
|
+ <changelog href="https://nextcloud.com/changelog/#13-0-0"/>
|
|
|
+ <whatsNew lang="en">
|
|
|
+ <regular>
|
|
|
+ <item>Refined user interface</item>
|
|
|
+ <item>End-to-end Encryption</item>
|
|
|
+ <item>Video and Text Chat</item>
|
|
|
+ </regular>
|
|
|
+ <admin>
|
|
|
+ <item>Changes to the Nginx configuration</item>
|
|
|
+ <item>Theming: CSS files were consolidated</item>
|
|
|
+ </admin>
|
|
|
+ </whatsNew>
|
|
|
+ <whatsNew lang="de">
|
|
|
+ <regular>
|
|
|
+ <item>Überarbeitete Benutzerschnittstelle</item>
|
|
|
+ <item>Ende-zu-Ende Verschlüsselung</item>
|
|
|
+ <item>Video- und Text-Chat</item>
|
|
|
+ </regular>
|
|
|
+ <admin>
|
|
|
+ <item>Änderungen an der Nginx Konfiguration</item>
|
|
|
+ <item>Theming: CSS Dateien wurden konsolidiert</item>
|
|
|
+ </admin>
|
|
|
+ </whatsNew>
|
|
|
+</release>',
|
|
|
+ [
|
|
|
+ 'changelogURL' => 'https://nextcloud.com/changelog/#13-0-0',
|
|
|
+ 'whatsNew' => [
|
|
|
+ 'en' => [
|
|
|
+ 'regular' => [
|
|
|
+ 'Refined user interface',
|
|
|
+ 'End-to-end Encryption',
|
|
|
+ 'Video and Text Chat'
|
|
|
+ ],
|
|
|
+ 'admin' => [
|
|
|
+ 'Changes to the Nginx configuration',
|
|
|
+ 'Theming: CSS files were consolidated'
|
|
|
+ ],
|
|
|
+ ],
|
|
|
+ 'de' => [
|
|
|
+ 'regular' => [
|
|
|
+ 'Überarbeitete Benutzerschnittstelle',
|
|
|
+ 'Ende-zu-Ende Verschlüsselung',
|
|
|
+ 'Video- und Text-Chat'
|
|
|
+ ],
|
|
|
+ 'admin' => [
|
|
|
+ 'Änderungen an der Nginx Konfiguration',
|
|
|
+ 'Theming: CSS Dateien wurden konsolidiert'
|
|
|
+ ],
|
|
|
+ ],
|
|
|
+ ],
|
|
|
+ ]
|
|
|
+ ],
|
|
|
+ [ # 1- admin part not translated
|
|
|
+ '<?xml version="1.0" encoding="utf-8" ?>
|
|
|
+<release xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
|
|
|
+ xsi:noNamespaceSchemaLocation="https://updates.nextcloud.com/changelog_server/schema.xsd"
|
|
|
+ version="13.0.0">
|
|
|
+ <changelog href="https://nextcloud.com/changelog/#13-0-0"/>
|
|
|
+ <whatsNew lang="en">
|
|
|
+ <regular>
|
|
|
+ <item>Refined user interface</item>
|
|
|
+ <item>End-to-end Encryption</item>
|
|
|
+ <item>Video and Text Chat</item>
|
|
|
+ </regular>
|
|
|
+ <admin>
|
|
|
+ <item>Changes to the Nginx configuration</item>
|
|
|
+ <item>Theming: CSS files were consolidated</item>
|
|
|
+ </admin>
|
|
|
+ </whatsNew>
|
|
|
+ <whatsNew lang="de">
|
|
|
+ <regular>
|
|
|
+ <item>Überarbeitete Benutzerschnittstelle</item>
|
|
|
+ <item>Ende-zu-Ende Verschlüsselung</item>
|
|
|
+ <item>Video- und Text-Chat</item>
|
|
|
+ </regular>
|
|
|
+ </whatsNew>
|
|
|
+</release>',
|
|
|
+ [
|
|
|
+ 'changelogURL' => 'https://nextcloud.com/changelog/#13-0-0',
|
|
|
+ 'whatsNew' => [
|
|
|
+ 'en' => [
|
|
|
+ 'regular' => [
|
|
|
+ 'Refined user interface',
|
|
|
+ 'End-to-end Encryption',
|
|
|
+ 'Video and Text Chat'
|
|
|
+ ],
|
|
|
+ 'admin' => [
|
|
|
+ 'Changes to the Nginx configuration',
|
|
|
+ 'Theming: CSS files were consolidated'
|
|
|
+ ],
|
|
|
+ ],
|
|
|
+ 'de' => [
|
|
|
+ 'regular' => [
|
|
|
+ 'Überarbeitete Benutzerschnittstelle',
|
|
|
+ 'Ende-zu-Ende Verschlüsselung',
|
|
|
+ 'Video- und Text-Chat'
|
|
|
+ ],
|
|
|
+ 'admin' => [
|
|
|
+ ],
|
|
|
+ ],
|
|
|
+ ],
|
|
|
+ ]
|
|
|
+ ],
|
|
|
+ [ # 2 - minimal set
|
|
|
+ '<?xml version="1.0" encoding="utf-8" ?>
|
|
|
+<release xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
|
|
|
+ xsi:noNamespaceSchemaLocation="https://updates.nextcloud.com/changelog_server/schema.xsd"
|
|
|
+ version="13.0.0">
|
|
|
+ <changelog href="https://nextcloud.com/changelog/#13-0-0"/>
|
|
|
+ <whatsNew lang="en">
|
|
|
+ <regular>
|
|
|
+ <item>Refined user interface</item>
|
|
|
+ <item>End-to-end Encryption</item>
|
|
|
+ <item>Video and Text Chat</item>
|
|
|
+ </regular>
|
|
|
+ </whatsNew>
|
|
|
+</release>',
|
|
|
+ [
|
|
|
+ 'changelogURL' => 'https://nextcloud.com/changelog/#13-0-0',
|
|
|
+ 'whatsNew' => [
|
|
|
+ 'en' => [
|
|
|
+ 'regular' => [
|
|
|
+ 'Refined user interface',
|
|
|
+ 'End-to-end Encryption',
|
|
|
+ 'Video and Text Chat'
|
|
|
+ ],
|
|
|
+ 'admin' => [],
|
|
|
+ ],
|
|
|
+ ],
|
|
|
+ ]
|
|
|
+ ],
|
|
|
+ [ # 3 - minimal set (procrastinator edition)
|
|
|
+ '<?xml version="1.0" encoding="utf-8" ?>
|
|
|
+<release xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
|
|
|
+ xsi:noNamespaceSchemaLocation="https://updates.nextcloud.com/changelog_server/schema.xsd"
|
|
|
+ version="13.0.0">
|
|
|
+ <changelog href="https://nextcloud.com/changelog/#13-0-0"/>
|
|
|
+ <whatsNew lang="en">
|
|
|
+ <regular>
|
|
|
+ <item>Write this tomorrow</item>
|
|
|
+ </regular>
|
|
|
+ </whatsNew>
|
|
|
+</release>',
|
|
|
+ [
|
|
|
+ 'changelogURL' => 'https://nextcloud.com/changelog/#13-0-0',
|
|
|
+ 'whatsNew' => [
|
|
|
+ 'en' => [
|
|
|
+ 'regular' => [
|
|
|
+ 'Write this tomorrow',
|
|
|
+ ],
|
|
|
+ 'admin' => [],
|
|
|
+ ],
|
|
|
+ ],
|
|
|
+ ]
|
|
|
+ ],
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @dataProvider changesXMLProvider
|
|
|
+ */
|
|
|
+ public function testExtractData(string $body, array $expected) {
|
|
|
+ $actual = $this->invokePrivate($this->checker, 'extractData', [$body]);
|
|
|
+ $this->assertSame($expected, $actual);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function etagProvider() {
|
|
|
+ return [
|
|
|
+ [''],
|
|
|
+ ['a27aab83d8205d73978435076e53d143']
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @dataProvider etagProvider
|
|
|
+ */
|
|
|
+ public function testQueryChangesServer(string $etag) {
|
|
|
+ $uri = 'https://changes.nextcloud.server/?13.0.5';
|
|
|
+ $entry = $this->createMock(ChangesResult::class);
|
|
|
+ $entry->expects($this->any())
|
|
|
+ ->method('__call')
|
|
|
+ ->willReturn($etag);
|
|
|
+
|
|
|
+ $expectedHeaders = $etag === '' ? [] : ['If-None-Match: ' . $etag];
|
|
|
+
|
|
|
+ $client = $this->createMock(IClient::class);
|
|
|
+ $client->expects($this->once())
|
|
|
+ ->method('get')
|
|
|
+ ->with($uri, ['headers' => $expectedHeaders])
|
|
|
+ ->willReturn($this->createMock(IResponse::class));
|
|
|
+
|
|
|
+ $this->clientService->expects($this->once())
|
|
|
+ ->method('newClient')
|
|
|
+ ->willReturn($client);
|
|
|
+
|
|
|
+ $response = $this->invokePrivate($this->checker, 'queryChangesServer', [$uri, $entry]);
|
|
|
+ $this->assertInstanceOf(IResponse::class, $response);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function versionProvider(): array {
|
|
|
+ return [
|
|
|
+ ['13.0.7', '13.0.7'],
|
|
|
+ ['13.0.7.3', '13.0.7'],
|
|
|
+ ['13.0.7.3.42', '13.0.7'],
|
|
|
+ ['13.0', '13.0.0'],
|
|
|
+ ['13', '13.0.0'],
|
|
|
+ ['', '0.0.0'],
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @dataProvider versionProvider
|
|
|
+ */
|
|
|
+ public function testNormalizeVersion(string $input, string $expected) {
|
|
|
+ $normalized = $this->invokePrivate($this->checker, 'normalizeVersion', [$input]);
|
|
|
+ $this->assertSame($expected, $normalized);
|
|
|
+ }
|
|
|
+}
|