Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]

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