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