Search moodle.org's
Developer Documentation

  • 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 37 and 311] [Versions 38 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  /**
      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  }