[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/_test/core/ -> DokuWikiTest.php (source)

   1  <?php
   2  
   3  use dokuwiki\Extension\PluginController;
   4  use dokuwiki\Extension\Event;
   5  use dokuwiki\Extension\EventHandler;
   6  /**
   7   * Helper class to provide basic functionality for tests
   8   *
   9   * @uses PHPUnit_Framework_TestCase and thus PHPUnit 5.7+ is required
  10   */
  11  abstract class DokuWikiTest extends PHPUnit\Framework\TestCase {
  12  
  13      /**
  14       * tests can override this
  15       *
  16       * @var array plugins to enable for test class
  17       */
  18      protected $pluginsEnabled = array();
  19  
  20      /**
  21       * tests can override this
  22       *
  23       * @var array plugins to disable for test class
  24       */
  25      protected $pluginsDisabled = array();
  26  
  27      /**
  28       * setExpectedException was deprecated in PHPUnit 6
  29       *
  30       * @param string $class
  31       * @param null|string $message
  32       */
  33      public function setExpectedException($class, $message=null) {
  34          $this->expectException($class);
  35          if(!is_null($message)) {
  36              $this->expectExceptionMessage($message);
  37          }
  38      }
  39  
  40      /**
  41       * Setup the data directory
  42       *
  43       * This is ran before each test class
  44       */
  45      public static function setUpBeforeClass() : void {
  46          // just to be safe not to delete something undefined later
  47          if(!defined('TMP_DIR')) die('no temporary directory');
  48          if(!defined('DOKU_TMP_DATA')) die('no temporary data directory');
  49  
  50          self::setupDataDir();
  51          self::setupConfDir();
  52      }
  53  
  54      /**
  55       * Reset the DokuWiki environment before each test run. Makes sure loaded config,
  56       * language and plugins are correct.
  57       *
  58       * @throws Exception if plugin actions fail
  59       * @return void
  60       */
  61      public function setUp() : void {
  62          // reset execution time if it's enabled
  63          if(ini_get('max_execution_time') > 0) {
  64              set_time_limit(90);
  65          }
  66  
  67          // reload config
  68          global $conf, $config_cascade;
  69          $conf = array();
  70          foreach (array('default','local','protected') as $config_group) {
  71              if (empty($config_cascade['main'][$config_group])) continue;
  72              foreach ($config_cascade['main'][$config_group] as $config_file) {
  73                  if (file_exists($config_file)) {
  74                      include($config_file);
  75                  }
  76              }
  77          }
  78  
  79          // reload license config
  80          global $license;
  81          $license = array();
  82  
  83          // load the license file(s)
  84          foreach (array('default','local') as $config_group) {
  85              if (empty($config_cascade['license'][$config_group])) continue;
  86              foreach ($config_cascade['license'][$config_group] as $config_file) {
  87                  if(file_exists($config_file)){
  88                      include($config_file);
  89                  }
  90              }
  91          }
  92          // reload some settings
  93          $conf['gzip_output'] &= (strpos($_SERVER['HTTP_ACCEPT_ENCODING'],'gzip') !== false);
  94  
  95          if($conf['compression'] == 'bz2' && !DOKU_HAS_BZIP) {
  96              $conf['compression'] = 'gz';
  97          }
  98          if($conf['compression'] == 'gz' && !DOKU_HAS_GZIP) {
  99              $conf['compression'] = 0;
 100          }
 101          // make real paths and check them
 102          init_creationmodes();
 103          init_paths();
 104          init_files();
 105  
 106          // reset loaded plugins
 107          global $plugin_controller_class, $plugin_controller;
 108          /** @var PluginController $plugin_controller */
 109          $plugin_controller = new $plugin_controller_class();
 110  
 111          // disable all non-default plugins
 112          global $default_plugins;
 113          foreach ($plugin_controller->getList() as $plugin) {
 114              if (!in_array($plugin, $default_plugins)) {
 115                  if (!$plugin_controller->disable($plugin)) {
 116                      throw new Exception('Could not disable plugin "'.$plugin.'"!');
 117                  }
 118              }
 119          }
 120  
 121          // disable and enable configured plugins
 122          foreach ($this->pluginsDisabled as $plugin) {
 123              if (!$plugin_controller->disable($plugin)) {
 124                  throw new Exception('Could not disable plugin "'.$plugin.'"!');
 125              }
 126          }
 127          foreach ($this->pluginsEnabled as $plugin) {
 128              /*  enable() returns false but works...
 129              if (!$plugin_controller->enable($plugin)) {
 130                  throw new Exception('Could not enable plugin "'.$plugin.'"!');
 131              }
 132              */
 133              $plugin_controller->enable($plugin);
 134          }
 135  
 136          // reset event handler
 137          global $EVENT_HANDLER;
 138          $EVENT_HANDLER = new EventHandler();
 139  
 140          // reload language
 141          $local = $conf['lang'];
 142          Event::createAndTrigger('INIT_LANG_LOAD', $local, 'init_lang', true);
 143  
 144          global $INPUT;
 145          $INPUT = new \dokuwiki\Input\Input();
 146      }
 147  
 148      /**
 149       * Reinitialize the data directory for this class run
 150       */
 151      public static function setupDataDir() {
 152          // remove any leftovers from the last run
 153          if(is_dir(DOKU_TMP_DATA)) {
 154              // clear indexer data and cache
 155              idx_get_indexer()->clear();
 156              TestUtils::rdelete(DOKU_TMP_DATA);
 157          }
 158  
 159          // populate default dirs
 160          TestUtils::rcopy(TMP_DIR, __DIR__ . '/../data/');
 161      }
 162  
 163      /**
 164       * Reinitialize the conf directory for this class run
 165       */
 166      public static function setupConfDir() {
 167          $defaults = [
 168              'acronyms.conf',
 169              'dokuwiki.php',
 170              'entities.conf',
 171              'interwiki.conf',
 172              'license.php',
 173              'manifest.json',
 174              'mediameta.php',
 175              'mime.conf',
 176              'plugins.php',
 177              'plugins.required.php',
 178              'scheme.conf',
 179              'smileys.conf',
 180              'wordblock.conf'
 181          ];
 182  
 183          // clear any leftovers
 184          if(is_dir(DOKU_CONF)) {
 185              TestUtils::rdelete(DOKU_CONF);
 186          }
 187          mkdir(DOKU_CONF);
 188  
 189          // copy defaults
 190          foreach($defaults as $file) {
 191              copy(DOKU_INC . '/conf/' . $file, DOKU_CONF . $file);
 192          }
 193  
 194          // copy test files
 195          TestUtils::rcopy(TMP_DIR, __DIR__ . '/../conf');
 196      }
 197  
 198      /**
 199       * Waits until a new second has passed
 200       *
 201       * This tried to be clever about the passing of time and return early if possible. Unfortunately
 202       * this never worked reliably for unknown reasons. To avoid flaky tests, this now always simply
 203       * sleeps for a full second on every call.
 204       *
 205       * @param bool $init no longer used
 206       * @return int new timestamp
 207       */
 208      protected function waitForTick($init = false) {
 209          sleep(1);
 210          return time();
 211      }
 212  
 213      /**
 214       * Allow for testing inaccessible methods (private or protected)
 215       *
 216       * This makes it easier to test protected methods without needing to create intermediate
 217       * classes inheriting and changing the access.
 218       *
 219       * @link https://stackoverflow.com/a/8702347/172068
 220       * @param object $obj Object in which to call the method
 221       * @param string $func The method to call
 222       * @param array $args The arguments to call the method with
 223       * @return mixed
 224       * @throws ReflectionException when the given obj/func does not exist
 225       */
 226      protected static function callInaccessibleMethod($obj, $func, array $args) {
 227          $class = new \ReflectionClass($obj);
 228          $method = $class->getMethod($func);
 229          $method->setAccessible(true);
 230          return $method->invokeArgs($obj, $args);
 231      }
 232  
 233      /**
 234       * Allow for reading inaccessible properties (private or protected)
 235       *
 236       * This makes it easier to check internals of tested objects. This should generally
 237       * be avoided.
 238       *
 239       * @param object $obj Object on which to access the property
 240       * @param string $prop name of the property to access
 241       * @return mixed
 242       * @throws ReflectionException  when the given obj/prop does not exist
 243       */
 244      protected static function getInaccessibleProperty($obj, $prop) {
 245          $class = new \ReflectionClass($obj);
 246          $property = $class->getProperty($prop);
 247          $property->setAccessible(true);
 248          return $property->getValue($obj);
 249      }
 250  
 251      /**
 252       * Allow for reading inaccessible properties (private or protected)
 253       *
 254       * This makes it easier to set internals of tested objects. This should generally
 255       * be avoided.
 256       *
 257       * @param object $obj Object on which to access the property
 258       * @param string $prop name of the property to access
 259       * @param mixed $value new value to set the property to
 260       * @return void
 261       * @throws ReflectionException when the given obj/prop does not exist
 262       */
 263      protected static function setInaccessibleProperty($obj, $prop, $value) {
 264          $class = new \ReflectionClass($obj);
 265          $property = $class->getProperty($prop);
 266          $property->setAccessible(true);
 267          $property->setValue($obj, $value);
 268      }
 269  }