summaryrefslogtreecommitdiffstats
path: root/library/Icinga/Test
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--library/Icinga/Test/BaseTestCase.php361
-rw-r--r--library/Icinga/Test/ClassLoader.php113
-rw-r--r--library/Icinga/Test/DbTest.php47
3 files changed, 521 insertions, 0 deletions
diff --git a/library/Icinga/Test/BaseTestCase.php b/library/Icinga/Test/BaseTestCase.php
new file mode 100644
index 0000000..6702df0
--- /dev/null
+++ b/library/Icinga/Test/BaseTestCase.php
@@ -0,0 +1,361 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace {
+
+ if (!function_exists('t')) {
+ function t()
+ {
+ return func_get_arg(0);
+ }
+ }
+
+ if (!function_exists('mt')) {
+ function mt()
+ {
+ return func_get_arg(0);
+ }
+ }
+}
+
+namespace Icinga\Test {
+
+ use Exception;
+ use ipl\I18n\NoopTranslator;
+ use ipl\I18n\StaticTranslator;
+ use RuntimeException;
+ use Mockery;
+ use Icinga\Application\Icinga;
+ use Icinga\Data\ConfigObject;
+ use Icinga\Data\ResourceFactory;
+ use Icinga\Data\Db\DbConnection;
+
+ /**
+ * Class BaseTestCase
+ */
+ abstract class BaseTestCase extends Mockery\Adapter\Phpunit\MockeryTestCase implements DbTest
+ {
+ /**
+ * Path to application/
+ *
+ * @var string
+ */
+ public static $appDir;
+
+ /**
+ * Path to library/Icinga
+ *
+ * @var string
+ */
+ public static $libDir;
+
+ /**
+ * Path to etc/
+ *
+ * @var
+ */
+ public static $etcDir;
+
+ /**
+ * Path to test/php/
+ *
+ * @var string
+ */
+ public static $testDir;
+
+ /**
+ * Path to share/icinga2-web
+ *
+ * @var string
+ */
+ public static $shareDir;
+
+ /**
+ * Path to modules/
+ *
+ * @var string
+ */
+ public static $moduleDir;
+
+ /**
+ * Resource configuration for different database types
+ *
+ * @var array
+ */
+ protected static $dbConfiguration = array(
+ 'mysql' => array(
+ 'type' => 'db',
+ 'db' => 'mysql',
+ 'host' => '127.0.0.1',
+ 'port' => 3306,
+ 'dbname' => 'icinga_unittest',
+ 'username' => 'icinga_unittest',
+ 'password' => 'icinga_unittest'
+ ),
+ 'pgsql' => array(
+ 'type' => 'db',
+ 'db' => 'pgsql',
+ 'host' => '127.0.0.1',
+ 'port' => 5432,
+ 'dbname' => 'icinga_unittest',
+ 'username' => 'icinga_unittest',
+ 'password' => 'icinga_unittest'
+ ),
+ );
+
+ /**
+ * Setup the default timezone
+ */
+ public static function setupTimezone()
+ {
+ date_default_timezone_set('UTC');
+ }
+
+ /**
+ * Setup test path environment
+ *
+ * @throws RuntimeException
+ */
+ public static function setupDirectories()
+ {
+ $baseDir = getenv('ICINGAWEB_BASEDIR') ?: realpath(__DIR__ . '/../../../');
+ if ($baseDir === false) {
+ throw new RuntimeException('Application base dir not found');
+ }
+
+ $libDir = getenv('ICINGAWEB_ICINGA_LIB') ?: realpath($baseDir . '/library/Icinga');
+ if ($libDir === false) {
+ throw new RuntimeException('Icinga library dir not found');
+ }
+
+ self::$appDir = $baseDir . '/application';
+ self::$libDir = $libDir;
+ self::$etcDir = $baseDir . '/etc';
+ self::$testDir = $baseDir . '/test/php';
+ self::$shareDir = $baseDir . '/share/icinga2-web';
+ self::$moduleDir = getenv('ICINGAWEB_MODULES_DIR') ?: $baseDir . '/modules';
+ }
+
+ /**
+ * Setup MVC bootstrapping and ensure that the Icinga-Mock gets reinitialized
+ */
+ public function setUp(): void
+ {
+ parent::setUp();
+
+ StaticTranslator::$instance = new NoopTranslator();
+ $this->setupIcingaMock();
+ }
+
+ /**
+ * Setup mock object for the application's bootstrap
+ *
+ * @return Mockery\Mock
+ */
+ protected function setupIcingaMock()
+ {
+ $requestMock = Mockery::mock('Icinga\Web\Request')->shouldDeferMissing();
+ $requestMock->shouldReceive('getPathInfo')->andReturn('')->byDefault()
+ ->shouldReceive('getBaseUrl')->andReturn('/')->byDefault()
+ ->shouldReceive('getQuery')->andReturn(array())->byDefault()
+ ->shouldReceive('getParam')->with(Mockery::type('string'), Mockery::type('string'))
+ ->andReturnUsing(function ($name, $default) {
+ return $default;
+ })->byDefault();
+
+ $responseMock = Mockery::mock('Icinga\Web\Response')->shouldDeferMissing();
+ // Can't express this as demeter chains. See: https://github.com/padraic/mockery/issues/59
+ $bootstrapMock = Mockery::mock('Icinga\Application\ApplicationBootstrap')->shouldDeferMissing();
+ $libDir = dirname(self::$libDir);
+ $bootstrapMock->shouldReceive('getFrontController')->andReturn($bootstrapMock)
+ ->shouldReceive('getApplicationDir')->andReturn(self::$appDir)
+ ->shouldReceive('getLibraryDir')->andReturnUsing(function ($subdir = null) use ($libDir) {
+ if ($subdir !== null) {
+ $libDir .= '/' . ltrim($subdir, '/');
+ }
+ return $libDir;
+ })
+ ->shouldReceive('getRequest')->andReturn($requestMock)
+ ->shouldReceive('getResponse')->andReturn($responseMock);
+
+ Icinga::setApp($bootstrapMock, true);
+ return $bootstrapMock;
+ }
+
+ /**
+ * Return the currently active request mock object
+ *
+ * @return Icinga\Web\Request
+ */
+ public function getRequestMock()
+ {
+ return Icinga::app()->getRequest();
+ }
+
+ /**
+ * Return the currently active response mock object
+ *
+ * @return Icinga\Web\Response
+ */
+ public function getResponseMock()
+ {
+ return Icinga::app()->getFrontController()->getResponse();
+ }
+
+ /**
+ * Create Config for database configuration
+ *
+ * @param string $name
+ *
+ * @return ConfigObject
+ * @throws RuntimeException
+ */
+ protected function createDbConfigFor($name)
+ {
+ if (array_key_exists($name, self::$dbConfiguration)) {
+ $config = new ConfigObject(self::$dbConfiguration[$name]);
+
+ $host = getenv(sprintf('ICINGAWEB_TEST_%s_HOST', strtoupper($name)));
+ if ($host) {
+ $config['host'] = $host;
+ }
+
+ $port = getenv(sprintf('ICINGAWEB_TEST_%s_PORT', strtoupper($name)));
+ if ($port) {
+ $config['port'] = $port;
+ }
+
+ return $config;
+ }
+
+ throw new RuntimeException('Configuration for database type not available: ' . $name);
+ }
+
+ /**
+ * Creates an array of Icinga\Data\Db\DbConnection
+ *
+ * @param string $name
+ *
+ * @return array
+ */
+ protected function createDbConnectionFor($name)
+ {
+ try {
+ $conn = ResourceFactory::createResource($this->createDbConfigFor($name));
+ } catch (Exception $e) {
+ $conn = $e->getMessage();
+ }
+
+ return array(
+ array($conn)
+ );
+ }
+
+ /**
+ * PHPUnit provider for mysql
+ *
+ * @return DbConnection
+ */
+ public function mysqlDb()
+ {
+ return $this->createDbConnectionFor('mysql');
+ }
+
+ /**
+ * PHPUnit provider for pgsql
+ *
+ * @return DbConnection
+ */
+ public function pgsqlDb()
+ {
+ return $this->createDbConnectionFor('pgsql');
+ }
+
+ /**
+ * PHPUnit provider for oracle
+ *
+ * @return DbConnection
+ */
+ public function oracleDb()
+ {
+ return $this->createDbConnectionFor('oracle');
+ }
+
+ /**
+ * Executes sql file by using the database connection
+ *
+ * @param DbConnection $resource
+ * @param string $filename
+ *
+ * @throws RuntimeException
+ */
+ public function loadSql(DbConnection $resource, $filename)
+ {
+ if (!is_file($filename)) {
+ throw new RuntimeException(
+ 'Sql file not found: ' . $filename . ' (test=' . $this->getName() . ')'
+ );
+ }
+
+ $sqlData = file_get_contents($filename);
+
+ if (!$sqlData) {
+ throw new RuntimeException(
+ 'Sql file is empty: ' . $filename . ' (test=' . $this->getName() . ')'
+ );
+ }
+
+ $resource->getDbAdapter()->exec($sqlData);
+ }
+
+ /**
+ * Setup provider for testcase
+ *
+ * @param string|DbConnection|null $resource
+ */
+ public function setupDbProvider($resource)
+ {
+ if (!$resource instanceof DbConnection) {
+ if (is_string($resource)) {
+ $this->markTestSkipped('Could not initialize provider: ' . $resource);
+ } else {
+ $this->markTestSkipped('Could not initialize provider');
+ }
+ return;
+ }
+
+ $adapter = $resource->getDbAdapter();
+
+ try {
+ $adapter->getConnection();
+ } catch (Exception $e) {
+ $this->markTestSkipped('Could not connect to provider: '. $e->getMessage());
+ }
+
+ $tables = $adapter->listTables();
+ foreach ($tables as $table) {
+ $adapter->exec('DROP TABLE ' . $table . ';');
+ }
+ }
+
+ /**
+ * Add assertMatchesRegularExpression() method for phpunit >= 8.0 < 9.0 for compatibility with PHP 7.2.
+ *
+ * @TODO Remove once PHP 7.2 support is not needed for testing anymore.
+ */
+ public static function assertMatchesRegularExpression(
+ string $pattern,
+ string $string,
+ string $message = ''
+ ): void {
+ if (method_exists(parent::class, 'assertMatchesRegularExpression')) {
+ parent::assertMatchesRegularExpression($pattern, $string, $message);
+ } else {
+ static::assertRegExp($pattern, $string, $message);
+ }
+ }
+ }
+
+ BaseTestCase::setupTimezone();
+ BaseTestCase::setupDirectories();
+}
diff --git a/library/Icinga/Test/ClassLoader.php b/library/Icinga/Test/ClassLoader.php
new file mode 100644
index 0000000..af90a7e
--- /dev/null
+++ b/library/Icinga/Test/ClassLoader.php
@@ -0,0 +1,113 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Test;
+
+/**
+ * PSR-4 class loader
+ */
+class ClassLoader
+{
+ /**
+ * Namespace separator
+ */
+ const NAMESPACE_SEPARATOR = '\\';
+
+ /**
+ * Namespaces
+ *
+ * @var array
+ */
+ private $namespaces = array();
+
+ /**
+ * Register a base directory for a namespace prefix
+ *
+ * @param string $namespace
+ * @param string $directory
+ *
+ * @return $this
+ */
+ public function registerNamespace($namespace, $directory)
+ {
+ $this->namespaces[$namespace] = $directory;
+
+ return $this;
+ }
+
+ /**
+ * Test whether a namespace exists
+ *
+ * @param string $namespace
+ *
+ * @return bool
+ */
+ public function hasNamespace($namespace)
+ {
+ return array_key_exists($namespace, $this->namespaces);
+ }
+
+ /**
+ * Get the source file of the given class or interface
+ *
+ * @param string $class Name of the class or interface
+ *
+ * @return string|null
+ */
+ public function getSourceFile($class)
+ {
+ foreach ($this->namespaces as $namespace => $dir) {
+ if ($class === strstr($class, $namespace)) {
+ $classPath = str_replace(
+ self::NAMESPACE_SEPARATOR,
+ DIRECTORY_SEPARATOR,
+ substr($class, strlen($namespace))
+ ) . '.php';
+ if (file_exists($file = $dir . $classPath)) {
+ return $file;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Load the given class or interface
+ *
+ * @param string $class Name of the class or interface
+ *
+ * @return bool Whether the class or interface has been loaded
+ */
+ public function loadClass($class)
+ {
+ if ($file = $this->getSourceFile($class)) {
+ require $file;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Register {@link loadClass()} as an autoloader
+ */
+ public function register()
+ {
+ spl_autoload_register(array($this, 'loadClass'));
+ }
+
+ /**
+ * Unregister {@link loadClass()} as an autoloader
+ */
+ public function unregister()
+ {
+ spl_autoload_unregister(array($this, 'loadClass'));
+ }
+
+ /**
+ * Unregister this as an autoloader
+ */
+ public function __destruct()
+ {
+ $this->unregister();
+ }
+}
diff --git a/library/Icinga/Test/DbTest.php b/library/Icinga/Test/DbTest.php
new file mode 100644
index 0000000..d1b1ff0
--- /dev/null
+++ b/library/Icinga/Test/DbTest.php
@@ -0,0 +1,47 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Test;
+
+use Icinga\Data\Db\DbConnection;
+
+interface DbTest
+{
+ /**
+ * PHPUnit provider for mysql
+ *
+ * @return DbConnection
+ */
+ public function mysqlDb();
+
+ /**
+ * PHPUnit provider for pgsql
+ *
+ * @return DbConnection
+ */
+ public function pgsqlDb();
+
+ /**
+ * PHPUnit provider for oracle
+ *
+ * @return DbConnection
+ */
+ public function oracleDb();
+
+ /**
+ * Executes sql file on PDO object
+ *
+ * @param DbConnection $resource
+ * @param string $filename
+ *
+ * @return boolean Operational success flag
+ */
+ public function loadSql(DbConnection $resource, $filename);
+
+ /**
+ * Setup provider for testcase
+ *
+ * @param string|DbConnection|null $resource
+ */
+ public function setupDbProvider($resource);
+}