Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

Differences Between: [Versions 310 and 311] [Versions 39 and 311]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  namespace core;
  18  
  19  defined('MOODLE_INTERNAL') || die();
  20  
  21  use core\update\testable_checker;
  22  use core\update\testable_checker_cron_executed;
  23  
  24  global $CFG;
  25  require_once (__DIR__.'/fixtures/testable_update_checker.php');
  26  
  27  /**
  28   * Tests of the basic API of the available update checker.
  29   *
  30   * @package   core
  31   * @category  test
  32   * @copyright 2012, 2015 David Mudrak <david@moodle.com>
  33   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  34   */
  35  class update_checker_test extends \advanced_testcase {
  36  
  37      public function test_core_available_update() {
  38          $provider = testable_checker::instance();
  39          $this->assertInstanceOf('\core\update\checker', $provider);
  40  
  41          $provider->fake_current_environment(2012060102.00, '2.3.2 (Build: 20121012)', '2.3', array());
  42          $updates = $provider->get_update_info('core');
  43          $this->assertCount(2, $updates);
  44  
  45          $provider->fake_current_environment(2012060103.00, '2.3.3 (Build: 20121212)', '2.3', array());
  46          $updates = $provider->get_update_info('core');
  47          $this->assertCount(1, $updates);
  48  
  49          $provider->fake_current_environment(2012060103.00, '2.3.3 (Build: 20121212)', '2.3', array());
  50          $updates = $provider->get_update_info('core', array('minmaturity' => MATURITY_STABLE));
  51          $this->assertNull($updates);
  52      }
  53  
  54      /**
  55       * If there are no fetched data yet, the first cron should fetch them.
  56       */
  57      public function test_cron_initial_fetch() {
  58          $provider = testable_checker::instance();
  59          $provider->fakerecentfetch = null;
  60          $provider->fakecurrenttimestamp = -1;
  61          $this->expectException(\core\update\testable_checker_cron_executed::class);
  62          $provider->cron();
  63      }
  64  
  65      /**
  66       * If there is a fresh fetch available, no cron execution is expected.
  67       */
  68      public function test_cron_has_fresh_fetch() {
  69          $provider = testable_checker::instance();
  70          $provider->fakerecentfetch = time() - 23 * HOURSECS; // Fetched 23 hours ago.
  71          $provider->fakecurrenttimestamp = -1;
  72          $provider->cron();
  73          $this->assertTrue(true); // We should get here with no exception thrown.
  74      }
  75  
  76      /**
  77       * If there is an outdated fetch, the cron execution is expected.
  78       */
  79      public function test_cron_has_outdated_fetch() {
  80          $provider = testable_checker::instance();
  81          $provider->fakerecentfetch = time() - 49 * HOURSECS; // Fetched 49 hours ago.
  82          $provider->fakecurrenttimestamp = -1;
  83          $this->expectException(\core\update\testable_checker_cron_executed::class);
  84          $provider->cron();
  85      }
  86  
  87      /**
  88       * The first cron after 01:42 AM today should fetch the data.
  89       *
  90       * @see testable_checker::cron_execution_offset()
  91       */
  92      public function test_cron_offset_execution_not_yet() {
  93          $provider = testable_checker::instance();
  94          $provider->fakecurrenttimestamp = mktime(1, 40, 02); // 01:40:02 AM today
  95          $provider->fakerecentfetch = $provider->fakecurrenttimestamp - 24 * HOURSECS;
  96          $provider->cron();
  97          $this->assertTrue(true); // We should get here with no exception thrown.
  98      }
  99  
 100      /**
 101       * The first cron after 01:42 AM today should fetch the data and then
 102       * it is supposed to wait next 24 hours.
 103       *
 104       * @see testable_checker::cron_execution_offset()
 105       */
 106      public function test_cron_offset_execution() {
 107          $provider = testable_checker::instance();
 108  
 109          // The cron at 01:45 should fetch the data.
 110          $provider->fakecurrenttimestamp = mktime(1, 45, 02); // 01:45:02 AM today
 111          $provider->fakerecentfetch = $provider->fakecurrenttimestamp - 24 * HOURSECS - 1;
 112          $executed = false;
 113          try {
 114              $provider->cron();
 115          } catch (testable_checker_cron_executed $e) {
 116              $executed = true;
 117          }
 118          $this->assertTrue($executed, 'Cron should be executed at 01:45:02 but it was not.');
 119  
 120          // Another cron at 06:45 should still consider data as fresh enough.
 121          $provider->fakerecentfetch = $provider->fakecurrenttimestamp;
 122          $provider->fakecurrenttimestamp = mktime(6, 45, 03); // 06:45:03 AM
 123          $executed = false;
 124          try {
 125              $provider->cron();
 126          } catch (testable_checker_cron_executed $e) {
 127              $executed = true;
 128          }
 129          $this->assertFalse($executed, 'Cron should not be executed at 06:45:03 but it was.');
 130  
 131          // The next scheduled execution should happen the next day.
 132          $provider->fakecurrenttimestamp = $provider->fakerecentfetch + 24 * HOURSECS + 1;
 133          $executed = false;
 134          try {
 135              $provider->cron();
 136          } catch (testable_checker_cron_executed $e) {
 137              $executed = true;
 138          }
 139          $this->assertTrue($executed, 'Cron should be executed the next night but it was not.');
 140      }
 141  
 142      public function test_compare_responses_both_empty() {
 143          $provider = testable_checker::instance();
 144          $old = array();
 145          $new = array();
 146          $cmp = $provider->compare_responses($old, $new);
 147          $this->assertIsArray($cmp);
 148          $this->assertEmpty($cmp);
 149      }
 150  
 151      public function test_compare_responses_old_empty() {
 152          $provider = testable_checker::instance();
 153          $old = array();
 154          $new = array(
 155              'updates' => array(
 156                  'core' => array(
 157                      array(
 158                          'version' => 2012060103
 159                      )
 160                  )
 161              )
 162          );
 163          $cmp = $provider->compare_responses($old, $new);
 164          $this->assertIsArray($cmp);
 165          $this->assertNotEmpty($cmp);
 166          $this->assertTrue(isset($cmp['core'][0]['version']));
 167          $this->assertEquals(2012060103, $cmp['core'][0]['version']);
 168      }
 169  
 170      public function test_compare_responses_no_change() {
 171          $provider = testable_checker::instance();
 172          $old = $new = array(
 173              'updates' => array(
 174                  'core' => array(
 175                      array(
 176                          'version' => 2012060104
 177                      ),
 178                      array(
 179                          'version' => 2012120100
 180                      )
 181                  ),
 182                  'mod_foo' => array(
 183                      array(
 184                          'version' => 2011010101
 185                      )
 186                  )
 187              )
 188          );
 189          $cmp = $provider->compare_responses($old, $new);
 190          $this->assertIsArray($cmp);
 191          $this->assertEmpty($cmp);
 192      }
 193  
 194      public function test_compare_responses_new_and_missing_update() {
 195          $provider = testable_checker::instance();
 196          $old = array(
 197              'updates' => array(
 198                  'core' => array(
 199                      array(
 200                          'version' => 2012060104
 201                      )
 202                  ),
 203                  'mod_foo' => array(
 204                      array(
 205                          'version' => 2011010101
 206                      )
 207                  )
 208              )
 209          );
 210          $new = array(
 211              'updates' => array(
 212                  'core' => array(
 213                      array(
 214                          'version' => 2012060104
 215                      ),
 216                      array(
 217                          'version' => 2012120100
 218                      )
 219                  )
 220              )
 221          );
 222          $cmp = $provider->compare_responses($old, $new);
 223          $this->assertIsArray($cmp);
 224          $this->assertNotEmpty($cmp);
 225          $this->assertCount(1, $cmp);
 226          $this->assertCount(1, $cmp['core']);
 227          $this->assertEquals(2012120100, $cmp['core'][0]['version']);
 228      }
 229  
 230      public function test_compare_responses_modified_update() {
 231          $provider = testable_checker::instance();
 232          $old = array(
 233              'updates' => array(
 234                  'mod_foo' => array(
 235                      array(
 236                          'version' => 2011010101
 237                      )
 238                  )
 239              )
 240          );
 241          $new = array(
 242              'updates' => array(
 243                  'mod_foo' => array(
 244                      array(
 245                          'version' => 2011010102
 246                      )
 247                  )
 248              )
 249          );
 250          $cmp = $provider->compare_responses($old, $new);
 251          $this->assertIsArray($cmp);
 252          $this->assertNotEmpty($cmp);
 253          $this->assertCount(1, $cmp);
 254          $this->assertCount(1, $cmp['mod_foo']);
 255          $this->assertEquals(2011010102, $cmp['mod_foo'][0]['version']);
 256      }
 257  
 258      public function test_compare_responses_invalid_format() {
 259          $provider = testable_checker::instance();
 260          $broken = array(
 261              'status' => 'ERROR' // No 'updates' key here.
 262          );
 263          $this->expectException(\core\update\checker_exception::class);
 264          $cmp = $provider->compare_responses($broken, $broken);
 265      }
 266  
 267      public function test_is_same_release_explicit() {
 268          $provider = testable_checker::instance();
 269          $this->assertTrue($provider->is_same_release('2.3dev (Build: 20120323)', '2.3dev (Build: 20120323)'));
 270          $this->assertTrue($provider->is_same_release('2.3dev (Build: 20120323)', '2.3dev (Build: 20120330)'));
 271          $this->assertFalse($provider->is_same_release('2.3dev (Build: 20120529)', '2.3 (Build: 20120601)'));
 272          $this->assertFalse($provider->is_same_release('2.3dev', '2.3 dev'));
 273          $this->assertFalse($provider->is_same_release('2.3.1', '2.3'));
 274          $this->assertFalse($provider->is_same_release('2.3.1', '2.3.2'));
 275          $this->assertTrue($provider->is_same_release('2.3.2+', '2.3.2')); // Yes, really!
 276          $this->assertTrue($provider->is_same_release('2.3.2 (Build: 123456)', '2.3.2+ (Build: 123457)'));
 277          $this->assertFalse($provider->is_same_release('3.0 Community Edition', '3.0 Enterprise Edition'));
 278          $this->assertTrue($provider->is_same_release('3.0 Community Edition', '3.0 Community Edition (Build: 20290101)'));
 279      }
 280  
 281      public function test_is_same_release_implicit() {
 282          $provider = testable_checker::instance();
 283          $provider->fake_current_environment(2012060102.00, '2.3.2 (Build: 20121012)', '2.3', array());
 284          $this->assertTrue($provider->is_same_release('2.3.2'));
 285          $this->assertTrue($provider->is_same_release('2.3.2+'));
 286          $this->assertTrue($provider->is_same_release('2.3.2+ (Build: 20121013)'));
 287          $this->assertFalse($provider->is_same_release('2.4dev (Build: 20121012)'));
 288      }
 289  }