[ 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  
  63          // reload config
  64          global $conf, $config_cascade;
  65          $conf = array();
  66          foreach (array('default','local','protected') as $config_group) {
  67              if (empty($config_cascade['main'][$config_group])) continue;
  68              foreach ($config_cascade['main'][$config_group] as $config_file) {
  69                  if (file_exists($config_file)) {
  70                      include($config_file);
  71                  }
  72              }
  73          }
  74  
  75          // reload license config
  76          global $license;
  77          $license = array();
  78  
  79          // load the license file(s)
  80          foreach (array('default','local') as $config_group) {
  81              if (empty($config_cascade['license'][$config_group])) continue;
  82              foreach ($config_cascade['license'][$config_group] as $config_file) {
  83                  if(file_exists($config_file)){
  84                      include($config_file);
  85                  }
  86              }
  87          }
  88          // reload some settings
  89          $conf['gzip_output'] &= (strpos($_SERVER['HTTP_ACCEPT_ENCODING'],'gzip') !== false);
  90  
  91          if($conf['compression'] == 'bz2' && !DOKU_HAS_BZIP) {
  92              $conf['compression'] = 'gz';
  93          }
  94          if($conf['compression'] == 'gz' && !DOKU_HAS_GZIP) {
  95              $conf['compression'] = 0;
  96          }
  97          // make real paths and check them
  98          init_creationmodes();
  99          init_paths();
 100          init_files();
 101  
 102          // reset loaded plugins
 103          global $plugin_controller_class, $plugin_controller;
 104          /** @var PluginController $plugin_controller */
 105          $plugin_controller = new $plugin_controller_class();
 106  
 107          // disable all non-default plugins
 108          global $default_plugins;
 109          foreach ($plugin_controller->getList() as $plugin) {
 110              if (!in_array($plugin, $default_plugins)) {
 111                  if (!$plugin_controller->disable($plugin)) {
 112                      throw new Exception('Could not disable plugin "'.$plugin.'"!');
 113                  }
 114              }
 115          }
 116  
 117          // disable and enable configured plugins
 118          foreach ($this->pluginsDisabled as $plugin) {
 119              if (!$plugin_controller->disable($plugin)) {
 120                  throw new Exception('Could not disable plugin "'.$plugin.'"!');
 121              }
 122          }
 123          foreach ($this->pluginsEnabled as $plugin) {
 124              /*  enable() returns false but works...
 125              if (!$plugin_controller->enable($plugin)) {
 126                  throw new Exception('Could not enable plugin "'.$plugin.'"!');
 127              }
 128              */
 129              $plugin_controller->enable($plugin);
 130          }
 131  
 132          // reset event handler
 133          global $EVENT_HANDLER;
 134          $EVENT_HANDLER = new EventHandler();
 135  
 136          // reload language
 137          $local = $conf['lang'];
 138          Event::createAndTrigger('INIT_LANG_LOAD', $local, 'init_lang', true);
 139  
 140          global $INPUT;
 141          $INPUT = new \dokuwiki\Input\Input();
 142      }
 143  
 144      /**
 145       * Reinitialize the data directory for this class run
 146       */
 147      public static function setupDataDir() {
 148          // remove any leftovers from the last run
 149          if(is_dir(DOKU_TMP_DATA)) {
 150              // clear indexer data and cache
 151              idx_get_indexer()->clear();
 152              TestUtils::rdelete(DOKU_TMP_DATA);
 153          }
 154  
 155          // populate default dirs
 156          TestUtils::rcopy(TMP_DIR, __DIR__ . '/../data/');
 157      }
 158  
 159      /**
 160       * Reinitialize the conf directory for this class run
 161       */
 162      public static function setupConfDir() {
 163          $defaults = [
 164              'acronyms.conf',
 165              'dokuwiki.php',
 166              'entities.conf',
 167              'interwiki.conf',
 168              'license.php',
 169              'manifest.json',
 170              'mediameta.php',
 171              'mime.conf',
 172              'plugins.php',
 173              'plugins.required.php',
 174              'scheme.conf',
 175              'smileys.conf',
 176              'wordblock.conf'
 177          ];
 178  
 179          // clear any leftovers
 180          if(is_dir(DOKU_CONF)) {
 181              TestUtils::rdelete(DOKU_CONF);
 182          }
 183          mkdir(DOKU_CONF);
 184  
 185          // copy defaults
 186          foreach($defaults as $file) {
 187              copy(DOKU_INC . '/conf/' . $file, DOKU_CONF . $file);
 188          }
 189  
 190          // copy test files
 191          TestUtils::rcopy(TMP_DIR, __DIR__ . '/../conf');
 192      }
 193  
 194      /**
 195       * Waits until a new second has passed
 196       *
 197       * This tried to be clever about the passing of time and return early if possible. Unfortunately
 198       * this never worked reliably fo unknown reasons. To avoid flaky tests, this now always simply
 199       * sleeps for a full second on every call.
 200       *
 201       * @param bool $init no longer used
 202       * @return int new timestamp
 203       */
 204      protected function waitForTick($init = false) {
 205          sleep(1);
 206          return time();
 207      }
 208  
 209      /**
 210       * Allow for testing inaccessible methods (private or protected)
 211       *
 212       * This makes it easier to test protected methods without needing to create intermediate
 213       * classes inheriting and changing the access.
 214       *
 215       * @link https://stackoverflow.com/a/8702347/172068
 216       * @param object $obj Object in which to call the method
 217       * @param string $func The method to call
 218       * @param array $args The arguments to call the method with
 219       * @return mixed
 220       * @throws ReflectionException when the given obj/func does not exist
 221       */
 222      protected static function callInaccessibleMethod($obj, $func, array $args) {
 223          $class = new \ReflectionClass($obj);
 224          $method = $class->getMethod($func);
 225          $method->setAccessible(true);
 226          return $method->invokeArgs($obj, $args);
 227      }
 228  
 229      /**
 230       * Allow for reading inaccessible properties (private or protected)
 231       *
 232       * This makes it easier to check internals of tested objects. This should generally
 233       * be avoided.
 234       *
 235       * @param object $obj Object on which to access the property
 236       * @param string $prop name of the property to access
 237       * @return mixed
 238       * @throws ReflectionException  when the given obj/prop does not exist
 239       */
 240      protected static function getInaccessibleProperty($obj, $prop) {
 241          $class = new \ReflectionClass($obj);
 242          $property = $class->getProperty($prop);
 243          $property->setAccessible(true);
 244          return $property->getValue($obj);
 245      }
 246  
 247      /**
 248       * Allow for reading inaccessible properties (private or protected)
 249       *
 250       * This makes it easier to set internals of tested objects. This should generally
 251       * be avoided.
 252       *
 253       * @param object $obj Object on which to access the property
 254       * @param string $prop name of the property to access
 255       * @param mixed $value new value to set the property to
 256       * @return void
 257       * @throws ReflectionException when the given obj/prop does not exist
 258       */
 259      protected static function setInaccessibleProperty($obj, $prop, $value) {
 260          $class = new \ReflectionClass($obj);
 261          $property = $class->getProperty($prop);
 262          $property->setAccessible(true);
 263          $property->setValue($obj, $value);
 264      }
 265  }