Upgraded drupal core with security updates
[yaffs-website] / web / core / modules / update / tests / src / Functional / UpdateCoreTest.php
1 <?php
2
3 namespace Drupal\Tests\update\Functional;
4
5 use Drupal\Core\Url;
6 use Drupal\Tests\Traits\Core\CronRunTrait;
7
8 /**
9  * Tests the Update Manager module through a series of functional tests using
10  * mock XML data.
11  *
12  * @group update
13  */
14 class UpdateCoreTest extends UpdateTestBase {
15
16   use CronRunTrait;
17
18   /**
19    * Modules to enable.
20    *
21    * @var array
22    */
23   public static $modules = ['update_test', 'update', 'language', 'block'];
24
25   protected function setUp() {
26     parent::setUp();
27     $admin_user = $this->drupalCreateUser(['administer site configuration', 'administer modules', 'administer themes']);
28     $this->drupalLogin($admin_user);
29     $this->drupalPlaceBlock('local_actions_block');
30   }
31
32   /**
33    * Sets the version to x.x.x when no project-specific mapping is defined.
34    *
35    * @param string $version
36    *   The version.
37    */
38   protected function setSystemInfo($version) {
39     $setting = [
40       '#all' => [
41         'version' => $version,
42       ],
43     ];
44     $this->config('update_test.settings')->set('system_info', $setting)->save();
45   }
46
47   /**
48    * Tests the Update Manager module when no updates are available.
49    */
50   public function testNoUpdatesAvailable() {
51     foreach ([0, 1] as $minor_version) {
52       foreach ([0, 1] as $patch_version) {
53         foreach (['-alpha1', '-beta1', ''] as $extra_version) {
54           $this->setSystemInfo("8.$minor_version.$patch_version" . $extra_version);
55           $this->refreshUpdateStatus(['drupal' => "$minor_version.$patch_version" . $extra_version]);
56           $this->standardTests();
57           $this->assertText(t('Up to date'));
58           $this->assertNoText(t('Update available'));
59           $this->assertNoText(t('Security update required!'));
60           $this->assertRaw('check.svg', 'Check icon was found.');
61         }
62       }
63     }
64   }
65
66   /**
67    * Tests the Update Manager module when one normal update is available.
68    */
69   public function testNormalUpdateAvailable() {
70     $this->setSystemInfo('8.0.0');
71
72     // Ensure that the update check requires a token.
73     $this->drupalGet('admin/reports/updates/check');
74     $this->assertResponse(403, 'Accessing admin/reports/updates/check without a CSRF token results in access denied.');
75
76     foreach ([0, 1] as $minor_version) {
77       foreach (['-alpha1', '-beta1', ''] as $extra_version) {
78         $this->refreshUpdateStatus(['drupal' => "$minor_version.1" . $extra_version]);
79         $this->standardTests();
80         $this->drupalGet('admin/reports/updates');
81         $this->clickLink(t('Check manually'));
82         $this->checkForMetaRefresh();
83         $this->assertNoText(t('Security update required!'));
84         $this->assertRaw(\Drupal::l("8.$minor_version.1" . $extra_version, Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version-release")), 'Link to release appears.');
85         $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version.tar.gz")), 'Link to download appears.');
86         $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-8-$minor_version-1$extra_version-release")), 'Link to release notes appears.');
87
88         switch ($minor_version) {
89           case 0:
90             // Both stable and unstable releases are available.
91             // A stable release is the latest.
92             if ($extra_version == '') {
93               $this->assertNoText(t('Up to date'));
94               $this->assertText(t('Update available'));
95               $this->assertText(t('Recommended version:'));
96               $this->assertNoText(t('Latest version:'));
97               $this->assertRaw('warning.svg', 'Warning icon was found.');
98             }
99             // Only unstable releases are available.
100             // An unstable release is the latest.
101             else {
102               $this->assertText(t('Up to date'));
103               $this->assertNoText(t('Update available'));
104               $this->assertNoText(t('Recommended version:'));
105               $this->assertText(t('Latest version:'));
106               $this->assertRaw('check.svg', 'Check icon was found.');
107             }
108             break;
109           case 1:
110             // Both stable and unstable releases are available.
111             // A stable release is the latest.
112             if ($extra_version == '') {
113               $this->assertNoText(t('Up to date'));
114               $this->assertText(t('Update available'));
115               $this->assertText(t('Recommended version:'));
116               $this->assertNoText(t('Latest version:'));
117               $this->assertRaw('warning.svg', 'Warning icon was found.');
118             }
119             // Both stable and unstable releases are available.
120             // An unstable release is the latest.
121             else {
122               $this->assertNoText(t('Up to date'));
123               $this->assertText(t('Update available'));
124               $this->assertText(t('Recommended version:'));
125               $this->assertText(t('Latest version:'));
126               $this->assertRaw('warning.svg', 'Warning icon was found.');
127             }
128             break;
129         }
130       }
131     }
132   }
133
134   /**
135    * Tests the Update Manager module when a major update is available.
136    */
137   public function testMajorUpdateAvailable() {
138     foreach ([0, 1] as $minor_version) {
139       foreach ([0, 1] as $patch_version) {
140         foreach (['-alpha1', '-beta1', ''] as $extra_version) {
141           $this->setSystemInfo("8.$minor_version.$patch_version" . $extra_version);
142           $this->refreshUpdateStatus(['drupal' => '9']);
143           $this->standardTests();
144           $this->drupalGet('admin/reports/updates');
145           $this->clickLink(t('Check manually'));
146           $this->checkForMetaRefresh();
147           $this->assertNoText(t('Security update required!'));
148           $this->assertRaw(\Drupal::l('9.0.0', Url::fromUri("http://example.com/drupal-9-0-0-release")), 'Link to release appears.');
149           $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-9-0-0.tar.gz")), 'Link to download appears.');
150           $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-9-0-0-release")), 'Link to release notes appears.');
151           $this->assertNoText(t('Up to date'));
152           $this->assertText(t('Not supported!'));
153           $this->assertText(t('Recommended version:'));
154           $this->assertNoText(t('Latest version:'));
155           $this->assertRaw('error.svg', 'Error icon was found.');
156         }
157       }
158     }
159   }
160
161   /**
162    * Tests the Update Manager module when a security update is available.
163    */
164   public function testSecurityUpdateAvailable() {
165     foreach ([0, 1] as $minor_version) {
166       $this->setSystemInfo("8.$minor_version.0");
167       $this->refreshUpdateStatus(['drupal' => "$minor_version.2-sec"]);
168       $this->standardTests();
169       $this->assertNoText(t('Up to date'));
170       $this->assertNoText(t('Update available'));
171       $this->assertText(t('Security update required!'));
172       $this->assertRaw(\Drupal::l("8.$minor_version.2", Url::fromUri("http://example.com/drupal-8-$minor_version-2-release")), 'Link to release appears.');
173       $this->assertRaw(\Drupal::l(t('Download'), Url::fromUri("http://example.com/drupal-8-$minor_version-2.tar.gz")), 'Link to download appears.');
174       $this->assertRaw(\Drupal::l(t('Release notes'), Url::fromUri("http://example.com/drupal-8-$minor_version-2-release")), 'Link to release notes appears.');
175       $this->assertRaw('error.svg', 'Error icon was found.');
176     }
177   }
178
179   /**
180    * Ensures proper results where there are date mismatches among modules.
181    */
182   public function testDatestampMismatch() {
183     $system_info = [
184       '#all' => [
185         // We need to think we're running a -dev snapshot to see dates.
186         'version' => '8.1.0-dev',
187         'datestamp' => time(),
188       ],
189       'block' => [
190         // This is 2001-09-09 01:46:40 GMT, so test for "2001-Sep-".
191         'datestamp' => '1000000000',
192       ],
193     ];
194     $this->config('update_test.settings')->set('system_info', $system_info)->save();
195     $this->refreshUpdateStatus(['drupal' => 'dev']);
196     $this->assertNoText(t('2001-Sep-'));
197     $this->assertText(t('Up to date'));
198     $this->assertNoText(t('Update available'));
199     $this->assertNoText(t('Security update required!'));
200   }
201
202   /**
203    * Checks that running cron updates the list of available updates.
204    */
205   public function testModulePageRunCron() {
206     $this->setSystemInfo('8.0.0');
207     $this->config('update.settings')
208       ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString())
209       ->save();
210     $this->config('update_test.settings')
211       ->set('xml_map', ['drupal' => '0.0'])
212       ->save();
213
214     $this->cronRun();
215     $this->drupalGet('admin/modules');
216     $this->assertNoText(t('No update information available.'));
217   }
218
219   /**
220    * Checks the messages at admin/modules when the site is up to date.
221    */
222   public function testModulePageUpToDate() {
223     $this->setSystemInfo('8.0.0');
224     // Instead of using refreshUpdateStatus(), set these manually.
225     $this->config('update.settings')
226       ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString())
227       ->save();
228     $this->config('update_test.settings')
229       ->set('xml_map', ['drupal' => '0.0'])
230       ->save();
231
232     $this->drupalGet('admin/reports/updates');
233     $this->clickLink(t('Check manually'));
234     $this->checkForMetaRefresh();
235     $this->assertText(t('Checked available update data for one project.'));
236     $this->drupalGet('admin/modules');
237     $this->assertNoText(t('There are updates available for your version of Drupal.'));
238     $this->assertNoText(t('There is a security update available for your version of Drupal.'));
239   }
240
241   /**
242    * Checks the messages at admin/modules when an update is missing.
243    */
244   public function testModulePageRegularUpdate() {
245     $this->setSystemInfo('8.0.0');
246     // Instead of using refreshUpdateStatus(), set these manually.
247     $this->config('update.settings')
248       ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString())
249       ->save();
250     $this->config('update_test.settings')
251       ->set('xml_map', ['drupal' => '0.1'])
252       ->save();
253
254     $this->drupalGet('admin/reports/updates');
255     $this->clickLink(t('Check manually'));
256     $this->checkForMetaRefresh();
257     $this->assertText(t('Checked available update data for one project.'));
258     $this->drupalGet('admin/modules');
259     $this->assertText(t('There are updates available for your version of Drupal.'));
260     $this->assertNoText(t('There is a security update available for your version of Drupal.'));
261   }
262
263   /**
264    * Checks the messages at admin/modules when a security update is missing.
265    */
266   public function testModulePageSecurityUpdate() {
267     $this->setSystemInfo('8.0.0');
268     // Instead of using refreshUpdateStatus(), set these manually.
269     $this->config('update.settings')
270       ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString())
271       ->save();
272     $this->config('update_test.settings')
273       ->set('xml_map', ['drupal' => '0.2-sec'])
274       ->save();
275
276     $this->drupalGet('admin/reports/updates');
277     $this->clickLink(t('Check manually'));
278     $this->checkForMetaRefresh();
279     $this->assertText(t('Checked available update data for one project.'));
280     $this->drupalGet('admin/modules');
281     $this->assertNoText(t('There are updates available for your version of Drupal.'));
282     $this->assertText(t('There is a security update available for your version of Drupal.'));
283
284     // Make sure admin/appearance warns you you're missing a security update.
285     $this->drupalGet('admin/appearance');
286     $this->assertNoText(t('There are updates available for your version of Drupal.'));
287     $this->assertText(t('There is a security update available for your version of Drupal.'));
288
289     // Make sure duplicate messages don't appear on Update status pages.
290     $this->drupalGet('admin/reports/status');
291     // We're expecting "There is a security update..." inside the status report
292     // itself, but the drupal_set_message() appears as an li so we can prefix
293     // with that and search for the raw HTML.
294     $this->assertNoRaw('<li>' . t('There is a security update available for your version of Drupal.'));
295
296     $this->drupalGet('admin/reports/updates');
297     $this->assertNoText(t('There is a security update available for your version of Drupal.'));
298
299     $this->drupalGet('admin/reports/updates/settings');
300     $this->assertNoText(t('There is a security update available for your version of Drupal.'));
301   }
302
303   /**
304    * Tests the Update Manager module when the update server returns 503 errors.
305    */
306   public function testServiceUnavailable() {
307     $this->refreshUpdateStatus([], '503-error');
308     // Ensure that no "Warning: SimpleXMLElement..." parse errors are found.
309     $this->assertNoText('SimpleXMLElement');
310     $this->assertUniqueText(t('Failed to get available update data for one project.'));
311   }
312
313   /**
314    * Tests that exactly one fetch task per project is created and not more.
315    */
316   public function testFetchTasks() {
317     $projecta = [
318       'name' => 'aaa_update_test',
319     ];
320     $projectb = [
321       'name' => 'bbb_update_test',
322     ];
323     $queue = \Drupal::queue('update_fetch_tasks');
324     $this->assertEqual($queue->numberOfItems(), 0, 'Queue is empty');
325     update_create_fetch_task($projecta);
326     $this->assertEqual($queue->numberOfItems(), 1, 'Queue contains one item');
327     update_create_fetch_task($projectb);
328     $this->assertEqual($queue->numberOfItems(), 2, 'Queue contains two items');
329     // Try to add project a again.
330     update_create_fetch_task($projecta);
331     $this->assertEqual($queue->numberOfItems(), 2, 'Queue still contains two items');
332
333     // Clear storage and try again.
334     update_storage_clear();
335     update_create_fetch_task($projecta);
336     $this->assertEqual($queue->numberOfItems(), 2, 'Queue contains two items');
337   }
338
339   /**
340    * Checks language module in core package at admin/reports/updates.
341    */
342   public function testLanguageModuleUpdate() {
343     $this->setSystemInfo('8.0.0');
344     // Instead of using refreshUpdateStatus(), set these manually.
345     $this->config('update.settings')
346       ->set('fetch.url', Url::fromRoute('update_test.update_test')->setAbsolute()->toString())
347       ->save();
348     $this->config('update_test.settings')
349       ->set('xml_map', ['drupal' => '0.1'])
350       ->save();
351
352     $this->drupalGet('admin/reports/updates');
353     $this->assertText(t('Language'));
354   }
355
356   /**
357    * Ensures that the local actions appear.
358    */
359   public function testLocalActions() {
360     $admin_user = $this->drupalCreateUser(['administer site configuration', 'administer modules', 'administer software updates', 'administer themes']);
361     $this->drupalLogin($admin_user);
362
363     $this->drupalGet('admin/modules');
364     $this->clickLink(t('Install new module'));
365     $this->assertUrl('admin/modules/install');
366
367     $this->drupalGet('admin/appearance');
368     $this->clickLink(t('Install new theme'));
369     $this->assertUrl('admin/theme/install');
370
371     $this->drupalGet('admin/reports/updates');
372     $this->clickLink(t('Install new module or theme'));
373     $this->assertUrl('admin/reports/updates/install');
374   }
375
376 }