Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 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 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]

   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   * Tests for \tool_langimport\locale class.
  19   *
  20   * @package    tool_langimport
  21   * @copyright  2018 Université Rennes 2 {@link https://www.univ-rennes2.fr}
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  /**
  28   * Tests for \tool_langimport\locale class.
  29   *
  30   * @coversDefaultClass \tool_langimport\locale
  31   * @copyright  2018 Université Rennes 2 {@link https://www.univ-rennes2.fr}
  32   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  33   */
  34  class locale_testcase extends \advanced_testcase {
  35      /**
  36       * Test that \tool_langimport\locale::check_locale_availability() works as expected.
  37       *
  38       * @covers ::check_locale_availability
  39       * @return void
  40       */
  41      public function test_check_locale_availability() {
  42          // Create a mock of set_locale() method to simulate :
  43          // - first setlocale() call which backup current locale
  44          // - second setlocale() call which try to set new 'es' locale
  45          // - third setlocale() call which restore locale.
  46          $mock = $this->getMockBuilder(\tool_langimport\locale::class)
  47              ->setMethods(['set_locale'])
  48              ->getMock();
  49          $mock->method('set_locale')->will($this->onConsecutiveCalls('en', 'es', 'en'));
  50  
  51          // Test what happen when locale is available on system.
  52          $result = $mock->check_locale_availability('en');
  53          $this->assertTrue($result);
  54  
  55          // Create a mock of set_locale() method to simulate :
  56          // - first setlocale() call which backup current locale
  57          // - second setlocale() call which fail to set new locale
  58          // - third setlocale() call which restore locale.
  59          $mock = $this->getMockBuilder(\tool_langimport\locale::class)
  60              ->setMethods(['set_locale'])
  61              ->getMock();
  62          $mock->method('set_locale')->will($this->onConsecutiveCalls('en', false, 'en'));
  63  
  64          // Test what happen when locale is not available on system.
  65          $result = $mock->check_locale_availability('en');
  66          $this->assertFalse($result);
  67  
  68          // Test an invalid parameter.
  69          $locale = new \tool_langimport\locale();
  70          $this->expectException(coding_exception::class);
  71          $locale->check_locale_availability('');
  72      }
  73  
  74      /**
  75       * Test \tool_langimport\locale::set_locale() own logic.
  76       *
  77       * We have to explicitly test set_locale() own logic and results,
  78       * that effectively sets the current locale, so we need to restore
  79       * the original locale after every test (ugly, from a purist unit test
  80       * point of view, but needed).
  81       *
  82       * @dataProvider set_locale_provider
  83       * @covers ::set_locale
  84       *
  85       * @param string $set locale string to be set.
  86       * @param string $ret expected results returned after setting the locale.
  87       */
  88      public function test_set_locale(string $set, string $ret) {
  89          // Make set_locale() public.
  90          $loc = new \tool_langimport\locale();
  91          $rc = new \ReflectionClass(\tool_langimport\locale::class);
  92          $rm = $rc->getMethod('set_locale');
  93          $rm->setAccessible(true);
  94  
  95          // Capture current locale for later restore (funnily, using the set_locale() method itself.
  96          $originallocale = $rm->invokeArgs($loc, [LC_ALL, 0]);
  97  
  98          // Assert we get the locale defined as expected.
  99          $this->assertEquals($ret, $rm->invokeArgs($loc, [LC_ALL, $set]));
 100  
 101          // We have finished, restore the original locale, so this doesn't affect other tests at distance.
 102          // (again, funnily, using the very same set_locale() method).
 103          $rm->invokeArgs($loc, [LC_ALL, $originallocale]);
 104  
 105      }
 106  
 107      /**
 108       * Data provider for test_set_locale().
 109       *
 110       * Provides a locale to be set (as 'set') and a expected return value (as 'ret'). Note that
 111       * some of the locales are OS dependent, so only the ones matching the OS will be provided.
 112       *
 113       * We make extensive use of the en_AU.UTF-8/English_Australia.1252 locale that is mandatory to
 114       * be installed in any system running PHPUnit tests.
 115       */
 116      public function set_locale_provider(): array {
 117          // Let's list the allowed categories by OS.
 118          $bsdallowed = ['LC_COLLATE', 'LC_CTYPE', 'LC_MESSAGES', 'LC_MONETARY', 'LC_NUMERIC', 'LC_TIME'];
 119          $winallowed = ['LC_COLLATE', 'LC_CTYPE', 'LC_MONETARY', 'LC_NUMERIC', 'LC_TIME'];
 120          $linuxallowed = [
 121              'LC_COLLATE', 'LC_CTYPE', 'LC_MESSAGES', 'LC_MONETARY', 'LC_NUMERIC', 'LC_TIME',
 122              'LC_PAPER', 'LC_NAME', 'LC_ADDRESS', 'LC_TELEPHONE', 'LC_MEASUREMENT', 'LC_IDENTIFICATION'
 123          ];
 124  
 125          // The base locale name is also OS dependent.
 126          $baselocale = get_string('locale', 'langconfig');
 127          if (PHP_OS_FAMILY === 'Windows') {
 128              $baselocale = get_string('localewin', 'langconfig');
 129          }
 130  
 131          // Here we'll go accumulating cases to be provided.
 132          $cases = [];
 133  
 134          // First, the simplest case, just pass a locale name, without categories.
 135          $cases['rawlocale'] = [
 136              'set' => $baselocale,
 137              'ret' => $baselocale,
 138          ];
 139  
 140          // Now, let's fill ALL LC categories, we should get back the locale name if all them are set with same value.
 141          // Note that this case is the one that, under Linux only, covers the changes performed to the set_locale() method.
 142          // Pick the correct categories depending on the OS.
 143          $oscategories = $bsdallowed; // Default to BSD/Dawrwin ones because they are the standard 6 supported by PHP.
 144          if (PHP_OS_FAMILY === 'Windows') {
 145              $oscategories = $winallowed;
 146          } else if (PHP_OS_FAMILY === 'Linux') {
 147              $oscategories = $linuxallowed;
 148          }
 149  
 150          $localestr = '';
 151          foreach ($oscategories as $category) {
 152              // Format is different by OS too, so let build the string conditionally.
 153              if (PHP_OS_FAMILY === 'BSD' || PHP_OS_FAMILY === 'Darwin') {
 154                  // BSD uses slashes (/) separated list of the 6 values in exact order.
 155                  $localestr .= '/' . $baselocale;
 156              } else {
 157                  // Linux/Windows use semicolon (;) separated list of category=value pairs.
 158                  $localestr .= ';' . $category . '=' . $baselocale;
 159              }
 160          }
 161          $cases['allcategories'] = [
 162              'set' => trim($localestr, ';/'),
 163              'ret' => $baselocale,
 164          ];
 165  
 166          // Return all the built cases.
 167          return $cases;
 168      }
 169  }