diff --git a/.gitignore b/.gitignore index df2c1fb5b..d57bdee03 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ test/php/bin/extcmd_test # misc test output test/frontend/static/public +test/php/library/Icinga/Protocol/Statusdat/.cache # Generated API documentation doc/api diff --git a/.vagrant-puppet/files/etc/icingaweb/authentication.ini b/.vagrant-puppet/files/etc/icingaweb/authentication.ini new file mode 100644 index 000000000..551cee143 --- /dev/null +++ b/.vagrant-puppet/files/etc/icingaweb/authentication.ini @@ -0,0 +1,9 @@ +[internal_ldap_authentication] +backend = ldap +resource = internal_ldap +user_class = inetOrgPerson +user_name_attribute = uid + +[internal_db_authentication] +backend = db +resource = internal_db diff --git a/.vagrant-puppet/files/etc/icingaweb/dashboard/dashboard.ini b/.vagrant-puppet/files/etc/icingaweb/dashboard/dashboard.ini new file mode 100644 index 000000000..50e5a6373 --- /dev/null +++ b/.vagrant-puppet/files/etc/icingaweb/dashboard/dashboard.ini @@ -0,0 +1,35 @@ +[Incidents] +title = "Current incidents" + +[Incidents.Service Problems] +url = "monitoring/list/services" +service_problem = 1 +limit = 10 +sort = service_severity + +[Incidents.Recently Recovered Services] +url = "monitoring/list/services" +sort = "service_last_state_change" +service_state = 0 +limit = 10 +dir = "desc" + +[Incidents.Host Problems] +url = "monitoring/list/hosts" +host_problem = 1 +sort = host_severity + +[Landing] +title = "Landing page" + +[Landing.Hostgroups] +url = "monitoring/chart/hostgroup?height=400&width=500" + +[Landing.Servicegroups] +url = "monitoring/chart/servicegroup?height=360&width=450" + +[Landing.Unhandled Problem Services] +url = "monitoring/list/services?service_handled=0&service_problem=1" + +[Landing.Unhandled Problem Hosts] +url = "monitoring/list/hosts?host_handled=0&host_problem=1" diff --git a/.vagrant-puppet/files/etc/icingaweb/menu.ini b/.vagrant-puppet/files/etc/icingaweb/menu.ini new file mode 100644 index 000000000..b63914202 --- /dev/null +++ b/.vagrant-puppet/files/etc/icingaweb/menu.ini @@ -0,0 +1,25 @@ +[Dashboard] +title = "Dashboard" +url = "dashboard" +icon = "img/icons/dashboard.png" +priority = 10 + +[System] +icon = img/icons/configuration.png +priority = 200 + +[System.Preferences] +title = "Preferences" +url = "preference" +priority = 200 + +[System.Configuration] +title = "Configuration" +url = "config" +priority = 300 + +[Logout] +url = "authentication/logout" +icon = img/icons/logout.png +priority = 300 + diff --git a/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/backends.ini b/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/backends.ini new file mode 100644 index 000000000..6805f2e8b --- /dev/null +++ b/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/backends.ini @@ -0,0 +1,19 @@ +[localdb] + +type = ido +resource = "ido" + +[locallive] +disabled = "1" +type = livestatus +resource = livestatus + +[localfile] +disabled = "1" +type = statusdat +resource = statusdat + +;[localfailsafe] +;enabled=false +;type = combo +;backends = localdb, locallive, localfile diff --git a/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/instances.ini b/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/instances.ini new file mode 100644 index 000000000..2f54e11e3 --- /dev/null +++ b/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/instances.ini @@ -0,0 +1,2 @@ +[icinga] +path = "/usr/local/icinga-mysql/var/rw/icinga.cmd" diff --git a/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/menu.ini b/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/menu.ini new file mode 100644 index 000000000..0c7e37dea --- /dev/null +++ b/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/menu.ini @@ -0,0 +1,100 @@ + +[Problems] +priority = 20 +icon = "img/icons/error.png" + +[Problems.Unhandled Hosts] +priority = 40 +url = "monitoring/list/hosts?host_problem=1&host_handled=0" + +[Problems.Unhandled Services] +priority = 40 +url = "monitoring/list/services?service_problem=1&service_handled=0&sort=service_severity" + +[Problems.Host Problems] +priority = 50 +url = "monitoring/list/hosts?host_problem=1&sort=host_severity" + +[Problems.Service Problems] +priority = 50 +url = "monitoring/list/services?service_problem=1&sort=service_severity&dir=desc" + +[Problems.Current Downtimes] +url = "monitoring/list/downtimes?downtime_is_in_effect=1" + +[Overview] +priority = 30 +icon = "img/icons/hostgroup.png" + +[Overview.Tactical Overview] +title = "Tactical Overview" +url = "monitoring/tactical" +priority = 40 + +[Overview.Hosts] +title = "Hosts" +url = "monitoring/list/hosts" +priority = 50 + +[Overview.Services] +title = "Services" +url = "monitoring/list/services" +priority = 50 + +[Overview.Servicematrix] +title = "Servicematrix" +url = "monitoring/list/servicematrix" +priority = 51 + +[Overview.Servicegroups] +title = "Servicegroups" +url = "monitoring/list/servicegroups" +priority = 60 + +[Overview.Hostgroups] +title = "Hostgroups" +url = "monitoring/list/hostgroups" +priority = 60 + +[Overview.Contactgroups] +title = "Contactgroups" +url = "monitoring/list/contactgroups" +priority = 61 + +[Overview.Downtimes] +title = "Downtimes" +url = "monitoring/list/downtimes" +priority = 70 + +[Overview.Comments] +title = "Comments" +url = "monitoring/list/comments" +priority = 70 + +[History] +icon = "img/icons/history.png" + +[History.Critical Events] +title = "Critical Events" +url = "monitoring/list/statehistorysummary" +priority = 50 + +[History.Notifications] +title = "Notifications" +url = "monitoring/list/notifications" + +[History.Events] +title = "All Events" +url = "monitoring/list/eventhistory?raw_timestamp>=-2+days" + +[System.Process Info] +title = "Process Info" +url = "monitoring/process/info" +priority = 120 + +[System.Performance Info] +title = "Performance Info" +url = "monitoring/process/performance" +priority = 130 + + diff --git a/.vagrant-puppet/files/etc/icingaweb/resources.ini b/.vagrant-puppet/files/etc/icingaweb/resources.ini new file mode 100644 index 000000000..2ef51e921 --- /dev/null +++ b/.vagrant-puppet/files/etc/icingaweb/resources.ini @@ -0,0 +1,34 @@ +[internal_db] +type = db +db = mysql +host = localhost +port = 3306 +password = icingaweb +username = icingaweb +dbname = icingaweb + +[ido] +type = db +db = mysql +host = localhost +port = 3306 +password = icinga +username = icinga +dbname = icinga + +[statusdat] +type = statusdat +status_file = /usr/local/icinga-mysql/var/status.dat +object_file = /usr/local/icinga-mysql/var/objects.cache + +[livestatus] +type = livestatus +socket = /usr/local/icinga-mysql/var/rw/live + +[internal_ldap] +type = ldap +hostname = localhost +port = 389 +root_dn = "ou=people, dc=icinga, dc=org" +bind_dn = "cn=admin,cn=config" +bind_pw = admin diff --git a/.vagrant-puppet/manifests/default.pp b/.vagrant-puppet/manifests/default.pp index e55d916fb..9c5666a89 100644 --- a/.vagrant-puppet/manifests/default.pp +++ b/.vagrant-puppet/manifests/default.pp @@ -637,33 +637,30 @@ file { '/etc/icingaweb': } file { '/etc/icingaweb/authentication.ini': - replace => 'no', - source => 'puppet:////vagrant/config/authentication.ini', + source => 'puppet:////vagrant/.vagrant-puppet/files/etc/icingaweb/authentication.ini', owner => 'apache', group => 'apache', require => File['/etc/icingaweb'] } file { '/etc/icingaweb/config.ini': - replace => 'no', - source => 'puppet:////vagrant/config/config.ini', + ensure => file, owner => 'apache', group => 'apache', - require => File['/etc/icingaweb'] } file { '/etc/icingaweb/menu.ini': - replace => 'no', - source => 'puppet:////vagrant/config/menu.ini', + source => 'puppet:////vagrant/.vagrant-puppet/files/etc/icingaweb/menu.ini', owner => 'apache', group => 'apache', + # replace => false, } file { '/etc/icingaweb/resources.ini': - replace => 'no', - source => 'puppet:////vagrant/config/resources.ini', + source => 'puppet:////vagrant/.vagrant-puppet/files/etc/icingaweb/resources.ini', owner => 'apache', group => 'apache', + replace => false } file { ['/etc/icingaweb/enabledModules', '/etc/icingaweb/modules', '/etc/icingaweb/modules/monitoring']: @@ -672,30 +669,20 @@ file { ['/etc/icingaweb/enabledModules', '/etc/icingaweb/modules', '/etc/icingaw group => 'apache', } -file { '/etc/icingaweb/enabledModules/monitoring': - ensure => 'link', - target => '/vagrant/modules/monitoring', - owner => 'apache', - group => 'apache', -} - file { '/etc/icingaweb/modules/monitoring/backends.ini': - replace => 'no', - source => 'puppet:////vagrant/config/modules/monitoring/backends.ini', + source => 'puppet:////vagrant/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/backends.ini', owner => 'apache', group => 'apache', } file { '/etc/icingaweb/modules/monitoring/instances.ini': - replace => 'no', - source => 'puppet:////vagrant/config/modules/monitoring/instances.ini', + source => 'puppet:////vagrant/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/instances.ini', owner => 'apache', group => 'apache', } file { '/etc/icingaweb/modules/monitoring/menu.ini': - replace => 'no', - source => 'puppet:////vagrant/config/modules/monitoring/menu.ini', + source => 'puppet:////vagrant/.vagrant-puppet/files/etc/icingaweb/modules/monitoring/menu.ini', owner => 'apache', group => 'apache', } @@ -707,8 +694,11 @@ file { '/etc/icingaweb/dashboard': } file { '/etc/icingaweb/dashboard/dashboard.ini': - replace => 'no', - source => 'puppet:////vagrant/config/dashboard/dashboard.ini', + source => 'puppet:////vagrant/.vagrant-puppet/files/etc/icingaweb/dashboard/dashboard.ini', owner => 'apache', group => 'apache', } + +pear::package { 'deepend/Mockery': + channel => 'pear.survivethedeepend.com' +} diff --git a/.vagrant-puppet/modules/pear/manifests/package.pp b/.vagrant-puppet/modules/pear/manifests/package.pp index ed004d139..90b807b3d 100644 --- a/.vagrant-puppet/modules/pear/manifests/package.pp +++ b/.vagrant-puppet/modules/pear/manifests/package.pp @@ -28,14 +28,23 @@ define pear::package( $require_ = Class['pear'] } + if $channel { + exec { "pear discover ${channel}": + command => "sudo pear channel-discover ${channel}", + unless => "pear channel-info ${channel}", + require => $require_, + before => Exec["pear install ${name}"] + } + } + exec { "pear install ${name}": - command => "pear install --alldeps ${channel}", - creates => "/usr/bin/${name}", + command => "pear install --alldeps ${name}", + unless => "pear list ${name}", require => $require_ } exec { "pear upgrade ${name}": - command => "pear upgrade ${channel}", + command => "pear upgrade ${name}", require => Exec["pear install ${name}"] } } diff --git a/application/clicommands/AutocompleteCommand.php b/application/clicommands/AutocompleteCommand.php index b41b59fd8..4171b27c1 100644 --- a/application/clicommands/AutocompleteCommand.php +++ b/application/clicommands/AutocompleteCommand.php @@ -1,4 +1,5 @@ fail("Not implemented yet"); } } +// @codeCoverageIgnoreEnd diff --git a/application/clicommands/WebCommand.php b/application/clicommands/WebCommand.php index 3e67e7ac4..12d140f43 100644 --- a/application/clicommands/WebCommand.php +++ b/application/clicommands/WebCommand.php @@ -1,4 +1,5 @@ view->tabs->activate('authentication'); $order = array_keys($config->toArray()); - $this->view->backends = array(); $this->view->messageBox = new AlertMessageBox(true); - foreach ($config as $backend=>$backendConfig) { + $backends = array(); + foreach ($order as $backend) { $form = new ReorderForm(); $form->setName('form_reorder_backend_' . $backend); - $form->setAuthenticationBackend($backend); + $form->setBackendName($backend); $form->setCurrentOrder($order); $form->setRequest($this->_request); - if (!$showOnly && $form->isSubmittedAndValid()) { + if ($form->isSubmittedAndValid()) { if ($this->writeAuthenticationFile($form->getReorderedConfig($config))) { $this->addSuccessMessage('Authentication Order Updated'); $this->redirectNow('config/authentication'); } + return; } - $this->view->backends[] = (object) array( - 'name' => $backend, - 'reorderForm' => $form + $backends[] = (object) array( + 'name' => $backend, + 'reorderForm' => $form ); } - $this->render('authentication'); + + $this->view->backends = $backends; } /** @@ -398,7 +397,7 @@ class ConfigController extends BaseConfigController { $this->view->resourceTypes = $this->resourceTypes; $resources = IcingaConfig::app('resources', true); - $form = new EditResourceForm(); + $form = new ResourceForm(); $form->setRequest($this->_request); if ($form->isSubmittedAndValid()) { $name = $form->getName(); @@ -430,7 +429,7 @@ class ConfigController extends BaseConfigController $this->render('resource/modify'); return; } - $form = new EditResourceForm(); + $form = new ResourceForm(); if ($this->_request->isPost() === false) { $form->setOldName($name); $form->setName($name); @@ -558,4 +557,4 @@ class ConfigController extends BaseConfigController } } } -// @codingStandardsIgnoreEnd +// @codeCoverageIgnoreEnd diff --git a/application/controllers/DashboardController.php b/application/controllers/DashboardController.php index 6c6084b80..7b917e2e7 100644 --- a/application/controllers/DashboardController.php +++ b/application/controllers/DashboardController.php @@ -1,5 +1,5 @@ getTabs()->add('addurl', array( - 'title' => 'Add Dashboard URL', - 'url' => Url::fromRequest() - ))->activate('addurl'); + $this->getTabs()->add( + 'addurl', + array( + 'title' => 'Add Dashboard URL', + 'url' => Url::fromRequest() + ) + )->activate('addurl'); + $form = new AddUrlForm(); - $form->setRequest($this->_request); + $form->setRequest($this->getRequest()); + $form->setAction(Url::fromRequest()->setParams(array())->getAbsoluteUrl()); $this->view->form = $form; + if ($form->isSubmittedAndValid()) { $dashboard = $this->getDashboard(); $dashboard->setComponentUrl( @@ -102,15 +110,12 @@ class DashboardController extends ActionController $form->getValue('component'), ltrim($form->getValue('url'), '/') ); - try { - $dashboard->store(); - $this->redirectNow( - Url::fromPath('dashboard', array('pane' => $form->getValue('pane'))) - ); - } catch (ConfigurationError $exc) { - $this->_helper->viewRenderer('show_configuration'); - $this->view->exceptionMessage = $exc->getMessage(); - $this->view->iniConfigurationString = $dashboard->toIni(); + + $configFile = IcingaConfig::app('dashboard/dashboard')->getConfigFile(); + if ($this->writeConfiguration(new Zend_Config($dashboard->toArray()), $configFile)) { + $this->redirectNow(Url::fromPath('dashboard', array('pane' => $form->getValue('pane')))); + } else { + $this->render('show-configuration'); } } } @@ -141,5 +146,30 @@ class DashboardController extends ActionController */ $this->view->dashboard = $dashboard; } + + /** + * Store the given configuration as INI file + * + * @param Zend_Config $config The configuration to store + * @param string $target The path where to store the configuration + * + * @return bool Whether the configuartion has been successfully stored + */ + protected function writeConfiguration(Zend_Config $config, $target) + { + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + + try { + $writer->write(); + } catch (Exception $e) { + Logger::error(new ConfiguationError("Cannot write dashboard to $target", 0, $e)); + $this->view->iniConfigurationString = $writer->render(); + $this->view->exceptionMessage = $e->getMessage(); + $this->view->file = $target; + return false; + } + + return true; + } } -// @codingStandardsIgnoreEnd +// @codeCoverageIgnoreEnd diff --git a/application/controllers/ErrorController.php b/application/controllers/ErrorController.php index 06034ae4e..343a40b7f 100644 --- a/application/controllers/ErrorController.php +++ b/application/controllers/ErrorController.php @@ -1,5 +1,5 @@ getResponse()->setHttpResponseCode(500); - $this->view->title = 'Server error'; + $this->view->title = 'Server error: ' . $exception->getMessage(); $this->view->message = $exception->getMessage(); if ($this->getInvokeArg('displayExceptions') == true) { $this->view->stackTrace = $exception->getTraceAsString(); @@ -77,4 +77,4 @@ class ErrorController extends ActionController $this->view->request = $error->request; } } -// @codingStandardsIgnoreEnd +// @codeCoverageIgnoreEnd diff --git a/application/controllers/FilterController.php b/application/controllers/FilterController.php index 72f0a2ad0..74ade2492 100644 --- a/application/controllers/FilterController.php +++ b/application/controllers/FilterController.php @@ -1,4 +1,5 @@ renderScript('parts/topbar.phtml'); } } -// @codingStandardsIgnoreEnd +// @codeCoverageIgnoreEnd diff --git a/application/controllers/ListController.php b/application/controllers/ListController.php index a2c1e5138..c062266a9 100644 --- a/application/controllers/ListController.php +++ b/application/controllers/ListController.php @@ -1,5 +1,5 @@ toArray(); if (!in_array('logging', $config_ini) || ( in_array('type', $config_ini['logging']) && - $config_ini['logging']['type'] === 'stream' && + $config_ini['logging']['type'] === 'file' && in_array('target', $config_ini['logging']) && file_exists($config_ini['logging']['target']) ) @@ -79,4 +79,4 @@ class ListController extends Controller } } } -// @codingStandardsIgnoreEnd +// @codeCoverageIgnoreEnd diff --git a/application/controllers/PreferenceController.php b/application/controllers/PreferenceController.php index 3393226e7..b3c9e5302 100644 --- a/application/controllers/PreferenceController.php +++ b/application/controllers/PreferenceController.php @@ -1,5 +1,5 @@ view->form = $form; } } -// @codingStandardsIgnoreEnd +// @codeCoverageIgnoreEnd diff --git a/application/controllers/SearchController.php b/application/controllers/SearchController.php index d0a76a737..5760803da 100644 --- a/application/controllers/SearchController.php +++ b/application/controllers/SearchController.php @@ -1,10 +1,5 @@ - * @license http://www.icinga.org/license/gpl2 GPL, version 2 - */ +// @codeCoverageIgnoreStart use Icinga\Web\Controller\ActionController; use Icinga\Application\Icinga; @@ -50,3 +45,4 @@ class SearchController extends ActionController $this->view->tabs = $dashboard->getTabs(); } } +// @codeCoverageIgnoreEnd diff --git a/application/controllers/StaticController.php b/application/controllers/StaticController.php index 1b85618f6..17089510a 100644 --- a/application/controllers/StaticController.php +++ b/application/controllers/StaticController.php @@ -1,5 +1,5 @@ printStack(); } } -// @codingStandardsIgnoreEnd +// @codeCoverageIgnoreEnd diff --git a/application/forms/Authentication/LoginForm.php b/application/forms/Authentication/LoginForm.php index b4e79cbe8..97ca3ea2c 100644 --- a/application/forms/Authentication/LoginForm.php +++ b/application/forms/Authentication/LoginForm.php @@ -1,4 +1,5 @@ 'backend_force_creation', - 'label' => 'Force Changes', - 'helptext' => 'Check this box to enforce changes without connectivity validation', + 'label' => t('Force Changes'), + 'helptext' => t('Check this box to enforce changes without connectivity validation'), 'order' => 0 ) ); @@ -150,16 +150,16 @@ abstract class BaseBackendForm extends Form * If logic validation fails, the 'backend_force_creation' checkbox is prepended to the form to allow users to * skip the logic connection validation. * - * @param array $data The form input to validate + * @param array $data The form input to validate * - * @return bool True when validation succeeded, false if not + * @return bool Whether validation succeeded or not */ public function isValid($data) { if (!parent::isValid($data)) { return false; } - if ($this->getRequest()->getPost('backend_force_creation')) { + if (isset($data['backend_force_creation']) && $data['backend_force_creation']) { return true; } if (!$this->isValidAuthenticationBackend()) { @@ -173,7 +173,7 @@ abstract class BaseBackendForm extends Form * Return an array containing all sections defined by this form as the key and all settings * as an key-value sub-array * - * @return array + * @return array */ abstract public function getConfig(); @@ -183,7 +183,7 @@ abstract class BaseBackendForm extends Form * An implementation should not throw any exception, but use the add/setErrorMessages method of * Zend_Form. If the 'backend_force_creation' checkbox is set, this method won't be called. * - * @return bool True when validation succeeded, otherwise false + * @return bool Whether validation succeeded or not */ abstract public function isValidAuthenticationBackend(); } diff --git a/application/forms/Config/Authentication/DbBackendForm.php b/application/forms/Config/Authentication/DbBackendForm.php index 437d4ae8c..e7ab9bc3f 100644 --- a/application/forms/Config/Authentication/DbBackendForm.php +++ b/application/forms/Config/Authentication/DbBackendForm.php @@ -29,8 +29,11 @@ namespace Icinga\Form\Config\Authentication; +use \Exception; use \Icinga\Authentication\Backend\DbUserBackend; use \Zend_Config; +use Icinga\Data\ResourceFactory; +use Icinga\Authentication\UserBackend; /** * Form class for adding/modifying database authentication backends @@ -38,21 +41,23 @@ use \Zend_Config; class DbBackendForm extends BaseBackendForm { /** - * Return a list of all database resource ready to be used as the multiOptions - * attribute in a Zend_Form_Element_Select object + * Return content of the resources.ini or previously set resources * - * @return array + * @return array */ - private function getDatabaseResources() + public function getResources() { - $backends = array(); - foreach ($this->getResources() as $resname => $resource) { - if ($resource['type'] !== 'db') { - continue; + if ($this->resources === null) { + $res = ResourceFactory::getResourceConfigs('db')->toArray(); + + foreach (array_keys($res) as $key) { + $res[$key] = $key; } - $backends[$resname] = $resname; + + return $res; + } else { + return $this->resources; } - return $backends; } /** @@ -64,15 +69,14 @@ class DbBackendForm extends BaseBackendForm { $this->setName('form_modify_backend'); $name = $this->filterName($this->getBackendName()); - $this->addElement( 'text', 'backend_' . $name . '_name', array( 'required' => true, - 'allowEmpty' => false, - 'label' => 'Backend Name', - 'helptext' => 'The name of this authentication provider', + 'allowEmpty' => false, + 'label' => t('Backend Name'), + 'helptext' => t('The name of this authentication provider'), 'value' => $this->getBackendName() ) ); @@ -81,12 +85,12 @@ class DbBackendForm extends BaseBackendForm 'select', 'backend_' . $name . '_resource', array( - 'label' => 'Database Connection', - 'required' => true, - 'allowEmpty' => false, - 'helptext' => 'The database connection to use for authenticating with this provider', - 'value' => $this->getBackend()->get('resource'), - 'multiOptions' => $this->getDatabaseResources() + 'required' => true, + 'allowEmpty' => false, + 'label' => t('Database Connection'), + 'helptext' => t('The database connection to use for authenticating with this provider'), + 'value' => $this->getBackend()->get('resource'), + 'multiOptions' => $this->getResources() ) ); @@ -112,53 +116,39 @@ class DbBackendForm extends BaseBackendForm */ public function getConfig() { - $name = $this->getBackendName(); - $prefix = 'backend_' . $this->filterName($name) . '_'; - + $prefix = 'backend_' . $this->filterName($this->getBackendName()) . '_'; $section = $this->getValue($prefix . 'name'); $cfg = array( - 'backend' => 'db', - 'target' => 'user', - 'resource' => $this->getValue($prefix . 'resource'), - ); - return array( - $section => $cfg + 'backend' => 'db', + 'resource' => $this->getValue($prefix . 'resource'), ); + + return array($section => $cfg); } /** * Validate the current configuration by creating a backend and requesting the user count * - * @return bool True when the backend is valid, false otherwise + * @return bool Whether validation succeeded or not + * * @see BaseBackendForm::isValidAuthenticationBackend */ public function isValidAuthenticationBackend() { - // @TODO fix validation of authentication backends (AK #5712) - return true; try { - $name = $this->getBackendName(); - $dbBackend = new DbUserBackend( - new Zend_Config( - array( - 'backend' => 'db', - 'target' => 'user', - 'resource' => $this->getValue('backend_' . $this->filterName($name) . '_resource'), - ) - ) - ); - $dbBackend->connect(); - if ($dbBackend->getUserCount() < 1) { - $this->addErrorMessage("No users found under the specified database backend"); + $testConnection = ResourceFactory::createResource(ResourceFactory::getResourceConfig( + $this->getValue('backend_' . $this->filterName($this->getBackendName()) . '_resource') + )); + $dbUserBackend = new DbUserBackend($testConnection); + if ($dbUserBackend->count() < 1) { + $this->addErrorMessage(t("No users found under the specified database backend")); return false; } - } catch (\Exception $e) { - $this->addErrorMessage("Using the specified backend failed: " . $e->getMessage()); - return false; - } catch (\Zend_Db_Statement_Exception $e) { - $this->addErrorMessage("Using the specified backend failed: " . $e->getMessage()); + } catch (Exception $e) { + $this->addErrorMessage(sprintf(t('Using the specified backend failed: %s'), $e->getMessage())); return false; } + return true; } } diff --git a/application/forms/Config/Authentication/LdapBackendForm.php b/application/forms/Config/Authentication/LdapBackendForm.php index d52cf451b..966cea1cc 100644 --- a/application/forms/Config/Authentication/LdapBackendForm.php +++ b/application/forms/Config/Authentication/LdapBackendForm.php @@ -30,11 +30,10 @@ namespace Icinga\Form\Config\Authentication; use \Exception; -use Icinga\Data\ResourceFactory; use \Zend_Config; -use \Icinga\Web\Form; -use \Icinga\Authentication\Backend\LdapUserBackend; -use \Icinga\Protocol\Ldap\Connection as LdapConnection; +use Icinga\Web\Form; +use Icinga\Data\ResourceFactory; +use Icinga\Authentication\Backend\LdapUserBackend; /** * Form for adding or modifying LDAP authentication backends @@ -42,14 +41,31 @@ use \Icinga\Protocol\Ldap\Connection as LdapConnection; class LdapBackendForm extends BaseBackendForm { /** - * Create this form and add all required elements + * Return content of the resources.ini or previously set resources * - * @param $options Only useful for testing purposes: - * 'resources' => All available resources. + * @return array + */ + public function getResources() + { + if ($this->resources === null) { + $res = ResourceFactory::getResourceConfigs('ldap')->toArray(); + + foreach (array_keys($res) as $key) { + $res[$key] = $key; + } + + return $res; + } else { + return $this->resources; + } + } + + /** + * Create this form and add all required elements * * @see Form::create() */ - public function create($options = array()) + public function create() { $this->setName('form_modify_backend'); $name = $this->filterName($this->getBackendName()); @@ -57,12 +73,12 @@ class LdapBackendForm extends BaseBackendForm $this->addElement( 'text', - 'backend_'.$name.'_name', + 'backend_' . $name . '_name', array( 'required' => true, - 'allowEmpty' => false, - 'label' => 'Backend Name', - 'helptext' => 'The name of this authentication backend', + 'allowEmpty' => false, + 'label' => t('Backend Name'), + 'helptext' => t('The name of this authentication backend'), 'value' => $this->getBackendName() ) ); @@ -71,13 +87,12 @@ class LdapBackendForm extends BaseBackendForm 'select', 'backend_' . $name . '_resource', array( - 'label' => 'Database Connection', - 'required' => true, - 'allowEmpty' => false, - 'helptext' => 'The database connection to use for authenticating with this provider', - 'value' => $this->getBackend()->get('resource'), - 'multiOptions' => array_key_exists('resources', $options) ? - $options['resources'] : $this->getLdapResources() + 'required' => true, + 'allowEmpty' => false, + 'label' => t('LDAP Resource'), + 'helptext' => t('The resource to use for authenticating with this provider'), + 'value' => $this->getBackend()->get('resource'), + 'multiOptions' => $this->getResources() ) ); @@ -85,10 +100,10 @@ class LdapBackendForm extends BaseBackendForm 'text', 'backend_' . $name . '_user_class', array( - 'label' => 'LDAP User Object Class', - 'value' => $backend->get('user_class', 'inetOrgPerson'), - 'helptext' => 'The object class used for storing users on the ldap server', - 'required' => true + 'required' => true, + 'label' => t('LDAP User Object Class'), + 'helptext' => t('The object class used for storing users on the ldap server'), + 'value' => $backend->get('user_class', 'inetOrgPerson') ) ); @@ -96,10 +111,10 @@ class LdapBackendForm extends BaseBackendForm 'text', 'backend_' . $name . '_user_name_attribute', array( - 'label' => 'LDAP User Name Attribute', - 'value' => $backend->get('user_name_attribute', 'uid'), - 'helptext' => 'The attribute name used for storing the user name on the ldap server', - 'required' => true + 'required' => true, + 'label' => t('LDAP User Name Attribute'), + 'helptext' => t('The attribute name used for storing the user name on the ldap server'), + 'value' => $backend->get('user_name_attribute', 'uid') ) ); @@ -125,52 +140,55 @@ class LdapBackendForm extends BaseBackendForm */ public function getConfig() { - $name = $this->getBackendName(); - $prefix = 'backend_' . $this->filterName($name) . '_'; - + $prefix = 'backend_' . $this->filterName($this->getBackendName()) . '_'; $section = $this->getValue($prefix . 'name'); $cfg = array( - 'target' => 'user', - 'resource' => $this->getValue($prefix . 'resource'), - 'user_class' => $this->getValue($prefix . 'user_class'), - 'user_name_attribute' => $this->getValue($prefix . 'user_name_attribute') - ); - return array( - $section => $cfg + 'backend' => 'ldap', + 'resource' => $this->getValue($prefix . 'resource'), + 'user_class' => $this->getValue($prefix . 'user_class'), + 'user_name_attribute' => $this->getValue($prefix . 'user_name_attribute') ); + return array($section => $cfg); } /** * Validate the current configuration by creating a backend and requesting the user count * - * @return bool True when the backend is valid, false otherwise + * @return bool Whether validation succeeded or not + * * @see BaseBackendForm::isValidAuthenticationBacken */ public function isValidAuthenticationBackend() { + if (!ResourceFactory::ldapAvailable()) { + /* + * It should be possible to run icingaweb without the php ldap extension, when + * no ldap backends are needed. When the user tries to create an ldap backend + * without ldap installed we need to show him an error. + */ + $this->addErrorMessage(t('Using ldap is not possible, the php extension "ldap" is not installed.')); + return false; + } try { $cfg = $this->getConfig(); $backendName = 'backend_' . $this->filterName($this->getBackendName()) . '_name'; $backendConfig = new Zend_Config($cfg[$this->getValue($backendName)]); - $testConn = new LdapUserBackend($backendConfig); - if ($testConn->getUserCount() === 0) { + $backend = ResourceFactory::createResource(ResourceFactory::getResourceConfig($backendConfig->resource)); + $testConn = new LdapUserBackend( + $backend, + $backendConfig->user_class, + $backendConfig->user_name_attribute + ); + if ($testConn->count() === 0) { throw new Exception('No Users Found On Directory Server'); } } catch (Exception $exc) { $this->addErrorMessage( - 'Connection Validation Failed:' . $exc->getMessage() + t('Connection Validation Failed: ' . $exc->getMessage()) ); return false; } + return true; } - - private function getLdapResources() - { - $res = ResourceFactory::getResourceConfigs('ldap')->toArray(); - foreach ($res as $key => $value) { - $res[$key] = $key; - } - return $res; - } } diff --git a/application/forms/Config/Authentication/ReorderForm.php b/application/forms/Config/Authentication/ReorderForm.php index f81ee5b0d..b6a3b81f0 100644 --- a/application/forms/Config/Authentication/ReorderForm.php +++ b/application/forms/Config/Authentication/ReorderForm.php @@ -30,12 +30,10 @@ namespace Icinga\Form\Config\Authentication; use \Zend_Config; -use \Icinga\Web\Form; -use \Icinga\Web\Url; +use Icinga\Web\Form; /** - * Form for modifying the authentication provider order. - * + * Form for modifying the authentication provider order */ class ReorderForm extends Form { @@ -44,19 +42,20 @@ class ReorderForm extends Form * * @var string */ - private $backend = null; + protected $backend; /** * The current ordering of all backends, required to determine possible changes * * @var array */ - private $currentOrder = array(); + protected $currentOrder = array(); /** * Set an array with the current order of all backends * - * @param array $order An array containing backend names in the order they are defined in the authentication.ini + * @param array $order An array containing backend names in the order + * they are defined in the authentication.ini */ public function setCurrentOrder(array $order) { @@ -66,20 +65,17 @@ class ReorderForm extends Form /** * Set the name of the authentication backend for which to create the form * - * @param string $backend The name of the authentication backend + * @param string $backend The name of the authentication backend */ - public function setAuthenticationBackend($backend) + public function setBackendName($backend) { $this->backend = $backend; } /** - * Return the name of the currently set backend as it will appear in the forms + * Return the name of the currently set backend as it will appear in the form * - * This calls the Zend Filtername function in order to filter specific chars - * - * @return string The filtered name of the backend - * @see Form::filterName() + * @return string The name of the backend */ public function getBackendName() { @@ -87,28 +83,24 @@ class ReorderForm extends Form } /** - * Create this form. - * - * Note: The form action will be set here to the authentication overview + * Create this form * * @see Form::create */ public function create() { - $this->upForm = new Form(); - $this->downForm = new Form(); - if ($this->moveElementUp($this->backend, $this->currentOrder) !== $this->currentOrder) { + $upForm = new Form(); - $this->upForm->addElement( + $upForm->addElement( 'hidden', 'form_backend_order', array( 'required' => true, - 'value' => join(',', $this->moveElementUp($this->backend, $this->currentOrder)) + 'value' => join(',', $this->moveElementUp($this->backend, $this->currentOrder)) ) ); - $this->upForm->addElement( + $upForm->addElement( 'button', 'btn_' . $this->getBackendName() . '_reorder_up', array( @@ -116,21 +108,25 @@ class ReorderForm extends Form 'escape' => false, 'value' => 'btn_' . $this->getBackendName() . '_reorder_up', 'name' => 'btn_' . $this->getBackendName() . '_reorder_up', - 'label' => $this->getView()->icon('up.png', 'Move up in authentication order'), + 'label' => $this->getView()->icon('up.png', t('Move up in authentication order')) ) ); + + $this->addSubForm($upForm, 'btn_reorder_up'); } if ($this->moveElementDown($this->backend, $this->currentOrder) !== $this->currentOrder) { - $this->downForm->addElement( + $downForm = new Form(); + + $downForm->addElement( 'hidden', 'form_backend_order', array( 'required' => true, - 'value' => join(',', $this->moveElementDown($this->backend, $this->currentOrder)) + 'value' => join(',', $this->moveElementDown($this->backend, $this->currentOrder)) ) ); - $this->downForm->addElement( + $downForm->addElement( 'button', 'btn_' . $this->getBackendName() . '_reorder_down', array( @@ -138,72 +134,68 @@ class ReorderForm extends Form 'escape' => false, 'value' => 'btn_' . $this->getBackendName() . '_reorder_down', 'name' => 'btn_' . $this->getBackendName() . '_reorder_down', - 'label' => $this->getView()->icon('down.png', 'Move down in authentication order'), - + 'label' => $this->getView()->icon('down.png', t('Move down in authentication order')) ) ); + + $this->addSubForm($downForm, 'btn_reorder_down'); } - $this->setAction(Url::fromPath("config/authentication", array())->getAbsoluteUrl()); } /** - * Return the result of $this->getValues but flatten the result + * Return the flattened result of $this->getValues * - * The result will be a key=>value array without subarrays + * @return array The currently set values * - * @param bool $supressArrayNotation passed to getValues - * - * @return array The currently set values * @see Form::getValues() */ - public function getFlattenedValues($supressArrayNotation = false) + protected function getFlattenedValues() { - $values = parent::getValues($supressArrayNotation); $result = array(); - foreach ($values as $key => &$value) { + foreach (parent::getValues() as $key => $value) { if (is_array($value)) { $result += $value; } else { $result[$key] = $value; } } + return $result; } /** * Determine whether this form is submitted by testing the submit buttons of both subforms * - * @return bool True when the form is submitted, otherwise false + * @return bool Whether the form has been submitted or not */ public function isSubmitted() { $checkData = $this->getRequest()->getParams(); - return isset ($checkData['btn_' . $this->getBackendName() . '_reorder_up']) || - isset ($checkData['btn_' . $this->getBackendName() . '_reorder_down']); + return isset($checkData['btn_' . $this->getBackendName() . '_reorder_up']) || + isset($checkData['btn_' . $this->getBackendName() . '_reorder_down']); } /** - * Return the reordered configuration after a reorder button has been submited + * Return the reordered configuration after a reorder button has been submitted * - * @param Zend_Config $config The configuration to reorder + * @param Zend_Config $config The configuration to reorder * - * @return array An array containing the reordered configuration + * @return array An array containing the reordered configuration */ public function getReorderedConfig(Zend_Config $config) { $originalConfig = $config->toArray(); - $reordered = array(); $newOrder = $this->getFlattenedValues(); $order = explode(',', $newOrder['form_backend_order']); + + $reordered = array(); foreach ($order as $key) { - if (!isset($originalConfig[$key])) { - continue; + if (isset($originalConfig[$key])) { + $reordered[$key] = $originalConfig[$key]; } - $reordered[$key] = $originalConfig[$key]; } return $reordered; - } /** @@ -216,28 +208,27 @@ class ReorderForm extends Form * moveElementUp('third', $array); // returns ['first', 'third', 'second'] * * - * @param string $key The key to bubble up one slot - * @param array $array The array to work with + * @param string $key The key to bubble up one slot + * @param array $array The array to work with * - * @return array The modified array + * @return array The modified array */ - private static function moveElementUp($key, array $array) + protected static function moveElementUp($key, array $array) { - $swap = null; - for ($i=0; $i * - * @param string $key The key to bubble up one slot - * @param array $array The array to work with + * @param string $key The key to bubble up one slot + * @param array $array The array to work with * - * @return array The modified array + * @return array The modified array */ - private static function moveElementDown($key, array $array) + protected static function moveElementDown($key, array $array) { - $swap = null; - for ($i=0; $ibaseDir = $dir; - } - - /** - * Return the applications base directory or the value from a previous setBaseDir call - * - * This is used to determine the default logging paths in a manner that allows to set a different path - * during testing - * - * @return string - */ - public function getBaseDir() - { - if ($this->baseDir) { - return $this->baseDir; - } - return realpath(Icinga::app()->getApplicationDir() . '/../'); - } - - /** - * Return true if the debug log path textfield should be displayed - * - * This is the case if the "logging_use_debug" field is autosubmitted - * and true or if it is not submitted, but the configuration for debug - * logging is set to true - * - * @param Zend_Config $config The debug section of the config.ini - * - * @return bool Whether to display the debug path field or not - */ - private function shouldDisplayDebugLog(Zend_Config $config) - { - $debugParam = $this->getRequest()->getParam('logging_debug_enable', null); - if ($debugParam !== null) { - return intval($debugParam) === 1; - } else { - return intval($config->get('enable', 0)) === 1; - } - + return realpath(Icinga::app()->getApplicationDir() . '/../var/log/icingaweb.log'); } /** @@ -107,108 +60,124 @@ class LoggingForm extends Form $this->setName('form_config_logging'); $config = $this->getConfiguration(); - $logging = $config->logging; - - if ($logging === null) { - $logging = new Zend_Config(array()); - } - $debug = $logging->debug; - if ($debug === null) { - $debug = new Zend_Config(array()); + if (($loggingConfig = $config->logging) === null) { + $loggingConfig = new Zend_Config(array()); } - $txtLogPath = new Zend_Form_Element_Text( + $this->addElement( + 'checkbox', + 'logging_enable', + array( + 'required' => true, + 'label' => t('Logging Enabled'), + 'helptext' => t('Check this to enable logging.'), + 'value' => $loggingConfig->enable ? 1 : 0 + ) + ); + $this->addElement( + 'select', + 'logging_level', array( - 'name' => 'logging_app_target', - 'label' => 'Application Log Path', - 'helptext' => 'The logfile to write the icingaweb debug logs to.' - . 'The webserver must be able to write at this location', 'required' => true, - 'value' => $logging->get('target', $this->getBaseDir() . '/var/log/icingaweb.log') + 'label' => t('Logging Level'), + 'helptext' => t('The maximum loglevel to emit.'), + 'value' => intval($loggingConfig->get('level', 0)), + 'multiOptions' => array( + 0 => t('Error'), + 1 => t('Warning'), + 2 => t('Information'), + 3 => t('Debug') + ) ) ); - $txtLogPath->addValidator(new WritablePathValidator()); - $this->addElement($txtLogPath); - $this->addElement( - 'checkbox', - 'logging_app_verbose', + 'select', + 'logging_type', array( - 'label' => 'Verbose Logging', - 'required' => true, - 'helptext' => 'Check to write more verbose output to the icinga log file', - 'value' => intval($logging->get('verbose', 0)) === 1 + 'required' => true, + 'label' => t('Logging Type'), + 'helptext' => t('The type of logging to utilize.'), + 'value' => $loggingConfig->get('type', 'file'), + 'multiOptions' => array( + 'file' => t('File'), + 'syslog' => 'Syslog' + ) ) ); + $this->enableAutoSubmit(array('logging_type')); - $this->addElement( - 'checkbox', - 'logging_debug_enable', - array( - 'label' => 'Use Debug Log', - 'required' => true, - 'helptext' => 'Check to write a seperate debug log (Warning: This file can grow very big)', - 'value' => $this->shouldDisplayDebugLog($debug) - ) - ); + switch ($this->getRequest()->getParam('logging_type', $loggingConfig->get('type', 'file'))) + { + case 'syslog': + $this->addElement( + 'text', + 'logging_application', + array( + 'required' => true, + 'label' => t('Application Prefix'), + 'helptext' => t('The name of the application by which to prefix syslog messages.'), + 'value' => $loggingConfig->get('application', 'icingaweb') + ) + ); + $this->addElement( + 'select', + 'logging_facility', + array( + 'required' => true, + 'label' => t('Facility'), + 'helptext' => t('The Syslog facility to utilize.'), + 'value' => $loggingConfig->get('facility', 'LOG_USER'), + 'multiOptions' => array( + 'LOG_USER' => 'LOG_USER' + ) + ) + ); + break; + case 'file': + default: + $this->addElement( + 'text', + 'logging_target', + array( + 'required' => true, + 'label' => t('Filepath'), + 'helptext' => t('The logfile to write messages to.'), + 'value' => $loggingConfig->target ? $loggingConfig->target : $this->getDefaultLogDir(), + 'validators' => array(new WritablePathValidator()) + ) + ); + } - $textLoggingDebugPath = new Zend_Form_Element_Text( - array( - 'name' => 'logging_debug_target', - 'label' => 'Debug Log Path', - 'required' => $this->shouldDisplayDebugLog($debug), - 'condition' => $this->shouldDisplayDebugLog($debug), - 'value' => $debug->get('target', $this->getBaseDir() . '/var/log/icingaweb2.debug.log'), - 'helptext' => 'Set the path to the debug log' - ) - ); - $textLoggingDebugPath->addValidator(new WritablePathValidator()); - - $decorator = new ConditionalHidden(); - $this->addElement($textLoggingDebugPath); - $textLoggingDebugPath->addDecorator($decorator); - - $this->enableAutoSubmit(array('logging_debug_enable')); - - $this->addElement( - 'button', - 'btn_submit', - array( - 'type' => 'submit', - 'escape' => false, - 'value' => '1', - 'class' => 'btn btn-cta btn-common', - 'label' => ' Save Changes' - ) - ); + $this->setSubmitLabel('{{SAVE_ICON}} Save Changes'); } /** - * Return a Zend_Config object containing the state defined in this form + * Return a Zend_Config object containing the state defined in this form * - * @return Zend_Config The config defined in this form + * @return Zend_Config The config defined in this form */ public function getConfig() { - $config = $this->getConfiguration(); - if ($config->logging === null) { - $config->logging = new Zend_Config(array(), true); - } - if ($config->logging->debug === null) { - $config->logging->debug = new Zend_Config(array(), true); - } - $values = $this->getValues(); - $cfg = $config->toArray(); + $cfg = $this->getConfiguration()->toArray(); - $cfg['logging']['enable'] = 1; - $cfg['logging']['type'] = 'stream'; - $cfg['logging']['verbose'] = $values['logging_app_verbose']; - $cfg['logging']['target'] = $values['logging_app_target']; + $cfg['logging']['enable'] = $values['logging_enable'] == 1; + $cfg['logging']['level'] = $values['logging_level']; + + switch ($values['logging_type']) + { + case 'file': + $cfg['logging']['type'] = 'file'; + $cfg['logging']['target'] = $values['logging_target']; + break; + case 'syslog': + $cfg['logging']['type'] = 'syslog'; + $cfg['logging']['application'] = $values['logging_application']; + $cfg['logging']['facility'] = $values['logging_facility']; + break; + } - $cfg['logging']['debug']['enable'] = intval($values['logging_debug_enable']); - $cfg['logging']['debug']['type'] = 'stream'; - $cfg['logging']['debug']['target'] = $values['logging_debug_target']; return new Zend_Config($cfg); } } +// @codeCoverageIgnoreEnd diff --git a/application/forms/Config/Resource/CreateResourceForm.php b/application/forms/Config/Resource/CreateResourceForm.php deleted file mode 100644 index a688ae62f..000000000 --- a/application/forms/Config/Resource/CreateResourceForm.php +++ /dev/null @@ -1,13 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Icinga\Form\Config\Resource; - -use \Zend_Config; -use Icinga\Web\Form; -use Icinga\Logger\Logger; -use Icinga\Web\Form\Decorator\HelpText; -use Icinga\Data\ResourceFactory; - -/** - * Form for modifying a monitoring backend - */ -class EditResourceForm extends Form -{ - /** - * The currently edited resource. - * - * @var Zend_Config - */ - private $resource; - - /** - * @var string - */ - private $name = ''; - - /** - * @var string - */ - private $oldName = ''; - - /** - * Return the current resource name. - * - * @param string $name - * - * @return void|\Zend_Form - */ - public function setName($name) - { - $this->name = $name; - } - - /** - * @return null|string - */ - public function getName() - { - return $this->getValue('resource_all_name'); - } - - /** - * Set the original name of the resource. This value is persisted using - * a hidden field. - * - * @param $name - */ - public function setOldName($name) - { - $this->oldName = $name; - } - - /** - * Get the resource name that was initially set. - */ - public function getOldName() - { - return $this->getValue('resource_all_name_old'); - } - - private function addDbForm() - { - $this->addElement( - 'select', - 'resource_db_db', - array( - 'label' => 'Database Type', - 'value' => $this->getResource()->get('db', 'mysql'), - 'required' => true, - 'helptext' => 'The type of SQL database you want to create.', - 'multiOptions' => array( - 'mysql' => 'MySQL', - 'pgsql' => 'PostgreSQL' - //'oracle' => 'Oracle' - ) - ) - ); - - $this->addElement( - 'text', - 'resource_db_host', - array ( - 'label' => 'Host', - 'value' => $this->getResource()->get('host', 'localhost'), - 'required' => true, - 'helptext' => 'The hostname of the database.' - ) - ); - - $this->addElement( - 'text', - 'resource_db_port', - array( - 'label' => 'Port', - 'value' => $this->getResource()->get('port', 3306), - 'required' => true, - 'validators' => array( - array('regex', false, '/^[0-9]+$/') - ), - 'helptext' => 'The port number to use.' - ) - ); - - $this->addElement( - 'text', - 'resource_db_dbname', - array( - 'label' => 'Database Name', - 'value' => $this->getResource()->get('dbname', ''), - 'required' => true, - 'helptext' => 'The name of the database to use' - ) - ); - - $this->addElement( - 'text', - 'resource_db_username', - array ( - 'label' => 'Username', - 'value' => $this->getResource()->get('username', ''), - 'required' => true, - 'helptext' => 'The user name to use for authentication.' - ) - ); - - $this->addElement( - 'password', - 'resource_db_password', - array( - 'label' => 'Password', - 'renderPassword' => true, - 'value' => $this->getResource()->get('password', ''), - 'helptext' => 'The password to use for authentication', - 'required' => true - ) - ); - } - - private function addStatusdatForm() - { - $this->addElement( - 'text', - 'resource_statusdat_status_file', - array( - 'label' => 'Status.dat File', - 'value' => $this->getResource()->get('status_file', '/usr/local/icinga/var/status.dat'), - 'required' => true, - 'helptext' => 'Location of your icinga status.dat file' - ) - ); - $this->addElement( - 'text', - 'resource_statusdat_object_file', - array( - 'label' => 'Objects.cache File', - 'value' => $this->getResource()->get('status_file', '/usr/local/icinga/var/objects.cache'), - 'required' => true, - 'helptext' => 'Location of your icinga objects.cache file' - ) - ); - } - - private function addLivestatusForm() - { - $this->addElement( - 'text', - 'resource_livestatus_socket', - array( - 'label' => 'Livestatus Socket Location', - 'required' => true, - 'helptext' => 'The path to your livestatus socket used for querying monitoring data', - 'value' => $this->getResource()->socket, - ) - ); - } - - private function addLdapForm() - { - $this->addElement( - 'text', - 'resource_ldap_hostname', - array( - 'label' => 'LDAP Server Host', - 'allowEmpty' => false, - 'value' => $this->getResource()->get('hostname', 'localhost'), - 'helptext' => 'The hostname or address of the LDAP server to use for authentication', - 'required' => true - ) - ); - - $this->addElement( - 'text', - 'resource_ldap_root_dn', - array( - 'label' => 'LDAP Root DN', - 'value' => $this->getResource()->get('root_dn', 'ou=people,dc=icinga,dc=org'), - 'helptext' => 'The path where users can be found on the ldap server', - 'required' => true - ) - ); - - $this->addElement( - 'text', - 'resource_ldap_bind_dn', - array( - 'label' => 'LDAP Bind DN', - 'value' => $this->getResource()->get('bind_dn', 'cn=admin,cn=config'), - 'helptext' => 'The user dn to use for querying the ldap server', - 'required' => true - ) - ); - - $this->addElement( - 'password', - 'resource_ldap_bind_pw', - array( - 'label' => 'LDAP Bind Password', - 'renderPassword' => true, - 'value' => $this->getResource()->get('bind_pw', ''), - 'helptext' => 'The password to use for querying the ldap server', - 'required' => true - ) - ); - } - - /** - * Set the resource configuration to edit. - * - * @param Zend_Config $resource - */ - public function setResource(Zend_Config $resource) - { - $this->resource = $resource; - } - - /** - * Get the current resource configuration. - * - * @return Zend_Config - */ - public function getResource() - { - if (!isset($this->resource)) { - // Init empty resource - $this->resource = new Zend_Config( - array('type' => 'db') - ); - } - return $this->resource; - } - - /** - * Add a field to change the resource name and one hidden field - * to save the previous resource name. - */ - private function addNameFields() - { - $this->addElement( - 'text', - 'resource_all_name', - array( - 'label' => 'Resource Name', - 'value' => $this->name, - 'helptext' => 'The unique name of this resource', - 'required' => true - ) - ); - $this->addElement( - 'hidden', - 'resource_all_name_old', - array( - 'value' => $this->oldName - ) - ); - } - - /** - * Add checkbox at the beginning of the form which allows to skip logic connection validation - */ - private function addForceCreationCheckbox() - { - $checkbox = new \Zend_Form_Element_Checkbox( - array( - 'name' => 'backend_force_creation', - 'label' => 'Force Changes', - 'helptext' => 'Check this box to enforce changes without connectivity validation', - 'order' => 0 - ) - ); - $checkbox->addDecorator(new HelpText()); - $this->addElement($checkbox); - } - - /** - * Add a select box for choosing the type to use for this backend - */ - private function addTypeSelectionBox() - { - $this->addElement( - 'select', - 'resource_type', - array( - 'label' => 'Resource Type', - 'value' => $this->getResource()->type, - 'required' => true, - 'helptext' => 'The type of resource.', - 'multiOptions' => array( - 'db' => 'SQL Database', - 'ldap' => 'Ldap', - 'statusdat' => 'Status.dat', - 'livestatus' => 'Livestatus' - ) - ) - ); - $this->enableAutoSubmit(array('resource_type')); - } - - /** - * Validate this form with the Zend validation mechanism and perform a validation of the connection. - * - * If validation fails, the 'backend_force_creation' checkbox is prepended to the form to allow users to - * skip the logic connection validation. - * - * @param array $data The form input to validate - * - * @return bool True when validation succeeded, false if not - */ - public function isValid($data) - { - if (!parent::isValid($data)) { - return false; - } - if ($this->getRequest()->getPost('backend_force_creation')) { - return true; - } - if (!$this->isValidResource()) { - $this->addForceCreationCheckbox(); - return false; - } - return true; - } - - /** - * Test if the changed resource is a valid resource, by instantiating it and - * checking if connection is possible. - * - * @return bool True when connection to the resource is possible. - */ - private function isValidResource() - { - try { - $config = $this->getConfig(); - switch ($config->type) { - case 'db': - $resource = ResourceFactory::createResource($config); - $resource->getConnection()->getConnection(); - break; - case 'statusdat': - if (!file_exists($config->object_file) || !file_exists($config->status_file)) { - $this->addErrorMessage( - 'Connectivity validation failed, the provided file or socket does not exist.' - ); - return false; - } - break; - case 'livestatus': - // TODO: Implement check - break; - case 'ldap': - $resource = ResourceFactory::createResource($config); - $resource->connect(); - break; - } - } catch (\Exception $exc) { - $this->addErrorMessage('Connectivity validation failed, connection to the given resource not possible.'); - return false; - } - return true; - } - - public function create() - { - $this->addNameFields(); - $this->addTypeSelectionBox(); - switch ($this->getRequest()->getParam('resource_type', $this->getResource()->type)) { - case 'db': - $this->addDbForm(); - break; - case 'statusdat': - $this->addStatusdatForm(); - break; - case 'livestatus': - $this->addLivestatusForm(); - break; - case 'ldap': - $this->addLdapForm(); - break; - } - $this->setSubmitLabel('{{SAVE_ICON}} Save Changes'); - } - - /** - * Return a configuration containing the backend settings entered in this form - * - * @return Zend_Config The updated configuration for this backend - */ - public function getConfig() - { - $values = $this->getValues(); - $type = $values['resource_type']; - $result = array('type' => $type); - foreach ($values as $key => $value) { - if ($key !== 'resource_type' && $key !== 'resource_all_name' && $key !== 'resource_all_name_old') { - $configKey = explode('_', $key, 3); - if (sizeof($configKey) < 3) { - Logger::warning('EditResourceForm: invalid form key "' . $key . '" was ignored.'); - continue; - } - $result[$configKey[2]] = $value; - } - } - return new Zend_Config($result); - } -} diff --git a/application/forms/Config/ResourceForm.php b/application/forms/Config/ResourceForm.php new file mode 100644 index 000000000..52650411f --- /dev/null +++ b/application/forms/Config/ResourceForm.php @@ -0,0 +1,531 @@ + + * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 + * @author Icinga Development Team + * + */ +// {{{ICINGA_LICENSE_HEADER}}} + +namespace Icinga\Form\Config; + +use Exception; +use Zend_Config; +use Zend_Form_Element_Checkbox; +use Icinga\Web\Form; +use Icinga\Data\ResourceFactory; +use Icinga\Web\Form\Element\Number; +use Icinga\Web\Form\Decorator\HelpText; + +class ResourceForm extends Form +{ + /** + * The resource + * + * @var Zend_Config + */ + protected $resource; + + /** + * The (new) name of the resource + * + * @var string + */ + protected $name; + + /** + * The old name of the resource + * + * @var string + */ + protected $oldName; + + /** + * Set the current resource name + * + * @param string $name The name to set + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * Get the current resource name + * + * @return null|string + */ + public function getName() + { + $name = $this->getValue('resource_all_name'); + if (!$name) { + return $this->name; + } + + return $name; + } + + /** + * Set the original name of the resource + * + * @param string $name The name to set + */ + public function setOldName($name) + { + $this->oldName = $name; + } + + /** + * Get the resource name that was initially set + * + * @return null|string + */ + public function getOldName() + { + $oldName = $this->getValue('resource_all_name_old'); + if (!$oldName) { + return $this->oldName; + } + + return $oldName; + } + + /** + * Set the resource configuration to edit. + * + * @param Zend_Config $resource The config to set + */ + public function setResource(Zend_Config $resource) + { + $this->resource = $resource; + } + + /** + * Get the current resource configuration. + * + * @return Zend_Config + */ + public function getResource() + { + if (!isset($this->resource)) { + $this->resource = new Zend_Config(array('type' => 'db')); + } + + return $this->resource; + } + + protected function addDbForm() + { + $this->addElement( + 'select', + 'resource_db_db', + array( + 'required' => true, + 'label' => t('Database Type'), + 'helptext' => t('The type of SQL database you want to create.'), + 'value' => $this->getResource()->get('db', 'mysql'), + 'multiOptions' => array( + 'mysql' => 'MySQL', + 'pgsql' => 'PostgreSQL' + //'oracle' => 'Oracle' + ) + ) + ); + + $this->addElement( + 'text', + 'resource_db_host', + array ( + 'required' => true, + 'label' => t('Host'), + 'helptext' => t('The hostname of the database.'), + 'value' => $this->getResource()->get('host', 'localhost') + ) + ); + + $this->addElement( + new Number( + array( + 'name' => 'resource_db_port', + 'required' => true, + 'label' => t('Port'), + 'helptext' => t('The port to use.'), + 'value' => $this->getResource()->get('port', 3306) + ) + ) + ); + + $this->addElement( + 'text', + 'resource_db_dbname', + array( + 'required' => true, + 'label' => t('Database Name'), + 'helptext' => t('The name of the database to use'), + 'value' => $this->getResource()->get('dbname', '') + ) + ); + + $this->addElement( + 'text', + 'resource_db_username', + array ( + 'required' => true, + 'label' => t('Username'), + 'helptext' => t('The user name to use for authentication.'), + 'value' => $this->getResource()->get('username', '') + ) + ); + + $this->addElement( + 'password', + 'resource_db_password', + array( + 'required' => true, + 'renderPassword' => true, + 'label' => t('Password'), + 'helptext' => t('The password to use for authentication'), + 'value' => $this->getResource()->get('password', '') + ) + ); + } + + protected function addStatusdatForm() + { + $this->addElement( + 'text', + 'resource_statusdat_status_file', + array( + 'required' => true, + 'label' => t('Filepath'), + 'helptext' => t('Location of your icinga status.dat file'), + 'value' => $this->getResource()->get('status_file', '/usr/local/icinga/var/status.dat') + ) + ); + + $this->addElement( + 'text', + 'resource_statusdat_object_file', + array( + 'required' => true, + 'label' => t('Filepath'), + 'helptext' => t('Location of your icinga objects.cache file'), + 'value' => $this->getResource()->get('status_file', '/usr/local/icinga/var/objects.cache') + ) + ); + } + + protected function addLivestatusForm() + { + $this->addElement( + 'text', + 'resource_livestatus_socket', + array( + 'required' => true, + 'label' => t('Socket'), + 'helptext' => t('The path to your livestatus socket used for querying monitoring data'), + 'value' => $this->getResource()->get('socket', '/usr/local/icinga/var/rw/livestatus') + ) + ); + } + + protected function addLdapForm() + { + $this->addElement( + 'text', + 'resource_ldap_hostname', + array( + 'required' => true, + 'allowEmpty' => false, + 'label' => t('Host'), + 'helptext' => t('The hostname or address of the LDAP server to use for authentication'), + 'value' => $this->getResource()->get('hostname', 'localhost') + ) + ); + + $this->addElement( + 'text', + 'resource_ldap_root_dn', + array( + 'required' => true, + 'label' => t('Root DN'), + 'helptext' => t('The path where users can be found on the ldap server'), + 'value' => $this->getResource()->get('root_dn', 'ou=people,dc=icinga,dc=org') + ) + ); + + $this->addElement( + 'text', + 'resource_ldap_bind_dn', + array( + 'required' => true, + 'label' => t('Bind DN'), + 'helptext' => t('The user dn to use for querying the ldap server'), + 'value' => $this->getResource()->get('bind_dn', 'cn=admin,cn=config') + ) + ); + + $this->addElement( + 'password', + 'resource_ldap_bind_pw', + array( + 'required' => true, + 'renderPassword' => true, + 'label' => t('Bind Password'), + 'helptext' => t('The password to use for querying the ldap server'), + 'value' => $this->getResource()->get('bind_pw', '') + ) + ); + } + + protected function addFileForm() + { + $this->addElement( + 'text', + 'resource_file_filename', + array( + 'required' => true, + 'label' => t('Filepath'), + 'helptext' => t('The filename to fetch information from'), + 'value' => $this->getResource()->get('filename', '') + ) + ); + + $this->addElement( + 'text', + 'resource_file_fields', + array( + 'required' => true, + 'label' => t('Pattern'), + 'helptext' => t('The regular expression by which to identify columns'), + 'value' => $this->getResource()->get('fields', '') + ) + ); + } + + protected function addNameFields() + { + $this->addElement( + 'text', + 'resource_all_name', + array( + 'required' => true, + 'label' => t('Resource Name'), + 'helptext' => t('The unique name of this resource'), + 'value' => $this->getName() + ) + ); + + $this->addElement( + 'hidden', + 'resource_all_name_old', + array( + 'value' => $this->getOldName() + ) + ); + } + + /** + * Add checkbox at the beginning of the form which allows to skip connection validation + */ + protected function addForceCreationCheckbox() + { + $checkbox = new Zend_Form_Element_Checkbox( + array( + 'order' => 0, + 'name' => 'resource_force_creation', + 'label' => t('Force Changes'), + 'helptext' => t('Check this box to enforce changes without connectivity validation') + ) + ); + $checkbox->addDecorator(new HelpText()); + $this->addElement($checkbox); + } + + /** + * Add a select box for choosing the type to use for this backend + */ + protected function addTypeSelectionBox() + { + $this->addElement( + 'select', + 'resource_type', + array( + 'required' => true, + 'label' => t('Resource Type'), + 'helptext' => t('The type of resource'), + 'value' => $this->getResource()->type, + 'multiOptions' => array( + 'db' => t('SQL Database'), + 'ldap' => 'LDAP', + 'statusdat' => 'Status.dat', + 'livestatus' => 'Livestatus', + 'file' => t('File') + ) + ) + ); + $this->enableAutoSubmit(array('resource_type')); + } + + /** + * Validate this form with the Zend validation mechanism and perform a validation of the connection + * + * If validation fails, the 'resource_force_creation' checkbox is prepended to the form to allow users to + * skip the connection validation + * + * @param array $data The form input to validate + * + * @return bool True when validation succeeded, false if not + */ + public function isValid($data) + { + if (!parent::isValid($data)) { + return false; + } + if (isset($data['resource_force_creation']) && $data['resource_force_creation']) { + return true; + } + if (!$this->isValidResource()) { + $this->addForceCreationCheckbox(); + return false; + } + return true; + } + + /** + * Test if the changed resource is a valid resource, by instantiating it and + * checking if a connection is possible + * + * @return bool True when a connection to the resource is possible + */ + public function isValidResource() + { + $config = $this->getConfig(); + + try { + switch ($config->type) { + case 'db': + /* + * It should be possible to run icingaweb without the pgsql or mysql extension or Zend-Pdo-Classes, + * in case they aren't actually used. When the user tries to create a resource that depends on an + * uninstalled extension, an error should be displayed. + */ + if ($config->db === 'mysql' && !ResourceFactory::mysqlAvailable()) { + $this->addErrorMessage( + t('You need to install the php extension "mysql" and the ' . + 'Zend_Pdo_Mysql classes to use MySQL database resources.') + ); + return false; + } + if ($config->db === 'pgsql' && !ResourceFactory::pgsqlAvailable()) { + $this->addErrorMessage( + t('You need to install the php extension "pgsql" and the ' . + 'Zend_Pdo_Pgsql classes to use PostgreSQL database resources.') + ); + return false; + } + + $resource = ResourceFactory::createResource($config); + $resource->getConnection()->getConnection(); + break; + case 'statusdat': + if (!file_exists($config->object_file) || !file_exists($config->status_file)) { + $this->addErrorMessage( + t('Connectivity validation failed, the provided file does not exist.') + ); + return false; + } + break; + case 'livestatus': + $resource = ResourceFactory::createResource($config); + $resource->connect()->disconnect(); + break; + case 'ldap': + $resource = ResourceFactory::createResource($config); + $resource->connect(); + break; + case 'file': + if (!file_exists($config->filename)) { + $this->addErrorMessage( + t('Connectivity validation failed, the provided file does not exist.') + ); + return false; + } + break; + } + } catch (Exception $e) { + $this->addErrorMessage(t('Connectivity validation failed, connection to the given resource not possible.')); + return false; + } + + return true; + } + + public function create() + { + $this->addNameFields(); + $this->addTypeSelectionBox(); + + switch ($this->getRequest()->getParam('resource_type', $this->getResource()->type)) { + case 'db': + $this->addDbForm(); + break; + case 'statusdat': + $this->addStatusdatForm(); + break; + case 'livestatus': + $this->addLivestatusForm(); + break; + case 'ldap': + $this->addLdapForm(); + break; + case 'file': + $this->addFileForm(); + break; + } + + $this->setSubmitLabel('{{SAVE_ICON}} Save Changes'); + } + + /** + * Return a configuration containing the backend settings entered in this form + * + * @return Zend_Config The updated configuration for this backend + */ + public function getConfig() + { + $values = $this->getValues(); + + $result = array('type' => $values['resource_type']); + foreach ($values as $key => $value) { + if ($key !== 'resource_type' && $key !== 'resource_all_name' && $key !== 'resource_all_name_old') { + $configKey = explode('_', $key, 3); + if (count($configKey) === 3) { + $result[$configKey[2]] = $value; + } + } + } + + return new Zend_Config($result); + } +} diff --git a/application/forms/Dashboard/AddUrlForm.php b/application/forms/Dashboard/AddUrlForm.php index 7f6a0c80b..8a914f868 100644 --- a/application/forms/Dashboard/AddUrlForm.php +++ b/application/forms/Dashboard/AddUrlForm.php @@ -1,4 +1,5 @@ 'Url', 'required' => true, - 'value' => $this->getRequest()->getParam('url', null) + 'value' => htmlspecialchars_decode($this->getRequest()->getParam('url', '')) ) ); $elems = $dashboard->getPaneKeyTitleArray(); @@ -167,6 +163,6 @@ class AddUrlForm extends Form ) ); $this->setSubmitLabel("Add To Dashboard"); - } } +// @codeCoverageIgnoreEnd diff --git a/application/forms/Preference/GeneralForm.php b/application/forms/Preference/GeneralForm.php index ca2b6699f..512b54689 100644 --- a/application/forms/Preference/GeneralForm.php +++ b/application/forms/Preference/GeneralForm.php @@ -1,4 +1,5 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Icinga\Form; - -class TestForm -{ -} diff --git a/application/views/helpers/DateFormat.php b/application/views/helpers/DateFormat.php index 76408de6b..80c6bc50a 100644 --- a/application/views/helpers/DateFormat.php +++ b/application/views/helpers/DateFormat.php @@ -1,6 +1,4 @@ format($format); } @@ -96,6 +96,7 @@ class Zend_View_Helper_DateFormat extends Zend_View_Helper_Abstract * Format date according to user's format * * @param int $timestamp A unix timestamp + * * @return string The formatted date string */ public function formatDate($timestamp) @@ -107,6 +108,7 @@ class Zend_View_Helper_DateFormat extends Zend_View_Helper_Abstract * Format time according to user's format * * @param int $timestamp A unix timestamp + * * @return string The formatted time string */ public function formatTime($timestamp) @@ -133,7 +135,8 @@ class Zend_View_Helper_DateFormat extends Zend_View_Helper_Abstract public function getDateFormat() { return $this->request->getUser()->getPreferences()->get( - 'app.dateFormat', Config::app()->global !== null ? Config::app()->global->get('dateFormat', 'd/m/Y') : 'd/m/Y' + 'app.dateFormat', + Config::app()->global !== null ? Config::app()->global->get('dateFormat', 'd/m/Y') : 'd/m/Y' ); } @@ -145,7 +148,8 @@ class Zend_View_Helper_DateFormat extends Zend_View_Helper_Abstract public function getTimeFormat() { return $this->request->getUser()->getPreferences()->get( - 'app.timeFormat', Config::app()->global !== null ? Config::app()->global->get('timeFormat', 'g:i A') : 'g:i A' + 'app.timeFormat', + Config::app()->global !== null ? Config::app()->global->get('timeFormat', 'g:i A') : 'g:i A' ); } @@ -159,5 +163,3 @@ class Zend_View_Helper_DateFormat extends Zend_View_Helper_Abstract return $this->getDateFormat() . ' ' . $this->getTimeFormat(); } } - -// @codingStandardsIgnoreStop diff --git a/application/views/helpers/FormDateTime.php b/application/views/helpers/FormDateTime.php index d810de288..95f5019d7 100644 --- a/application/views/helpers/FormDateTime.php +++ b/application/views/helpers/FormDateTime.php @@ -1,6 +1,5 @@ getClosingBracket(); } } - -// @codingStandardsIgnoreStop +// @codeCoverageIgnoreEnd diff --git a/application/views/helpers/FormTriStateCheckbox.php b/application/views/helpers/FormTriStateCheckbox.php index 5e01ac557..5db0532fc 100644 --- a/application/views/helpers/FormTriStateCheckbox.php +++ b/application/views/helpers/FormTriStateCheckbox.php @@ -1,6 +1,5 @@ ' - . '
' . ($value == 1 ? '{{ICON_ENABLED}}' : ($value === 'unchanged' ? '{{ICON_MIXED}}' : '{{ICON_DISABLED}}' )) . '
' - . 'On ' - . 'Off '; + $xhtml = '
' + . '
' . ($value == 1 ? ' ' : ($value === 'unchanged' ? ' ' : ' ' )) . '
' + + . 'On ' + + . 'Off '; if ($value === 'unchanged') { $xhtml = $xhtml . ' Mixed '; + . $name . '" ' . 'checked "> Undefined '; }; return $xhtml . '
'; } } +// @codeCoverageIgnoreEnd diff --git a/bin/icingacli b/bin/icingacli index a026ea570..1a0781222 100755 --- a/bin/icingacli +++ b/bin/icingacli @@ -3,4 +3,4 @@ use Icinga\Application\Cli; require_once dirname(__DIR__) . '/library/Icinga/Application/Cli.php'; -Cli::start('@icingaweb_config_path@')->dispatch(); +Cli::start()->dispatch(); diff --git a/config/config.ini.in b/config/config.ini.in index 4d12e67cb..c8724ad77 100644 --- a/config/config.ini.in +++ b/config/config.ini.in @@ -16,7 +16,7 @@ timeFormat = "g:i A" authenticationMode = "internal" [logging] -;enable = false +enable = true ; Writing to a Stream type = "stream" ; Write data to the following file diff --git a/config/resources.ini.in b/config/resources.ini.in index c5eafeb55..d4c617c51 100644 --- a/config/resources.ini.in +++ b/config/resources.ini.in @@ -49,7 +49,7 @@ bind_dn = "@ldap_binddn@" bind_pw = @ldap_bindpass@ [logfile] -type = file -filename = "/vagrant/var/log/icingaweb.log" -fields = "/^(?[0-9]{4}(-[0-9]{2}){2}T[0-9]{2}(:[0-9]{2}){2}(\\+[0-9]{2}:[0-9]{2})?) (?[A-Za-z]+)( \([0-9]+\))?: (?.*)$/" +type = file +filename = "@icingaweb_log_path@/icingaweb.log" +fields = "/^(?[0-9]{4}(-[0-9]{2}){2}T[0-9]{2}(:[0-9]{2}){2}(\\+[0-9]{2}:[0-9]{2})?) - (?[A-Za-z]+) - (?.*)$/" ; format: PCRE diff --git a/doc/test/frontend_tests.md b/doc/test/frontend_tests.md deleted file mode 100644 index 073dd8c9d..000000000 --- a/doc/test/frontend_tests.md +++ /dev/null @@ -1,78 +0,0 @@ -# Frontend component tests - -Frontend tests test your code from the users perspective: By opening a specific url, executing a few clicks, strokes, etc. -and expecting something to happen. We use [CasperJS](http://casperjs.org/) for frontend testing, which is basically a -headless Webkit browser. - -**NOTE**: The 1.1.0DEV version does *NOT* work at this time as the api changed. Use the stable 1.0.3 branch instead. - -In order to be able to run the frontend tests, you need a running instance of icingaweb. You should make sure that you -don't need this instance after running the tests, as they could change preferences or configuration - -## Writing tests - - -### Test bootstrap - icingawebtest.js module - -The icingawebtest.js module is required for proper testing, as this module eases casperjs usage. After importing the -module with: - - var icingawebtest = require('./icingawebtest'); - -You only need two methods for testing: - -* *getTestEnv()*: This method returns a modified casperjs test environment. The difference to then normal casperjs object - is that all methods which take a URL are overloaded so you can add a relative URL if you want to (and - normally you don't want to hardcode your test URLs) - Example: - - var casper = icingawebtest.getTestEnv(); - -* performLogin(): This calls the login page of your icingaweb instance and tries to login with the supplied credentials - - icinga.performLogin(); - - -Login is performed with the credentials from the CASPERJS_USER/CASPERJS_PASS environment (this can be set with the -./runtest --user %user% --pass %pass% arguments). The host, server and port are also represented as -CASPERJS_HOST, CASPERJS_PORT and CASPERJS_PATH environment settings. The default in runtest resembles the version that -works best in the vagrant development environment: - -* The default user is 'jdoe' -* The default password is 'password' -* The host and port are localhost:80 -* The default path is icinga2-web - -### Writing the test code - -Most tests will require you to login with the supplied credentials, this can be performed with a simple call - - icinga.performLogin(); - -You can then start the test by calling casper.thenOpen with the page you want to work - - casper.thenOpen("/mysite", function() { - // perform tests - }); - -### Testing - -Afterwards, everything is like a normal CasperJS test, so you can wrap your assertions in a casper.then method: - - // assert a specific title - casper.then(function() { - this.test.assertTitle("Just an empty page"); - }); - -Note that asynchronous calls reuqire you to wait or provide a callback until the resource is loaded: - - // waitForSelector calls callbackFn as soon as the selector returns a non-empty set - casper.waitForSelector("div#icinga-main a", callbackFn); - -At the end of your test, you have to provide - - casper.run(function() { - this.test.done(); - }); - -Otherwise the tests won't be executed. diff --git a/doc/test/js_tests.md b/doc/test/js_tests.md deleted file mode 100644 index aa08fb646..000000000 --- a/doc/test/js_tests.md +++ /dev/null @@ -1,88 +0,0 @@ -# Writing JavaScipt tests - -JavaScript tests are executed using [mocha](http://visionmedia.github.io/mocha/) as a test framework and -[should.js](https://github.com/visionmedia/should.js/) as the assertion framework. - -## Mocking require.js - -As we use require.js for asynchronous dependency resolution in JavaScript, this can lead to problems in our node.js -environment. In order to avoid requirejs calls to cause issues, it has been mocked in the testlib/asyncmock.js class -and should be required in every testcase: - - var rjsmock = require("requiremock.js"); - -rjsmock now makes dependency management comfortable and provides the following most important methods: - - // remove all registered dependencies from the rjsmock cache - rjsmock.purgeDependencies(); - - // register the following objects underneath the following requirejs paths: - rjsmock.registerDependencies({ - 'icinga/container' : { - updateContainer : function() {}, - createPopupContainer: function() {} - } - }); - // in your js code a require(['icinga/container], function(container) {}) would now have the above mock - // object in the container variable - - requireNew("icinga/util/async.js"); // requires icinga/util/async.js file - and ignores the requirejs cache - var async = rjsmock.getDefine(); // returns the last define, this way you can retrieve a specific javacript file - -## Faking async responses - -As we currently use the icinga/util/async.js class for all asynchronous requests, it's easy to fake responses. The asyncmock.js -class provides functions for this. To use it in your test, you first have to require it: - - var asyncMock = require("asyncmock.js"); - -You now can use asyncMock.setNextAsyncResult((async) asyncManager, (string) resultString, (bool) fails, (object) headers) to -let the next request of the passed asyncManager object return resultString as the response, with the headers provided as the -last parameter. If fails = true, the error callback of the request will be called. - - -## Example test - -The following example describes a complete test, (which tests whether the registerHeaderListener method in the async class works) : - - var should = require("should"); // require should.js for assertions - var rjsmock = require("requiremock.js"); // use the requiremock described above - var asyncMock = require("asyncmock.js"); // Helper class to fake async requests - - GLOBAL.document = $('body'); // needed when our test accesses window.document - - - describe('The async module', function() { // start the test scenario - it("Allows to react on specific headers", function(done) { // Start a test case - when done is called it is finished - rjsmock.purgeDependencies(); // Remove any dependency previously declared - rjsmock.registerDependencies({ // Mock icinga/container, as this is a dependency for the following include - 'icinga/container' : { - updateContainer : function() {}, - createPopupContainer: function() {} - } - }); - - requireNew("icinga/util/async.js"); // This is the file we want to test, load it and all of it's dependencies - var async = rjsmock.getDefine(); // Retrieve a reference to the loaded file - - // Use asyncMock.setNextAsyncResult to let the next async request return 'result' without failing and set - // the response headers 'X-Dont-Care' and 'X-Test-Header' - asyncMock.setNextAsyncResult(async, "result", false, { - 'X-Dont-Care' : 'Ignore-me', - 'X-Test-Header' : 'Testme123' - }); - - // register a listener for results with the X-Test-Header response - async.registerHeaderListener("X-Test-Header", function(value, header) { - // test for the correct header - should.equal("Testme123", value); - // call done to mark this test as succeeded - done(); - },this); - // run the faked request - var test = async.createRequest(); - }); - - }); - - diff --git a/doc/test/php_tests.md b/doc/test/php_tests.md index d010cadcb..b0ab668a6 100644 --- a/doc/test/php_tests.md +++ b/doc/test/php_tests.md @@ -4,7 +4,7 @@ The path where you should put your PHPUnit tests should reflect the path in the sourcetree, with test/php/ prepended. So if you're testing a file library/Icinga/My/File.php the test file should be at test/php/library/Icinga/My/File.php. This -also applies for modules, where the test folder is underneath modules/myModule/test/php +also applies for modules, where the tests are underneath modules/myModule/test/php ## Example test skeleton @@ -12,13 +12,8 @@ Let's assume you're testing a class MyClass underneath the MyModule module and t modules/mymodule/library/MyModule/Helper/MyClass.php. openingHours = CheesecakeFactory::getOpeningHours(); + } + + protected function tearDown() + { + parent::tearDown(); + CheesecakeFactory::setOpeningHours($this->openingHours); + } + public function testThatInteractsWithStaticAttributes() { CheesecakeFactory::setOpeningHours(24); @@ -59,79 +59,7 @@ should **document** that the test interacts with static attributes: } } -## Requirements and the dependency mess - -### spl_autoload_register vs. require - -When looking at our test classes, you'll notice that we don't use PHPs autoloader to automatically load dependency, but -write 'require_once' by ourselfs. This has the following reasons: - -- When writing tests, you to be aware of every dependency your testclass includes. With autoloading, it's not directly - obvious which classes are included during runtime. -- When mocking classes, you don't need to tell your autoloader to use this class instead of the one used in production -- Tests can't be run isolated without an boostrap class initializing the autoloader - -### How to avoid require_once massacres: LibraryLoader - -The downside of this approach is obvious: Especially when writing compoment tests you end up writing a lot of 'require' -classes. In the worst case, the PHP require_once method doesn't recognize a path to be already included and ends up -with an 'Cannot redeclare class XY' issue. - -To avoid this, you should implement a LibraryLoader class for your component that handles the require_once calls. -For example, the status.dat component tests has a TestLoader class that includes all dependencies of the component: - - - namespace Tests\Icinga\Protocol\Statusdat; - use Test\Icinga\LibraryLoader; - - require_once('library/Icinga/LibraryLoader.php'); - - /** - * Load all required libraries to use the statusdat - * component in integration tests - * - **/ - class StatusdatTestLoader extends LibraryLoader - { - /** - * @see LibraryLoader::requireLibrary - * - **/ - public static function requireLibrary() - { - // include Zend requirements - require_once 'Zend/Config.php'; - require_once 'Zend/Cache.php'; - require_once 'Zend/Log.php'; - - // retrieve the path to the icinga library - $libPath = self::getLibraryPath(); - - // require library dependencies - require_once($libPath."/Data/AbstractQuery.php"); - require_once($libPath."/Application/Logger.php"); - require_once($libPath."/Data/DatasourceInterface.php"); - - // shorthand for the folder where the statusdat component can be found - $statusdat = realpath($libPath."/Protocol/Statusdat/"); - require_once($statusdat."/View/AccessorStrategy.php"); - // ... a few more requires ... - require_once($statusdat."/Query/Group.php"); - } - } - -Now an component test (like tests/php/library/Icinga/Protocol/Statusdat/ReaderTest.php) can avoid the require calls and -just use the requireLibrary method: - - use Icinga\Protocol\Statusdat\Reader as Reader; - - // Load library at once - require_once("StatusdatTestLoader.php"); - StatusdatTestLoader::requireLibrary(); - -**Note**: This should be used for component tests, where you want to test the combination of your classes. When testing - a single execution unit, like a method, it's often better to explicitly write your dependencies. - -If you compare the first approach with the last one you will notice that, even if we produced more code in the end, our -test is more verbose in what it is doing. When someone is updating your test, he should easily see what tests are existing -and what scenarios are missing. +The reason to avoid using @backupStaticAttributes is the fact that if it is necessary to utilize a +singleton in your *unit* tests you probably want to rethink what you are going to test and because +some tests are using the mock framework [`Mockery`](https://github.com/padraic/mockery) which is +using static class properties to implement its caching mechanics. diff --git a/doc/test/running_tests.md b/doc/test/running_tests.md index d34397e27..116911057 100644 --- a/doc/test/running_tests.md +++ b/doc/test/running_tests.md @@ -6,11 +6,10 @@ Tests for the application can be found underneath the test folder: test/ php/ PHPUnit tests for backend code - js/ mocha tests for JavaScript frontend code unittests - frontend/ Integration tests for the frontend using casperjs + regression/ PHPUnit regression tests The same structure applies for modules, which also contain a toplevel test folder and suitable subtests. When you fix -a bug and write a regression test for it, put the test in the 'regression' and name it %DESCRIPTION%%TicketNumber% (myBug1234.js) +a bug and write a regression test for it, put it in 'regression' and name it %DESCRIPTION%%TicketNumber% (myBug1234.php) ## Running tests diff --git a/doc/test/styleguide.md b/doc/test/styleguide.md index 9f0bd62e9..4186b3375 100644 --- a/doc/test/styleguide.md +++ b/doc/test/styleguide.md @@ -18,11 +18,8 @@ This list summarizes what will be described in the next few chapters: - Your assertions should reflect one test scenario, i.e. don't write one test method that tests if something works **and** if it correctly detects errors after it works. Write one test to determine the behaviour with correct input and one that tests the behaviour with invalid input. -- When writing unit-tests (like function level tests), try to keep your dependencies as low as possible (best indicator herefor - is the number of require calls in your test). Mock external components and inject them into the class you want to test. If - your testsubject is not able to use mocked dependencies, it's often a design flaw and should be considered as a bug - (and be fixed) -- When writing component tests with a lot of dependencies, wrap the require calls in a LibraryLoader subclass +- Mock external components and inject them into the class you want to test. If your testsubject is not able to use mocked + dependencies, it's often a design flaw and should be considered as a bug (and be fixed) ## What should be tested @@ -163,12 +160,6 @@ need much dependency handling. An example for a unittest would be to test the fo A unit test for this user could, but should not look like this (we'll explain why): - require_once "../../library/Icinga/MyLibrary/UserManager.php"; - // needed by UserManager - require_once "../../library/Icinga/Authentication/Manager.php" - require_once "../../library/Icinga/Authentication/User.php" - // .. imagine a few more require_once - use Icinga/MyLibrary/UserManager class UserManagerTest extends \PHPUnit_Framework_TestCase @@ -196,7 +187,7 @@ A unit test for this user could, but should not look like this (we'll explain wh $this->assertTrue($mgr->isCorrectPassword("hans", "validpasswor")); } -This test has obviously a few issues: +This test has a few issues: - First, it assert a precondition to apply : A database must exist with the users jdoe and jsmith and the credentials must match the ones provided in the test @@ -238,7 +229,6 @@ It would of course be best to create an Interface like UserSource which the Auth we trust our Programmer to provide a suitable object. We now can eliminate all the AuthManager dependencies by mocking the AuthManager (lets dumb it down to just providing an array of users): - require_once "../../library/Icinga/MyLibrary/UserManager.php"; use Icinga/MyLibrary/UserManager class AuthManagerMock @@ -286,7 +276,6 @@ AuthManager (lets dumb it down to just providing an array of users): Ok, we might have more code here than before, but our test is now less like prone to fail: - Our test doesn't assume any preconditions to apply, like having a db server with correct users -- The require call to the AuthManager is gone, so if there's a bug in the AuthManager implementation our test is not affected @@ -368,84 +357,3 @@ Also, the assertions should get an error message that will be printed on failure Now if something fails, we now see what has been tested via the testmethod and what caused the test to fail in the assertion error message. You could also leave the comments and everybody knows what you are doing. - -## Testing PHP - - -## Requirements and the dependency mess - -### spl_autoload_register vs. require - -When looking at our test classes, you'll notice that we don't use PHPs autoloader to automatically load dependency, but -write 'require_once' by ourselfs. This has the following reasons: - -- When writing tests, you to be aware of every dependency your testclass includes. With autoloading, it's not directly - obvious which classes are included during runtime. -- When mocking classes, you don't need to tell your autoloader to use this class instead of the one used in production -- Tests can't be run isolated without an boostrap class initializing the autoloader - -### How to avoid require_once massacres: LibraryLoader - -The downside of this approach is obvious: Especially when writing compoment tests you end up writing a lot of 'require' -classes. In the worst case, the PHP require_once method doesn't recognize a path to be already included and ends up -with an 'Cannot redeclare class XY' issue. - -To avoid this, you should implement a LibraryLoader class for your component that handles the require_once calls. -For example, the status.dat component tests has a TestLoader class that includes all dependencies of the component: - - - namespace Tests\Icinga\Protocol\Statusdat; - use Test\Icinga\LibraryLoader; - - require_once('library/Icinga/LibraryLoader.php'); - - /** - * Load all required libraries to use the statusdat - * component in integration tests - * - **/ - class StatusdatTestLoader extends LibraryLoader - { - /** - * @see LibraryLoader::requireLibrary - * - **/ - public static function requireLibrary() - { - // include Zend requirements - require_once 'Zend/Config.php'; - require_once 'Zend/Cache.php'; - require_once 'Zend/Log.php'; - - // retrieve the path to the icinga library - $libPath = self::getLibraryPath(); - - // require library dependencies - require_once($libPath."/Data/AbstractQuery.php"); - require_once($libPath."/Application/Logger.php"); - require_once($libPath."/Data/DatasourceInterface.php"); - - // shorthand for the folder where the statusdat component can be found - $statusdat = realpath($libPath."/Protocol/Statusdat/"); - require_once($statusdat."/View/AccessorStrategy.php"); - // ... a few more requires ... - require_once($statusdat."/Query/Group.php"); - } - } - -Now an component test (like tests/php/library/Icinga/Protocol/Statusdat/ReaderTest.php) can avoid the require calls and -just use the requireLibrary method: - - use Icinga\Protocol\Statusdat\Reader as Reader; - - // Load library at once - require_once("StatusdatTestLoader.php"); - StatusdatTestLoader::requireLibrary(); - -**Note**: This should be used for component tests, where you want to test the combination of your classes. When testing - a single execution unit, like a method, it's often better to explicitly write your dependencies. - -If you compare the first approach with the last one you will notice that, even if we produced more code in the end, our -test is more verbose in what it is doing. When someone is updating your test, he should easily see what tests are existing -and what scenarios are missing. - diff --git a/doc/testing.md b/doc/testing.md index 724788563..0c0616d59 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -50,29 +50,14 @@ password is queried when connecting from the local machine: Icinga has it's own base test which lets you easily require libraries, testing database and form functionality. The class resides in library/Icinga/Test. If you write a test, just subclass BaseTestCase. -### Default test header - -Before writing a test you should include the base test first - - // @codingStandardsIgnoreStart - require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); - // @codingStandardsIgnoreEnd - -Now you can simply include dependencies with predefined properties: - - require_once BaseTestCase::$libDir . '/Web/Form.php'; - require_once BaseTestCase::$appDir . '/forms/Config/AuthenticationForm.php'; - -BaseTestCase provides static variables for every directory in the project. - ### Writing database tests -The base test uses the PHPUnit dataProvider annotation system to create Zend Database Adapters. Typically a +The base test uses the PHPUnit dataProvider annotation system to create database connections. Typically a database test looks like this: /** * @dataProvider mysqlDb - * @param Zend_Db_Adapter_PDO_Abstract $mysqlDb + * @param Icinga\Data\Db\Connection $mysqlDb */ public function testSomethingWithMySql($mysqlDb) { @@ -106,58 +91,3 @@ BaseTestCase holds method to require form libraries and create form classes base The second parameter of createForm() can be omitted. You can set initial post request data as an array if needed. - -## Writing tests for controllers - -When writing tests for controllers, you can subclass the MonitoringControllerTest class underneath monitoring/test/php/testlib: - - class MyTestclass extends MonitoringControllerTest - { - // test stuff - } - -This class handles a lot of depenendency resolving and controller mocking. In order to test your action correctly and -without side effects, the TestFixture class allows your to define and set up your faked monitoring results in the backend -you want to test: - - use Test\Monitoring\Testlib\Datasource\TestFixture; - - class MyTestclass extends MonitoringControllerTest - { - public function testSomething() - { - $fixture = new TestFixture(); - // adding a new critical, but acknowledged host - $fixture->addHost("hostname", 1, ObjectFlags::ACKNOWLEDGED()) - - // add a comment to the host (this has to be done before adding services) - ->addComment("author", "comment text") - - // assign to hostgroup - ->addToHostgroup("myHosts") - - // and add three services to this host - ->addService("svc1", 0) // Service is ok - ->addService("svc2", 1, ObjectFlags::PASSIVE) // service is warning and passive - ->addService("svc3", 2, null, array("notes_url" => "test.html")) // critical with notes url - ->addComment("author", "what a nice service comment") // add a comment to the service - ->addToServicegroup("alwaysdown"); // add svc3 to servicegroup - - // Create the datasource from this fixture, here in MySQL - $this->setupFixture($fixture, "mysql"); - - // ... do the actual testing (discussed now) - } - } - -After the call to setupFixture() your backend should be ready to be tested. Setting up the controller manually would -force you to go through the whole bootstrap. To avoid this the MonitoringControllerTest class provides a 'requireController' -method which returns the Controller for you with an already set up backend using your previously defined testdata: - - $controller = $this->requireController('MyController', 'mysql'); - // controller is now the Zend controller instance, perform an action - $controller->myAction(); - $result = $controller->view->hosts->fetchAll(); - -This example assumes that the controller populates the 'host' variable in the view, so now you can assert the state of -the result according to your test plan. \ No newline at end of file diff --git a/etc/module_skeleton/application/controllers/IndexController.php b/etc/module_skeleton/application/controllers/IndexController.php deleted file mode 100644 index 275a048e7..000000000 --- a/etc/module_skeleton/application/controllers/IndexController.php +++ /dev/null @@ -1,11 +0,0 @@ -libDir = realpath(__DIR__ . '/../..'); @@ -139,13 +140,23 @@ abstract class ApplicationBootstrap define('ICINGA_APPDIR', $this->appDir); } + if ($configDir === null) { + if (array_key_exists('ICINGAWEB_CONFIGDIR', $_SERVER)) { + $configDir = $_SERVER['ICINGAWEB_CONFIGDIR']; + } else if (array_key_exists('ICINGAWEB_CONFIGDIR', $_ENV)) { + $configDir = $_ENV['ICINGAWEB_CONFIGDIR']; + } else { + $configDir = '/etc/icingaweb'; + } + } + $this->configDir = realpath($configDir); + $this->setupAutoloader(); $this->setupZendAutoloader(); Benchmark::measure('Bootstrap, autoloader registered'); Icinga::setApp($this); - $this->configDir = realpath($configDir); require_once dirname(__FILE__) . '/functions.php'; } @@ -269,7 +280,7 @@ abstract class ApplicationBootstrap * * @return ApplicationBootstrap */ - public static function start($configDir) + public static function start($configDir = null) { $application = new static($configDir); $application->bootstrap(); @@ -364,7 +375,7 @@ abstract class ApplicationBootstrap 'level' => Logger::$ERROR, 'type' => 'syslog', 'facility' => 'LOG_USER', - 'application' => 'Icinga Web' + 'application' => 'icingaweb' ) ) ); @@ -446,13 +457,8 @@ abstract class ApplicationBootstrap protected function setupTimezone() { $timeZoneString = $this->config->global !== null ? $this->config->global->get('timezone', 'UTC') : 'UTC'; - try { - $tz = new DateTimeZone($timeZoneString); - } catch (Exception $e) { - throw new ConfigurationError(t('Invalid timezone') . ' "' . $timeZoneString . '"'); - } date_default_timezone_set($timeZoneString); - DateTimeFactory::setConfig(array('timezone' => $tz)); + DateTimeFactory::setConfig(array('timezone' => $timeZoneString)); return $this; } @@ -482,3 +488,4 @@ abstract class ApplicationBootstrap return $this; } } +// @codeCoverageIgnoreEnd diff --git a/library/Icinga/Application/Benchmark.php b/library/Icinga/Application/Benchmark.php index fbe967391..65bb37d37 100644 --- a/library/Icinga/Application/Benchmark.php +++ b/library/Icinga/Application/Benchmark.php @@ -1,4 +1,5 @@ setupTimezone() ->setupInternationalization() ->parseBasicParams() - ->fixLoggingConfig() ->setupLogger() ->setupResourceFactory() ->setupModuleManager(); } - protected function fixLoggingConfig() + protected function setupLogging() { - $conf = $this->config->logging; - if (! isset($conf->type) || $conf->type === 'stream') { - $conf->level = $this->verbose; - $conf->target = 'php://stderr'; - } + Logger::create( + new Zend_Config( + array( + 'enable' => true, + 'level' => Logger::$INFO, + 'type' => 'file', + 'target' => 'php://stderr' + ) + ) + ); return $this; } @@ -177,3 +184,4 @@ class Cli extends ApplicationBootstrap throw new ProgrammingError('Icinga is not running on CLI'); } } +// @codeCoverageIgnoreEnd diff --git a/library/Icinga/Application/EmbeddedWeb.php b/library/Icinga/Application/EmbeddedWeb.php index 31852bafb..e3f966ed8 100644 --- a/library/Icinga/Application/EmbeddedWeb.php +++ b/library/Icinga/Application/EmbeddedWeb.php @@ -1,4 +1,5 @@ loadEnabledModules(); } } +// @codeCoverageIgnoreEnd diff --git a/library/Icinga/Application/Icinga.php b/library/Icinga/Application/Icinga.php index b6422e092..a3a0d3b96 100644 --- a/library/Icinga/Application/Icinga.php +++ b/library/Icinga/Application/Icinga.php @@ -59,12 +59,14 @@ class Icinga /** * Setter for an application environment * - * @param ApplicationBootstrap $app + * @param ApplicationBootstrap $app + * @param bool $overwrite + * * @throws ProgrammingError */ - public static function setApp(ApplicationBootstrap $app) + public static function setApp(ApplicationBootstrap $app, $overwrite = false) { - if (self::$app !== null) { + if (self::$app !== null && !$overwrite) { throw new ProgrammingError('Cannot start Icinga twice'); } diff --git a/library/Icinga/Application/LegacyWeb.php b/library/Icinga/Application/LegacyWeb.php index bf1ff3a45..acce4ad47 100644 --- a/library/Icinga/Application/LegacyWeb.php +++ b/library/Icinga/Application/LegacyWeb.php @@ -1,4 +1,5 @@ legacyBasedir; } } +// @codeCoverageIgnoreEnd diff --git a/library/Icinga/Application/Loader.php b/library/Icinga/Application/Loader.php index a74b0548d..9cb74a167 100644 --- a/library/Icinga/Application/Loader.php +++ b/library/Icinga/Application/Loader.php @@ -1,30 +1,5 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} namespace Icinga\Application; @@ -40,6 +15,7 @@ class Loader /** * List of namespaces + * * @var array */ private $namespaces = array(); @@ -54,14 +30,16 @@ class Loader /** * Register new namespace for directory - * @param string $namespace - * @param string $directory - * @throws \Icinga\Exception\ProgrammingError + * + * @param string $namespace + * @param string $directory + * + * @throws ProgrammingError */ public function registerNamespace($namespace, $directory) { if (!is_dir($directory)) { - throw new ProgrammingError('Directory does not exist: '. $directory); + throw new ProgrammingError('Directory does not exist: ' . $directory); } $this->namespaces[$namespace] = $directory; @@ -69,8 +47,10 @@ class Loader /** * Test if a namespace exists - * @param string $namespace - * @return bool + * + * @param string $namespace + * + * @return bool */ public function hasNamespace($namespace) { @@ -80,19 +60,19 @@ class Loader /** * Class loader * - * Ignores all but classes in the Icinga namespace. + * Ignores all but classes in registered namespaces. * - * @param string $class - * @return boolean + * @param string $class + * + * @return boolean */ public function loadClass($class) { $namespace = $this->getNamespaceForClass($class); if ($namespace) { - $file = $this->namespaces[$namespace]. preg_replace('/^'. preg_quote($namespace). '/', '', $class); - - $file = str_replace(self::NAMESPACE_SEPARATOR, '/', $file). '.php'; + $file = $this->namespaces[$namespace] . preg_replace('/^' . preg_quote($namespace) . '/', '', $class); + $file = str_replace(self::NAMESPACE_SEPARATOR, '/', $file) . '.php'; if (@file_exists($file)) { require_once $file; @@ -108,16 +88,19 @@ class Loader * * Return is the longest match in the array found * - * @param string $className - * @return bool|string + * @param string $className + * + * @return bool|string */ private function getNamespaceForClass($className) { $testNamespace = ''; $testLength = 0; - foreach ($this->namespaces as $namespace => $directory) { - $stub = preg_replace('/^'. preg_quote($namespace). '/', '', $className); + foreach (array_keys($this->namespaces) as $namespace) { + $stub = preg_replace( + '/^' . preg_quote($namespace) . '(' . preg_quote(self::NAMESPACE_SEPARATOR) . '|$)/', '', $className + ); $length = strlen($className) - strlen($stub); if ($length > $testLength) { $testLength = $length; diff --git a/library/Icinga/Application/Modules/Manager.php b/library/Icinga/Application/Modules/Manager.php index db597f6d3..050c6c275 100644 --- a/library/Icinga/Application/Modules/Manager.php +++ b/library/Icinga/Application/Modules/Manager.php @@ -128,10 +128,10 @@ class Manager private function detectEnabledModules() { $canonical = $this->enableDir; - if ($canonical === false) { - throw new NotReadableError( - 'Cannot read enabled modules. Module directory "' . $this->enableDir . '" does not exist' - ); + if ($canonical === false || ! file_exists($canonical)) { + // TODO: I guess the check for false has something to do with a + // call to realpath no longer present + return; } if (!is_dir($this->enableDir)) { throw new NotReadableError( diff --git a/library/Icinga/Application/Platform.php b/library/Icinga/Application/Platform.php index 80bb6896d..dfc98819d 100644 --- a/library/Icinga/Application/Platform.php +++ b/library/Icinga/Application/Platform.php @@ -1,4 +1,5 @@ $userTimezone)); + date_default_timezone_set($userTimezone); + } catch (ConfigurationError $e) { return parent::setupTimezone(); } - date_default_timezone_set($userTimezone); - DateTimeFactory::setConfig(array('timezone' => $tz)); return $this; } @@ -372,3 +372,4 @@ class Web extends ApplicationBootstrap return $this; } } +// @codeCoverageIgnoreEnd diff --git a/library/Icinga/Application/webrouter.php b/library/Icinga/Application/webrouter.php index 89dc2365c..2cf7a3155 100644 --- a/library/Icinga/Application/webrouter.php +++ b/library/Icinga/Application/webrouter.php @@ -10,14 +10,6 @@ use Icinga\Chart\Inline\PieChart; error_reporting(E_ALL | E_STRICT); -if (array_key_exists('ICINGAWEB_CONFIGDIR', $_ENV)) { - $configDir = $_ENV['ICINGAWEB_CONFIGDIR']; -} elseif (array_key_exists('ICINGAWEB_CONFIGDIR', $_SERVER)) { - $configDir = $_SERVER['ICINGAWEB_CONFIGDIR']; -} else { - $configDir = '/etc/icingaweb'; -} - if (isset($_SERVER['REQUEST_URI'])) { $ruri = $_SERVER['REQUEST_URI']; } else { @@ -40,9 +32,8 @@ $baseDir = dirname($_SERVER['SCRIPT_FILENAME']); // Fix aliases $remove = dirname($_SERVER['PHP_SELF']); if (substr($ruri, 0, strlen($remove)) !== $remove) { - return false; + return false; } - $ruri = ltrim(substr($ruri, strlen($remove)), '/'); if (strpos($ruri, '?') === false) { @@ -61,8 +52,8 @@ $special = array( if (in_array($path, $special)) { - require_once __DIR__ . '/EmbeddedWeb.php'; - EmbeddedWeb::start($configDir); + include_once __DIR__ . '/EmbeddedWeb.php'; + EmbeddedWeb::start(); switch($path) { @@ -89,17 +80,17 @@ if (in_array($path, $special)) { if (!array_key_exists('data', $_GET)) { return false; } - require_once __DIR__ . '/EmbeddedWeb.php'; - EmbeddedWeb::start($configDir); + include __DIR__ . '/EmbeddedWeb.php'; + EmbeddedWeb::start(); header('Content-Type: image/svg+xml'); $pie = new PieChart(); $pie->initFromRequest(); echo $pie->render(); -} elseif (file_exists($baseDir . $ruri) && is_file($baseDir . $ruri)) { +} elseif (file_exists($baseDir . '/' . $path) && is_file($baseDir . '/' . $path)) { return false; } else { - require_once __DIR__ . '/Web.php'; - Web::start($configDir)->dispatch(); + include __DIR__ . '/Web.php'; + Web::start()->dispatch(); } diff --git a/library/Icinga/Cli/Screen/AnsiScreen.php b/library/Icinga/Cli/AnsiScreen.php similarity index 65% rename from library/Icinga/Cli/Screen/AnsiScreen.php rename to library/Icinga/Cli/AnsiScreen.php index fa9cc9cc2..a18b9649e 100644 --- a/library/Icinga/Cli/Screen/AnsiScreen.php +++ b/library/Icinga/Cli/AnsiScreen.php @@ -1,6 +1,6 @@ '30', 'darkgray' => '1;30', @@ -40,36 +38,6 @@ class AnsiScreen extends Screen 'lightgray' => '47', ); - public function __construct() - { - } - - public function getColumns() - { - $cols = (int) getenv('COLUMNS'); - if (! $cols) { - // stty -a ? - $cols = (int) exec('tput cols'); - } - if (! $cols) { - $cols = 80; - } - return $cols; - } - - public function getRows() - { - $rows = (int) getenv('ROWS'); - if (! $rows) { - // stty -a ? - $rows = (int) exec('tput rows'); - } - if (! $rows) { - $rows = 25; - } - return $rows; - } - public function strlen($string) { return strlen($this->stripAnsiCodes($string)); @@ -80,40 +48,6 @@ class AnsiScreen extends Screen return preg_replace('/\e\[?.*?[\@-~]/', '', $string); } - public function newlines($count = 1) - { - return str_repeat("\n", $count); - } - - public function center($txt) - { - $len = $this->strlen($txt); - $width = floor(($this->getColumns() + $len) / 2) - $len; - return str_repeat(' ', $width) . $txt; - } - - public function hasUtf8() - { - if ($this->isUtf8 === null) { - // null should equal 0 here, however seems to equal '' on some systems: - $current = setlocale(LC_ALL, 0); - - $parts = preg_split('/;/', $current); - $lc_parts = array(); - foreach ($parts as $part) { - if (strpos($part, '=') === false) { - continue; - } - list($key, $val) = preg_split('/=/', $part, 2); - $lc_parts[$key] = $val; - } - - $this->isUtf8 = array_key_exists('LC_CTYPE', $lc_parts) - && preg_match('~\.UTF-8$~i', $lc_parts['LC_CTYPE']); - } - return $this->isUtf8; - } - public function clear() { return "\033[2J" // Clear the whole screen @@ -121,6 +55,20 @@ class AnsiScreen extends Screen . "\033[1S"; // Scroll whole page up by 1 line (why?) } + public function underline($text) + { + return "\033[4m" + . $text + . "\033[0m"; // Reset color codes + } + + public function colorize($text, $fgColor = null, $bgColor = null) + { + return $this->startColor($fgColor, $bgColor) + . $text + . "\033[0m"; // Reset color codes + } + protected function fgColor($color) { if (! array_key_exists($color, $this->fgColors)) { @@ -163,18 +111,4 @@ class AnsiScreen extends Screen } return "\033[" . implode(';', $parts) . 'm'; } - - public function underline($text) - { - return "\033[4m" - . $text - . "\033[0m"; // Reset color codes - } - - public function colorize($text, $fgColor = null, $bgColor = null) - { - return $this->startColor($fgColor, $bgColor) - . $text - . "\033[0m"; // Reset color codes - } } diff --git a/library/Icinga/Cli/Screen.php b/library/Icinga/Cli/Screen.php index 92475559d..bd29ebb37 100644 --- a/library/Icinga/Cli/Screen.php +++ b/library/Icinga/Cli/Screen.php @@ -2,16 +2,102 @@ namespace Icinga\Cli; -use Icinga\Cli\Screen\AnsiScreen; +use Icinga\Cli\AnsiScreen; class Screen { protected static $instance; + protected $isUtf8; + + public function getColumns() + { + $cols = (int) getenv('COLUMNS'); + if (! $cols) { + // stty -a ? + $cols = (int) exec('tput cols'); + } + if (! $cols) { + $cols = 80; + } + return $cols; + } + + public function getRows() + { + $rows = (int) getenv('ROWS'); + if (! $rows) { + // stty -a ? + $rows = (int) exec('tput rows'); + } + if (! $rows) { + $rows = 25; + } + return $rows; + } + + public function strlen($string) + { + return strlen($string); + } + + public function newlines($count = 1) + { + return str_repeat("\n", $count); + } + + public function center($txt) + { + $len = $this->strlen($txt); + $width = floor(($this->getColumns() + $len) / 2) - $len; + return str_repeat(' ', $width) . $txt; + } + + public function hasUtf8() + { + if ($this->isUtf8 === null) { + // null should equal 0 here, however seems to equal '' on some systems: + $current = setlocale(LC_ALL, 0); + + $parts = preg_split('/;/', $current); + $lc_parts = array(); + foreach ($parts as $part) { + if (strpos($part, '=') === false) { + continue; + } + list($key, $val) = preg_split('/=/', $part, 2); + $lc_parts[$key] = $val; + } + + $this->isUtf8 = array_key_exists('LC_CTYPE', $lc_parts) + && preg_match('~\.UTF-8$~i', $lc_parts['LC_CTYPE']); + } + return $this->isUtf8; + } + + public function clear() + { + return "\n"; + } + + public function underline($text) + { + return $text; + } + + public function colorize($text, $fgColor = null, $bgColor = null) + { + return $text; + } + public static function instance() { if (self::$instance === null) { - self::$instance = new AnsiScreen(); + if (function_exists('posix_isatty') && posix_isatty(STDOUT)) { + self::$instance = new AnsiScreen(); + } else { + self::$instance = new Screen(); + } } return self::$instance; } diff --git a/library/Icinga/Config/PreservingIniWriter.php b/library/Icinga/Config/PreservingIniWriter.php index d8dc8cf6d..159a52fdd 100644 --- a/library/Icinga/Config/PreservingIniWriter.php +++ b/library/Icinga/Config/PreservingIniWriter.php @@ -29,14 +29,13 @@ namespace Icinga\Config; -use \Zend_Config; -use \Zend_Config_Ini; -use \Zend_Config_Writer_FileAbstract; -use \Icinga\Config\IniEditor; +use Zend_Config; +use Zend_Config_Ini; +use Zend_Config_Writer_FileAbstract; +use Icinga\Config\IniEditor; /** - * A ini file adapter that respects the file structure and the comments of already - * existing ini files + * A ini file adapter that respects the file structure and the comments of already existing ini files */ class PreservingIniWriter extends Zend_Config_Writer_FileAbstract { @@ -45,7 +44,7 @@ class PreservingIniWriter extends Zend_Config_Writer_FileAbstract * * @var array */ - private $options; + protected $options; /** * Create a new PreservingIniWriter @@ -67,7 +66,7 @@ class PreservingIniWriter extends Zend_Config_Writer_FileAbstract /** * Render the Zend_Config into a config file string * - * @return string + * @return string */ public function render() { @@ -86,12 +85,12 @@ class PreservingIniWriter extends Zend_Config_Writer_FileAbstract /** * Create a property diff and apply the changes to the editor * - * @param Zend_Config $oldconfig The config representing the state before the change - * @param Zend_Config $newconfig The config representing the state after the change - * @param IniEditor $editor The editor that should be used to edit the old config file - * @param array $parents The parent keys that should be respected when editing the config + * @param Zend_Config $oldconfig The config representing the state before the change + * @param Zend_Config $newconfig The config representing the state after the change + * @param IniEditor $editor The editor that should be used to edit the old config file + * @param array $parents The parent keys that should be respected when editing the config */ - private function diffConfigs( + protected function diffConfigs( Zend_Config $oldconfig, Zend_Config $newconfig, IniEditor $editor, @@ -102,13 +101,10 @@ class PreservingIniWriter extends Zend_Config_Writer_FileAbstract } /** - * Update the order of the sections in the ini file to match - * the order of the new config + * Update the order of the sections in the ini file to match the order of the new config */ - private function updateSectionOrder( - Zend_Config $newconfig, - IniEditor $editor - ) { + protected function updateSectionOrder(Zend_Config $newconfig, IniEditor $editor) + { $order = array(); foreach ($newconfig as $key => $value) { if ($value instanceof Zend_Config) { @@ -126,48 +122,33 @@ class PreservingIniWriter extends Zend_Config_Writer_FileAbstract * @param IniEditor $editor The editor that should be used to edit the old config file * @param array $parents The parent keys that should be respected when editing the config */ - private function diffPropertyUpdates( + protected function diffPropertyUpdates( Zend_Config $oldconfig, Zend_Config $newconfig, IniEditor $editor, array $parents = array() ) { - /* - * The current section. This value is null when processing - * the section-less root element - */ + // The current section. This value is null when processing the section-less root element $section = empty($parents) ? null : $parents[0]; - - /* - * Iterate over all properties in the new configuration file and search for changes - */ + // Iterate over all properties in the new configuration file and search for changes foreach ($newconfig as $key => $value) { $oldvalue = $oldconfig->get($key); $nextParents = array_merge($parents, array($key)); - $keyIdentifier = empty($parents) ? - array($key) : array_slice($nextParents, 1, null, true); - + $keyIdentifier = empty($parents) ? array($key) : array_slice($nextParents, 1, null, true); if ($value instanceof Zend_Config) { - /* - * The value is a nested Zend_Config, handle it recursively - */ - if (!isset($section)) { - /* - * Update the section declaration - */ + // The value is a nested Zend_Config, handle it recursively + if ($section === null) { + // Update the section declaration $extends = $newconfig->getExtends(); - $extend = array_key_exists($key, $extends) ? - $extends[$key] : null; + $extend = array_key_exists($key, $extends) ? $extends[$key] : null; $editor->setSection($key, $extend); } - if (!isset($oldvalue)) { + if ($oldvalue === null) { $oldvalue = new Zend_Config(array()); } $this->diffConfigs($oldvalue, $value, $editor, $nextParents); } else { - /* - * The value is a plain value, use the editor to set it - */ + // The value is a plain value, use the editor to set it if (is_numeric($key)) { $editor->setArrayElement($keyIdentifier, $value, $section); } else { @@ -185,43 +166,35 @@ class PreservingIniWriter extends Zend_Config_Writer_FileAbstract * @param IniEditor $editor The editor that should be used to edit the old config file * @param array $parents The parent keys that should be respected when editing the config */ - private function diffPropertyDeletions( + protected function diffPropertyDeletions( Zend_Config $oldconfig, Zend_Config $newconfig, IniEditor $editor, array $parents = array() ) { - /* - * The current section. This value is null when processing - * the section-less root element - */ + // The current section. This value is null when processing the section-less root element $section = empty($parents) ? null : $parents[0]; - /* - * Iterate over all properties in the old configuration file and search for - * deleted properties - */ + // Iterate over all properties in the old configuration file and search for deleted properties foreach ($oldconfig as $key => $value) { $nextParents = array_merge($parents, array($key)); $newvalue = $newconfig->get($key); - $keyIdentifier = empty($parents) ? - array($key) : array_slice($nextParents, 1, null, true); + $keyIdentifier = empty($parents) ? array($key) : array_slice($nextParents, 1, null, true); - if (!isset($newvalue)) { + if ($newvalue === null) { if ($value instanceof Zend_Config) { - /* - * The deleted value is a nested Zend_Config, handle it recursively - */ + // The deleted value is a nested Zend_Config, handle it recursively $this->diffConfigs($value, new Zend_Config(array()), $editor, $nextParents); - if (!isset($section)) { + if ($section === null) { $editor->removeSection($key); } } else { - /* - * The deleted value is a plain value, use the editor to delete it - */ + // The deleted value is a plain value, use the editor to delete it if (is_numeric($key)) { $editor->resetArrayElement($keyIdentifier, $section); + } elseif (!empty($parents)) { + // Drop nested properties, fixes #5958 + $editor->resetArrayElement($nextParents, $section); } else { $editor->reset($keyIdentifier, $section); } diff --git a/library/Icinga/Data/ResourceFactory.php b/library/Icinga/Data/ResourceFactory.php index 3b4d14e3b..ef22179b2 100644 --- a/library/Icinga/Data/ResourceFactory.php +++ b/library/Icinga/Data/ResourceFactory.php @@ -143,8 +143,18 @@ class ResourceFactory implements ConfigAwareFactory return $resource; } - public static function getBackendType($resource) + public static function ldapAvailable() { + return extension_loaded('ldap'); + } + public static function pgsqlAvailable() + { + return extension_loaded('pgsql'); + } + + public static function mysqlAvailable() + { + return extension_loaded('mysql'); } } diff --git a/library/Icinga/File/Csv.php b/library/Icinga/File/Csv.php index 7fb4b25ee..4873fcf97 100644 --- a/library/Icinga/File/Csv.php +++ b/library/Icinga/File/Csv.php @@ -1,4 +1,6 @@ stream = Config::resolvePath($config->target); + $this->path = Config::resolvePath($config->target); $this->setup(); } @@ -43,17 +44,17 @@ class StreamWriter extends LogWriter } /** - * Create the stream if it does not already exist + * Create the file if it does not already exist */ protected function setup() { - if (substr($this->stream, 0, 6) !== 'php://') { - if (!file_exists($this->stream) && (!@touch($this->stream) || !@chmod($this->stream, 0664))) { - throw new ConfigurationError('Cannot create log file "' . $this->stream . '"'); + if (substr($this->path, 0, 6) !== 'php://') { + if (!file_exists($this->path) && (!@touch($this->path) || !@chmod($this->path, 0664))) { + throw new ConfigurationError('Cannot create log file "' . $this->path . '"'); } - if (!@is_writable($this->stream)) { - throw new ConfigurationError('Cannot write to log file "' . $this->stream . '"'); + if (!@is_writable($this->path)) { + throw new ConfigurationError('Cannot write to log file "' . $this->path . '"'); } } } @@ -84,14 +85,20 @@ class StreamWriter extends LogWriter } /** - * Write a message to the stream + * Write a message to the path * * @param string $text The message to write + * + * @throws Exception In case write acess to the path failed */ protected function write($text) { - $fd = fopen($this->stream, 'a'); - fwrite($fd, $text . PHP_EOL); + $fd = fopen($this->path, 'a'); + + if ($fd === false || fwrite($fd, $text . PHP_EOL) === false) { + throw new Exception('Failed to write to log file "' . $this->path . '"'); + } + fclose($fd); } } diff --git a/library/Icinga/Logger/Writer/SyslogWriter.php b/library/Icinga/Logger/Writer/SyslogWriter.php index e78971304..6dd6cb528 100644 --- a/library/Icinga/Logger/Writer/SyslogWriter.php +++ b/library/Icinga/Logger/Writer/SyslogWriter.php @@ -1,11 +1,12 @@ path); $file = @fopen($this->path, $this->openMode); if (!$file) { - throw new \RuntimeException('Could not open icinga pipe at $file : ' . print_r(error_get_last(), true)); + throw new ConfigurationError(sprintf('Could not open icinga command pipe at "%s"', $this->path)); } fwrite($file, '[' . time() . '] ' . $message . PHP_EOL); Logger::debug('Writing [' . time() . '] ' . $message . PHP_EOL); diff --git a/library/Icinga/Protocol/File/Reader.php b/library/Icinga/Protocol/File/Reader.php index b2eb80c23..f5677e855 100644 --- a/library/Icinga/Protocol/File/Reader.php +++ b/library/Icinga/Protocol/File/Reader.php @@ -184,35 +184,67 @@ class Reader implements DatasourceInterface $PHP_EOL_len = strlen(PHP_EOL); $lines = array(); $s = ''; - $f = fopen($this->filename, 'rb'); - fseek($f, 0, SEEK_END); - $pos = ftell($f); - while ($read_lines === null || count($lines) < $read_lines) { - fseek($f, --$pos); - $c = fgetc($f); - if ($c === false || $pos < 0) { - $l = $this->validateLine($s, $query); - if (!($l === false || $skip_lines)) { - $lines[] = $l; - } - break; + $f = @fopen($this->filename, 'rb'); + if ($f !== false) { + $buffer = ''; + fseek($f, 0, SEEK_END); + if (ftell($f) === 0) { + return array(); } - $s = $c . $s; - if (strpos($s, PHP_EOL) === 0) { - $l = $this->validateLine((string)substr($s, $PHP_EOL_len), $query); - if ($l !== false) { - if ($skip_lines) { - $skip_lines--; - } else { + while ($read_lines === null || count($lines) < $read_lines) { + $c = $this->fgetc($f, $buffer); + if ($c === false) { + $l = $this->validateLine($s, $query); + if (!($l === false || $skip_lines)) { $lines[] = $l; } + break; + } + $s = $c . $s; + if (strpos($s, PHP_EOL) === 0) { + $l = $this->validateLine((string)substr($s, $PHP_EOL_len), $query); + if ($l !== false) { + if ($skip_lines) { + $skip_lines--; + } else { + $lines[] = $l; + } + } + $s = ''; } - $s = ''; } } return $lines; } + /** + * Backend for $this->readFromEnd + */ + public function fgetc($file, &$buffer) + { + $strlen = strlen($buffer); + if ($strlen === 0) { + $pos = ftell($file); + if ($pos === 0) { + return false; + } + if ($pos < 4096) { + fseek($file, 0); + $buffer = fread($file, $pos); + fseek($file, 0); + } else { + fseek($file, -4096, SEEK_CUR); + $buffer = fread($file, 4096); + fseek($file, -4096, SEEK_CUR); + } + return $this->fgetc($file, $buffer); + } else { + $char = substr($buffer, -1); + $buffer = substr($buffer, 0, $strlen - 1); + return $char; + } + } + /** * Backend for $this->read * Direction: FIFO @@ -222,27 +254,33 @@ class Reader implements DatasourceInterface $PHP_EOL_len = strlen(PHP_EOL); $lines = array(); $s = ''; - $f = fopen($this->filename, 'rb'); - while ($read_lines === null || count($lines) < $read_lines) { - $c = fgetc($f); - if ($c === false) { - $l = $this->validateLine($s, $query); - if (!($l === false || $skip_lines)) { - $lines[] = $l; - } - break; - } - $s .= $c; - if (strpos($s, PHP_EOL) !== false) { - $l = $this->validateLine((string)substr($s, 0, strlen($s) - $PHP_EOL_len), $query); - if ($l !== false) { - if ($skip_lines) { - $skip_lines--; - } else { - $lines[] = $l; + $f = @fopen($this->filename, 'rb'); + if ($f !== false) { + $buffer = ''; + while ($read_lines === null || count($lines) < $read_lines) { + if (strlen($buffer) === 0) { + $buffer = fread($f, 4096); + if (strlen($buffer) === 0) { + $l = $this->validateLine($s, $query); + if (!($l === false || $skip_lines)) { + $lines[] = $l; + } + break; } } - $s = ''; + $s .= substr($buffer, 0, 1); + $buffer = substr($buffer, 1); + if (strpos($s, PHP_EOL) !== false) { + $l = $this->validateLine((string)substr($s, 0, strlen($s) - $PHP_EOL_len), $query); + if ($l !== false) { + if ($skip_lines) { + $skip_lines--; + } else { + $lines[] = $l; + } + } + $s = ''; + } } } return $lines; @@ -259,26 +297,29 @@ class Reader implements DatasourceInterface $PHP_EOL_len = strlen(PHP_EOL); $lines = 0; $s = ''; - $f = fopen($this->filename, 'rb'); - fseek($f, 0, SEEK_END); - $pos = ftell($f); - while (true) { - fseek($f, --$pos); - $c = fgetc($f); - if ($c === false || $pos < 0) { - if ($this->validateLine($s, $query) !== false) { - $lines++; + $f = @fopen($this->filename, 'rb'); + if ($f !== false) { + $buffer = ''; + while (true) { + if (strlen($buffer) === 0) { + $buffer = fread($f, 4096); + if (strlen($buffer) === 0) { + if ($this->validateLine($s, $query) !== false) { + $lines++; + } + break; + } } - break; - } - $s = $c . $s; - if (strpos($s, PHP_EOL) === 0) { - if ($this->validateLine((string)substr($s, $PHP_EOL_len), $query) !== false) { - $lines++; + $s .= substr($buffer, 0, 1); + $buffer = substr($buffer, 1); + if (strpos($s, PHP_EOL) !== false) { + if ($this->validateLine((string)substr($s, 0, strlen($s) - $PHP_EOL_len), $query) !== false) { + $lines++; + } + $s = ''; } - $s = ''; } } return $lines; } -} \ No newline at end of file +} diff --git a/library/Icinga/Protocol/Livestatus/Connection.php b/library/Icinga/Protocol/Livestatus/Connection.php index 395d21442..fe440c788 100644 --- a/library/Icinga/Protocol/Livestatus/Connection.php +++ b/library/Icinga/Protocol/Livestatus/Connection.php @@ -273,6 +273,15 @@ class Connection } } + public function connect() + { + if (!$this->connection) { + $this->getConnection(); + } + + return $this; + } + public function disconnect() { if ($this->connection) { diff --git a/library/Icinga/Test/BaseTestCase.php b/library/Icinga/Test/BaseTestCase.php index 02eeb56a4..5b63219d6 100644 --- a/library/Icinga/Test/BaseTestCase.php +++ b/library/Icinga/Test/BaseTestCase.php @@ -1,30 +1,5 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} namespace { @@ -46,28 +21,24 @@ namespace { namespace Icinga\Test { - require_once 'Zend/Test/PHPUnit/ControllerTestCase.php'; - require_once 'Zend/Db/Adapter/Pdo/Abstract.php'; - require_once 'DbTest.php'; - require_once 'FormTest.php'; - // @codingStandardsIgnoreStart - use \Exception; - use \RuntimeException; - use Zend_Test_PHPUnit_ControllerTestCase; + use Exception; + use RuntimeException; + use Mockery; use Zend_Config; - use Zend_Db_Adapter_Pdo_Abstract; - use Zend_Db_Adapter_Pdo_Mysql; - use Zend_Db_Adapter_Pdo_Pgsql; - use Zend_Db_Adapter_Pdo_Oci; + use Zend_Controller_Request_Abstract; + use Zend_Controller_Request_HttpTestCase; + use PHPUnit_Framework_TestCase; + use Icinga\Application\Icinga; + use Icinga\Util\DateTimeFactory; use Icinga\Data\ResourceFactory; + use Icinga\Data\Db\Connection; use Icinga\User\Preferences; use Icinga\Web\Form; - // @codingStandardsIgnoreEnd /** * Class BaseTestCase */ - class BaseTestCase extends Zend_Test_PHPUnit_ControllerTestCase implements DbTest, FormTest + class BaseTestCase extends PHPUnit_Framework_TestCase implements DbTest, FormTest { /** * Path to application/ @@ -111,12 +82,19 @@ namespace Icinga\Test { */ public static $moduleDir; + /** + * Store request for form tests + * + * @var Zend_Controller_Request_HttpTestCase + */ + private $request; + /** * Resource configuration for different database types * * @var array */ - private static $dbConfiguration = array( + protected static $dbConfiguration = array( 'mysql' => array( 'type' => 'db', 'db' => 'mysql', @@ -138,17 +116,12 @@ namespace Icinga\Test { ); /** - * Constructs a test case with the given name. - * - * @param string $name - * @param array $data - * @param string $dataName - * @see PHPUnit_Framework_TestCase::__construct + * Setup the default timezone and pass it to DateTimeFactory::setConfig */ - public function __construct($name = null, array $data = array(), $dataName = '') + public static function setupTimezone() { - parent::__construct($name, $data, $dataName); date_default_timezone_set('UTC'); + DateTimeFactory::setConfig(array('timezone' => 'UTC')); } /** @@ -158,12 +131,6 @@ namespace Icinga\Test { */ public static function setupDirectories() { - static $initialized = false; - - if ($initialized === true) { - return; - } - $baseDir = realpath(__DIR__ . '/../../../'); if ($baseDir === false) { @@ -176,8 +143,36 @@ namespace Icinga\Test { self::$testDir = $baseDir . '/test/php'; self::$shareDir = $baseDir . '/share/icinga2-web'; self::$moduleDir = $baseDir . '/modules'; + } - $initialized = true; + /** + * Setup MVC bootstrapping and ensure that the Icinga-Mock gets reinitialized + */ + public function setUp() + { + parent::setUp(); + + $requestMock = Mockery::mock('Icinga\Web\Request'); + $requestMock->shouldReceive('getPathInfo')->andReturn('') + ->shouldReceive('getBaseUrl')->andReturn('/') + ->shouldReceive('getQuery')->andReturn(array()); + $this->setupIcingaMock($requestMock); + } + + /** + * Setup mock object for the application's bootstrap + * + * @param Zend_Controller_Request_Abstract $request The request to be returned by + * Icinga::app()->getFrontController()->getRequest() + */ + protected function setupIcingaMock(Zend_Controller_Request_Abstract $request) + { + $bootstrapMock = Mockery::mock('Icinga\Application\ApplicationBootstrap')->shouldDeferMissing(); + $bootstrapMock->shouldReceive('getFrontController->getRequest')->andReturnUsing( + function () use ($request) { return $request; } + )->shouldReceive('getApplicationDir')->andReturn(self::$appDir); + + Icinga::setApp($bootstrapMock, true); } /** @@ -188,7 +183,7 @@ namespace Icinga\Test { * @return Zend_Config * @throws RuntimeException */ - private function createDbConfigFor($name) + protected function createDbConfigFor($name) { if (array_key_exists($name, self::$dbConfiguration)) { return new Zend_Config(self::$dbConfiguration[$name]); @@ -198,67 +193,64 @@ namespace Icinga\Test { } /** - * Creates an array of Zend Database Adapter + * Creates an array of Icinga\Data\Db\Connection * * @param string $name * * @return array */ - private function createDbAdapterFor($name) + protected function createDbConnectionFor($name) { - $this->requireDbLibraries(); - try { - $adapter = ResourceFactory::createResource($this->createDbConfigFor($name))->getConnection(); + $conn = ResourceFactory::createResource($this->createDbConfigFor($name)); } catch (Exception $e) { - $adapter = $e->getMessage(); + $conn = $e->getMessage(); } return array( - array($adapter) + array($conn) ); } /** * PHPUnit provider for mysql * - * @return Zend_Db_Adapter_Pdo_Mysql + * @return Connection */ public function mysqlDb() { - return $this->createDbAdapterFor('mysql'); + return $this->createDbConnectionFor('mysql'); } /** * PHPUnit provider for pgsql * - * @return Zend_Db_Adapter_Pdo_Pgsql + * @return Connection */ public function pgsqlDb() { - return $this->createDbAdapterFor('pgsql'); + return $this->createDbConnectionFor('pgsql'); } /** * PHPUnit provider for oracle * - * @return Zend_Db_Adapter_Pdo_Oci + * @return Connection */ public function oracleDb() { - return $this->createDbAdapterFor('oracle'); + return $this->createDbConnectionFor('oracle'); } /** - * Executes sql file on PDO object + * Executes sql file by using the database connection * - * @param Zend_Db_Adapter_Pdo_Abstract $resource - * @param string $filename + * @param Connection $resource + * @param string $filename * - * @return boolean Operational success flag * @throws RuntimeException */ - public function loadSql(Zend_Db_Adapter_Pdo_Abstract $resource, $filename) + public function loadSql(Connection $resource, $filename) { if (!is_file($filename)) { throw new RuntimeException( @@ -274,17 +266,17 @@ namespace Icinga\Test { ); } - $resource->exec($sqlData); + $resource->getConnection()->exec($sqlData); } /** * Setup provider for testcase * - * @param string|Zend_Db_Adapter_PDO_Abstract|null $resource + * @param string|Connection|null $resource */ public function setupDbProvider($resource) { - if (!$resource instanceof Zend_Db_Adapter_Pdo_Abstract) { + if (!$resource instanceof Connection) { if (is_string($resource)) { $this->markTestSkipped('Could not initialize provider: ' . $resource); } else { @@ -293,15 +285,17 @@ namespace Icinga\Test { return; } + $adapter = $resource->getConnection(); + try { - $resource->getConnection(); + $adapter->getConnection(); } catch (Exception $e) { $this->markTestSkipped('Could not connect to provider: '. $e->getMessage()); } - $tables = $resource->listTables(); + $tables = $adapter->listTables(); foreach ($tables as $table) { - $resource->exec('DROP TABLE ' . $table . ';'); + $adapter->exec('DROP TABLE ' . $table . ';'); } } @@ -341,57 +335,22 @@ namespace Icinga\Test { } /** - * Require all libraries to instantiate forms + * Retrieve test case request object + * + * This is a mock methods borrowed from Zend Controller Test Case to handle form tests properly (#6106) + * + * @return Zend_Controller_Request_HttpTestCase */ - public static function requireFormLibraries() + public function getRequest() { - require_once 'Zend/Form/Decorator/Abstract.php'; - require_once 'Zend/Validate/Abstract.php'; - require_once 'Zend/Form/Element/Xhtml.php'; - require_once 'Zend/Form/Element/Text.php'; - require_once 'Zend/Form/Element/Submit.php'; - require_once 'Zend/Form/Element/Checkbox.php'; - require_once 'Zend/Form.php'; - require_once 'Zend/View.php'; - - require_once self::$libDir . '/Web/Form/InvalidCSRFTokenException.php'; - - require_once self::$libDir . '/Web/Form/Element/DateTimePicker.php'; - require_once self::$libDir . '/Web/Form/Element/Note.php'; - require_once self::$libDir . '/Web/Form/Element/Number.php'; - - require_once self::$libDir . '/Web/Form/Decorator/ConditionalHidden.php'; - require_once self::$libDir . '/Web/Form/Decorator/HelpText.php'; - require_once self::$libDir . '/Web/Form/Decorator/BootstrapForm.php'; - - require_once self::$libDir . '/Web/Form/Validator/DateFormatValidator.php'; - require_once self::$libDir . '/Web/Form/Validator/TimeFormatValidator.php'; - require_once self::$libDir . '/Web/Form/Validator/WritablePathValidator.php'; - - require_once self::$libDir . '/Web/Form.php'; - - require_once self::$libDir . '/User/Preferences.php'; - } - - /** - * Require all classes for database adapter creation - */ - public static function requireDbLibraries() - { - require_once 'Zend/Config.php'; - require_once 'Zend/Db.php'; - require_once 'Zend/Log.php'; - - require_once self::$libDir . '/Exception/ConfigurationError.php'; - require_once self::$libDir . '/Util/ConfigAwareFactory.php'; - require_once self::$libDir . '/Data/DatasourceInterface.php'; - require_once self::$libDir . '/Data/ResourceFactory.php'; - require_once self::$libDir . '/Data/Db/Connection.php'; - require_once self::$libDir . '/Application/Logger.php'; + if (null === $this->request) { + require_once 'Zend/Controller/Request/HttpTestCase.php'; + $this->request = new Zend_Controller_Request_HttpTestCase; + } + return $this->request; } } + BaseTestCase::setupTimezone(); BaseTestCase::setupDirectories(); - BaseTestCase::requireFormLibraries(); - BaseTestcase::requireDbLibraries(); } diff --git a/library/Icinga/Test/DbTest.php b/library/Icinga/Test/DbTest.php index ef385d9da..12cea240c 100644 --- a/library/Icinga/Test/DbTest.php +++ b/library/Icinga/Test/DbTest.php @@ -29,48 +29,45 @@ namespace Icinga\Test; -use \Zend_Db_Adapter_Pdo_Abstract; -use \Zend_Db_Adapter_Pdo_Mysql; -use \Zend_Db_Adapter_Pdo_Pgsql; -use \Zend_Db_Adapter_Pdo_Oci; +use Icinga\Data\Db\Connection; interface DbTest { /** * PHPUnit provider for mysql * - * @return Zend_Db_Adapter_Pdo_Mysql + * @return Connection */ public function mysqlDb(); /** * PHPUnit provider for pgsql * - * @return Zend_Db_Adapter_Pdo_Pgsql + * @return Connection */ public function pgsqlDb(); /** * PHPUnit provider for oracle * - * @return Zend_Db_Adapter_Pdo_Oci + * @return Connection */ public function oracleDb(); /** * Executes sql file on PDO object * - * @param Zend_Db_Adapter_PDO_Abstract $resource - * @param string $filename + * @param Connection $resource + * @param string $filename * * @return boolean Operational success flag */ - public function loadSql(Zend_Db_Adapter_PDO_Abstract $resource, $filename); + public function loadSql(Connection $resource, $filename); /** * Setup provider for testcase * - * @param string|Zend_Db_Adapter_PDO_Abstract|null $resource + * @param string|Connection|null $resource */ public function setupDbProvider($resource); } diff --git a/library/Icinga/User.php b/library/Icinga/User.php index 5d7887af3..9a759e529 100644 --- a/library/Icinga/User.php +++ b/library/Icinga/User.php @@ -29,18 +29,15 @@ namespace Icinga; -use \DateTimeZone; -use \Exception; -use \InvalidArgumentException; +use DateTimeZone; +use InvalidArgumentException; use Icinga\User\Preferences; use Icinga\User\Message; -use Icinga\Application\Config; /** * This class represents an authorized user * - * You can retrieve authorization information (@TODO: Not implemented yet) or - * to retrieve user information + * You can retrieve authorization information (@TODO: Not implemented yet) or user information */ class User { @@ -49,85 +46,85 @@ class User * * @var string */ - private $username; + protected $username; /** * Firstname * * @var string */ - private $firstname; + protected $firstname; /** * Lastname * * @var string */ - private $lastname; + protected $lastname; /** * Users email address * * @var string */ - private $email; + protected $email; /** * Domain * * @var string */ - private $domain; + protected $domain; /** - * More information about user + * More information about this user * * @var array */ - private $additionalInformation = array(); + protected $additionalInformation = array(); /** * Set of permissions * * @var array */ - private $permissions = array(); + protected $permissions = array(); /** * Set of restrictions * * @var array */ - private $restrictions = array(); + protected $restrictions = array(); /** * Groups for this user * * @var array */ - private $groups = array(); + protected $groups = array(); /** * Preferences object * * @var Preferences */ - private $preferences; + protected $preferences; /** * Queued notifications for this user. * * @var array() */ - private $messages; + protected $messages; /** * Creates a user object given the provided information * - * @param string $username - * @param string $firstname - * @param string $lastname - * @param string $email + * @param string $username + * @param string $firstname + * @param string $lastname + * @param string $email */ public function __construct($username, $firstname = null, $lastname = null, $email = null) { @@ -149,7 +146,7 @@ class User /** * Setter for preferences * - * @param Preferences $preferences + * @param Preferences $preferences */ public function setPreferences(Preferences $preferences) { @@ -159,20 +156,21 @@ class User /** * Getter for preferences * - * @return Preferences + * @return Preferences */ public function getPreferences() { if ($this->preferences === null) { $this->preferences = new Preferences(); } + return $this->preferences; } /** * Return all groups this user belongs to * - * @return array + * @return array */ public function getGroups() { @@ -181,6 +179,8 @@ class User /** * Set the groups this user belongs to + * + * @param array $groups */ public function setGroups(array $groups) { @@ -190,8 +190,9 @@ class User /** * Return true if the user is a member of this group * - * @param string $group - * @return boolean + * @param string $group + * + * @return boolean */ public function isMemberOf($group) { @@ -201,7 +202,7 @@ class User /** * Return permission information for this user * - * @return Array + * @return array */ public function getPermissions() { @@ -211,7 +212,7 @@ class User /** * Setter for permissions * - * @param array $permissions + * @param array $permissions */ public function setPermissions(array $permissions) { @@ -222,6 +223,7 @@ class User * Return restriction information for this user * * @param string $name + * * @return array */ public function getRestrictions($name) @@ -229,13 +231,14 @@ class User if (array_key_exists($name, $this->restrictions)) { return $this->restrictions[$name]; } + return array(); } /** * Settter for restrictions * - * @param array $restrictions + * @param array $restrictions */ public function setRestrictions(array $restrictions) { @@ -245,7 +248,7 @@ class User /** * Getter for username * - * @return string + * @return string */ public function getUsername() { @@ -255,7 +258,7 @@ class User /** * Setter for username * - * @param string $name + * @param string $name */ public function setUsername($name) { @@ -265,7 +268,7 @@ class User /** * Getter for firstname * - * @return string + * @return string */ public function getFirstname() { @@ -275,7 +278,7 @@ class User /** * Setter for firstname * - * @param string $name + * @param string $name */ public function setFirstname($name) { @@ -285,7 +288,7 @@ class User /** * Getter for lastname * - * @return string + * @return string */ public function getLastname() { @@ -295,7 +298,7 @@ class User /** * Setter for lastname * - * @param string $name + * @param string $name */ public function setLastname($name) { @@ -305,7 +308,7 @@ class User /** * Getter for email * - * @return string + * @return string */ public function getEmail() { @@ -315,8 +318,9 @@ class User /** * Setter for mail * - * @param string $mail - * @throws InvalidArgumentException When an invalid mail is provided + * @param string $mail + * + * @throws InvalidArgumentException When an invalid mail is provided */ public function setEmail($mail) { @@ -330,7 +334,7 @@ class User /** * Setter for domain * - * @param string $domain + * @param string $domain */ public function setDomain($domain) { @@ -340,7 +344,7 @@ class User /** * Getter for domain * - * @return string + * @return string */ public function getDomain() { @@ -351,8 +355,8 @@ class User /** * Set additional information about user * - * @param string $key - * @param string $value + * @param string $key + * @param string $value */ public function setAdditional($key, $value) { @@ -362,14 +366,15 @@ class User /** * Getter for additional information * - * @param string $key - * @return mixed|null + * @param string $key + * @return mixed|null */ public function getAdditional($key) { if (isset($this->additionalInformation[$key])) { return $this->additionalInformation[$key]; } + return null; } @@ -386,6 +391,7 @@ class User if ($tz === null) { $tz = date_default_timezone_get(); } + return new DateTimeZone($tz); } @@ -394,7 +400,7 @@ class User * * This function does NOT automatically write to the session, messages will not be persisted until you do. * - * @param Message $msg The message + * @param Message $msg The message */ public function addMessage(Message $msg) { @@ -404,7 +410,7 @@ class User /** * Get all currently pending messages * - * @return array the messages + * @return array The messages */ public function getMessages() { diff --git a/library/Icinga/User/Message.php b/library/Icinga/User/Message.php index 2fb76f9ee..36f45a936 100644 --- a/library/Icinga/User/Message.php +++ b/library/Icinga/User/Message.php @@ -1,8 +1,9 @@ level; } } +// @codeCoverageIgnoreEnd diff --git a/library/Icinga/User/Preferences.php b/library/Icinga/User/Preferences.php index 0e4b808d2..25c5e15ce 100644 --- a/library/Icinga/User/Preferences.php +++ b/library/Icinga/User/Preferences.php @@ -44,8 +44,6 @@ use Countable; * * $preferences = new Preferences(array('aPreference' => 'value')); // Start with initial preferences * - * $prefrences = $user->getPreferences(); // Retrieve preferences from a \Icinga\User instance - * * $preferences->aNewPreference = 'value'; // Set a preference * * unset($preferences->aPreference); // Unset a preference @@ -60,12 +58,12 @@ class Preferences implements Countable * * @var array */ - private $preferences = array(); + protected $preferences = array(); /** * Constructor * - * @param array $preferences Preferences key-value array + * @param array $preferences Preferences key-value array */ public function __construct(array $preferences = array()) { @@ -75,7 +73,7 @@ class Preferences implements Countable /** * Count all preferences * - * @return int The number of preferences + * @return int The number of preferences */ public function count() { @@ -85,7 +83,7 @@ class Preferences implements Countable /** * Determine whether a preference exists * - * @param string $name + * @param string $name * * @return bool */ @@ -97,8 +95,8 @@ class Preferences implements Countable /** * Write data to a preference * - * @param string $name - * @param mixed $value + * @param string $name + * @param mixed $value */ public function __set($name, $value) { @@ -108,8 +106,8 @@ class Preferences implements Countable /** * Retrieve a preference and return $default if the preference is not set * - * @param string $name - * @param mixed $default + * @param string $name + * @param mixed $default * * @return mixed */ @@ -118,13 +116,14 @@ class Preferences implements Countable if (array_key_exists($name, $this->preferences)) { return $this->preferences[$name]; } + return $default; } /** * Magic method so that $obj->value will work. * - * @param string $name + * @param string $name * * @return mixed */ @@ -136,7 +135,7 @@ class Preferences implements Countable /** * Remove a given preference * - * @param string $name Preference name + * @param string $name Preference name */ public function remove($name) { @@ -146,7 +145,8 @@ class Preferences implements Countable /** * Determine if a preference is set and is not NULL * - * @param string $name Preference name + * @param string $name Preference name + * * @return bool */ public function __isset($name) @@ -157,7 +157,7 @@ class Preferences implements Countable /** * Unset a given preference * - * @param string $name Preference name + * @param string $name Preference name */ public function __unset($name) { @@ -167,7 +167,7 @@ class Preferences implements Countable /** * Get preferences as array * - * @return array + * @return array */ public function toArray() { diff --git a/library/Icinga/User/Preferences/Store/DbStore.php b/library/Icinga/User/Preferences/Store/DbStore.php index 367552b7f..e60746c1e 100644 --- a/library/Icinga/User/Preferences/Store/DbStore.php +++ b/library/Icinga/User/Preferences/Store/DbStore.php @@ -4,8 +4,8 @@ namespace Icinga\User\Preferences\Store; -use \Exception; -use \Zend_Db_Select; +use Exception; +use Zend_Db_Select; use Icinga\Exception\NotReadableError; use Icinga\Exception\NotWritableError; use Icinga\User\Preferences; diff --git a/library/Icinga/User/Preferences/Store/IniStore.php b/library/Icinga/User/Preferences/Store/IniStore.php index c3521b422..7363f2569 100644 --- a/library/Icinga/User/Preferences/Store/IniStore.php +++ b/library/Icinga/User/Preferences/Store/IniStore.php @@ -4,7 +4,7 @@ namespace Icinga\User\Preferences\Store; -use \Zend_Config; +use Zend_Config; use Icinga\Util\File; use Icinga\Config\PreservingIniWriter; use Icinga\Exception\NotReadableError; diff --git a/library/Icinga/Util/DateTimeFactory.php b/library/Icinga/Util/DateTimeFactory.php index 17aa72948..5f6700882 100644 --- a/library/Icinga/Util/DateTimeFactory.php +++ b/library/Icinga/Util/DateTimeFactory.php @@ -29,8 +29,9 @@ namespace Icinga\Util; -use \DateTime; -use \DateTimeZone; +use Exception; +use DateTime; +use DateTimeZone; use Icinga\Util\ConfigAwareFactory; use Icinga\Exception\ConfigurationError; @@ -41,35 +42,42 @@ class DateTimeFactory implements ConfigAwareFactory { /** * Time zone used throughout DateTime object creation + * * @var DateTimeZone */ - private static $timeZone; + protected static $timeZone; /** * Set the factory's config * * Set the factory's time zone via key timezone in the given config array * - * @param array $config - * @throws \Icinga\Exception\ConfigurationError if the given config is not valid + * @param array $config An array with key 'timezone' + * + * @throws ConfigurationError if the given array misses the key 'timezone' */ public static function setConfig($config) { - if (!array_key_exists('timezone', $config)) { - throw new ConfigurationError(t('"DateTimeFactory" expects a valid time zone to be set via "setConfig"')); + try { + $tz = new DateTimeZone(isset($config['timezone']) ? $config['timezone'] : ''); + } catch (Exception $e) { + throw new ConfigurationError('"DateTimeFactory" expects a valid time zone be set via "setConfig"'); } - self::$timeZone = $config['timezone']; + + self::$timeZone = $tz; } /** - * Return new DateTime object using the given format, time and set time zone + * Return new DateTime object using the given format, time and set timezone * * Wraps DateTime::createFromFormat() * * @param string $format * @param string $time * @param DateTimeZone $timeZone + * * @return DateTime + * * @see DateTime::createFromFormat() */ public static function parse($time, $format, DateTimeZone $timeZone = null) @@ -84,46 +92,13 @@ class DateTimeFactory implements ConfigAwareFactory * * @param string $time * @param DateTimeZone $timeZone + * * @return DateTime + * * @see DateTime::__construct() */ public static function create($time = 'now', DateTimeZone $timeZone = null) { return new DateTime($time, $timeZone !== null ? $timeZone : self::$timeZone); } - - /** - * Return the amount of seconds based on the given month - * - * @param DateTime $dateTime The date and time to use - * - * @return int - */ - public static function getSecondsByMonth(DateTime $dateTime) - { - return (int) $dateTime->format('t') * 24 * 3600; - } - - /** - * Return the amount of seconds based on the given year - * - * @param DateTime $dateTime The date and time to use - * - * @return int - */ - public static function getSecondsByYear(DateTime $dateTime) - { - return (self::isLeapYear($dateTime) ? 366 : 365) * 24 * 3600; - } - - /** - * Return whether the given year is a leap year - * - * @param DateTime $dateTime The date and time to check - * @return bool - */ - public static function isLeapYear(DateTime $dateTime) - { - return $dateTime->format('L') == 1; - } } diff --git a/library/Icinga/Util/File.php b/library/Icinga/Util/File.php index 47b0deb6c..c46025ebc 100644 --- a/library/Icinga/Util/File.php +++ b/library/Icinga/Util/File.php @@ -1,4 +1,5 @@ 0 && $result < 2) { - $pow--; - $result = $value / pow($base, $pow); + $result = $value / pow($base, --$pow); } + return sprintf( '%s%0.2f %s', $sign, $result, - $units[$pow] + $units[abs($pow)] ); } + + /** + * Return the amount of seconds based on the given month + * + * @param DateTime|int $dateTimeOrTimestamp The date and time to use + * + * @return int + */ + public static function secondsByMonth($dateTimeOrTimestamp) + { + if (!($dt = $dateTimeOrTimestamp) instanceof DateTime) { + $dt = new DateTime(); + $dt->setTimestamp($dateTimeOrTimestamp); + } + + return (int) $dt->format('t') * 24 * 3600; + } + + /** + * Return the amount of seconds based on the given year + * + * @param DateTime|int $dateTimeOrTimestamp The date and time to use + * + * @return int + */ + public static function secondsByYear($dateTimeOrTimestamp) + { + return (self::isLeapYear($dateTimeOrTimestamp) ? 366 : 365) * 24 * 3600; + } + + /** + * Return whether the given year is a leap year + * + * @param DateTime|int $dateTimeOrTimestamp The date and time to use + * + * @return bool + */ + public static function isLeapYear($dateTimeOrTimestamp) + { + if (!($dt = $dateTimeOrTimestamp) instanceof DateTime) { + $dt = new DateTime(); + $dt->setTimestamp($dateTimeOrTimestamp); + } + + return $dt->format('L') == 1; + } } diff --git a/library/Icinga/Util/Translator.php b/library/Icinga/Util/Translator.php index 61d667463..733806c72 100644 --- a/library/Icinga/Util/Translator.php +++ b/library/Icinga/Util/Translator.php @@ -29,7 +29,7 @@ namespace Icinga\Util; -use \Exception; +use Exception; /** * Helper class to ease internationalization when using gettext diff --git a/library/Icinga/Web/Controller/ActionController.php b/library/Icinga/Web/Controller/ActionController.php index be0f32756..5b42f8730 100644 --- a/library/Icinga/Web/Controller/ActionController.php +++ b/library/Icinga/Web/Controller/ActionController.php @@ -1,4 +1,5 @@ getParam('view') === 'compact') { + if ($isXhr) { $layout->setLayout('inline'); } @@ -464,3 +465,4 @@ class ActionController extends Zend_Controller_Action return parent::__call($name, $params); } } +// @codeCoverageIgnoreEnd diff --git a/library/Icinga/Web/Controller/BaseConfigController.php b/library/Icinga/Web/Controller/BaseConfigController.php index 0a38f423d..186247f8c 100644 --- a/library/Icinga/Web/Controller/BaseConfigController.php +++ b/library/Icinga/Web/Controller/BaseConfigController.php @@ -1,4 +1,5 @@ view->tabs = ControllerTabCollector::collectControllerTabs('ConfigController'); } } +// @codeCoverageIgnoreEnd diff --git a/library/Icinga/Web/Controller/BasePreferenceController.php b/library/Icinga/Web/Controller/BasePreferenceController.php index e1c330413..5365ff40f 100644 --- a/library/Icinga/Web/Controller/BasePreferenceController.php +++ b/library/Icinga/Web/Controller/BasePreferenceController.php @@ -1,4 +1,5 @@ save($currentPreferences); } } +// @codeCoverageIgnoreEnd diff --git a/library/Icinga/Web/Controller/ControllerTabCollector.php b/library/Icinga/Web/Controller/ControllerTabCollector.php index dded99830..a29e5d57a 100644 --- a/library/Icinga/Web/Controller/ControllerTabCollector.php +++ b/library/Icinga/Web/Controller/ControllerTabCollector.php @@ -1,4 +1,5 @@ sessionId) { $this->sessionId = session_id(); } - return $this->sessionId; - } - /** - * Set whether to inform a user when he is about to discard changes (false, default) or not - * - * @param boolean $bool False to not inform users when they leave modified forms, otherwise true - */ - public function setIgnoreChangeDiscarding($bool) - { - $this->ignoreChangeDiscarding = (boolean) $bool; + return $this->sessionId; } /** @@ -174,7 +148,7 @@ class Form extends Zend_Form * * This method should be used for testing purposes only * - * @param string $sessionId + * @param string $sessionId */ public function setSessionId($sessionId) { @@ -184,7 +158,7 @@ class Form extends Zend_Form /** * Return the HTML element name of the CSRF token field * - * @return string + * @return string */ public function getTokenElementName() { @@ -194,7 +168,7 @@ class Form extends Zend_Form /** * Render the form to HTML * - * @param Zend_View_Interface $view + * @param Zend_View_Interface $view * * @return string */ @@ -210,6 +184,7 @@ class Form extends Zend_Form */ protected function create() { + } /** @@ -217,12 +192,13 @@ class Form extends Zend_Form */ protected function preValidation(array $data) { + } /** * Setter for the request * - * @param Zend_Controller_Request_Abstract $request + * @param Zend_Controller_Request_Abstract $request */ public function setRequest(Zend_Controller_Request_Abstract $request) { @@ -232,7 +208,7 @@ class Form extends Zend_Form /** * Getter for the request * - * @return Zend_Controller_Request_Abstract + * @return Zend_Controller_Request_Abstract */ public function getRequest() { @@ -242,7 +218,7 @@ class Form extends Zend_Form /** * Set the configuration to be used for this form when no preferences are set yet * - * @param IcingaConfig $cfg + * @param IcingaConfig $cfg * * @return self */ @@ -257,20 +233,21 @@ class Form extends Zend_Form * * Returns the set configuration or an empty default one. * - * @return Zend_Config + * @return Zend_Config */ public function getConfiguration() { if ($this->config === null) { $this->config = new Zend_Config(array(), true); } + return $this->config; } /** * Set preferences to be used instead of the one from the user object (used for testing) * - * @param Zend_Config $prefs + * @param Zend_Config $prefs */ public function setUserPreferences($prefs) { @@ -280,13 +257,14 @@ class Form extends Zend_Form /** * Return the preferences of the user or the overwritten ones * - * @return Zend_Config + * @return Zend_Config */ public function getUserPreferences() { if ($this->preferences) { return $this->preferences; } + return $this->getRequest()->getUser()->getPreferences(); } @@ -297,7 +275,6 @@ class Form extends Zend_Form */ public function buildForm() { - if ($this->created === false) { $this->initCsrfToken(); $this->create(); @@ -314,18 +291,15 @@ class Form extends Zend_Form if (!$this->getAction() && $this->getRequest()) { $this->setAction($this->getRequest()->getRequestUri()); } - $this->addElementDecorators(); + $this->created = true; - if (!$this->ignoreChangeDiscarding) { - //$this->setAttrib('data-icinga-component', 'app/form'); - } } } /** * Setter for the cancel label * - * @param string $cancelLabel + * @param string $cancelLabel */ public function setCancelLabel($cancelLabel) { @@ -335,22 +309,23 @@ class Form extends Zend_Form /** * Add cancel button to form */ - private function addCancelButton() + protected function addCancelButton() { - $cancelLabel = new Zend_Form_Element_Reset( - array( - 'name' => 'btn_reset', - 'label' => $this->cancelLabel, - 'class' => 'btn pull-right' + $this->addElement( + new Zend_Form_Element_Reset( + array( + 'name' => 'btn_reset', + 'label' => $this->cancelLabel, + 'class' => 'btn pull-right' + ) ) ); - $this->addElement($cancelLabel); } /** * Setter for the submit label * - * @param string $submitLabel + * @param string $submitLabel */ public function setSubmitLabel($submitLabel) { @@ -360,22 +335,23 @@ class Form extends Zend_Form /** * Add submit button to form */ - private function addSubmitButton() + protected function addSubmitButton() { - $submitButton = new Zend_Form_Element_Submit( - array( - 'name' => 'btn_submit', - 'label' => $this->submitLabel, + $this->addElement( + new Zend_Form_Element_Submit( + array( + 'name' => 'btn_submit', + 'label' => $this->submitLabel + ) ) ); - $this->addElement($submitButton); } /** * Add message to form * - * @param string $message The message to be displayed - * @param int $headingType Whether it should be displayed as heading (1-6) or not (null) + * @param string $message The message to be displayed + * @param int $headingType Whether it should be displayed as heading (1-6) or not (null) */ public function addNote($message, $headingType = null) { @@ -399,17 +375,16 @@ class Form extends Zend_Form * * Enables automatic submission of this form once the user edits specific elements * - * @param array $triggerElements The element names which should auto-submit the form + * @param array $triggerElements The element names which should auto-submit the form * - * @throws ProgrammingError When an element is found which does not yet exist + * @throws ProgrammingError When an element is found which does not yet exist */ - final public function enableAutoSubmit($triggerElements) + public function enableAutoSubmit($triggerElements) { foreach ($triggerElements as $elementName) { $element = $this->getElement($elementName); if ($element !== null) { $element->setAttrib('onchange', '$(this.form).submit();'); - $element->setAttrib('data-icinga-form-autosubmit', true); } else { throw new ProgrammingError( 'You need to add the element "' . $elementName . '" to' . @@ -425,9 +400,7 @@ class Form extends Zend_Form * Ensures that the current request method is POST, that the form was manually submitted and that the data provided * in the request is valid and gets repopulated in case its invalid. * - * @return bool True when the form is submitted and valid, otherwise false - * @see Form::isValid() - * @see Form::isSubmitted() + * @return bool True when the form is submitted and valid, otherwise false */ public function isSubmittedAndValid() { @@ -457,7 +430,7 @@ class Form extends Zend_Form * Per default, this checks whether the button set with the 'setSubmitLabel' method * is being submitted. For custom submission logic, this method must be overwritten * - * @return bool True when the form is marked as submitted, otherwise false + * @return bool True when the form is marked as submitted, otherwise false */ public function isSubmitted() { @@ -466,6 +439,7 @@ class Form extends Zend_Form $checkData = $this->getRequest()->getParams(); $submitted = isset($checkData['btn_submit']); } + return $submitted; } @@ -474,13 +448,13 @@ class Form extends Zend_Form * * This method should be used for testing purposes only * - * @param bool $disabled Set true in order to disable CSRF tokens in this form (default: true), otherwise false - * - * @see tokenDisabled + * @param bool $disabled Set true in order to disable CSRF tokens in + * this form (default: true), otherwise false */ - final public function setTokenDisabled($disabled = true) + public function setTokenDisabled($disabled = true) { $this->tokenDisabled = (boolean) $disabled; + if ($disabled === true) { $this->removeElement($this->tokenElementName); } @@ -489,54 +463,47 @@ class Form extends Zend_Form /** * Add CSRF counter measure field to form */ - final public function initCsrfToken() + public function initCsrfToken() { - if ($this->tokenDisabled || $this->getElement($this->tokenElementName)) { - return; + if (!$this->tokenDisabled && $this->getElement($this->tokenElementName) === null) { + $this->addElement( + 'hidden', + $this->tokenElementName, + array( + 'value' => $this->generateCsrfTokenAsString() + ) + ); } - $this->addElement( - 'hidden', - $this->tokenElementName, - array( - 'value' => $this->generateCsrfTokenAsString(), - 'decorators' => array('ViewHelper') - ) - ); } /** * Test the submitted data for a correct CSRF token * - * @param array $checkData The POST data send by the user + * @param array $checkData The POST data send by the user * * @throws InvalidCSRFTokenException When CSRF Validation fails */ - final public function assertValidCsrfToken(array $checkData) + public function assertValidCsrfToken(array $checkData) { - if ($this->tokenDisabled) { - return; - } - - if (!isset($checkData[$this->tokenElementName]) - || !$this->hasValidCsrfToken($checkData[$this->tokenElementName]) - ) { - throw new InvalidCSRFTokenException(); + if (!$this->tokenDisabled) { + if (!isset($checkData[$this->tokenElementName]) + || !$this->hasValidCsrfToken($checkData[$this->tokenElementName]) + ) { + throw new InvalidCSRFTokenException(); + } } } /** * Check whether the form's CSRF token-field has a valid value * - * @param string $elementValue Value from the form element + * @param string $elementValue Value from the form element * * @return bool */ - private function hasValidCsrfToken($elementValue) + protected function hasValidCsrfToken($elementValue) { - if ($this->getElement($this->tokenElementName) === null) { - return false; - } - if (strpos($elementValue, '|') === false) { + if ($this->getElement($this->tokenElementName) === null || strpos($elementValue, '|') === false) { return false; } @@ -549,26 +516,12 @@ class Form extends Zend_Form return $token === hash('sha256', $this->getSessionId() . $seed); } - /** - * Add element decorators which apply to all elements - * - * Adds `HelpText` decorator - * - * @see HelpText - */ - private function addElementDecorators() - { - foreach ($this->getElements() as $element) { - $element->addDecorator(new HelpText()); - } - } - /** * Generate a new (seed, token) pair * - * @return array + * @return array */ - final public function generateCsrfToken() + public function generateCsrfToken() { $seed = mt_rand(); $hash = hash('sha256', $this->getSessionId() . $seed); @@ -579,9 +532,9 @@ class Form extends Zend_Form /** * Return the string representation of the CSRF seed/token pair * - * @return string + * @return string */ - final public function generateCsrfTokenAsString() + public function generateCsrfTokenAsString() { list ($seed, $token) = $this->generateCsrfToken($this->getSessionId()); return sprintf('%s|%s', $seed, $token); @@ -593,31 +546,29 @@ class Form extends Zend_Form * Additionally, all DtDd tags will be removed and the Bootstrap compatible * BootstrapForm decorator will be added to the elements * - * * @param string|Zend_Form_Element $element String element type, or an object of type Zend_Form_Element * @param string $name The name of the element to add if $element is a string * @param array $options The settings for the element if $element is a string * - * @return Form + * @return self * @see Zend_Form::addElement() */ public function addElement($element, $name = null, $options = null) { parent::addElement($element, $name, $options); - $el = $name ? $this->getElement($name) : $element; - - // Do not add structural elements to invisible elements - // which produces ugly views - if (strpos(strtolower(get_class($el)), 'hidden') !== false) { - $el->setDecorators(array('ViewHelper')); - return $this; - } + $el = $name !== null ? $this->getElement($name) : $element; if ($el) { - $el->removeDecorator('HtmlTag'); - $el->removeDecorator('Label'); - $el->removeDecorator('DtDdWrapper'); - $el->addDecorator(new BootstrapForm()); + if (strpos(strtolower(get_class($el)), 'hidden') !== false) { + // Do not add structural elements to invisible elements which produces ugly views + $el->setDecorators(array('ViewHelper')); + } else { + $el->removeDecorator('HtmlTag'); + $el->removeDecorator('Label'); + $el->removeDecorator('DtDdWrapper'); + $el->addDecorator(new BootstrapForm()); + $el->addDecorator(new HelpText()); + } } return $this; @@ -626,7 +577,9 @@ class Form extends Zend_Form /** * Load the default decorators * - * @return Zend_Form + * Overwrites Zend_Form::loadDefaultDecorators to avoid having the HtmlTag-Decorator added + * + * @return self */ public function loadDefaultDecorators() { @@ -637,8 +590,10 @@ class Form extends Zend_Form $decorators = $this->getDecorators(); if (empty($decorators)) { $this->addDecorator('FormElements') - ->addDecorator('Form'); + //->addDecorator('HtmlTag', array('tag' => 'dl', 'class' => 'zend_form')) + ->addDecorator('Form'); } + return $this; } } diff --git a/library/Icinga/Web/Form/Decorator/BootstrapForm.php b/library/Icinga/Web/Form/Decorator/BootstrapForm.php index 89ad82780..281e94dd7 100644 --- a/library/Icinga/Web/Form/Decorator/BootstrapForm.php +++ b/library/Icinga/Web/Form/Decorator/BootstrapForm.php @@ -1,4 +1,5 @@ '; } } +// @codeCoverageIgnoreEnd diff --git a/library/Icinga/Web/Form/Decorator/ConditionalHidden.php b/library/Icinga/Web/Form/Decorator/ConditionalHidden.php index 305054a88..3964dc7e6 100644 --- a/library/Icinga/Web/Form/Decorator/ConditionalHidden.php +++ b/library/Icinga/Web/Form/Decorator/ConditionalHidden.php @@ -1,4 +1,5 @@ addError(t('Please enter a number.')); + } + + return false; + } } diff --git a/library/Icinga/Web/Form/Element/TriStateCheckbox.php b/library/Icinga/Web/Form/Element/TriStateCheckbox.php index 0271bf236..cc6d935ee 100644 --- a/library/Icinga/Web/Form/Element/TriStateCheckbox.php +++ b/library/Icinga/Web/Form/Element/TriStateCheckbox.php @@ -48,9 +48,9 @@ class TriStateCheckbox extends Zend_Form_Element_Xhtml */ public $helper = 'formTriStateCheckbox'; - public function __construct($spec, $options = null) + public function __construct($name, $options = null) { - parent::__construct($spec, $options); + parent::__construct($name, $options); $this->triStateValidator = new TriStateValidator($this->patterns); $this->addValidator($this->triStateValidator); diff --git a/library/Icinga/Web/Hook.php b/library/Icinga/Web/Hook.php index 915597f86..6f3ffc2f0 100644 --- a/library/Icinga/Web/Hook.php +++ b/library/Icinga/Web/Hook.php @@ -29,9 +29,9 @@ namespace Icinga\Web; +use Exception; use Icinga\Logger\Logger; use Icinga\Exception\ProgrammingError; -use stdClass; /** * Icinga Web Hook registry @@ -79,9 +79,9 @@ class Hook /** * Whether someone registered itself for the given hook name * - * @param string $name One of the predefined hook names + * @param string $name One of the predefined hook names * - * @return bool + * @return bool */ public static function has($name) { @@ -89,72 +89,29 @@ class Hook } /** - * Get the first registered instance for the given hook name + * Create or return an instance of a given hook * - * TODO: Multiple instances are not handled yet * TODO: Should return some kind of a hook interface * - * @param string $name One of the predefined hook names - * - * @return mixed - * @throws ProgrammingError - */ - public static function get($name) - { - if (! self::has($name)) { - return null; - } - if (! array_key_exists($name, self::$instances)) { - $class = self::$hooks[$name]; - try { - $obj = new $class(); - } catch (\Exception $e) { - // TODO: Persist unloading for "some time" or "current session" - Logger::debug( - 'Hook "%s" (%s) failed, will be unloaded: %s', - $name, - $class, - $e->getMessage() - ); - unset(self::$hooks[$name]); - return null; - } - $base_class = 'Icinga\\Web\\Hook\\' . ucfirst($name); - if (! $obj instanceof $base_class) { - throw new ProgrammingError( - sprintf( - '%s is not an instance of %s', - get_class($obj), - $base_class - ) - ); - } - self::$instances[$name] = $obj; - - } - return self::$instances[$name]; - } - - /** - * Create or return an instance of the hook - * - * @param string $name - * @param string $key - * @return stdClass + * @param string $name One of the predefined hook names + * @param string $key The identifier of a specific subtype * + * @return mixed */ public static function createInstance($name, $key) { if (!self::has($name, $key)) { return null; } + if (isset(self::$instances[$name][$key])) { return self::$instances[$name][$key]; } + $class = self::$hooks[$name][$key]; try { $instance = new $class(); - } catch (\Exception $e) { + } catch (Exception $e) { Logger::debug( 'Hook "%s" (%s) (%s) failed, will be unloaded: %s', $name, @@ -162,9 +119,11 @@ class Hook $class, $e->getMessage() ); + // TODO: Persist unloading for "some time" or "current session" unset(self::$hooks[$name][$key]); return null; } + self::assertValidHook($instance, $name); self::$instances[$name][$key] = $instance; return $instance; @@ -173,11 +132,12 @@ class Hook /** * Test for a valid class name * - * @param stdClass $instance - * @param string $name - * @throws ProgrammingError + * @param mixed $instance + * @param string $name + * + * @throws ProgrammingError */ - private static function assertValidHook(&$instance, $name) + private static function assertValidHook($instance, $name) { $base_class = self::$BASE_NS . ucfirst($name); if (!$instance instanceof $base_class) { @@ -194,43 +154,45 @@ class Hook /** * Return all instances of a specific name * - * @param string $name + * @param string $name One of the predefined hook names * - * @return array + * @return array */ public static function all($name) { if (!self::has($name)) { return array(); } + foreach (self::$hooks[$name] as $key => $hook) { if (self::createInstance($name, $key) === null) { return array(); } } + return self::$instances[$name]; } /** * Get the first hook * - * @param string $name + * @param string $name One of the predefined hook names * - * @return stdClass + * @return null|mixed */ public static function first($name) { - return self::createInstance($name, key(self::$hooks[$name])); + if (self::has($name)) { + return self::createInstance($name, key(self::$hooks[$name])); + } } /** * Register your hook * - * @param string $name One of the predefined hook names - * @param string $key - * @param string $class Your class name, must inherit one of the classes - * in the Icinga/Web/Hook folder + * Alias for Hook::registerClass() * + * @see Hook::registerClass() */ public static function register($name, $key, $class) { @@ -240,12 +202,17 @@ class Hook /** * Register a class * - * @param string $name - * @param string $key - * @param string $class + * @param string $name One of the predefined hook names + * @param string $key The identifier of a specific subtype + * @param string $class Your class name, must inherit one of the + * classes in the Icinga/Web/Hook folder */ public static function registerClass($name, $key, $class) { + if (!class_exists($class)) { + throw new ProgrammingError('"' . $class . '" is not an existing class'); + } + if (!isset(self::$hooks[$name])) { self::$hooks[$name] = array(); } @@ -256,23 +223,23 @@ class Hook /** * Register an object * - * @param string $name - * @param string $key - * @param object $object + * @param string $name One of the predefined hook names + * @param string $key The identifier of a specific subtype + * @param object $object The instantiated hook to register * - * @throws ProgrammingError + * @throws ProgrammingError */ public static function registerObject($name, $key, $object) { if (!is_object($object)) { - throw new ProgrammingError('object is not an instantiated class'); + throw new ProgrammingError('"' . $object . '" is not an instantiated class'); } if (!isset(self::$instances[$name])) { self::$instances[$name] = array(); } - self::$instances[$name][$key] =& $object; + self::$instances[$name][$key] = $object; self::registerClass($name, $key, get_class($object)); } } diff --git a/library/Icinga/Web/Hook/Configuration/ConfigurationTabBuilder.php b/library/Icinga/Web/Hook/Configuration/ConfigurationTabBuilder.php index ae772f68e..dad7a37f0 100644 --- a/library/Icinga/Web/Hook/Configuration/ConfigurationTabBuilder.php +++ b/library/Icinga/Web/Hook/Configuration/ConfigurationTabBuilder.php @@ -90,7 +90,7 @@ class ConfigurationTabBuilder { /** @var ConfigurationTab $configTab */ $configTab = null; - foreach (Hook::get(self::HOOK_NAMESPACE) as $configTab) { + foreach (Hook::all(self::HOOK_NAMESPACE) as $configTab) { if (!$configTab instanceof ConfigurationTabInterface) { throw new ProgrammingError('tab not instance of ConfigTabInterface'); } diff --git a/library/Icinga/Web/Hook/Grapher.php b/library/Icinga/Web/Hook/Grapher.php index f5703ba2e..7edaafb05 100644 --- a/library/Icinga/Web/Hook/Grapher.php +++ b/library/Icinga/Web/Hook/Grapher.php @@ -1,4 +1,5 @@ getModuleManager(); + $manager = Icinga::app()->getModuleManager(); + try { $menuConfigs = array(Config::app('menu')); } catch (NotReadableError $e) { Logger::error($e); $menuConfigs = array(); } - try { - foreach ($manager->listEnabledModules() as $moduleName) { - $moduleMenuConfig = Config::module($moduleName, 'menu'); - if ($moduleMenuConfig) { - $menuConfigs[] = $moduleMenuConfig; - } - } + try { + $modules = $manager->listEnabledModules(); } catch (NotReadableError $e) { Logger::error($e); + $modules = array(); } + + foreach ($modules as $moduleName) { + try { + $moduleMenuConfig = Config::module($moduleName, 'menu'); + } catch (NotReadableError $e) { + Logger::error($e); + $moduleMenuConfig = array(); + } + + if (!empty($moduleMenuConfig)) { + $menuConfigs[] = $moduleMenuConfig; + } + } + return $menu->loadMenuItems($menu->flattenConfigs($menuConfigs)); } /** - * Flatten configs into a key-value array + * Flatten configs + * + * @param array $configs An two dimensional array of menu configurations + * + * @return array The flattened config, as key-value array */ public function flattenConfigs(array $configs) { @@ -79,18 +94,23 @@ class Menu extends MenuItem $flattened[$section] = $itemConfig; } } - ksort($flattened); + return $flattened; } /** - * Load menu items from a key-value array + * Load menu items + * + * @param array $items The items to load, as key-value array + * + * @return self */ - public function loadMenuItems(array $flattened) + public function loadMenuItems(array $items) { - foreach ($flattened as $id => $itemConfig) { + foreach ($items as $id => $itemConfig) { $this->addChild($id, $itemConfig); } + return $this; } } diff --git a/library/Icinga/Web/MenuItem.php b/library/Icinga/Web/MenuItem.php index 16fd30548..6f5394ca6 100644 --- a/library/Icinga/Web/MenuItem.php +++ b/library/Icinga/Web/MenuItem.php @@ -13,7 +13,7 @@ class MenuItem * * @type string */ - private $id; + protected $id; /** * Item title @@ -22,7 +22,7 @@ class MenuItem * * @type string */ - private $title; + protected $title; /** * Item priority @@ -31,44 +31,48 @@ class MenuItem * * @type int */ - private $priority = 100; + protected $priority = 100; /** * Item url * * @type string */ - private $url; + protected $url; /** * Item icon path * * @type string */ - private $icon; + protected $icon; /** * Item icon class * * @type string */ - private $iconClass; + protected $iconClass; /** * Item's children * * @type array */ - private $children = array(); - - private $attribs = array(); + protected $children = array(); + /** + * HTML anchor tag attributes + * + * @var array + */ + protected $attribs = array(); /** * Create a new MenuItem * - * @param int $id - * @param object $config + * @param int $id + * @param object $config */ public function __construct($id, $config = null) { @@ -81,7 +85,7 @@ class MenuItem /** * Setter for id * - * @param string $id + * @param string $id * * @return self */ @@ -104,7 +108,7 @@ class MenuItem /** * Setter for title * - * @param string $title + * @param string $title * * @return self */ @@ -114,11 +118,10 @@ class MenuItem return $this; } - /** * Getter for title * - * @return string + * @return string */ public function getTitle() { @@ -128,7 +131,7 @@ class MenuItem /** * Setter for priority * - * @param int $priority + * @param int $priority * * @return self */ @@ -141,7 +144,7 @@ class MenuItem /** * Getter for priority * - * @return int + * @return int */ public function getPriority() { @@ -151,7 +154,7 @@ class MenuItem /** * Setter for URL * - * @param string $url + * @param string $url * * @return self */ @@ -164,7 +167,7 @@ class MenuItem /** * Getter for URL * - * @return string + * @return string */ public function getUrl() { @@ -174,7 +177,7 @@ class MenuItem /** * Setter for icon path * - * @param string $path + * @param string $path * * @return self */ @@ -187,7 +190,7 @@ class MenuItem /** * Getter for icon path * - * @return string + * @return string */ public function getIcon() { @@ -197,7 +200,7 @@ class MenuItem /** * Setter for icon class * - * @param string $iconClass + * @param string $iconClass * * @return self */ @@ -210,7 +213,7 @@ class MenuItem /** * Getter for icon class * - * @return string + * @return string */ public function getIconClass() { @@ -220,7 +223,7 @@ class MenuItem /** * Set the configuration for the item * - * @param object $config + * @param Zend_Config $config */ public function setConfig($config) { @@ -249,18 +252,21 @@ class MenuItem } else { // Submenu item list($parentId, $id) = explode('.', $id, 2); + if ($this->hasChild($parentId)) { $parent = $this->getChild($parentId); } else { $parent = $this->addChild($parentId); } + $menuItem = $parent->addChild($id, $itemConfig); } + return $menuItem; } /** - * Check whether the item has children + * Check whether the item has any children * * @return bool */ @@ -270,10 +276,11 @@ class MenuItem } /** - * Get children sorted + * Get sorted children * * @return array - * @see cmpChildren() + * + * @see MenuItem::cmpChildren() */ public function getChildren() { @@ -282,11 +289,11 @@ class MenuItem } /** - * Whether a given child id exists + * Return whether a given child id exists * * @param string $id * - * @return self|$default + * @return bool */ public function hasChild($id) { @@ -300,20 +307,22 @@ class MenuItem * @param mixed $default * * @return MenuItem + * * @throws ProgrammingError */ public function getChild($id) { - if ($this->hasChild($id)) { - return $this->children[$id]; + if (!$this->hasChild($id)) { + throw new ProgrammingError(sprintf('Trying to get invalid Menu child "%s"', $id)); } - throw new ProgrammingError(sprintf('Trying to get invalid Menu child "%s"', $id)); + + return $this->children[$id]; } /** - * Set HTML a tag attributes + * Set HTML anchor tag attributes * - * @param array $attribs + * @param array $attribs * * @return self */ @@ -324,9 +333,9 @@ class MenuItem } /** - * Get HTML a tag attributes + * Get HTML anchor tag attributes * - * @return array + * @return array */ public function getAttribs() { @@ -336,8 +345,8 @@ class MenuItem /** * Compare children based on priority and title * - * @param MenuItem $a - * @param MenuItem $b + * @param MenuItem $a + * @param MenuItem $b * * @return int */ @@ -346,6 +355,7 @@ class MenuItem if ($a->priority === $b->priority) { return ($a->getTitle() > $b->getTitle()) ? 1 : -1; } + return ($a->priority > $b->priority) ? 1 : -1; } } diff --git a/library/Icinga/Web/Request.php b/library/Icinga/Web/Request.php index 95a5a2a37..1753afa87 100644 --- a/library/Icinga/Web/Request.php +++ b/library/Icinga/Web/Request.php @@ -1,4 +1,5 @@ user; } } +// @codeCoverageIgnoreEnd diff --git a/library/Icinga/Web/Session.php b/library/Icinga/Web/Session.php index ef7887d61..220c6b4f7 100644 --- a/library/Icinga/Web/Session.php +++ b/library/Icinga/Web/Session.php @@ -1,4 +1,5 @@ removed[] = $key; - unset($this->values[$key]); + $this->delete($key); } /** @@ -161,6 +160,17 @@ class SessionNamespace implements IteratorAggregate return isset($this->values[$key]) ? $this->values[$key] : $default; } + /** + * Delete the given value from the session + * + * @param string $key The value's name + */ + public function delete($key) + { + $this->removed[] = $key; + unset($this->values[$key]); + } + /** * Getter for all session values * @@ -180,7 +190,7 @@ class SessionNamespace implements IteratorAggregate public function setAll(array $values, $overwrite = false) { foreach ($values as $key => $value) { - if ($this->get($key) !== $value && !$overwrite) { + if ($this->get($key, $value) !== $value && !$overwrite) { continue; } $this->set($key, $value); diff --git a/library/Icinga/Web/StyleSheet.php b/library/Icinga/Web/StyleSheet.php index 6114643e6..b247f32e9 100644 --- a/library/Icinga/Web/StyleSheet.php +++ b/library/Icinga/Web/StyleSheet.php @@ -1,4 +1,5 @@ getFrontController()->getRequest(); } @@ -135,38 +124,45 @@ class Url * If $params are given, those will be added to the urls parameters * and overwrite any existing parameters * - * @param string $url The string representation of the Url to parse - * @param array $params An array of parameters that should additionally be considered for the Url - * @param Zend_Request $request A request to use instead of the default one + * @param string $url The string representation of the url to parse + * @param array $params An array of parameters that should additionally be considered for the url + * @param Zend_Request $request A request to use instead of the default one * - * @return Url + * @return Url */ public static function fromPath($url, array $params = array(), $request = null) { - $urlObject = new Url(); if ($request === null) { $request = self::getRequest(); } - $urlObject->setBaseUrl($request->getBaseUrl()); - /* - * Fetch fragment manually and remove it from the url, to 'help' the parse_url() function - * parsing the url properly. Otherwise calling the function with a fragment, but without a - * query will cause unpredictable behaviour. - */ - $fragment = self::getUrlFragment($url); - $url = self::stripUrlFragment($url); - - $urlParts = parse_url($url); - - if (isset($urlParts["path"])) { - $urlObject->setPath($urlParts["path"]); + if (!is_string($url)) { + throw new ProgrammingError(sprintf('url "%s" is not a string', $url)); } - if (isset($urlParts["query"])) { + + $urlObject = new Url(); + $baseUrl = $request->getBaseUrl(); + $urlObject->setBaseUrl($baseUrl); + + // Fetch fragment manually and remove it from the url, to 'help' the parse_url() function + // parsing the url properly. Otherwise calling the function with a fragment, but without a + // query will cause unpredictable behaviour. + $url = self::stripUrlFragment($url); + $urlParts = parse_url($url); + if (isset($urlParts['path'])) { + if ($baseUrl !== '' && strpos($urlParts['path'], $baseUrl) === 0) { + $urlObject->setPath(substr($urlParts['path'], strlen($baseUrl))); + } else { + $urlObject->setPath($urlParts['path']); + } + } + if (isset($urlParts['query'])) { $urlParams = array(); - parse_str($urlParts["query"], $urlParams); + parse_str($urlParts['query'], $urlParams); $params = array_merge($urlParams, $params); } + + $fragment = self::getUrlFragment($url); if ($fragment !== '') { $urlObject->setAnchor($fragment); } @@ -178,11 +174,11 @@ class Url /** * Get the fragment of a given url * - * @param $url The url containing the fragment. + * @param string $url The url containing the fragment. * - * @return string The fragment without the '#' + * @return string The fragment without the '#' */ - private static function getUrlFragment($url) + protected static function getUrlFragment($url) { $url = parse_url($url); if (isset($url['fragment'])) { @@ -195,11 +191,11 @@ class Url /** * Remove the fragment-part of a given url * - * @param $url string The url to strip from its fragment + * @param string $url The url to strip from its fragment * - * @return string The url without the fragment. + * @return string The url without the fragment */ - private static function stripUrlFragment($url) + protected static function stripUrlFragment($url) { return preg_replace('/#.*$/', '', $url); } @@ -220,9 +216,9 @@ class Url /** * Return the parameter for the given alias * - * @param string $alias The alias to translate + * @param string $alias The alias to translate * - * @return string The parameter name + * @return string The parameter name */ public function translateAlias($alias) { @@ -230,26 +226,28 @@ class Url } /** - * Overwrite the baseUrl. + * Overwrite the baseUrl * * If an empty Url is given '/' is used as the base * - * @param string $baseUrl The url path to use as the Url Base - * @return $this + * @param string $baseUrl The url path to use as the Url Base + * + * @return self */ public function setBaseUrl($baseUrl) { - if (trim($baseUrl) == '') { + if (($baseUrl = rtrim($baseUrl, '/ ')) === '') { $baseUrl = '/'; } + $this->baseUrl = $baseUrl; return $this; } /** - * Return the baseUrl set for this Url + * Return the baseUrl set for this url * - * @return string + * @return string */ public function getBaseUrl() { @@ -259,19 +257,22 @@ class Url /** * Set the relative path of this url, without query parameters * - * @param string $path The path to set + * @param string $path The path to set + * + * @return self */ public function setPath($path) { - $this->path = $path; + $this->path = ltrim($path, '/'); + return $this; } /** - * Return the relative path of this Url, without query parameters + * Return the relative path of this url, without query parameters * * If you want the relative path with query parameters use getRelativeUrl * - * @return string + * @return string */ public function getPath() { @@ -281,36 +282,38 @@ class Url /** * Return the relative url with query parameters as a string * - * @return string + * @return string */ public function getRelativeUrl() { if (empty($this->params)) { - return ltrim($this->path, '/') . $this->anchor; + return $this->path . $this->anchor; } + $params = array(); foreach ($this->params as $param => $value) { $params[$this->translateAlias($param)] = $value; } - return ltrim($this->path, '/') . '?' . http_build_query($params, '', '&') . $this->anchor; + + return $this->path . '?' . http_build_query($params, '', '&') . $this->anchor; } /** * Return the absolute url with query parameters as a string * - * @return string + * @return string */ public function getAbsoluteUrl() { - $url = $this->getRelativeUrl(); - return preg_replace('/\/{2,}/', '/', '/'.$this->baseUrl.'/'.$url); + return $this->baseUrl . ($this->baseUrl !== '/' ? '/' : '') . $this->getRelativeUrl(); } /** * Add a set of parameters to the query part if the keys don't exist yet * - * @param array $params The parameters to add - * @return self + * @param array $params The parameters to add + * + * @return self */ public function addParams(array $params) { @@ -321,8 +324,9 @@ class Url /** * Set and overwrite the given params if one if the same key already exists * - * @param array $params The parameters to set - * @return self + * @param array $params The parameters to set + * + * @return self */ public function overwriteParams(array $params) { @@ -333,8 +337,9 @@ class Url /** * Overwrite the parameters used in the query part * - * @param array $params The new parameters to use for the query part - * @return $this + * @param array $params The new parameters to use for the query part + * + * @return self */ public function setParams(array $params) { @@ -345,7 +350,7 @@ class Url /** * Return all parameters that will be used in the query part * - * @return array An associative key => value array containing all parameters + * @return array An associative key => value array containing all parameters */ public function getParams() { @@ -353,48 +358,52 @@ class Url } /** - * Return true if the Urls' query parameter with $key exists, otherwise false + * Return true if a urls' query parameter exists, otherwise false * - * @param $key A key to check for existing - * @return bool + * @param string $param The url parameter name to check + * + * @return bool */ - public function hasParam($key) + public function hasParam($param) { - return array_key_exists($key, $this->params); + return array_key_exists($param, $this->params); } /** - * Return the Url's query parameter with the name $key if exists, otherwise $default + * Return a url's query parameter if it exists, otherwise $default * - * @param $key A query parameter name to return if existing - * @param mixed $default A value to return when the parameter doesn't exist - * @return mixed + * @param string $param A query parameter name to return if existing + * @param mixed $default A value to return when the parameter doesn't exist + * + * @return mixed */ - public function getParam($key, $default = null) + public function getParam($param, $default = null) { - if ($this->hasParam($key)) { - return $this->params[$key]; + if ($this->hasParam($param)) { + return $this->params[$param]; } + return $default; } /** - * Set a single parameter $key, overwriting existing ones with the same key + * Set a single parameter, overwriting any existing one with the same name * - * @param string $key A string representing the key of the parameter - * @param array|string $value An array or string to set as the parameter value - * @return $this + * @param string $param The query parameter name + * @param array|string $value An array or string to set as the parameter value + * + * @return self */ - public function setParam($key, $value) + public function setParam($param, $value) { - $this->params[$key] = $value; + $this->params[$param] = $value; return $this; } /** * Set the url anchor-part * - * @param $anchor The site's anchor string without the '#' + * @param string $anchor The site's anchor string without the '#' * * @return self */ @@ -407,9 +416,9 @@ class Url /** * Remove provided key (if string) or keys (if array of string) from the query parameter array * - * @param string|array $keyOrArrayOfKeys An array of strings or a string representing the key(s) + * @param string|array $keyOrArrayOfKeys An array of strings or a string representing the key(s) * of the parameters to be removed - * @return $this + * @return self */ public function remove($keyOrArrayOfKeys) { @@ -418,45 +427,51 @@ class Url } else { $this->removeKey($keyOrArrayOfKeys); } + return $this; } /** * Remove all parameters with the parameter names in the $keys array * - * @param array $keys An array of strings containing parameter names to remove - * @return $this + * @param array $keys An array of strings containing parameter names to remove + * + * @return self */ public function removeKeys(array $keys) { foreach ($keys as $key) { $this->removeKey($key); } + return $this; } /** * Remove a single parameter with the provided parameter name $key * - * @param string $key The key to remove from the Url - * @return $this + * @param string $key The key to remove from the url + * + * @return self */ public function removeKey($key) { if (isset($this->params[$key])) { unset($this->params[$key]); } + return $this; } /** * Return a copy of this url without the parameter given * - * The argument can either a single query parameter name or an array of parameter names to + * The argument can be either a single query parameter name or an array of parameter names to * remove from the query list * - * @param string|array $keyOrArrayOfKeys A single string or an array containing parameter names - * @return Url + * @param string|array $keyOrArrayOfKeys A single string or an array containing parameter names + * + * @return Url */ public function getUrlWithout($keyOrArrayOfKeys) { @@ -467,7 +482,8 @@ class Url /** * Alias for @see Url::getAbsoluteUrl() - * @return mixed + * + * @return string */ public function __toString() { diff --git a/library/Icinga/Web/View.php b/library/Icinga/Web/View.php index 83686b5ab..67995f8c7 100644 --- a/library/Icinga/Web/View.php +++ b/library/Icinga/Web/View.php @@ -1,4 +1,5 @@ renderVertical($grid); } } +// @codeCoverageIgnoreEnd diff --git a/library/Icinga/Web/Widget/Chart/InlinePie.php b/library/Icinga/Web/Widget/Chart/InlinePie.php index 6c9d1196e..c2ff99314 100644 --- a/library/Icinga/Web/Widget/Chart/InlinePie.php +++ b/library/Icinga/Web/Widget/Chart/InlinePie.php @@ -1,4 +1,5 @@ + EOD; /** @@ -118,10 +120,13 @@ EOD; * The labels to be displayed in the pie-chart * * @param null $labels + * + * @return $this */ public function setLabels($labels = null) { $this->url->setParam('labels', implode(',', $labels)); + return $this; } /** @@ -227,4 +232,4 @@ EOD; return $template; } } - +// @codeCoverageIgnoreEnd diff --git a/library/Icinga/Web/Widget/Dashboard.php b/library/Icinga/Web/Widget/Dashboard.php index f148dbf83..107e4c0a6 100644 --- a/library/Icinga/Web/Widget/Dashboard.php +++ b/library/Icinga/Web/Widget/Dashboard.php @@ -31,14 +31,11 @@ namespace Icinga\Web\Widget; use Icinga\Application\Icinga; use Icinga\Application\Config as IcingaConfig; -use Icinga\Logger\Logger; -use Icinga\Exception\ConfigurationError; use Icinga\Exception\ProgrammingError; use Icinga\Web\Widget\AbstractWidget; use Icinga\Web\Widget\Dashboard\Pane; use Icinga\Web\Widget\Dashboard\Component as DashboardComponent; use Icinga\Web\Url; -use Zend_View_Abstract; /** * Dashboards display multiple views on a single page @@ -115,46 +112,6 @@ class Dashboard extends AbstractWidget return $this->tabs; } - /** - * Store the current dashboard with all it's panes and components to the given file (or the default one if none is - * given) - * - * - * @param string $file The filename to store this dashboard as an ini - * - * @return $this - * @throws \Icinga\Exception\ConfigurationError If persisting fails, details are written to the log - * - */ - public function store($file = null) - { - if ($file === null) { - $file = IcingaConfig::app('dashboard/dashboard')->getConfigFile(); - } - - if (!is_writable($file)) { - Logger::error('Tried to persist dashboard to %s, but path is not writeable', $file); - throw new ConfigurationError('Can\'t persist dashboard'); - } - // make sure empty dashboards don't cause errors - $iniString = trim($this->toIni()); - if (!$iniString) { - $iniString = ' '; - } - if (!@file_put_contents($file, $iniString)) { - $error = error_get_last(); - if ($error == null) { - $error = 'Unknown Error'; - } else { - $error = $error['message']; - } - Logger::error('Tried to persist dashboard to %s, but got error: %s', $file, $error); - throw new ConfigurationError('Can\'t Persist Dashboard'); - } else { - return $this; - } - } - /** * Populate this dashboard via the given configuration file * @@ -352,17 +309,18 @@ class Dashboard extends AbstractWidget } /** - * Return the ini string describing this dashboard + * Return this dashboard's structure as array * - * @return string + * @return array */ - public function toIni() + public function toArray() { - $ini = ''; + $array = array(); foreach ($this->panes as $pane) { - $ini .= $pane->toIni(); + $array += $pane->toArray(); } - return $ini; + + return $array; } /** diff --git a/library/Icinga/Web/Widget/Dashboard/Component.php b/library/Icinga/Web/Widget/Dashboard/Component.php index 10fbc640d..6b355e3e0 100644 --- a/library/Icinga/Web/Widget/Dashboard/Component.php +++ b/library/Icinga/Web/Widget/Dashboard/Component.php @@ -76,7 +76,7 @@ class Component extends AbstractWidget

{REMOVE}{TITLE}

EOD; @@ -144,17 +144,18 @@ EOD; } /** - * Return this component in a suitable format and encoding for ini files + * Return this component's structure as array * - * @return string + * @return array */ - public function toIni() + public function toArray() { - $ini = 'url = "' . $this->url->getRelativeUrl() . '"' . PHP_EOL; - foreach ($this->url->getParams() as $key => $val) { - $ini .= $key.' = "' . $val . '"' . PHP_EOL; + $array = array('url' => $this->url->getPath()); + foreach ($this->url->getParams() as $key => $value) { + $array[$key] = $value; } - return $ini; + + return $array; } /** @@ -165,8 +166,11 @@ EOD; $view = $this->view(); $url = clone($this->url); $url->addParams(array('view' => 'compact')); + $iframeUrl = clone($url); + $iframeUrl->addParams(array('_render' => 'iframe')); $html = str_replace('{URL}', $url, $this->template); + $html = str_replace('{IFRAME_URL}', $iframeUrl, $html); $html = str_replace('{FULL_URL}', $url->getUrlWithout('view'), $html); $html = str_replace('{REMOVE_BTN}', $this->getRemoveForm($view), $html); $html = str_replace('{TITLE}', $view->escape($this->getTitle()), $html); @@ -181,6 +185,8 @@ EOD; */ protected function getRemoveForm() { + // TODO: temporarily disabled, should point to a form asking for confirmal + return ''; $removeUrl = Url::fromPath( '/dashboard/removecomponent', array( diff --git a/library/Icinga/Web/Widget/Dashboard/Pane.php b/library/Icinga/Web/Widget/Dashboard/Pane.php index d9d943fab..24b43040d 100644 --- a/library/Icinga/Web/Widget/Dashboard/Pane.php +++ b/library/Icinga/Web/Widget/Dashboard/Pane.php @@ -29,15 +29,13 @@ namespace Icinga\Web\Widget\Dashboard; -use Icinga\Exception\ConfigurationError; -use Icinga\Exception\ProgrammingError; -use Icinga\Web\Widget\AbstractWidget; use Zend_Config; -use Zend_View_Abstract; +use Icinga\Web\Widget\AbstractWidget; +use Icinga\Exception\ProgrammingError; +use Icinga\Exception\ConfigurationError; /** * A pane, displaying different Dashboard components - * */ class Pane extends AbstractWidget { @@ -190,25 +188,18 @@ class Pane extends AbstractWidget } /** - * Return the ini representation of this pane as a string + * Return the this pane's structure as array * - * @return string + * @return array */ - public function toIni() + public function toArray() { - if (empty($this->components)) { - return ''; - } - $ini = '[' . $this->getName() . ']' . PHP_EOL. - 'title = "' . $this->getTitle() . '"' . PHP_EOL; - + $array = array($this->getName() => array('title' => $this->getTitle())); foreach ($this->components as $title => $component) { - // component header - $ini .= '[' . $this->getName() . '.' . $title . ']' . PHP_EOL; - // component content - $ini .= $component->toIni() . PHP_EOL; + $array[$this->getName() . ".$title"] = $component->toArray(); } - return $ini; + + return $array; } /** diff --git a/library/Icinga/Web/Widget/FilterBadgeRenderer.php b/library/Icinga/Web/Widget/FilterBadgeRenderer.php index 8bf0bced9..d5fdaf310 100644 --- a/library/Icinga/Web/Widget/FilterBadgeRenderer.php +++ b/library/Icinga/Web/Widget/FilterBadgeRenderer.php @@ -1,4 +1,5 @@ nodeToBadge(Tree::normalizeTree($this->tree->root)); } } +// @codeCoverageIgnoreEnd diff --git a/library/Icinga/Web/Widget/FilterBox.php b/library/Icinga/Web/Widget/FilterBox.php index 3059197d1..1c986ded2 100644 --- a/library/Icinga/Web/Widget/FilterBox.php +++ b/library/Icinga/Web/Widget/FilterBox.php @@ -1,4 +1,5 @@ getElement('query')->setDecorators(array('ViewHelper')); $badges = new FilterBadgeRenderer($this->initialFilter); - $form->setIgnoreChangeDiscarding(true); return '
' . $badges->render($view) . '
' . $form; $html = str_replace('{{FORM}}', $form->render($view), self::$TPL); $html = '
' . $html . '
'; return str_replace('{{BADGES}}', $badges->render($view), $html); } } +// @codeCoverageIgnoreEnd diff --git a/library/Icinga/Web/Widget/SortBox.php b/library/Icinga/Web/Widget/SortBox.php index a3ee99a8f..97e528784 100644 --- a/library/Icinga/Web/Widget/SortBox.php +++ b/library/Icinga/Web/Widget/SortBox.php @@ -1,4 +1,5 @@ not show. - * */ public function __construct(array $disabled = array()) { - foreach ($this->supportedTypes as $type => $values) { - if (in_array($type, $disabled)) { - continue; + foreach ($this->supportedTypes as $type => $tabConfig) { + if (!in_array($type, $disabled)) { + $tabConfig['url'] = Url::fromRequest(); + $tabConfig['tagParams'] = array( + 'target' => '_blank' + ); + $this->tabs[] = new Tab($tabConfig); } - if (!isset($this->supportedTypes[$type])) { - Logger::error('Tried to add an unsupported output type: %s', $type); - continue; - } - $tabConfig = $this->supportedTypes[$type]; - $tabConfig['url'] = Url::fromRequest(); - $tabConfig['tagParams'] = array( - 'target' => '_blank' - ); - $this->tabs[] = new Tab($tabConfig); } } @@ -132,3 +125,4 @@ class OutputFormat implements Tabextension } } } +// @codeCoverageIgnoreEnd diff --git a/library/Icinga/Web/Widget/Tabextension/Tabextension.php b/library/Icinga/Web/Widget/Tabextension/Tabextension.php index 2cf2c7b45..5d51379ef 100644 --- a/library/Icinga/Web/Widget/Tabextension/Tabextension.php +++ b/library/Icinga/Web/Widget/Tabextension/Tabextension.php @@ -29,7 +29,7 @@ namespace Icinga\Web\Widget\Tabextension; -use \Icinga\Web\Widget\Tabs; +use Icinga\Web\Widget\Tabs; /** * Tabextension interface that allows to extend a tabbar with reusable components diff --git a/modules/monitoring/application/clicommands/ListCommand.php b/modules/monitoring/application/clicommands/ListCommand.php index a07601871..4ddf2e781 100644 --- a/modules/monitoring/application/clicommands/ListCommand.php +++ b/modules/monitoring/application/clicommands/ListCommand.php @@ -263,9 +263,9 @@ class ListCommand extends Command try { $pset = PerfdataSet::fromString($row->service_perfdata); $perfs = array(); - foreach ($pset->getAll() as $perfName => $p) { + foreach ($pset as $perfName => $p) { if ($percent = $p->getPercentage()) { - if ($percent < 0 || $percent > 300) { + if ($percent < 0 || $percent > 100) { continue; } $perfs[] = ' ' diff --git a/modules/monitoring/application/controllers/ConfigController.php b/modules/monitoring/application/controllers/ConfigController.php index f10ecf826..5bd6b3b3c 100644 --- a/modules/monitoring/application/controllers/ConfigController.php +++ b/modules/monitoring/application/controllers/ConfigController.php @@ -263,19 +263,19 @@ class Monitoring_ConfigController extends BaseConfigController { */ private function writeConfiguration($config, $file) { + $target = IcingaConfig::module('monitoring', $file)->getConfigFile(); + $writer = new PreservingIniWriter(array('filename' => $target, 'config' => $config)); + try { - $writer = new PreservingIniWriter(array( - 'filename' => IcingaConfig::module('monitoring', $file)->getConfigFile(), - 'config' => $config - )); $writer->write(); - return true; } catch (Exception $exc) { $this->view->exceptionMessage = $exc->getMessage(); $this->view->iniConfigurationString = $writer->render(); - $this->view->file = IcingaConfig::module('monitoring', $file)->getConfigFile(); + $this->view->file = $target; return false; } + + return true; } /** diff --git a/modules/monitoring/application/controllers/ListController.php b/modules/monitoring/application/controllers/ListController.php index 89b84873f..8005e8713 100644 --- a/modules/monitoring/application/controllers/ListController.php +++ b/modules/monitoring/application/controllers/ListController.php @@ -74,7 +74,7 @@ class Monitoring_ListController extends Controller public function init() { $this->backend = Backend::createBackend($this->_getParam('backend')); - $this->view->grapher = Hook::get('grapher'); + $this->view->grapher = Hook::first('grapher'); $this->createTabs(); $this->view->activeRowHref = $this->getParam('detail'); $this->view->compact = ($this->_request->getParam('view') === 'compact'); @@ -113,6 +113,7 @@ class Monitoring_ListController extends Controller ))->activate('hosts'); $this->setAutorefreshInterval(10); + $this->view->query = $this->_request->getQuery(); $this->view->title = 'Host Status'; $this->compactView = 'hosts-compact'; $dataview = HostStatusView::fromRequest( @@ -176,6 +177,7 @@ class Monitoring_ListController extends Controller } } $this->view->title = 'Service Status'; + $this->view->query = $this->_request->getQuery(); $this->setAutorefreshInterval(10); $query = $this->fetchServices(); $this->applyRestrictions($query); diff --git a/modules/monitoring/application/controllers/MultiController.php b/modules/monitoring/application/controllers/MultiController.php index 2599912c3..00dcb7ed2 100644 --- a/modules/monitoring/application/controllers/MultiController.php +++ b/modules/monitoring/application/controllers/MultiController.php @@ -31,12 +31,12 @@ use \Icinga\Web\Form; use \Icinga\Web\Controller\ActionController; use \Icinga\Web\Widget\Tabextension\OutputFormat; use \Icinga\Module\Monitoring\Backend; -use \Icinga\Module\Monitoring\Object\Host; -use \Icinga\Module\Monitoring\Object\Service; +use \Icinga\Data\BaseQuery; +use \Icinga\Web\Widget\Chart\InlinePie; use \Icinga\Module\Monitoring\Form\Command\MultiCommandFlagForm; -use \Icinga\Module\Monitoring\DataView\HostStatus as HostStatusView; +use \Icinga\Module\Monitoring\DataView\HostStatus as HostStatusView; use \Icinga\Module\Monitoring\DataView\ServiceStatus as ServiceStatusView; -use \Icinga\Module\Monitoring\DataView\Comment as CommentView; +use \Icinga\Module\Monitoring\DataView\Comment as CommentView; /** * Displays aggregations collections of multiple objects. @@ -45,18 +45,17 @@ class Monitoring_MultiController extends ActionController { public function init() { - $this->view->queries = $this->getDetailQueries(); $this->backend = Backend::createBackend($this->_getParam('backend')); $this->createTabs(); } public function hostAction() { - $filters = $this->view->queries; - $errors = array(); + $multiFilter = $this->getAllParamsAsArray(); + $errors = array(); - // Hosts - $backendQuery = HostStatusView::fromRequest( + // Fetch Hosts + $hostQuery = HostStatusView::fromRequest( $this->_request, array( 'host_name', @@ -64,58 +63,154 @@ class Monitoring_MultiController extends ActionController 'host_unhandled_service_count', 'host_passive_checks_enabled', 'host_obsessing', + 'host_state', 'host_notifications_enabled', 'host_event_handler_enabled', 'host_flap_detection_enabled', - 'host_active_checks_enabled' + 'host_active_checks_enabled', + + // columns intended for filter-request + 'host_problem', + 'host_handled' ) )->getQuery(); - if ($this->_getParam('host') !== '*') { - $this->applyQueryFilter($backendQuery, $filters); - } - $hosts = $backendQuery->fetchAll(); + $this->applyQueryFilter($hostQuery, $multiFilter); + $hosts = $hostQuery->fetchAll(); - // Comments - $commentQuery = CommentView::fromRequest($this->_request)->getQuery(); - $this->applyQueryFilter($commentQuery, $filters); - $comments = array_keys($this->getUniqueValues($commentQuery->fetchAll(), 'comment_id')); + // Fetch comments + $commentQuery = $this->applyQueryFilter( + CommentView::fromParams(array('backend' => $this->_request->getParam('backend')))->getQuery(), + $multiFilter, + 'comment_host' + ); + $comments = array_keys($this->getUniqueValues($commentQuery->fetchAll(), 'comment_internal_id')); - $this->view->objects = $this->view->hosts = $hosts; - $this->view->problems = $this->getProblems($hosts); - $this->view->comments = isset($comments) ? $comments : $this->getComments($hosts); + // Populate view + $this->view->objects = $this->view->hosts = $hosts; + $this->view->problems = $this->getProblems($hosts); + $this->view->comments = isset($comments) ? $comments : $this->getComments($hosts); $this->view->hostnames = $this->getProperties($hosts, 'host_name'); $this->view->downtimes = $this->getDowntimes($hosts); - $this->view->errors = $errors; + $this->view->errors = $errors; + $this->view->states = $this->countStates($hosts, 'host', 'host_name'); + $this->view->pie = $this->createPie($this->view->states, $this->view->getHelper('MonitoringState')->getHostStateColors()); + // need the query content to list all hosts + $this->view->query = $this->_request->getQuery(); + + // Handle configuration changes $this->handleConfigurationForm(array( 'host_passive_checks_enabled' => 'Passive Checks', - 'host_active_checks_enabled' => 'Active Checks', - 'host_obsessing' => 'Obsessing', - 'host_notifications_enabled' => 'Notifications', - 'host_event_handler_enabled' => 'Event Handler', - 'host_flap_detection_enabled' => 'Flap Detection' + 'host_active_checks_enabled' => 'Active Checks', + 'host_notifications_enabled' => 'Notifications', + 'host_event_handler_enabled' => 'Event Handler', + 'host_flap_detection_enabled' => 'Flap Detection', + 'host_obsessing' => 'Obsessing' )); - $this->view->form->setAction('/icinga2-web/monitoring/multi/host'); } - /** - * @param $backendQuery BaseQuery The query to apply the filter to - * @param $filter array Containing the filter expressions from the request - */ - private function applyQueryFilter($backendQuery, $filter) + + public function serviceAction() { + $multiFilter = $this->getAllParamsAsArray(); + $errors = array(); + $backendQuery = ServiceStatusView::fromRequest( + $this->_request, + array( + 'host_name', + 'host_state', + 'service_description', + 'service_handled', + 'service_state', + 'service_in_downtime', + 'service_passive_checks_enabled', + 'service_notifications_enabled', + 'service_event_handler_enabled', + 'service_flap_detection_enabled', + 'service_active_checks_enabled', + 'service_obsessing', + + // also accept all filter-requests from ListView + 'service_problem', + 'service_severity', + 'service_last_check', + 'service_state_type', + 'host_severity', + 'host_address', + 'host_last_check' + ) + )->getQuery(); + + $this->applyQueryFilter($backendQuery, $multiFilter); + $services = $backendQuery->fetchAll(); + + // Comments + $commentQuery = $this->applyQueryFilter( + CommentView::fromParams(array('backend' => $this->_request->getParam('backend')))->getQuery(), + $multiFilter, + 'comment_host', + 'comment_service' + ); + $comments = array_keys($this->getUniqueValues($commentQuery->fetchAll(), 'comment_internal_id')); + + // populate the view + $this->view->objects = $this->view->services = $services; + $this->view->problems = $this->getProblems($services); + $this->view->comments = isset($comments) ? $comments : $this->getComments($services); + $this->view->hostnames = $this->getProperties($services, 'host_name'); + $this->view->servicenames = $this->getProperties($services, 'service_description'); + $this->view->downtimes = $this->getDowntimes($services); + $this->view->service_states = $this->countStates($services, 'service'); + $this->view->host_states = $this->countStates($services, 'host', 'host_name'); + $this->view->service_pie = $this->createPie($this->view->service_states, $this->view->getHelper('MonitoringState')->getServiceStateColors()); + $this->view->host_pie = $this->createPie($this->view->host_states, $this->view->getHelper('MonitoringState')->getHostStateColors()); + $this->view->errors = $errors; + + // need the query content to list all hosts + $this->view->query = $this->_request->getQuery(); + + $this->handleConfigurationForm(array( + 'service_passive_checks_enabled' => 'Passive Checks', + 'service_active_checks_enabled' => 'Active Checks', + 'service_notifications_enabled' => 'Notifications', + 'service_event_handler_enabled' => 'Event Handler', + 'service_flap_detection_enabled' => 'Flap Detection', + 'service_obsessing' => 'Obsessing', + )); + } + + + /** + * Apply the query-filter received + * + * @param $backendQuery BaseQuery The query to apply the filter to + * @param $filter array Containing the queries of the current request, converted into an + * array-structure. + * @param $hostColumn string The name of the host-column in the BaseQuery, defaults to 'host_name' + * @param $serviceColumn string The name of the service-column in the BaseQuery, defaults to 'service-description' + * + * @return BaseQuery The given BaseQuery + */ + private function applyQueryFilter( + BaseQuery $backendQuery, + array $filter, + $hostColumn = 'host_name', + $serviceColumn = 'service_description' + ) { // fetch specified hosts foreach ($filter as $index => $expr) { + // Every query entry must define at least the host. if (!array_key_exists('host', $expr)) { $errors[] = 'Query ' . $index . ' misses property host.'; continue; } // apply filter expressions from query - $backendQuery->orWhere('host_name', $expr['host']); + $backendQuery->orWhere($hostColumn, $expr['host']); if (array_key_exists('service', $expr)) { - $backendQuery->andWhere('service_description', $expr['service']); + $backendQuery->andWhere($serviceColumn, $expr['service']); } } + return $backendQuery; } /** @@ -134,23 +229,25 @@ class Monitoring_MultiController extends ActionController if (is_array($value)) { $unique[$value[$key]] = $value[$key]; } else { - $unique[$value->{$key}] = $value->{$key}; + $unique[$value->$key] = $value->$key; } } return $unique; } /** - * Get the numbers of problems in the given objects + * Get the numbers of problems of the given objects * - * @param $object array The hosts or services + * @param $objects The objects containing the problems + * + * @return int The problem count */ private function getProblems($objects) { $problems = 0; foreach ($objects as $object) { if (property_exists($object, 'host_unhandled_service_count')) { - $problems += $object->{'host_unhandled_service_count'}; + $problems += $object->host_unhandled_service_count; } else if ( property_exists($object, 'service_handled') && !$object->service_handled && @@ -162,6 +259,34 @@ class Monitoring_MultiController extends ActionController return $problems; } + private function countStates($objects, $type = 'host', $unique = null) + { + $known = array(); + if ($type === 'host') { + $states = array_fill_keys($this->view->getHelper('MonitoringState')->getHostStateNames(), 0); + } else { + $states = array_fill_keys($this->view->getHelper('MonitoringState')->getServiceStateNames(), 0); + } + foreach ($objects as $object) { + if (isset($unique)) { + if (array_key_exists($object->$unique, $known)) { + continue; + } + $known[$object->$unique] = true; + } + $states[$this->view->monitoringState($object, $type)]++; + } + return $states; + } + + private function createPie($states, $colors) + { + $chart = new InlinePie(array_values($states), $colors); + $chart->setLabels(array_keys($states))->setHeight(100)->setWidth(100); + return $chart; + } + + private function getComments($objects) { $unique = array(); @@ -175,7 +300,7 @@ class Monitoring_MultiController extends ActionController { $objectnames = array(); foreach ($objects as $object) { - $objectnames[] = $object->{$property}; + $objectnames[] = $object->$property; } return $objectnames; } @@ -195,54 +320,6 @@ class Monitoring_MultiController extends ActionController return $downtimes; } - public function serviceAction() - { - $filters = $this->view->queries; - $errors = array(); - - $backendQuery = ServiceStatusView::fromRequest( - $this->_request, - array( - 'host_name', - 'service_description', - 'service_handled', - 'service_state', - 'service_in_downtime', - - 'service_passive_checks_enabled', - 'service_notifications_enabled', - 'service_event_handler_enabled', - 'service_flap_detection_enabled', - 'service_active_checks_enabled' - ) - )->getQuery(); - if ($this->_getParam('service') !== '*' && $this->_getParam('host') !== '*') { - $this->applyQueryFilter($backendQuery, $filters); - } - $services = $backendQuery->fetchAll(); - - // Comments - $commentQuery = CommentView::fromRequest($this->_request)->getQuery(); - $this->applyQueryFilter($commentQuery, $filters); - $comments = array_keys($this->getUniqueValues($commentQuery->fetchAll(), 'comment_id')); - - $this->view->objects = $this->view->services = $services; - $this->view->problems = $this->getProblems($services); - $this->view->comments = isset($comments) ? $comments : $this->getComments($services); - $this->view->hostnames = $this->getProperties($services, 'host_name'); - $this->view->servicenames = $this->getProperties($services, 'service_description'); - $this->view->downtimes = $this->getDowntimes($services); - $this->view->errors = $errors; - - $this->handleConfigurationForm(array( - 'service_passive_checks_enabled' => 'Passive Checks', - 'service_active_checks_enabled' => 'Active Checks', - 'service_notifications_enabled' => 'Notifications', - 'service_event_handler_enabled' => 'Event Handler', - 'service_flap_detection_enabled' => 'Flap Detection' - )); - $this->view->form->setAction('/icinga2-web/monitoring/multi/service'); - } /** * Handle the form to edit configuration flags. @@ -252,6 +329,7 @@ class Monitoring_MultiController extends ActionController private function handleConfigurationForm(array $flags) { $this->view->form = $form = new MultiCommandFlagForm($flags); + $this->view->formElements = $form->buildCheckboxes(); $form->setRequest($this->_request); if ($form->isSubmittedAndValid()) { // TODO: Handle commands @@ -263,28 +341,37 @@ class Monitoring_MultiController extends ActionController } /** - * Fetch all requests from the 'detail' parameter. + * "Flips" the structure of the objects created by _getAllParams * - * @return array An array of request that contain - * the filter arguments as properties. + * Regularly, _getAllParams would return queries like host[0]=value1&service[0]=value2 as + * two entirely separate arrays. Instead, we want it as one single array, containing one single object + * for each index, containing all of its members as keys. + * + * @return array An array of all query parameters (See example above) + * + * array(
+ * 0 => array(host => value1, service => value2),
+ * ...
+ * ) + *
*/ - private function getDetailQueries() + private function getAllParamsAsArray() { $details = $this->_getAllParams(); - $objects = array(); + $queries = array(); foreach ($details as $property => $values) { if (!is_array($values)) { continue; } foreach ($values as $index => $value) { - if (!array_key_exists($index, $objects)) { - $objects[$index] = array(); + if (!array_key_exists($index, $queries)) { + $queries[$index] = array(); } - $objects[$index][$property] = $value; + $queries[$index][$property] = $value; } } - return $objects; + return $queries; } /** diff --git a/modules/monitoring/application/controllers/TimelineController.php b/modules/monitoring/application/controllers/TimelineController.php index 47917995d..48efe0845 100644 --- a/modules/monitoring/application/controllers/TimelineController.php +++ b/modules/monitoring/application/controllers/TimelineController.php @@ -6,6 +6,7 @@ use \DateTime; use \DateInterval; use \Zend_Config; use Icinga\Web\Url; +use Icinga\Util\Format; use Icinga\Application\Config; use Icinga\Util\DateTimeFactory; use Icinga\Web\Controller\ActionController; @@ -170,13 +171,13 @@ class Monitoring_TimelineController extends ActionController case '1m': $dateCopy = clone $dateTime; for ($i = 0; $i < 6; $i++) { - $dateCopy->sub(new DateInterval('PT' . DateTimeFactory::getSecondsByMonth($dateCopy) . 'S')); + $dateCopy->sub(new DateInterval('PT' . Format::secondsByMonth($dateCopy) . 'S')); } return $dateCopy->add(new DateInterval('PT1S'))->diff($dateTime); case '1y': $dateCopy = clone $dateTime; for ($i = 0; $i < 4; $i++) { - $dateCopy->sub(new DateInterval('PT' . DateTimeFactory::getSecondsByYear($dateCopy) . 'S')); + $dateCopy->sub(new DateInterval('PT' . Format::secondsByYear($dateCopy) . 'S')); } return $dateCopy->add(new DateInterval('PT1S'))->diff($dateTime); default: diff --git a/modules/monitoring/application/forms/Command/MultiCommandFlagForm.php b/modules/monitoring/application/forms/Command/MultiCommandFlagForm.php index 593e471f9..3b30574ff 100644 --- a/modules/monitoring/application/forms/Command/MultiCommandFlagForm.php +++ b/modules/monitoring/application/forms/Command/MultiCommandFlagForm.php @@ -32,6 +32,7 @@ namespace Icinga\Module\Monitoring\Form\Command; use \Icinga\Web\Form\Element\TriStateCheckbox; use \Icinga\Web\Form; use \Zend_Form_Element_Hidden; +use \Zend_Form; /** * A form to edit multiple command flags of multiple commands at once. When some commands have @@ -71,6 +72,7 @@ class MultiCommandFlagForm extends Form { { $this->flags = $flags; parent::__construct(); + $this->setEnctype(Zend_Form::ENCTYPE_MULTIPART); } /** @@ -103,11 +105,6 @@ class MultiCommandFlagForm extends Form { return $changed; } - /** - * Extract the values from a set of items. - * - * @param array $items The items - */ private function valuesFromObjects($items) { $values = array(); @@ -142,6 +139,21 @@ class MultiCommandFlagForm extends Form { return array_merge($values, $old); } + public function buildCheckboxes() + { + $checkboxes = array(); + foreach ($this->flags as $flag => $description) { + $checkboxes[] = new TriStateCheckbox( + $flag, + array( + 'label' => $description, + 'required' => true + ) + ); + } + return $checkboxes; + } + /** * Create the multi flag form * @@ -150,16 +162,9 @@ class MultiCommandFlagForm extends Form { public function create() { $this->setName('form_flag_configuration'); - foreach ($this->flags as $flag => $description) { - $this->addElement(new TriStateCheckbox( - $flag, - array( - 'label' => $description, - 'required' => true - ) - )); - - $old = new Zend_Form_Element_Hidden($flag . self::OLD_VALUE_MARKER); + foreach ($this->buildCheckboxes() as $checkbox) { + $this->addElement($checkbox); + $old = new Zend_Form_Element_Hidden($checkbox->getName() . self::OLD_VALUE_MARKER); $this->addElement($old); } $this->setSubmitLabel('Save Configuration'); diff --git a/modules/monitoring/application/views/helpers/CommandForm.php b/modules/monitoring/application/views/helpers/CommandForm.php index d3124019d..7ebc788c6 100644 --- a/modules/monitoring/application/views/helpers/CommandForm.php +++ b/modules/monitoring/application/views/helpers/CommandForm.php @@ -56,7 +56,6 @@ class Zend_View_Helper_CommandForm extends Zend_View_Helper_Abstract { $form = new Form(); $form->setAttrib('class', 'inline'); - $form->setIgnoreChangeDiscarding(true); $form->setRequest(Zend_Controller_Front::getInstance()->getRequest()); // Filter work only from get parts. Put important diff --git a/modules/monitoring/application/views/helpers/MonitoringState.php b/modules/monitoring/application/views/helpers/MonitoringState.php index dff80a205..2051975b7 100644 --- a/modules/monitoring/application/views/helpers/MonitoringState.php +++ b/modules/monitoring/application/views/helpers/MonitoringState.php @@ -7,7 +7,6 @@ class Zend_View_Helper_MonitoringState extends Zend_View_Helper_Abstract public function monitoringState($object, $type = 'service') { - if ($type === 'service') { return $this->servicestates[$object->service_state]; } elseif ($type === 'host') { @@ -15,6 +14,26 @@ class Zend_View_Helper_MonitoringState extends Zend_View_Helper_Abstract } } + public function getServiceStateColors() + { + return array('#44bb77', '#FFCC66', '#FF5566', '#E066FF', '#77AAFF'); + } + + public function getHostStateColors() + { + return array('#44bb77', '#FF5566', '#E066FF', '#77AAFF'); + } + + public function getServiceStateNames() + { + return array_values($this->servicestates); + } + + public function getHostStateNames() + { + return array_values($this->hoststates); + } + public function getStateFlags($object, $type = 'service') { $state_classes = array(); diff --git a/modules/monitoring/application/views/helpers/Perfdata.php b/modules/monitoring/application/views/helpers/Perfdata.php index 483ad0453..49e88cae6 100644 --- a/modules/monitoring/application/views/helpers/Perfdata.php +++ b/modules/monitoring/application/views/helpers/Perfdata.php @@ -1,90 +1,82 @@ getAll(); - $perfdata = preg_replace('~\'([^\']+)\'~e', "str_replace(' ', '\'', '$1')", $perfdata); - $parts = preg_split('~\s+~', $perfdata, -1, PREG_SPLIT_NO_EMPTY); - - $table = array(); $result = ''; - if ($compact === true) { - $compact = 5; - } - if ($compact && count($parts) > $compact) { - $parts = array_slice($parts, 0, $compact); - } - foreach ($parts as $part) { - if (strpos($part, '=') === false) continue; - list($name, $vals) = preg_split('~=~', $part, 2); - $name = str_replace("'", ' ', $name); - $parts = preg_split('~;~', $vals, 5); - while (count($parts) < 5) $parts[] = null; - list($val, $warn, $crit, $min, $max) = $parts; - - $unit = ''; - if (preg_match('~^([\d+\.]+)([^\d]+)$~', $val, $m)) { - $unit = $m[2]; - $val = $m[1]; - } else { + $table = array(); + $pset = array_slice(PerfdataSet::fromString($perfdataStr)->asArray(), 0, ($compact ? 5 : null)); + foreach ($pset as $label => $perfdata) { + if (!$perfdata->isPercentage() && $perfdata->getMaximumValue() === null) { continue; } - if ($unit == 'c') continue; // Counter pie graphs are not useful - if ($compact && $val < 0.0001) continue; - if ($unit == '%') { - if (! $min ) $min = 0; - if (! $max) $max = 100; - } else { - if (! $max && $crit > 0) $max = $crit; - //return ''; - } - if (! $max) continue; - $green = 0; - $orange = 0; - $red = 0; - $gray = $max - $val; - if ($val < $warn) $green = $val; - elseif ($val < $crit) $orange = $val; - else $red = $val; - $inlinePie = new InlinePie(array($green, $orange, $red, $gray)); + + $pieChart = new InlinePie($this->calculatePieChartData($perfdata)); if ($compact) { - $inlinePie->setTitle(htmlspecialchars($name) . ': ' . htmlspecialchars($ps[$name]->getFormattedValue())); - $inlinePie->setStyle('float: right;'); - $result .= $inlinePie->render(); + $pieChart->setTitle( + htmlspecialchars($label) . ': ' . htmlspecialchars($this->formatPerfdataValue($perfdata)) + ); + $pieChart->setStyle('float: right;'); + $result .= $pieChart->render(); } else { - $inlinePie->setTitle(htmlspecialchars($name)); - $inlinePie->setStyle('float: left; margin: 0.2em 0.5em 0.2em 0;'); - $table[] = '' . $inlinePie->render() - . htmlspecialchars($name) + $pieChart->setTitle(htmlspecialchars($label)); + $pieChart->setStyle('float: left; margin: 0.2em 0.5em 0.2em 0;'); + $table[] = '' . $pieChart->render() + . htmlspecialchars($label) . '' - . htmlspecialchars($ps[$name]->getFormattedValue()) . + . htmlspecialchars($this->formatPerfdataValue($perfdata)) . ''; } } - if ($result == '' && ! $compact) { - $result = $perfdata; + + // TODO: What if we have both? And should we trust sprintf-style placeholders in perfdata titles? + if (empty($table)) { + return $compact ? $result : $perfdataStr; + } else { + return '' . implode("\n", $table) . '
'; } - if (! empty($table)) { - // TODO: What if we have both? And should we trust sprintf-style placeholders in perfdata titles? - $result = '' . implode("\n", $table) . '
'; + } + + protected function calculatePieChartData(Perfdata $perfdata) + { + $rawValue = $perfdata->getValue(); + $minValue = $perfdata->getMinimumValue() !== null ? $perfdata->getMinimumValue() : 0; + $maxValue = $perfdata->getMaximumValue(); + $usedValue = ($rawValue - $minValue); + $unusedValue = ($maxValue - $minValue) - $usedValue; + + $gray = $unusedValue; + $green = $orange = $red = 0; + // TODO(#6122): Add proper treshold parsing. + if ($perfdata->getCriticalTreshold() && $perfdata->getValue() > $perfdata->getCriticalTreshold()) { + $red = $usedValue; + } elseif ($perfdata->getWarningTreshold() && $perfdata->getValue() > $perfdata->getWarningTreshold()) { + $orange = $usedValue; + } else { + $green = $usedValue; } - return $result; + return array($green, $orange, $red, $gray); + } + + protected function formatPerfdataValue(Perfdata $perfdata) + { + if ($perfdata->isBytes()) { + return Format::bytes($perfdata->getValue()); + } elseif ($perfdata->isSeconds()) { + return Format::seconds($perfdata->getValue()); + } elseif ($perfdata->isPercentage()) { + return $perfdata->getValue() . '%'; + } + + return $perfdata->getValue(); } } diff --git a/modules/monitoring/application/views/helpers/SelectionToolbar.php b/modules/monitoring/application/views/helpers/SelectionToolbar.php index 32f07325b..dccb9fa27 100644 --- a/modules/monitoring/application/views/helpers/SelectionToolbar.php +++ b/modules/monitoring/application/views/helpers/SelectionToolbar.php @@ -13,11 +13,8 @@ class Zend_View_Helper_SelectionToolbar extends Zend_View_Helper_Abstract public function selectionToolbar($type, $target = null) { if ($type == 'multi') { - return '
Select ' - . ' All ' - . ' None
'; - } else if ($type == 'single') { - return '
Select None
'; + return '
' + . ' Show All
'; } else { return ''; } diff --git a/modules/monitoring/application/views/scripts/list/hosts-compact.phtml b/modules/monitoring/application/views/scripts/list/hosts-compact.phtml index b6ac4e15e..d06c3af32 100644 --- a/modules/monitoring/application/views/scripts/list/hosts-compact.phtml +++ b/modules/monitoring/application/views/scripts/list/hosts-compact.phtml @@ -5,7 +5,12 @@ if ($hosts->count() === 0) { return; } -?> +?>
" + data-icinga-multiselect-data="host" +> getHelper('MonitoringState');
Sort by sortControl->render($this); ?>
- + paginationControl($hosts, null, null, array('preserve' => $this->preserve)); ?> +selectionToolbar('multi', $this->href('monitoring/multi/host', $query)); ?>
@@ -19,12 +20,17 @@ if ($hosts->count() === 0) { } ?> -
+
" + data-icinga-multiselect-data="host" +> util()->getHostStateName($host->host_state)); - $hostLink = $this->href('monitoring/show/host', array('host' => $host->host_name)); + $hostLink = $this->href('/monitoring/show/host', array('host' => $host->host_name)); $icons = array(); if (!$host->host_handled && $host->host_state > 0){ diff --git a/modules/monitoring/application/views/scripts/list/notifications.phtml b/modules/monitoring/application/views/scripts/list/notifications.phtml index 03dad8d97..97b56a650 100644 --- a/modules/monitoring/application/views/scripts/list/notifications.phtml +++ b/modules/monitoring/application/views/scripts/list/notifications.phtml @@ -2,7 +2,8 @@ tabs ?>
Sort by sortControl->render($this) ?> - + +selectionToolbar('single') ?>
paginationControl($notifications, null, null, array('preserve' => $this->preserve)) ?> diff --git a/modules/monitoring/application/views/scripts/list/services.phtml b/modules/monitoring/application/views/scripts/list/services.phtml index 643f6d419..111d3336a 100644 --- a/modules/monitoring/application/views/scripts/list/services.phtml +++ b/modules/monitoring/application/views/scripts/list/services.phtml @@ -8,12 +8,21 @@ if (!$this->compact): ?> Sort by sortControl ?> -paginationControl($services, null, null, array('preserve' => $this->preserve)); ?> + +paginationControl($services, null, null, array('preserve' => $this->preserve));?> + + +selectionToolbar('multi', $this->href('monitoring/multi/service', $query)); ?>
-
+
" + data-icinga-multiselect-data="service,host" +> - + + + + diff --git a/modules/monitoring/application/views/scripts/multi/components/configuration.phtml b/modules/monitoring/application/views/scripts/multi/components/configuration.phtml deleted file mode 100644 index 7dd4c0844..000000000 --- a/modules/monitoring/application/views/scripts/multi/components/configuration.phtml +++ /dev/null @@ -1,10 +0,0 @@ -
-
- Configuration -
-
-
- Change configuration for objects) ?> objects. - form->render($this); ?> -
-
diff --git a/modules/monitoring/application/views/scripts/multi/components/downtimes.phtml b/modules/monitoring/application/views/scripts/multi/components/downtimes.phtml index ffbf73640..66ea016ec 100644 --- a/modules/monitoring/application/views/scripts/multi/components/downtimes.phtml +++ b/modules/monitoring/application/views/scripts/multi/components/downtimes.phtml @@ -1,49 +1,25 @@ -
+ + + + diff --git a/modules/monitoring/application/views/scripts/multi/components/flags.phtml b/modules/monitoring/application/views/scripts/multi/components/flags.phtml new file mode 100644 index 000000000..c7fba5d97 --- /dev/null +++ b/modules/monitoring/application/views/scripts/multi/components/flags.phtml @@ -0,0 +1,31 @@ +
+
+ Comments + + + icon('remove_petrol.png') ?> Remove Comments +
+ + icon('notification_disabled_petrol.png') ?> Delay Notifications +
+ + icon('acknowledgement_petrol.png') ?> Acknowledge - - - icon('notification.png') ?>"> - - - - -
-
- -
- 0) { ?> - - There are comments assigned to the selected items. - - - icon('remove.png') ?>"> - - - There are 0 comments assigned to the selected items. - -
- - Delay Notifications - -
- +
Change comments . +
+ Downtimes + + + icon('remove_petrol.png') ?> Remove Downtimes +
+ + icon('in_downtime_petrol.png') ?> Schedule Downtimes - - -
-
-
- 0) { ?> - - Selected items are currently in downtime. - - - icon('remove.png') ?> - - - 0 Selected items are currently in downtime. - -
- - - Remove Acknowledgements - -
- +
+ Change downtimes + . +
+ + form->getElements() as $name => $element): + if ($element instanceof \Icinga\Web\Form\Element\TriStateCheckbox): + $element->setDecorators(array('ViewHelper')); + ?> + + + + + + + + + +
+ + + render() ?> +
render() ?>
+ \ No newline at end of file diff --git a/modules/monitoring/application/views/scripts/multi/components/objectlist.phtml b/modules/monitoring/application/views/scripts/multi/components/objectlist.phtml new file mode 100644 index 000000000..21bdf3f3b --- /dev/null +++ b/modules/monitoring/application/views/scripts/multi/components/objectlist.phtml @@ -0,0 +1,34 @@ + + ' . $object->host_name . ' ' . $object->service_description . ''; + } else { + echo $this->href( + 'monitoring/show/host', + array('host' => $object->host_name) + ); + echo '">' . $object->host_name . ''; + }?>, + 5) { + echo ' ... ' . (count($objects) - 5) . ' more ... '; + } + + if (!$this->is_service) { + $link = 'monitoring/list/hosts'; + $target = array( + 'host' => $this->hostquery + ); + } else { + $link = 'monitoring/list/services'; + $target = array( + 'host' => $this->hostquery, + 'service' => $this->servicequery + ); + } +?> list all \ No newline at end of file diff --git a/modules/monitoring/application/views/scripts/multi/components/summary.phtml b/modules/monitoring/application/views/scripts/multi/components/summary.phtml index 354533c12..fb761cce2 100644 --- a/modules/monitoring/application/views/scripts/multi/components/summary.phtml +++ b/modules/monitoring/application/views/scripts/multi/components/summary.phtml @@ -1,93 +1,72 @@ getHelper('CommandForm'); -$servicequery = isset($this->servicequery) ? $this->servicequery : ''; + /** @var Zend_View_Helper_CommandForm $cf */ + $cf = $this->getHelper('CommandForm'); + $servicequery = isset($this->servicequery) ? $this->servicequery : ''; + $objectName = $this->is_service ? 'Services' : 'Hosts'; ?> -
- - 10) { - $text = ' and ' . (count($objects) - 10) . ' more ...'; - } else { - $text = ' show all ...'; - } - if ($this->is_service) { - $link = 'monitoring/list/hosts'; - $target = array( - 'host' => implode(',', $hostnames) - ); - } else { - $link = 'monitoring/list/services'; - // TODO: Show multiple targets for services - $target = array(); - } - ?> - -
-
- + + + + + + + icon('refresh_petrol.png') ?> Recheck +
+ + icon('reschedule_petrol.png') ?> Reschedule +
-
- The selected objects have problems ?> service problems.

+ + + Perform actions on . + + - - Acknowledge Problems - - - - Schedule Downtimes - -
+ + + problems ?> Problems + + + + icon('in_downtime_petrol.png') ?> Schedule Downtimes + + + + Handle problems ?> problems on objects) ?> . + + + + + unhandled) ?> Unhandled + + + + icon('acknowledgement_petrol.png') ?> Acknowledge +
+ + icon('remove_petrol.png') ?> Remove Acknowledgements + + + + + \ No newline at end of file diff --git a/modules/monitoring/application/views/scripts/multi/host.phtml b/modules/monitoring/application/views/scripts/multi/host.phtml index 165ece8ef..e473ba05a 100644 --- a/modules/monitoring/application/views/scripts/multi/host.phtml +++ b/modules/monitoring/application/views/scripts/multi/host.phtml @@ -1,33 +1,59 @@ is_service = false; $this->hostquery = implode($this->hostnames, ','); -$this->target = array( - 'host' => $this->hostquery -); +$this->target = array('host' => $this->hostquery); ?> -tabs->render($this); ?> -
-
- Hosts ( objects) -
- - - -
-
-
- -
- render('multi/components/summary.phtml'); ?> -
+
+ tabs; ?>
-render('multi/components/comments.phtml'); ?> -render('multi/components/downtimes.phtml'); ?> -render('multi/components/configuration.phtml'); ?> +
+

Summary for hosts

+ + render('multi/components/objectlist.phtml'); ?> + + + + + + + + + + +
+

Hosts

+
+ pie->render(); ?> + + $count) { + if ($count > 0) { + echo ucfirst($state) . ': ' . $count . '
'; + } + } + ?> +
+ +

icon('hostgroup.png')?> Host Actions

+ + + + render('multi/components/summary.phtml'); ?> + render('multi/components/comments.phtml'); ?> + render('multi/components/downtimes.phtml'); ?> + +
+ + render('multi/components/flags.phtml') ?> +
+ + + + diff --git a/modules/monitoring/application/views/scripts/multi/service.phtml b/modules/monitoring/application/views/scripts/multi/service.phtml index f594dc836..c0e6e32e2 100644 --- a/modules/monitoring/application/views/scripts/multi/service.phtml +++ b/modules/monitoring/application/views/scripts/multi/service.phtml @@ -8,30 +8,72 @@ $this->target = array( ); ?> -tabs->render($this); ?> -
- -
- Services ( objects ) -
- - - -
-
-
- -
- render('multi/components/summary.phtml'); ?> -
- +
+ tabs; ?>
-render('multi/components/comments.phtml'); ?> -render('multi/components/downtimes.phtml'); ?> -render('multi/components/configuration.phtml'); ?> +
+

Summary for services

+ + render('multi/components/objectlist.phtml'); ?> + + + + + + + + + + + + + + +
+

Services

+
+

Hosts

+
+ service_pie->render(); ?> + + $count) { + if ($count > 0) { + echo ucfirst($state) . ': ' . $count . '
'; + } + } + ?> +
+ host_pie->render(); ?> + + $count) { + if ($count > 0) { + echo ucfirst($state) . ': ' . $count . '
'; + } + } + ?> +
+ +

icon('servicegroup.png')?> Service Actions

+ + + + render('multi/components/summary.phtml'); ?> + render('multi/components/comments.phtml'); ?> + render('multi/components/downtimes.phtml'); ?> + +
+ + render('multi/components/flags.phtml') ?> +
+ + + + diff --git a/modules/monitoring/doc/test/how_to_test_controllers.md b/modules/monitoring/doc/test/how_to_test_controllers.md deleted file mode 100644 index d23c06c12..000000000 --- a/modules/monitoring/doc/test/how_to_test_controllers.md +++ /dev/null @@ -1,98 +0,0 @@ -# Testing controllers with different backends - -Icingaweb's monitoring controllers support a variety of different backends (IDO, Statusdat, Livestatus) and make it -therefore hard to test for every backend. In order to make life a little bit easier, Test-Fixtures allow you to setup -a backend with specific monitoring data and test it afterwards by running the controller's action. - -## Example - -It's best to subclass MonitoringControllerTest (found in modules/monitoring/test/testlib), as this handles depency resoultion -and setup for you: - - - // assume our test is underneath the test/application/controllers folder in the monitoring module - require_once(dirname(__FILE__).'/../../testlib/MonitoringControllerTest.php'); - - use Test\Monitoring\Testlib\MonitoringControllerTest; - use Test\Monitoring\Testlib\Datasource\TestFixture; - use Test\Monitoring\Testlib\Datasource\ObjectFlags; - - class MyControllerTest extends MonitoringControllerTest - { - public function testSomething() - { - // Create a test fixture - $fixture = new TestFixture() - $fixture->addHost('host', 0) // Add a host with state OK - ->addToHostgroup('myHosts') // Add host to hostgroup - ->addService('svc1', 1) // Add a warning service 'svc1' underneath host - ->addToServiceGroup('svc_warning') // add this service to a servicegroup svc_warning - ->addService('svc2', 2, ObjectFlags::ACKNOWLEDGED()) // Add a critical, but acknowledged service to this host - ->addService( - 'svc3', - 1, - new ObjectFlags(), - array("customvariables" => - array("customer" => "myCustomer") - ) - ); // add a warning service with a customvariable - - $this->setupFixture($fixture, "mysql"); // setup the fixture for MySQL, so the backend is populated with the data set above - // backends can be mysql, pgsql, statusdat (and in the future livestatus) - $controller = $this->requireController('MyController', 'mysql'); // request a controller with the given backend injected - $controller->myAction(); // controller is now the Zend controller instance, perform an action - $result = $controller->view->hosts->fetchAll(); // get the result of the query - // and assert stuff - $this->assertEquals(1, count($result), "Asserting one host being retrieved in the controller"); - } - } - -## The Test-fixture API - -In order to populate your backend with specific monitoring objects, you have to create a TestFixture class. This class -allows you to setup the monitoring objects in a backend independent way using a few methods: - -### TestFixture::addHost($name, $state, [ObjectFlags $flags], [array $properties]) - -The addHost method adds a host with the name $name and the status $state (0-2) to your testfixture. When no ObjectFlags -object is provided, the default flags are used (not flapping, notifications enabled, active and passive enabled, not -acknowledged, not in downtime and not pending). The $properties array can contain additional settings like 'address', - an 'customvariables' array, 'notes_url', 'action_url' or 'icon_image'. - -Subsequent addToHostgroup and addService calls will affect this host (so the service will be added to this host) - -### TestFixture::addService($name, $state, [ObjectFlags $flags], [array $properties]) - -The addHost method adds a service with the name $name and the status $state (0-3) to your testfixture. When no ObjectFlags -object is provided, the default flags are used (not flapping, notifications enabled, active and passive enabled, not -acknowledged, not in downtime and not pending). The $properties array can contain additional settings like an -'customvariables' array, 'notes_url', 'action_url' or 'icon_image'. - -Subsequent addToServicegroup calls will affect this service. - - -### ObjectFlags - -The Objectflags object encapsulates the following monitoring states with the following default values: - - public $flapping = 0; // Whether this host is flapping - public $notifications = 1; // Whether notifications are enabled - public $active_checks = 1; // Whether actice checks are enabled - public $passive_checks = 1; // Whether passive checks are enabled - public $acknowledged = 0; // Whether this object has been acknowledged - public $in_downtime = 0; // Whether this object is in a scheduled downtime - public $is_pending = 0; // Whether this object is currently pending - public $time = time(); // The last check and statechange time - -ObjectFlags can either be created using new ObjectFlags([$ageInSeconds]) and directly modify the attributes or by -calling one of the following factory methods: - - - ObjectFlags::FLAPPING() - ObjectFlags::PENDING() - ObjectFlags::DISABLE_NOTIFICATIONS() - ObjectFlags::PASSIVE_ONLY() - ObjectFlags::ACTIVE_ONLY() - ObjectFlags::DISABLED() { - ObjectFlags::ACKNOWLEDGED() - ObjectFlags::IN_DOWNTIME() diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php index 31a122c7f..dde165c0e 100644 --- a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php +++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php @@ -37,7 +37,7 @@ class ContactgroupQuery extends IdoQuery 'services' => array( 'service_object_id' => 'so.object_id', 'service_host_name' => 'so.name1 COLLATE latin1_general_ci', - 'service' => 'so.name1 COLLATE latin1_general_ci', + 'service' => 'so.name2 COLLATE latin1_general_ci', 'service_description' => 'so.name2 COLLATE latin1_general_ci', ) ); diff --git a/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php b/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php index 700ada117..31d8960ac 100644 --- a/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php +++ b/modules/monitoring/library/Monitoring/DataView/ServiceStatus.php @@ -133,6 +133,10 @@ class ServiceStatus extends DataView { return array( 'host_name' => array( + 'columns' => array( + 'service_host_name', + 'service_description' + ), 'order' => self::SORT_ASC ), 'host_address' => array( diff --git a/modules/monitoring/library/Monitoring/Environment.php b/modules/monitoring/library/Monitoring/Environment.php index a1e41d732..0213118a2 100644 --- a/modules/monitoring/library/Monitoring/Environment.php +++ b/modules/monitoring/library/Monitoring/Environment.php @@ -37,12 +37,12 @@ class Environment public static function grapher($env = null) { - return Hook::get('grapher', null, self::config($env, 'grapher')); + return Hook::createInstance('grapher', null, self::config($env, 'grapher')); } public static function configBackend($env = null) { - return Hook::get( + return Hook::createInstance( 'configBackend', null, self::config($env, 'configBackend') diff --git a/modules/monitoring/library/Monitoring/Object/AbstractObject.php b/modules/monitoring/library/Monitoring/Object/AbstractObject.php index ba046decb..23417f034 100644 --- a/modules/monitoring/library/Monitoring/Object/AbstractObject.php +++ b/modules/monitoring/library/Monitoring/Object/AbstractObject.php @@ -142,6 +142,7 @@ abstract class AbstractObject public function fetchContacts() { +/* $query = Contact::fromRequest( $this->request, array( @@ -152,6 +153,21 @@ abstract class AbstractObject ) )->getQuery() ->where('host_name', $this->host_name); +*/ + + $query = Contact::fromParams(array('backend' => null), array( + 'contact_name', + 'contact_alias', + 'contact_email', + 'contact_pager', + ))->getQuery(); + + if ($this->type === 'service') { + $query->where('service_host_name', $this->host_name); + $query->where('service_description', $this->service_description); + } else { + $query->where('host_name', $this->host_name); + } $this->contacts = $query->fetchAll(); return $this; @@ -173,6 +189,19 @@ abstract class AbstractObject public function fetchContactgroups() { + + $query = Contactgroup::fromParams(array('backend' => null), array( + 'contactgroup_name', + 'contactgroup_alias' + ))->getQuery(); + + if ($this->type === 'service') { + $query->where('service_host_name', $this->host_name); + $query->where('service_description', $this->service_description); + } else { + $query->where('host_name', $this->host_name); + } +/* $query = Contactgroup::fromRequest( $this->request, array( @@ -180,7 +209,7 @@ abstract class AbstractObject 'contactgroup_alias' ) )->getQuery(); - +*/ $this->contactgroups = $query->fetchAll(); return $this; diff --git a/modules/monitoring/library/Monitoring/Plugin/Perfdata.php b/modules/monitoring/library/Monitoring/Plugin/Perfdata.php index 4d7cb13db..f01880885 100644 --- a/modules/monitoring/library/Monitoring/Plugin/Perfdata.php +++ b/modules/monitoring/library/Monitoring/Plugin/Perfdata.php @@ -1,223 +1,280 @@ unit) { - case self::BYTES: - return $this->formatBytes() . ' von ' . $this->formatBytes($this->max); - break; - case self::SECONDS: - return $this->formatSeconds(); - break; - case self::PERCENT: - return number_format($this->val, 2, ',', '.') . '%'; - break; - default: - return $this->val; - } - } + /** + * The value + * + * @var float + */ + protected $value; - public function hasMax() - { - return $this->max !== null && $this->max > 0; - } + /** + * The minimum value + * + * @var float + */ + protected $minValue; - public function getPercentage() - { - if ($this->unit === self::PERCENT) { - return $this->val; - } - if ($this->hasMax()) { - return $this->val / $this->max * 100; - } - return false; - } + /** + * The maximum value + * + * @var float + */ + protected $maxValue; - public function getValue() - { - return $this->val; - } + /** + * The WARNING treshold + * + * @var string + */ + protected $warningTreshold; - protected function formatBytes($val = null) - { - $steps = array( - 1 => 'Byte', - 1024 => 'KByte', - 1024 * 1024 => 'MByte', - 1024 * 1024 * 1024 => 'GByte', - 1024 * 1024 * 1024 * 1024 => 'TByte' - ); - return $this->formatSpecial($steps, 1, $val); - } + /** + * The CRITICAL treshold + * + * @var string + */ + protected $criticalTreshold; - protected function formatSeconds() + /** + * Create a new Perfdata object based on the given performance data value + * + * @param string $perfdataValue The value to parse + */ + protected function __construct($perfdataValue) { - $steps = array( - 1 => 'us', - 1000 => 'ms', - 10000000 => 's', - ); - return $this->formatSpecial($steps, 1000000, $this->val); - } + $this->perfdataValue = $perfdataValue; + $this->parse(); - protected function formatSpecial($steps, $multi = 1, $val = null) - { - if ($val === null) { - $val = abs($this->val); - } else { - $val = abs($val); - } - // TODO: Check this, prefix fails if $val is given - if ($this->val < 0) { - $prefix = '-'; - } else { - $prefix = ''; - } - $val *= $multi; - $step = 1; - foreach (array_keys($steps) as $key) { - if ($key > $val * 1) { - break; + if ($this->unit === '%') { + if ($this->minValue === null) { + $this->minValue = 0.0; } - $step = $key; - } - if ($step <= 0) $step = 1; - return $prefix - . number_format($val / $step, 1, ',', '.') - . ' ' - . $steps[$step]; - } - - protected function __construct(& $perfdata) - { - $this->byte_map = array( - 'b' => 1, - 'kb' => 1024, - 'mb' => 1024 * 1024, - 'gb' => 1024 * 1024 * 1024, - 'tb' => 1024 * 1024 * 1024 * 1024 - ); - - // UGLY, fixes floats using comma: - $perfdata = preg_replace('~\,~', '.', $perfdata); - - $parts = preg_split('~;~', $perfdata, 5); - while (count($parts) < 5) { - $parts[] = null; - } - list( - $this->val, - $this->warn, - $this->crit, - $this->min, - $this->max - ) = $parts; - // TODO: check numbers! - - $unit = null; - if (! preg_match('~^(\-?[\d+\.]+(?:E\-?\d+)?)([^\d]+)?$~', $this->val, $m)) { - return $perfdata; - // Numbers with an exponential base will be rendered invalid using the regex above -// throw new \Exception('Got invalid perfdata: ' . $perfdata); - } - $this->val = $m[1]; - if (isset($m[2])) { - $unit = strtolower($m[2]); - } - if ($unit === 'c') { - $this->unit = self::COUNTER; - } - - if ($unit === '%') { - if (! is_numeric($this->min)) { - $this->min = 0; - } - if (! is_numeric($this->max)) { - $this->max = 100; - } - $this->unit = self::PERCENT; - } else { - if (! is_numeric($this->max) && $this->crit > 0) { - $this->max = $this->crit; - } - } - - if (array_key_exists($unit, $this->byte_map)) { - $this->unit = self::BYTES; - $this->val = $this->val * $this->byte_map[$unit]; - $this->min = $this->min * $this->byte_map[$unit]; - $this->max = $this->max * $this->byte_map[$unit]; - } - if ($unit === 's') { - $this->unit = self::SECONDS; - } - if ($unit === 'ms') { - $this->unit = self::SECONDS; - $this->val = $this->val / 1000; - } - if ($unit === '%') { - if (! is_numeric($this->min)) { - $this->min = 0; - } - if (! is_numeric($this->max)) { - $this->max = 100; - } - } else { - if (! is_numeric($this->max) && $this->crit > 0) { - $this->max = $this->crit; + if ($this->maxValue === null) { + $this->maxValue = 100.0; } } } + /** + * Return a new Perfdata object based on the given performance data value + * + * @param string $perfdataValue The value to parse + * + * @return Perfdata + * + * @throws ProgrammingError In case the given performance data value has no content + */ + public static function fromString($perfdataValue) + { + if (empty($perfdataValue)) { + throw new ProgrammingError('Perfdata::fromString expects a string with content'); + } + + return new static($perfdataValue); + } + + /** + * Return whether this performance data value is a number + * + * @return bool True in case it's a number, otherwise False + */ + public function isNumber() + { + return $this->unit === null; + } + + /** + * Return whether this performance data value are seconds + * + * @return bool True in case it's seconds, otherwise False + */ + public function isSeconds() + { + return in_array($this->unit, array('s', 'ms', 'us')); + } + + /** + * Return whether this performance data value is in percentage + * + * @return bool True in case it's in percentage, otherwise False + */ + public function isPercentage() + { + return $this->unit === '%'; + } + + /** + * Return whether this performance data value is in bytes + * + * @return bool True in case it's in bytes, otherwise False + */ + public function isBytes() + { + return in_array($this->unit, array('b', 'kb', 'mb', 'gb', 'tb')); + } + + /** + * Return whether this performance data value is a counter + * + * @return bool True in case it's a counter, otherwise False + */ public function isCounter() { - return $this->unit === self::COUNTER; + return $this->unit === 'c'; } - public static function fromString(& $perfdata) + /** + * Return the value or null if it is unknown (U) + * + * @return null|float + */ + public function getValue() { - $pdat = new Perfdata($perfdata); - return $pdat; + return $this->value; } - protected function normalizeNumber($num) + /** + * Return the value as percentage (0-100) + * + * @return null|float + */ + public function getPercentage() { - return $num; - // Bullshit, still TODO - /* - $dot = strpos($num, '.'); - $comma = strpos($num, ','); - - if ($dot === false) { - // No dot... - if ($comma === false) { - // ...and no comma, it's an integer: - return (int) $num; - } else { - // just a comma - } - } else { - if ($comma === false) { + if ($this->isPercentage()) { + return $this->value; + } + + if ($this->maxValue !== null) { + $minValue = $this->minValue !== null ? $this->minValue : 0; + + if ($this->value > $minValue) { + return (($this->value - $minValue) / ($this->maxValue - $minValue)) * 100; + } + } + } + + /** + * Return this value's warning treshold or null if it is not available + * + * @return null|string + */ + public function getWarningTreshold() + { + return $this->warningTreshold; + } + + /** + * Return this value's critical treshold or null if it is not available + * + * @return null|string + */ + public function getCriticalTreshold() + { + return $this->criticalTreshold; + } + + /** + * Return the minimum value or null if it is not available + * + * @return null|float + */ + public function getMinimumValue() + { + return $this->minValue; + } + + /** + * Return the maximum value or null if it is not available + * + * @return null|float + */ + public function getMaximumValue() + { + return $this->maxValue; + } + + /** + * Parse the current performance data value + * + * @todo Handle optional min/max if UOM == % + */ + protected function parse() + { + $parts = explode(';', $this->perfdataValue); + + $matches = array(); + if (preg_match('@^(\d+(\.\d+)?)([a-zA-Z%]{1,2})$@', $parts[0], $matches)) { + $this->unit = strtolower($matches[3]); + $this->value = self::convert($matches[1], $this->unit); + } else { + $this->value = self::convert($parts[0]); + } + + switch (count($parts)) + { + case 5: + $this->maxValue = self::convert($parts[4], $this->unit); + case 4: + $this->minValue = self::convert($parts[3], $this->unit); + case 3: + // TODO(#6123): Tresholds have the same UOM and need to be converted as well! + $this->criticalTreshold = trim($parts[2]) ? trim($parts[2]) : null; + case 2: + // TODO(#6123): Tresholds have the same UOM and need to be converted as well! + $this->warningTreshold = trim($parts[1]) ? trim($parts[1]) : null; + } + } + + /** + * Return the given value converted to its smallest supported representation + * + * @param string $value The value to convert + * @param string $fromUnit The unit the value currently represents + * + * @return null|float Null in case the value is not a number + */ + protected static function convert($value, $fromUnit = null) + { + if (is_numeric($value)) { + switch ($fromUnit) + { + case 'us': + return $value / pow(10, 6); + case 'ms': + return $value / pow(10, 3); + case 'tb': + return floatval($value) * pow(2, 40); + case 'gb': + return floatval($value) * pow(2, 30); + case 'mb': + return floatval($value) * pow(2, 20); + case 'kb': + return floatval($value) * pow(2, 10); + default: + return (float) $value; + } } - */ } } diff --git a/modules/monitoring/library/Monitoring/Plugin/PerfdataSet.php b/modules/monitoring/library/Monitoring/Plugin/PerfdataSet.php index 7f6876f1a..8038354a4 100644 --- a/modules/monitoring/library/Monitoring/Plugin/PerfdataSet.php +++ b/modules/monitoring/library/Monitoring/Plugin/PerfdataSet.php @@ -1,68 +1,144 @@ ptr = & $perfdata; - $this->len = strlen($this->ptr); - while ($this->pos < $this->len) { - $label = $this->readLabel(); - $perf = $this->readUntil(' '); - if (empty($perf)) continue; - $this->perfdata[$label] = Perfdata::fromString($perf); + if (($perfdataStr = trim($perfdataStr)) !== '') { + $this->perfdataStr = $perfdataStr; + $this->parse(); } } - public static function fromString(& $perfdata) + /** + * Return a iterator for this set of performance data + * + * @return ArrayIterator + */ + public function getIterator() { - $pset = new PerfdataSet($perfdata); - return $pset; + return new ArrayIterator($this->asArray()); } - public function getAll() + /** + * Return a new set of performance data + * + * @param string $perfdataStr A space separated list of label/value pairs + * + * @return PerfdataSet + */ + public static function fromString($perfdataStr) { - return $this->perfdata === null ? array() : $this->perfdata; + return new static($perfdataStr); } + /** + * Return this set of performance data as array + * + * @return array + */ + public function asArray() + { + return $this->perfdata; + } + + /** + * Parse the current performance data + */ + protected function parse() + { + while ($this->parserPos < strlen($this->perfdataStr)) { + $label = trim($this->readLabel()); + $value = trim($this->readUntil(' ')); + + if ($label && $value) { + $this->perfdata[$label] = Perfdata::fromString($value); + } + } + } + + /** + * Return the next label found in the performance data + * + * @return string The label found + */ protected function readLabel() { $this->skipSpaces(); - if (in_array($this->ptr[$this->pos], array('"', "'"))) { - $this->pos++; - $label = $this->readUntil($this->ptr[$this->pos - 1]); - $this->pos++; // Skip ' or " - $skip = $this->readUntil('='); - $this->pos++; + if (in_array($this->perfdataStr[$this->parserPos], array('"', "'"))) { + $quoteChar = $this->perfdataStr[$this->parserPos++]; + $label = $this->readUntil('='); + $this->parserPos++; + + if (($closingPos = strpos($label, $quoteChar)) > 0) { + $label = substr($label, 0, $closingPos); + } } else { $label = $this->readUntil('='); - $this->pos++; + $this->parserPos++; } + $this->skipSpaces(); - return trim($label); + return $label; } - protected function readUntil($stop_char) + /** + * Return all characters between the current parser position and the given character + * + * @param string $stopChar The character on which to stop + * + * @return string + */ + protected function readUntil($stopChar) { - $start = $this->pos; - while ($this->pos < $this->len && $this->ptr[$this->pos] !== $stop_char) { - $this->pos++; + $start = $this->parserPos; + while ($this->parserPos < strlen($this->perfdataStr) && $this->perfdataStr[$this->parserPos] !== $stopChar) { + $this->parserPos++; } - return substr($this->ptr, $start, $this->pos - $start); + + return substr($this->perfdataStr, $start, $this->parserPos - $start); } + /** + * Advance the parser position to the next non-whitespace character + */ protected function skipSpaces() { - while ($this->pos < $this->len && $this->ptr[$this->pos] === ' ') { - $this->pos++; + while ($this->parserPos < strlen($this->perfdataStr) && $this->perfdataStr[$this->parserPos] === ' ') { + $this->parserPos++; } } } diff --git a/modules/monitoring/library/Monitoring/Timeline/TimeRange.php b/modules/monitoring/library/Monitoring/Timeline/TimeRange.php index 93c81f98f..7ea4787b8 100644 --- a/modules/monitoring/library/Monitoring/Timeline/TimeRange.php +++ b/modules/monitoring/library/Monitoring/Timeline/TimeRange.php @@ -4,11 +4,11 @@ namespace Icinga\Module\Monitoring\Timeline; -use \StdClass; -use \Iterator; -use \DateTime; -use \DateInterval; -use Icinga\Util\DateTimeFactory; +use StdClass; +use Iterator; +use DateTime; +use DateInterval; +use Icinga\Util\Format; /** * A range of time split into a specific interval @@ -172,17 +172,17 @@ class TimeRange implements Iterator } elseif ($this->interval->m) { for ($i = 0; $i < $this->interval->m; $i++) { if ($this->negative) { - $dateTime->sub(new DateInterval('PT' . DateTimeFactory::getSecondsByMonth($dateTime) . 'S')); + $dateTime->sub(new DateInterval('PT' . Format::secondsByMonth($dateTime) . 'S')); } else { - $dateTime->add(new DateInterval('PT' . DateTimeFactory::getSecondsByMonth($dateTime) . 'S')); + $dateTime->add(new DateInterval('PT' . Format::secondsByMonth($dateTime) . 'S')); } } } elseif ($this->interval->y) { for ($i = 0; $i < $this->interval->y; $i++) { if ($this->negative) { - $dateTime->sub(new DateInterval('PT' . DateTimeFactory::getSecondsByYear($dateTime) . 'S')); + $dateTime->sub(new DateInterval('PT' . Format::secondsByYear($dateTime) . 'S')); } else { - $dateTime->add(new DateInterval('PT' . DateTimeFactory::getSecondsByYear($dateTime) . 'S')); + $dateTime->add(new DateInterval('PT' . Format::secondsByYear($dateTime) . 'S')); } } } diff --git a/modules/monitoring/test/php/application/controllers/ListControllerHostTest.php b/modules/monitoring/test/php/application/controllers/ListControllerHostTest.php deleted file mode 100644 index 18e529beb..000000000 --- a/modules/monitoring/test/php/application/controllers/ListControllerHostTest.php +++ /dev/null @@ -1,113 +0,0 @@ -executeHostListTestFor("mysql"); - } - - public function testHostListPgSQL() - { - $this->executeHostListTestFor("pgsql"); - } - - public function testHostListStatus() - { - $this->executeHostListTestFor("statusdat"); - } - - public function executeHostListTestFor($backend) - { - date_default_timezone_set('UTC'); - $checkTime = (string)(time()-2000); - $fixture = new TestFixture(); - $firstHostFlags = ObjectFlags::PASSIVE_ONLY(); - $firstHostFlags->acknowledged = 1; - $firstHostFlags->in_downtime = 1; - $firstHostFlags->has_been_checked = 1; - $firstHostFlags->notifications = 0; - $firstHostFlags->flapping = 1; - $firstHostFlags->time = $checkTime; - - $fixture->addHost('host1', 1, $firstHostFlags, array( - "address" => "10.92.1.5", - "has_been_checked" => 1, - "icon_image" => "myIcon.png", - "notes_url" => "note1.html", - "action_url" => "action.html"))-> - addToHostgroup('router')-> - addComment('author', 'host comment text')-> - addService('svc1', 2)-> - addService('svc2', 2)-> - addService('svc3', 2, ObjectFlags::ACKNOWLEDGED())-> - addService('svc4', 0); - $fixture->addHost('host2', 1)-> - addService('svc1', 2); - $fixture->addHost('host3', 0)-> - addService('svc1', 0); - $fixture->addHost('host4', 0)-> - addService('svc1', 0); - $fixture->addHost('host5', 2, ObjectFlags::ACKNOWLEDGED())-> - addService('svc1', 3)->addComment('author','svc comment'); - - try { - $this->setupFixture($fixture, $backend); - } catch (\PDOException $e) { - echo $e->getMessage(); - $this->markTestSkipped('Could not setup fixture for backends '.$backend.' :'.$e->getMessage()); - return null; - } - $controller = $this->requireController('ListController', $backend); - $controller->hostsAction(); - $result = $controller->view->hosts; - - $this->assertEquals(5, $result->getTotalItemCount(), 'Testing correct result count for '.$backend); - - $result = $result->getAdapter()->getItems(0,6); - for($i=1;$i<=5;$i++) { - $this->assertEquals('host'.$i, $result[$i-1]->host_name, "Asserting correct host names for backend ".$backend); - } - - $hostToTest = $result[0]; - $persistedLastCheck = explode("+", $hostToTest->host_last_check); - $persistedLastCheck = $persistedLastCheck[0]; - $this->assertEquals("10.92.1.5", $hostToTest->host_address, "Testing for correct host address field (backend ".$backend.")"); - // commented out due to failing tests when delay is too long - // $this->assertEquals(date("Y-m-d H:i:s", intval($checkTime)), $persistedLastCheck, "Testing for correct last check time format (backend ".$backend.")"); - //$this->assertEquals($checkTime, $hostToTest->host_last_state_change, "Testing for correct last state change (backend ".$backend.")"); - $this->assertEquals("Plugin output for host host1", $hostToTest->host_output, "Testing correct output for host (backend ".$backend.")"); - $this->assertEquals("Long plugin output for host host1", $hostToTest->host_long_output, "Testing correct long output for host (backend ".$backend.")"); - $this->assertEquals(0, $hostToTest->host_notifications_enabled, "Testing for disabled notifications (backend ".$backend.')'); - $this->assertEquals(1, $hostToTest->host_acknowledged, "Testing for host being acknowledged (backend ".$backend.')'); - $this->assertEquals(1, $hostToTest->host_in_downtime, "Testing for host being in downtime (backend ".$backend.')'); - $this->assertEquals(1, $hostToTest->host_is_flapping, "Testing for host being flapping (backend ".$backend.')'); - $this->assertEquals(1, $hostToTest->host_last_comment, 'Testing correct comment count for first host (backend '.$backend.')'); - $this->assertEquals(0, $hostToTest->host_state_type, 'Testing for soft state'); - $this->assertEquals(1, $hostToTest->host_handled, 'Testing for handled host (backend '.$backend.')'); - $this->assertEquals("myIcon.png", $hostToTest->host_icon_image, 'Testing for icon image (backend '.$backend.')'); - $this->assertEquals("note1.html", $hostToTest->host_notes_url, 'Testing for notes url (backend '.$backend.')'); - $this->assertEquals("action.html", $hostToTest->host_action_url, 'Testing for action url (backend '.$backend.')'); - $this->assertEquals(2, $hostToTest->host_unhandled_service_count, 'Testing correct open problems count (backend '.$backend.')'); - } - -} diff --git a/modules/monitoring/test/php/application/controllers/ListControllerServiceTest.php b/modules/monitoring/test/php/application/controllers/ListControllerServiceTest.php deleted file mode 100644 index f22e52c61..000000000 --- a/modules/monitoring/test/php/application/controllers/ListControllerServiceTest.php +++ /dev/null @@ -1,78 +0,0 @@ -executeServiceListTestFor("mysql"); - } - - public function testServiceListPgSQL() - { - $this->executeServiceListTestFor("pgsql"); - } - -// public function testServiceListStatusdat() -// { -// $this->executeServiceListTestFor("statusdat"); -// } - - public function executeServiceListTestFor($backend) - { - date_default_timezone_set('UTC'); - $checkTime = time()-2000; - $fixture = new TestFixture(); - $fixture->addHost('host1', 0)-> - addService("svc1", 0, new ObjectFlags(2000), array( - "notes_url" => "notes.url", - "action_url" => "action.url", - "icon_image" => "svcIcon.png" - ))-> - addService("svcDown", 2) -> addComment("author", "Comment text")-> - addService("svcFlapping", 1, ObjectFlags::FLAPPING())->addToServicegroup("Warning")-> - addService("svcNotifDisabled", 2, ObjectFlags::DISABLE_NOTIFICATIONS())-> - addService("svcPending", 0, ObjectFlags::PENDING()); - $fixture->addHost('host2', 1)-> - addService("svcPassive", 1, ObjectFlags::PASSIVE_ONLY())->addToServicegroup("Warning")-> - addService("svcDisabled", 1, ObjectFlags::DISABLED())->addToServicegroup("Warning")-> - addService("svcDowntime", 2, ObjectFlags::IN_DOWNTIME())-> - addService("svcAcknowledged", 1, ObjectFlags::ACKNOWLEDGED())->addToServicegroup("Warning"); - try { - $this->setupFixture($fixture, $backend); - } catch (\PDOException $e) { - echo $e->getMessage(); - $this->markTestSkipped('Could not setup fixture for backends '.$backend.' :'.$e->getMessage()); - return null; - } - - $controller = $this->requireController('ListController', $backend); - $controller->servicesAction(); - - $result = $controller->view->services; - - $this->assertEquals(9, $result->getTotalItemCount(), "Testing for correct service count"); - $result = $result->getAdapter()->getItems(0,1); - $this->assertEquals("notes.url", $result[0]->service_notes_url, "Testing for correct notes_url"); - $this->assertEquals("action.url", $result[0]->service_action_url, "Testing for correct action_url"); - $this->assertEquals(0, $result[0]->service_state, "Testing for correct Service state"); - } - -} diff --git a/modules/monitoring/test/php/application/forms/Command/AcknowledgeFormTest.php b/modules/monitoring/test/php/application/forms/Command/AcknowledgeFormTest.php index bb9b31706..32d8e35d3 100644 --- a/modules/monitoring/test/php/application/forms/Command/AcknowledgeFormTest.php +++ b/modules/monitoring/test/php/application/forms/Command/AcknowledgeFormTest.php @@ -1,62 +1,15 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Test\Monitoring\Forms\Command; - -require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Test/BaseTestCase.php'); +namespace Tests\Icinga\Module\Monitoring\Application\Forms\Command; use Icinga\Test\BaseTestCase; -require_once BaseTestCase::$moduleDir . '/monitoring/application/forms/Command/CommandForm.php'; -require_once BaseTestCase::$moduleDir . '/monitoring/application/forms/Command/AcknowledgeForm.php'; -require_once BaseTestCase::$libDir . '/Util/ConfigAwareFactory.php'; -require_once BaseTestCase::$libDir . '/Util/DateTimeFactory.php'; - -use \DateTimeZone; -use Icinga\Util\DateTimeFactory; - class AcknowledgeFormTest extends BaseTestCase { const FORM_CLASS = 'Icinga\Module\Monitoring\Form\Command\AcknowledgeForm'; - /** - * Set DateTimeFactory's time zone to UTC - * - * Utilizes singleton DateTimeFactory - * - * @backupStaticAttributes enabled - */ - public function setUp() - { - DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC'))); - } - public function testFormValid() { $form = $this->createForm( diff --git a/modules/monitoring/test/php/application/forms/Command/CommentFormTest.php b/modules/monitoring/test/php/application/forms/Command/CommentFormTest.php index 8975b93e1..3228af399 100644 --- a/modules/monitoring/test/php/application/forms/Command/CommentFormTest.php +++ b/modules/monitoring/test/php/application/forms/Command/CommentFormTest.php @@ -1,41 +1,11 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Test\Monitoring\Forms\Command; - -require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Test/BaseTestCase.php'); +namespace Tests\Icinga\Module\Monitoring\Application\Forms\Command; use Icinga\Test\BaseTestCase; -require_once BaseTestCase::$moduleDir . '/monitoring/application/forms/Command/CommandForm.php'; -require_once BaseTestCase::$moduleDir . '/monitoring/application/forms/Command/CommentForm.php'; - class CommentFormTest extends BaseTestCase { const FORM_CLASS = 'Icinga\Module\Monitoring\Form\Command\CommentForm'; diff --git a/modules/monitoring/test/php/application/forms/Command/CustomNotificationFormTest.php b/modules/monitoring/test/php/application/forms/Command/CustomNotificationFormTest.php index efcf1f102..9c03ff3ec 100644 --- a/modules/monitoring/test/php/application/forms/Command/CustomNotificationFormTest.php +++ b/modules/monitoring/test/php/application/forms/Command/CustomNotificationFormTest.php @@ -1,41 +1,11 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Test\Monitoring\Forms\Command; - -require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Test/BaseTestCase.php'); +namespace Tests\Icinga\Module\Monitoring\Application\Forms\Command; use Icinga\Test\BaseTestCase; -require_once BaseTestCase::$moduleDir . '/monitoring/application/forms/Command/CommandForm.php'; -require_once BaseTestCase::$moduleDir . '/monitoring/application/forms/Command/CustomNotificationForm.php'; - class CustomNotificationFormTest extends BaseTestCase { const FORM_CLASS = 'Icinga\Module\Monitoring\Form\Command\CustomNotificationForm'; diff --git a/modules/monitoring/test/php/application/forms/Command/DelayNotificationFormTest.php b/modules/monitoring/test/php/application/forms/Command/DelayNotificationFormTest.php index 66b4b4455..3a955f191 100644 --- a/modules/monitoring/test/php/application/forms/Command/DelayNotificationFormTest.php +++ b/modules/monitoring/test/php/application/forms/Command/DelayNotificationFormTest.php @@ -1,41 +1,10 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Test\Monitoring\Forms\Command; - -require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Test/BaseTestCase.php'); +namespace Tests\Icinga\Module\Monitoring\Application\Forms\Command; use Icinga\Test\BaseTestCase; - -require_once BaseTestCase::$moduleDir . '/monitoring/application/forms/Command/CommandForm.php'; -require_once BaseTestCase::$moduleDir . '/monitoring/application/forms/Command/DelayNotificationForm.php'; - use Icinga\Module\Monitoring\Form\Command\DelayNotificationForm; class DelayNotificationFormTest extends BaseTestCase diff --git a/modules/monitoring/test/php/application/forms/Command/RescheduleNextCheckFormTest.php b/modules/monitoring/test/php/application/forms/Command/RescheduleNextCheckFormTest.php index 23f82caac..72a4914f5 100644 --- a/modules/monitoring/test/php/application/forms/Command/RescheduleNextCheckFormTest.php +++ b/modules/monitoring/test/php/application/forms/Command/RescheduleNextCheckFormTest.php @@ -1,63 +1,15 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Test\Monitoring\Forms\Command; - -require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Test/BaseTestCase.php'); +namespace Tests\Icinga\Module\Monitoring\Application\Forms\Command; use Icinga\Test\BaseTestCase; -require_once BaseTestCase::$moduleDir . '/monitoring/application/forms/Command/CommandForm.php'; -require_once BaseTestCase::$moduleDir . '/monitoring/application/forms/Command/WithChildrenCommandForm.php'; -require_once BaseTestCase::$moduleDir . '/monitoring/application/forms/Command/RescheduleNextCheckForm.php'; -require_once BaseTestCase::$libDir . '/Util/ConfigAwareFactory.php'; -require_once BaseTestCase::$libDir . '/Util/DateTimeFactory.php'; - -use \DateTimeZone; -use Icinga\Util\DateTimeFactory; - class RescheduleNextCheckFormTest extends BaseTestCase { const FORM_CLASS = 'Icinga\Module\Monitoring\Form\Command\RescheduleNextCheckForm'; - /** - * Set DateTimeFactory's time zone to UTC - * - * Utilizes singleton DateTimeFactory - * - * @backupStaticAttributes enabled - */ - public function setUp() - { - DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC'))); - } - public function testFormInvalidWhenChecktimeIsIncorrect() { $form = $this->createForm( diff --git a/modules/monitoring/test/php/application/forms/Command/ScheduleDowntimeFormTest.php b/modules/monitoring/test/php/application/forms/Command/ScheduleDowntimeFormTest.php index 47083d70c..5c7138b17 100644 --- a/modules/monitoring/test/php/application/forms/Command/ScheduleDowntimeFormTest.php +++ b/modules/monitoring/test/php/application/forms/Command/ScheduleDowntimeFormTest.php @@ -1,69 +1,16 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Test\Monitoring\Forms\Command; - -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Test/BaseTestCase.php'); -// @codingStandardsIgnoreEnd +namespace Tests\Icinga\Module\Monitoring\Application\Forms\Command; use Icinga\Test\BaseTestCase; -// @codingStandardsIgnoreStart -require_once 'Zend/Validate/Digits.php'; -require_once 'Zend/Validate/GreaterThan.php'; -require_once BaseTestCase::$libDir . '/Web/Form.php'; -require_once BaseTestCase::$libDir . '/Util/DateTimeFactory.php'; -require_once BaseTestCase::$libDir . '/Util/ConfigAwareFactory.php'; -require_once BaseTestCase::$moduleDir . '/monitoring/application/forms/Command/ScheduleDowntimeForm.php'; -// @codingStandardsIgnoreEnd - -use DateTimeZone; -use Icinga\Util\DateTimeFactory; -use Icinga\Module\Monitoring\Form\Command\ScheduleDowntimeForm; // Used by constant FORM_CLASS +use Icinga\Module\Monitoring\Form\Command\ScheduleDowntimeForm; class ScheduleDowntimeFormTest extends BaseTestCase { const FORM_CLASS = 'Icinga\Module\Monitoring\Form\Command\ScheduleDowntimeForm'; - /** - * Set up the default time zone - * - * Utilizes singleton DateTimeFactory - * - * @backupStaticAttributes enabled - */ - public function setUp() - { - date_default_timezone_set('UTC'); - DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC'))); - } - public function testCorrectFormElementCreation() { $formFixed = $this->createForm(self::FORM_CLASS); diff --git a/modules/monitoring/test/php/application/forms/Command/SubmitPassiveCheckResultTest.php b/modules/monitoring/test/php/application/forms/Command/SubmitPassiveCheckResultTest.php index 62ab06ffd..4c83294df 100644 --- a/modules/monitoring/test/php/application/forms/Command/SubmitPassiveCheckResultTest.php +++ b/modules/monitoring/test/php/application/forms/Command/SubmitPassiveCheckResultTest.php @@ -1,42 +1,10 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Test\Monitoring\Forms\Command; - -require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Test/BaseTestCase.php'); +namespace Tests\Icinga\Module\Monitoring\Application\Forms\Command; use Icinga\Test\BaseTestCase; - -require_once BaseTestCase::$libDir . '/Exception/ProgrammingError.php'; -require_once BaseTestCase::$moduleDir . '/monitoring/application/forms/Command/CommandForm.php'; -require_once BaseTestCase::$moduleDir . '/monitoring/application/forms/Command/SubmitPassiveCheckResultForm.php'; - use Icinga\Module\Monitoring\Form\Command\SubmitPassiveCheckResultForm; class SubmitPassiveCheckResultFormTest extends BaseTestCase diff --git a/modules/monitoring/test/php/application/views/helpers/MonitoringFlagsTest.php b/modules/monitoring/test/php/application/views/helpers/MonitoringFlagsTest.php index be3fd9cd0..e2bd0393a 100644 --- a/modules/monitoring/test/php/application/views/helpers/MonitoringFlagsTest.php +++ b/modules/monitoring/test/php/application/views/helpers/MonitoringFlagsTest.php @@ -1,12 +1,17 @@ '1', ); - $monitoringFlags = new \Zend_View_Helper_MonitoringFlags(); + $monitoringFlags = new Zend_View_Helper_MonitoringFlags(); $returnArray = $monitoringFlags->monitoringFlags((object)$testArray); $this->assertCount(6, $returnArray); @@ -47,7 +52,7 @@ class MonitoringFlagsTest extends \PHPUnit_Framework_TestCase 'flap_detection_enabled' => '0', ); - $monitoringFlags = new \Zend_View_Helper_MonitoringFlags(); + $monitoringFlags = new Zend_View_Helper_MonitoringFlags(); $returnArray = $monitoringFlags->monitoringFlags((object)$testArray); $this->assertCount(6, $returnArray); diff --git a/modules/monitoring/test/php/application/views/helpers/MonitoringPropertiesTest.php b/modules/monitoring/test/php/application/views/helpers/MonitoringPropertiesTest.php index 18b1daf2f..e602e0237 100644 --- a/modules/monitoring/test/php/application/views/helpers/MonitoringPropertiesTest.php +++ b/modules/monitoring/test/php/application/views/helpers/MonitoringPropertiesTest.php @@ -1,15 +1,17 @@ current_check_attempt = '5'; - $propertyHelper = new \Zend_View_Helper_MonitoringProperties(); + $propertyHelper = new Zend_View_Helper_MonitoringProperties(); $items = $propertyHelper->monitoringProperties($host); $this->assertEquals('5/10 (HARD state)', $items['Current Attempt']); @@ -77,14 +82,13 @@ class MonitoringPropertiesTest extends \PHPUnit_Framework_TestCase public function testOutput2() { - date_default_timezone_set("UTC"); $host = new HostStruct4Properties(); $host->current_check_attempt = '5'; $host->active_checks_enabled = '1'; $host->passive_checks_enabled = '0'; $host->is_flapping = '1'; - $propertyHelper = new \Zend_View_Helper_MonitoringProperties(); + $propertyHelper = new Zend_View_Helper_MonitoringProperties(); $items = $propertyHelper->monitoringProperties($host); $test = array( diff --git a/modules/monitoring/test/php/application/views/helpers/ResolveMacrosTest.php b/modules/monitoring/test/php/application/views/helpers/ResolveMacrosTest.php index f52202671..0f02f0743 100644 --- a/modules/monitoring/test/php/application/views/helpers/ResolveMacrosTest.php +++ b/modules/monitoring/test/php/application/views/helpers/ResolveMacrosTest.php @@ -1,64 +1,38 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Test\Modules\Monitoring\Application\Views\Helpers; - -require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Test/BaseTestCase.php'); +namespace Tests\Icinga\Modules\Monitoring\Application\Views\Helpers; +use \Mockery; +use \Zend_View_Helper_ResolveMacros; use Icinga\Test\BaseTestCase; -require_once 'Zend/View/Helper/Abstract.php'; -require_once BaseTestCase::$moduleDir . '/monitoring/application/views/helpers/ResolveMacros.php'; - -use \stdClass; +// @codingStandardsIgnoreStart +require_once realpath(BaseTestCase::$moduleDir . '/monitoring/application/views/helpers/ResolveMacros.php'); +// @codingStandardsIgnoreEnd class ResolveMacrosTest extends BaseTestCase { public function testHostMacros() { - $hostMock = new stdClass(); + $hostMock = Mockery::mock('host'); $hostMock->host_name = 'test'; $hostMock->host_address = '1.1.1.1'; - $helper = new \Zend_View_Helper_ResolveMacros(); + $helper = new Zend_View_Helper_ResolveMacros(); $this->assertEquals($helper->resolveMacros('$HOSTNAME$', $hostMock), $hostMock->host_name); $this->assertEquals($helper->resolveMacros('$HOSTADDRESS$', $hostMock), $hostMock->host_address); } public function testServiceMacros() { - $svcMock = new stdClass(); + $svcMock = Mockery::mock('service'); $svcMock->host_name = 'test'; $svcMock->host_address = '1.1.1.1'; $svcMock->service_description = 'a service'; - $helper = new \Zend_View_Helper_ResolveMacros(); + $helper = new Zend_View_Helper_ResolveMacros(); $this->assertEquals($helper->resolveMacros('$HOSTNAME$', $svcMock), $svcMock->host_name); $this->assertEquals($helper->resolveMacros('$HOSTADDRESS$', $svcMock), $svcMock->host_address); $this->assertEquals($helper->resolveMacros('$SERVICEDESC$', $svcMock), $svcMock->service_description); @@ -66,25 +40,25 @@ class ResolveMacrosTest extends BaseTestCase public function testCustomvars() { - $objectMock = new stdClass(); + $objectMock = Mockery::mock('object'); $objectMock->customvars = array( 'CUSTOMVAR' => 'test' ); - $helper = new \Zend_View_Helper_ResolveMacros(); + $helper = new Zend_View_Helper_ResolveMacros(); $this->assertEquals($helper->resolveMacros('$CUSTOMVAR$', $objectMock), $objectMock->customvars['CUSTOMVAR']); } public function testFaultyMacros() { - $hostMock = new \stdClass(); + $hostMock = Mockery::mock('host'); $hostMock->host_name = 'test'; $hostMock->customvars = array( 'HOST' => 'te', 'NAME' => 'st' ); - $helper = new \Zend_View_Helper_ResolveMacros(); + $helper = new Zend_View_Helper_ResolveMacros(); $this->assertEquals( $helper->resolveMacros('$$HOSTNAME$ $ HOSTNAME$ $HOST$NAME$', $hostMock), '$test $ HOSTNAME$ teNAME$' @@ -93,12 +67,12 @@ class ResolveMacrosTest extends BaseTestCase public function testMacrosWithSpecialCharacters() { - $objectMock = new \stdClass(); + $objectMock = Mockery::mock('object'); $objectMock->customvars = array( 'V€RY_SP3C|@L' => 'not too special!' ); - $helper = new \Zend_View_Helper_ResolveMacros(); + $helper = new Zend_View_Helper_ResolveMacros(); $this->assertEquals( $helper->resolveMacros('$V€RY_SP3C|@L$', $objectMock), $objectMock->customvars['V€RY_SP3C|@L'] diff --git a/modules/monitoring/test/php/library/Filter/Type/StatusFilterTest.php b/modules/monitoring/test/php/library/Monitoring/Filter/Type/StatusFilterTest.php similarity index 67% rename from modules/monitoring/test/php/library/Filter/Type/StatusFilterTest.php rename to modules/monitoring/test/php/library/Monitoring/Filter/Type/StatusFilterTest.php index 99fb1094d..84f76d135 100644 --- a/modules/monitoring/test/php/library/Filter/Type/StatusFilterTest.php +++ b/modules/monitoring/test/php/library/Monitoring/Filter/Type/StatusFilterTest.php @@ -1,49 +1,14 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Test\Modules\Monitoring\Library\Filter\Type; +namespace Tests\Icinga\Module\Monitoring\Filter\Type; use Icinga\Module\Monitoring\Filter\Type\StatusFilter; use Icinga\Filter\Type\TimeRangeSpecifier; use Icinga\Filter\Query\Node; use Icinga\Test\BaseTestCase; -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../../../library/Icinga/Test/BaseTestCase.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Query/Node.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/QueryProposer.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Type/FilterType.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Type/TimeRangeSpecifier.php'); -require_once realpath(BaseTestCase::$moduleDir .'/monitoring/library/Monitoring/Filter/Type/StatusFilter.php'); -// @codingStandardsIgnoreEnd - - class StatusFilterTest extends BaseTestCase { public function testOperatorProposal() @@ -140,4 +105,4 @@ class StatusFilterTest extends BaseTestCase 'Assert the right node to be the time specifier query (field)' ); } -} \ No newline at end of file +} diff --git a/modules/monitoring/test/php/library/Filter/UrlViewFilterTest.php b/modules/monitoring/test/php/library/Monitoring/Filter/UrlViewFilterTest.php similarity index 60% rename from modules/monitoring/test/php/library/Filter/UrlViewFilterTest.php rename to modules/monitoring/test/php/library/Monitoring/Filter/UrlViewFilterTest.php index 376bf7d5f..e7afd3911 100644 --- a/modules/monitoring/test/php/library/Filter/UrlViewFilterTest.php +++ b/modules/monitoring/test/php/library/Monitoring/Filter/UrlViewFilterTest.php @@ -1,37 +1,11 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Test\Modules\Monitoring\Library\Filter; -use Icinga\Filter\Filterable; -use Icinga\Filter\Query\Tree; +namespace Tests\Icinga\Module\Monitoring\Filter; + +use \Mockery; use Icinga\Module\Monitoring\Filter\Type\StatusFilter; -use Icinga\Filter\Type\TimeRangeSpecifier; use Icinga\Filter\Query\Node; use Icinga\Filter\Filter; use Icinga\Filter\Type\TextFilter; @@ -39,52 +13,19 @@ use Icinga\Filter\FilterAttribute; use Icinga\Module\Monitoring\Filter\UrlViewFilter; use Icinga\Test\BaseTestCase; -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../../library/Icinga/Test/BaseTestCase.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/QueryProposer.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/Filter.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/FilterAttribute.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/Domain.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/Query/Node.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/Query/Tree.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/Type/FilterType.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/Type/TextFilter.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Type/TimeRangeSpecifier.php'); -require_once realpath(BaseTestCase::$moduleDir .'/monitoring/library/Monitoring/Filter/Type/StatusFilter.php'); -require_once realpath(BaseTestCase::$moduleDir .'/monitoring/library/Monitoring/Filter/UrlViewFilter.php'); - -class FilterMock implements Filterable -{ - public function isValidFilterTarget($field) - { - return true; - } - - public function getMappedField($field) - { - return $field; - } - - public function applyFilter() - { - return true; - } - - public function clearFilter() - { - // TODO: Implement clearFilter() method. - } - - public function addFilter($filter) - { - // TODO: Implement addFilter() method. - } - - -} - class UrlViewFilterTest extends BaseTestCase { + public function setUp() + { + parent::setUp(); + $this->filterMock = Mockery::mock('Icinga\Filter\Filterable'); + $this->filterMock->shouldReceive('isValidFilterTarget')->with(Mockery::any())->andReturn(true) + ->shouldReceive('getMappedField')->andReturnUsing(function ($f) { return $f; }) + ->shouldReceive('applyFilter')->andReturn(true) + ->shouldReceive('clearFilter')->andReturnNull() + ->shouldReceive('addFilter')->with(Mockery::any())->andReturnNull(); + } + public function testUrlParamCreation() { $this->markTestSkipped('Or queries are disabled'); @@ -113,7 +54,7 @@ class UrlViewFilterTest extends BaseTestCase . ' and attr5 is UP'; $tree = $searchEngine->createQueryTreeForFilter($query); - $filterFactory = new UrlViewFilter(new FilterMock()); + $filterFactory = new UrlViewFilter($this->filterMock); $uri = $filterFactory->fromTree($tree); $this->assertEquals( 'attr1!=Hans+wurst|attr2=%2Asomething%2A&attr3=bla%2A|attr4=1&host_last_state_change>=yesterday&attr5=0', @@ -124,7 +65,7 @@ class UrlViewFilterTest extends BaseTestCase public function testTreeFromSimpleKeyValueUrlCreation() { - $filterFactory = new UrlViewFilter(new FilterMock()); + $filterFactory = new UrlViewFilter($this->filterMock); $tree = $filterFactory->parseUrl('attr1!=Hans+Wurst'); $this->assertEquals( $tree->root->type, @@ -152,7 +93,7 @@ class UrlViewFilterTest extends BaseTestCase { $this->markTestSkipped("OR queries are disabled"); - $filterFactory = new UrlViewFilter(new FilterMock()); + $filterFactory = new UrlViewFilter($this->filterMock); $query = 'attr1!=Hans+Wurst&test=test123|bla=1'; $tree = $filterFactory->parseUrl($query); $this->assertEquals($tree->root->type, Node::TYPE_AND, 'Assert the root of the filter tree to be an AND node'); @@ -162,7 +103,7 @@ class UrlViewFilterTest extends BaseTestCase public function testImplicitConjunctionInUrl() { $this->markTestSkipped("OR queries are disabled"); - $filterFactory = new UrlViewFilter(new FilterMock()); + $filterFactory = new UrlViewFilter($this->filterMock); $query = 'attr1!=Hans+Wurst&test=test123|bla=1|2|3'; $tree = $filterFactory->parseUrl($query); $this->assertEquals($tree->root->type, Node::TYPE_AND, 'Assert the root of the filter tree to be an AND node'); @@ -175,7 +116,7 @@ class UrlViewFilterTest extends BaseTestCase public function testMissingValuesInQueries() { - $filterFactory = new UrlViewFilter(new FilterMock()); + $filterFactory = new UrlViewFilter($this->filterMock); $queryStr = 'attr1!=Hans+Wurst&test='; $tree = $filterFactory->parseUrl($queryStr); $query = $filterFactory->fromTree($tree); @@ -184,7 +125,7 @@ class UrlViewFilterTest extends BaseTestCase public function testErrorInQueries() { - $filterFactory = new UrlViewFilter(new FilterMock()); + $filterFactory = new UrlViewFilter($this->filterMock); $queryStr = 'test=&attr1!=Hans+Wurst'; $tree = $filterFactory->parseUrl($queryStr); $query = $filterFactory->fromTree($tree); @@ -193,7 +134,7 @@ class UrlViewFilterTest extends BaseTestCase public function testSenselessConjunctions() { - $filterFactory = new UrlViewFilter(new FilterMock()); + $filterFactory = new UrlViewFilter($this->filterMock); $queryStr = 'test=&|/5/|&attr1!=Hans+Wurst'; $tree = $filterFactory->parseUrl($queryStr); $query = $filterFactory->fromTree($tree); @@ -203,12 +144,11 @@ class UrlViewFilterTest extends BaseTestCase public function testRandomString() { $filter = ''; - $filterFactory = new UrlViewFilter(new FilterMock()); + $filterFactory = new UrlViewFilter($this->filterMock); for ($i=0; $i<10;$i++) { $filter .= str_shuffle('&|ds& wra =!<>|dsgs=,-G'); $tree = $filterFactory->parseUrl($filter); } - } } diff --git a/modules/monitoring/test/php/library/Monitoring/Plugin/PerfdataSetTest.php b/modules/monitoring/test/php/library/Monitoring/Plugin/PerfdataSetTest.php new file mode 100644 index 000000000..86c0f71a7 --- /dev/null +++ b/modules/monitoring/test/php/library/Monitoring/Plugin/PerfdataSetTest.php @@ -0,0 +1,101 @@ +assertArrayHasKey( + 'key1', + $pset->perfdata, + 'PerfdataSet does not correctly parse valid simple labels' + ); + $this->assertArrayHasKey( + 'key2', + $pset->perfdata, + 'PerfdataSet does not correctly parse valid simple labels' + ); + $this->assertArrayHasKey( + 'key3', + $pset->perfdata, + 'PerfdataSet does not correctly parse valid simple labels' + ); + } + + public function testWhetherNonQuotedPerfdataLablesWithSpacesAreProperlyParsed() + { + $pset = PerfdataSetWithPublicData::fromString('key 1=val1 key 1 + 1=val2'); + $this->assertArrayHasKey( + 'key 1', + $pset->perfdata, + 'PerfdataSet does not correctly parse non quoted labels with spaces' + ); + $this->assertArrayHasKey( + 'key 1 + 1', + $pset->perfdata, + 'PerfdataSet does not correctly parse non quoted labels with spaces' + ); + } + + public function testWhetherValidQuotedPerfdataLabelsAreProperlyParsed() + { + $pset = PerfdataSetWithPublicData::fromString('\'key 1\'=val1 "key 2"=val2'); + $this->assertArrayHasKey( + 'key 1', + $pset->perfdata, + 'PerfdataSet does not correctly parse valid quoted labels' + ); + $this->assertArrayHasKey( + 'key 2', + $pset->perfdata, + 'PerfdataSet does not correctly parse valid quoted labels' + ); + } + + public function testWhetherInvalidQuotedPerfdataLabelsAreProperlyParsed() + { + $pset = PerfdataSetWithPublicData::fromString('\'key 1=val1 key 2"=val2'); + $this->assertArrayHasKey( + 'key 1', + $pset->perfdata, + 'PerfdataSet does not correctly parse invalid quoted labels' + ); + $this->assertArrayHasKey( + 'key 2"', + $pset->perfdata, + 'PerfdataSet does not correctly parse invalid quoted labels' + ); + } + + /** + * @depends testWhetherValidSimplePerfdataLabelsAreProperlyParsed + */ + public function testWhetherAPerfdataSetIsIterable() + { + $pset = PerfdataSet::fromString('key=value'); + foreach ($pset as $label => $value) { + $this->assertEquals('key', $label); + return; + } + + $this->fail('PerfdataSet objects cannot be iterated'); + } + + public function testWhetherPerfdataSetsCanBeInitializedWithEmptyStrings() + { + $pset = PerfdataSetWithPublicData::fromString(''); + $this->assertEmpty($pset->perfdata, 'PerfdataSet::fromString does not accept emtpy strings'); + } +} diff --git a/modules/monitoring/test/php/library/Monitoring/Plugin/PerfdataTest.php b/modules/monitoring/test/php/library/Monitoring/Plugin/PerfdataTest.php new file mode 100644 index 000000000..9bb32ffd8 --- /dev/null +++ b/modules/monitoring/test/php/library/Monitoring/Plugin/PerfdataTest.php @@ -0,0 +1,352 @@ +assertEquals( + 1337.0, + Perfdata::fromString('1337')->getValue(), + 'Perfdata::getValue does not return correct values' + ); + $this->assertEquals( + 1337.0, + Perfdata::fromString('1337;;;;')->getValue(), + 'Perfdata::getValue does not return correct values' + ); + } + + public function testWhetherDecimalValuesAreCorrectlyParsed() + { + $this->assertEquals( + 1337.5, + Perfdata::fromString('1337.5')->getValue(), + 'Perfdata objects do not parse decimal values correctly' + ); + $this->assertEquals( + 1337.5, + Perfdata::fromString('1337.5B')->getValue(), + 'Perfdata objects do not parse decimal values correctly' + ); + } + + public function testWhetherGetValueReturnsNullForInvalidOrUnknownValues() + { + $this->assertNull( + Perfdata::fromString('U')->getValue(), + 'Perfdata::getValue does not return null for unknown values' + ); + $this->assertNull( + Perfdata::fromString('i am not a value')->getValue(), + 'Perfdata::getValue does not return null for invalid values' + ); + } + + public function testWhetherGetWarningTresholdReturnsCorrectValues() + { + $this->assertEquals( + '10', + Perfdata::fromString('1;10')->getWarningTreshold(), + 'Perfdata::getWarningTreshold does not return correct values' + ); + $this->assertEquals( + '10:', + Perfdata::fromString('1;10:')->getWarningTreshold(), + 'Perfdata::getWarningTreshold does not return correct values' + ); + $this->assertEquals( + '~:10', + Perfdata::fromString('1;~:10')->getWarningTreshold(), + 'Perfdata::getWarningTreshold does not return correct values' + ); + $this->assertEquals( + '10:20', + Perfdata::fromString('1;10:20')->getWarningTreshold(), + 'Perfdata::getWarningTreshold does not return correct values' + ); + $this->assertEquals( + '@10:20', + Perfdata::fromString('1;@10:20')->getWarningTreshold(), + 'Perfdata::getWarningTreshold does not return correct values' + ); + } + + public function testWhetherGetCriticalTresholdReturnsCorrectValues() + { + $this->assertEquals( + '10', + Perfdata::fromString('1;;10')->getCriticalTreshold(), + 'Perfdata::getCriticalTreshold does not return correct values' + ); + $this->assertEquals( + '10:', + Perfdata::fromString('1;;10:')->getCriticalTreshold(), + 'Perfdata::getCriticalTreshold does not return correct values' + ); + $this->assertEquals( + '~:10', + Perfdata::fromString('1;;~:10')->getCriticalTreshold(), + 'Perfdata::getCriticalTreshold does not return correct values' + ); + $this->assertEquals( + '10:20', + Perfdata::fromString('1;;10:20')->getCriticalTreshold(), + 'Perfdata::getCriticalTreshold does not return correct values' + ); + $this->assertEquals( + '@10:20', + Perfdata::fromString('1;;@10:20')->getCriticalTreshold(), + 'Perfdata::getCriticalTreshold does not return correct values' + ); + } + + public function testWhetherGetMinimumValueReturnsCorrectValues() + { + $this->assertEquals( + 1337.0, + Perfdata::fromString('1;;;1337')->getMinimumValue(), + 'Perfdata::getMinimumValue does not return correct values' + ); + $this->assertEquals( + 1337.5, + Perfdata::fromString('1;;;1337.5')->getMinimumValue(), + 'Perfdata::getMinimumValue does not return correct values' + ); + } + + public function testWhetherGetMaximumValueReturnsCorrectValues() + { + $this->assertEquals( + 1337.0, + Perfdata::fromString('1;;;;1337')->getMaximumValue(), + 'Perfdata::getMaximumValue does not return correct values' + ); + $this->assertEquals( + 1337.5, + Perfdata::fromString('1;;;;1337.5')->getMaximumValue(), + 'Perfdata::getMaximumValue does not return correct values' + ); + } + + public function testWhetherMissingValuesAreReturnedAsNull() + { + $perfdata = Perfdata::fromString('1;;3;5'); + $this->assertNull( + $perfdata->getWarningTreshold(), + 'Perfdata objects do not return null for missing warning tresholds' + ); + $this->assertNull( + $perfdata->getMaximumValue(), + 'Perfdata objects do not return null for missing maximum values' + ); + } + + /** + * @depends testWhetherGetValueReturnsValidValues + */ + public function testWhetherValuesAreIdentifiedAsNumber() + { + $this->assertTrue( + Perfdata::fromString('666')->isNumber(), + 'Perfdata objects do not identify ordinary digits as number' + ); + } + + /** + * @depends testWhetherGetValueReturnsValidValues + */ + public function testWhetherValuesAreIdentifiedAsSeconds() + { + $this->assertTrue( + Perfdata::fromString('666s')->isSeconds(), + 'Perfdata objects do not identify seconds as seconds' + ); + $this->assertTrue( + Perfdata::fromString('666us')->isSeconds(), + 'Perfdata objects do not identify microseconds as seconds' + ); + $this->assertTrue( + Perfdata::fromString('666ms')->isSeconds(), + 'Perfdata objects do not identify milliseconds as seconds' + ); + } + + /** + * @depends testWhetherGetValueReturnsValidValues + */ + public function testWhetherValuesAreIdentifiedAsPercentage() + { + $this->assertTrue( + Perfdata::fromString('66%')->isPercentage(), + 'Perfdata objects do not identify percentages as percentages' + ); + } + + /** + * @depends testWhetherValuesAreIdentifiedAsPercentage + */ + public function testWhetherMinAndMaxAreNotRequiredIfUnitIsInPercent() + { + $perfdata = Perfdata::fromString('1%'); + $this->assertEquals( + 0.0, + $perfdata->getMinimumValue(), + 'Perfdata objects do not set minimum value to 0 if UOM is %' + ); + $this->assertEquals( + 100.0, + $perfdata->getMaximumValue(), + 'Perfdata objects do not set maximum value to 100 if UOM is %' + ); + } + + /** + * @depends testWhetherGetValueReturnsValidValues + */ + public function testWhetherValuesAreIdentifiedAsBytes() + { + $this->assertTrue( + Perfdata::fromString('66666B')->isBytes(), + 'Perfdata objects do not identify bytes as bytes' + ); + $this->assertTrue( + Perfdata::fromString('6666KB')->isBytes(), + 'Perfdata objects do not identify kilobytes as bytes' + ); + $this->assertTrue( + Perfdata::fromString('666MB')->isBytes(), + 'Perfdata objects do not identify megabytes as bytes' + ); + $this->assertTrue( + Perfdata::fromString('66GB')->isBytes(), + 'Perfdata objects do not identify gigabytes as bytes' + ); + $this->assertTrue( + Perfdata::fromString('6TB')->isBytes(), + 'Perfdata objects do not identify terabytes as bytes' + ); + } + + /** + * @depends testWhetherGetValueReturnsValidValues + */ + public function testWhetherValuesAreIdentifiedAsCounter() + { + $this->assertTrue( + Perfdata::fromString('123c')->isCounter(), + 'Perfdata objects do not identify counters as counters' + ); + } + + /** + * @depends testWhetherValuesAreIdentifiedAsSeconds + */ + public function testWhetherMicroSecondsAreCorrectlyConvertedToSeconds() + { + $this->assertEquals( + 666 / pow(10, 6), + Perfdata::fromString('666us')->getValue(), + 'Perfdata objects do not correctly convert microseconds to seconds' + ); + } + + /** + * @depends testWhetherValuesAreIdentifiedAsSeconds + */ + public function testWhetherMilliSecondsAreCorrectlyConvertedToSeconds() + { + $this->assertEquals( + 666 / pow(10, 3), + Perfdata::fromString('666ms')->getValue(), + 'Perfdata objects do not correctly convert microseconds to seconds' + ); + } + + /** + * @depends testWhetherValuesAreIdentifiedAsPercentage + */ + public function testWhetherPercentagesAreHandledCorrectly() + { + $this->assertEquals( + 66.0, + Perfdata::fromString('66%')->getPercentage(), + 'Perfdata objects do not correctly handle native percentages' + ); + $this->assertEquals( + 50.0, + Perfdata::fromString('0;;;-250;250')->getPercentage(), + 'Perfdata objects do not correctly convert suitable values to percentages' + ); + $this->assertNull( + Perfdata::fromString('50')->getPercentage(), + 'Perfdata objects do return a percentage though their unit is not % and no maximum is given' + ); + $this->assertNull( + Perfdata::fromString('25;;;50;100')->getPercentage(), + 'Perfdata objects do return a percentage though their value is lower than it\'s allowed minimum' + ); + } + + /** + * @depends testWhetherValuesAreIdentifiedAsBytes + */ + public function testWhetherKiloBytesAreCorrectlyConvertedToBytes() + { + $this->assertEquals( + 6666.0 * pow(2, 10), + Perfdata::fromString('6666KB')->getValue(), + 'Perfdata objects do not corretly convert kilobytes to bytes' + ); + } + + /** + * @depends testWhetherValuesAreIdentifiedAsBytes + */ + public function testWhetherMegaBytesAreCorrectlyConvertedToBytes() + { + $this->assertEquals( + 666.0 * pow(2, 20), + Perfdata::fromString('666MB')->getValue(), + 'Perfdata objects do not corretly convert megabytes to bytes' + ); + } + + /** + * @depends testWhetherValuesAreIdentifiedAsBytes + */ + public function testWhetherGigaBytesAreCorrectlyConvertedToBytes() + { + $this->assertEquals( + 66.0 * pow(2, 30), + Perfdata::fromString('66GB')->getValue(), + 'Perfdata objects do not corretly convert gigabytes to bytes' + ); + } + + /** + * @depends testWhetherValuesAreIdentifiedAsBytes + */ + public function testWhetherTeraBytesAreCorrectlyConvertedToBytes() + { + $this->assertEquals( + 6.0 * pow(2, 40), + Perfdata::fromString('6TB')->getValue(), + 'Perfdata objects do not corretly convert terabytes to bytes' + ); + } +} diff --git a/modules/monitoring/test/php/testlib/MonitoringControllerTest.php b/modules/monitoring/test/php/testlib/MonitoringControllerTest.php deleted file mode 100644 index f2409cacf..000000000 --- a/modules/monitoring/test/php/testlib/MonitoringControllerTest.php +++ /dev/null @@ -1,310 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Test\Monitoring\Testlib; - -require_once 'Zend/View.php'; -require_once 'Zend/Test/PHPUnit/ControllerTestCase.php'; - -use \Zend_View; -use \Zend_Config; -use \Zend_Test_PHPUnit_ControllerTestCase; -use \Icinga\Protocol\Statusdat\Reader; -use \Icinga\Web\Controller\ActionController; -use \Test\Monitoring\Testlib\DataSource\TestFixture; -use \Test\Monitoring\Testlib\DataSource\DataSourceTestSetup; -use Icinga\Module\Monitoring\Backend; -use Icinga\Data\ResourceFactory; - -/** - * Base class for monitoring controllers that loads required dependencies - * and allows easier setup of tests - * - * Example: - * - * - * class MyControllerTest extends MonitoringControllerTest - * { - * public function testSomething() - * { - * // Create a test fixture - * $fixture = new TestFixture() - * $fixture->addHost('host', 0)->addService(...)->..->; - * - * $this->setupFixture($fixture, "mysql"); // setup the fixture - * $controller = $this->requireController('MyController', 'mysql'); - * // controller is now the Zend controller instance, perform an action - * $controller->myAction(); - * $result = $controller->view->hosts->fetchAll(); - * // assert stuff - * } - * } - */ -abstract class MonitoringControllerTest extends Zend_Test_PHPUnit_ControllerTestCase -{ - /** - * The module directory for requiring modules (is relative to the source file) - * @var string - */ - private $moduleDir = ""; - - /** - * The application directory for requirying library files (is relative to the source file) - * @var string - */ - private $appDir = ""; - - /** - * Require necessary libraries on test creation - * - * This is called for every test and assures that all required libraries for the controllers - * are loaded. If you need additional dependencies you should overwrite this method, call the parent - * and then require your classes - * - * @backupStaticAttributes enabled - */ - public function setUp() - { - $this->moduleDir = dirname(__FILE__) . '/../../../'; - $this->appDir = $this->moduleDir.'../../library/Icinga/'; - $module = $this->moduleDir; - $app = $this->appDir; - set_include_path(get_include_path().':'.$module); - set_include_path(get_include_path().':'.$app); - - require_once('Zend/Config.php'); - require_once('Zend/Db.php'); - require_once(dirname(__FILE__) . '/datasource/DataSourceTestSetup.php'); - - $this->requireBase(); - $this->requireViews(); - - ResourceFactory::setConfig( - new Zend_Config(array( - 'statusdat-unittest' => array( - 'type' => 'statusdat', - 'status_file' => '/tmp/teststatus.dat', - 'object_file' => '/tmp/testobjects.cache', - 'no_cache' => true - ), - 'ido-mysql-unittest' => array( - 'type' => 'db', - 'db' => 'mysql', - 'host' => 'localhost', - 'username' => 'icinga_unittest', - 'password' => 'icinga_unittest', - 'dbname' => 'icinga_unittest' - ), - 'ido-pgsql-unittest' => array( - 'type' => 'db', - 'db' => 'mysql', - 'host' => 'localhost', - 'username' => 'icinga_unittest', - 'password' => 'icinga_unittest', - 'dbname' => 'icinga_unittest' - ) - )) - ); - Backend::setConfig( - new Zend_Config(array( - 'statusdat-unittest' => array( - 'type' => 'statusdat', - 'resource' => 'statusdat-unittest' - ), - 'ido-mysql-unittest' => array( - 'type' => 'ido', - 'resource' => 'ido-mysql-unittest' - ), - 'ido-pgsql-unittest' => array( - 'type' => 'ido', - 'resource' => 'ido-pgsql-unittest' - ) - )) - ); - } - - /** - * Require base application and data retrieval classes from the Icinga Library - * - */ - private function requireBase() - { - require_once('Application/Benchmark.php'); - require_once('Data/BaseQuery.php'); - require_once('Data/DatasourceInterface.php'); - require_once('Data/Db/Connection.php'); - require_once('Data/Db/Query.php'); - require_once('Exception/ProgrammingError.php'); - require_once('Web/Widget/SortBox.php'); - require_once('Web/Widget/FilterBox.php'); - require_once('Web/Widget/FilterBadgeRenderer.php'); - require_once('library/Monitoring/Backend.php'); - require_once('library/Monitoring/Controller.php'); - - } - - /** - * Require all defined IDO queries in this module - * - */ - private function requireIDOQueries() - { - require_once('library/Monitoring/Backend/Ido/Query/IdoQuery.php'); - $this->requireFolder('library/Monitoring/Backend/Ido/Query'); - } - - /** - * Require all php files in the folder $folder - * - * @param $folder The path to the folder containing PHP files - */ - private function requireFolder($folder) - { - $module = $this->moduleDir; - $views = scandir($module.$folder); - foreach ($views as $view) { - if (!preg_match('/php$/', $view)) { - continue; - } - require_once(realpath($module.$folder."/".$view)); - } - } - - /** - * Require all views and queries from the statusdat backen - * - */ - private function requireStatusDatQueries() - { - require_once(realpath($this->moduleDir.'/library/Monitoring/Backend/Statusdat/Query/StatusdatQuery.php')); - $this->requireFolder('library/Monitoring/Backend/Statusdat'); - $this->requireFolder('library/Monitoring/Backend/Statusdat/Query'); - } - - /** - * Require all (generic) view classes from the monitoring module - */ - private function requireViews() - { - $module = $this->moduleDir; - - } - - /** - * Require and set up a controller $controller using the backend type specified at $backend - * - * @param string $controller The name of the controller tu use - * (must be under monitoring/application/controllers) - * @param string $backend The backend to use ('mysql', 'pgsql' or 'statusdat') - * @return ModuleActionController The newly created controller - */ - public function requireController($controller, $backend) - { - require_once($this->moduleDir . '/library/Monitoring/Controller.php'); - require_once($this->moduleDir . '/application/controllers/'.$controller.'.php'); - $controllerName = '\Monitoring_'.ucfirst($controller); - $request = $this->getRequest(); - if ($backend == 'statusdat') { - $this->requireStatusDatQueries(); - $request->setParam('backend', 'statusdat-unittest'); - } else { - $this->requireStatusDatQueries(); - $request->setParam('backend', "ido-$backend-unittest"); - } - /** @var ActionController $controller */ - $controller = new $controllerName( - $request, - $this->getResponse(), - array('noInit' => true) - ); - $controller->setBackend($this->getBackendFor($backend)); - - // Many controllers need a view to work properly - $controller->view = new Zend_View(); - - return $controller; - } - - /** - * Create a new backend and insert the given fixture into it - * - * @param TestFixture $fixture The TestFixture to create - * @param string $type The type of the backend ('mysql', 'pgsql' or 'statusdat') - */ - public function setupFixture(TestFixture $fixture, $type) - { - $dbInstance = new DataSourceTestSetup($type); - $dbInstance->setup(); - $dbInstance->insert($fixture); - } - - /** - * Set up and configure a new testbackend for the given type - * - * @param string $type The type of the backend 'mysql', 'pgsql' or 'statusdat' - * @return Ido|Statusdat The newly created backend - */ - public function getBackendFor($type) - { - if ($type == "mysql" || $type == "pgsql") { - $this->requireIDOQueries(); - $backendConfig = new Zend_Config(array( - 'type' => 'ido' - )); - $resourceConfig = new Zend_Config( - array( - 'type' => 'db', - 'db' => $type, - 'host' => "localhost", - 'username' => "icinga_unittest", - 'password' => "icinga_unittest", - 'dbname' => "icinga_unittest" - ) - ); - return new Backend($backendConfig, $resourceConfig); - } elseif ($type == "statusdat") { - $this->requireStatusDatQueries(); - $backendConfig = new Zend_Config(array( - 'type' => 'statusdat' - )); - $resourceConfig = new Zend_Config( - array( - 'type' => 'statusdat', - 'status_file' => '/tmp/teststatus.dat', - 'object_file' => '/tmp/testobjects.cache', - 'no_cache' => true - ) - ); - return new Backend( - $backendConfig, - $resourceConfig - ); - } - } -} diff --git a/modules/monitoring/test/php/testlib/datasource/DataSourceTestSetup.php b/modules/monitoring/test/php/testlib/datasource/DataSourceTestSetup.php deleted file mode 100644 index 859ecd576..000000000 --- a/modules/monitoring/test/php/testlib/datasource/DataSourceTestSetup.php +++ /dev/null @@ -1,155 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Test\Monitoring\Testlib\DataSource; - -require_once(dirname(__FILE__).'/strategies/InsertionStrategy.php'); -require_once(dirname(__FILE__).'/strategies/SetupStrategy.php'); - -require_once(dirname(__FILE__).'/strategies/MySQLSetupStrategy.php'); -require_once(dirname(__FILE__).'/strategies/PgSQLSetupStrategy.php'); -require_once(dirname(__FILE__).'/strategies/PDOInsertionStrategy.php'); - -require_once(dirname(__FILE__).'/strategies/StatusdatInsertionStrategy.php'); -require_once(dirname(__FILE__).'/strategies/StatusdatSetupStrategy.php'); - -require_once(dirname(__FILE__).'/TestFixture.php'); - -use \Test\Monitoring\Testlib\Datasource\Strategies\InsertionStrategy; -use \Test\Monitoring\Testlib\Datasource\Strategies\SetupStrategy; -use \Test\Monitoring\Testlib\Datasource\Strategies\MySQLSetupStrategy; -use \Test\Monitoring\Testlib\Datasource\Strategies\PgSQLSetupStrategy; -use \Test\Monitoring\Testlib\Datasource\Strategies\PDOInsertionStrategy; -use \Test\Monitoring\Testlib\Datasource\Strategies\StatusdatInsertionStrategy; -use \Test\Monitoring\Testlib\Datasource\Strategies\StatusdatSetupStrategy; - -/** - * Fascade class that handles creation of test-fixture backends - * - * This class handles the creation and combination of SetupStrategies and InsertionStrategy - * when testing controllers/queries with different backends. - * - * Example: - * - * // TestFixtures contain the objects that should be written for testing - * $fixture = new TestFixture(); - * $fixture->addHost(..)->... // setup fixture - * - * $ds = new DataSourceTestSetup('mysql'); - * $ds->setup(); // create a blank datasource - * $ds->insert($fixture); - * - * - * - */ -class DataSourceTestSetup implements SetupStrategy, InsertionStrategy -{ - /** - * The SetupStrategy that is used on 'setup' - * @var \Test\Monitoring\Testlib\Datasource\Strategies\StatusdatSetupStrategy - */ - private $setupStrategy; - - /** - * The InsertionStrategy that is used on 'insert' - * @var \Test\Monitoring\Testlib\Datasource\Strategies\StatusdatInsertionStrategy - */ - private $insertionStrategy; - - /** - * Create a DataSource for the backend $type. - * - * On creation, a suitable setup/insert combination will be used - * for the provided backend, so the caller needn't to care about which - * setup or insertion strategy he wants to use. - * - * @param String $type The type of the backend (currently 'mysql', 'pgsql' and 'statusdat') - */ - public function __construct($type) - { - if ($type == 'mysql') { - $this->setupStrategy = new MySQLSetupStrategy(); - $this->insertionStrategy = new PDOInsertionStrategy(); - $this->insertionStrategy->datetimeFormat = "Y-m-d H:i:s"; - - } elseif ($type == 'pgsql') { - $this->setupStrategy = new PgSQLSetupStrategy(); - $this->insertionStrategy = new PDOInsertionStrategy(); - $this->insertionStrategy->datetimeFormat = "Y-m-d H:i:s"; - } elseif ($type == 'statusdat') { - $this->setupStrategy = new StatusdatSetupStrategy(); - $this->insertionStrategy = new StatusdatInsertionStrategy(); - } else { - throw new \Exception('Unsupported backend '.$type); - } - } - - /** - * Insert a testfixture into this datasource - * - * @param TestFixture $fixture The fixture to insert into the datasource - */ - public function insert(TestFixture $fixture) { - $this->insertionStrategy->insert($fixture); - } - - /** - * Create a blank datasource that can be filled with TestFixtures afterwards - * - * @param String $version An (optional) version to use for creation - * @param mixed $connection An (optional) connection to use for this datasource - */ - public function setup($version = null, $connection = null) - { - $c = $this->setupStrategy->setup($version, $connection); - - $this->insertionStrategy->setConnection($c); - } - - /** - * Remove all testdata created in this datasource - * - * @param mixed $connection An optional connection to use for clean up - */ - public function teardown($connection = null) - { - $this->setupStrategy->teardown($connection); - } - - /** - * Sets the connection to use for writing to this datasource - * - * @param mixed $connection The connection to use. The actual type depends - * on the used backend - */ - public function setConnection($connection) - { - $this->insertionStrategy->setConnection($connection); - } -} diff --git a/modules/monitoring/test/php/testlib/datasource/TestFixture.php b/modules/monitoring/test/php/testlib/datasource/TestFixture.php deleted file mode 100644 index 7eb2cd406..000000000 --- a/modules/monitoring/test/php/testlib/datasource/TestFixture.php +++ /dev/null @@ -1,586 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Test\Monitoring\Testlib\DataSource; - -/** - * Status flags for objects - * - */ -class ObjectFlags { - /** - * 1 if the test host is flapping, otherwise 0 - * @var int - */ - public $flapping = 0; - - /** - * 1 if the test host has notifications enabled, otherwise 0 - * @var int - */ - public $notifications = 1; - - /** - * 1 if the test host is active, otherwise 0 - * @var int - */ - public $active_checks = 1; - - /** - * 1 if the test host allows passive checks, otherwise 0 - * @var int - */ - public $passive_checks = 1; - - /** - * 1 if the test host is acknowledged, otherwise 0 - * @var int - */ - public $acknowledged = 0; - - /** - * 1 if the test host is in a downtime, otherwise 0 - * @var int - */ - public $in_downtime = 0; - - /** - * 1 if the test host is pending, otherwise 0 - * @var int - */ - public $is_pending = 0; - - /** - * The last check and state change time as a UNIX timestamp - * @var int - */ - public $time = 0; - - /** - * Create a new ObjectFlags instance with default values - * - * @param int $ageInSeconds How old this check should be in seconds - */ - public function __construct($ageInSeconds = null) - { - if(!is_int($ageInSeconds)) - $ageInSeconds = 0; - $this->time = time()-$ageInSeconds; - } - - /** - * Create a new ObjectFlags object that is in 'flapping' state - * - * @return ObjectFlags - */ - public static function FLAPPING() - { - $flags = new ObjectFlags(); - $flags->flapping = 0; - return $flags; - } - - /** - * Create a new ObjectFlags object that is in 'pending' state - * - * @return ObjectFlags - */ - public static function PENDING() - { - $flags = new ObjectFlags(); - $flags->is_pending = 1; - return $flags; - } - - /** - * Create a new ObjectFlags object that is in 'notifications_disabled' state - * - * @return ObjectFlags - */ - public static function DISABLE_NOTIFICATIONS() - { - $flags = new ObjectFlags(); - $flags->notifications = 0; - return $flags; - } - - /** - * Create a new ObjectFlags object that has active checks disabled but passive enabled - * - * @return ObjectFlags - */ - public static function PASSIVE_ONLY() - { - $flags = new ObjectFlags(); - $flags->active_checks = 0; - return $flags; - } - - /** - * Create a new ObjectFlags object that has passive checks disabled but active enabled - * - * @return ObjectFlags - */ - public static function ACTIVE_ONLY() - { - $flags = new ObjectFlags(); - $flags->passive_checks = 0; - return $flags; - } - - /** - * Create a new ObjectFlags object that is neither active nor passive - * - * @return ObjectFlags - */ - public static function DISABLED() { - $flags = new ObjectFlags(); - $flags->passive_checks = 0; - $flags->active_checks = 0; - return $flags; - } - - /** - * Create a new ObjectFlags object that is in 'acknowledged' state - * - * @return ObjectFlags - */ - public static function ACKNOWLEDGED() - { - $flags = new ObjectFlags(); - $flags->acknowledged = 1; - return $flags; - } - - /** - * Create a new ObjectFlags object that is in a downtime - * - * @return ObjectFlags - */ - public static function IN_DOWNTIME() - { - $flags = new ObjectFlags(); - $flags->in_downtime = 1; - return $flags; - } -} - -/** - * Internal class that adds an object scope on Fixture operations - * - * This class allows to use $fixture->addHost('host',0)->addService() instead('svc') - * of $fixture->addHost('host',0); $fixture->addService('host', 'svc') as it encapsulates - * the scope of the last called object and automatically adds it as the first parameter - * of the next call. - * - */ -class TestFixtureObjectClosure -{ - /** - * The object (hostname or hostname/servicename pair) this scope represents - * @var String|array - */ - private $scope; - - /** - * The Testfixture to operate on - * @var TestFixture - */ - private $environment; - - /** - * Create a new scope using the TestFixture with the given host / service - * as the scope - * - * @param TestFixture $environment The testfixture to use for subsequent calls - * @param $scope The scope to prepend to all further calls - */ - public function __construct(TestFixture $environment, $scope) - { - $this->scope = $scope; - $this->environment = $environment; - } - - /** - * Magic method that forwards all function calls to the environment - * but prepends the scope. - * - * A call func($arg1) to this class would be rewritten to $environment->func($scope, $arg1) - * - * @param string $string The method that should be called with this scope - * @param array $arguments The arguments the user passed to the function - * @return mixed The result of the function call - */ - public function __call($string, $arguments) - { - $callArg = array($this->scope); - $args = array_merge($callArg, $arguments); - return call_user_func_array(array($this->environment, $string), $args); - } -} - -/** - * Create test-states that can be persisted to different backends - * using DataSourceTestSetup. - * - * This class provides not all fields used in monitoring, but the most - * important ones (and the ones that are missing should be added during - * developmen). - * - * Usage: - * - * $fixture = new TestFixture(); - * // adding a new critical, but acknowledged host - * $fixture->addHost("hostname", 1, ObjectFlags::ACKNOWLEDGED()) - * - * // add a comment to the host (this has to be done before adding services) - * ->addComment("author", "comment text") - * - * // assign to hostgroup - * ->addToHostgroup("myHosts") - * - * // and add three services to this host - * ->addService("svc1", 0) // Service is ok - * ->addService("svc2", 1, ObjectFlags::PASSIVE) // service is warning and passive - * ->addService("svc3", 2, null, array("notes_url" => "test.html")) // critical with notes url - * ->addComment("author", "what a nice service comment") // add a comment to the service - * ->addToServicegroup("alwaysdown"); // add svc3 to servicegroup - * - * // Create the datasource from this fixture, here form MySQL - * $ds = new DataSourceTestSetup("mysql"); - * $ds->setup(); - * // insert fixture - * $ds->insert($fixture); - * - * - */ -class TestFixture -{ - /** - * Internal dataholder for all defined hosts - * @var array - */ - private $hosts = array(); - - /** - * Internal holder for all defined services - * @var array - */ - private $services = array(); - - /** - * Internal holder for all defined contacts - * @var array - */ - private $contacts = array(); - - /** - * Internal holder for all defined comments - * @var array - */ - private $comments = array(); - - /** - * Internal holder for all defined servicegroups - * @var array - */ - private $servicegroups = array(); - - /** - * Internal holder for all defined hostgroups - * @var array - */ - private $hostgroups = array(); - - /** - * Return array with all defined hostobjects - * - * @return array Returns an array of host-arrays, which have the following fields - * - 'name' : The name of the host - * - 'state' : The state of the host (0,1,2) - * - 'address' : The string representation of the address (127.0.0.1 as default) - * - 'flags' : An ObjectFlags object containing additional state information - * - 'icon_image' : The icon image of this host (default: 'icon.png') - * - 'notes_url' : The notes url of this host (default empty string) - * - 'action_url' : The action url of this host (default empty string) - * - 'contacts' : An array of contact objects (having 'name' as the most important field) - * - 'customvariables' : An associative "cv_name"=>"cv_value" array containing the customvariables - */ - public function getHosts() - { - return $this->hosts; - } - - /** - * Return array with all defined service objects - * - * @return array Returns an array of service-arrays, which have the following fields - * - 'name' : The name of the service - * - 'host' : A reference to the hostobject - * - 'state' : The state of the service (0,1,2,3) - * - 'flags' : An ObjectFlags object containing additional state information - * - 'icon_image' : The icon image of this service (default: 'icon.png') - * - 'notes_url' : The notes url of this service (default empty string) - * - 'action_url' : The action url of this service (default empty string) - * - 'contacts' : An array of contact objects (having 'name' as the most important field) - * - 'customvariables' : An associative "cv_name"=>"cv_value" array containing the customvariables - */ - public function getServices() - { - return $this->services; - } - - /** - * Return array with all defined contacts - * - * @return array Returns an array of contact-arrays, which have the following fields - * - 'alias' : The name of the contact - */ - public function getContacts() - { - return $this->contacts; - } - - /** - * Return array with all defined servicegroups - * - * @return array Returns an array of group-arrays in the following format: - * - 'name' : The name of the group - * - 'members' : An array of service objects that belong to this group - */ - public function getServicegroups() - { - return $this->servicegroups; - } - - /** - * Return an array with all defined hostgroups - * - * @return array Returns an array of group-arrays in the following format: - * - 'name' : The name of the group - * - 'members' : An array of host objects that belong to this group - */ - public function getHostgroups() - { - return $this->hostgroups; - } - - /** - * Return an array of service and hostcomments - * - * @return array Returns an array of comment arrays in the following format: - * - 'service' (if servicecomment) : A reference to the service object this comment belongs to - * - 'host' (if hostcomment) : A reference to the host object this comment belongs to - * - 'author' : The author of this comment - * - 'text' : The comment text - */ - public function getComments() - { - return $this->comments; - } - - /** - * Add a new host to this TestFixture - * - * @param string $name The name of the host to add - * @param int $state The state of the host to add (0,1,2) - * @param ObjectFlags $flags (optional) An @see ObjectFlags object defining additional state inforamtion - * @param array $additional (optional) An array with additional object fields - * - * @return TestFixtureObjectClosure The TestFixture with the newly added host as the scope - */ - public function addHost($name, $state, ObjectFlags $flags = null, array $additional = array()) { - if ($flags === null) { - $flags = new ObjectFlags(); - } - if (isset($this->hosts[$name])) { - throw new Exception('Tried to create hosts twice'); - } - $this->hosts[$name] = array( - 'name' => $name, - 'state' => $state, - 'address' => '127.0.0.1', - 'flags' => $flags, - 'icon_image' => 'icon.png', - 'notes_url' => '', - 'action_url' => '', - 'contacts' => array(), - 'customvariables' => array() - - ); - $this->hosts[$name] = array_merge($this->hosts[$name], $additional); - return new TestFixtureObjectClosure($this, $name); - } - - /** - * Add a new service to this TestFixture - * - * @param string $host The name of the host this service belongs to (must exist prior to service creation) - * @param string $name The name of the service to add - * @param int $state The state of the service to add (0,1,2,3) - * @param ObjectFlags $flags (optional) An @see ObjectFlags object defining additional state information - * @param array $additional (optional) An array with additional object fields - * - * @return TestFixtureObjectClosure The TestFixture with the newly added service as the scope - */ - public function addService($host, $name, $state, ObjectFlags $flags = null, array $additional = array()) { - // when called in service scope only use the host - if (is_array($host)) { - $host = $host[0]; - } - if ($flags === null) { - $flags = new ObjectFlags(); - } - if (!isset($this->hosts[$host])) { - throw new Exception('Tried to create service for non existing host '.$host); - } - if (isset($this->services[$name])) { - throw new Exception('Tried to create service twice '.$name); - } - $this->services[$host.';'.$name] = array( - 'host' => &$this->hosts[$host], - 'name' => $name, - 'state' => $state, - 'contacts' => array(), - 'icon_image' => 'icon.png', - 'notes_url' => '', - 'action_url' => '', - 'customvariables' => array(), - 'flags' => $flags - ); - $this->services[$host.';'.$name] = array_merge($this->services[$host.';'.$name], $additional); - - return new TestFixtureObjectClosure($this, array($host, $name)); - } - - /** - * Add a new comment to the host or service provided in $hostOrServiceHostPair - * - * @param string|array $hostOrServiceHostPair Either a string with the hostname or an array with the hostname - * as the first and the servicename as the second element - * @param $author The author for the coment - * @param $text The content of the comment - * @return TestFixtureObjectClosure The TestFixture with the comment owner as the scope - */ - public function addComment($hostOrServiceHostPair, $author, $text) { - if (is_array($hostOrServiceHostPair)) { - if (!isset($this->services[$hostOrServiceHostPair[0].';'.$hostOrServiceHostPair[1]])) { - throw new Exception('Tried to add a comment for a nonexisting service '.$hostOrServiceHostPair[1]); - } - $this->comments[] = array( - 'service' => &$this->services[$hostOrServiceHostPair[0].';'.$hostOrServiceHostPair[1]], - 'author' => $author, - 'text' => $text - ); - } else { - if (!isset($this->hosts[$hostOrServiceHostPair])) { - throw new Exception('Tried to add a comment for a nonexisting host '.$hostOrServiceHostPair); - } - $this->comments[] = array( - 'host' => &$this->hosts[$hostOrServiceHostPair], - 'author' => $author, - 'text' => $text - ); - } - return new TestFixtureObjectClosure($this, $hostOrServiceHostPair); - } - - /** - * Assign a new contact to a host or service - * - * @param $hostOrServiceHostPair Either a string with the hostname or an array with the hostname - * as the first and the servicename as the second element - * @param $contactname The contactname to assign (will be created) - * @return TestFixtureObjectClosure The TestFixture with the host or service as the scope - */ - public function assignContact($hostOrServiceHostPair, $contactname) { - $this->contacts[$contactname] = array('alias' => $contactname); - if (is_array($hostOrServiceHostPair)) { - if (!isset($this->services[$hostOrServiceHostPair[0].';'.$hostOrServiceHostPair[1]])) { - throw new Exception('Tried to add a comment for a nonexisting service '.$hostOrServiceHostPair[1]); - } - $service = $this->services[$hostOrServiceHostPair[0].';'.$hostOrServiceHostPair[1]]; - $service['contacts'][] = &$this->contacts[$contactname]; - } else { - if (!isset($this->hosts[$hostOrServiceHostPair])) { - throw new Exception('Tried to add a comment for a nonexisting host '.$hostOrServiceHostPair); - } - $host = $this->hosts[$hostOrServiceHostPair]; - $host['contacts'][] = &$this->contacts[$contactname]; - } - return new TestFixtureObjectClosure($this, $hostOrServiceHostPair); - } - - /** - * Add a host to a hostgroup - * - * Create the new hostgroup if it not exists yet, otherwise just add the - * host to it - * - * @param string $host The name of the host to add to the hostgroup - * @param string $groupname The name of the hostgroup - * @return TestFixtureObjectClosure The TestFixture with the host as the scope - */ - public function addToHostgroup($host, $groupname) { - // check if in service scope - if (is_array($host)) { - $host = $host[0]; - } - if (!isset($this->hosts[$host])) { - throw new Exception('Tried to add non-existing host '.$host.' to hostgroup '); - } - if (!isset($this->hostgroups[$groupname])) { - $this->hostgroups[$groupname] = array("name" => $groupname, "members" => array()); - } - $this->hostgroups[$groupname]["members"][] = &$this->hosts[$host]; - return new TestFixtureObjectClosure($this, $host); - } - - /** - * Add service to a servicegroup - * - * Create the new service if it not exists yet, otherwise just add the service - * - * @param array $serviceHostPair An array containing the hostname as the first and the - * servicename as the second element - * @param string $groupname The name of the servicegroup - * @return TestFixtureObjectClosure The TestFixture with the service as the scope - */ - public function addToServicegroup(array $serviceHostPair, $groupname) { - if (!isset($this->services[$serviceHostPair[0].";".$serviceHostPair[1]])) { - throw new Exception('Tried to add non-existing service '.$serviceHostPair[1].' to servicegroup '); - } - $service = &$this->services[$serviceHostPair[0].";".$serviceHostPair[1]]; - if (!isset($this->servicegroups[$groupname])) { - $this->servicegroups[$groupname] = array("name" => $groupname, "members" => array()); - } - $this->servicegroups[$groupname]["members"][] = &$service; - return new TestFixtureObjectClosure($this, $serviceHostPair); - } -} diff --git a/modules/monitoring/test/php/testlib/datasource/schemes/ObjectsCacheTemplates.php b/modules/monitoring/test/php/testlib/datasource/schemes/ObjectsCacheTemplates.php deleted file mode 100644 index b7e80114c..000000000 --- a/modules/monitoring/test/php/testlib/datasource/schemes/ObjectsCacheTemplates.php +++ /dev/null @@ -1,99 +0,0 @@ - scheduled_time --- SYSTEMCOMMANDS, SERVICECHECKS, HOSTCHECKS, EVENTHANDLERS => start_time --- EXTERNALCOMMANDS => entry_time - --- instance_id -CREATE INDEX timedevents_i_id_idx on icinga_timedevents(instance_id); -CREATE INDEX timedeventq_i_id_idx on icinga_timedeventqueue(instance_id); -CREATE INDEX systemcommands_i_id_idx on icinga_systemcommands(instance_id); -CREATE INDEX servicechecks_i_id_idx on icinga_servicechecks(instance_id); -CREATE INDEX hostchecks_i_id_idx on icinga_hostchecks(instance_id); -CREATE INDEX eventhandlers_i_id_idx on icinga_eventhandlers(instance_id); -CREATE INDEX externalcommands_i_id_idx on icinga_externalcommands(instance_id); - --- time -CREATE INDEX timedevents_time_id_idx on icinga_timedevents(scheduled_time); -CREATE INDEX timedeventq_time_id_idx on icinga_timedeventqueue(scheduled_time); -CREATE INDEX systemcommands_time_id_idx on icinga_systemcommands(start_time); -CREATE INDEX servicechecks_time_id_idx on icinga_servicechecks(start_time); -CREATE INDEX hostchecks_time_id_idx on icinga_hostchecks(start_time); -CREATE INDEX eventhandlers_time_id_idx on icinga_eventhandlers(start_time); -CREATE INDEX externalcommands_time_id_idx on icinga_externalcommands(entry_time); - - --- for starting cleanup - referenced in dbhandler.c:882 --- instance_id only - --- realtime data -CREATE INDEX programstatus_i_id_idx on icinga_programstatus(instance_id); -CREATE INDEX hoststatus_i_id_idx on icinga_hoststatus(instance_id); -CREATE INDEX servicestatus_i_id_idx on icinga_servicestatus(instance_id); -CREATE INDEX contactstatus_i_id_idx on icinga_contactstatus(instance_id); -CREATE INDEX timedeventqueue_i_id_idx on icinga_timedeventqueue(instance_id); -CREATE INDEX comments_i_id_idx on icinga_comments(instance_id); -CREATE INDEX scheduleddowntime_i_id_idx on icinga_scheduleddowntime(instance_id); -CREATE INDEX runtimevariables_i_id_idx on icinga_runtimevariables(instance_id); -CREATE INDEX customvariablestatus_i_id_idx on icinga_customvariablestatus(instance_id); - --- config data -CREATE INDEX configfiles_i_id_idx on icinga_configfiles(instance_id); -CREATE INDEX configfilevariables_i_id_idx on icinga_configfilevariables(instance_id); -CREATE INDEX customvariables_i_id_idx on icinga_customvariables(instance_id); -CREATE INDEX commands_i_id_idx on icinga_commands(instance_id); -CREATE INDEX timeperiods_i_id_idx on icinga_timeperiods(instance_id); -CREATE INDEX timeperiod_timeranges_i_id_idx on icinga_timeperiod_timeranges(instance_id); -CREATE INDEX contactgroups_i_id_idx on icinga_contactgroups(instance_id); -CREATE INDEX contactgroup_members_i_id_idx on icinga_contactgroup_members(instance_id); -CREATE INDEX hostgroups_i_id_idx on icinga_hostgroups(instance_id); -CREATE INDEX hostgroup_members_i_id_idx on icinga_hostgroup_members(instance_id); -CREATE INDEX servicegroups_i_id_idx on icinga_servicegroups(instance_id); -CREATE INDEX servicegroup_members_i_id_idx on icinga_servicegroup_members(instance_id); -CREATE INDEX hostesc_i_id_idx on icinga_hostescalations(instance_id); -CREATE INDEX hostesc_contacts_i_id_idx on icinga_hostescalation_contacts(instance_id); -CREATE INDEX serviceesc_i_id_idx on icinga_serviceescalations(instance_id); -CREATE INDEX serviceesc_contacts_i_id_idx on icinga_serviceescalation_contacts(instance_id); -CREATE INDEX hostdependencies_i_id_idx on icinga_hostdependencies(instance_id); -CREATE INDEX contacts_i_id_idx on icinga_contacts(instance_id); -CREATE INDEX contact_addresses_i_id_idx on icinga_contact_addresses(instance_id); -CREATE INDEX contact_notifcommands_i_id_idx on icinga_contact_notificationcommands(instance_id); -CREATE INDEX hosts_i_id_idx on icinga_hosts(instance_id); -CREATE INDEX host_parenthosts_i_id_idx on icinga_host_parenthosts(instance_id); -CREATE INDEX host_contacts_i_id_idx on icinga_host_contacts(instance_id); -CREATE INDEX services_i_id_idx on icinga_services(instance_id); -CREATE INDEX service_contacts_i_id_idx on icinga_service_contacts(instance_id); -CREATE INDEX service_contactgroups_i_id_idx on icinga_service_contactgroups(instance_id); -CREATE INDEX host_contactgroups_i_id_idx on icinga_host_contactgroups(instance_id); -CREATE INDEX hostesc_cgroups_i_id_idx on icinga_hostescalation_contactgroups(instance_id); -CREATE INDEX serviceesc_cgroups_i_id_idx on icinga_serviceescalation_contactgroups(instance_id); - --- ----------------------------------------- --- more index stuff (WHERE clauses) --- ----------------------------------------- - --- hosts -CREATE INDEX hosts_host_object_id_idx on icinga_hosts(host_object_id); - --- hoststatus -CREATE INDEX hoststatus_stat_upd_time_idx on icinga_hoststatus(status_update_time); -CREATE INDEX hoststatus_current_state_idx on icinga_hoststatus(current_state); -CREATE INDEX hoststatus_check_type_idx on icinga_hoststatus(check_type); -CREATE INDEX hoststatus_state_type_idx on icinga_hoststatus(state_type); -CREATE INDEX hoststatus_last_state_chg_idx on icinga_hoststatus(last_state_change); -CREATE INDEX hoststatus_notif_enabled_idx on icinga_hoststatus(notifications_enabled); -CREATE INDEX hoststatus_problem_ack_idx on icinga_hoststatus(problem_has_been_acknowledged); -CREATE INDEX hoststatus_act_chks_en_idx on icinga_hoststatus(active_checks_enabled); -CREATE INDEX hoststatus_pas_chks_en_idx on icinga_hoststatus(passive_checks_enabled); -CREATE INDEX hoststatus_event_hdl_en_idx on icinga_hoststatus(event_handler_enabled); -CREATE INDEX hoststatus_flap_det_en_idx on icinga_hoststatus(flap_detection_enabled); -CREATE INDEX hoststatus_is_flapping_idx on icinga_hoststatus(is_flapping); -CREATE INDEX hoststatus_p_state_chg_idx on icinga_hoststatus(percent_state_change); -CREATE INDEX hoststatus_latency_idx on icinga_hoststatus(latency); -CREATE INDEX hoststatus_ex_time_idx on icinga_hoststatus(execution_time); -CREATE INDEX hoststatus_sch_downt_d_idx on icinga_hoststatus(scheduled_downtime_depth); - --- services -CREATE INDEX services_host_object_id_idx on icinga_services(host_object_id); - --- servicestatus -CREATE INDEX srvcstatus_stat_upd_time_idx on icinga_servicestatus(status_update_time); -CREATE INDEX srvcstatus_current_state_idx on icinga_servicestatus(current_state); -CREATE INDEX srvcstatus_check_type_idx on icinga_servicestatus(check_type); -CREATE INDEX srvcstatus_state_type_idx on icinga_servicestatus(state_type); -CREATE INDEX srvcstatus_last_state_chg_idx on icinga_servicestatus(last_state_change); -CREATE INDEX srvcstatus_notif_enabled_idx on icinga_servicestatus(notifications_enabled); -CREATE INDEX srvcstatus_problem_ack_idx on icinga_servicestatus(problem_has_been_acknowledged); -CREATE INDEX srvcstatus_act_chks_en_idx on icinga_servicestatus(active_checks_enabled); -CREATE INDEX srvcstatus_pas_chks_en_idx on icinga_servicestatus(passive_checks_enabled); -CREATE INDEX srvcstatus_event_hdl_en_idx on icinga_servicestatus(event_handler_enabled); -CREATE INDEX srvcstatus_flap_det_en_idx on icinga_servicestatus(flap_detection_enabled); -CREATE INDEX srvcstatus_is_flapping_idx on icinga_servicestatus(is_flapping); -CREATE INDEX srvcstatus_p_state_chg_idx on icinga_servicestatus(percent_state_change); -CREATE INDEX srvcstatus_latency_idx on icinga_servicestatus(latency); -CREATE INDEX srvcstatus_ex_time_idx on icinga_servicestatus(execution_time); -CREATE INDEX srvcstatus_sch_downt_d_idx on icinga_servicestatus(scheduled_downtime_depth); - --- timedeventqueue -CREATE INDEX timed_e_q_event_type_idx on icinga_timedeventqueue(event_type); -CREATE INDEX timed_e_q_sched_time_idx on icinga_timedeventqueue(scheduled_time); -CREATE INDEX timed_e_q_object_id_idx on icinga_timedeventqueue(object_id); -CREATE INDEX timed_e_q_rec_ev_id_idx on icinga_timedeventqueue(recurring_event); - --- timedevents -CREATE INDEX timed_e_event_type_idx on icinga_timedevents(event_type); --- CREATE INDEX timed_e_sched_time_idx on icinga_timedevents(scheduled_time); --already set for delete -CREATE INDEX timed_e_object_id_idx on icinga_timedevents(object_id); -CREATE INDEX timed_e_rec_ev_idx on icinga_timedevents(recurring_event); - --- hostchecks -CREATE INDEX hostchks_h_obj_id_idx on icinga_hostchecks(host_object_id); - --- servicechecks -CREATE INDEX servicechks_s_obj_id_idx on icinga_servicechecks(service_object_id); - --- objects -CREATE INDEX objects_objtype_id_idx ON icinga_objects(objecttype_id); -CREATE INDEX objects_name1_idx ON icinga_objects(name1); -CREATE INDEX objects_name2_idx ON icinga_objects(name2); -CREATE INDEX objects_inst_id_idx ON icinga_objects(instance_id); - --- instances --- CREATE INDEX instances_name_idx on icinga_instances(instance_name); - --- logentries --- CREATE INDEX loge_instance_id_idx on icinga_logentries(instance_id); --- #236 -CREATE INDEX loge_time_idx on icinga_logentries(logentry_time); --- CREATE INDEX loge_data_idx on icinga_logentries(logentry_data); -CREATE INDEX loge_inst_id_time_idx on icinga_logentries (instance_id ASC, logentry_time DESC); - --- commenthistory --- CREATE INDEX c_hist_instance_id_idx on icinga_logentries(instance_id); --- CREATE INDEX c_hist_c_time_idx on icinga_logentries(comment_time); --- CREATE INDEX c_hist_i_c_id_idx on icinga_logentries(internal_comment_id); - --- downtimehistory --- CREATE INDEX d_t_hist_nstance_id_idx on icinga_downtimehistory(instance_id); --- CREATE INDEX d_t_hist_type_idx on icinga_downtimehistory(downtime_type); --- CREATE INDEX d_t_hist_object_id_idx on icinga_downtimehistory(object_id); --- CREATE INDEX d_t_hist_entry_time_idx on icinga_downtimehistory(entry_time); --- CREATE INDEX d_t_hist_sched_start_idx on icinga_downtimehistory(scheduled_start_time); --- CREATE INDEX d_t_hist_sched_end_idx on icinga_downtimehistory(scheduled_end_time); - --- scheduleddowntime --- CREATE INDEX sched_d_t_downtime_type_idx on icinga_scheduleddowntime(downtime_type); --- CREATE INDEX sched_d_t_object_id_idx on icinga_scheduleddowntime(object_id); --- CREATE INDEX sched_d_t_entry_time_idx on icinga_scheduleddowntime(entry_time); --- CREATE INDEX sched_d_t_start_time_idx on icinga_scheduleddowntime(scheduled_start_time); --- CREATE INDEX sched_d_t_end_time_idx on icinga_scheduleddowntime(scheduled_end_time); - --- statehistory -CREATE INDEX statehist_i_id_o_id_s_ty_s_ti on icinga_statehistory(instance_id, object_id, state_type, state_time); ---#2274 -create index statehist_state_idx on icinga_statehistory(object_id,state); - - --- SLA statehistory -CREATE INDEX slahist_i_id_o_id_s_ti_s_s_ti_e on icinga_slahistory(instance_id,object_id,start_time,end_time); - --- Icinga Web Notifications -CREATE INDEX notification_idx ON icinga_notifications(notification_type, object_id, start_time); -CREATE INDEX notification_object_id_idx ON icinga_notifications(object_id); -CREATE INDEX contact_notification_idx ON icinga_contactnotifications(notification_id, contact_object_id); -CREATE INDEX contacts_object_id_idx ON icinga_contacts(contact_object_id); -CREATE INDEX contact_notif_meth_notif_idx ON icinga_contactnotificationmethods(contactnotification_id, command_object_id); -CREATE INDEX command_object_idx ON icinga_commands(object_id); -CREATE INDEX services_combined_object_idx ON icinga_services(service_object_id, host_object_id); - - --- #2618 -CREATE INDEX cntgrpmbrs_cgid_coid ON icinga_contactgroup_members (contactgroup_id,contact_object_id); -CREATE INDEX hstgrpmbrs_hgid_hoid ON icinga_hostgroup_members (hostgroup_id,host_object_id); -CREATE INDEX hstcntgrps_hid_cgoid ON icinga_host_contactgroups (host_id,contactgroup_object_id); -CREATE INDEX hstprnthsts_hid_phoid ON icinga_host_parenthosts (host_id,parent_host_object_id); -CREATE INDEX runtimevars_iid_varn ON icinga_runtimevariables (instance_id,varname); -CREATE INDEX sgmbrs_sgid_soid ON icinga_servicegroup_members (servicegroup_id,service_object_id); -CREATE INDEX scgrps_sid_cgoid ON icinga_service_contactgroups (service_id,contactgroup_object_id); -CREATE INDEX tperiod_tid_d_ss_es ON icinga_timeperiod_timeranges (timeperiod_id,day,start_sec,end_sec); - --- #3649 -CREATE INDEX sla_idx_sthist ON icinga_statehistory (object_id, state_time DESC); -CREATE INDEX sla_idx_dohist ON icinga_downtimehistory (object_id, actual_start_time, actual_end_time); -CREATE INDEX sla_idx_obj ON icinga_objects (objecttype_id, is_active, name1); - --- ----------------------------------------- --- set dbversion --- ----------------------------------------- -INSERT INTO icinga_dbversion (name, version, create_time, modify_time) VALUES ('idoutils', '1.9.0', NOW(), NOW()) ON DUPLICATE KEY UPDATE version='1.9.0', modify_time=NOW(); - diff --git a/modules/monitoring/test/php/testlib/datasource/schemes/idoPgSQL.sql b/modules/monitoring/test/php/testlib/datasource/schemes/idoPgSQL.sql deleted file mode 100644 index 9cea9665b..000000000 --- a/modules/monitoring/test/php/testlib/datasource/schemes/idoPgSQL.sql +++ /dev/null @@ -1,1638 +0,0 @@ --- -------------------------------------------------------- --- pgsql.sql --- DB definition for Postgresql --- --- Copyright (c) 2009-2013 Icinga Development Team (http://www.icinga.org) --- --- initial version: 2009-05-13 Markus Manzke --- current version: 2012-04-19 Michael Friedrich --- --- -------------------------------------------------------- - --- --- Functions --- - -CREATE OR REPLACE FUNCTION from_unixtime(integer) RETURNS timestamp with time zone AS ' - SELECT to_timestamp($1) AS result -' LANGUAGE sql; - -CREATE OR REPLACE FUNCTION unix_timestamp(timestamp with time zone) RETURNS bigint AS ' - SELECT EXTRACT(EPOCH FROM $1)::bigint AS result; -' LANGUAGE sql; - - --- ----------------------------------------- --- set dbversion --- ----------------------------------------- - -CREATE OR REPLACE FUNCTION updatedbversion(version_i TEXT) RETURNS void AS $$ -BEGIN - IF EXISTS( SELECT * FROM icinga_dbversion WHERE name='idoutils') - THEN - UPDATE icinga_dbversion - SET version=version_i, modify_time=NOW() - WHERE name='idoutils'; - ELSE - INSERT INTO icinga_dbversion (dbversion_id, name, version, create_time, modify_time) VALUES ('1', 'idoutils', version_i, NOW(), NOW()); - END IF; - - RETURN; -END; -$$ LANGUAGE plpgsql; --- HINT: su - postgres; createlang plpgsql icinga; - - - --- --- Database: icinga --- - --- -------------------------------------------------------- - --- --- Table structure for table icinga_acknowledgements --- - -CREATE TABLE icinga_acknowledgements ( - acknowledgement_id bigserial, - instance_id bigint default 0, - entry_time timestamp with time zone default '1970-01-01 00:00:00', - entry_time_usec INTEGER default 0, - acknowledgement_type INTEGER default 0, - object_id bigint default 0, - state INTEGER default 0, - author_name TEXT default '', - comment_data TEXT default '', - is_sticky INTEGER default 0, - persistent_comment INTEGER default 0, - notify_contacts INTEGER default 0, - end_time timestamp with time zone default '1970-01-01 00:00:00', - CONSTRAINT PK_acknowledgement_id PRIMARY KEY (acknowledgement_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_commands --- - -CREATE TABLE icinga_commands ( - command_id bigserial, - instance_id bigint default 0, - config_type INTEGER default 0, - object_id bigint default 0, - command_line TEXT default '', - CONSTRAINT PK_command_id PRIMARY KEY (command_id) , - CONSTRAINT UQ_commands UNIQUE (instance_id,object_id,config_type) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_commenthistory --- - -CREATE TABLE icinga_commenthistory ( - commenthistory_id bigserial, - instance_id bigint default 0, - entry_time timestamp with time zone default '1970-01-01 00:00:00', - entry_time_usec INTEGER default 0, - comment_type INTEGER default 0, - entry_type INTEGER default 0, - object_id bigint default 0, - comment_time timestamp with time zone default '1970-01-01 00:00:00', - internal_comment_id bigint default 0, - author_name TEXT default '', - comment_data TEXT default '', - is_persistent INTEGER default 0, - comment_source INTEGER default 0, - expires INTEGER default 0, - expiration_time timestamp with time zone default '1970-01-01 00:00:00', - deletion_time timestamp with time zone default '1970-01-01 00:00:00', - deletion_time_usec INTEGER default 0, - CONSTRAINT PK_commenthistory_id PRIMARY KEY (commenthistory_id) , - CONSTRAINT UQ_commenthistory UNIQUE (instance_id,comment_time,internal_comment_id) -); - --- -------------------------------------------------------- - --- --- Table structure for table icinga_comments --- - -CREATE TABLE icinga_comments ( - comment_id bigserial, - instance_id bigint default 0, - entry_time timestamp with time zone default '1970-01-01 00:00:00', - entry_time_usec INTEGER default 0, - comment_type INTEGER default 0, - entry_type INTEGER default 0, - object_id bigint default 0, - comment_time timestamp with time zone default '1970-01-01 00:00:00', - internal_comment_id bigint default 0, - author_name TEXT default '', - comment_data TEXT default '', - is_persistent INTEGER default 0, - comment_source INTEGER default 0, - expires INTEGER default 0, - expiration_time timestamp with time zone default '1970-01-01 00:00:00', - CONSTRAINT PK_comment_id PRIMARY KEY (comment_id) , - CONSTRAINT UQ_comments UNIQUE (instance_id,comment_time,internal_comment_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_configfiles --- - -CREATE TABLE icinga_configfiles ( - configfile_id bigserial, - instance_id bigint default 0, - configfile_type INTEGER default 0, - configfile_path TEXT default '', - CONSTRAINT PK_configfile_id PRIMARY KEY (configfile_id) , - CONSTRAINT UQ_configfiles UNIQUE (instance_id,configfile_type,configfile_path) -); - --- -------------------------------------------------------- - --- --- Table structure for table icinga_configfilevariables --- - -CREATE TABLE icinga_configfilevariables ( - configfilevariable_id bigserial, - instance_id bigint default 0, - configfile_id bigint default 0, - varname TEXT default '', - varvalue TEXT default '', - CONSTRAINT PK_configfilevariable_id PRIMARY KEY (configfilevariable_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_conninfo --- - -CREATE TABLE icinga_conninfo ( - conninfo_id bigserial, - instance_id bigint default 0, - agent_name TEXT default '', - agent_version TEXT default '', - disposition TEXT default '', - connect_source TEXT default '', - connect_type TEXT default '', - connect_time timestamp with time zone default '1970-01-01 00:00:00', - disconnect_time timestamp with time zone default '1970-01-01 00:00:00', - last_checkin_time timestamp with time zone default '1970-01-01 00:00:00', - data_start_time timestamp with time zone default '1970-01-01 00:00:00', - data_end_time timestamp with time zone default '1970-01-01 00:00:00', - bytes_processed bigint default 0, - lines_processed bigint default 0, - entries_processed bigint default 0, - CONSTRAINT PK_conninfo_id PRIMARY KEY (conninfo_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_contactgroups --- - -CREATE TABLE icinga_contactgroups ( - contactgroup_id bigserial, - instance_id bigint default 0, - config_type INTEGER default 0, - contactgroup_object_id bigint default 0, - alias TEXT default '', - CONSTRAINT PK_contactgroup_id PRIMARY KEY (contactgroup_id) , - CONSTRAINT UQ_contactgroups UNIQUE (instance_id,config_type,contactgroup_object_id) -); - --- -------------------------------------------------------- - --- --- Table structure for table icinga_contactgroup_members --- - -CREATE TABLE icinga_contactgroup_members ( - contactgroup_member_id bigserial, - instance_id bigint default 0, - contactgroup_id bigint default 0, - contact_object_id bigint default 0, - CONSTRAINT PK_contactgroup_member_id PRIMARY KEY (contactgroup_member_id) -); - --- -------------------------------------------------------- - --- --- Table structure for table icinga_contactnotificationmethods --- - -CREATE TABLE icinga_contactnotificationmethods ( - contactnotificationmethod_id bigserial, - instance_id bigint default 0, - contactnotification_id bigint default 0, - start_time timestamp with time zone default '1970-01-01 00:00:00', - start_time_usec INTEGER default 0, - end_time timestamp with time zone default '1970-01-01 00:00:00', - end_time_usec INTEGER default 0, - command_object_id bigint default 0, - command_args TEXT default '', - CONSTRAINT PK_contactnotificationmethod_id PRIMARY KEY (contactnotificationmethod_id) , - CONSTRAINT UQ_contactnotificationmethods UNIQUE (instance_id,contactnotification_id,start_time,start_time_usec) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_contactnotifications --- - -CREATE TABLE icinga_contactnotifications ( - contactnotification_id bigserial, - instance_id bigint default 0, - notification_id bigint default 0, - contact_object_id bigint default 0, - start_time timestamp with time zone default '1970-01-01 00:00:00', - start_time_usec INTEGER default 0, - end_time timestamp with time zone default '1970-01-01 00:00:00', - end_time_usec INTEGER default 0, - CONSTRAINT PK_contactnotification_id PRIMARY KEY (contactnotification_id) , - CONSTRAINT UQ_contactnotifications UNIQUE (instance_id,contact_object_id,start_time,start_time_usec) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_contacts --- - -CREATE TABLE icinga_contacts ( - contact_id bigserial, - instance_id bigint default 0, - config_type INTEGER default 0, - contact_object_id bigint default 0, - alias TEXT default '', - email_address TEXT default '', - pager_address TEXT default '', - host_timeperiod_object_id bigint default 0, - service_timeperiod_object_id bigint default 0, - host_notifications_enabled INTEGER default 0, - service_notifications_enabled INTEGER default 0, - can_submit_commands INTEGER default 0, - notify_service_recovery INTEGER default 0, - notify_service_warning INTEGER default 0, - notify_service_unknown INTEGER default 0, - notify_service_critical INTEGER default 0, - notify_service_flapping INTEGER default 0, - notify_service_downtime INTEGER default 0, - notify_host_recovery INTEGER default 0, - notify_host_down INTEGER default 0, - notify_host_unreachable INTEGER default 0, - notify_host_flapping INTEGER default 0, - notify_host_downtime INTEGER default 0, - CONSTRAINT PK_contact_id PRIMARY KEY (contact_id) , - CONSTRAINT UQ_contacts UNIQUE (instance_id,config_type,contact_object_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_contactstatus --- - -CREATE TABLE icinga_contactstatus ( - contactstatus_id bigserial, - instance_id bigint default 0, - contact_object_id bigint default 0, - status_update_time timestamp with time zone default '1970-01-01 00:00:00', - host_notifications_enabled INTEGER default 0, - service_notifications_enabled INTEGER default 0, - last_host_notification timestamp with time zone default '1970-01-01 00:00:00', - last_service_notification timestamp with time zone default '1970-01-01 00:00:00', - modified_attributes INTEGER default 0, - modified_host_attributes INTEGER default 0, - modified_service_attributes INTEGER default 0, - CONSTRAINT PK_contactstatus_id PRIMARY KEY (contactstatus_id) , - CONSTRAINT UQ_contactstatus UNIQUE (contact_object_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_contact_addresses --- - -CREATE TABLE icinga_contact_addresses ( - contact_address_id bigserial, - instance_id bigint default 0, - contact_id bigint default 0, - address_number INTEGER default 0, - address TEXT default '', - CONSTRAINT PK_contact_address_id PRIMARY KEY (contact_address_id) , - CONSTRAINT UQ_contact_addresses UNIQUE (contact_id,address_number) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_contact_notificationcommands --- - -CREATE TABLE icinga_contact_notificationcommands ( - contact_notificationcommand_id bigserial, - instance_id bigint default 0, - contact_id bigint default 0, - notification_type INTEGER default 0, - command_object_id bigint default 0, - command_args TEXT default '', - CONSTRAINT PK_contact_notificationcommand_id PRIMARY KEY (contact_notificationcommand_id) , - CONSTRAINT UQ_contact_notificationcommands UNIQUE (contact_id,notification_type,command_object_id,command_args) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_customvariables --- - -CREATE TABLE icinga_customvariables ( - customvariable_id bigserial, - instance_id bigint default 0, - object_id bigint default 0, - config_type INTEGER default 0, - has_been_modified INTEGER default 0, - varname TEXT default '', - varvalue TEXT default '', - CONSTRAINT PK_customvariable_id PRIMARY KEY (customvariable_id) , - CONSTRAINT UQ_customvariables UNIQUE (object_id,config_type,varname) -) ; -CREATE INDEX icinga_customvariables_i ON icinga_customvariables(varname); - --- -------------------------------------------------------- - --- --- Table structure for table icinga_customvariablestatus --- - -CREATE TABLE icinga_customvariablestatus ( - customvariablestatus_id bigserial, - instance_id bigint default 0, - object_id bigint default 0, - status_update_time timestamp with time zone default '1970-01-01 00:00:00', - has_been_modified INTEGER default 0, - varname TEXT default '', - varvalue TEXT default '', - CONSTRAINT PK_customvariablestatus_id PRIMARY KEY (customvariablestatus_id) , - CONSTRAINT UQ_customvariablestatus UNIQUE (object_id,varname) -) ; -CREATE INDEX icinga_customvariablestatus_i ON icinga_customvariablestatus(varname); - - --- -------------------------------------------------------- - --- --- Table structure for table icinga_dbversion --- - -CREATE TABLE icinga_dbversion ( - dbversion_id bigserial, - name TEXT default '', - version TEXT default '', - create_time timestamp with time zone default '1970-01-01 00:00:00', - modify_time timestamp with time zone default '1970-01-01 00:00:00', - CONSTRAINT PK_dbversion_id PRIMARY KEY (dbversion_id) , - CONSTRAINT UQ_dbversion UNIQUE (name) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_downtimehistory --- - -CREATE TABLE icinga_downtimehistory ( - downtimehistory_id bigserial, - instance_id bigint default 0, - downtime_type INTEGER default 0, - object_id bigint default 0, - entry_time timestamp with time zone default '1970-01-01 00:00:00', - author_name TEXT default '', - comment_data TEXT default '', - internal_downtime_id bigint default 0, - triggered_by_id bigint default 0, - is_fixed INTEGER default 0, - duration INTEGER default 0, - scheduled_start_time timestamp with time zone default '1970-01-01 00:00:00', - scheduled_end_time timestamp with time zone default '1970-01-01 00:00:00', - was_started INTEGER default 0, - actual_start_time timestamp with time zone default '1970-01-01 00:00:00', - actual_start_time_usec INTEGER default 0, - actual_end_time timestamp with time zone default '1970-01-01 00:00:00', - actual_end_time_usec INTEGER default 0, - was_cancelled INTEGER default 0, - is_in_effect INTEGER default 0, - trigger_time timestamp with time zone default '1970-01-01 00:00:00', - CONSTRAINT PK_downtimehistory_id PRIMARY KEY (downtimehistory_id) , - CONSTRAINT UQ_downtimehistory UNIQUE (instance_id,object_id,entry_time,internal_downtime_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_eventhandlers --- - -CREATE TABLE icinga_eventhandlers ( - eventhandler_id bigserial, - instance_id bigint default 0, - eventhandler_type INTEGER default 0, - object_id bigint default 0, - state INTEGER default 0, - state_type INTEGER default 0, - start_time timestamp with time zone default '1970-01-01 00:00:00', - start_time_usec INTEGER default 0, - end_time timestamp with time zone default '1970-01-01 00:00:00', - end_time_usec INTEGER default 0, - command_object_id bigint default 0, - command_args TEXT default '', - command_line TEXT default '', - timeout INTEGER default 0, - early_timeout INTEGER default 0, - execution_time double precision default 0, - return_code INTEGER default 0, - output TEXT default '', - long_output TEXT default '', - CONSTRAINT PK_eventhandler_id PRIMARY KEY (eventhandler_id) , - CONSTRAINT UQ_eventhandlers UNIQUE (instance_id,object_id,start_time,start_time_usec) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_externalcommands --- - -CREATE TABLE icinga_externalcommands ( - externalcommand_id bigserial, - instance_id bigint default 0, - entry_time timestamp with time zone default '1970-01-01 00:00:00', - command_type INTEGER default 0, - command_name TEXT default '', - command_args TEXT default '', - CONSTRAINT PK_externalcommand_id PRIMARY KEY (externalcommand_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_flappinghistory --- - -CREATE TABLE icinga_flappinghistory ( - flappinghistory_id bigserial, - instance_id bigint default 0, - event_time timestamp with time zone default '1970-01-01 00:00:00', - event_time_usec INTEGER default 0, - event_type INTEGER default 0, - reason_type INTEGER default 0, - flapping_type INTEGER default 0, - object_id bigint default 0, - percent_state_change double precision default 0, - low_threshold double precision default 0, - high_threshold double precision default 0, - comment_time timestamp with time zone default '1970-01-01 00:00:00', - internal_comment_id bigint default 0, - CONSTRAINT PK_flappinghistory_id PRIMARY KEY (flappinghistory_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_hostchecks --- - -CREATE TABLE icinga_hostchecks ( - hostcheck_id bigserial, - instance_id bigint default 0, - host_object_id bigint default 0, - check_type INTEGER default 0, - is_raw_check INTEGER default 0, - current_check_attempt INTEGER default 0, - max_check_attempts INTEGER default 0, - state INTEGER default 0, - state_type INTEGER default 0, - start_time timestamp with time zone default '1970-01-01 00:00:00', - start_time_usec INTEGER default 0, - end_time timestamp with time zone default '1970-01-01 00:00:00', - end_time_usec INTEGER default 0, - command_object_id bigint default 0, - command_args TEXT default '', - command_line TEXT default '', - timeout INTEGER default 0, - early_timeout INTEGER default 0, - execution_time double precision default 0, - latency double precision default 0, - return_code INTEGER default 0, - output TEXT default '', - long_output TEXT default '', - perfdata TEXT default '', - CONSTRAINT PK_hostcheck_id PRIMARY KEY (hostcheck_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_hostdependencies --- - -CREATE TABLE icinga_hostdependencies ( - hostdependency_id bigserial, - instance_id bigint default 0, - config_type INTEGER default 0, - host_object_id bigint default 0, - dependent_host_object_id bigint default 0, - dependency_type INTEGER default 0, - inherits_parent INTEGER default 0, - timeperiod_object_id bigint default 0, - fail_on_up INTEGER default 0, - fail_on_down INTEGER default 0, - fail_on_unreachable INTEGER default 0, - CONSTRAINT PK_hostdependency_id PRIMARY KEY (hostdependency_id) , - CONSTRAINT UQ_hostdependencies UNIQUE (instance_id,config_type,host_object_id,dependent_host_object_id,dependency_type,inherits_parent,fail_on_up,fail_on_down,fail_on_unreachable) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_hostescalations --- - -CREATE TABLE icinga_hostescalations ( - hostescalation_id bigserial, - instance_id bigint default 0, - config_type INTEGER default 0, - host_object_id bigint default 0, - timeperiod_object_id bigint default 0, - first_notification INTEGER default 0, - last_notification INTEGER default 0, - notification_interval double precision default 0, - escalate_on_recovery INTEGER default 0, - escalate_on_down INTEGER default 0, - escalate_on_unreachable INTEGER default 0, - CONSTRAINT PK_hostescalation_id PRIMARY KEY (hostescalation_id) , - CONSTRAINT UQ_hostescalations UNIQUE (instance_id,config_type,host_object_id,timeperiod_object_id,first_notification,last_notification) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_hostescalation_contactgroups --- - -CREATE TABLE icinga_hostescalation_contactgroups ( - hostescalation_contactgroup_id bigserial, - instance_id bigint default 0, - hostescalation_id bigint default 0, - contactgroup_object_id bigint default 0, - CONSTRAINT PK_hostescalation_contactgroup_id PRIMARY KEY (hostescalation_contactgroup_id) , - CONSTRAINT UQ_hostescalation_contactgroups UNIQUE (hostescalation_id,contactgroup_object_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_hostescalation_contacts --- - -CREATE TABLE icinga_hostescalation_contacts ( - hostescalation_contact_id bigserial, - instance_id bigint default 0, - hostescalation_id bigint default 0, - contact_object_id bigint default 0, - CONSTRAINT PK_hostescalation_contact_id PRIMARY KEY (hostescalation_contact_id) , - CONSTRAINT UQ_hostescalation_contacts UNIQUE (instance_id,hostescalation_id,contact_object_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_hostgroups --- - -CREATE TABLE icinga_hostgroups ( - hostgroup_id bigserial, - instance_id bigint default 0, - config_type INTEGER default 0, - hostgroup_object_id bigint default 0, - alias TEXT default '', - CONSTRAINT PK_hostgroup_id PRIMARY KEY (hostgroup_id) , - CONSTRAINT UQ_hostgroups UNIQUE (instance_id,hostgroup_object_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_hostgroup_members --- - -CREATE TABLE icinga_hostgroup_members ( - hostgroup_member_id bigserial, - instance_id bigint default 0, - hostgroup_id bigint default 0, - host_object_id bigint default 0, - CONSTRAINT PK_hostgroup_member_id PRIMARY KEY (hostgroup_member_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_hosts --- - -CREATE TABLE icinga_hosts ( - host_id bigserial, - instance_id bigint default 0, - config_type INTEGER default 0, - host_object_id bigint default 0, - alias TEXT default '', - display_name TEXT default '', - address TEXT default '', - address6 TEXT default '', - check_command_object_id bigint default 0, - check_command_args TEXT default '', - eventhandler_command_object_id bigint default 0, - eventhandler_command_args TEXT default '', - notification_timeperiod_object_id bigint default 0, - check_timeperiod_object_id bigint default 0, - failure_prediction_options TEXT default '', - check_interval double precision default 0, - retry_interval double precision default 0, - max_check_attempts INTEGER default 0, - first_notification_delay double precision default 0, - notification_interval double precision default 0, - notify_on_down INTEGER default 0, - notify_on_unreachable INTEGER default 0, - notify_on_recovery INTEGER default 0, - notify_on_flapping INTEGER default 0, - notify_on_downtime INTEGER default 0, - stalk_on_up INTEGER default 0, - stalk_on_down INTEGER default 0, - stalk_on_unreachable INTEGER default 0, - flap_detection_enabled INTEGER default 0, - flap_detection_on_up INTEGER default 0, - flap_detection_on_down INTEGER default 0, - flap_detection_on_unreachable INTEGER default 0, - low_flap_threshold double precision default 0, - high_flap_threshold double precision default 0, - process_performance_data INTEGER default 0, - freshness_checks_enabled INTEGER default 0, - freshness_threshold INTEGER default 0, - passive_checks_enabled INTEGER default 0, - event_handler_enabled INTEGER default 0, - active_checks_enabled INTEGER default 0, - retain_status_information INTEGER default 0, - retain_nonstatus_information INTEGER default 0, - notifications_enabled INTEGER default 0, - obsess_over_host INTEGER default 0, - failure_prediction_enabled INTEGER default 0, - notes TEXT default '', - notes_url TEXT default '', - action_url TEXT default '', - icon_image TEXT default '', - icon_image_alt TEXT default '', - vrml_image TEXT default '', - statusmap_image TEXT default '', - have_2d_coords INTEGER default 0, - x_2d INTEGER default 0, - y_2d INTEGER default 0, - have_3d_coords INTEGER default 0, - x_3d double precision default 0, - y_3d double precision default 0, - z_3d double precision default 0, - CONSTRAINT PK_host_id PRIMARY KEY (host_id) , - CONSTRAINT UQ_hosts UNIQUE (instance_id,config_type,host_object_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_hoststatus --- - -CREATE TABLE icinga_hoststatus ( - hoststatus_id bigserial, - instance_id bigint default 0, - host_object_id bigint default 0, - status_update_time timestamp with time zone default '1970-01-01 00:00:00', - output TEXT default '', - long_output TEXT default '', - perfdata TEXT default '', - current_state INTEGER default 0, - has_been_checked INTEGER default 0, - should_be_scheduled INTEGER default 0, - current_check_attempt INTEGER default 0, - max_check_attempts INTEGER default 0, - last_check timestamp with time zone default '1970-01-01 00:00:00', - next_check timestamp with time zone default '1970-01-01 00:00:00', - check_type INTEGER default 0, - last_state_change timestamp with time zone default '1970-01-01 00:00:00', - last_hard_state_change timestamp with time zone default '1970-01-01 00:00:00', - last_hard_state INTEGER default 0, - last_time_up timestamp with time zone default '1970-01-01 00:00:00', - last_time_down timestamp with time zone default '1970-01-01 00:00:00', - last_time_unreachable timestamp with time zone default '1970-01-01 00:00:00', - state_type INTEGER default 0, - last_notification timestamp with time zone default '1970-01-01 00:00:00', - next_notification timestamp with time zone default '1970-01-01 00:00:00', - no_more_notifications INTEGER default 0, - notifications_enabled INTEGER default 0, - problem_has_been_acknowledged INTEGER default 0, - acknowledgement_type INTEGER default 0, - current_notification_number INTEGER default 0, - passive_checks_enabled INTEGER default 0, - active_checks_enabled INTEGER default 0, - event_handler_enabled INTEGER default 0, - flap_detection_enabled INTEGER default 0, - is_flapping INTEGER default 0, - percent_state_change double precision default 0, - latency double precision default 0, - execution_time double precision default 0, - scheduled_downtime_depth INTEGER default 0, - failure_prediction_enabled INTEGER default 0, - process_performance_data INTEGER default 0, - obsess_over_host INTEGER default 0, - modified_host_attributes INTEGER default 0, - event_handler TEXT default '', - check_command TEXT default '', - normal_check_interval double precision default 0, - retry_check_interval double precision default 0, - check_timeperiod_object_id bigint default 0, - CONSTRAINT PK_hoststatus_id PRIMARY KEY (hoststatus_id) , - CONSTRAINT UQ_hoststatus UNIQUE (host_object_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_host_contactgroups --- - -CREATE TABLE icinga_host_contactgroups ( - host_contactgroup_id bigserial, - instance_id bigint default 0, - host_id bigint default 0, - contactgroup_object_id bigint default 0, - CONSTRAINT PK_host_contactgroup_id PRIMARY KEY (host_contactgroup_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_host_contacts --- - -CREATE TABLE icinga_host_contacts ( - host_contact_id bigserial, - instance_id bigint default 0, - host_id bigint default 0, - contact_object_id bigint default 0, - CONSTRAINT PK_host_contact_id PRIMARY KEY (host_contact_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_host_parenthosts --- - -CREATE TABLE icinga_host_parenthosts ( - host_parenthost_id bigserial, - instance_id bigint default 0, - host_id bigint default 0, - parent_host_object_id bigint default 0, - CONSTRAINT PK_host_parenthost_id PRIMARY KEY (host_parenthost_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_instances --- - -CREATE TABLE icinga_instances ( - instance_id bigserial, - instance_name TEXT default '', - instance_description TEXT default '', - CONSTRAINT PK_instance_id PRIMARY KEY (instance_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_logentries --- - -CREATE TABLE icinga_logentries ( - logentry_id bigserial, - instance_id bigint default 0, - logentry_time timestamp with time zone default '1970-01-01 00:00:00', - entry_time timestamp with time zone default '1970-01-01 00:00:00', - entry_time_usec INTEGER default 0, - logentry_type INTEGER default 0, - logentry_data TEXT default '', - realtime_data INTEGER default 0, - inferred_data_extracted INTEGER default 0, - CONSTRAINT PK_logentry_id PRIMARY KEY (logentry_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_notifications --- - -CREATE TABLE icinga_notifications ( - notification_id bigserial, - instance_id bigint default 0, - notification_type INTEGER default 0, - notification_reason INTEGER default 0, - object_id bigint default 0, - start_time timestamp with time zone default '1970-01-01 00:00:00', - start_time_usec INTEGER default 0, - end_time timestamp with time zone default '1970-01-01 00:00:00', - end_time_usec INTEGER default 0, - state INTEGER default 0, - output TEXT default '', - long_output TEXT default '', - escalated INTEGER default 0, - contacts_notified INTEGER default 0, - CONSTRAINT PK_notification_id PRIMARY KEY (notification_id) , - CONSTRAINT UQ_notifications UNIQUE (instance_id,object_id,start_time,start_time_usec) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_objects --- - -CREATE TABLE icinga_objects ( - object_id bigserial, - instance_id bigint default 0, - objecttype_id bigint default 0, - name1 TEXT, - name2 TEXT, - is_active INTEGER default 0, - CONSTRAINT PK_object_id PRIMARY KEY (object_id) --- UNIQUE (objecttype_id,name1,name2) -) ; -CREATE INDEX icinga_objects_i ON icinga_objects(objecttype_id,name1,name2); - --- -------------------------------------------------------- - --- --- Table structure for table icinga_processevents --- - -CREATE TABLE icinga_processevents ( - processevent_id bigserial, - instance_id bigint default 0, - event_type INTEGER default 0, - event_time timestamp with time zone default '1970-01-01 00:00:00', - event_time_usec INTEGER default 0, - process_id bigint default 0, - program_name TEXT default '', - program_version TEXT default '', - program_date TEXT default '', - CONSTRAINT PK_processevent_id PRIMARY KEY (processevent_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_programstatus --- - -CREATE TABLE icinga_programstatus ( - programstatus_id bigserial, - instance_id bigint default 0, - status_update_time timestamp with time zone default '1970-01-01 00:00:00', - program_start_time timestamp with time zone default '1970-01-01 00:00:00', - program_end_time timestamp with time zone default '1970-01-01 00:00:00', - is_currently_running INTEGER default 0, - process_id bigint default 0, - daemon_mode INTEGER default 0, - last_command_check timestamp with time zone default '1970-01-01 00:00:00', - last_log_rotation timestamp with time zone default '1970-01-01 00:00:00', - notifications_enabled INTEGER default 0, - disable_notif_expire_time timestamp with time zone default '1970-01-01 00:00:00', - active_service_checks_enabled INTEGER default 0, - passive_service_checks_enabled INTEGER default 0, - active_host_checks_enabled INTEGER default 0, - passive_host_checks_enabled INTEGER default 0, - event_handlers_enabled INTEGER default 0, - flap_detection_enabled INTEGER default 0, - failure_prediction_enabled INTEGER default 0, - process_performance_data INTEGER default 0, - obsess_over_hosts INTEGER default 0, - obsess_over_services INTEGER default 0, - modified_host_attributes INTEGER default 0, - modified_service_attributes INTEGER default 0, - global_host_event_handler TEXT default '', - global_service_event_handler TEXT default '', - CONSTRAINT PK_programstatus_id PRIMARY KEY (programstatus_id) , - CONSTRAINT UQ_programstatus UNIQUE (instance_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_runtimevariables --- - -CREATE TABLE icinga_runtimevariables ( - runtimevariable_id bigserial, - instance_id bigint default 0, - varname TEXT default '', - varvalue TEXT default '', - CONSTRAINT PK_runtimevariable_id PRIMARY KEY (runtimevariable_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_scheduleddowntime --- - -CREATE TABLE icinga_scheduleddowntime ( - scheduleddowntime_id bigserial, - instance_id bigint default 0, - downtime_type INTEGER default 0, - object_id bigint default 0, - entry_time timestamp with time zone default '1970-01-01 00:00:00', - author_name TEXT default '', - comment_data TEXT default '', - internal_downtime_id bigint default 0, - triggered_by_id bigint default 0, - is_fixed INTEGER default 0, - duration INTEGER default 0, - scheduled_start_time timestamp with time zone default '1970-01-01 00:00:00', - scheduled_end_time timestamp with time zone default '1970-01-01 00:00:00', - was_started INTEGER default 0, - actual_start_time timestamp with time zone default '1970-01-01 00:00:00', - actual_start_time_usec INTEGER default 0, - is_in_effect INTEGER default 0, - trigger_time timestamp with time zone default '1970-01-01 00:00:00', - CONSTRAINT PK_scheduleddowntime_id PRIMARY KEY (scheduleddowntime_id) , - CONSTRAINT UQ_scheduleddowntime UNIQUE (instance_id,object_id,entry_time,internal_downtime_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_servicechecks --- - -CREATE TABLE icinga_servicechecks ( - servicecheck_id bigserial, - instance_id bigint default 0, - service_object_id bigint default 0, - check_type INTEGER default 0, - current_check_attempt INTEGER default 0, - max_check_attempts INTEGER default 0, - state INTEGER default 0, - state_type INTEGER default 0, - start_time timestamp with time zone default '1970-01-01 00:00:00', - start_time_usec INTEGER default 0, - end_time timestamp with time zone default '1970-01-01 00:00:00', - end_time_usec INTEGER default 0, - command_object_id bigint default 0, - command_args TEXT default '', - command_line TEXT default '', - timeout INTEGER default 0, - early_timeout INTEGER default 0, - execution_time double precision default 0, - latency double precision default 0, - return_code INTEGER default 0, - output TEXT default '', - long_output TEXT default '', - perfdata TEXT default '', - CONSTRAINT PK_servicecheck_id PRIMARY KEY (servicecheck_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_servicedependencies --- - -CREATE TABLE icinga_servicedependencies ( - servicedependency_id bigserial, - instance_id bigint default 0, - config_type INTEGER default 0, - service_object_id bigint default 0, - dependent_service_object_id bigint default 0, - dependency_type INTEGER default 0, - inherits_parent INTEGER default 0, - timeperiod_object_id bigint default 0, - fail_on_ok INTEGER default 0, - fail_on_warning INTEGER default 0, - fail_on_unknown INTEGER default 0, - fail_on_critical INTEGER default 0, - CONSTRAINT PK_servicedependency_id PRIMARY KEY (servicedependency_id) , - CONSTRAINT UQ_servicedependencies UNIQUE (instance_id,config_type,service_object_id,dependent_service_object_id,dependency_type,inherits_parent,fail_on_ok,fail_on_warning,fail_on_unknown,fail_on_critical) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_serviceescalations --- - -CREATE TABLE icinga_serviceescalations ( - serviceescalation_id bigserial, - instance_id bigint default 0, - config_type INTEGER default 0, - service_object_id bigint default 0, - timeperiod_object_id bigint default 0, - first_notification INTEGER default 0, - last_notification INTEGER default 0, - notification_interval double precision default 0, - escalate_on_recovery INTEGER default 0, - escalate_on_warning INTEGER default 0, - escalate_on_unknown INTEGER default 0, - escalate_on_critical INTEGER default 0, - CONSTRAINT PK_serviceescalation_id PRIMARY KEY (serviceescalation_id) , - CONSTRAINT UQ_serviceescalations UNIQUE (instance_id,config_type,service_object_id,timeperiod_object_id,first_notification,last_notification) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_serviceescalation_contactgroups --- - -CREATE TABLE icinga_serviceescalation_contactgroups ( - serviceescalation_contactgroup_id bigserial, - instance_id bigint default 0, - serviceescalation_id bigint default 0, - contactgroup_object_id bigint default 0, - CONSTRAINT PK_serviceescalation_contactgroup_id PRIMARY KEY (serviceescalation_contactgroup_id) , - CONSTRAINT UQ_serviceescalation_contactgro UNIQUE (serviceescalation_id,contactgroup_object_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_serviceescalation_contacts --- - -CREATE TABLE icinga_serviceescalation_contacts ( - serviceescalation_contact_id bigserial, - instance_id bigint default 0, - serviceescalation_id bigint default 0, - contact_object_id bigint default 0, - CONSTRAINT PK_serviceescalation_contact_id PRIMARY KEY (serviceescalation_contact_id) , - CONSTRAINT UQ_serviceescalation_contacts UNIQUE (instance_id,serviceescalation_id,contact_object_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_servicegroups --- - -CREATE TABLE icinga_servicegroups ( - servicegroup_id bigserial, - instance_id bigint default 0, - config_type INTEGER default 0, - servicegroup_object_id bigint default 0, - alias TEXT default '', - CONSTRAINT PK_servicegroup_id PRIMARY KEY (servicegroup_id) , - CONSTRAINT UQ_servicegroups UNIQUE (instance_id,config_type,servicegroup_object_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_servicegroup_members --- - -CREATE TABLE icinga_servicegroup_members ( - servicegroup_member_id bigserial, - instance_id bigint default 0, - servicegroup_id bigint default 0, - service_object_id bigint default 0, - CONSTRAINT PK_servicegroup_member_id PRIMARY KEY (servicegroup_member_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_services --- - -CREATE TABLE icinga_services ( - service_id bigserial, - instance_id bigint default 0, - config_type INTEGER default 0, - host_object_id bigint default 0, - service_object_id bigint default 0, - display_name TEXT default '', - check_command_object_id bigint default 0, - check_command_args TEXT default '', - eventhandler_command_object_id bigint default 0, - eventhandler_command_args TEXT default '', - notification_timeperiod_object_id bigint default 0, - check_timeperiod_object_id bigint default 0, - failure_prediction_options TEXT default '', - check_interval double precision default 0, - retry_interval double precision default 0, - max_check_attempts INTEGER default 0, - first_notification_delay double precision default 0, - notification_interval double precision default 0, - notify_on_warning INTEGER default 0, - notify_on_unknown INTEGER default 0, - notify_on_critical INTEGER default 0, - notify_on_recovery INTEGER default 0, - notify_on_flapping INTEGER default 0, - notify_on_downtime INTEGER default 0, - stalk_on_ok INTEGER default 0, - stalk_on_warning INTEGER default 0, - stalk_on_unknown INTEGER default 0, - stalk_on_critical INTEGER default 0, - is_volatile INTEGER default 0, - flap_detection_enabled INTEGER default 0, - flap_detection_on_ok INTEGER default 0, - flap_detection_on_warning INTEGER default 0, - flap_detection_on_unknown INTEGER default 0, - flap_detection_on_critical INTEGER default 0, - low_flap_threshold double precision default 0, - high_flap_threshold double precision default 0, - process_performance_data INTEGER default 0, - freshness_checks_enabled INTEGER default 0, - freshness_threshold INTEGER default 0, - passive_checks_enabled INTEGER default 0, - event_handler_enabled INTEGER default 0, - active_checks_enabled INTEGER default 0, - retain_status_information INTEGER default 0, - retain_nonstatus_information INTEGER default 0, - notifications_enabled INTEGER default 0, - obsess_over_service INTEGER default 0, - failure_prediction_enabled INTEGER default 0, - notes TEXT default '', - notes_url TEXT default '', - action_url TEXT default '', - icon_image TEXT default '', - icon_image_alt TEXT default '', - CONSTRAINT PK_service_id PRIMARY KEY (service_id) , - CONSTRAINT UQ_services UNIQUE (instance_id,config_type,service_object_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_servicestatus --- - -CREATE TABLE icinga_servicestatus ( - servicestatus_id bigserial, - instance_id bigint default 0, - service_object_id bigint default 0, - status_update_time timestamp with time zone default '1970-01-01 00:00:00', - output TEXT default '', - long_output TEXT default '', - perfdata TEXT default '', - current_state INTEGER default 0, - has_been_checked INTEGER default 0, - should_be_scheduled INTEGER default 0, - current_check_attempt INTEGER default 0, - max_check_attempts INTEGER default 0, - last_check timestamp with time zone default '1970-01-01 00:00:00', - next_check timestamp with time zone default '1970-01-01 00:00:00', - check_type INTEGER default 0, - last_state_change timestamp with time zone default '1970-01-01 00:00:00', - last_hard_state_change timestamp with time zone default '1970-01-01 00:00:00', - last_hard_state INTEGER default 0, - last_time_ok timestamp with time zone default '1970-01-01 00:00:00', - last_time_warning timestamp with time zone default '1970-01-01 00:00:00', - last_time_unknown timestamp with time zone default '1970-01-01 00:00:00', - last_time_critical timestamp with time zone default '1970-01-01 00:00:00', - state_type INTEGER default 0, - last_notification timestamp with time zone default '1970-01-01 00:00:00', - next_notification timestamp with time zone default '1970-01-01 00:00:00', - no_more_notifications INTEGER default 0, - notifications_enabled INTEGER default 0, - problem_has_been_acknowledged INTEGER default 0, - acknowledgement_type INTEGER default 0, - current_notification_number INTEGER default 0, - passive_checks_enabled INTEGER default 0, - active_checks_enabled INTEGER default 0, - event_handler_enabled INTEGER default 0, - flap_detection_enabled INTEGER default 0, - is_flapping INTEGER default 0, - percent_state_change double precision default 0, - latency double precision default 0, - execution_time double precision default 0, - scheduled_downtime_depth INTEGER default 0, - failure_prediction_enabled INTEGER default 0, - process_performance_data INTEGER default 0, - obsess_over_service INTEGER default 0, - modified_service_attributes INTEGER default 0, - event_handler TEXT default '', - check_command TEXT default '', - normal_check_interval double precision default 0, - retry_check_interval double precision default 0, - check_timeperiod_object_id bigint default 0, - CONSTRAINT PK_servicestatus_id PRIMARY KEY (servicestatus_id) , - CONSTRAINT UQ_servicestatus UNIQUE (service_object_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_service_contactgroups --- - -CREATE TABLE icinga_service_contactgroups ( - service_contactgroup_id bigserial, - instance_id bigint default 0, - service_id bigint default 0, - contactgroup_object_id bigint default 0, - CONSTRAINT PK_service_contactgroup_id PRIMARY KEY (service_contactgroup_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_service_contacts --- - -CREATE TABLE icinga_service_contacts ( - service_contact_id bigserial, - instance_id bigint default 0, - service_id bigint default 0, - contact_object_id bigint default 0, - CONSTRAINT PK_service_contact_id PRIMARY KEY (service_contact_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_statehistory --- - -CREATE TABLE icinga_statehistory ( - statehistory_id bigserial, - instance_id bigint default 0, - state_time timestamp with time zone default '1970-01-01 00:00:00', - state_time_usec INTEGER default 0, - object_id bigint default 0, - state_change INTEGER default 0, - state INTEGER default 0, - state_type INTEGER default 0, - current_check_attempt INTEGER default 0, - max_check_attempts INTEGER default 0, - last_state INTEGER default '-1', - last_hard_state INTEGER default '-1', - output TEXT default '', - long_output TEXT default '', - CONSTRAINT PK_statehistory_id PRIMARY KEY (statehistory_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_systemcommands --- - -CREATE TABLE icinga_systemcommands ( - systemcommand_id bigserial, - instance_id bigint default 0, - start_time timestamp with time zone default '1970-01-01 00:00:00', - start_time_usec INTEGER default 0, - end_time timestamp with time zone default '1970-01-01 00:00:00', - end_time_usec INTEGER default 0, - command_line TEXT default '', - timeout INTEGER default 0, - early_timeout INTEGER default 0, - execution_time double precision default 0, - return_code INTEGER default 0, - output TEXT default '', - long_output TEXT default '', - CONSTRAINT PK_systemcommand_id PRIMARY KEY (systemcommand_id) , - CONSTRAINT UQ_systemcommands UNIQUE (instance_id,start_time,start_time_usec) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_timedeventqueue --- - -CREATE TABLE icinga_timedeventqueue ( - timedeventqueue_id bigserial, - instance_id bigint default 0, - event_type INTEGER default 0, - queued_time timestamp with time zone default '1970-01-01 00:00:00', - queued_time_usec INTEGER default 0, - scheduled_time timestamp with time zone default '1970-01-01 00:00:00', - recurring_event INTEGER default 0, - object_id bigint default 0, - CONSTRAINT PK_timedeventqueue_id PRIMARY KEY (timedeventqueue_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_timedevents --- - -CREATE TABLE icinga_timedevents ( - timedevent_id bigserial, - instance_id bigint default 0, - event_type INTEGER default 0, - queued_time timestamp with time zone default '1970-01-01 00:00:00', - queued_time_usec INTEGER default 0, - event_time timestamp with time zone default '1970-01-01 00:00:00', - event_time_usec INTEGER default 0, - scheduled_time timestamp with time zone default '1970-01-01 00:00:00', - recurring_event INTEGER default 0, - object_id bigint default 0, - deletion_time timestamp with time zone default '1970-01-01 00:00:00', - deletion_time_usec INTEGER default 0, - CONSTRAINT PK_timedevent_id PRIMARY KEY (timedevent_id) , - CONSTRAINT UQ_timedevents UNIQUE (instance_id,event_type,scheduled_time,object_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_timeperiods --- - -CREATE TABLE icinga_timeperiods ( - timeperiod_id bigserial, - instance_id bigint default 0, - config_type INTEGER default 0, - timeperiod_object_id bigint default 0, - alias TEXT default '', - CONSTRAINT PK_timeperiod_id PRIMARY KEY (timeperiod_id) , - CONSTRAINT UQ_timeperiods UNIQUE (instance_id,config_type,timeperiod_object_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_timeperiod_timeranges --- - -CREATE TABLE icinga_timeperiod_timeranges ( - timeperiod_timerange_id bigserial, - instance_id bigint default 0, - timeperiod_id bigint default 0, - day INTEGER default 0, - start_sec INTEGER default 0, - end_sec INTEGER default 0, - CONSTRAINT PK_timeperiod_timerange_id PRIMARY KEY (timeperiod_timerange_id) -) ; - --- -------------------------------------------------------- - --- --- Table structure for table icinga_slahistory --- - -CREATE TABLE icinga_slahistory ( - slahistory_id serial, - instance_id bigint default 0, - start_time timestamp with time zone default '1970-01-01 00:00:00', - end_time timestamp with time zone default '1970-01-01 00:00:00', - acknowledgement_time timestamp with time zone default '1970-01-01 00:00:00', - object_id bigint default 0, - state INTEGER default 0, - state_type INTEGER default '0', - scheduled_downtime INTEGER default 0, - CONSTRAINT PK_slahistory_id PRIMARY KEY (slahistory_id) -) ; - - - --- ----------------------------------------- --- add index (delete) --- ----------------------------------------- - --- for periodic delete --- instance_id and --- TIMEDEVENTS => scheduled_time --- SYSTEMCOMMANDS, SERVICECHECKS, HOSTCHECKS, EVENTHANDLERS => start_time --- EXTERNALCOMMANDS => entry_time - --- instance_id -CREATE INDEX timedevents_i_id_idx on icinga_timedevents(instance_id); -CREATE INDEX timedeventq_i_id_idx on icinga_timedeventqueue(instance_id); -CREATE INDEX systemcommands_i_id_idx on icinga_systemcommands(instance_id); -CREATE INDEX servicechecks_i_id_idx on icinga_servicechecks(instance_id); -CREATE INDEX hostchecks_i_id_idx on icinga_hostchecks(instance_id); -CREATE INDEX eventhandlers_i_id_idx on icinga_eventhandlers(instance_id); -CREATE INDEX externalcommands_i_id_idx on icinga_externalcommands(instance_id); - --- time -CREATE INDEX timedevents_time_id_idx on icinga_timedevents(scheduled_time); -CREATE INDEX timedeventq_time_id_idx on icinga_timedeventqueue(scheduled_time); -CREATE INDEX systemcommands_time_id_idx on icinga_systemcommands(start_time); -CREATE INDEX servicechecks_time_id_idx on icinga_servicechecks(start_time); -CREATE INDEX hostchecks_time_id_idx on icinga_hostchecks(start_time); -CREATE INDEX eventhandlers_time_id_idx on icinga_eventhandlers(start_time); -CREATE INDEX externalcommands_time_id_idx on icinga_externalcommands(entry_time); - - --- for starting cleanup - referenced in dbhandler.c:882 --- instance_id only - --- realtime data -CREATE INDEX programstatus_i_id_idx on icinga_programstatus(instance_id); -CREATE INDEX hoststatus_i_id_idx on icinga_hoststatus(instance_id); -CREATE INDEX servicestatus_i_id_idx on icinga_servicestatus(instance_id); -CREATE INDEX contactstatus_i_id_idx on icinga_contactstatus(instance_id); -CREATE INDEX timedeventqueue_i_id_idx on icinga_timedeventqueue(instance_id); -CREATE INDEX comments_i_id_idx on icinga_comments(instance_id); -CREATE INDEX scheduleddowntime_i_id_idx on icinga_scheduleddowntime(instance_id); -CREATE INDEX runtimevariables_i_id_idx on icinga_runtimevariables(instance_id); -CREATE INDEX customvariablestatus_i_id_idx on icinga_customvariablestatus(instance_id); - --- config data -CREATE INDEX configfiles_i_id_idx on icinga_configfiles(instance_id); -CREATE INDEX configfilevariables_i_id_idx on icinga_configfilevariables(instance_id); -CREATE INDEX customvariables_i_id_idx on icinga_customvariables(instance_id); -CREATE INDEX commands_i_id_idx on icinga_commands(instance_id); -CREATE INDEX timeperiods_i_id_idx on icinga_timeperiods(instance_id); -CREATE INDEX timeperiod_timeranges_i_id_idx on icinga_timeperiod_timeranges(instance_id); -CREATE INDEX contactgroups_i_id_idx on icinga_contactgroups(instance_id); -CREATE INDEX contactgroup_members_i_id_idx on icinga_contactgroup_members(instance_id); -CREATE INDEX hostgroups_i_id_idx on icinga_hostgroups(instance_id); -CREATE INDEX hostgroup_members_i_id_idx on icinga_hostgroup_members(instance_id); -CREATE INDEX servicegroups_i_id_idx on icinga_servicegroups(instance_id); -CREATE INDEX servicegroup_members_i_id_idx on icinga_servicegroup_members(instance_id); -CREATE INDEX hostesc_i_id_idx on icinga_hostescalations(instance_id); -CREATE INDEX hostesc_contacts_i_id_idx on icinga_hostescalation_contacts(instance_id); -CREATE INDEX serviceesc_i_id_idx on icinga_serviceescalations(instance_id); -CREATE INDEX serviceesc_contacts_i_id_idx on icinga_serviceescalation_contacts(instance_id); -CREATE INDEX hostdependencies_i_id_idx on icinga_hostdependencies(instance_id); -CREATE INDEX contacts_i_id_idx on icinga_contacts(instance_id); -CREATE INDEX contact_addresses_i_id_idx on icinga_contact_addresses(instance_id); -CREATE INDEX contact_notifcommands_i_id_idx on icinga_contact_notificationcommands(instance_id); -CREATE INDEX hosts_i_id_idx on icinga_hosts(instance_id); -CREATE INDEX host_parenthosts_i_id_idx on icinga_host_parenthosts(instance_id); -CREATE INDEX host_contacts_i_id_idx on icinga_host_contacts(instance_id); -CREATE INDEX services_i_id_idx on icinga_services(instance_id); -CREATE INDEX service_contacts_i_id_idx on icinga_service_contacts(instance_id); -CREATE INDEX service_contactgroups_i_id_idx on icinga_service_contactgroups(instance_id); -CREATE INDEX host_contactgroups_i_id_idx on icinga_host_contactgroups(instance_id); -CREATE INDEX hostesc_cgroups_i_id_idx on icinga_hostescalation_contactgroups(instance_id); -CREATE INDEX serviceesc_cgroups_i_id_idx on icinga_serviceescalation_contactgroups(instance_id); - --- ----------------------------------------- --- more index stuff (WHERE clauses) --- ----------------------------------------- - --- hosts -CREATE INDEX hosts_host_object_id_idx on icinga_hosts(host_object_id); - --- hoststatus -CREATE INDEX hoststatus_stat_upd_time_idx on icinga_hoststatus(status_update_time); -CREATE INDEX hoststatus_current_state_idx on icinga_hoststatus(current_state); -CREATE INDEX hoststatus_check_type_idx on icinga_hoststatus(check_type); -CREATE INDEX hoststatus_state_type_idx on icinga_hoststatus(state_type); -CREATE INDEX hoststatus_last_state_chg_idx on icinga_hoststatus(last_state_change); -CREATE INDEX hoststatus_notif_enabled_idx on icinga_hoststatus(notifications_enabled); -CREATE INDEX hoststatus_problem_ack_idx on icinga_hoststatus(problem_has_been_acknowledged); -CREATE INDEX hoststatus_act_chks_en_idx on icinga_hoststatus(active_checks_enabled); -CREATE INDEX hoststatus_pas_chks_en_idx on icinga_hoststatus(passive_checks_enabled); -CREATE INDEX hoststatus_event_hdl_en_idx on icinga_hoststatus(event_handler_enabled); -CREATE INDEX hoststatus_flap_det_en_idx on icinga_hoststatus(flap_detection_enabled); -CREATE INDEX hoststatus_is_flapping_idx on icinga_hoststatus(is_flapping); -CREATE INDEX hoststatus_p_state_chg_idx on icinga_hoststatus(percent_state_change); -CREATE INDEX hoststatus_latency_idx on icinga_hoststatus(latency); -CREATE INDEX hoststatus_ex_time_idx on icinga_hoststatus(execution_time); -CREATE INDEX hoststatus_sch_downt_d_idx on icinga_hoststatus(scheduled_downtime_depth); - --- services -CREATE INDEX services_host_object_id_idx on icinga_services(host_object_id); - ---servicestatus -CREATE INDEX srvcstatus_stat_upd_time_idx on icinga_servicestatus(status_update_time); -CREATE INDEX srvcstatus_current_state_idx on icinga_servicestatus(current_state); -CREATE INDEX srvcstatus_check_type_idx on icinga_servicestatus(check_type); -CREATE INDEX srvcstatus_state_type_idx on icinga_servicestatus(state_type); -CREATE INDEX srvcstatus_last_state_chg_idx on icinga_servicestatus(last_state_change); -CREATE INDEX srvcstatus_notif_enabled_idx on icinga_servicestatus(notifications_enabled); -CREATE INDEX srvcstatus_problem_ack_idx on icinga_servicestatus(problem_has_been_acknowledged); -CREATE INDEX srvcstatus_act_chks_en_idx on icinga_servicestatus(active_checks_enabled); -CREATE INDEX srvcstatus_pas_chks_en_idx on icinga_servicestatus(passive_checks_enabled); -CREATE INDEX srvcstatus_event_hdl_en_idx on icinga_servicestatus(event_handler_enabled); -CREATE INDEX srvcstatus_flap_det_en_idx on icinga_servicestatus(flap_detection_enabled); -CREATE INDEX srvcstatus_is_flapping_idx on icinga_servicestatus(is_flapping); -CREATE INDEX srvcstatus_p_state_chg_idx on icinga_servicestatus(percent_state_change); -CREATE INDEX srvcstatus_latency_idx on icinga_servicestatus(latency); -CREATE INDEX srvcstatus_ex_time_idx on icinga_servicestatus(execution_time); -CREATE INDEX srvcstatus_sch_downt_d_idx on icinga_servicestatus(scheduled_downtime_depth); - --- timedeventqueue -CREATE INDEX timed_e_q_event_type_idx on icinga_timedeventqueue(event_type); -CREATE INDEX timed_e_q_sched_time_idx on icinga_timedeventqueue(scheduled_time); -CREATE INDEX timed_e_q_object_id_idx on icinga_timedeventqueue(object_id); -CREATE INDEX timed_e_q_rec_ev_id_idx on icinga_timedeventqueue(recurring_event); - --- timedevents -CREATE INDEX timed_e_event_type_idx on icinga_timedevents(event_type); ---CREATE INDEX timed_e_sched_time_idx on icinga_timedevents(scheduled_time); --already set for delete -CREATE INDEX timed_e_object_id_idx on icinga_timedevents(object_id); -CREATE INDEX timed_e_rec_ev_idx on icinga_timedevents(recurring_event); - --- hostchecks -CREATE INDEX hostchks_h_obj_id_idx on icinga_hostchecks(host_object_id); - --- servicechecks -CREATE INDEX servicechks_s_obj_id_idx on icinga_servicechecks(service_object_id); - --- objects -CREATE INDEX objects_objtype_id_idx ON icinga_objects(objecttype_id); -CREATE INDEX objects_name1_idx ON icinga_objects(name1); -CREATE INDEX objects_name2_idx ON icinga_objects(name2); -CREATE INDEX objects_inst_id_idx ON icinga_objects(instance_id); - --- instances --- CREATE INDEX instances_name_idx on icinga_instances(instance_name); - --- logentries --- CREATE INDEX loge_instance_id_idx on icinga_logentries(instance_id); --- #236 -CREATE INDEX loge_time_idx on icinga_logentries(logentry_time); --- CREATE INDEX loge_data_idx on icinga_logentries(logentry_data); -CREATE INDEX loge_inst_id_time_idx on icinga_logentries (instance_id, logentry_time); - - --- commenthistory --- CREATE INDEX c_hist_instance_id_idx on icinga_logentries(instance_id); --- CREATE INDEX c_hist_c_time_idx on icinga_logentries(comment_time); --- CREATE INDEX c_hist_i_c_id_idx on icinga_logentries(internal_comment_id); - --- downtimehistory --- CREATE INDEX d_t_hist_nstance_id_idx on icinga_downtimehistory(instance_id); --- CREATE INDEX d_t_hist_type_idx on icinga_downtimehistory(downtime_type); --- CREATE INDEX d_t_hist_object_id_idx on icinga_downtimehistory(object_id); --- CREATE INDEX d_t_hist_entry_time_idx on icinga_downtimehistory(entry_time); --- CREATE INDEX d_t_hist_sched_start_idx on icinga_downtimehistory(scheduled_start_time); --- CREATE INDEX d_t_hist_sched_end_idx on icinga_downtimehistory(scheduled_end_time); - --- scheduleddowntime --- CREATE INDEX sched_d_t_downtime_type_idx on icinga_scheduleddowntime(downtime_type); --- CREATE INDEX sched_d_t_object_id_idx on icinga_scheduleddowntime(object_id); --- CREATE INDEX sched_d_t_entry_time_idx on icinga_scheduleddowntime(entry_time); --- CREATE INDEX sched_d_t_start_time_idx on icinga_scheduleddowntime(scheduled_start_time); --- CREATE INDEX sched_d_t_end_time_idx on icinga_scheduleddowntime(scheduled_end_time); - --- Icinga Web Notifications -CREATE INDEX notification_idx ON icinga_notifications(notification_type, object_id, start_time); -CREATE INDEX notification_object_id_idx ON icinga_notifications(object_id); -CREATE INDEX contact_notification_idx ON icinga_contactnotifications(notification_id, contact_object_id); -CREATE INDEX contacts_object_id_idx ON icinga_contacts(contact_object_id); -CREATE INDEX contact_notif_meth_notif_idx ON icinga_contactnotificationmethods(contactnotification_id, command_object_id); -CREATE INDEX command_object_idx ON icinga_commands(object_id); -CREATE INDEX services_combined_object_idx ON icinga_services(service_object_id, host_object_id); - --- statehistory -CREATE INDEX statehist_i_id_o_id_s_ty_s_ti on icinga_statehistory(instance_id, object_id, state_type, state_time); ---#2274 -create index statehist_state_idx on icinga_statehistory(object_id,state); - --- SLA statehistory -CREATE INDEX slahist_i_id_o_id_s_ti_s_s_ti_e on icinga_slahistory(instance_id,object_id,start_time,end_time); - --- #2618 -CREATE INDEX cntgrpmbrs_cgid_coid ON icinga_contactgroup_members (contactgroup_id,contact_object_id); -CREATE INDEX hstgrpmbrs_hgid_hoid ON icinga_hostgroup_members (hostgroup_id,host_object_id); -CREATE INDEX hstcntgrps_hid_cgoid ON icinga_host_contactgroups (host_id,contactgroup_object_id); -CREATE INDEX hstprnthsts_hid_phoid ON icinga_host_parenthosts (host_id,parent_host_object_id); -CREATE INDEX runtimevars_iid_varn ON icinga_runtimevariables (instance_id,varname); -CREATE INDEX sgmbrs_sgid_soid ON icinga_servicegroup_members (servicegroup_id,service_object_id); -CREATE INDEX scgrps_sid_cgoid ON icinga_service_contactgroups (service_id,contactgroup_object_id); -CREATE INDEX tperiod_tid_d_ss_es ON icinga_timeperiod_timeranges (timeperiod_id,day,start_sec,end_sec); - --- #3649 -CREATE INDEX sla_idx_sthist ON icinga_statehistory (object_id, state_time DESC); -CREATE INDEX sla_idx_dohist ON icinga_downtimehistory (object_id, actual_start_time, actual_end_time); -CREATE INDEX sla_idx_obj ON icinga_objects (objecttype_id, is_active, name1); - - --- ----------------------------------------- --- set dbversion --- ----------------------------------------- - -SELECT updatedbversion('1.9.0'); diff --git a/modules/monitoring/test/php/testlib/datasource/strategies/InsertionStrategy.php b/modules/monitoring/test/php/testlib/datasource/strategies/InsertionStrategy.php deleted file mode 100644 index 50138fa35..000000000 --- a/modules/monitoring/test/php/testlib/datasource/strategies/InsertionStrategy.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Test\Monitoring\Testlib\Datasource\Strategies; -use \Test\Monitoring\Testlib\DataSource\TestFixture; - -/** - * Generic interface for Fixture insertion implementations - * - * These implementations can create Icinga-compatible Datatsources - * from TestFixture classes and are therefore rather free in their - * implementation - * - */ -interface InsertionStrategy { - /** - * Tell the class to use the given ressource as the - * connection identifier - * - * @param $connection A generic connection identifier, - * the concrete class depends on the implementation - */ - public function setConnection($connection); - - /** - * Insert the passed fixture into the datasource and allow - * the icinga backends to query it. - * - * @param TestFixture $fixture - */ - public function insert(TestFixture $fixture); -} diff --git a/modules/monitoring/test/php/testlib/datasource/strategies/MySQLSetupStrategy.php b/modules/monitoring/test/php/testlib/datasource/strategies/MySQLSetupStrategy.php deleted file mode 100644 index ae167d891..000000000 --- a/modules/monitoring/test/php/testlib/datasource/strategies/MySQLSetupStrategy.php +++ /dev/null @@ -1,107 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Test\Monitoring\Testlib\Datasource\Strategies; - -/** - * SetupStrategy implementation for MySQL based IDO-Backends - * - * This strategy creates a new MySQL Database and removes old ones - * if necessary. Per default the database user is icinga_unittest:icinga_unittest - * and the database to be created is also icinga_unittest. The user must - * have all Privileges on the test database, so its best to create him - * with: - * - * mysql -u root - * # CREATE USER `icinga_unittest`@`localhost` IDENTIFIED BY 'icinga_unittest'; - * # CREATE DATABASE icinga_unittest; - * # GRANT ALL PRIVILEGES ON icinga_unittest.* TO `icinga_unittest`@`localhost` - * - **/ -class MySQLSetupStrategy implements SetupStrategy { - - /** - * Tears down any existing databases and creates a new blank IDO scheme. - * - * The database is created according to the passed version (or using the newest version if no version is provided), - * using the idoMySQL-%VERSION%.sql underneath the schemes folder. - * A \PDO Connection can be provided, if not the icinga_unittest default - * connection will be established and used. - * - * @param String $version An optional version to use as the db scheme - * @param \PDO $connection An optional connection to use instead of icinga_unittest - * @return \PDO The connection that has been created - * - * @throws \PDOException In case connecting to or creating the database fails - * @throws \Exception In case of an invalid/non-existing DB scheme - */ - public function setup($version = null, $connection = null) - { - if ($connection === null) { - $connection = new \PDO("mysql:dbname=icinga_unittest", "icinga_unittest", "icinga_unittest"); - } - - $connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - $this->teardown($connection); - - // the latest schema doesn't have a suffix, so if no version is given this one is used - $sqlFileName = 'idoMySQL'.($version !== null ? '-'.$version : '' ).'.sql'; - $path = realpath(dirname(__FILE__).'/../schemes/'.$sqlFileName); - if (!file_exists($path)) { - throw new \Exception('File '.$path.' not found: Could not create scheme for IDO mysql backend '.($version ? '(version : '.$version.')' :'')); - } - - $connection->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true); - - if ($connection->query(file_get_contents($path)) === false) { - $error = $connection->errorInfo();; - throw new \PDOException($error[0].' : '.$error[2]); - } - return $connection; - } - - /** - * Drops all tables from the connection via DROP TABLE - * - * @param \PDO $connection An optional connection to use, if none is - * given the icinga_unittest default will be used - * - */ - public function teardown($connection = null) - { - if ($connection === null) { - $connection = new \PDO("mysql:dbname=icinga_unittest", "icinga_unittest", "icinga_unittest"); - } - - $tables = $connection->query("SHOW TABLES")->fetchAll(); - foreach($tables as $table) { - $connection->query("DROP TABLE ".$table[0]); - } - } -} diff --git a/modules/monitoring/test/php/testlib/datasource/strategies/PDOInsertionStrategy.php b/modules/monitoring/test/php/testlib/datasource/strategies/PDOInsertionStrategy.php deleted file mode 100644 index 660e8daec..000000000 --- a/modules/monitoring/test/php/testlib/datasource/strategies/PDOInsertionStrategy.php +++ /dev/null @@ -1,328 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Test\Monitoring\Testlib\Datasource\Strategies; -use \Test\Monitoring\Testlib\DataSource\TestFixture; - -/** - * TestFixture insertion implementation for PDO based backends - * - * This class allows to create the actual IDO databases from TestFixture - * classes using PDO. - * - */ -class PDOInsertionStrategy -{ - /** - * Points to the (icinga) objectId of the next inserted object - * @var int - */ - private $objectId = 0; - - /** - * The fixture that is being inserted by this object - * @var TestFixture - */ - private $fixture; - - /** - * The database (PDO) connection to use for inserting - * @var \PDO - */ - private $connection; - - /** - * The date format that will be used for inserting - * date values, see @link http://php.net/manual/en/function.date.php - * for possible values - * - * @var string - */ - public $datetimeFormat = "U"; - - /** - * @see InsertionStrategy::setConnection - * - * @param \PDO $connection The PDO connection to use - */ - public function setConnection($connection) { - $this->connection = $connection; - } - - /** - * Insert the provided @see TestFixture into this database - * - * @param TestFixture $fixture The fixture to insert into the database - */ - public function insert(TestFixture $fixture) - { - $this->fixture = $fixture; - - $this->insertContacts(); - - $this->insertHosts(); - $this->insertServices(); - $this->insertComments(); - - $this->insertHostgroups(); - $this->insertServicegroups(); - } - - /** - * Insert all hosts from the current fixture into the IDO Database - * - * This method updates the icinga_objects, icinga_hosts, icinga_hoststatus - * and icinga_customvariablestatus tables with the host values provided - * by the internal fixture (@see PDOInsertStrategy::insert) - * - */ - private function insertHosts() - { - $hosts = $this->fixture->getHosts(); - - $insertObjectQuery = $this->connection->prepare( - 'INSERT INTO icinga_objects (object_id, objecttype_id, name1, is_active) VALUES (?, 1, ?, 1);' - ); - $insertHostQuery = $this->connection->prepare( - 'INSERT INTO icinga_hosts ('. - 'host_id, alias, display_name, address, host_object_id, '. - 'icon_image, notes_url, action_url'. - ') VALUES (?, ?, ?, ?, ?, ?, ?, ?);' - ); - $insertContactQuery = $this->connection->prepare( - 'INSERT INTO icinga_host_contacts (host_id, contact_object_id) VALUES (?, ?);' - ); - $insertHostStatusQuery = $this->connection->prepare( - 'INSERT INTO icinga_hoststatus'. - '(host_object_id, current_state, last_check, last_state_change, notifications_enabled, '. - 'active_checks_enabled, passive_checks_enabled, is_flapping, scheduled_downtime_depth,'. - 'output, long_output, '. - 'problem_has_been_acknowledged, has_been_checked) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' - ); - $insertCVQuery = $this->connection->prepare( - 'INSERT INTO icinga_customvariablestatus'. - '(object_id, varname, varvalue) VALUES (?, ?, ?)' - ); - foreach($hosts as &$host) { - $flags = $host["flags"]; - - $insertObjectQuery->execute(array($this->objectId, $host["name"])); - $insertHostQuery->execute(array( - $this->objectId, $host["name"]." alias", $host["name"], $host["address"], $this->objectId, - $host["icon_image"], $host["notes_url"], $host["action_url"] - )); - $insertHostStatusQuery->execute(array( - $this->objectId, $host["state"], date($this->datetimeFormat, $flags->time), - date($this->datetimeFormat, $flags->time), $flags->notifications, $flags->active_checks, - $flags->passive_checks, $flags->flapping, $flags->in_downtime, "Plugin output for host ".$host["name"], - "Long plugin output for host ".$host["name"], $flags->acknowledged, $flags->is_pending == 0 - )); - - foreach($host["contacts"] as $contact) { - $insertContactQuery->execute(array($this->objectId, $contact["object_id"])); - } - foreach($host["customvariables"] as $cvName=>$cvValue) { - $insertCVQuery->execute(array($this->objectId, $cvName, $cvValue)); - } - - $host["object_id"] = $this->objectId; - $this->objectId++; - } - } - - /** - * Insert all services from the provided fixture into the IDO database - * - * This method updates the icinga_objects, icinga_services, icinga_servicestatus, - * icinga_service_contacts, icinga_customvariablestatus - */ - private function insertServices() - { - $services = $this->fixture->getServices(); - $insertObjectQuery = $this->connection->prepare( - 'INSERT INTO icinga_objects (object_id, objecttype_id, name1, name2, is_active) VALUES (?, 2, ?, ?, 1);' - ); - $insertServiceQuery = $this->connection->prepare( - 'INSERT INTO icinga_services ('. - 'service_id, host_object_id, service_object_id, display_name, '. - 'icon_image, notes_url, action_url'. - ') VALUES (?, ?, ?, ?, ?, ?, ?)' - ); - $insertServiceStatusQuery = $this->connection->prepare( - 'INSERT INTO icinga_servicestatus'. - '(service_object_id, current_state, last_check, last_state_change, notifications_enabled, '. - 'active_checks_enabled, passive_checks_enabled, is_flapping, scheduled_downtime_depth,'. - 'output, long_output, '. - 'problem_has_been_acknowledged, has_been_checked) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ' - ); - $insertContactQuery = $this->connection->prepare( - 'INSERT INTO icinga_service_contacts (host_id, contact_object_id) VALUES (?, ?);' - ); - $insertCVQuery = $this->connection->prepare( - 'INSERT INTO icinga_customvariablestatus '. - '(object_id, varname, varvalue) VALUES (?, ?, ?)' - ); - - foreach($services as &$service) { - $flags = $service["flags"]; - - $insertObjectQuery->execute(array($this->objectId, $service["host"]["name"], $service["name"])); - $insertServiceQuery->execute(array( - $this->objectId, $service['host']['object_id'], $this->objectId, $service['name'], - $service["icon_image"], $service["notes_url"], $service["action_url"] - )); - $insertServiceStatusQuery->execute(array( - $this->objectId, $service["state"], date($this->datetimeFormat, $flags->time), - date($this->datetimeFormat, $flags->time), $flags->notifications, $flags->active_checks, - $flags->passive_checks, $flags->flapping, $flags->in_downtime, "Plugin output for service ".$service["name"], - "Long plugin output for service ".$service["name"], $flags->acknowledged, - $flags->is_pending == 0 ? '1' : '0' - )); - - foreach($service["contacts"] as $contact) { - $insertContactQuery->execute(array($this->objectId, $contact["object_id"])); - } - - foreach($service["customvariables"] as $cvName=>$cvValue) { - $insertCVQuery->execute(array($this->objectId, $cvName, $cvValue)); - } - - $service["object_id"] = $this->objectId; - $this->objectId++; - } - } - - /** - * Insert the contacts provided by the fixture into the database - * - * This method updates the icinga_objects and icinga_contacts tables - * according to the provided fixture - */ - private function insertContacts() - { - $insertObjectQuery = $this->connection->prepare( - 'INSERT INTO icinga_objects (object_id, objecttype_id, name1) VALUES (?, 10, ?);' - ); - $insertContactQuery = $this->connection->prepare( - 'INSERT INTO icinga_contacts (contact_object_id, alias) VALUES (?, ?);' - ); - $contacts = $this->fixture->getContacts(); - foreach($contacts as &$contact) { - $insertObjectQuery->execute($this->objectId, $contact["alias"]); - $insertContactQuery->execute($this->objectId, $contact["alias"]); - $contact["object_id"] = $this->objectId; - $this->objectId++; - } - } - - /** - * Insert comments provided by the fixture into the IDO database - * - * This method updates the icinga_comments table according to the provided - * fixture - */ - private function insertComments() - { $comment_id=0; - $insertCommentsQuery = $this->connection->prepare( - 'INSERT INTO icinga_comments (object_id, comment_type, internal_comment_id, author_name, comment_data)'. - ' VALUES (?, ?, ?, ?, ?);' - ); - $comments = $this->fixture->getComments(); - foreach ($comments as $comment) { - if (isset($comment["host"])) { - $type = 1; - $object_id = $comment["host"]["object_id"]; - } elseif (isset($comment["service"])) { - $type = 2; - $object_id = $comment["service"]["object_id"]; - } - $insertCommentsQuery->execute(array( - $object_id, $type, $comment_id++, $comment["author"], $comment["text"] - )); - } - } - - /** - * Insert hostgroups from the provided fixture into the IDO database - * - * This method updates the icinga_objects, icinga_hostgroups and icinga_hostgroup_members - * table with the values provide by the fixture - */ - private function insertHostgroups() - { - $insertObjectQuery = $this->connection->prepare( - 'INSERT INTO icinga_objects (object_id, objecttype_id, name1) VALUES (?, 3, ?)' - ); - $insertHostgroupQuery = $this->connection->prepare( - 'INSERT INTO icinga_hostgroups (hostgroup_id, hostgroup_object_id, alias) VALUES (?, ?, ?)' - ); - $insertHostgroupMemberQuery = $this->connection->prepare( - 'INSERT INTO icinga_hostgroup_members (hostgroup_id, host_object_id) VALUES (?, ?)' - ); - $hostgroups = $this->fixture->getHostgroups(); - - foreach ($hostgroups as &$hostgroup) { - $insertObjectQuery->execute(array($this->objectId, $hostgroup["name"])); - $insertHostgroupQuery->execute(array($this->objectId, $this->objectId, $hostgroup["name"])); - foreach ($hostgroup["members"] as $member) { - $insertHostgroupMemberQuery->execute(array($this->objectId, $member["object_id"])); - } - $this->objectId++; - } - } - - /** - * Insert servicegroups from the provided fixture into the IDO database - * - * This method updates the icinga_objects, icinga_servicegroups and icinga_servicegroup_members - * table with the values provide by the fixture - */ - private function insertServicegroups() - { - $insertObjectQuery = $this->connection->prepare( - 'INSERT INTO icinga_objects (object_id, objecttype_id, name1) VALUES (?, 4, ?)' - ); - $insertServicegroupQuery = $this->connection->prepare( - 'INSERT INTO icinga_servicegroups (servicegroup_id, servicegroup_object_id, alias) VALUES (?, ?, ?)' - ); - $insertServicegroupMemberQuery = $this->connection->prepare( - 'INSERT INTO icinga_servicegroup_members (servicegroup_id, service_object_id) VALUES (?, ?)' - ); - $servicegroups = $this->fixture->getServicegroups(); - - foreach ($servicegroups as &$servicegroup) { - $insertObjectQuery->execute(array($this->objectId, $servicegroup["name"])); - $insertServicegroupQuery->execute(array($this->objectId, $this->objectId, $servicegroup["name"])); - foreach ($servicegroup["members"] as $member) { - $insertServicegroupMemberQuery->execute(array($this->objectId, $member["object_id"])); - } - $this->objectId++; - } - } -} diff --git a/modules/monitoring/test/php/testlib/datasource/strategies/PgSQLSetupStrategy.php b/modules/monitoring/test/php/testlib/datasource/strategies/PgSQLSetupStrategy.php deleted file mode 100644 index 7014326d7..000000000 --- a/modules/monitoring/test/php/testlib/datasource/strategies/PgSQLSetupStrategy.php +++ /dev/null @@ -1,102 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Test\Monitoring\Testlib\Datasource\Strategies; - -/*** - * SetupStrategy implementation for PostgreSQL based IDO-Backends - * - * This strategy creates a new PostgreSQL Database and removes old ones - * if necessary. Per default the database user is icinga_unittest:icinga_unittest - * and the database to be created is also icinga_unittest. - **/ -class PgSQLSetupStrategy implements SetupStrategy { - - /** - * Tears down any existing databases and creates a new blank IDO scheme. - * - * The database is created according to the passed version (or using the - * newest version if no version is provided), using the idoPgSQL-%VERSION%.sql - * underneath the schemes folder. - * A \PDO Connection can be provided, if not the icinga_unittest default - * connection will be established and used. - * - * @param String $version An optional version to use as the db scheme - * @param \PDO $connection An optional connection to use instead of icinga_unittest - * @return \PDO The connection that has been created - * - * @throws \PDOException In case connecting to or creating the database fails - * @throws \Exception In case of an invalid/non-existing DB scheme - */ - public function setup($version = null, $connection = null) - { - if ($connection === null) { - $connection = new \PDO('pgsql:dbname=icinga_unittest', 'icinga_unittest', 'icinga_unittest'); - } - - $connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - $this->teardown($connection); - - // the latest schema doesn't have a suffix, so if no version is given this one is used - $sqlFileName = 'idoPgSQL'.($version !== null ? '-'.$version : '' ).'.sql'; - $path = realpath(dirname(__FILE__).'/../schemes/'.$sqlFileName); - if (!file_exists($path)) { - throw new \Exception('File '.$path.' not found: Could not create scheme for IDO pgsql backend '.($version ? '(version : '.$version.')' :'')); - } - $connection->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true); - - if ($connection->query(file_get_contents($path)) === false) { - $error = $connection->errorInfo();; - throw new \PDOException($error[0].' : '.$error[2]); - } - return $connection; - } - - /** - * Drops all tables from the connection via DROP TABLE - * - * @param \PDO $connection An optional connection to use, if none is - * given the icinga_unittest default will be used - * - */ - public function teardown($connection = null) - { - if ($connection === null) { - $connection = new \PDO('pgsql:dbname=icinga_unittest', 'icinga_unittest', 'icinga_unittest'); - } - $tables = $connection - ->query('SELECT table_schema,table_name FROM information_schema.tables WHERE table_type = \'BASE TABLE\''. - 'AND table_schema = \'public\' ORDER BY table_schema,table_name;') - ->fetchAll(); - - foreach($tables as $table) { - $connection->query('DROP TABLE '.$table['table_name']); - } - } -} diff --git a/modules/monitoring/test/php/testlib/datasource/strategies/SetupStrategy.php b/modules/monitoring/test/php/testlib/datasource/strategies/SetupStrategy.php deleted file mode 100644 index 1661aecab..000000000 --- a/modules/monitoring/test/php/testlib/datasource/strategies/SetupStrategy.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Test\Monitoring\Testlib\Datasource\Strategies; -use Test\Monitoring\Testlib\DataSource\schemes\ObjectsCacheTemplates; -use \Test\Monitoring\Testlib\DataSource\TestFixture; -use \Test\Monitoring\Testlib\DataSource\schemes\StatusdatTemplates; - -require_once(dirname(__FILE__).'/../schemes/ObjectsCacheTemplates.php'); -require_once(dirname(__FILE__).'/../schemes/StatusdatTemplates.php'); - -/** - * An @see InsertionStrategy for creating status.dat and objects.cache - * files from a TestFixture - * - * This class helps testing status.dat backends by writing testfixtures - * to according objects.cache and status.dat files which then can be read - * by the Statusdat parser and used in tests. - * - * The Templates for insertion can be found under schemes/objectsCacheTemplates.php - * and schemes/StatusdatTempaltes.php - * - */ -class StatusdatInsertionStrategy implements InsertionStrategy { - - /** - * The status.dat filename to write the object-state to - * @var String - */ - private $statusDatFile; - - /** - * The objects.cache filename to write the object structure to - * @var String - */ - private $objectsCacheFile; - - /** - * The TestFixture that will be written to a status.dat compatible format - * @var TestFixture - */ - private $fixture; - - /** - * The content of the status.dat file that will be written - * @var String - */ - private $statusDat; - - /** - * The content of the objects.cache file that will be written - * @var String - */ - private $objectsCache; - - /** - * Tell this object to use the status.dat/objects.cache file combination - * provided in $resource - * - * @param Array $ressource An associative array containing the following keys: - * - "status_file" : The location where to write the status.dat to - * - "objects_file" : The location to write the objects cache to - */ - public function setConnection($ressource) - { - $this->statusDatFile = $ressource['status_file']; - $this->objectsCacheFile = $ressource['object_file']; - } - - /** - * Insert the provided fixture into the status.dat and objects.cache files for testing - * - * @param TestFixture $fixture The fixture to create status.dat and objects.cache files from - */ - public function insert(TestFixture $fixture) - { - $this->fixture = $fixture; - $this->statusDat = '# Automatically created test statusdat from fixture\n'; - $this->objectsCache = ''; - $this->insertHoststatus(); - $this->insertHosts(); - $this->insertServicestatus(); - $this->insertServices(); - - $this->insertHostgroups(); - $this->insertServicegroups(); - $this->insertComments(); - - file_put_contents($this->statusDatFile, $this->statusDat); - file_put_contents($this->objectsCacheFile, $this->objectsCache); - } - - /** - * Insert the host monitoring state from the provided fixture to the internal - * statusdat string $statusDat - * - */ - private function insertHoststatus() - { - $hosts = $this->fixture->getHosts(); - foreach ($hosts as $host) { - $cvs = ''; - foreach ($host['customvariables'] as $name=>$var) { - $cvs .= '_'.$name.'='.$var."\n"; - } - $flags = $host['flags']; - $hostStatus = str_replace( - array( - '{{HOST_NAME}}', '{{TIME}}', '{{NOTIFICATIONS_ENABLED}}', - '{{ACKNOWLEDGED}}', '{{ACTIVE_ENABLED}}', '{{PASSIVE_ENABLED}}', - '{{FLAPPING}}', '{{IN_DOWNTIME}}', '{{HOST_STATUS}}','{{CVS}}') - , array( - $host['name'], $flags->time, $flags->notifications, $flags->acknowledged, - $flags->active_checks, $flags->passive_checks, $flags->flapping, - $flags->in_downtime, $host['state'], $cvs - ), StatusdatTemplates::$HOST); - $this->statusDat .= "\n".$hostStatus; - } - } - - /** - * Insert the host object state into the internal objects.cache representation - * $objectsCache - * - */ - private function insertHosts() - { - $hosts = $this->fixture->getHosts(); - foreach ($hosts as $host) { - if ($host['flags']->is_pending) { - continue; // Pending states are not written to status.dat yet - } - $hostDefinition = str_replace( - array('\t', - '{{HOST_NAME}}', '{{HOST_ADDRESS}}', '{{ICON_IMAGE}}', - '{{NOTES_URL}}', '{{ACTION_URL}}' - ), - array("\t", - $host['name'], $host['address'], $host['icon_image'], - $host['notes_url'], $host['action_url'] - ), - ObjectsCacheTemplates::$HOST - ); - $this->objectsCache .= "\n".$hostDefinition; - } - } - - /** - * Insert the service monitoring state from the provided fixture to the internal - * statusdat string $statusDat - * - */ - private function insertServicestatus() - { - $services = $this->fixture->getServices(); - foreach ($services as $service) { - if ($service['flags']->is_pending) { - continue; // Pending states are not written to status.dat yet - } - $cvs = ''; - foreach ($service['customvariables'] as $name=>$var) { - $cvs .= '_'.$name.'='.$var; - } - - $flags = $service['flags']; - $serviceStatus = str_replace( - array( - '{{HOST_NAME}}','{{SERVICE_NAME}}', '{{TIME}}', '{{NOTIFICATIONS_ENABLED}}', - '{{ACKNOWLEDGED}}', '{{ACTIVE_ENABLED}}', '{{PASSIVE_ENABLED}}', - '{{FLAPPING}}', '{{IN_DOWNTIME}}', '{{SERVICE_STATUS}}','{{CVS}}') - , array( - $service['host']['name'], $service['name'], $flags->time, $flags->notifications, - $flags->acknowledged, $flags->active_checks, $flags->passive_checks, - $flags->flapping, $flags->in_downtime, $service['state'], $cvs - ), StatusdatTemplates::$SERIVCE); - - $this->statusDat .= "\n".$serviceStatus; - } - - } - - /** - * Insert the service object state into the internal objects.cache representation - * $objectsCache - * - */ - private function insertServices() - { - $services = $this->fixture->getServices(); - foreach ($services as $service) { - $serviceDefinition = str_replace( - array('\t', - '{{HOST_NAME}}', '{{SERVICE_NAME}}', '{{ICON_IMAGE}}', - '{{NOTES_URL}}', '{{ACTION_URL}}' - ), - array("\t", - $service['host']['name'], $service['name'], $service['icon_image'], - $service['notes_url'], $service['action_url'] - ), - ObjectsCacheTemplates::$SERVICE - ); - $this->objectsCache .= "\n".$serviceDefinition; - } - } - - /** - * Inserts a group object into the object.cache file - * - * @param String $type The type of the group ('host' or 'service') - * @param String $name The name of the group to insert - * @param array $members A String array of the members names to use - */ - private function insertGroup($type, $name, array $members) - { - $groupDefinition = str_replace( - array('\t', - '{{TYPE}}', '{{NAME}}', '{{MEMBERS}}' - ), - array("\t", - $type, $name, implode(",", $members) - ), - ObjectsCacheTemplates::$GROUP - ); - $this->objectsCache .= "\n".$groupDefinition; - } - - /** - * Insert all hostgroups from the fixtures into the objects.cache - * - */ - private function insertHostgroups() - { - $hostgroups = $this->fixture->getHostgroups(); - foreach ($hostgroups as $hostgroup) { - $memberNames = array(); - foreach ($hostgroup["members"] as $member) { - $memberNames[] = $member["name"]; - } - $this->insertGroup("host", $hostgroup["name"], $memberNames); - } - } - - /** - * Inserts all servicegroups from the fixtures into the objects.cache - * - */ - private function insertServicegroups() - { - $servicegroups = $this->fixture->getServicegroups(); - foreach ($servicegroups as $servicegroup) { - $memberNames = array(); - foreach ($servicegroup["members"] as $member) { - $memberNames[] = $member["host"]["name"]; - $memberNames[] = $member["name"]; - } - $this->insertGroup("service", $servicegroup["name"], $memberNames); - } - } - - /** - * Inserts all comments from the fixtures into the status.dat string - * $statusDat - * - */ - private function insertComments() - { - $comments = $this->fixture->getComments(); - $commentId = 1; - foreach($comments as $comment) { - if (isset($comment["service"])) { - $service = $comment["service"]; - $commentDefinition = str_replace( - array('{{HOST_NAME}}', '{{SERVICE_NAME}}', '{{TIME}}', '{{AUTHOR}}', '{{TEXT}}', '{{ID}}'), - array( - $service["host"]["name"], $service["name"], $service["flags"]->time, - $comment["author"], $comment["text"], $commentId++ - ), - StatusdatTemplates::$SERVICECOMMENT - ); - } elseif (isset($comment["host"])) { - $host = $comment["host"]; - $commentDefinition = str_replace( - array('{{HOST_NAME}}', '{{TIME}}', '{{AUTHOR}}', '{{TEXT}}', '{{ID}}'), - array( - $host["name"], $host["flags"]->time, - $comment["author"], $comment["text"], $commentId++ - ), - StatusdatTemplates::$HOSTCOMMENT - ); - } - $this->statusDat .= "\n".$commentDefinition; - } - } -} diff --git a/modules/monitoring/test/php/testlib/datasource/strategies/StatusdatSetupStrategy.php b/modules/monitoring/test/php/testlib/datasource/strategies/StatusdatSetupStrategy.php deleted file mode 100644 index e428ec6fe..000000000 --- a/modules/monitoring/test/php/testlib/datasource/strategies/StatusdatSetupStrategy.php +++ /dev/null @@ -1,126 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Test\Monitoring\Testlib\Datasource\Strategies; - -use Tests\Icinga\Protocol\Statusdat\StatusdatTestLoader; -/** - * SetupStrategy for status dat. - * - * This class is used for setting up a test enviromnent for querying - * statusdat fixtures. - * - */ -class StatusdatSetupStrategy implements SetupStrategy { - - /** - * Recursively require all php files underneath $folder - * - * @param String $folder The folder to require - */ - private function requireFolder($folder) - { - $files = scandir($folder); - foreach($files as $file) { - if ($file[0] == ".") { - continue; - } - if (is_dir($folder."/".$file)) { - $this->requireFolder($folder."/".$file); - } elseif (preg_match("/\.php/", $file)) { - require_once(realpath($folder."/".$file)); - } - } - } - - /** - * Require all classes needed to work with the status.dat Reader - * - * This includes the Status.dat Reader and Parser classes - * from Icinga/PRotocol as well as a few dependencies (Logging, Zend_Cache) - * - */ - private function requireStatusDat() - { - require_once 'library/Icinga/Protocol/Statusdat/StatusdatTestLoader.php'; - StatusdatTestLoader::requireLibrary(); - } - - /** - * Create the status.dat and objects.cache files for using testfixtures - * - * Remove existing files for status.dat testfixtures and create new - * (empty) files at /tmp/ when no resource is given. - * - * @param String $version The version to use, will be ignored - * @param array $resource An optional associative array pointing to the - * objects_cache and status.dat files. The keys are as following: - * - "status_file" : Path to the status.dat to remove and recreate - * - "objects_file" : Path to the objects.cache file to remove and recreate - * @return array An path array (see $resource) that contains the used file paths - */ - public function setup($version = null, $resource = null) - { - if ($resource == null) { - $resource = array( - "status_file" => "/tmp/teststatus.dat", - "object_file" => "/tmp/testobjects.cache" - ); - } - $this->requireStatusDat(); - $this->teardown($resource); - touch($resource["status_file"]); - touch($resource["object_file"]); - return $resource; - } - - /** - * Remove test status.dat and objects.cache files - * - * @param array $resource An optional associative array pointing to the - * objects_cache and status.dat files. The keys are as following: - * - "status_file" : Path to the status.dat to remove - * - "objects_file" : Path to the objects.cache file to remove - */ - public function teardown($resource = null) - { - if ($resource == null) { - $resource = array( - "status_file" => "/tmp/teststatus.dat", - "object_file" => "/tmp/testobjects.cache" - ); - } - if (file_exists($resource["status_file"])) { - unlink($resource["status_file"]); - } - if (file_exists($resource["object_file"])) { - unlink($resource["object_file"]); - } - } -} diff --git a/public/css/icinga/layout-colors.less b/public/css/icinga/layout-colors.less index 0b6c25660..36225c66b 100644 --- a/public/css/icinga/layout-colors.less +++ b/public/css/icinga/layout-colors.less @@ -44,9 +44,17 @@ @colorWarningHandled: #ffcc66; @colorCritical: #ff5566; @colorCriticalHandled: #ff99aa; +/* @colorUnknown: #dd66ff; @colorUnknownHandled: #ee99ff; -@colorPending: #77aaff; -@colorInvalid: #999; @colorUnreachable: #dd66ff; @colorUnreachableHandled: #ee99ff; +*/ +@colorUnknown: #aa44ff; +@colorUnknownHandled: #cc77ff; +@colorUnreachable: #aa44ff; +@colorUnreachableHandled: #cc77ff; + +@colorPending: #77aaff; +@colorInvalid: #999; + diff --git a/public/css/icinga/layout-structure.less b/public/css/icinga/layout-structure.less index afcd0bb86..1e6382cde 100644 --- a/public/css/icinga/layout-structure.less +++ b/public/css/icinga/layout-structure.less @@ -35,6 +35,17 @@ html { bottom: 0; } +.iframe { + #header, #sidebar { + display: none; + } + + #main { + left: 0; + top: 0; + } +} + #responsive-debug { font-size: 0.9em; font-family: Courier new, monospace; diff --git a/public/css/icinga/menu.less b/public/css/icinga/menu.less index 9632345a3..6b7d73ed0 100644 --- a/public/css/icinga/menu.less +++ b/public/css/icinga/menu.less @@ -6,6 +6,7 @@ #menu a { outline: 0; + color: black; } #menu .separator { @@ -26,6 +27,10 @@ display: none; } +.no-js #menu > ul > li > ul { + display: block; +} + #menu > ul > li.active > ul { display: block; } diff --git a/public/css/icinga/selection-toolbar.less b/public/css/icinga/selection-toolbar.less new file mode 100644 index 000000000..91d83fbc4 --- /dev/null +++ b/public/css/icinga/selection-toolbar.less @@ -0,0 +1,8 @@ +div.selection-toolbar { + float: right; + padding-right: 20px; +} + +div.selection-toolbar a { + color: #049baf +} \ No newline at end of file diff --git a/public/js/icinga/events.js b/public/js/icinga/events.js index 614b85c38..d78229a16 100644 --- a/public/js/icinga/events.js +++ b/public/js/icinga/events.js @@ -13,6 +13,12 @@ Icinga.Events.prototype = { + keyboard: { + ctrlKey: false, + altKey: false, + shiftKey: false + }, + /** * Icinga will call our initialize() function once it's ready */ @@ -20,6 +26,7 @@ this.applyGlobalDefaults(); this.applyHandlers($('#layout')); this.icinga.ui.prepareContainers(); + this.icinga.ui.prepareMultiselectTables($(document)); }, // TODO: What's this? @@ -61,11 +68,27 @@ $('input.autofocus', el).focus(); - $('.inlinepie', el).sparkline('html', { - type: 'pie', - sliceColors: ['#44bb77', '#ffaa44', '#ff5566', '#dcd'], - width: '2em', - height: '2em', + $('div.inlinepie', el).each(function() { + var $img = $(this).find('img'); + var title = $img.attr('title'), + values = $img.data('icinga-values'), + colors = $img.data('icinga-colors'), + width = $img.css('width'), + height = $img.css('height'); + if (colors) { + colors = colors.split(','); + } + $img.replaceWith(values); + $(this).sparkline( + 'html', + { + type: 'pie', + sliceColors: colors || ['#44bb77', '#ffaa44', '#ff5566', '#dcd'], + width: width, + height: height, + tooltipChartTitle: title + } + ); }); }, @@ -89,8 +112,9 @@ // We want to catch each link click $(document).on('click', 'a', { self: this }, this.linkClicked); - // We treat tr's with a href attribute like links - $(document).on('click', 'tr[href]', { self: this }, this.linkClicked); + // Select a table row + $(document).on('click', 'table.action tr[href]', { self: this }, this.rowSelected); + $(document).on('click', 'table.action tr a', { self: this }, this.rowSelected); $(document).on('click', 'button', { self: this }, this.submitForm); @@ -110,6 +134,8 @@ $(document).on('mouseleave', '#sidebar', this.leaveSidebar); $(document).on('click', '.tree .handle', { self: this }, this.treeNodeToggle); + // Toggle all triStateButtons + $(document).on('click', 'div.tristate .tristate-dummy', { self: this }, this.clickTriState); // TBD: a global autocompletion handler // $(document).on('keyup', 'form.auto input', this.formChangeDelayed); @@ -225,6 +251,38 @@ return event.data.self.submitForm(event, true); }, + clickTriState: function (event) { + var $tristate = $(this); + var triState = parseInt($tristate.data('icinga-tristate'), 10); + + // load current values + var old = $tristate.data('icinga-old').toString(); + var value = $tristate.parent().find('input:radio:checked').first().prop('checked', false).val(); + + // calculate the new value + if (triState) { + // 1 => 0 + // 0 => unchanged + // unchanged => 1 + value = value === '1' ? '0' : (value === '0' ? 'unchanged' : '1'); + } else { + // 1 => 0 + // 0 => 1 + value = value === '1' ? '0' : '1'; + } + + // update form value + $tristate.parent().find('input:radio[value="' + value + '"]').prop('checked', true); + // update dummy + + if (value !== old) { + $tristate.parent().find('b.tristate-changed').css('visibility', 'visible'); + } else { + $tristate.parent().find('b.tristate-changed').css('visibility', 'hidden'); + } + self.icinga.ui.setTriState(value.toString(), $tristate); + }, + /** * */ @@ -277,6 +335,92 @@ return false; }, + handleExternalTarget: function($node) { + var linkTarget = $node.attr('target'); + + // TODO: Let remote links pass through. Right now they only work + // combined with target="_blank" or target="_self" + // window.open is used as return true; didn't work reliable + if (linkTarget === '_blank' || linkTarget === '_self') { + window.open(href, linkTarget); + return true; + } + return false; + }, + + /** + * Handle table selection. + */ + rowSelected: function(event) { + var self = event.data.self; + var icinga = self.icinga; + var $tr = $(this); + var $table = $tr.closest('table.multiselect'); + var data = self.icinga.ui.getSelectionKeys($table); + var multisel = $table.hasClass('multiselect'); + var url = $table.data('icinga-multiselect-url'); + + // When the selection points to a link, select the closest row + if ($tr.prop('tagName').toLowerCase() === 'a') { + $tr = $tr.closest('tr').first(); + } + + event.stopPropagation(); + event.preventDefault(); + + if (icinga.events.handleExternalTarget($tr)) { + // link handled externally + return false; + } + if (multisel && !data) { + icinga.logger.error('A table with multiselection must define the attribute "data-icinga-multiselect-data"'); + return; + } + if (multisel && !url) { + icinga.logger.error('A table with multiselection must define the attribute "data-icinga-multiselect-url"'); + return; + } + + // update selection + if ((event.ctrlKey || event.metaKey) && multisel) { + icinga.ui.toogleTableRowSelection($tr); + // multi selection + } else if (event.shiftKey && multisel) { + // range selection + icinga.ui.addTableRowRangeSelection($tr); + } else { + // single selection + icinga.ui.setTableRowSelection($tr); + } + // focus only the current table. + icinga.ui.focusTable($table[0]); + + // update url + var $target = self.getLinkTargetFor($tr); + if (multisel) { + var $trs = $table.find('tr[href].active'); + if ($trs.length > 1) { + var queries = []; + var selectionData = icinga.ui.getSelectionSetData($trs, data); + var query = icinga.ui.selectionDataToQuery(selectionData, data, icinga); + icinga.loader.loadUrl(url + '?' + query, $target); + icinga.ui.storeSelectionData(selectionData); + } else if ($trs.length === 1) { + // display a single row + icinga.loader.loadUrl($tr.attr('href'), $target); + icinga.ui.storeSelectionData($tr.attr('href')); + } else { + // display nothing + icinga.loader.loadUrl('#'); + icinga.ui.storeSelectionData(null); + } + } else { + icinga.loader.loadUrl($tr.attr('href'), $target); + } + return false; + }, + + /** * Someone clicked a link or tr[href] */ @@ -299,6 +443,11 @@ return false; } + // ignore links inside of tables. + if ($a.closest('table tr').length > 0) { + return; + } + // Handle all other links as XHR requests event.stopPropagation(); event.preventDefault(); @@ -409,7 +558,8 @@ $(window).off('beforeunload', this.onUnload); $(document).off('scroll', '.container', this.onContainerScroll); $(document).off('click', 'a', this.linkClicked); - $(document).off('click', 'tr[href]', this.linkClicked); + $(document).off('click', 'table.action tr[href]', this.rowSelected); + $(document).off('click', 'table.action tr a', this.rowSelected); $(document).off('submit', 'form', this.submitForm); $(document).off('click', 'button', this.submitForm); $(document).off('change', 'form select.autosubmit', this.submitForm); @@ -417,6 +567,7 @@ $(document).off('mouseleave', '.historycolorgrid td', this.historycolorgidUnhover); $(document).off('mouseenter', 'li.dropdown', this.dropdownHover); $(document).off('mouseleave', 'li.dropdown', this.dropdownLeave); + $(document).off('click', 'div.tristate .tristate-dummy', this.clickTriState); }, destroy: function() { diff --git a/public/js/icinga/history.js b/public/js/icinga/history.js index 68e858ddb..326be38c7 100644 --- a/public/js/icinga/history.js +++ b/public/js/icinga/history.js @@ -142,8 +142,7 @@ ).historyTriggered = true; } - // && document.location.hash.match(/^#!/) ?? - if (document.location.hash) { + if (document.location.hash && document.location.hash.match(/^#!/)) { parts = document.location.hash.split(/#!/); diff --git a/public/js/icinga/loader.js b/public/js/icinga/loader.js index cafd9aad8..5d2679d55 100644 --- a/public/js/icinga/loader.js +++ b/public/js/icinga/loader.js @@ -247,7 +247,9 @@ if (! req.autorefresh) { // TODO: Hook for response/url? var $forms = $('[action="' + this.icinga.utils.parseUrl(url).path + '"]'); + var $matches = $.merge($('[href="' + url + '"]'), $forms); + $matches.each(function (idx, el) { if ($(el).closest('#menu').length) { $('#menu .active').removeClass('active'); @@ -273,6 +275,7 @@ }); } else { // TODO: next container url + // Get first container url? active = $('[href].active', req.$target).attr('href'); } @@ -311,10 +314,8 @@ req.$target.data('icingaModule', moduleName); classes.push('icinga-module'); classes.push('module-' + moduleName); - req.$target.attr('class', classes); } else { req.$target.removeData('icingaModule'); - // req.$target.attr('class', 'container'); // TODO: remove module-$name } req.$target.attr('class', classes.join(' ')); @@ -389,19 +390,12 @@ this.icinga.history.pushCurrentState(); } } + this.icinga.ui.initializeTriStates($resp); - - /* - * Replace SVG piecharts with jQuery-Sparkline + /** + * Make multiselection-tables not selectable. */ - $('.inlinepie', $resp).each(function(){ - var title = $(this).attr('title'), - style = $(this).attr('style'), - values = $(this).data('icinga-values'); - var html = '
' + values + '
'; - $(this).replaceWith(html); - }); - + this.icinga.ui.prepareMultiselectTables($resp); /* Should we try to fiddle with responses containing full HTML? */ /* @@ -438,7 +432,39 @@ } if (active) { - $('[href="' + active + '"]', req.$target).addClass('active'); + var focusedUrl = this.icinga.ui.getFocusedContainerDataUrl(); + var oldSelectionData = this.icinga.ui.loadSelectionData(); + if (typeof oldSelectionData === 'string') { + $('[href="' + oldSelectionData + '"]', req.$target).addClass('active'); + + } else if (oldSelectionData !== null) { + var $container; + if (!focusedUrl) { + $container = $('document').first(); + } else { + $container = $('.container[data-icinga-url="' + focusedUrl + '"]');; + } + + var $table = $container.find('table.action').first(); + var keys = self.icinga.ui.getSelectionKeys($table); + + // build map of selected queries + var oldSelectionQueries = {}; + $.each(oldSelectionData, function(i, query){ + oldSelectionQueries[self.icinga.ui.selectionDataToQueryComp(query)] = true; + }); + + // set all new selections to active + $table.find('tr[href]').filter(function(){ + var $tr = $(this); + var rowData = self.icinga.ui.getSelectionData($tr, keys, self.icinga); + var newSelectionQuery = self.icinga.ui.selectionDataToQueryComp(rowData); + if (oldSelectionQueries[newSelectionQuery]) { + return true; + } + return false; + }).addClass('active'); + } } req.$target.trigger('rendered'); }, @@ -482,7 +508,7 @@ // Icinga.debug(req.getResponseHeader('X-Icinga-Redirect')); } else { if (errorThrown === 'abort') { - this.icinga.logger.info( + this.icinga.logger.debug( 'Request to ' + url + ' has been aborted for ', req.$target ); diff --git a/public/js/icinga/ui.js b/public/js/icinga/ui.js index 27ebae7a4..e71310d62 100644 --- a/public/js/icinga/ui.js +++ b/public/js/icinga/ui.js @@ -7,6 +7,13 @@ 'use strict'; + // Stores the icinga-data-url of the last focused table. + var focusedTableDataUrl = null; + + // The stored selection data, useful for preserving selections over + // multiple reload-cycles. + var selectionData = null; + Icinga.UI = function (icinga) { this.icinga = icinga; @@ -198,12 +205,10 @@ return true; } } - this.icinga.logger.error( 'Someone messed up our responsiveness hacks, html font-family is', layout ); - return false; }, @@ -271,6 +276,220 @@ */ }, + /** + * Prepare all multiselectable tables for multi-selection by + * removing the regular text selection. + */ + prepareMultiselectTables: function () { + var $rows = $('table.multiselect tr[href]'); + $rows.find('td').attr('unselectable', 'on') + .css('user-select', 'none') + .css('-webkit-user-select', 'none') + .css('-moz-user-select', 'none') + .css('-ms-user-select', 'none'); + }, + + /** + * Add the given table-row to the selection of the closest + * table and deselect all other rows of the closest table. + * + * @param $tr {jQuery} The selected table row. + * @returns {boolean} If the selection was changed. + */ + setTableRowSelection: function ($tr) { + var $table = $tr.closest('table.multiselect'); + $table.find('tr[href].active').removeClass('active'); + $tr.addClass('active'); + return true; + }, + + /** + * Toggle the given table row to "on" when not selected, or to "off" when + * currently selected. + * + * @param $tr {jQuery} The table row. + * @returns {boolean} If the selection was changed. + */ + toogleTableRowSelection: function ($tr) { + // multi selection + if ($tr.hasClass('active')) { + $tr.removeClass('active'); + } else { + $tr.addClass('active'); + } + return true; + }, + + /** + * Add a new selection range to the closest table, using the selected row as + * range target. + * + * @param $tr {jQuery} The target of the selected range. + * @returns {boolean} If the selection was changed. + */ + addTableRowRangeSelection: function ($tr) { + var $table = $tr.closest('table.multiselect'); + var $rows = $table.find('tr[href]'), + from, to; + var selected = $tr.first().get(0); + $rows.each(function(i, el) { + if ($(el).hasClass('active') || el === selected) { + if (!from) { + from = el; + } + to = el; + } + }); + var inRange = false; + $rows.each(function(i, el){ + if (el === from) { + inRange = true; + } + if (inRange) { + $(el).addClass('active'); + } + if (el === to) { + inRange = false; + } + }); + return false; + }, + + + /** + * Read the data from a whole set of selections. + * + * @param $selections {jQuery} All selected rows in a jQuery-selector. + * @param keys {Array} An array containing all valid keys. + * @returns {Array} An array containing an object with the data for each selection. + */ + getSelectionSetData: function($selections, keys) { + var selections = []; + var icinga = this.icinga; + + // read all current selections + $selections.each(function(ind, selected) { + selections.push(icinga.ui.getSelectionData($(selected), keys, icinga)); + }); + return selections; + }, + + getSelectionKeys: function($selection) + { + var d = $selection.data('icinga-multiselect-data') && $selection.data('icinga-multiselect-data').split(','); + return d || []; + }, + + /** + * Read the data from the given selected object. + * + * @param $selection {jQuery} The selected object. + * @param keys {Array} An array containing all valid keys. + * @param icinga {Icinga} The main icinga object. + * @returns {Object} An object containing all key-value pairs associated with this selection. + */ + getSelectionData: function($selection, keys, icinga) + { + var url = $selection.attr('href'); + var params = this.icinga.utils.parseUrl(url).params; + var tuple = {}; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + if (params[key]) { + tuple[key] = params[key]; + } + } + return tuple; + }, + + /** + * Convert a set of selection data to a single query. + * + * @param selectionData {Array} The selection data generated from getSelectionData + * @returns {String} The formatted and uri-encoded query-string. + */ + selectionDataToQuery: function (selectionData) { + var queries = []; + + // create new url + if (selectionData.length < 2) { + // single-selection + $.each(selectionData[0], function(key, value){ + queries.push(key + '=' + encodeURIComponent(value)); + }); + } else { + // multi-selection + $.each(selectionData, function(i, el){ + $.each(el, function(key, value) { + queries.push(key + '[' + i + ']=' + encodeURIComponent(value)); + }); + }); + } + return queries.join('&'); + }, + + /** + * Create a single query-argument (not compatible to selectionDataToQuery) + * + * @param data + * @returns {string} + */ + selectionDataToQueryComp: function(data) { + var queries = []; + $.each(data, function(key, value){ + queries.push(key + '=' + encodeURIComponent(value)); + }); + return queries.join('&'); + }, + + /** + * Store a set of selection-data to preserve it accross page-reloads + * + * @param data {Array|String|Null} The selection-data be an Array of Objects, + * containing the selection data (when multiple rows where selected), a + * String containing a single url (when only a single row was selected) or + * Null when nothing was selected. + */ + storeSelectionData: function(data) { + selectionData = data; + }, + + /** + * Load the last stored set of selection-data + * + * @returns {Array|String|Null} May be an Array of Objects, containing the selection data + * (when multiple rows where selected), a String containing a single url + * (when only a single row was selected) or Null when nothing was selected. + */ + loadSelectionData: function() { + return selectionData; + }, + + /** + * Focus the given table by deselecting all selections on all other tables. + * + * Focusing a table is important for environments with multiple tables like + * the dashboard. It should only be possible to select rows at one table at a time, + * when a user selects a row on a table all rows that are not child of the given table + * will be removed from the selection. + * + * @param table {htmlElement} The table to focus. + */ + focusTable: function (table) { + $('table').filter(function(){ return this !== table; }).find('tr[href]').removeClass('active'); + var n = $(table).closest('div.container').attr('data-icinga-url'); + focusedTableDataUrl = n; + }, + + /** + * Return the URL of the last focused table container. + * + * @returns {String} The data-icinga-url of the last focused table, which should be unique in each site. + */ + getFocusedContainerDataUrl: function() { + return focusedTableDataUrl; + }, + refreshDebug: function () { var size = this.getDefaultFontSize().toString(); @@ -369,6 +588,62 @@ return $calc.width() / 1000; }, + /** + * Initialize all TriStateCheckboxes in the given html + */ + initializeTriStates: function ($html) { + var self = this; + $('div.tristate', $html).each(function(index, item) { + var $target = $(item); + + // hide input boxess and remove text nodes + $target.find("input").hide(); + $target.contents().filter(function() { return this.nodeType === 3; }).remove(); + + // has three states? + var triState = $target.find('input[value="unchanged"]').size() > 0 ? 1 : 0; + + // fetch current value from radiobuttons + var value = $target.find('input:checked').first().val(); + + $target.append( + ' ' + ); + if (triState) { + // TODO: find a better way to activate indeterminate checkboxes after load. + $target.append( + '' + ); + } + }); + }, + + /** + * Set the value of the given TriStateCheckbox + * + * @param value {String} The value to set, can be '1', '0' and 'unchanged' + * @param $checkbox {jQuery} The checkbox + */ + setTriState: function(value, $checkbox) + { + switch (value) { + case ('1'): + $checkbox.prop('checked', true).prop('indeterminate', false); + break; + case ('0'): + $checkbox.prop('checked', false).prop('indeterminate', false); + break; + case ('unchanged'): + $checkbox.prop('checked', false).prop('indeterminate', true); + break; + } + }, + initializeControls: function (parent) { var self = this; diff --git a/public/js/icinga/utils.js b/public/js/icinga/utils.js index 7a756092e..bf081d016 100644 --- a/public/js/icinga/utils.js +++ b/public/js/icinga/utils.js @@ -104,7 +104,7 @@ path : a.pathname.replace(/^([^\/])/,'/$1'), relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [,''])[1], segments: a.pathname.replace(/^\//,'').split('/'), - params : this.parseParams(a), + params : this.parseParams(a) }; a = null; diff --git a/test/php/application/controllers/IndexControllerTest.php b/test/php/application/controllers/IndexControllerTest.php deleted file mode 100644 index 73732ba7d..000000000 --- a/test/php/application/controllers/IndexControllerTest.php +++ /dev/null @@ -1,53 +0,0 @@ -applicationPath = realpath(__DIR__. '/../../../../application'); - - if (!defined('APPLICATION_PATH')) { - define('APPLICATION_PATH', $this->applicationPath); - } - - if (!defined('APPLICATION_ENV')) { - define('APPLICATION_ENV', 'test'); - } - - // Assign and instantiate in one step: - $this->bootstrap = array($this, 'appBootstrap'); - - parent::setUp(); - } - - public function appBootstrap() - { - $this->getFrontController()->setControllerDirectory($this->applicationPath. '/controllers'); - } - - public function testIndexAction() - { - $this->markTestSkipped('Static can not be detached from bootstrap'); - $this->dispatch('/index/welcome'); - $this->assertController('error'); - } -} diff --git a/test/php/application/forms/Config/Authentication/BaseBackendFormTest.php b/test/php/application/forms/Config/Authentication/BaseBackendFormTest.php new file mode 100644 index 000000000..ca32a1dae --- /dev/null +++ b/test/php/application/forms/Config/Authentication/BaseBackendFormTest.php @@ -0,0 +1,61 @@ +is_valid; + } +} + +class BaseBackendFormTest extends BaseTestCase +{ + public function testIsForceCreationCheckboxBeingAdded() + { + $form = new BackendForm(); + $form->is_valid = false; + + $this->assertFalse($form->isValid(array())); + $this->assertNotNull( + $form->getElement('backend_force_creation'), + 'Checkbox to force a backend\'s creation is not being added though the backend is invalid' + ); + } + + public function testIsForceCreationCheckboxNotBeingAdded() + { + $form = new BackendForm(); + $form->is_valid = true; + + $this->assertTrue($form->isValid(array())); + $this->assertNull( + $form->getElement('backend_force_creation'), + 'Checkbox to force a backend\'s creation is being added though the backend is valid' + ); + } + + public function testIsTheFormValidIfForceCreationTrue() + { + $form = new BackendForm(); + $form->is_valid = false; + + $this->assertTrue( + $form->isValid(array('backend_force_creation' => 1)), + 'BaseBackendForm with invalid backend is not valid though force creation is set' + ); + } +} diff --git a/test/php/application/forms/Config/Authentication/DbBackendFormTest.php b/test/php/application/forms/Config/Authentication/DbBackendFormTest.php new file mode 100644 index 000000000..b5553a896 --- /dev/null +++ b/test/php/application/forms/Config/Authentication/DbBackendFormTest.php @@ -0,0 +1,68 @@ +shouldReceive('create')->with('test', Mockery::type('\Zend_Config'))->andReturnUsing( + function () { return Mockery::mock(array('count' => 1)); } + ); + + $form = new DbBackendForm(); + $form->setBackendName('test'); + $form->setResources(array('test_db_backend' => null)); + $form->create(); + $form->populate(array('backend_test_resource' => 'test_db_backend')); + + $this->assertTrue( + $form->isValidAuthenticationBackend(), + 'DbBackendForm claims that a valid authentication backend with users is not valid' + ); + } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testInvalidBackendIsNotValid() + { + Mockery::mock('alias:Icinga\Authentication\UserBackend') + ->shouldReceive('create')->with('test', Mockery::type('\Zend_Config'))->andReturnUsing( + function () { return Mockery::mock(array('count' => 0)); } + ); + + $form = new DbBackendForm(); + $form->setBackendName('test'); + $form->setResources(array('test_db_backend' => null)); + $form->create(); + $form->populate(array('backend_test_resource' => 'test_db_backend')); + + $this->assertFalse( + $form->isValidAuthenticationBackend(), + 'DbBackendForm claims that an invalid authentication backend without users is valid' + ); + } +} diff --git a/test/php/application/forms/Config/Authentication/LdapBackendFormTest.php b/test/php/application/forms/Config/Authentication/LdapBackendFormTest.php new file mode 100644 index 000000000..a3a0cfcaa --- /dev/null +++ b/test/php/application/forms/Config/Authentication/LdapBackendFormTest.php @@ -0,0 +1,68 @@ +shouldReceive('create')->with('test', Mockery::type('\Zend_Config'))->andReturnUsing( + function () { return Mockery::mock(array('count' => 1)); } + ); + + $form = new LdapBackendForm(); + $form->setBackendName('test'); + $form->setResources(array('test_ldap_backend' => null)); + $form->create(); + $form->populate(array('backend_test_resource' => 'test_ldap_backend')); + + $this->assertTrue( + $form->isValidAuthenticationBackend(), + 'LdapBackendForm claims that a valid authentication backend with users is not valid' + ); + } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testInvalidBackendIsNotValid() + { + Mockery::mock('alias:Icinga\Authentication\UserBackend') + ->shouldReceive('create')->with('test', Mockery::type('\Zend_Config'))->andReturnUsing( + function () { return Mockery::mock(array('count' => 0)); } + ); + + $form = new LdapBackendForm(); + $form->setBackendName('test'); + $form->setResources(array('test_ldap_backend' => null)); + $form->create(); + $form->populate(array('backend_test_resource' => 'test_ldap_backend')); + + $this->assertFalse( + $form->isValidAuthenticationBackend(), + 'LdapBackendForm claims that an invalid authentication backend without users is valid' + ); + } +} diff --git a/test/php/application/forms/Config/Authentication/ReorderFormTest.php b/test/php/application/forms/Config/Authentication/ReorderFormTest.php new file mode 100644 index 000000000..a61efc48a --- /dev/null +++ b/test/php/application/forms/Config/Authentication/ReorderFormTest.php @@ -0,0 +1,80 @@ + $this->order); + } +} + +class ReorderFormTest extends BaseTestCase +{ + public function setUp() + { + parent::setUp(); + $this->viewMock = Mockery::mock('\Zend_View'); + $this->viewMock->shouldReceive('icon')->andReturn(''); + } + + public function testMoveBackendUp() + { + $config = new Zend_Config( + array( + 'test1' => '', + 'test2' => '', + 'test3' => '' + ) + ); + $oldOrder = array_keys($config->toArray()); + + $form = new RequestLessReorderForm(); + $form->setCurrentOrder($oldOrder); + $form->setBackendName('test3'); + $form->setView($this->viewMock); + $form->create(); + + $form->order = $form->getSubForm('btn_reorder_up')->getElement('form_backend_order')->getValue(); + $this->assertSame( + $form->getReorderedConfig($config), + array('test1' => '', 'test3' => '', 'test2' => ''), + 'Moving elements up with ReorderForm does not seem to properly work' + ); + } + + public function testMoveBackendDown() + { + $config = new Zend_Config( + array( + 'test1' => '', + 'test2' => '', + 'test3' => '' + ) + ); + $oldOrder = array_keys($config->toArray()); + + $form = new RequestLessReorderForm(); + $form->setCurrentOrder($oldOrder); + $form->setBackendName('test1'); + $form->setView($this->viewMock); + $form->create(); + + $form->order = $form->getSubForm('btn_reorder_down')->getElement('form_backend_order')->getValue(); + $this->assertSame( + $form->getReorderedConfig($config), + array('test2' => '', 'test1' => '', 'test3' => ''), + 'Moving elements down with ReorderForm does not seem to properly work' + ); + } +} diff --git a/test/php/application/forms/Config/AuthenticationFormTest.php b/test/php/application/forms/Config/AuthenticationFormTest.php deleted file mode 100644 index 61559d82f..000000000 --- a/test/php/application/forms/Config/AuthenticationFormTest.php +++ /dev/null @@ -1,234 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Test\Icinga\Form\Config; - -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -// @codingStandardsIgnoreEnd - -use Icinga\Test\BaseTestCase; - -// @codingStandardsIgnoreStart -require_once 'Zend/Form.php'; -require_once 'Zend/Config.php'; -require_once 'Zend/Config/Ini.php'; - -require_once BaseTestCase::$testDir . '/library/Icinga/Web/RequestMock.php'; - -require_once BaseTestCase::$libDir . '/Web/Form.php'; -require_once BaseTestCase::$libDir . '/Web/Url.php'; - -require_once BaseTestCase::$appDir . '/forms/Config/Authentication/BaseBackendForm.php'; -require_once BaseTestCase::$appDir . '/forms/Config/Authentication/DbBackendForm.php'; -require_once BaseTestCase::$appDir . '/forms/Config/Authentication/LdapBackendForm.php'; -require_once BaseTestCase::$appDir . '/forms/Config/Authentication/ReorderForm.php'; -// @codingStandardsIgnoreEnd - -use \Zend_Config; -use \Icinga\Web\Url; -use \Tests\Icinga\Web\RequestMock; - -/** - * Test for the authentication provider form - * - */ -class AuthenticationFormTest extends BaseTestCase -{ - /** - * Return a test configuration containing a database and a ldap backend - * - * @return Zend_Config - */ - private function getTestConfig() - { - return new Zend_Config( - array( - 'test-db' => array( - 'backend' => 'db', - 'target' => 'user', - 'resource' => 'db_resource' - ), - 'test-ldap' => array( - 'backend' => 'ldap', - 'target' => 'user', - 'hostname' => 'test host', - 'root_dn' => 'ou=test,dc=icinga,dc=org', - 'bind_dn' => 'cn=testuser,cn=config', - 'bind_pw' => 'password', - 'user_class' => 'testClass', - 'user_name_attribute' => 'testAttribute' - ) - ) - ); - } - - /** - * Test the ldap provider form population from config - */ - public function testLdapProvider() - { - $this->requireFormLibraries(); - $form = $this->createForm('Icinga\Form\Config\Authentication\LdapBackendForm'); - $config = new Zend_Config( - array( - 'backend' => 'ldap', - 'target' => 'user', - 'user_class' => 'testClass', - 'user_name_attribute' => 'testAttribute' - ) - ); - $form->setBackendName('testldap'); - $form->setBackend($config); - $form->create(array('resources' => array())); - - // parameters to be hidden - $notShown = array('backend', 'target'); - foreach ($config->toArray() as $name => $value) { - if (in_array($name, $notShown)) { - continue; - } - $this->assertEquals( - $value, - $form->getValue('backend_testldap_' . $name), - 'Asserting the ' . $name . ' parameter to be correctly populated for a ldap authentication form' - ); - } - } - - /** - * Test the database provider form population from config - */ - public function testDbProvider() - { - $this->requireFormLibraries(); - $form = $this->createForm('Icinga\Form\Config\Authentication\DbBackendForm'); - $config = new Zend_Config( - array( - 'backend' => 'db', - 'target' => 'user', - 'resource' => 'db_resource' - ) - ); - $form->setResources( - array( - 'db_resource' => array( - 'type' => 'db' - ) - ) - ); - - $form->setBackendName('test-db'); - $form->setBackend($config); - $form->create(); - - // parameters to be hidden - $notShown = array('backend', 'target'); - foreach ($config->toArray() as $name => $value) { - if (in_array($name, $notShown)) { - continue; - } - $this->assertEquals( - $value, - $form->getValue('backend_testdb_' . $name), - 'Asserting the ' . $name . ' parameter to be correctly populated for a db authentication form' - ); - } - } - - /** - * Test whether order modifications via 'priority' are considered - * - * @backupStaticAttributes enabled - */ - public function testModifyOrder() - { - Url::$overwrittenRequest = new RequestMock(); - $this->requireFormLibraries(); - $form = $this->createForm('Icinga\Form\Config\Authentication\ReorderForm'); - $form->setAuthenticationBackend('backend2'); - $form->setCurrentOrder(array('backend1', 'backend2', 'backend3', 'backend4')); - - $form->create(); - $this->assertSame( - 2, - count($form->getSubForms()), - 'Assert that a form for moving backend up and down exists' - ); - $this->assertTrue( - $form->upForm->getElement('form_backend_order') !== null, - 'Assert that a "move backend up" button exists' - ); - $this->assertSame( - array('backend2', 'backend1', 'backend3', 'backend4'), - explode(',', $form->upForm->getElement('form_backend_order')->getValue()), - 'Assert the "move backend up" button containing the correct order' - ); - - $this->assertTrue( - $form->downForm->getElement('form_backend_order') !== null, - 'Assert that a "move backend down" button exists' - ); - $this->assertSame( - array('backend1', 'backend3', 'backend2', 'backend4'), - explode(',', $form->downForm->getElement('form_backend_order')->getValue()), - 'Assert the "move backend up" button containing the correct order' - ); - } - - /** - * Test whether the reorder form doesn't display senseless ordering (like moving the uppermost element up or - * the lowermose down) - * - * @backupStaticAttributes enabled - */ - public function testInvalidOrderingNotShown() - { - Url::$overwrittenRequest = new RequestMock(); - $this->requireFormLibraries(); - $form = $this->createForm('Icinga\Form\Config\Authentication\ReorderForm'); - $form->setAuthenticationBackend('backend1'); - $form->setCurrentOrder(array('backend1', 'backend2', 'backend3', 'backend4')); - - $form->create(); - $this->assertSame( - 2, - count($form->getSubForms()), - 'Assert that a form for moving backend up and down exists, even when moving up is not possible' - ); - $this->assertTrue( - $form->downForm->getElement('form_backend_order') !== null, - 'Assert that a "move backend down" button exists when moving up is not possible' - ); - $this->assertTrue( - $form->upForm->getElement('form_backend_order') === null, - 'Assert that a "move backend up" button does not exist when moving up is not possible' - ); - } -} diff --git a/test/php/application/forms/Config/GeneralFormTest.php b/test/php/application/forms/Config/GeneralFormTest.php deleted file mode 100644 index 16c969d94..000000000 --- a/test/php/application/forms/Config/GeneralFormTest.php +++ /dev/null @@ -1,232 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Test\Icinga\Form\Config; - -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -// @codingStandardsIgnoreEnd - -use Icinga\Test\BaseTestCase; -// @codingStandardsIgnoreStart -require_once 'Zend/Form.php'; -require_once 'Zend/Config.php'; -require_once 'Zend/Config/Ini.php'; -require_once 'Zend/View/Helper/Abstract.php'; -require_once BaseTestCase::$libDir . '/Web/Form.php'; -require_once BaseTestCase::$appDir . '/forms/Config/GeneralForm.php'; -require_once BaseTestCase::$appDir . '/views/helpers/DateFormat.php'; -require_once BaseTestCase::$libDir . '/Util/ConfigAwareFactory.php'; -require_once BaseTestCase::$libDir . '/Util/DateTimeFactory.php'; -require_once BaseTestCase::$libDir . '/Util/Translator.php'; -// @codingStandardsIgnoreEnd - -use \DateTimeZone; -use \DOMDocument; -use \Zend_Config; -use \Zend_View; -use \Zend_View_Helper_DateFormat; -use \Icinga\Util\DateTimeFactory; - -class GeneralFormTest extends BaseTestCase -{ - private function isHiddenElement($value, $htmlString) - { - $html = new DOMDocument(); - $html->loadHTML($htmlString); - $hidden = $html->getElementsByTagName('noscript'); - - foreach ($hidden as $node) { - foreach ($node->childNodes as $child) { - if ($child->hasAttributes() === false) { - continue; - } - if (strpos($child->attributes->getNamedItem('id')->value, $value . '-element') !== false) { - return true; - } - } - } - return false; - } - /** - * - */ - public function testCorrectFieldPopulation() - { - DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC'))); - $this->requireFormLibraries(); - $form = $this->createForm('Icinga\Form\Config\GeneralForm'); - $form->setDateFormatter(new Zend_View_Helper_DateFormat($this->getRequest())); - $form->setConfiguration( - new Zend_Config( - array( - 'global' => array( - 'environment' => 'development', - 'timezone' => 'Europe/Berlin', - 'indexModule' => 'monitoring', - 'indexController' => 'dashboard', - 'moduleFolder' => '/my/module/path', - 'dateFormat' => 'd-m/Y', - 'timeFormat' => 'A:i' - ), - 'preferences' => array( - 'type' => 'ini', - 'configPath' => './my/path' - ) - ) - ) - ); - $form->setResources( - array( - 'db' => array( - 'type' => 'db' - ) - ) - ); - $form->setConfigDir('/tmp'); - - $form->create(); - $this->assertEquals( - 1, - $form->getValue('environment'), - 'Asserting the checkbox for devlopment being set to true' - ); - $this->assertEquals( - 'Europe/Berlin', - $form->getValue('timezone'), - 'Asserting the correct timezone to be displayed' - ); - $this->assertEquals( - '/my/module/path', - $form->getValue('module_folder'), - 'Asserting the correct module folder to be set' - ); - $this->assertEquals( - 'd-m/Y', - $form->getValue('date_format'), - 'Asserting the correct data format to be set' - ); - $this->assertEquals( - 'A:i', - $form->getValue('time_format'), - 'Asserting the correct time to be set' - ); - $this->assertEquals( - 'ini', - $form->getValue('preferences_type'), - 'Asserting the correct preference type to be set' - ); - $this->assertEquals( - './my/path', - $form->getValue('preferences_ini_path'), - 'Asserting the correct ini path to be set' - ); - $this->assertEquals( - '', - $form->getValue('preferences_db_resource'), - 'Asserting the database resource not to be set' - ); - } - - public function testCorrectConditionalIniFieldRendering() - { - DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC'))); - $this->requireFormLibraries(); - $form = $this->createForm('Icinga\Form\Config\GeneralForm'); - $form->setDateFormatter(new Zend_View_Helper_DateFormat($this->getRequest())); - $form->setConfiguration( - new Zend_Config( - array( - 'preferences' => array( - 'type' => 'ini', - 'configPath' => './my/path' - ) - ) - ) - ); - $form->setConfigDir('/tmp'); - $form->setResources( - array( - 'db' => array( - 'type' => 'db' - ) - ) - ); - $form->create(); - - $view = new Zend_View(); - - $this->assertFalse( - $this->isHiddenElement('preferences_ini_path', $form->render($view)), - "Asserting the ini path field to be displayed when an ini preference is set" - ); - $this->assertTrue( - $this->isHiddenElement('preferences_db_resource', $form->render($view)), - "Asserting the db resource to be hidden when an ini preference is set" - ); - } - - public function testCorrectConditionalDbFieldRendering() - { - DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC'))); - $this->requireFormLibraries(); - $form = $this->createForm('Icinga\Form\Config\GeneralForm'); - $form->setDateFormatter(new Zend_View_Helper_DateFormat($this->getRequest())); - $form->setConfiguration( - new Zend_Config( - array( - 'preferences' => array( - 'type' => 'db', - 'configPath' => './my/path', - 'resource' => 'my_resource' - ) - ) - ) - ); - $form->setConfigDir('/tmp'); - $form->setResources( - array( - 'db' => array( - 'type' => 'db' - ) - ) - ); - $form->create(); - $view = new Zend_View(); - - $this->assertTrue( - $this->isHiddenElement('preferences_ini_path', $form->render($view)), - "Asserting the ini path field to be hidden when db preference is set" - ); - $this->assertFalse( - $this->isHiddenElement('preferences_ini_resource', $form->render($view)), - "Asserting the db resource to be displayed when db preference is set" - ); - } -} diff --git a/test/php/application/forms/Config/LoggingFormTest.php b/test/php/application/forms/Config/LoggingFormTest.php deleted file mode 100644 index fdcfe5b25..000000000 --- a/test/php/application/forms/Config/LoggingFormTest.php +++ /dev/null @@ -1,179 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Test\Icinga\Form\Config; - -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -// @codingStandardsIgnoreEnd - -use Icinga\Test\BaseTestCase; -// @codingStandardsIgnoreStart -require_once 'Zend/Form.php'; -require_once 'Zend/Config.php'; -require_once 'Zend/Config/Ini.php'; -require_once BaseTestCase::$libDir . '/Web/Form.php'; -require_once BaseTestCase::$appDir . '/forms/Config/GeneralForm.php'; -require_once BaseTestCase::$appDir . '/forms/Config/LoggingForm.php'; -// @codingStandardsIgnoreEnd - -use \Zend_Config; - -/** - * Test for the authentication provider form - * - */ -class LoggingFormTest extends BaseTestCase -{ - /** - * Test the logging form to be correctly populated from configuration - * - */ - public function testLoggingFormPopulation() - { - $this->requireFormLibraries(); - $form = $this->createForm('Icinga\Form\Config\LoggingForm'); - $config = new Zend_Config( - array( - 'logging' => array( - 'enable' => 1, - 'target' => '/some/path', - 'verbose' => 0, - 'type' => 'stream', - 'debug' => array( - 'enable' => 1, - 'target' => '/some/debug/path', - 'type' => 'stream' - ) - ) - ) - ); - $form->setConfiguration($config); - $form->setBaseDir('basedir'); - $form->create(); - - $this->assertEquals( - '0', - $form->getValue('logging_app_verbose'), - 'Asserting the logging verbose tick not to be set' - ); - $this->assertEquals( - '/some/path', - $form->getValue('logging_app_target'), - 'Asserting the logging path to be set' - ); - $this->assertEquals( - 1, - $form->getValue('logging_debug_enable'), - 'Asserting the debug log enable tick to be set' - ); - $this->assertEquals( - '/some/debug/path', - $form->getValue('logging_debug_target'), - 'Asserting the debug log path to be set' - ); - } - - /** - * Test the logging form to create correct modified configurations when submit - * - */ - public function testCorrectConfigCreation() - { - $this->requireFormLibraries(); - $form = $this->createForm( - 'Icinga\Form\Config\LoggingForm', - array( - 'logging_enable' => 1, - 'logging_app_target' => 'some/new/target', - 'logging_app_verbose' => 1, - 'logging_debug_enable' => 0, - 'logging_debug_target' => 'a/new/target' - ) - ); - $baseConfig = new Zend_Config( - array( - 'global' => array( - 'option' => 'value' - ), - 'logging' => array( - 'enable' => 1, - 'target' => '/some/path', - 'verbose' => 0, - 'type' => 'stream', - 'debug' => array( - 'enable' => 1, - 'target' => '/some/debug/path', - 'type' => 'stream' - ) - ) - ) - ); - $form->setConfiguration($baseConfig); - $form->setBaseDir('basedir'); - $form->create(); - $form->populate($this->getRequest()->getParams()); - $config = $form->getConfig(); - $this->assertEquals( - 'value', - $config->global->option, - 'Asserting global options not to be altered when changing log' - ); - $this->assertEquals( - 1, - $config->logging->enable, - 'Asserting logging to stay enabled when enable is ticked' - ); - $this->assertEquals( - 'some/new/target', - $config->logging->target, - 'Asserting target modifications to be applied' - ); - $this->assertEquals( - 1, - $config->logging->verbose, - 'Asserting ticking the verbose checkbox to be applied' - ); - $this->assertEquals( - 'stream', - $config->logging->type, - 'Asserting the type to stay "stream"' - ); - $this->assertEquals( - 0, - $config->logging->debug->enable, - 'Asserting debug log to be disabled' - ); - $this->assertEquals( - 'a/new/target', - $config->logging->debug->target, - 'Asserting the debug log target modifications to be applied' - ); - } -} diff --git a/test/php/application/forms/Config/Resource/ResourceFormTest.php b/test/php/application/forms/Config/Resource/ResourceFormTest.php new file mode 100644 index 000000000..6dba6ce54 --- /dev/null +++ b/test/php/application/forms/Config/Resource/ResourceFormTest.php @@ -0,0 +1,268 @@ +is_valid; + } +} + +class ResourceFormTest extends BaseTestCase +{ + public function tearDown() + { + parent::tearDown(); + Mockery::close(); // Necessary because some tests run in a separate process + } + + public function testIsForceCreationCheckboxBeingAdded() + { + $form = new TestResourceForm(); + $form->is_valid = false; + + $this->assertFalse($form->isValid(array())); + $this->assertNotNull( + $form->getElement('resource_force_creation'), + 'Checkbox to force the creation of a resource is not being added though the resource is invalid' + ); + } + + public function testIsForceCreationCheckboxNotBeingAdded() + { + $form = new TestResourceForm(); + $form->is_valid = true; + + $this->assertTrue($form->isValid(array())); + $this->assertNull( + $form->getElement('resource_force_creation'), + 'Checkbox to force the creation of a resource is being added though the resource is valid' + ); + } + + public function testIsTheFormValidIfForceCreationTrue() + { + $form = new TestResourceForm(); + $form->is_valid = false; + + $this->assertTrue( + $form->isValid(array('resource_force_creation' => 1)), + 'ResourceForm with invalid resource is not valid though force creation is set' + ); + } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testValidDbResourceIsValid() + { + $this->setUpResourceFactoryMock( + Mockery::mock()->shouldReceive('getConnection')->atMost()->twice()->andReturn(Mockery::self())->getMock() + ); + $form = $this->buildResourceForm(new Zend_Config(array('type' => 'db'))); + + $this->assertTrue( + $form->isValidResource(), + 'ResourceForm claims that a valid db resource is not valid' + ); + } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testInvalidDbResourceIsNotValid() + { + $this->setUpResourceFactoryMock( + Mockery::mock()->shouldReceive('getConnection')->once()->andThrow('\Exception')->getMock() + ); + $form = $this->buildResourceForm(new Zend_Config(array('type' => 'db'))); + + $this->assertFalse( + $form->isValidResource(), + 'ResourceForm claims that an invalid db resource is valid' + ); + } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testValidLdapResourceIsValid() + { + $this->setUpResourceFactoryMock( + Mockery::mock()->shouldReceive('connect')->getMock() + ); + $form = $this->buildResourceForm(new Zend_Config(array('type' => 'ldap'))); + + $this->assertTrue( + $form->isValidResource(), + 'ResourceForm claims that a valid ldap resource is not valid' + ); + } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testInvalidLdapResourceIsNotValid() + { + $this->setUpResourceFactoryMock( + Mockery::mock()->shouldReceive('connect')->once()->andThrow('\Exception')->getMock() + ); + $form = $this->buildResourceForm(new Zend_Config(array('type' => 'ldap'))); + + $this->assertFalse( + $form->isValidResource(), + 'ResourceForm claims that an invalid ldap resource is valid' + ); + } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testValidLivestatusResourceIsValid() + { + $this->setUpResourceFactoryMock( + Mockery::mock()->shouldReceive('connect')->andReturn(Mockery::self()) + ->shouldReceive('disconnect')->getMock() + ); + $form = $this->buildResourceForm(new Zend_Config(array('type' => 'livestatus'))); + + $this->assertTrue( + $form->isValidResource(), + 'ResourceForm claims that a valid livestatus resource is not valid' + ); + } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testInvalidLivestatusResourceIsNotValid() + { + $this->setUpResourceFactoryMock( + Mockery::mock()->shouldReceive('connect')->once()->andThrow('\Exception')->getMock() + ); + $form = $this->buildResourceForm(new Zend_Config(array('type' => 'livestatus'))); + + $this->assertFalse( + $form->isValidResource(), + 'ResourceForm claims that an invalid livestatus resource is valid' + ); + } + + public function testValidFileResourceIsValid() + { + $form = $this->buildResourceForm( + new Zend_Config( + array( + 'type' => 'file', + 'filename' => BaseTestCase::$testDir . '/res/status/icinga.status.dat' + ) + ) + ); + + $this->assertTrue( + $form->isValidResource(), + 'ResourceForm claims that a valid file resource is not valid' + ); + } + + public function testInvalidFileResourceIsNotValid() + { + $form = $this->buildResourceForm( + new Zend_Config( + array( + 'type' => 'file', + 'filename' => 'not_existing' + ) + ) + ); + + $this->assertFalse( + $form->isValidResource(), + 'ResourceForm claims that an invalid file resource is valid' + ); + } + + public function testValidStatusdatResourceIsValid() + { + $form = $this->buildResourceForm( + new Zend_Config( + array( + 'type' => 'statusdat', + 'status_file' => BaseTestCase::$testDir . '/res/status/icinga.status.dat', + 'object_file' => BaseTestCase::$testDir . '/res/status/icinga.objects.cache', + ) + ) + ); + + $this->assertTrue( + $form->isValidResource(), + 'ResourceForm claims that a valid statusdat resource is not valid' + ); + } + + public function testInvalidStatusdatResourceIsNotValid() + { + $form = $this->buildResourceForm( + new Zend_Config( + array( + 'type' => 'statusdat', + 'status_file' => 'not_existing', + 'object_file' => 'not_existing' + ) + ) + ); + + $this->assertFalse( + $form->isValidResource(), + 'ResourceForm claims that an invalid statusdat resource is valid' + ); + } + + protected function buildResourceForm($resourceConfig) + { + $form = new ResourceForm(); + $form->setRequest($this->getRequestMock()); + $form->setResource($resourceConfig); + $form->create(); + + return $form; + } + + protected function getRequestMock() + { + return Mockery::mock('\Zend_Controller_Request_Abstract') + ->shouldReceive('getParam') + ->with(Mockery::type('string'), Mockery::type('string')) + ->andReturnUsing(function ($name, $default) { return $default; }) + ->getMock(); + } + + protected function setUpResourceFactoryMock($resourceMock) + { + Mockery::mock('alias:Icinga\Data\ResourceFactory') + ->shouldReceive('createResource') + ->with(Mockery::type('\Zend_Config')) + ->andReturn($resourceMock); + } +} diff --git a/test/php/application/forms/Preference/GeneralFormTest.php b/test/php/application/forms/Preference/GeneralFormTest.php deleted file mode 100644 index e4a6a0ea7..000000000 --- a/test/php/application/forms/Preference/GeneralFormTest.php +++ /dev/null @@ -1,103 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Test\Icinga\Form\Preference; - -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -// @codingStandardsIgnoreEnd - -use Icinga\Test\BaseTestCase; - -// @codingStandardsIgnoreStart -require_once 'Zend/Form/Element/Select.php'; -require_once 'Zend/View/Helper/Abstract.php'; -require_once BaseTestCase::$libDir . '/User/Preferences.php'; -require_once BaseTestCase::$libDir . '/Web/Form.php'; -require_once BaseTestCase::$appDir . '/forms/Preference/GeneralForm.php'; -require_once BaseTestCase::$appDir . '/views/helpers/DateFormat.php'; -require_once BaseTestCase::$libDir . '/Util/ConfigAwareFactory.php'; -require_once BaseTestCase::$libDir . '/Util/DateTimeFactory.php'; -// @codingStandardsIgnoreEnd - -use \DateTimeZone; -use \Icinga\User\Preferences; -use \Zend_View_Helper_DateFormat; -use \Icinga\Util\DateTimeFactory; - -/** - * Test for general form, mainly testing enable/disable behaviour - */ -class GeneralFormTest extends BaseTestCase -{ - /** - * Test whether fields using the default values have input disabled - * - */ - public function testDisableFormIfUsingDefault() - { - DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC'))); - $this->requireFormLibraries(); - $form = $this->createForm('Icinga\Form\Preference\GeneralForm'); - $form->setDateFormatter(new Zend_View_Helper_DateFormat($this->getRequest())); - $form->setRequest($this->getRequest()); - $form->create(); - $this->assertSame( - 1, - $form->getElement('timezone')->getAttrib('disabled'), - 'Asserting form elements to be disabled when not set in a preference' - ); - } - - /** - * Test whether fields with preferences are enabled - * - */ - public function testEnableFormIfUsingPreference() - { - DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC'))); - $this->requireFormLibraries(); - $form = $this->createForm('Icinga\Form\Preference\GeneralForm'); - $form->setDateFormatter(new Zend_View_Helper_DateFormat($this->getRequest())); - $form->setRequest($this->getRequest()); - $form->setUserPreferences( - new Preferences( - array( - 'app.timezone' => 'Europe/Berlin' - ) - ) - ); - $form->create(); - $this->assertSame( - null, - $form->getElement('timezone')->getAttrib('disabled'), - 'Asserting form elements to be disabled when not set in a preference' - ); - } -} diff --git a/test/php/application/views/helpers/DateFormatTest.php b/test/php/application/views/helpers/DateFormatTest.php new file mode 100644 index 000000000..8de8442f6 --- /dev/null +++ b/test/php/application/views/helpers/DateFormatTest.php @@ -0,0 +1,165 @@ +oldConfigDir = Config::$configDir; + Config::$configDir = dirname(__FILE__) . '/DateFormatTest'; + } + + public function tearDown() + { + parent::tearDown(); + Config::$configDir = $this->oldConfigDir; + DateTimeFactory::setConfig(array('timezone' => date_default_timezone_get())); + } + + public function testFormatReturnsCorrectDateWithTimezoneApplied() + { + DateTimeFactory::setConfig(array('timezone' => 'Europe/Berlin')); + $helper = new Zend_View_Helper_DateFormat($this->getRequestMock()); + + $this->assertEquals( + '12:05', + $helper->format(1397729100, 'H:i'), + 'Zend_View_Helper_DateFormat::format does not return a valid' . + ' formatted time or does not apply the user\'s timezone' + ); + } + + public function testFormatDateReturnsCorrectDate() + { + $helper = new Zend_View_Helper_DateFormat($this->getRequestMock('d_m_y')); + + $this->assertEquals( + '17_04_14', + $helper->formatDate(1397729100), + 'Zend_View_Helper_DateFormat::formatDate does not return a valid formatted date' + ); + } + + public function testFormatTimeReturnsCorrectTime() + { + $helper = new Zend_View_Helper_DateFormat($this->getRequestMock(null, 'H:i')); + + $this->assertEquals( + '10:05', + $helper->formatTime(1397729100), + 'Zend_View_Helper_DateFormat::formatTime does not return a valid formatted time' + ); + } + + public function testFormatDatetimeReturnsCorrectDatetime() + { + $helper = new Zend_View_Helper_DateFormat($this->getRequestMock('d m Y', 'H:i a')); + + $this->assertEquals( + '17 04 2014 10:05 am', + $helper->formatDateTime(1397729100), + 'Zend_View_Helper_DateFormat::formatDateTime does not return a valid formatted date and time' + ); + } + + public function testGetDateFormatReturnsCorrectFormat() + { + $helper = new Zend_View_Helper_DateFormat($this->getRequestMock('d/m-y')); + + $this->assertEquals( + 'd/m-y', + $helper->getDateFormat(), + 'Zend_View_Helper_DateFormat::getDateFormat does not return the user\'s date format' + ); + } + + public function testGetTimeFormatReturnsCorrectFormat() + { + $helper = new Zend_View_Helper_DateFormat($this->getRequestMock(null, 'H.i A')); + + $this->assertEquals( + 'H.i A', + $helper->getTimeFormat(), + 'Zend_View_Helper_DateFormat::getTimeFormat does not return the user\'s time format' + ); + } + + public function testGetDatetimeFormatReturnsCorrectFormat() + { + $helper = new Zend_View_Helper_DateFormat($this->getRequestMock('d/m-y', 'H.i A')); + + $this->assertEquals( + 'd/m-y H.i A', + $helper->getDateTimeFormat(), + 'Zend_View_Helper_DateFormat::getDateTimeFormat does not return the user\'s date and time format' + ); + } + + public function testGetDateFormatReturnsFormatFromConfig() + { + $helper = new Zend_View_Helper_DateFormat($this->getRequestMock()); + + $this->assertEquals( + 'd-m-y', + $helper->getDateFormat(), + 'Zend_View_Helper_DateFormat::getDateFormat does not return the format set' . + ' in the global configuration if the user\'s preferences do not provide one' + ); + } + + public function testGetTimeFormatReturnsFormatFromConfig() + { + $helper = new Zend_View_Helper_DateFormat($this->getRequestMock()); + + $this->assertEquals( + 'G:i a', + $helper->getTimeFormat(), + 'Zend_View_Helper_DateFormat::getTimeFormat does not return the format set' . + ' in the global configuration if the user\'s preferences do not provide one' + ); + } + + public function testGetDatetimeFormatReturnsFormatFromConfig() + { + $helper = new Zend_View_Helper_DateFormat($this->getRequestMock()); + + $this->assertEquals( + 'd-m-y G:i a', + $helper->getDateTimeFormat(), + 'Zend_View_Helper_DateFormat::getDateTimeFormat does not return the format set' . + ' in the global configuration if the user\'s preferences do not provide one' + ); + } + + protected function getRequestMock($dateFormat = null, $timeFormat = null) + { + $mock = Mockery::mock('\Zend_Controller_Request_Abstract'); + $mock->shouldReceive('getUser->getPreferences->get') + ->with(Mockery::type('string'), Mockery::type('string')) + ->andReturnUsing( + function ($ident, $default) use ($dateFormat, $timeFormat) { + if ($dateFormat !== null && $ident === 'app.dateFormat') { + return $dateFormat; + } elseif ($timeFormat !== null && $ident === 'app.timeFormat') { + return $timeFormat; + } else { + return $default; + } + } + ); + + return $mock; + } +} diff --git a/test/php/application/views/helpers/DateFormatTest/config.ini b/test/php/application/views/helpers/DateFormatTest/config.ini new file mode 100644 index 000000000..f095d27ca --- /dev/null +++ b/test/php/application/views/helpers/DateFormatTest/config.ini @@ -0,0 +1,3 @@ +[global] +dateFormat = "d-m-y" +timeFormat = "G:i a" \ No newline at end of file diff --git a/test/php/bootstrap.php b/test/php/bootstrap.php new file mode 100644 index 000000000..4fc192e7d --- /dev/null +++ b/test/php/bootstrap.php @@ -0,0 +1,61 @@ +register(); + +require_once($libraryPath . '/Icinga/Application/Loader.php'); + +$loader = new Icinga\Application\Loader(); +$loader->registerNamespace('Tests', $testLibraryPath); +$loader->registerNamespace('Icinga', $libraryPath . '/Icinga'); +$loader->registerNamespace('Icinga\\Form', $applicationPath . '/forms'); + +$modules = scandir($modulePath); +foreach ($modules as $module) { + if ($module === '.' || $module === '..') { + continue; + } + + $moduleNamespace = 'Icinga\\Module\\' . ucfirst($module); + $moduleLibraryPath = $modulePath . '/' . $module . '/library/' . ucfirst($module); + + if (is_dir($moduleLibraryPath)) { + $loader->registerNamespace($moduleNamespace, $moduleLibraryPath); + } + + $moduleTestPath = $modulePath . '/' . $module . '/test/php'; + if (is_dir($moduleTestPath)) { + $loader->registerNamespace('Tests\\' . $moduleNamespace, $moduleTestPath); + } + + $moduleFormPath = $modulePath . '/' . $module . '/application/forms'; + if (is_dir($moduleFormPath)) { + $loader->registerNamespace($moduleNamespace . '\\Form', $moduleFormPath); + } +} + +$loader->register(); + +require_once 'Zend/Loader/Autoloader.php'; +\Zend_Loader_Autoloader::getInstance(); + +Icinga\Application\Config::$configDir = $configPath; diff --git a/test/php/library/Icinga/Application/ConfigTest.php b/test/php/library/Icinga/Application/ConfigTest.php index 98a83fdaa..bc39afecd 100644 --- a/test/php/library/Icinga/Application/ConfigTest.php +++ b/test/php/library/Icinga/Application/ConfigTest.php @@ -1,56 +1,36 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} namespace Tests\Icinga\Application; -require_once 'Zend/Config/Ini.php'; -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Application/Config.php'); - +use Icinga\Test\BaseTestCase; use \Icinga\Application\Config as IcingaConfig; -class ConfigTest extends \PHPUnit_Framework_TestCase +class ConfigTest extends BaseTestCase { /** * Set up config dir - * - * Utilizes singleton IcingaConfig - * - * @backupStaticAttributes enabled */ public function setUp() { - IcingaConfig::$configDir = dirname(__FILE__) . '/Config/files'; + parent::setUp(); + $this->configDir = IcingaConfig::$configDir; + IcingaConfig::$configDir = dirname(__FILE__) . '/ConfigTest/files'; + } + + /** + * Reset config dir + */ + public function tearDown() + { + parent::tearDown(); + IcingaConfig::$configDir = $this->configDir; } public function testAppConfig() { - $config = IcingaConfig::app(); + $config = IcingaConfig::app('config', true); $this->assertEquals(1, $config->logging->enable, 'Unexpected value retrieved from config file'); // Test non-existent property where null is the default value $this->assertEquals( @@ -90,28 +70,28 @@ class ConfigTest extends \PHPUnit_Framework_TestCase $config->backend->db->toArray() ); // Test singleton - $this->assertEquals($config, IcingaConfig::app()); + $this->assertEquals($config, IcingaConfig::app('config')); $this->assertEquals(array('logging', 'backend'), $config->keys()); $this->assertEquals(array('enable'), $config->keys('logging')); } public function testAppExtraConfig() { - $extraConfig = IcingaConfig::app('extra'); + $extraConfig = IcingaConfig::app('extra', true); $this->assertEquals(1, $extraConfig->meta->version); $this->assertEquals($extraConfig, IcingaConfig::app('extra')); } public function testModuleConfig() { - $moduleConfig = IcingaConfig::module('amodule'); + $moduleConfig = IcingaConfig::module('amodule', 'config', true); $this->assertEquals(1, $moduleConfig->menu->get('breadcrumb')); $this->assertEquals($moduleConfig, IcingaConfig::module('amodule')); } public function testModuleExtraConfig() { - $moduleExtraConfig = IcingaConfig::module('amodule', 'extra'); + $moduleExtraConfig = IcingaConfig::module('amodule', 'extra', true); $this->assertEquals( 'inetOrgPerson', $moduleExtraConfig->ldap->user->get('ldap_object_class') diff --git a/test/php/library/Icinga/Application/Config/files/config.ini b/test/php/library/Icinga/Application/ConfigTest/files/config.ini similarity index 100% rename from test/php/library/Icinga/Application/Config/files/config.ini rename to test/php/library/Icinga/Application/ConfigTest/files/config.ini diff --git a/test/php/library/Icinga/Application/Config/files/extra.ini b/test/php/library/Icinga/Application/ConfigTest/files/extra.ini similarity index 100% rename from test/php/library/Icinga/Application/Config/files/extra.ini rename to test/php/library/Icinga/Application/ConfigTest/files/extra.ini diff --git a/test/php/library/Icinga/Application/Config/files/modules/amodule/config.ini b/test/php/library/Icinga/Application/ConfigTest/files/modules/amodule/config.ini similarity index 100% rename from test/php/library/Icinga/Application/Config/files/modules/amodule/config.ini rename to test/php/library/Icinga/Application/ConfigTest/files/modules/amodule/config.ini diff --git a/test/php/library/Icinga/Application/Config/files/modules/amodule/extra.ini b/test/php/library/Icinga/Application/ConfigTest/files/modules/amodule/extra.ini similarity index 100% rename from test/php/library/Icinga/Application/Config/files/modules/amodule/extra.ini rename to test/php/library/Icinga/Application/ConfigTest/files/modules/amodule/extra.ini diff --git a/test/php/library/Icinga/Application/LoaderTest.php b/test/php/library/Icinga/Application/LoaderTest.php index 4c3d101ad..e2b1c8161 100644 --- a/test/php/library/Icinga/Application/LoaderTest.php +++ b/test/php/library/Icinga/Application/LoaderTest.php @@ -1,19 +1,13 @@ baseDir = tempnam($tempDir, 'icinga2-web'); system('mkdir -p '. $this->baseDir. dirname(self::$classFile)); file_put_contents($this->baseDir. self::$classFile, self::$classContent); } - protected function tearDown() + public function tearDown() { + parent::tearDown(); system('rm -rf '. $this->baseDir); } diff --git a/test/php/library/Icinga/Application/LoggerTest.php b/test/php/library/Icinga/Application/LoggerTest.php deleted file mode 100644 index 32e8d3980..000000000 --- a/test/php/library/Icinga/Application/LoggerTest.php +++ /dev/null @@ -1,91 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -// @codingStandardsIgnoreEnd - -use Icinga\Test\BaseTestCase; - -// @codingStandardsIgnoreStart -require_once BaseTestCase::$libDir . '/Logger/Logger.php'; -require_once BaseTestCase::$libDir . '/Logger/LogWriter.php'; -require_once BaseTestCase::$libDir . '/Logger/Writer/StreamWriter.php'; -// @codingStandardsIgnoreEnd - -use \Zend_Config; -use Icinga\Logger\Logger; - -class LoggerTest extends BaseTestCase -{ - /** - * @backupStaticAttributes enabled - */ - public function testLogfileCreation() - { - $target = tempnam(sys_get_temp_dir(), 'log'); - unlink($target); - Logger::create( - new Zend_Config( - array( - 'enable' => true, - 'level' => Logger::$ERROR, - 'type' => 'stream', - 'target' => $target - ) - ) - ); - $this->assertFileExists($target, 'Logger did not create the log file'); - unlink($target); - } - - /** - * @backupStaticAttributes enabled - * @depends testLogfileCreation - */ - public function testLoggingErrorMessages() - { - $target = tempnam(sys_get_temp_dir(), 'log'); - unlink($target); - Logger::create( - new Zend_Config( - array( - 'enable' => true, - 'level' => Logger::$ERROR, - 'type' => 'stream', - 'target' => $target - ) - ) - ); - Logger::error('This is a test error'); - $log = file_get_contents($target); - unlink($target); - $this->assertContains('This is a test error', $log, 'Log does not contain the error "This is a test error"'); - } -} diff --git a/test/php/library/Icinga/Application/Modules/Manager.php b/test/php/library/Icinga/Application/Modules/Manager.php deleted file mode 100644 index 116b1d1b5..000000000 --- a/test/php/library/Icinga/Application/Modules/Manager.php +++ /dev/null @@ -1,110 +0,0 @@ -name = $name; - $this->dir = $dir; - } - - public function register() - { - } -} - -class ManagerTest extends \PHPUnit_Framework_TestCase -{ - const MODULE_TARGET = "/tmp"; - - protected function setUp() - { - $moduleDir = self::MODULE_TARGET; - if (!is_writable($moduleDir)) { - $this->markTestSkipped("Temporary folder not writable for this user"); - return; - } - if (is_dir($moduleDir."/enabledModules")) { - exec("rm -r $moduleDir/enabledModules"); - } - - mkdir($moduleDir."/enabledModules"); - } - - public function testDetectEnabledModules() - { - $manager = new ModuleManager(null, "/tmp/enabledModules", array("none")); - $this->assertEmpty($manager->listEnabledModules()); - - symlink(getcwd()."/res/testModules/module1", "/tmp/enabledModules/module1"); - $manager = new ModuleManager(null, "/tmp/enabledModules", array("none")); - $this->assertEquals(array("module1"), $manager->listEnabledModules()); - symlink(getcwd()."/res/testModules/module2", "/tmp/enabledModules/module2"); - symlink(getcwd()."/res/???", "/tmp/enabledModules/module3"); - $manager = new ModuleManager(null, "/tmp/enabledModules", array("none")); - $this->assertEquals(array("module1", "module2"), $manager->listEnabledModules()); - } - - public function testLoadModule() - { - $manager = new ModuleManager(null, "/tmp/enabledModules", array("./res/testModules")); - $this->assertEmpty($manager->getLoadedModules()); - $manager->loadModule("module1", "Tests\Icinga\Application\Module\Manager\ModuleMock"); - $elems = $manager->getLoadedModules(); - $this->assertNotEmpty($elems); - $this->assertTrue(isset($elems["module1"])); - // assert the changes not to be permanent: - $manager = new ModuleManager(null, "/tmp/enabledModules", array("./res/testModules")); - $this->assertEmpty($manager->getLoadedModules()); - } - - public function testEnableModule() - { - $manager = new ModuleManager(null, "/tmp/enabledModules", array(getcwd()."/res/testModules")); - $this->assertEmpty($manager->listEnabledModules()); - $manager->enableModule("module1"); - $elems = $manager->listEnabledModules(); - $this->assertNotEmpty($elems); - $this->assertEquals($elems[0], "module1"); - $this->assertTrue(is_link("/tmp/enabledModules/module1")); - // assert the changes to be permanent: - $manager = new ModuleManager(null, "/tmp/enabledModules", array("./res/testModules")); - $this->assertNotEmpty($manager->listEnabledModules()); - } - - public function testDisableModule() - { - clearstatcache(true); - symlink(getcwd()."/res/testModules/module1", "/tmp/enabledModules/module1"); - $manager = new ModuleManager(null, "/tmp/enabledModules", array(getcwd()."/res/testModules")); - $elems = $manager->listEnabledModules(); - $this->assertNotEmpty($elems); - $this->assertEquals($elems[0], "module1"); - $manager->disableModule("module1"); - $this->assertFalse(file_exists("/tmp/enabledModules/module1")); - $this->assertEmpty($manager->listEnabledModules()); - // assert the changes to be permanent: - $manager = new ModuleManager(null, "/tmp/enabledModules", array("./res/testModules")); - $this->assertEmpty($manager->listEnabledModules()); - } - - protected function tearDown() - { - $moduleDir = self::MODULE_TARGET; - exec("rm -r $moduleDir/enabledModules"); - - } -} diff --git a/test/php/library/Icinga/Application/ZendDbMock.php b/test/php/library/Icinga/Application/ZendDbMock.php deleted file mode 100644 index 2579b83e5..000000000 --- a/test/php/library/Icinga/Application/ZendDbMock.php +++ /dev/null @@ -1,88 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Tests\Icinga\Application; - -/** - * Partially emulate the functionality of Zend_Db - */ -class ZendDbMock -{ - - /** - * The config that was used in the last call of the factory function - * - * @var mixed - */ - private static $config; - - /** - * Name of the adapter class that was used in the last call of the factory function - * - * @var mixed - */ - private static $adapter; - - /** - * Mock the factory-method of Zend_Db and save the given parameters - * - * @param $adapter String name of base adapter class, or Zend_Config object - * @param $config mixed OPTIONAL; an array or Zend_Config object with adapter - * parameters - * - * @return stdClass Empty object - */ - public static function factory($adapter, $config) - { - self::$config = $config; - self::$adapter = $adapter; - return new \stdClass(); - } - - /** - * Get the name of the adapter class that was used in the last call - * of the factory function - * - * @return String - */ - public static function getAdapter() - { - return self::$adapter; - } - - /** - * Get the config that was used in the last call of the factory function - * - * @return mixed - */ - public static function getConfig() - { - return self::$config; - } -} diff --git a/test/php/library/Icinga/Authentication/BackendMock.php b/test/php/library/Icinga/Authentication/BackendMock.php deleted file mode 100644 index 49c4d45ed..000000000 --- a/test/php/library/Icinga/Authentication/BackendMock.php +++ /dev/null @@ -1,129 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Tests\Icinga\Authentication; - -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -// @codingStandardsIgnoreEnd - -use Icinga\Test\BaseTestCase; - -// @codingStandardsIgnoreStart -require_once 'Zend/Config.php'; -require_once BaseTestCase::$libDir . '/Authentication/Credential.php'; -require_once BaseTestCase::$libDir . '/Authentication/UserBackend.php'; -require_once BaseTestCase::$libDir . '/User.php'; -// @codingStandardsIgnoreEnd - -use \Zend_Config; -use \Icinga\Authentication\Credential; -use \Icinga\Authentication\UserBackend as UserBackend; -use \Icinga\User; - -/** -* Simple backend mock that takes an config object -* with the property "credentials", which is an array -* of Credential this backend authenticates -**/ -class BackendMock implements UserBackend -{ - public $allowedCredentials = array(); - public $name; - - public function __construct(Zend_Config $config = null) - { - if ($config === null) { - return; - } - - if (isset ($config->credentials)) { - $this->allowedCredentials = $config->credentials; - } - - if ($config->name) { - $this->name = $config->name; - } else { - $this->name = 'TestBackendMock-' . uniqid(); - } - } - - public function hasUsername(Credential $userCredentials) - { - foreach ($this->allowedCredentials as $credential) { - if ($credential->getUsername() == $userCredentials->getUsername()) { - return true; - } - } - return false; - } - - /** - * Name of the backend - * - * @return string - */ - public function getName() - { - return $this->name; - } - - public static function getDummyUser() - { - return new User( - 'Username', - 'Firstname', - 'Lastname', - 'user@test.local' - ); - } - - public function getUserCount() { - return count($this->allowedCredentials); - } - - public function authenticate(Credential $credentials) - { - if (!in_array($credentials, $this->allowedCredentials)) { - return; - } - - return self::getDummyUser(); - } - - public function setCredentials(array $credentials) - { - $this->allowedCredentials = $credentials; - } - - public function connect() - { - - } -} diff --git a/test/php/library/Icinga/Authentication/DbUserBackendTest.php b/test/php/library/Icinga/Authentication/DbUserBackendTest.php deleted file mode 100644 index 591cc129a..000000000 --- a/test/php/library/Icinga/Authentication/DbUserBackendTest.php +++ /dev/null @@ -1,316 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Tests\Icinga\Authentication; - -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -// @codingStandardsIgnoreEnd - -use \Icinga\Test\BaseTestCase; - -// @codingStandardsIgnoreStart -require_once 'Zend/Config.php'; -require_once 'Zend/Config/Ini.php'; -require_once 'Zend/Db/Adapter/Abstract.php'; -require_once 'Zend/Db.php'; -require_once 'Zend/Log.php'; -require_once BaseTestCase::$libDir . '/Exception/ProgrammingError.php'; -require_once BaseTestCase::$libDir . '/Util/ConfigAwareFactory.php'; -require_once BaseTestCase::$libDir . '/Authentication/UserBackend.php'; -require_once BaseTestCase::$libDir . '/Protocol/Ldap/Exception.php'; -require_once BaseTestCase::$libDir . '/Application/Config.php'; -require_once BaseTestCase::$libDir . '/Authentication/Credential.php'; -require_once BaseTestCase::$libDir . '/Authentication/Backend/DbUserBackend.php'; -require_once BaseTestCase::$libDir . '/User.php'; -require_once BaseTestCase::$libDir . '/Application/Logger.php'; -// @codingStandardsIgnoreEnd - -use \PDO; -use \Zend_Db_Adapter_Pdo_Abstract; -use \Zend_Config; -use \Icinga\Authentication\Backend\DbUserBackend; -use \Icinga\Authentication\Credential; -use \Icinga\User; -use \Icinga\Application\Config; - -/** - * Test Class fpr DbUserBackend - */ -class DbUserBackendTest extends BaseTestCase -{ - const USER_NAME_COLUMN = 'username'; - - const SALT_COLUMN = 'salt'; - - const PASSWORD_COLUMN = 'password'; - - const ACTIVE_COLUMN = 'active'; - - /** - * The table that is used to store the authentication data - * - * @var string - */ - private $testTable = 'account'; - - /** - * Example users - * - * @var array - */ - private $userData = array( - array( - self::USER_NAME_COLUMN => 'user1', - self::PASSWORD_COLUMN => 'secret1', - self::SALT_COLUMN => '8a7487a539c5d1d6766639d04d1ed1e6', - self::ACTIVE_COLUMN => 1 - ), - array( - self::USER_NAME_COLUMN => 'user2', - self::PASSWORD_COLUMN => 'secret2', - self::SALT_COLUMN => '04b5521ddd761b5a5b633be83faa494d', - self::ACTIVE_COLUMN => 1 - ), - array( - self::USER_NAME_COLUMN => 'user3', - self::PASSWORD_COLUMN => 'secret3', - self::SALT_COLUMN => '08bb94ba3120338ae56db80ef551d324', - self::ACTIVE_COLUMN => 0 - ) - ); - - private function createDbBackendConfig($resource, $name = null) - { - if ($name === null) { - $name = 'TestDbUserBackend-' . uniqid(); - } - - $config = new Zend_Config( - array( - 'name' => $name, - 'resource' => $resource - ) - ); - - return $config; - } - - /** - * Test the authentication functions of the DbUserBackend using PostgreSQL as backend. - * - * @dataProvider pgsqlDb - */ - public function testCorrectUserLoginForPgsql($db) - { - $this->setupDbProvider($db); - $backend = new DbUserBackend($this->createDbBackendConfig($db)); - $backend->connect(); - $this->runBackendAuthentication($backend); - $this->runBackendUsername($backend); - } - - /** - * Test the authentication functions of the DbUserBackend using MySQL as backend. - * - * @dataProvider mysqlDb - */ - public function testCorrectUserLoginForMySQL($db) - { - $this->setupDbProvider($db); - $backend = new DbUserBackend($this->createDbBackendConfig($db)); - $backend->connect(); - $this->runBackendAuthentication($backend); - $this->runBackendUsername($backend); - } - - /** - * @param Zend_Db_Adapter_Pdo_Abstract $resource - */ - public function setupDbProvider($resource) - { - parent::setupDbProvider($resource); - - $type = $resource->getConnection()->getAttribute(PDO::ATTR_DRIVER_NAME); - - $dumpFile = BaseTestCase::$etcDir . '/schema/accounts.' . $type . '.sql'; - - $this->assertFileExists($dumpFile); - - $this->loadSql($resource, $dumpFile); - - for ($i = 0; $i < count($this->userData); $i++) { - $usr = $this->userData[$i]; - $data = array( - self::USER_NAME_COLUMN => $usr[self::USER_NAME_COLUMN], - self::PASSWORD_COLUMN => hash_hmac( - 'sha256', - $usr[self::PASSWORD_COLUMN], - $usr[self::SALT_COLUMN] - ), - self::ACTIVE_COLUMN => $usr[self::ACTIVE_COLUMN], - self::SALT_COLUMN => $usr[self::SALT_COLUMN] - ); - $resource->insert($this->testTable, $data); - } - } - - /** - * Run the hasUsername test against an instance of DbUserBackend - * - * @param DbUserBackend $backend The backend that will be tested. - */ - private function runBackendUsername($backend) - { - // Known user - $this->assertTrue( - $backend->hasUsername( - new Credential( - $this->userData[0][self::USER_NAME_COLUMN], - $this->userData[0][self::PASSWORD_COLUMN] - ) - ), - 'Assert that the user is known by the backend' - ); - - // Unknown user - $this->assertFalse( - $backend->hasUsername( - new Credential( - 'unknown user', - 'secret' - ) - ), - 'Assert that the user is not known by the backend' - ); - - // Inactive user - $this->assertFalse( - $backend->hasUsername( - new Credential( - $this->userData[2][self::USER_NAME_COLUMN], - $this->userData[2][self::PASSWORD_COLUMN] - ) - ), - 'Assert that the user is inactive and therefore not known by the backend' - ); - } - - /** - * Run the authentication test against an instance of DbUserBackend - * - * @param DbUserBackend $backend The backend that will be tested. - */ - private function runBackendAuthentication($backend) - { - // Known user - $this->assertNotNull( - $backend->authenticate( - new Credential( - $this->userData[0][self::USER_NAME_COLUMN], - $this->userData[0][self::PASSWORD_COLUMN] - ) - ), - 'Assert that an existing, active user with the right credentials can authenticate.' - ); - - // Wrong password - $this->assertNull( - $backend->authenticate( - new Credential( - $this->userData[1][self::USER_NAME_COLUMN], - 'wrongpassword' - ) - ), - 'Assert that an existing user with an invalid password cannot authenticate' - ); - - // Nonexisting user - $this->assertNull( - $backend->authenticate( - new Credential( - 'nonexisting user', - $this->userData[1][self::PASSWORD_COLUMN] - ) - ), - 'Assert that a non-existing user cannot authenticate.' - ); - - // Inactive user - $this->assertNull( - $backend->authenticate( - new Credential( - $this->userData[2][self::USER_NAME_COLUMN], - $this->userData[2][self::PASSWORD_COLUMN] - ) - ), - 'Assert that an inactive user cannot authenticate.' - ); - } - - /** - * @dataProvider mysqlDb - */ - public function testBackendNameAssignment($db) - { - $this->setupDbProvider($db); - - $testName = 'test-name-123123'; - $backend = new DbUserBackend($this->createDbBackendConfig($db, $testName)); - $backend->connect(); - $this->assertSame($testName, $backend->getName()); - } - - /** - * @dataProvider mysqlDb - */ - public function testCountUsersMySql($db) - { - $this->setupDbProvider($db); - $testName = 'test-name-123123'; - $backend = new DbUserBackend($this->createDbBackendConfig($db, $testName)); - $backend->connect(); - - $this->assertGreaterThan(0, $backend->getUserCount()); - } - - /** - * @dataProvider pgsqlDb - */ - public function testCountUsersPgSql($db) - { - $this->setupDbProvider($db); - $testName = 'test-name-123123'; - $backend = new DbUserBackend($this->createDbBackendConfig($db, $testName)); - $backend->connect(); - - $this->assertGreaterThan(0, $backend->getUserCount()); - } - -} diff --git a/test/php/library/Icinga/Authentication/ErrorProneBackendMock.php b/test/php/library/Icinga/Authentication/ErrorProneBackendMock.php deleted file mode 100644 index 7657ccd15..000000000 --- a/test/php/library/Icinga/Authentication/ErrorProneBackendMock.php +++ /dev/null @@ -1,132 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Tests\Icinga\Authentication; - -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -// @codingStandardsIgnoreEnd - -use Icinga\Test\BaseTestCase; - -// @codingStandardsIgnoreStart -require_once 'Zend/Config.php'; -require_once BaseTestCase::$libDir . '/Authentication/Credential.php'; -require_once BaseTestCase::$libDir . '/Authentication/UserBackend.php'; -require_once BaseTestCase::$libDir . '/User.php'; -// @codingStandardsIgnoreEnd - -use \Exception; -use \Zend_Config; -use \Icinga\Authentication\Credential; -use \Icinga\Authentication\UserBackend as UserBackend; -use \Icinga\User; - -/** - * Simple backend mock that takes an config object - * with the property "credentials", which is an array - * of Credential this backend authenticates - **/ -class ErrorProneBackendMock implements UserBackend -{ - public static $throwOnCreate = false; - - public $name; - - /** - * Creates a new object - * - * @param Zend_Config $config - * @throws Exception - */ - public function __construct(Zend_Config $config) - { - if (self::$throwOnCreate === true) { - throw new Exception('__construct error: Could not create'); - } - - if ($config->name) { - $this->name = $config->name; - } else { - $this->name = 'TestBackendErrorProneMock-' . uniqid(); - } - } - - /** - * Test if the username exists - * - * @param Credential $credentials - * - * @return bool - * @throws Exception - */ - public function hasUsername(Credential $credentials) - { - throw new Exception('hasUsername error: ' . $credentials->getUsername()); - } - - /** - * Authenticate - * - * @param Credential $credentials - * - * @return User - * @throws Exception - */ - public function authenticate(Credential $credentials) - { - throw new Exception('authenticate error: ' . $credentials->getUsername()); - } - - /** - * Name of the backend - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Get the number of users available through this backend - * - * @return int - * @throws Exception - */ - public function getUserCount() - { - throw new Exception('getUserCount error: No users in this error prone backend'); - } - - public function connect() - { - - } -} diff --git a/test/php/library/Icinga/Authentication/LdapUserBackendTest.php b/test/php/library/Icinga/Authentication/LdapUserBackendTest.php deleted file mode 100644 index b0c22edc7..000000000 --- a/test/php/library/Icinga/Authentication/LdapUserBackendTest.php +++ /dev/null @@ -1,233 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Tests\Icinga\Authentication; - -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -// @codingStandardsIgnoreEnd - -use Icinga\Authentication\Credential; -use \Icinga\Test\BaseTestCase; - -// @codingStandardsIgnoreStart -require_once 'Zend/Config.php'; -require_once BaseTestCase::$libDir . '/Protocol/Ldap/Connection.php'; -require_once BaseTestCase::$libDir . '/Protocol/Ldap/Query.php'; -require_once BaseTestCase::$libDir . '/Authentication/Credential.php'; -require_once BaseTestCase::$libDir . '/Authentication/UserBackend.php'; -require_once BaseTestCase::$libDir . '/Authentication/Backend/LdapUserBackend.php'; -// @codingStandardsIgnoreEnd - -use \Exception; -use \Zend_Config; -use Icinga\Authentication\Backend\LdapUserBackend; -use Icinga\Protocol\Ldap\Connection as LdapConnection; - -/** -* -* Test class for Ldapuserbackend -* Created Mon, 10 Jun 2013 07:54:34 +0000 -* -**/ -class LdapUserBackendTest extends BaseTestCase -{ - // Change this according to your ldap test server - const ADMIN_DN = 'cn=admin,dc=icinga,dc=org'; - const ADMIN_PASS = 'admin'; - - private $users = array( - 'cn=Richard Miles,ou=icinga-unittest,dc=icinga,dc=org' => array( - 'cn' => 'Richard Miles', - 'sn' => 'Miles', - 'objectclass' => 'inetOrgPerson', - 'givenName' => 'Richard', - 'mail' => 'richard@doe.local', - 'uid' => 'rmiles', - 'userPassword' => 'passrmiles' - ), - 'cn=Jane Woe,ou=icinga-unittest,dc=icinga,dc=org' => array( - 'cn' => 'Jane Woe', - 'sn' => 'Woe', - 'objectclass' => 'inetOrgPerson', - 'givenName' => 'Jane', - 'mail' => 'jane@woe.local', - 'uid' => 'jwoe', - 'userPassword' => 'passjwoe' - ) - ); - - private $baseOu = array( - 'ou=icinga-unittest,dc=icinga,dc=org' => array( - 'objectclass' => 'organizationalUnit', - 'ou' => 'icinga-unittest' - ) - ); - - private function getLDAPConnection() - { - $ldapConn = ldap_connect('localhost', 389); - - if (!$ldapConn) { - $this->markTestSkipped('Could not connect to test-ldap server, skipping test'); - } - $bind = @ldap_bind($ldapConn, self::ADMIN_DN, self::ADMIN_PASS); - - if (!$bind) { - $this->markTestSkipped('Could not bind to test-ldap server, skipping test'); - } - - return $ldapConn; - } - - private function clearTestData($connection) - { - foreach ($this->users as $ou => $info) { - @ldap_delete($connection, $ou); - } - - foreach ($this->baseOu as $ou => $info) { - @ldap_delete($connection, $ou); - } - } - - private function insertTestdata($connection) - { - foreach ($this->baseOu as $ou => $info) { - if (ldap_add($connection, $ou, $info) === false) { - $this->markTestSkipped('Couldn\'t set up test-ldap users, skipping test'); - } - } - - foreach ($this->users as $ou => $info) { - if (ldap_add($connection, $ou, $info) === false) { - $this->markTestSkipped('Couldn\'t set up test-ldap users, skipping test'); - } - } - } - - protected function setUp() - { - $conn = $this->getLDAPConnection(); - $this->clearTestData($conn); - $this->insertTestData($conn); - - $result = ldap_list($conn, 'ou=icinga-unittest, dc=icinga, dc=org', '(cn=Richard Miles)'); - - if (ldap_count_entries($conn, $result) < 1) { - $this->markTestSkipped('Couldn\'t set up test users, skipping test'); - } - - $result = ldap_list($conn, 'ou=icinga-unittest, dc=icinga, dc=org', '(cn=Jane Woe)'); - - if (ldap_count_entries($conn, $result) < 1) { - $this->markTestSkipped('Couldn\'t set up test users, skipping test'); - } - - ldap_close($conn); - } - - public function tearDown() - { - $conn = $this->getLDAPConnection(); - - // $this->clearTestData($conn); - ldap_close($conn); - } - - /** - * Create a backend config and initialise the LdapConnection to the testing backend manually, - * to prevent the LdapUserBackend from calling the unitialised ResourceFactory - * - * @return Zend_Config The authentication backend configuration - */ - private function createBackendConfig() - { - $resourceConfig = new Zend_Config( - array( - 'hostname' => 'localhost', - 'root_dn' => 'ou=icinga-unittest,dc=icinga,dc=org', - 'bind_dn' => 'cn=admin,cn=config', - 'bind_pw' => 'admin' - ) - ); - $backendConfig = new Zend_Config( - array( - 'resource' => new LdapConnection($resourceConfig), - 'target' => 'user', - 'user_class' => 'inetOrgPerson', - 'user_name_attribute' => 'uid' - ) - ); - return $backendConfig; - } - - /** - * Test for LdapUserBackend::HasUsername() - **/ - public function testHasUsername() - { - $backend = new LdapUserBackend($this->createBackendConfig()); - $this->assertTrue($backend->hasUsername(new Credential('jwoe'))); - $this->assertTrue($backend->hasUsername(new Credential('rmiles'))); - $this->assertFalse($backend->hasUsername(new Credential('DoesNotExist'))); - } - - /** - * Test for LdapUserBackend::Authenticate() - */ - public function testAuthenticate() - { - $backend = new LdapUserBackend($this->createBackendConfig()); - - $this->assertInstanceOf( - '\Icinga\User', - $backend->authenticate(new Credential('jwoe', 'passjwoe')) - ); - - $this->assertNull($backend->authenticate(new Credential('jwoe', 'passjwoe22'))); - - $this->assertInstanceOf( - '\Icinga\User', - $backend->authenticate(new Credential('rmiles', 'passrmiles')) - ); - - $this->assertNull($backend->authenticate(new Credential('rmiles', 'passrmiles33'))); - } - - /** - * @expectedException Exception - * @expectedExceptionMessage Cannot fetch single DN for - */ - public function testAuthenticateUnknownUser() - { - $backend = new LdapUserBackend($this->createBackendConfig()); - $this->assertFalse($backend->authenticate(new Credential('unknown123', 'passunknown123'))); - } -} diff --git a/test/php/library/Icinga/Authentication/ManagerTest.php b/test/php/library/Icinga/Authentication/ManagerTest.php deleted file mode 100644 index aaf9ffafd..000000000 --- a/test/php/library/Icinga/Authentication/ManagerTest.php +++ /dev/null @@ -1,358 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Tests\Icinga\Authentication; - -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -// @codingStandardsIgnoreEnd - -use \Icinga\Test\BaseTestCase; - -// @codingStandardsIgnoreStart -require_once 'Zend/Log.php'; -require_once 'Zend/Config.php'; -require_once BaseTestCase::$libDir . '/Logger/Logger.php'; -require_once BaseTestCase::$libDir . '/Authentication/Manager.php'; -require_once BaseTestCase::$libDir . '/Authentication/Membership.php'; -require_once BaseTestCase::$libDir . '/Authentication/Credential.php'; -require_once BaseTestCase::$libDir . '/Authentication/Membership.php'; -require_once BaseTestCase::$libDir . '/Exception/ConfigurationError.php'; -require_once BaseTestCase::$libDir . '/Exception/ProgrammingError.php'; -require_once BaseTestCase::$libDir . '/Exception/NotReadableError.php'; -require_once BaseTestCase::$libDir . '/Web/Session.php'; -require_once 'BackendMock.php'; -require_once 'ErrorProneBackendMock.php'; -require_once 'SessionMock.php'; -// @codingStandardsIgnoreEnd - -use \Zend_Config; -use Icinga\Web\Session; -use Icinga\Authentication\Manager as AuthManager; -use Icinga\Authentication\Credential; -use Icinga\Exception\ConfigurationError; - -/** - * @backupStaticAttributes enabled - */ -class ManagerTest extends BaseTestCase -{ - public function getTestCredentials() - { - return array( - new Credential("jdoe", "passjdoe"), - new Credential("root", "passroot"), - new Credential("test", "passtest") - ); - } - - public function getManagerInstance( - &$session = null, - $write = false, - $nobackend = false, - Zend_Config $managerConfig = null - ) { - if ($session == null) { - $session = new SessionMock(); - } - - if ($managerConfig === null) { - $managerConfig = new Zend_Config(array()); - } - - Session::create($session); - $manager = AuthManager::getInstance($managerConfig); - - if ($nobackend === false) { - $backend = new BackendMock(); - $backend->allowedCredentials = $this->getTestCredentials(); - $manager->addUserBackend($backend); - } - - return $manager; - } - - public function testManagerInstanciation() - { - $authMgr = $this->getManagerInstance(); - $this->assertSame($authMgr, AuthManager::getInstance()); - } - - public function testManagerProducingDependencies() - { - $authMgr = $this->getManagerInstance($session, true); - $this->assertSame($authMgr, AuthManager::getInstance()); - - $backend = new BackendMock(); - $backend->setCredentials($this->getTestCredentials()); - - $authMgr->addUserBackend($backend); - - $this->assertTrue( - $authMgr->authenticate( - new Credential('jdoe', 'passjdoe') - ) - ); - - $this->assertInstanceOf('Icinga\User', $authMgr->getUser()); - $this->assertSame('Username', $authMgr->getUser()->getUsername()); - - $session->isOpen = true; - $authMgr->removeAuthorization(); - - $this->assertNull($authMgr->getUser()); - } - - public function testAuthentication() - { - $auth = $this->getManagerInstance(); - $this->assertFalse( - $auth->authenticate( - new Credential("jhoe", "passjdoe"), - false - ) - ); - $this->assertFalse( - $auth->authenticate( - new Credential("joe", "passjhoe"), - false - ) - ); - $this->assertTrue( - $auth->authenticate( - new Credential("jdoe", "passjdoe"), - false - ) - ); - } - - public function testPersistAuthInSession() - { - $session = new SessionMock(); - $auth = $this->getManagerInstance($session, true); - $this->assertFalse($auth->isAuthenticated(true)); - $auth->authenticate(new Credential("jdoe", "passjdoe")); - $this->assertNotEquals(null, $session->get("user")); - $user = $session->get("user"); - $this->assertEquals("Username", $user->getUsername()); - $this->assertTrue($auth->isAuthenticated(true)); - } - - public function testAuthenticateFromSession() - { - $session = new SessionMock(); - $session->set("user", BackendMock::getDummyUser()); - $auth = $this->getManagerInstance($session, false); - $this->assertFalse($auth->isAuthenticated(true)); - $this->assertTrue($auth->isAuthenticated()); - $this->assertTrue($auth->isAuthenticated()); - } - - /** - * @expectedException Icinga\Exception\ConfigurationError - * @expectedExceptionMessage No authentication backend set - */ - public function testErrorProneBackendsFromConfigurationWhenInitiate() - { - $managerConfig = new Zend_Config( - array( - 'provider1' => array( - 'class' => 'Tests\Icinga\Authentication\ErrorProneBackendMock' - ) - ), - true - ); - - ErrorProneBackendMock::$throwOnCreate = true; - - $authManager = $this->getManagerInstance($session, true, true, $managerConfig); - - $this->assertNull( - $authManager->getUserBackend('provider1') - ); - - $authManager->authenticate( - new Credential('jdoe', 'passjdoe') - ); - } - - /** - * @expectedException Icinga\Exception\ConfigurationError - * @expectedExceptionMessage No working backend found. Unable to authenticate any - */ - public function testErrorProneBackendsFromConfigurationWhenAuthenticate() - { - $managerConfig = new Zend_Config( - array( - 'provider1' => array( - 'class' => 'Tests\Icinga\Authentication\ErrorProneBackendMock' - ), - 'provider2' => array( - 'class' => 'Tests\Icinga\Authentication\ErrorProneBackendMock' - ) - ), - true - ); - - ErrorProneBackendMock::$throwOnCreate = false; - - $authManager = $this->getManagerInstance($session, false, true, $managerConfig); - - $this->assertInstanceOf( - 'Tests\Icinga\Authentication\ErrorProneBackendMock', - $authManager->getUserBackend('provider1') - ); - - $this->assertInstanceOf( - 'Tests\Icinga\Authentication\ErrorProneBackendMock', - $authManager->getUserBackend('provider2') - ); - - $authManager->authenticate( - new Credential('jdoe', 'passjdoe') - ); - } - - public function testAuthenticationChainWithGoodProviders() - { - $managerConfig = new Zend_Config( - array( - 'provider1' => array( - 'class' => 'Tests\Icinga\Authentication\BackendMock' - ), - 'provider2' => array( - 'class' => 'Tests\Icinga\Authentication\BackendMock' - ) - ), - true - ); - - $authManager = $this->getManagerInstance($session, true, true, $managerConfig); - - $authManager->getUserBackend('provider1')->setCredentials( - array( - new Credential('p1-user1', 'p1-passwd1'), - new Credential('p1-user2', 'p1-passwd2') - ) - ); - - $authManager->getUserBackend('provider2')->setCredentials( - array( - new Credential('p2-user1', 'p2-passwd1'), - new Credential('p2-user2', 'p2-passwd2') - ) - ); - - $this->assertTrue( - $authManager->authenticate(new Credential('p2-user2', 'p2-passwd2')) - ); - } - - public function testAuthenticationChainWithBadProviders() - { - $managerConfig = new Zend_Config( - array( - 'provider1' => array( - 'class' => 'Tests\Icinga\Authentication\ErrorProneBackendMock' - ), - 'provider2' => array( - 'class' => 'Tests\Icinga\Authentication\ErrorProneBackendMock' - ), - 'provider3' => array( - 'class' => 'Tests\Icinga\Authentication\ErrorProneBackendMock' - ), - 'provider4' => array( - 'class' => 'Tests\Icinga\Authentication\BackendMock' - ) - ), - true - ); - - $authManager = $this->getManagerInstance($session, false, true, $managerConfig); - - $this->assertInstanceOf( - 'Tests\Icinga\Authentication\ErrorProneBackendMock', - $authManager->getUserBackend('provider1') - ); - - $this->assertInstanceOf( - 'Tests\Icinga\Authentication\BackendMock', - $authManager->getUserBackend('provider4') - ); - - $authManager->getUserBackend('provider4')->setCredentials( - array( - new Credential('p4-user1', 'p4-passwd1'), - new Credential('p4-user2', 'p4-passwd2') - ) - ); - - $session->isOpen = true; - - $this->assertTrue( - $authManager->authenticate(new Credential('p4-user2', 'p4-passwd2')) - ); - - $session->isOpen = true; - - $this->assertTrue( - $authManager->authenticate(new Credential('p4-user1', 'p4-passwd1')) - ); - - $session->isOpen = true; - - $this->assertFalse( - $authManager->authenticate(new Credential('p4-user2', 'p4-passwd1-WRONG123123')) - ); - } - - public function testErrorConditionsInConfiguration() - { - $managerConfig = new Zend_Config( - array( - 'provider1' => array( - 'backend' => 'db' - ), - 'provider2' => array( - 'target' => 'user' - ), - 'provider3' => array( - 'class' => 'Uhh\Ahh\WeDoNotCare123' - ) - ), - true - ); - - $authManager = $this->getManagerInstance($session, true, true, $managerConfig); - - $this->assertNull($authManager->getUserBackend('provider1')); - $this->assertNull($authManager->getUserBackend('provider2')); - $this->assertNull($authManager->getUserBackend('provider3')); - } -} diff --git a/test/php/library/Icinga/Authentication/SessionMock.php b/test/php/library/Icinga/Authentication/SessionMock.php deleted file mode 100644 index 6fce41700..000000000 --- a/test/php/library/Icinga/Authentication/SessionMock.php +++ /dev/null @@ -1,79 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Tests\Icinga\Authentication; - -require_once("../../library/Icinga/Session/SessionNamespace.php"); -require_once("../../library/Icinga/Session/Session.php"); - -use Icinga\Web\Session\Session; - -class SessionMock extends Session -{ - public $isOpen = false; - public $isWritten = false; - - public function open() - { - if (!$this->isOpen && $this->isWritten) { - throw new \Exception("Session write after close"); - } - $this->isOpen = true; - } - - public function read($keepOpen = false) - { - $this->open(); - if (!$keepOpen) { - $this->close(); - } - } - - public function write($keepOpen = false) - { - $this->open(); - if (!$keepOpen) { - $this->close(); - } - } - - public function close() - { - $this->isOpen = false; - $this->isWritten = true; - } - - public function purge() - { - } - - public function refreshId() - { - } -} diff --git a/test/php/library/Icinga/Chart/GraphChartTest.php b/test/php/library/Icinga/Chart/GraphChartTest.php index 77bb04d1a..25870791a 100644 --- a/test/php/library/Icinga/Chart/GraphChartTest.php +++ b/test/php/library/Icinga/Chart/GraphChartTest.php @@ -1,51 +1,13 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} namespace Tests\Icinga\Chart; -use DOMXPath; -use DOMDocument; - +use \DOMXPath; +use \DOMDocument; use Icinga\Chart\GridChart; use Icinga\Test\BaseTestCase; -use Test\Icinga\LibraryLoader; - -// TODO: Use autoloader #4673 -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -require_once realpath(BaseTestCase::$testDir . '/library/Icinga/LibraryLoader.php'); - -require_once realpath(BaseTestCase::$libDir . '/Chart/Primitive/Drawable.php'); -require_once realpath(BaseTestCase::$libDir . '/Chart/Primitive/Styleable.php'); -require_once realpath(BaseTestCase::$libDir . '/Chart/Primitive/Animatable.php'); -require_once realpath(BaseTestCase::$libDir . '/Chart/Unit/AxisUnit.php'); -require_once realpath(BaseTestCase::$libDir . '/Chart/Unit/LinearUnit.php'); -LibraryLoader::loadFolder(realpath(BaseTestCase::$libDir . '/Chart')); class GraphChartTest extends BaseTestCase { diff --git a/test/php/library/Icinga/Chart/PieChartTest.php b/test/php/library/Icinga/Chart/PieChartTest.php index 1c8a70fa8..c09f29e57 100644 --- a/test/php/library/Icinga/Chart/PieChartTest.php +++ b/test/php/library/Icinga/Chart/PieChartTest.php @@ -1,52 +1,13 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} namespace Tests\Icinga\Chart; -use DOMXPath; -use DOMDocument; - -use Icinga\Chart\GridChart; +use \DOMXPath; +use \DOMDocument; use Icinga\Chart\PieChart; use Icinga\Test\BaseTestCase; -use Test\Icinga\LibraryLoader; - -// TODO: Use autoloader #4673 -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -require_once realpath(BaseTestCase::$testDir . '/library/Icinga/LibraryLoader.php'); - -require_once realpath(BaseTestCase::$libDir . '/Chart/Primitive/Drawable.php'); -require_once realpath(BaseTestCase::$libDir . '/Chart/Primitive/Styleable.php'); -require_once realpath(BaseTestCase::$libDir . '/Chart/Primitive/Animatable.php'); -require_once realpath(BaseTestCase::$libDir . '/Chart/Unit/AxisUnit.php'); -require_once realpath(BaseTestCase::$libDir . '/Chart/Unit/LinearUnit.php'); -LibraryLoader::loadFolder(realpath(BaseTestCase::$libDir . '/Chart')); class PieChartTest extends BaseTestCase { diff --git a/test/php/library/Icinga/Config/PreservingIniWriterTest.php b/test/php/library/Icinga/Config/PreservingIniWriterTest.php index fe833edf7..db83c9b03 100644 --- a/test/php/library/Icinga/Config/PreservingIniWriterTest.php +++ b/test/php/library/Icinga/Config/PreservingIniWriterTest.php @@ -1,393 +1,637 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Tests\Icinga\PreservingIniWriterTest; +namespace Tests\Icinga\Config; -require_once 'Zend/Config.php'; -require_once 'Zend/Config/Ini.php'; -require_once 'Zend/Config/Writer/Ini.php'; -require_once('../../library/Icinga/Config/IniEditor.php'); -require_once('../../library/Icinga/Config/PreservingIniWriter.php'); - -use Icinga\Config\PreservingIniWriter; use Zend_Config; +use Zend_Config_Ini; +use Icinga\Test\BaseTestCase; +use Icinga\Config\PreservingIniWriter; -class PreservingIniWriterTest extends \PHPUnit_Framework_TestCase { +class PreservingIniWriterTest extends BaseTestCase +{ + protected $tempFile; - private $tmpfiles = array(); - - /** - * Set up the test fixture - */ public function setUp() { - $ini = -' -trailing1="wert" -arr[]="0" -arr[]="1" -arr[]="2" -arr[]="3" + parent::setUp(); -Trailing2= - -;1 -;2 -;3 -[section] -property = "some value" ; Some " ; comment" -property2 = "some ;value" ; Some comment with " quotes " -property3.nest1.nest2 = "value" ; ; - -[parent] -;4 -;5 -;6 -;7 -list[]="zero" -list[]="one" - -;8 -;9 -many.many.nests="value" -propOne="value1" -propTwo="2" -propThree= -propFour="true" - -Prop5="true" - -[child : parent] -PropOne="overwritten" -;10 -'; - $this->writeToTmp('orig', $ini); - - $emptyIni = " "; - $this->writeToTmp('empty', $emptyIni); - - $editedIni = -';1 -;2 -;3 -;4 -;5 -trailing1="1" - -[parent] -;6 -;7 -;8 -;9 -;10 -propOne="value1" - -[different] -prop1="1" -prop2="2" - -[nested : different] -prop2="5" -'; - $this->writeToTmp('edited', $editedIni); + $this->tempFile = tempnam(sys_get_temp_dir(), 'icinga-ini-writer-test'); } - /** - * Write a string to a temporary file - * - * @param string $name The name of the temporary file - * @param string $content The content - */ - private function writeToTmp($name, $content) - { - $this->tmpfiles[$name] = - tempnam(dirname(__FILE__) . '/temp', $name); - $file = fopen($this->tmpfiles[$name], 'w'); - fwrite($file, $content); - fflush($file); - fclose($file); - } - - /** - * Tear down the test fixture - */ public function tearDown() { - foreach ($this->tmpfiles as $filename) { - unlink($filename); - } + parent::tearDown(); + + unlink($this->tempFile); + } + + public function testWhetherSimplePropertiesAreInsertedInEmptyFiles() + { + $target = $this->writeConfigToTemporaryFile(''); + $config = new Zend_Config(array('key' => 'value')); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); + + $newConfig = new Zend_Config_Ini($target); + $this->assertEquals('value', $newConfig->get('key'), 'PreservingIniWriter does not insert in empty files'); + } + + public function testWhetherSimplePropertiesAreInsertedInExistingFiles() + { + $target = $this->writeConfigToTemporaryFile('key1 = "1"'); + $config = new Zend_Config(array('key2' => '2')); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); + + $newConfig = new Zend_Config_Ini($target); + $this->assertEquals('2', $newConfig->get('key2'), 'PreservingIniWriter does not insert in existing files'); } /** - * Test if the IniWriter works correctly when writing the changes back to - * the same ini file + * @depends testWhetherSimplePropertiesAreInsertedInExistingFiles */ - public function testPropertyChangeSameConfig() + public function testWhetherSimplePropertiesAreUpdated() { - $this->changeConfigAndWriteToFile('orig'); - $config = new \Zend_Config_Ini( - $this->tmpfiles['orig'], null, array('allowModifications' => true) + $target = $this->writeConfigToTemporaryFile('key = "value"'); + $config = new Zend_Config(array('key' => 'eulav')); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); + + $newConfig = new Zend_Config_Ini($target); + $this->assertEquals('eulav', $newConfig->get('key'), 'PreservingIniWriter does not update simple properties'); + } + + /** + * @depends testWhetherSimplePropertiesAreInsertedInExistingFiles + */ + public function testWhetherSimplePropertiesAreDeleted() + { + $target = $this->writeConfigToTemporaryFile('key = "value"'); + $config = new Zend_Config(array()); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); + + $newConfig = new Zend_Config_Ini($target); + $this->assertNull($newConfig->get('key'), 'PreservingIniWriter does not delete simple properties'); + } + + public function testWhetherNestedPropertiesAreInserted() + { + $target = $this->writeConfigToTemporaryFile(''); + $config = new Zend_Config(array('a' => array('b' => 'c'))); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); + + $newConfig = new Zend_Config_Ini($target); + $this->assertInstanceOf( + '\Zend_Config', + $newConfig->get('a'), + 'PreservingIniWriter does not insert nested properties' ); - $this->checkConfigProperties($config); - $this->checkConfigComments($this->tmpfiles['orig']); - } - - /** - * Test if the IniWriter works correctly when writing to an empty file - */ - public function testPropertyChangeEmptyConfig() - { - $this->changeConfigAndWriteToFile('empty'); - $config = new \Zend_Config_Ini( - $this->tmpfiles['empty'], null, array('allowModifications' => true) + $this->assertEquals( + 'c', + $newConfig->get('a')->get('b'), + 'PreservingIniWriter does not insert nested properties' ); - $this->checkConfigProperties($config); } /** - * Test if the IniWriter works correctly when writing to a file with changes + * @depends testWhetherNestedPropertiesAreInserted */ - public function testPropertyChangeEditedConfig() + public function testWhetherNestedPropertiesAreUpdated() { - $original = $this->changeConfigAndWriteToFile('edited'); - $config = new \Zend_Config_Ini( - $this->tmpfiles['edited'], null, array('allowModifications' => true) + $target = $this->writeConfigToTemporaryFile('a.b = "c"'); + $config = new Zend_Config(array('a' => array('b' => 'cc'))); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); + + $newConfig = new Zend_Config_Ini($target); + $this->assertInstanceOf( + '\Zend_Config', + $newConfig->get('a'), + 'PreservingIniWriter does not update nested properties' + ); + $this->assertEquals( + 'cc', + $newConfig->get('a')->get('b'), + 'PreservingIniWriter does not update nested properties' ); - $this->checkConfigProperties($config); - $this->checkConfigComments($this->tmpfiles['edited']); } /** - * Test if the order of sections is correctly changed in the config. + * @depends testWhetherNestedPropertiesAreInserted */ - public function testSectionOrderChange() + public function testWhetherNestedPropertiesAreDeleted() { - $original = ' -;1 + $target = $this->writeConfigToTemporaryFile('a.b = "c"'); + $config = new Zend_Config(array()); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); -[section2] -;3 + $newConfig = new Zend_Config_Ini($target); + $this->assertNull( + $newConfig->get('a'), + 'PreservingIniWriter does not delete nested properties' + ); + } -;4 -[section3] -;5 + public function testWhetherSimpleSectionPropertiesAreInserted() + { + $target = $this->writeConfigToTemporaryFile(''); + $config = new Zend_Config(array('section' => array('key' => 'value'))); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); -;2 -[section1] -property = "something" ; comment + $newConfig = new Zend_Config_Ini($target); + $this->assertInstanceOf( + '\Zend_Config', + $newConfig->get('section'), + 'PreservingIniWriter does not insert sections' + ); + $this->assertEquals( + 'value', + $newConfig->get('section')->get('key'), + 'PreservingIniWriter does not insert simple section properties' + ); + } - '; - $this->writeToTmp('section-order',$original); + /** + * @depends testWhetherSimpleSectionPropertiesAreInserted + */ + public function testWhetherSimpleSectionPropertiesAreUpdated() + { + $target = $this->writeConfigToTemporaryFile(<<<'EOD' +[section] +key = "value" +EOD + ); + $config = new Zend_Config(array('section' => array('key' => 'eulav'))); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); + + $newConfig = new Zend_Config_Ini($target); + $this->assertEquals( + 'eulav', + $newConfig->get('section')->get('key'), + 'PreservingIniWriter does not update simple section properties' + ); + } + + /** + * @depends testWhetherSimpleSectionPropertiesAreInserted + */ + public function testWhetherSimpleSectionPropertiesAreDeleted() + { + $target = $this->writeConfigToTemporaryFile(<<<'EOD' +[section] +key = "value" +EOD + ); + $config = new Zend_Config(array('section' => array())); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); + + $newConfig = new Zend_Config_Ini($target); + $this->assertNull( + $newConfig->get('section')->get('key'), + 'PreservingIniWriter does not delete simple section properties' + ); + } + + public function testWhetherNestedSectionPropertiesAreInserted() + { + $target = $this->writeConfigToTemporaryFile(''); + $config = new Zend_Config(array('section' => array('a' => array('b' => 'c')))); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); + + $newConfig = new Zend_Config_Ini($target); + $this->assertInstanceOf( + '\Zend_Config', + $newConfig->get('section'), + 'PreservingIniWriter does not insert sections' + ); + $this->assertInstanceOf( + '\Zend_Config', + $newConfig->get('section')->get('a'), + 'PreservingIniWriter does not insert nested section properties' + ); + $this->assertEquals( + 'c', + $newConfig->get('section')->get('a')->get('b'), + 'PreservingIniWriter does not insert nested section properties' + ); + } + + /** + * @depends testWhetherNestedSectionPropertiesAreInserted + */ + public function testWhetherNestedSectionPropertiesAreUpdated() + { + $target = $this->writeConfigToTemporaryFile(<<<'EOD' +[section] +a.b = "c" +EOD + ); + $config = new Zend_Config(array('section' => array('a' => array('b' => 'cc')))); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); + + $newConfig = new Zend_Config_Ini($target); + $this->assertEquals( + 'cc', + $newConfig->get('section')->get('a')->get('b'), + 'PreservingIniWriter does not update nested section properties' + ); + } + + /** + * @depends testWhetherNestedSectionPropertiesAreInserted + */ + public function testWhetherNestedSectionPropertiesAreDeleted() + { + $target = $this->writeConfigToTemporaryFile(<<<'EOD' +[section] +a.b = "c" +EOD + ); + $config = new Zend_Config(array('section' => array())); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); + + $newConfig = new Zend_Config_Ini($target); + $this->assertNull( + $newConfig->get('section')->get('a'), + 'PreservingIniWriter does not delete nested section properties' + ); + } + + public function testWhetherSimplePropertiesOfExtendingSectionsAreInserted() + { + $target = $this->writeConfigToTemporaryFile(''); $config = new Zend_Config( array( - 'section1' => array( - 'property' => 'something' - ), - 'section2' => array(), - 'section3' => array() + 'foo' => array('key1' => '1'), + 'bar' => array('key2' => '2') ) ); - $writer = new PreservingIniWriter( - array('config' => $config, 'filename' => $this->tmpfiles['section-order']) - ); + $config->setExtend('bar', 'foo'); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); $writer->write(); - $changed = new \Zend_Config_Ini( - $this->tmpfiles['section-order'], - null, - array('allowModifications' => true) - ); - $this->assertEquals($config->section1->property, $changed->section1->property); - /* - * IniWriter should move the sections, so that comments - * are now in the right order - */ - $this->checkConfigComments( - $this->tmpfiles['section-order'], - 5, - 'Sections re-ordered correctly' + $newConfig = new Zend_Config_Ini($target); + $this->assertInstanceOf( + '\Zend_Config', + $newConfig->get('foo'), + 'PreservingIniWriter does not insert extended sections' + ); + $this->assertInstanceOf( + '\Zend_Config', + $newConfig->get('bar'), + 'PreservingIniWriter does not insert extending sections' + ); + $this->assertEquals( + '2', + $newConfig->get('bar')->get('key2'), + 'PreservingIniWriter does not insert simple properties into extending sections' + ); + $this->assertEquals( + '1', + $newConfig->get('bar')->get('key1'), + 'PreservingIniWriter does not properly define extending sections' ); } /** - * Change the test config, write the changes to the temporary - * file $tmpFile and save the path to the file in the array tmpfiles - * - * @param string $tmpFile The name that should be given to the temporary file + * @depends testWhetherSimplePropertiesOfExtendingSectionsAreInserted */ - private function changeConfigAndWriteToFile($tmpFile) + public function testWhetherSimplePropertiesOfExtendingSectionsAreUpdated() { - $config = $this->createTestConfig(); - $this->alterConfig($config); - $writer = new PreservingIniWriter( - array('config' => $config,'filename' => $this->tmpfiles[$tmpFile]) + $target = $this->writeConfigToTemporaryFile(<<<'EOD' +[foo] +key1 = "1" + +[bar : foo] +key2 = "2" +EOD ); + $config = new Zend_Config( + array( + 'foo' => array('key1' => '1'), + 'bar' => array('key2' => '22') + ) + ); + $config->setExtend('bar', 'foo'); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); $writer->write(); - return $config; - } - /** - * Check if all comments are present - * - * @param String $file The file to check - * @param Number $count The amount of comments that should be present - * @param String $assertion The assertion message that will be displayed on errors - */ - private function checkConfigComments($file,$count = 10,$assertion = 'Comment unchanged') - { - $i = 0; - foreach (explode("\n",file_get_contents($file)) as $line) { - if (preg_match('/^;/',$line)) { - $i++; - $this->assertEquals( - $i,intval(substr($line,1)), - $assertion - ); - } - } - $this->assertEquals($count, $i, 'All comments exist'); - } - - /** - * Test if all configuration properties are set correctly - * - * @param mixed $config The configuration to check - */ - private function checkConfigProperties($config) - { - $this->assertEquals('val', $config->Trailing2, - 'Section-less property updated.'); - - $this->assertNull($config->trailing1, - 'Section-less property deleted.'); - - $this->assertEquals('value', $config->new, - 'Section-less property created.'); - - $this->assertEquals('0', $config->arr->{0}, - 'Value persisted in array'); - - $this->assertEquals('update', $config->arr->{2}, - 'Value changed in array'); - - $this->assertEquals('arrvalue', $config->arr->{4}, - 'Value added to array'); - - $this->assertEquals('', $config->parent->propOne, - 'Section property deleted.'); - - $this->assertEquals("2", $config->parent->propTwo, - 'Section property numerical unchanged.'); - - $this->assertEquals('update', $config->parent->propThree, - 'Section property updated.'); - - $this->assertEquals("true", $config->parent->propFour, - 'Section property boolean unchanged.'); - - $this->assertEquals("1", $config->parent->new, - 'Section property numerical created.'); - - $this->assertNull($config->parent->list->{0}, - 'Section array deleted'); - - $this->assertEquals('new', $config->parent->list->{1}, - 'Section array changed.'); - - $this->assertEquals('changed', $config->parent->many->many->nests, - 'Change strongly nested value.'); - - $this->assertEquals('new', $config->parent->many->many->new, - 'Ccreate strongy nested value.'); - - $this->assertEquals('overwritten', $config->child->PropOne, - 'Overridden inherited property unchanged.'); - - $this->assertEquals('somethingNew', $config->child->propTwo, - 'Inherited property changed.'); - - $this->assertEquals('test', $config->child->create, - 'Non-inherited property created.'); - - $this->assertInstanceOf('Zend_Config', $config->newsection, - 'New section created.'); - - $extends = $config->getExtends(); - $this->assertEquals('child', $extends['newsection'], - 'New inheritance created.'); - } - - /** - * Change the content of a Zend_Config for testing purposes - * - * @param Zend_Config $config The configuration that should be changed - */ - private function alterConfig(\Zend_Config $config) - { - $config->Trailing2 = 'val'; - unset($config->trailing1); - $config->new = 'value'; - $config->arr->{2} = "update"; - $config->arr->{4} = "arrvalue"; - - $config->section->property = "updated"; - unset($config->section->property3); - $config->section->property4 = "created"; - - $config->parent->propOne = null; - $config->parent->propThree = 'update'; - $config->parent->new = 1; - unset($config->parent->list->{0}); - $config->parent->list->{1} = 'new'; - - $config->parent->many->many->nests = "changed"; - $config->parent->many->many->new = "new"; - - $config->child->propTwo = 'somethingNew'; - $config->child->create = 'test'; - - $config->newsection = array(); - $config->newsection->p1 = "prop"; - $config->newsection->P2 = "prop"; - $config->setExtend('newsection', 'child'); - } - - /** - * Create the the configuration that will be used for the tests. - */ - private function createTestConfig() - { - return new \Zend_Config_Ini( - $this->tmpfiles['orig'], - null, - array('allowModifications' => true) + $newConfig = new Zend_Config_Ini($target); + $this->assertEquals( + '22', + $newConfig->get('bar')->get('key2'), + 'PreservingIniWriter does not update simple properties of extending sections' ); } + + /** + * @depends testWhetherSimplePropertiesOfExtendingSectionsAreInserted + */ + public function testWhetherSimplePropertiesOfExtendingSectionsAreDeleted() + { + $target = $this->writeConfigToTemporaryFile(<<<'EOD' +[foo] +key1 = "1" + +[bar : foo] +key2 = "2" +EOD + ); + $config = new Zend_Config( + array( + 'foo' => array('key1' => '1'), + 'bar' => array() + ) + ); + $config->setExtend('bar', 'foo'); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); + + $newConfig = new Zend_Config_Ini($target); + $this->assertNull( + $newConfig->get('bar')->get('key2'), + 'PreservingIniWriter does not delete simple properties of extending sections' + ); + } + + public function testWhetherNestedPropertiesOfExtendingSectionsAreInserted() + { + $target = $this->writeConfigToTemporaryFile(''); + $config = new Zend_Config( + array( + 'foo' => array('a' => array('b' => 'c')), + 'bar' => array('d' => array('e' => 'f')) + ) + ); + $config->setExtend('bar', 'foo'); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); + + $newConfig = new Zend_Config_Ini($target); + $this->assertInstanceOf( + '\Zend_Config', + $newConfig->get('foo'), + 'PreservingIniWriter does not insert extended sections' + ); + $this->assertInstanceOf( + '\Zend_Config', + $newConfig->get('bar'), + 'PreservingIniWriter does not insert extending sections' + ); + $this->assertInstanceOf( + '\Zend_Config', + $newConfig->get('bar')->get('d'), + 'PreservingIniWriter does not insert nested properties into extending sections' + ); + $this->assertEquals( + 'f', + $newConfig->get('bar')->get('d')->get('e'), + 'PreservingIniWriter does not insert nested properties into extending sections' + ); + $this->assertEquals( + 'c', + $newConfig->get('bar')->get('a')->get('b'), + 'PreservingIniWriter does not properly define extending sections with nested properties' + ); + } + + /** + * @depends testWhetherNestedPropertiesOfExtendingSectionsAreInserted + */ + public function testWhetherNestedPropertiesOfExtendingSectionsAreUpdated() + { + $target = $this->writeConfigToTemporaryFile(<<<'EOD' +[foo] +a.b = "c" + +[bar : foo] +d.e = "f" +EOD + ); + $config = new Zend_Config( + array( + 'foo' => array('a' => array('b' => 'c')), + 'bar' => array('d' => array('e' => 'ff')) + ) + ); + $config->setExtend('bar', 'foo'); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); + + $newConfig = new Zend_Config_Ini($target); + $this->assertEquals( + 'ff', + $newConfig->get('bar')->get('d')->get('e'), + 'PreservingIniWriter does not update nested properties of extending sections' + ); + } + + /** + * @depends testWhetherNestedPropertiesOfExtendingSectionsAreInserted + */ + public function testWhetherNestedPropertiesOfExtendingSectionsAreDeleted() + { + $target = $this->writeConfigToTemporaryFile(<<<'EOD' +[foo] +a.b = "c" + +[bar : foo] +d.e = "f" +EOD + ); + $config = new Zend_Config( + array( + 'foo' => array('a' => array('b' => 'c')), + 'bar' => array() + ) + ); + $config->setExtend('bar', 'foo'); + $writer = new PreservingIniWriter(array('config' => $config, 'filename' => $target)); + $writer->write(); + + $newConfig = new Zend_Config_Ini($target); + $this->assertNull( + $newConfig->get('bar')->get('d'), + 'PreservingIniWriter does not delete nested properties of extending sections' + ); + } + + public function testWhetherSectionAndPropertyOrderIsPreserved() + { + $config = <<<'EOD' +[one] +key1 = "1" +key2 = "2" + + +[two] +a.b = "c" +d.e = "f" + + +[three] +key = "value" +foo.bar = "raboof" +EOD; + $target = $this->writeConfigToTemporaryFile($config); + $writer = new PreservingIniWriter( + array( + 'config' => new Zend_Config( + array( + 'three' => array( + 'foo' => array( + 'bar' => 'raboof' + ), + 'key' => 'value' + ), + 'two' => array( + 'd' => array( + 'e' => 'f' + ), + 'a' => array( + 'b' => 'c' + ) + ), + 'one' => array( + 'key2' => '2', + 'key1' => '1' + ) + ) + ), + 'filename' => $target + ) + ); + + $this->assertEquals( + $config, + $writer->render(), + 'PreservingIniWriter does not preserve section and/or property order' + ); + } + + public function testWhetherCommentsOnEmptyLinesArePreserved() + { + $config = <<<'EOD' +; some interesting comment +key = "value" +; another interesting comment +; boring comment +EOD; + $target = $this->writeConfigToTemporaryFile($config); + $writer = new PreservingIniWriter( + array('config' => new Zend_Config(array('key' => 'value')), 'filename' => $target) + ); + + $this->assertEquals( + $config, + $writer->render(), + 'PreservingIniWriter does not preserve comments on empty lines' + ); + } + + public function testWhetherCommentsOnPropertyLinesArePreserved() + { + $config = <<<'EOD' +foo = 1337 ; I know what a " and a ' is +bar = 7331 ; I; tend; to; overact; !1!1!!11!111! ; +key = "value" ; some comment for a small sized property +xxl = "very loooooooooooooooooooooong" ; my value is very lo... +EOD; + $target = $this->writeConfigToTemporaryFile($config); + $writer = new PreservingIniWriter( + array( + 'config' => new Zend_Config( + array( + 'foo' => 1337, + 'bar' => 7331, + 'key' => 'value', + 'xxl' => 'very loooooooooooooooooooooong' + ) + ), + 'filename' => $target + ) + ); + + $this->assertEquals( + $config, + $writer->render(), + 'PreservingIniWriter does not preserve comments on property lines' + ); + } + + public function testWhetherCommentsOnEmptySectionLinesArePreserved() + { + $config = <<<'EOD' +[section] +; some interesting comment, in a section +key = "value" +EOD; + $target = $this->writeConfigToTemporaryFile($config); + $writer = new PreservingIniWriter( + array('config' => new Zend_Config(array('section' => array('key' => 'value'))), 'filename' => $target) + ); + + $this->assertEquals( + $config, + $writer->render(), + 'PreservingIniWriter does not preserve comments on empty section lines' + ); + } + + public function testWhetherCommentsOnSectionPropertyLinesArePreserved() + { + $config = <<<'EOD' +[section] +foo = 1337 ; I know what a " and a ' is +bar = 7331 ; I; tend; to; overact; !1!1!!11!111! ; +key = "value" ; some comment for a small sized property +xxl = "very loooooooooooooooooooooong" ; my value is very lo... +EOD; + $target = $this->writeConfigToTemporaryFile($config); + $writer = new PreservingIniWriter( + array( + 'config' => new Zend_Config( + array( + 'section' => array( + 'foo' => 1337, + 'bar' => 7331, + 'key' => 'value', + 'xxl' => 'very loooooooooooooooooooooong' + ) + ) + ), + 'filename' => $target + ) + ); + + $this->assertEquals( + $config, + $writer->render(), + 'PreservingIniWriter does not preserve comments on property lines' + ); + } + + /** + * Write a INI-configuration string to a temporary file and return it's path + * + * @param string $config The config string to write + * + * @return string The path to the temporary file + */ + protected function writeConfigToTemporaryFile($config) + { + file_put_contents($this->tempFile, $config); + return $this->tempFile; + } } diff --git a/test/php/library/Icinga/File/CsvTest.php b/test/php/library/Icinga/File/CsvTest.php new file mode 100644 index 000000000..2dcf68870 --- /dev/null +++ b/test/php/library/Icinga/File/CsvTest.php @@ -0,0 +1,39 @@ + array( + array('col1' => 'val1', 'col2' => 'val2', 'col3' => 'val3', 'col4' => 'val4'), + array('col1' => 'val5', 'col2' => 'val6', 'col3' => 'val7', 'col4' => 'val8') + ) + ) + ); + $csv = Csv::fromQuery($queryMock); + + $this->assertEquals( + join( + "\r\n", + array( + 'col1,col2,col3,col4', + '"val1","val2","val3","val4"', + '"val5","val6","val7","val8"' + ) + ) . "\r\n", + (string) $csv, + 'Csv does not render valid/correct csv structured data' + ); + } +} diff --git a/test/php/library/Icinga/Filter/DomainTest.php b/test/php/library/Icinga/Filter/DomainTest.php index cad71700e..a48233866 100644 --- a/test/php/library/Icinga/Filter/DomainTest.php +++ b/test/php/library/Icinga/Filter/DomainTest.php @@ -1,30 +1,5 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} namespace Tests\Icinga\Filter; @@ -35,20 +10,8 @@ use Icinga\Filter\Type\TextFilter; use Icinga\Test\BaseTestCase; use Icinga\Filter\Domain; -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/QueryProposer.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/FilterAttribute.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/Domain.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/Query/Node.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/Type/FilterType.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/Type/TextFilter.php'); - -// @codingStandardsIgnoreEnd - class DomainTest extends BaseTestCase { - public function testDomainRecognitionInQueryString() { $domain = new Domain('host'); @@ -99,5 +62,4 @@ class DomainTest extends BaseTestCase $this->assertEquals($node->right, 'my host', 'Assert a domain to insert the value as the right side of a treenode'); $this->assertEquals($node->operator, Node::OPERATOR_EQUALS, 'Assert the correct operator to be set in a single query'); } - } \ No newline at end of file diff --git a/test/php/library/Icinga/Filter/FilterTest.php b/test/php/library/Icinga/Filter/FilterTest.php index 57cc1f22a..a002ec500 100644 --- a/test/php/library/Icinga/Filter/FilterTest.php +++ b/test/php/library/Icinga/Filter/FilterTest.php @@ -1,53 +1,14 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} - namespace Tests\Icinga\Filter; -use Icinga\Test\BaseTestCase; use Icinga\Filter\FilterAttribute; use Icinga\Filter\Filter; use Icinga\Filter\Type\TextFilter; use Icinga\Filter\Query\Node; - -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/QueryProposer.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/Filter.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/FilterAttribute.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/Domain.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/Query/Node.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/Query/Tree.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/Type/FilterType.php'); -require_once realpath(BaseTestCase::$libDir . '/Filter/Type/TextFilter.php'); - -// @codingStandardsIgnoreEnd +use Icinga\Test\BaseTestCase; class FilterTest extends BaseTestCase { @@ -77,7 +38,6 @@ class FilterTest extends BaseTestCase $searchEngine->getProposalsForQuery('Host name Is test and Hostname contains'), 'Assert only proposals for the last query part being made' ); - } public function testSingleQueryTreeCreation() @@ -245,7 +205,6 @@ class FilterTest extends BaseTestCase ->setHandledAttributes('attr5') ); - $query = 'attr1 is not \'Hans wurst\'' . ' or attr2 contains something ' . ' and attr3 starts with bla' @@ -298,5 +257,4 @@ class FilterTest extends BaseTestCase 'Assert the root->right->right->type node to be an OPERATOR (query :"' . $query . '")' ); } - } \ No newline at end of file diff --git a/test/php/library/Icinga/Filter/QueryHandlerTest.php b/test/php/library/Icinga/Filter/QueryHandlerTest.php index 6d4cd04a5..e17744d08 100644 --- a/test/php/library/Icinga/Filter/QueryHandlerTest.php +++ b/test/php/library/Icinga/Filter/QueryHandlerTest.php @@ -1,80 +1,33 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} - namespace Tests\Icinga\Filter; +use \Mockery; use Icinga\Filter\Query\Node; use Icinga\Filter\FilterAttribute; -use Icinga\Filter\Type\FilterType; use Icinga\Test\BaseTestCase; -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Query/Node.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/QueryProposer.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Domain.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/FilterAttribute.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Type/FilterType.php'); - -class TypeMock extends FilterType -{ - public function isValidQuery($query) - { - return true; - } - - public function createTreeNode($query, $leftOperand) - { - $node = new Node(); - $node->left = $leftOperand; - return $node; - } - - - public function getProposalsForQuery($query) - { - return $this->getOperators(); - } - - public function getOperators() - { - return array('op1', 'is better than', 'is worse than'); - } - -} - class QueryHandlerTest extends BaseTestCase { + public function setUp() + { + parent::setUp(); + $typeMock = Mockery::mock('Icinga\Filter\Type\FilterType'); + $typeMock->shouldReceive('isValidQuery')->with(Mockery::type('string'))->andReturn(true) + ->shouldReceive('getOperators')->andReturn(array('op1', 'is better than', 'is worse than')) + ->shouldReceive('getProposalsForQuery')->with(Mockery::type('string'))->andReturnUsing( + function ($query) use ($typeMock) { return $typeMock->getOperators(); } + )->shouldReceive('createTreeNode')->with(Mockery::type('string'), Mockery::any())->andReturnUsing( + function ($query, $leftOperand) { $node = new Node(); $node->left = $leftOperand; return $node; } + ); + $this->typeMock = $typeMock; + } + public function testQueryHandlerSetup() { - $handler = new FilterAttribute(new TypeMock()); + $handler = new FilterAttribute($this->typeMock); $handler->setField('current_status'); $handler->setHandledAttributes('State', 'Status', 'Current State'); $this->assertTrue( @@ -93,7 +46,7 @@ class QueryHandlerTest extends BaseTestCase public function testQueryProposal() { - $handler = new FilterAttribute(new TypeMock()); + $handler = new FilterAttribute($this->typeMock); $handler->setField('current_status'); $handler->setHandledAttributes('Status', 'State', 'Current State'); @@ -119,8 +72,7 @@ class QueryHandlerTest extends BaseTestCase public function testOperatorProposal() { - - $handler = new FilterAttribute(new TypeMock()); + $handler = new FilterAttribute($this->typeMock); $handler->setField('current_status') ->setHandledAttributes('status', 'state', 'current state'); $this->assertEquals( @@ -132,11 +84,10 @@ class QueryHandlerTest extends BaseTestCase public function testAttributeRecognition() { - $handler = new FilterAttribute(new TypeMock()); + $handler = new FilterAttribute($this->typeMock); $handler->setField('current_status') ->setHandledAttributes('status', 'state', 'current state'); $node = $handler->convertToTreeNode('status is not \’some kind of magic\''); $this->assertEquals($node->left, 'current_status', 'Assert status to be set to the field'); } - } \ No newline at end of file diff --git a/test/php/library/Icinga/Filter/Type/BooleanFilterTest.php b/test/php/library/Icinga/Filter/Type/BooleanFilterTest.php index 5ebdf3b84..27057b987 100644 --- a/test/php/library/Icinga/Filter/Type/BooleanFilterTest.php +++ b/test/php/library/Icinga/Filter/Type/BooleanFilterTest.php @@ -1,52 +1,15 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} - namespace Tests\Icinga\Filter; use Icinga\Filter\Type\BooleanFilter; -use Icinga\Filter\Type\TimeRangeSpecifier; use Icinga\Filter\Query\Node; use Icinga\Test\BaseTestCase; -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../../library/Icinga/Test/BaseTestCase.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Query/Node.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/QueryProposer.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Type/FilterType.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Type/BooleanFilter.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Type/TimeRangeSpecifier.php'); -// @codingStandardsIgnoreEnd - class BooleanFilterTest extends BaseTestCase { - public function testOperatorProposal() { $filter = new BooleanFilter(array()); @@ -124,7 +87,6 @@ class BooleanFilterTest extends BaseTestCase $this->assertEquals(Node::OPERATOR_EQUALS, $node->operator, 'Assert the operator to be equals'); $this->assertEquals(1, $node->right[0], 'Assert the value to be 1'); - $node = $filter->createTreeNode('is not with problem', 'host_status'); $this->assertEquals('host_problem', $node->left, 'Assert the left part of the node to be host_problem'); $this->assertEquals(Node::OPERATOR_EQUALS, $node->operator, 'Assert the operator to be equals'); @@ -149,6 +111,5 @@ class BooleanFilterTest extends BaseTestCase $this->assertEquals('host_problem', $node->right->left, 'Assert the right part of the node to be host_problem'); $this->assertEquals(Node::OPERATOR_EQUALS, $node->right->operator, 'Assert the operator to be equals'); $this->assertEquals(1, $node->right->right[0], 'Assert the value to be 1'); - } } \ No newline at end of file diff --git a/test/php/library/Icinga/Filter/Type/TextSearchTest.php b/test/php/library/Icinga/Filter/Type/TextSearchTest.php index 927f60bf5..07a7126d0 100644 --- a/test/php/library/Icinga/Filter/Type/TextSearchTest.php +++ b/test/php/library/Icinga/Filter/Type/TextSearchTest.php @@ -1,30 +1,5 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} namespace Tests\Icinga\Filter; @@ -33,14 +8,6 @@ use Icinga\Filter\Type\TextFilter; use Icinga\Filter\Query\Node; use Icinga\Test\BaseTestCase; -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../../library/Icinga/Test/BaseTestCase.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Query/Node.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/QueryProposer.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Type/FilterType.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Type/TextFilter.php'); -// @codingStandardsIgnoreEnd - class TextFilterTest extends BaseTestCase { public function testOperatorProposal() @@ -65,13 +32,11 @@ class TextFilterTest extends BaseTestCase ); } - public function testGetOperatorAndValueFromQuery() { $textFilter = new TextFilter(); list($operator, $value) = $textFilter->getOperatorAndValueFromQuery('is not \'something\''); $this->assertEquals(Node::OPERATOR_EQUALS_NOT, $operator, 'Asserting text operators to be split via TextFilter'); $this->assertEquals('something', $value, 'Asserting quoted values to be recognized in TextFilter'); - } } \ No newline at end of file diff --git a/test/php/library/Icinga/Filter/Type/TimeRangeSpecifierTest.php b/test/php/library/Icinga/Filter/Type/TimeRangeSpecifierTest.php index 08319e3e4..c9b813e12 100644 --- a/test/php/library/Icinga/Filter/Type/TimeRangeSpecifierTest.php +++ b/test/php/library/Icinga/Filter/Type/TimeRangeSpecifierTest.php @@ -1,46 +1,12 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} namespace Tests\Icinga\Filter; use Icinga\Filter\Type\TimeRangeSpecifier; -use Icinga\Filter\Query\Node; use Icinga\Test\BaseTestCase; -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../../library/Icinga/Test/BaseTestCase.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Query/Node.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/QueryProposer.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Type/FilterType.php'); -require_once realpath(BaseTestCase::$libDir .'/Filter/Type/TimeRangeSpecifier.php'); -// @codingStandardsIgnoreEnd - class TimeRangeSpecifierTest extends BaseTestCase { public function testIsValid() diff --git a/test/php/library/Icinga/LibraryLoader.php b/test/php/library/Icinga/LibraryLoader.php deleted file mode 100644 index 3173eed05..000000000 --- a/test/php/library/Icinga/LibraryLoader.php +++ /dev/null @@ -1,54 +0,0 @@ -target = tempnam(sys_get_temp_dir(), 'log'); + } + + public function tearDown() + { + parent::tearDown(); + + unlink($this->target); + } + + public function testWhetherStreamWriterCreatesMissingFiles() + { + new FileWriter(new Zend_Config(array('target' => $this->target))); + $this->assertFileExists($this->target, 'StreamWriter does not create missing files on initialization'); + } + + /** + * @depends testWhetherStreamWriterCreatesMissingFiles + */ + public function testWhetherStreamWriterWritesMessages() + { + $writer = new FileWriter(new Zend_Config(array('target' => $this->target))); + $writer->log(Logger::$ERROR, 'This is a test error'); + $log = file_get_contents($this->target); + $this->assertContains('This is a test error', $log, 'StreamWriter does not write log messages'); + } +} diff --git a/test/php/library/Icinga/Protocol/Commandpipe/CommandPipeLoader.php b/test/php/library/Icinga/Protocol/Commandpipe/CommandPipeLoader.php deleted file mode 100644 index cc4ba8c09..000000000 --- a/test/php/library/Icinga/Protocol/Commandpipe/CommandPipeLoader.php +++ /dev/null @@ -1,59 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Tests\Icinga\Protocol\Commandpipe; - -require_once('./library/Icinga/LibraryLoader.php'); - -use Test\Icinga\LibraryLoader; - -class CommandPipeLoader extends LibraryLoader { - - public static function requireLibrary() - { - require_once('Zend/Config.php'); - require_once('Zend/Log.php'); - require_once(realpath('../../library/Icinga/Application/Logger.php')); - require_once(realpath('../../library/Icinga/Protocol/Commandpipe/Command.php')); - require_once(realpath('../../library/Icinga/Protocol/Commandpipe/Comment.php')); - require_once(realpath('../../library/Icinga/Protocol/Commandpipe/CommandPipe.php')); - require_once(realpath('../../library/Icinga/Protocol/Commandpipe/PropertyModifier.php')); - require_once(realpath('../../library/Icinga/Protocol/Commandpipe/Exception/InvalidCommandException.php')); - require_once(realpath('../../library/Icinga/Protocol/Commandpipe/Transport/Transport.php')); - require_once(realpath('../../library/Icinga/Protocol/Commandpipe/Transport/SecureShell.php')); - require_once(realpath('../../library/Icinga/Protocol/Commandpipe/Transport/LocalPipe.php')); - require_once(realpath('../../modules/monitoring/library/Monitoring/Command/AcknowledgeCommand.php')); - require_once(realpath('../../modules/monitoring/library/Monitoring/Command/AddCommentCommand.php')); - require_once(realpath('../../modules/monitoring/library/Monitoring/Command/ScheduleDowntimeCommand.php')); - require_once(realpath('../../modules/monitoring/library/Monitoring/Command/CustomNotificationCommand.php')); - require_once(realpath('../../modules/monitoring/library/Monitoring/Command/DelayNotificationCommand.php')); - require_once(realpath('../../modules/monitoring/library/Monitoring/Command/ScheduleCheckCommand.php')); - require_once(realpath('../../modules/monitoring/library/Monitoring/Command/SubmitPassiveCheckresultCommand.php')); - } -} diff --git a/test/php/library/Icinga/Protocol/Commandpipe/CommandPipeTest.php b/test/php/library/Icinga/Protocol/Commandpipe/CommandPipeTest.php index 24bc716f5..b65e202c6 100644 --- a/test/php/library/Icinga/Protocol/Commandpipe/CommandPipeTest.php +++ b/test/php/library/Icinga/Protocol/Commandpipe/CommandPipeTest.php @@ -1,41 +1,13 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} namespace Tests\Icinga\Protocol\Commandpipe; -require_once(realpath(__DIR__ . '/CommandPipeLoader.php')); -CommandPipeLoader::requireLibrary(); - -use Zend_Config; -use PHPUnit_Framework_TestCase; +use \Zend_Config; +use Icinga\Test\BaseTestCase; use Icinga\Protocol\Commandpipe\Comment; -use Icinga\Protocol\Commandpipe\Commandpipe as Commandpipe; +use Icinga\Protocol\Commandpipe\CommandPipe; use Icinga\Protocol\Commandpipe\PropertyModifier as MONFLAG; use Icinga\Protocol\Ldap\Exception; use Icinga\Module\Monitoring\Command\AcknowledgeCommand; @@ -56,7 +28,7 @@ if (!defined('EXTCMD_TEST_BIN')) { * Uses the helper script extcmd_test, which is basically the extracted command * parser functions from the icinga core */ -class CommandPipeTest extends PHPUnit_Framework_TestCase +class CommandPipeTest extends BaseTestCase { /** * Return the path of the test pipe used in these tests @@ -71,7 +43,7 @@ class CommandPipeTest extends PHPUnit_Framework_TestCase /** * Return a @see Icinga\Protocal\CommandPipe\CommandPipe instance set up for the local test pipe * - * @return Commandpipe + * @return CommandPipe */ private function getLocalTestPipe() { @@ -86,14 +58,14 @@ class CommandPipeTest extends PHPUnit_Framework_TestCase ) ); - return new Commandpipe($cfg); + return new CommandPipe($cfg); } /** * Return a @see Icinga\Protocal\CommandPipe\CommandPipe instance set up * for the local test pipe, but with ssh as the transport layer * - * @return Commandpipe + * @return CommandPipe */ private function getSSHTestPipe() { @@ -112,7 +84,7 @@ class CommandPipeTest extends PHPUnit_Framework_TestCase ) ); - return new Commandpipe($cfg); + return new CommandPipe($cfg); } /** diff --git a/test/php/library/Icinga/Protocol/Ldap/QueryTest.php b/test/php/library/Icinga/Protocol/Ldap/QueryTest.php index c449243cb..0fa155202 100644 --- a/test/php/library/Icinga/Protocol/Ldap/QueryTest.php +++ b/test/php/library/Icinga/Protocol/Ldap/QueryTest.php @@ -1,20 +1,18 @@ 'localhost', 'root_dn' => 'dc=example,dc=com', @@ -23,7 +21,7 @@ class QueryTest extends \PHPUnit_Framework_TestCase ) ); - $connection = new \Icinga\Protocol\Ldap\Connection($config); + $connection = new Connection($config); return $connection->select(); } @@ -39,18 +37,6 @@ class QueryTest extends \PHPUnit_Framework_TestCase return $select; } - /** - * Test for Query::Count() - shall be tested with connection - * - **/ - public function testCount() - { - } - - /** - * Test for Query::Limit() - * - **/ public function testLimit() { $select = $this->prepareSelect(); @@ -58,10 +44,6 @@ class QueryTest extends \PHPUnit_Framework_TestCase $this->assertEquals(4, $select->getOffset()); } - /** - * Test for Query::HasLimit() - * - **/ public function testHasLimit() { $select = $this->emptySelect(); @@ -70,10 +52,6 @@ class QueryTest extends \PHPUnit_Framework_TestCase $this->assertTrue($select->hasLimit()); } - /** - * Test for Query::HasOffset() - * - **/ public function testHasOffset() { $select = $this->emptySelect(); @@ -82,99 +60,39 @@ class QueryTest extends \PHPUnit_Framework_TestCase $this->assertTrue($select->hasOffset()); } - /** - * Test for Query::GetLimit() - * - **/ public function testGetLimit() { $select = $this->prepareSelect(); $this->assertEquals(10, $select->getLimit()); } - /** - * Test for Query::GetOffset() - * - **/ public function testGetOffset() { $select = $this->prepareSelect(); $this->assertEquals(10, $select->getLimit()); } - /** - * Test for Query::FetchTree() - * - **/ public function testFetchTree() { $this->markTestIncomplete('testFetchTree is not implemented yet - requires real LDAP'); } - /** - * Test for Query::FetchAll() - shall be tested with connection - * - **/ - public function testFetchAll() - { - } - - /** - * Test for Query::FetchRow() - shall be tested with connection - * - **/ - public function testFetchRow() - { - } - - /** - * Test for Query::FetchOne() - * - **/ - public function testFetchOne() - { - } - - /** - * Test for Query::FetchPairs() - * - **/ - public function testFetchPairs() - { - } - - /** - * Test for Query::From() - * - **/ public function testFrom() { return $this->testListFields(); } - /** - * Test for Query::Where() - * - **/ public function testWhere() { $this->markTestIncomplete('testWhere is not implemented yet'); } - /** - * Test for Query::Order() - * - **/ public function testOrder() { $select = $this->emptySelect()->order('bla'); // tested by testGetSortColumns } - /** - * Test for Query::ListFields() - * - **/ public function testListFields() { $select = $this->prepareSelect(); @@ -184,10 +102,6 @@ class QueryTest extends \PHPUnit_Framework_TestCase ); } - /** - * Test for Query::GetSortColumns() - * - **/ public function testGetSortColumns() { $select = $this->prepareSelect(); @@ -195,31 +109,10 @@ class QueryTest extends \PHPUnit_Framework_TestCase $this->assertEquals('testIntColumn', $cols[0][0]); } - /** - * Test for Query::Paginate() - requires real result - * - **/ - public function testPaginate() - { - } - - /** - * Test for Query::__toString() - * - **/ public function test__toString() { $select = $this->prepareSelect(); $res = '(&(objectClass=dummyClass)(testIntColumn=1)(testStringColumn=test)(testWildcard=abc*))'; $this->assertEquals($res, (string) $select); } - - /** - * Test for Query::__destruct() - * - **/ - public function test__destruct() - { - } - } diff --git a/test/php/library/Icinga/Protocol/Statusdat/Component/StatusdatComponentTest.php b/test/php/library/Icinga/Protocol/Statusdat/Component/StatusdatComponentTest.php deleted file mode 100644 index 4c56f3881..000000000 --- a/test/php/library/Icinga/Protocol/Statusdat/Component/StatusdatComponentTest.php +++ /dev/null @@ -1,66 +0,0 @@ - dirname(__FILE__)."/status.dat", - "object_file" => dirname(__FILE__)."/objects.cache" - )),null,true); - return $reader; - } - - public function testServicegroupFilterFromService() { - $r = $this->getReader(); - $group = array(array('a1','b2')); - $result = $r->select()->from("services")->where("group IN ?",$group)->getResult(); - - $this->assertCount(9, $result, 'Assert items to be returned in a servicegroup filter'); - foreach($result as $obj) { - $this->assertTrue(is_object($obj)); - } - } - - public function testServicegroupFilterFromHost() { - $r = $this->getReader(); - $group = array(array('a1','b2')); - $result = $r->select()->from("hosts")->where("services.group IN ?",$group)->getResult(); - $this->assertCount(3, $result); - foreach($result as $obj) { - $this->assertTrue(is_object($obj)); - } - } - - public function testHostgroupFilterFromHost() { - $r = $this->getReader(); - $group = array(array('exc-hostb')); - $result = $r->select()->from("hosts")->where("group IN ?",$group)->getResult(); - $this->assertCount(3, $result); - foreach($result as $obj) { - $this->assertTrue(is_object($obj)); - } - } - - public function testHostgroupFilterFromService() { - $r = $this->getReader(); - $group = array(array('exc-hostb')); - $result = $r->select()->from("services")->where("host.group IN ?",$group)->getResult(); - - $this->assertCount(9, $result); - foreach($result as $obj) { - $this->assertTrue(is_object($obj)); - } - } -} diff --git a/test/php/library/Icinga/Protocol/Statusdat/Component/objects.cache b/test/php/library/Icinga/Protocol/Statusdat/Component/objects.cache deleted file mode 100644 index 7b61b25df..000000000 --- a/test/php/library/Icinga/Protocol/Statusdat/Component/objects.cache +++ /dev/null @@ -1,124 +0,0 @@ -define servicegroup { - servicegroup_name sv1 - alias testsv1 - members hosta,servicea1,hostb,serviceb1,hostc,servicec1 -} - -define servicegroup { - servicegroup_name a1 - alias testsa1 - members hosta,servicea1 -} - -define servicegroup { - servicegroup_name b2 - alias testsb2 - members hostb,serviceb2 -} - -define servicegroup { - servicegroup_name sv2 - alias testsv2 - members hosta,servicea2,hostb,serviceb2,hostc,servicec2 -} - -define hostgroup { - hostgroup_name all-hosts - alias All hosts - members hosta,hostb,hostc -} - -define hostgroup { - hostgroup_name exc-hostb - alias Excluded host b - members hosta,hostc -} - -define host { - host_name hosta - alias hosta - address 127.0.0.5 - parents hosta - check_period 24x7 - check_command check-host-alive - contact_groups admins - notification_period workhours -} - -define host { - host_name hostb - alias hostb - address 127.0.0.5 - parents hostb - check_period 24x7 - check_command check-host-alive - contact_groups admins - notification_period workhours -} - -define host { - host_name hostc - alias hostc - address 127.0.0.5 - parents hostc - check_period 24x7 - check_command check-host-alive - contact_groups admins - notification_period workhours -} - -define service { - host_name hosta - service_description servicea1 - check_period 24x7 - check_command check_icinga_startup_delay -} - -define service { - host_name hosta - service_description servicea2 - check_period 24x7 - check_command check_icinga_startup_delay -} -define service { - host_name hosta - service_description servicea3 - check_period 24x7 - check_command check_icinga_startup_delay -} -define service { - host_name hostb - service_description serviceb1 - check_period 24x7 - check_command check_icinga_startup_delay -} -define service { - host_name hostb - service_description serviceb2 - check_period 24x7 - check_command check_icinga_startup_delay -} -define service { - host_name hostb - service_description serviceb3 - check_period 24x7 - check_command check_icinga_startup_delay -} -define service { - host_name hostc - service_description servicec1 - check_period 24x7 - check_command check_icinga_startup_delay - } -define service { - host_name hostc - service_description servicec2 - check_period 24x7 - check_command check_icinga_startup_delay - } -define service { - host_name hostc - service_description servicec3 - check_period 24x7 - check_command check_icinga_startup_delay - } diff --git a/test/php/library/Icinga/Protocol/Statusdat/Component/status.dat b/test/php/library/Icinga/Protocol/Statusdat/Component/status.dat deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/php/library/Icinga/Protocol/Statusdat/Exceptions/ParsingException.php b/test/php/library/Icinga/Protocol/Statusdat/Exceptions/ParsingException.php deleted file mode 100644 index 392f979e2..000000000 --- a/test/php/library/Icinga/Protocol/Statusdat/Exceptions/ParsingException.php +++ /dev/null @@ -1,7 +0,0 @@ -getStringAsFileHandle(" -define hostescalation { - host_name\ttest - key\tvalue -} - -define host { - host_name\ttest - alias\ttest123 -} - -define host { - host_name\ttest2 - alias\ttest123 -} - -define service { - host_name\ttest - service_description\tCurrent Users -} - -define servicegroup { - servicegroup_name\tgroup - members\ttest,Current Users -} - "); - $testParser = new Parser($fd); - $testParser->parseObjectsFile(); - $state = $testParser->getRuntimeState(); - $this->assertTrue(is_array($state)); - $this->assertTrue(isset($state["host"])); - $this->assertTrue(isset($state["service"])); - $this->assertEquals("test",$state["host"]["test"]->host_name); - $this->assertTrue(is_array($state["host"]["test"]->escalation)); - $this->assertTrue(isset($state["service"]["test;Current Users"]->group)); - $this->assertTrue(is_array($state["service"]["test;Current Users"]->group)); - $this->assertCount(1,$state["service"]["test;Current Users"]->group); - $this->assertEquals("group",$state["service"]["test;Current Users"]->group[0]); - $this->assertEquals("value",$state["host"]["test"]->escalation[0]->key); - $this->assertEquals("test2",$state["host"]["test2"]->host_name); - } - - public function testRuntimeParsing() - { - $baseState = array( - "host" => array( - "test" => (object) array( - "host_name" => "test" - ), - "test2" => (object) array( - "host_name" => "test2" - ) - ), - "service" => array( - "test;Current Users" => (object) array( - "host_name" => "test", - "service_description" => "Current Users" - ) - ) - ); - $fd = $this->getStringAsFileHandle(self::RUNTIME_STATE1); - - $testParser = new Parser($fd, $baseState); - $testParser->parseRuntimeState(); - $state = $testParser->getRuntimeState(); - - $this->assertTrue(isset($state["host"]["test"]->status)); - $this->assertEquals(3,$state["host"]["test"]->status->current_state); - - $this->assertTrue(is_array($state["host"]["test"]->comment)); - $this->assertEquals(2,count($state["host"]["test"]->comment)); - } - - public function testOverwriteRuntime() - { - $baseState = array( - "host" => array( - "test" => (object) array( - "host_name" => "test" - ), - "test2" => (object) array( - "host_name" => "test2" - ) - ), - "service" => array( - "test;Current Users" => (object) array( - "host_name" => "test", - "service_description" => "Current Users" - ) - ) - ); - $fd = $this->getStringAsFileHandle(self::RUNTIME_STATE1); - - $testParser = new Parser($fd, $baseState); - $testParser->parseRuntimeState(); - $state = $testParser->getRuntimeState(); - - $this->assertTrue(isset($state["host"]["test"]->status)); - $this->assertEquals(3,$state["host"]["test"]->status->current_state); - - $this->assertTrue(is_array($state["host"]["test"]->comment)); - $this->assertEquals(2,count($state["host"]["test"]->comment)); - - $fd = $this->getStringAsFileHandle(self::RUNTIME_STATE2); - $testParser->parseRuntimeState($fd); - $state = $testParser->getRuntimeState(); - - $this->assertTrue(isset($state["host"]["test"]->status)); - $this->assertEquals(2,$state["host"]["test"]->status->current_state); - $this->assertTrue(is_array($state["host"]["test"]->comment)); - $this->assertEquals(3,count($state["host"]["test"]->comment)); - - } - - /** - * Assert no errors occuring - */ - public function testRuntimeParsingForBigFile() - { - //$this->markTestSkipped('Skipped slow tests'); - $objects = fopen("./res/status/icinga.objects.cache","r"); - $status = fopen("./res/status/icinga.status.dat","r"); - $testParser = new Parser($objects); - $testParser->parseObjectsFile(); - $testParser->parseRuntimeState($status); - } - - const RUNTIME_STATE1 = " - -hoststatus { - host_name=test - current_state=3 - test=test123 -} - -hoststatus { - host_name=test2 - current_state=3 - test=test123 -} - -servicestatus { - host_name=test - service_description=Current Users - current_state=3 -} - -hostcomment { - host_name=test - key=value1 -} - -hostcomment { - host_name=test - key=value2 -}"; - const RUNTIME_STATE2 = " - -hoststatus { - host_name=test - current_state=2 - test=test123 -} - -hoststatus { - host_name=test2 - current_state=2 - test=test123 -} - -servicestatus { - host_name=test - service_description=Current Users - current_state=2 -} - -hostcomment { - host_name=test - key=value14 -} -hostcomment { - host_name=test - key=value15 -} - -hostcomment { - host_name=test - key=value24 -}"; - -} diff --git a/test/php/library/Icinga/Protocol/Statusdat/Query/ExpressionTest.php b/test/php/library/Icinga/Protocol/Statusdat/Query/ExpressionTest.php deleted file mode 100644 index cdb845207..000000000 --- a/test/php/library/Icinga/Protocol/Statusdat/Query/ExpressionTest.php +++ /dev/null @@ -1,157 +0,0 @@ - ?" => "isGreater", - "expression >= ?" => "isGreaterEq", - "expression <= ?" => "isLessEq", - "expression < ?" => "isLess", - "expression = ?" => "isEqual", - "expression != ?" => "isNotEqual", - "expression like ?" => "isLike", - "expression IN ? " => "isIn" - ); - - foreach ($assertions as $query => $callback) { - $expression = new Expression(); - $value = array(10); - $expression->fromString($query, $value); - $this->assertCount(0, $value); - $this->assertEquals("expression", $expression->getField()); - $this->assertEquals($callback, $expression->CB); - } - } - - public function testNumericComparisons() - { - $assertions = array( // subarrays are (TEST,MATCHES) - "expression < ?" => array(5, array(1, 2, 3, 4)), - "expression <= ?" => array(5, array(1, 2, 3, 4, 5)), - "expression >= ?" => array(5, array(5, 6, 7)), - "expression > ?" => array(5, array(6, 7)), - "expression = ?" => array(5, array(5)), - "expression != ?" => array(5, array(1, 2, 3, 4, 6, 7)), - "expression IN ?" => array(array(1, 5, 7), array(1, 5, 7)) - ); - - foreach ($assertions as $query => $test) { - $expression = new Expression(); - - $value = array($test[0]); - $testArray = array( - (object)array("expression" => 1), - (object)array("expression" => 2), - (object)array("expression" => 3), - (object)array("expression" => 4), - (object)array("expression" => 5), - (object)array("expression" => 6), - (object)array("expression" => 7) - ); - $expression->fromString($query, $value); - $this->assertCount(0, $value); - $result = $expression->filter($testArray); - foreach ($result as $index) { - $this->assertContains($index + 1, $test[1]); - } - } - } - - public function testNestedComparison() - { - - $testArray = array( - (object)array( - "expression" => "atest", - "state" => (object)array("value" => 1) - ), - (object)array( - "expression" => "testa", - "state" => (object)array("value" => 2) - ) - - ); - $expression = new Expression(); - $value = array(1); - $expression->fromString("state.value > ?", $value); - $this->assertCount(0, $value); - - $result = $expression->filter($testArray); - $this->assertEquals(1, count($result)); - $this->assertEquals(2, $testArray[$result[1]]->state->value); - } - - public function testNestedComparisonInArray() - { - $testArray = array( - (object)array( - "expression" => "atest", - "state" => array((object) array("test"=>"1","test2"=>1)) - ), - (object)array( - "expression" => "testa", - "state" => array((object) array("test"=>"2","test2"=>2)) - ) - - ); - $expression = new Expression(); - $value = array(1); - $expression->fromString("state.test > ?", $value); - $this->assertCount(0, $value); - - $result = $expression->filter($testArray); - $this->assertEquals(1, count($result)); - - } - - public function testCountQuery() - { - $testArray = array( - (object)array( - "expression" => "atest", - "multiple" => array("test"=>"1","test2"=>1) - ), - (object)array( - "expression" => "testa", - "multiple" => array("test"=>"2","test2"=>2,"test5"=>2,"test1"=>2,"test3"=>2,"test4"=>2) - ) - ); - $expression = new Expression(); - $value = array(2); - $expression->fromString("COUNT{multiple} > ?", $value); - $this->assertCount(0, $value); - - $result = $expression->filter($testArray); - $this->assertEquals(1, count($result)); - } - - /** - * Test for Expression::Filter() - * - **/ - public function testFilter() - { - $this->markTestIncomplete('testFilter is not implemented yet'); - } - -} diff --git a/test/php/library/Icinga/Protocol/Statusdat/Query/GroupTest.php b/test/php/library/Icinga/Protocol/Statusdat/Query/GroupTest.php deleted file mode 100644 index f94f5ccd2..000000000 --- a/test/php/library/Icinga/Protocol/Statusdat/Query/GroupTest.php +++ /dev/null @@ -1,211 +0,0 @@ -value = array_shift($value); - $this->rawExpression = $expression; - - } - - public function filter(array &$base, &$idx = null) - { - return array_intersect(array_values($idx), array_values($this->filter)); - } - - /** - * Add additional information about the query this filter belongs to - * - * @param $query - * @return mixed - */ - public function setQuery($query) - { - // TODO: Implement setQuery() method. - } - - -} - -class GroupTest extends \PHPUnit_Framework_TestCase -{ - public function testParsingSingleCondition() - { - $testQuery = new Statusdat\Query\Group(); - $value = array(4); - $testQuery->fromString("numeric_val >= ?", $value, "Tests\Icinga\Protocol\Statusdat\Query\QueryExpressionMock"); - $this->assertCount(1, $testQuery->getItems()); - $this->assertCount(0, $value); - - $expression = $testQuery->getItems(); - $expression = $expression[0]; - - $this->assertEquals("numeric_val >= ?", $expression->rawExpression); - $this->assertEquals(4, $expression->value); - - } - - public function testParsingSimpleAndCondition() - { - $testQuery = new Statusdat\Query\Group(); - $value = array(4, 'hosta'); - $testQuery->fromString("numeric_val >= ? AND host_name = ?", $value, "Tests\Icinga\Protocol\Statusdat\Query\QueryExpressionMock"); - $this->assertCount(2, $testQuery->getItems()); - $this->assertCount(0, $value); - $this->assertEquals("AND", $testQuery->getType()); - $items = $testQuery->getItems(); - - $expression0 = $items[0]; - $this->assertEquals("numeric_val >= ?", $expression0->rawExpression); - $this->assertEquals(4, $expression0->value); - - $expression1 = $items[1]; - $this->assertEquals("host_name = ?", $expression1->rawExpression); - $this->assertEquals("hosta", $expression1->value); - } - - public function testParsingSimpleORCondition() - { - $testQuery = new Statusdat\Query\Group(); - $value = array(4, 'hosta'); - $testQuery->fromString("numeric_val >= ? OR host_name = ?", $value, "Tests\Icinga\Protocol\Statusdat\Query\QueryExpressionMock"); - $this->assertCount(2, $testQuery->getItems()); - $this->assertCount(0, $value); - $this->assertEquals("OR", $testQuery->getType()); - $items = $testQuery->getItems(); - - $expression0 = $items[0]; - $this->assertEquals("numeric_val >= ?", $expression0->rawExpression); - $this->assertEquals(4, $expression0->value); - - $expression1 = $items[1]; - $this->assertEquals("host_name = ?", $expression1->rawExpression); - $this->assertEquals("hosta", $expression1->value); - } - - public function testParsingExplicitSubgroup() - { - $testQuery = new Statusdat\Query\Group(); - $value = array(4, 'service1', 'hosta'); - $testQuery->fromString("numeric_val >= ? AND (service_description = ? OR host_name = ?)", $value, "Tests\Icinga\Protocol\Statusdat\Query\QueryExpressionMock"); - $this->assertCount(2, $testQuery->getItems()); - $this->assertCount(0, $value); - $this->assertEquals("AND", $testQuery->getType()); - $items = $testQuery->getItems(); - - $expression0 = $items[0]; - $this->assertEquals("numeric_val >= ?", $expression0->rawExpression); - $this->assertEquals(4, $expression0->value); - - $subgroup = $items[1]; - $this->assertInstanceOf("Icinga\Protocol\Statusdat\Query\Group", $subgroup); - $this->assertEquals("OR", $subgroup->getType()); - $orItems = $subgroup->getItems(); - - $expression1 = $orItems[0]; - $this->assertEquals("service_description = ?", $expression1->rawExpression); - $this->assertEquals("service1", $expression1->value); - - $expression2 = $orItems[1]; - $this->assertEquals("host_name = ?", $expression2->rawExpression); - $this->assertEquals("hosta", $expression2->value); - } - - public function testParsingImplicitSubgroup() - { - $testQuery = new Statusdat\Query\Group(); - $value = array(4, 'service1', 'hosta'); - $testQuery->fromString("numeric_val >= ? AND service_description = ? OR host_name = ?", $value, "Tests\Icinga\Protocol\Statusdat\Query\QueryExpressionMock"); - $this->assertCount(2, $testQuery->getItems()); - $this->assertCount(0, $value); - $this->assertEquals("AND", $testQuery->getType()); - $items = $testQuery->getItems(); - - $expression0 = $items[0]; - $this->assertEquals("numeric_val >= ?", $expression0->rawExpression); - $this->assertEquals(4, $expression0->value); - - $subgroup = $items[1]; - $this->assertInstanceOf("Icinga\Protocol\Statusdat\Query\Group", $subgroup); - $this->assertEquals("OR", $subgroup->getType()); - $orItems = $subgroup->getItems(); - - $expression1 = $orItems[0]; - $this->assertEquals("service_description = ?", $expression1->rawExpression); - $this->assertEquals("service1", $expression1->value); - - $expression2 = $orItems[1]; - $this->assertEquals("host_name = ?", $expression2->rawExpression); - $this->assertEquals("hosta", $expression2->value); - } - - public function testAndFilter() - { - $testQuery = new Statusdat\Query\Group(); - $testQuery->setType(Statusdat\Query\Group::TYPE_AND); - $exp1 = new QueryExpressionMock(); - $exp1->filter = array(1, 2, 3, 4, 5, 6, 8); - $exp2 = new QueryExpressionMock(); - $exp2->filter = array(3, 4, 8); - $base = array(0, 1, 2, 3, 4, 5, 6, 7, 8); - - $this->assertEquals(array(3, 4, 8), array_values($testQuery->addItem($exp1)->addItem($exp2)->filter($base))); - - } - - public function testOrFilter() - { - $testQuery = new Statusdat\Query\Group(); - $testQuery->setType(Statusdat\Query\Group::TYPE_OR); - $exp1 = new QueryExpressionMock(); - $exp1->filter = array(1, 2, 3); - $exp2 = new QueryExpressionMock(); - $exp2->filter = array(3, 4, 6, 8); - $base = array(0, 1, 2, 3, 4, 5, 6, 7, 8); - $this->assertEquals(array(1, 2, 3, 4, 6, 8), array_values($testQuery->addItem($exp1)->addItem($exp2)->filter($base))); - } - - public function testCombinedFilter() - { - $testQuery_and = new Statusdat\Query\Group(); - $testQuery_and->setType(Statusdat\Query\Group::TYPE_AND); - $testQuery_or = new Statusdat\Query\Group(); - $testQuery_or->setType(Statusdat\Query\Group::TYPE_OR); - $base = array(0, 1, 2, 3, 4, 5, 6, 7, 8); - - $and_exp1 = new QueryExpressionMock(); - $and_exp1->filter = array(1, 2, 3, 4, 5, 6, 8); - $and_exp2 = new QueryExpressionMock(); - $and_exp2->filter = array(3, 4, 8); - - $or_exp1 = new QueryExpressionMock(); - $or_exp1->filter = array(1, 2, 3); - $or_exp2 = new QueryExpressionMock(); - $or_exp2->filter = array(3, 4, 6, 8); - $this->assertEquals(array(3, 4, 8), array_values( - $testQuery_and - ->addItem($and_exp1) - ->addItem($and_exp2) - ->addItem($testQuery_or->addItem($or_exp1)->addItem($or_exp2)) - ->filter($base)) - ); - } -} - diff --git a/test/php/library/Icinga/Protocol/Statusdat/QueryTest.php b/test/php/library/Icinga/Protocol/Statusdat/QueryTest.php deleted file mode 100644 index fa283ea2c..000000000 --- a/test/php/library/Icinga/Protocol/Statusdat/QueryTest.php +++ /dev/null @@ -1,144 +0,0 @@ -getServiceTestReader(); - $query = new Statusdat\Query($readerMock); - $objects = $readerMock->getObjects(); - - $result = $query->select()->from("services")->getResult(); - $this->assertCount(count($objects["service"]), $result); - } - - public function testSimpleHostSelect() - { - $readerMock = $this->getServiceTestReader(); - $query = new Statusdat\Query($readerMock); - $objects = $readerMock->getObjects(); - - $result = $query->from("hosts")->getResult(); - $this->assertCount(count($objects["host"]), $result); - - } - - public function testLimit() - { - $readerMock = $this->getServiceTestReader(); - $objects = $readerMock->getObjects(); - $query = new Statusdat\Query($readerMock); - - $result = $query->from("services")->limit(2)->getResult(); - $this->assertCount(2, $result); - - } - - public function testOffset() - { - $readerMock = $this->getServiceTestReader(); - $objects = $readerMock->getObjects(); - $query = new Statusdat\Query($readerMock); - - $result = $query->from("services")->limit(2, 4)->getResult(); - $this->assertCount(2, $result); - - } - - public function testGroupByColumn() - { - $readerMock = $this->getServiceTestReader(); - $objects = $readerMock->getObjects(); - $query = new Statusdat\Query($readerMock); - $result = $query->from("services")->groupByColumns("numeric_val")->getResult(); - $this->assertCount(3,$result); - foreach($result as $value) { - $this->assertTrue(isset($value->count)); - $this->assertTrue(isset($value->columns)); - $this->assertEquals(2,$value->count); - } - - } - - public function testOrderedGroupByColumn() - { - $readerMock = $this->getServiceTestReader(); - $objects = $readerMock->getObjects(); - $query = new Statusdat\Query($readerMock); - $result = $query->from("services")->order('numeric_val ASC')->groupByColumns("numeric_val")->getResult(); - $this->assertCount(3,$result); - foreach($result as $sstatus) { - $this->assertTrue(isset($sstatus->count)); - $this->assertTrue(isset($sstatus->columns)); - $this->assertEquals(2, $sstatus->count); - - } - - } - - private function getServiceTestReader() - { - $readerMock = new ReaderMock(array( - "host" => array( - "hosta" => (object) array( - "host_name" => "hosta", - "numeric_val" => 0, - "services" => array(0, 1, 2) - ), - "hostb" => (object) array( - "host_name" => "hostb", - "numeric_val" => 0, - "services" => array(3, 4, 5) - ) - ), - "service" => array( - "hosta;service1" => (object) array( - "host_name" => "hosta", - "service_description" => "service1", - "numeric_val" => 1 - ), - "hosta;service2" => (object) array( - "host_name" => "hosta", - "service_description" => "service2", - "numeric_val" => 3 - ), - "hosta;service3" => (object) array( - "host_name" => "hosta", - "service_description" => "service3", - "numeric_val" => 2 - ), - "hostb;service1" => (object) array( - "host_name" => "hostb", - "service_description" => "service1", - "numeric_val" => 1 - ), - "hostb;service2" => (object) array( - "host_name" => "hostb", - "service_description" => "service2", - "numeric_val" => 3 - ), - "hostb;service3" => (object) array( - "host_name" => "hostb", - "service_description" => "service3", - "numeric_val" => 2 - ) - ) - )); - return $readerMock; - } -} diff --git a/test/php/library/Icinga/Protocol/Statusdat/ReaderMock.php b/test/php/library/Icinga/Protocol/Statusdat/ReaderMock.php deleted file mode 100644 index 32c842fa9..000000000 --- a/test/php/library/Icinga/Protocol/Statusdat/ReaderMock.php +++ /dev/null @@ -1,53 +0,0 @@ -objects = $objects; - } - - public function getState() - { - return $this->objects; - } - - public function getInternalState() - { - - return array( - "objects" => $this->objects, - "indices" => $this->indices - ); - } - - public function getObjects() - { - return $this->objects; - } - - public function __call($arg1,$arg2) { - return $this; - } - - public function select() - { - return $this; - } - - public function getObjectByName($type, $idx) - { - if (isset($this->objects[$type]) && isset($this->objects[$type][$idx])) - return $this->objects[$type][$idx]; - return null; - } - -} diff --git a/test/php/library/Icinga/Protocol/Statusdat/ReaderTest.php b/test/php/library/Icinga/Protocol/Statusdat/ReaderTest.php deleted file mode 100644 index ca055e312..000000000 --- a/test/php/library/Icinga/Protocol/Statusdat/ReaderTest.php +++ /dev/null @@ -1,104 +0,0 @@ - $val) { - $this->$key = $val; - } - } - - function get($attr) - { - return $this->$attr; - } -} - -class ParserMock -{ - - public $runtime = array(); - public $objects = array(); - - public function parseObjectsFile() - { - return $this->objects; - } - - public function parseRuntimeState() - { - return $this->runtime; - } - - public function getRuntimeState() - { - return $this->runtime; - } -} - -class ReaderTest extends \PHPUnit_Framework_TestCase -{ - protected function tearDown() - { - if (file_exists('./tmp')) { - @system("rm -rf ./tmp"); - } - } - - public function testFileCaching() - { - if (!file_exists('./tmp')) { - mkdir('./tmp'); - } - $parser = new ParserMock(); - $parser->runtime = array( - "host" => array( - "test" => (object)array( - "host_name" => "test" - ) - ) - ); - $object_file = tempnam("./dir", "object"); - $status_file = tempnam("./dir", "status"); - $reader = new Reader(new ConfigMock(array( - "cache_path" => "/tmp", - "object_file" => $object_file, - "status_file" => $status_file - )), $parser); - unlink($object_file); - unlink($status_file); - $this->assertTrue(file_exists("/tmp/zend_cache---object" . md5($object_file))); - $this->assertTrue(file_exists("/tmp/zend_cache---state" . md5($object_file))); - system("rm /tmp/zend_cache*"); - } - - public function testEmptyFileException() - { - - $this->setExpectedException("Icinga\Exception\ConfigurationError"); - $parser = new ParserMock(); - $reader = new Reader(new ConfigMock(array( - "cache_path" => "/tmp", - "object_file" => "", - "status_file" => "", - )), $parser); - } -} diff --git a/test/php/library/Icinga/Protocol/Statusdat/RuntimeStateContainerTest.php b/test/php/library/Icinga/Protocol/Statusdat/RuntimeStateContainerTest.php deleted file mode 100644 index 720bbfc1d..000000000 --- a/test/php/library/Icinga/Protocol/Statusdat/RuntimeStateContainerTest.php +++ /dev/null @@ -1,30 +0,0 @@ -test = "test123"; - $this->assertEquals("test host",$container->host_name); - $this->assertEquals($container->test,"test123"); - $this->assertEquals(0,$container->current_state); - - } - -} diff --git a/test/php/library/Icinga/Protocol/Statusdat/StatusdatTestLoader.php b/test/php/library/Icinga/Protocol/Statusdat/StatusdatTestLoader.php deleted file mode 100644 index 9244640d9..000000000 --- a/test/php/library/Icinga/Protocol/Statusdat/StatusdatTestLoader.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Tests\Icinga\Test; - -require_once 'Zend/Db/Adapter/Pdo/Mysql.php'; -require_once 'Zend/Db/Adapter/Pdo/Pgsql.php'; -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); - -use \PDO; -use \RuntimeException; -use Icinga\Test\BaseTestCase; - -class BaseTestCaseDbTest extends BaseTestCase -{ - private $emptySqlDumpFile; - - protected function tearDown() - { - if ($this->emptySqlDumpFile) { - unlink($this->emptySqlDumpFile); - } - } - - public function testExistingTestDirectories() - { - $this->assertFileExists(self::$appDir); - $this->assertFileExists(self::$libDir); - $this->assertFileExists(self::$etcDir); - $this->assertFileExists(self::$testDir); - $this->assertFileExists(self::$moduleDir); - // $this->assertFileExists(self::$shareDir); - } - - /** - * @dataProvider mysqlDb - */ - public function testMySqlProviderAnnotation($resource) - { - $this->setupDbProvider($resource); - $this->assertInstanceOf('Zend_Db_Adapter_Pdo_Mysql', $resource); - } - - /** - * @dataProvider mysqlDb - */ - public function testMySqlCreateTablePart1($resource) - { - $this->setupDbProvider($resource); - /** @var \Zend_Db_Adapter_Pdo_Abstract $resource **/ - $resource->exec('CREATE TABLE test(uid INT NOT NULL PRIMARY KEY);'); - - $tables = $resource->listTables(); - $this->assertCount(1, $tables); - } - - /** - * @dataProvider mysqlDb - */ - public function testMySqlCreateTablePart2($resource) - { - $this->setupDbProvider($resource); - $tables = $resource->listTables(); - $this->assertCount(0, $tables); - } - - private function dbAdapterSqlLoadTable($resource) - { - /** @var $resource \Zend_Db_Adapter_Pdo_Abstract **/ - $this->setupDbProvider($resource); - - $sqlContent = array(); - $sqlContent[] = 'CREATE TABLE dummyData(value VARCHAR(50) NOT NULL PRIMARY KEY);'; - for ($i=0; $i<20; $i++) { - $sqlContent[] = 'INSERT INTO dummyData VALUES(\'' . uniqid(). '\');'; - } - - $tempFile = tempnam(sys_get_temp_dir(), 'icinga2-web-test-load-sql'); - file_put_contents($tempFile, implode(chr(10), $sqlContent)); - - $this->loadSql($resource, $tempFile); - - $count = (int)$resource->fetchOne('SELECT COUNT(*) as cntX from dummyData;'); - $this->assertSame(20, $count); - - $this->assertTrue(unlink($tempFile)); - } - - /** - * @dataProvider mysqlDb - */ - public function testMySqlLoadTable($resource) - { - $this->dbAdapterSqlLoadTable($resource); - } - - /** - * @dataProvider pgsqlDb - */ - public function testPgSqlProviderAnnotation($resource) - { - $this->setupDbProvider($resource); - $this->assertInstanceOf('Zend_Db_Adapter_Pdo_Pgsql', $resource); - } - - /** - * @dataProvider pgsqlDb - */ - public function testPgSqlCreateTablePart1($resource) - { - $this->setupDbProvider($resource); - /** @var \Zend_Db_Adapter_Pdo_Abstract $resource **/ - $resource->exec('CREATE TABLE test(uid INT NOT NULL PRIMARY KEY);'); - - $tables = $resource->listTables(); - $this->assertCount(1, $tables); - } - - /** - * @dataProvider pgsqlDb - */ - public function testPgSqlCreateTablePart2($resource) - { - $this->setupDbProvider($resource); - $tables = $resource->listTables(); - $this->assertCount(0, $tables); - } - - /** - * @dataProvider pgsqlDb - */ - public function testPgSqlLoadTable($resource) - { - $this->dbAdapterSqlLoadTable($resource); - } - - /** - * @dataProvider mysqlDb - */ - public function testNotExistSqlDumpFile($resource) - { - $this->setupDbProvider($resource); - - $this->setExpectedException( - 'RuntimeException', - 'Sql file not found: /does/not/exist1238837 (test=testNotExistSqlDumpFile with data set #0)' - ); - - $this->loadSql($resource, '/does/not/exist1238837'); - } - - /** - * @dataProvider mysqlDb - */ - public function testDumpFileIsEmpty($resource) - { - $this->setupDbProvider($resource); - $this->emptySqlDumpFile = tempnam(sys_get_temp_dir(), 'icinga2-web-db-test-empty'); - $this->assertFileExists($this->emptySqlDumpFile); - - $expectedMessage = 'Sql file is empty: ' - . $this->emptySqlDumpFile - . ' (test=testDumpFileIsEmpty with data set #0)'; - - $this->setExpectedException( - 'RuntimeException', - $expectedMessage - ); - - $this->loadSql($resource, $this->emptySqlDumpFile); - - } -} diff --git a/test/php/library/Icinga/Test/BaseTestCaseTest.php b/test/php/library/Icinga/Test/BaseTestCaseTest.php new file mode 100644 index 000000000..043d3c839 --- /dev/null +++ b/test/php/library/Icinga/Test/BaseTestCaseTest.php @@ -0,0 +1,187 @@ +emptySqlDumpFile) { + unlink($this->emptySqlDumpFile); + } + } + + /** + * @dataProvider mysqlDb + */ + public function testWhetherMySqlProviderAnnotationSetsUpZendDbAdapter($resource) + { + $this->setupDbProvider($resource); + $this->assertInstanceOf('Zend_Db_Adapter_Pdo_Mysql', $resource->getConnection()); + } + + /** + * @dataProvider mysqlDb + */ + public function testWhetherMySqlAdapterWorks($resource) + { + $this->setupDbProvider($resource); + $this->dbAdapterSqlLoadTable($resource); + } + + /** + * @dataProvider mysqlDb + */ + public function testWhetherCreatingTablesWithMySqlAdapterWorks($resource) + { + $this->setupDbProvider($resource); + $adapter = $resource->getConnection(); + $adapter->exec('CREATE TABLE test(uid INT NOT NULL PRIMARY KEY);'); + + $tables = $adapter->listTables(); + $this->assertCount(1, $tables); + } + + /** + * @dataProvider mysqlDb + * @depends testWhetherCreatingTablesWithMySqlAdapterWorks + */ + public function testWhetherSetupDbProviderCleansUpMySqlAdapter($resource) + { + $this->setupDbProvider($resource); + + $tables = $resource->getConnection()->listTables(); + $this->assertCount(0, $tables); + } + + /** + * @dataProvider pgsqlDb + */ + public function testWhetherPgSqlProviderAnnotationSetsUpZendDbAdapter($resource) + { + $this->setupDbProvider($resource); + $this->assertInstanceOf('Zend_Db_Adapter_Pdo_Pgsql', $resource->getConnection()); + } + + /** + * @dataProvider pgsqlDb + */ + public function testWhetherPgSqlAdapterWorks($resource) + { + $this->setupDbProvider($resource); + $this->dbAdapterSqlLoadTable($resource); + } + + /** + * @dataProvider pgsqlDb + */ + public function testWhetherCreatingTablesWithPgSqlAdapterWorks($resource) + { + $this->setupDbProvider($resource); + $adapter = $resource->getConnection(); + $adapter->exec('CREATE TABLE test(uid INT NOT NULL PRIMARY KEY);'); + + $tables = $adapter->listTables(); + $this->assertCount(1, $tables); + } + + /** + * @dataProvider pgsqlDb + * @depends testWhetherCreatingTablesWithPgSqlAdapterWorks + */ + public function testWhetherSetupDbProviderCleansUpPgSqlAdapter($resource) + { + $this->setupDbProvider($resource); + + $tables = $resource->getConnection()->listTables(); + $this->assertCount(0, $tables); + } + + /** + * @dataProvider oracleDb + */ + public function testWhetherOciProviderAnnotationSetsUpZendDbAdapter($resource) + { + $this->setupDbProvider($resource); + $this->assertInstanceOf('Zend_Db_Adapter_Pdo_Oci', $resource->getConnection()); + } + + /** + * @dataProvider oracleDb + */ + public function testWhetherOciAdapterWorks($resource) + { + $this->setupDbProvider($resource); + $this->dbAdapterSqlLoadTable($resource); + } + + /** + * @dataProvider oracleDb + */ + public function testWhetherCreatingTablesWithOciAdapterWorks($resource) + { + $this->setupDbProvider($resource); + $adapter = $resource->getConnection(); + $adapter->exec('CREATE TABLE test(uid INT NOT NULL PRIMARY KEY);'); + + $tables = $adapter->listTables(); + $this->assertCount(1, $tables); + } + + /** + * @dataProvider oracleDb + * @depends testWhetherCreatingTablesWithOciAdapterWorks + */ + public function testWhetherSetupDbProviderCleansUpOciAdapter($resource) + { + $this->setupDbProvider($resource); + + $tables = $resource->getConnection()->listTables(); + $this->assertCount(0, $tables); + } + + /** + * @expectedException RuntimeException + */ + public function testWhetherLoadSqlThrowsErrorWhenFileMissing() + { + $this->loadSql(Mockery::mock('Icinga\Data\Db\Connection'), 'not_existing'); + } + + /** + * @expectedException RuntimeException + */ + public function testWhetherLoadSqlThrowsErrorWhenFileEmpty() + { + $this->emptySqlDumpFile = tempnam(sys_get_temp_dir(), 'icinga2-web-db-test-empty'); + $this->loadSql(Mockery::mock('Icinga\Data\Db\Connection'), $this->emptySqlDumpFile); + } + + protected function dbAdapterSqlLoadTable($resource) + { + $sqlContent = array(); + $sqlContent[] = 'CREATE TABLE dummyData(value VARCHAR(50) NOT NULL PRIMARY KEY);'; + for ($i=0; $i<20; $i++) { + $sqlContent[] = 'INSERT INTO dummyData VALUES(\'' . uniqid(). '\');'; + } + + $tempFile = tempnam(sys_get_temp_dir(), 'icinga2-web-test-load-sql'); + file_put_contents($tempFile, implode(PHP_EOL, $sqlContent)); + + $this->loadSql($resource, $tempFile); + + $count = (int) $resource->getConnection()->fetchOne('SELECT COUNT(*) as cntX from dummyData;'); + $this->assertSame(20, $count); + + $this->assertTrue(unlink($tempFile)); + } +} diff --git a/test/php/library/Icinga/User/PreferencesTest.php b/test/php/library/Icinga/User/PreferencesTest.php new file mode 100644 index 000000000..da5c318fa --- /dev/null +++ b/test/php/library/Icinga/User/PreferencesTest.php @@ -0,0 +1,47 @@ +key = 'value'; + $this->assertTrue(isset($prefs->key)); + $this->assertEquals('value', $prefs->key); + } + + public function testWhetherPreferencesCanBeAccessed() + { + $prefs = new Preferences(array('key' => 'value')); + + $this->assertTrue($prefs->has('key')); + $this->assertEquals('value', $prefs->get('key')); + } + + public function testWhetherPreferencesCanBeRemoved() + { + $prefs = new Preferences(array('key' => 'value')); + + unset($prefs->key); + $this->assertFalse(isset($prefs->key)); + + $prefs->key = 'value'; + $prefs->remove('key'); + $this->assertFalse($prefs->has('key')); + } + + public function testWhetherPreferencesAreCountable() + { + $prefs = new Preferences(array('key1' => '1', 'key2' => '2')); + + $this->assertEquals(2, count($prefs)); + } +} diff --git a/test/php/library/Icinga/User/Store/DbStoreTest.php b/test/php/library/Icinga/User/Store/DbStoreTest.php new file mode 100644 index 000000000..6af17bcba --- /dev/null +++ b/test/php/library/Icinga/User/Store/DbStoreTest.php @@ -0,0 +1,176 @@ +insertions[$row[DbStore::COLUMN_PREFERENCE]] = $row[DbStore::COLUMN_VALUE]; + } + + public function update($table, $columns, $where) + { + $this->updates[$where[DbStore::COLUMN_PREFERENCE . '=?']] = $columns[DbStore::COLUMN_VALUE]; + } + + public function delete($table, $where) + { + $this->deletions = array_merge( + $this->deletions, + $where[DbStore::COLUMN_PREFERENCE . ' IN (?)'] + ); + } +} + +class FaultyDatabaseMock extends DatabaseMock +{ + public function insert($table, $row) + { + throw new Exception(); + } + + public function update($table, $columns, $where) + { + throw new Exception(); + } + + public function delete($table, $where) + { + throw new Exception(); + } +} + +class DbStoreWithSetPreferences extends DbStore +{ + public function setPreferences(array $preferences) + { + $this->preferences = $preferences; + } +} + +class DbStoreTest extends BaseTestCase +{ + public function testWhetherPreferenceInsertionWorks() + { + $dbMock = new DatabaseMock(); + $store = $this->getStore($dbMock); + $store->save( + Mockery::mock( + 'Icinga\User\Preferences', + array('toArray' => array('key' => 'value')) + ) + ); + + $this->assertArrayHasKey('key', $dbMock->insertions, 'DbStore::save does not insert new preferences'); + $this->assertEmpty($dbMock->updates, 'DbStore::save updates *new* preferences'); + $this->assertEmpty($dbMock->deletions, 'DbStore::save deletes *new* preferences'); + } + + /** + * @expectedException Icinga\Exception\NotWritableError + */ + public function testWhetherPreferenceInsertionThrowsNotWritableError() + { + $store = $this->getStore(new FaultyDatabaseMock()); + $store->save( + Mockery::mock( + 'Icinga\User\Preferences', + array('toArray' => array('key' => 'value')) + ) + ); + } + + public function testWhetherPreferenceUpdatesWork() + { + $dbMock = new DatabaseMock(); + $store = $this->getStore($dbMock); + $store->setPreferences(array('key' => 'value')); + $store->save( + Mockery::mock( + 'Icinga\User\Preferences', + array('toArray' => array('key' => 'eulav')) + ) + ); + + $this->assertArrayHasKey('key', $dbMock->updates, 'DbStore::save does not update existing preferences'); + $this->assertEmpty($dbMock->insertions, 'DbStore::save inserts *existing* preferences'); + $this->assertEmpty($dbMock->deletions, 'DbStore::save inserts *existing* preferneces'); + } + + /** + * @expectedException Icinga\Exception\NotWritableError + */ + public function testWhetherPreferenceUpdatesThrowNotWritableError() + { + $store = $this->getStore(new FaultyDatabaseMock()); + $store->setPreferences(array('key' => 'value')); + $store->save( + Mockery::mock( + 'Icinga\User\Preferences', + array('toArray' => array('key' => 'eulav')) + ) + ); + } + + public function testWhetherPreferenceDeletionWorks() + { + $dbMock = new DatabaseMock(); + $store = $this->getStore($dbMock); + $store->setPreferences(array('key' => 'value')); + $store->save( + Mockery::mock( + 'Icinga\User\Preferences', + array('toArray' => array()) + ) + ); + + $this->assertContains('key', $dbMock->deletions, 'DbStore::save does not delete removed preferences'); + $this->assertEmpty($dbMock->insertions, 'DbStore::save inserts *removed* preferences'); + $this->assertEmpty($dbMock->updates, 'DbStore::save updates *removed* preferences'); + } + + /** + * @expectedException Icinga\Exception\NotWritableError + */ + public function testWhetherPreferenceDeletionThrowsNotWritableError() + { + $store = $this->getStore(new FaultyDatabaseMock()); + $store->setPreferences(array('key' => 'value')); + $store->save( + Mockery::mock( + 'Icinga\User\Preferences', + array('toArray' => array()) + ) + ); + } + + protected function getStore($dbMock) + { + return new DbStoreWithSetPreferences( + new Zend_Config( + array( + 'connection' => Mockery::mock(array('getConnection' => $dbMock)) + ) + ), + Mockery::mock('Icinga\User', array('getUsername' => 'unittest')) + ); + } +} diff --git a/test/php/library/Icinga/User/Store/IniStoreTest.php b/test/php/library/Icinga/User/Store/IniStoreTest.php new file mode 100644 index 000000000..d6637d2f2 --- /dev/null +++ b/test/php/library/Icinga/User/Store/IniStoreTest.php @@ -0,0 +1,67 @@ +preferences = $preferences; + } + + public function getPreferences() + { + return $this->preferences; + } +} + +class IniStoreTest extends BaseTestCase +{ + public function testWhetherPreferenceChangesAreApplied() + { + $store = $this->getStore(); + $store->setPreferences(array('key1' => '1')); + + $store->save( + Mockery::mock('Icinga\User\Preferences', array('toArray' => array('key1' => '11', 'key2' => '2'))) + ); + $this->assertEquals( + array('key1' => '11', 'key2' => '2'), + $store->getPreferences(), + 'IniStore::save does not properly apply changed preferences' + ); + } + + public function testWhetherPreferenceDeletionsAreApplied() + { + $store = $this->getStore(); + $store->setPreferences(array('key' => 'value')); + + $store->save(Mockery::mock('Icinga\User\Preferences', array('toArray' => array()))); + $this->assertEmpty($store->getPreferences(), 'IniStore::save does not delete removed preferences'); + } + + protected function getStore() + { + return new IniStoreWithSetGetPreferencesAndEmptyWrite( + new Zend_Config( + array( + 'location' => 'some/Path/To/Some/Directory' + ) + ), + Mockery::mock('Icinga\User', array('getUsername' => 'unittest')) + ); + } +} diff --git a/test/php/library/Icinga/UserTest.php b/test/php/library/Icinga/UserTest.php index ec27a3381..ebb39293e 100644 --- a/test/php/library/Icinga/UserTest.php +++ b/test/php/library/Icinga/UserTest.php @@ -1,73 +1,63 @@ markTestIncomplete('testListGroups is not implemented yet'); - } - - public function testIsMemberOf() - { - $this->markTestIncomplete('testIsMemberOf is not implemented yet'); - } - - public function testGetPermissionList() - { - $this->markTestIncomplete('testGetPermissionList is not implemented yet'); - } - - public function testHasPermission() - { - $this->markTestIncomplete('testHasPermission is not implemented yet'); - } - - public function testGrantPermission() - { - $this->markTestIncomplete('testGrantPermission is not implemented yet'); - } - - public function testRevokePermission() - { - $this->markTestIncomplete('testRevokePermission is not implemented yet'); - } - public function testGetDefaultTimezoneIfTimezoneNotSet() { - $defaultTz = 'UTC'; - date_default_timezone_set($defaultTz); - $user = new IcingaUser('unittest'); - $prefs = new UserPreferences(array()); + $user = new User('unittest'); + $prefs = Mockery::mock('Icinga\User\Preferences'); + $prefs->shouldReceive('get')->with('timezone')->andReturnNull(); $user->setPreferences($prefs); - $this->assertEquals($user->getTimeZone(), new DateTimeZone($defaultTz), + + $this->assertEquals( + new DateTimeZone(date_default_timezone_get()), + $user->getTimeZone(), 'User\'s timezone does not match the default timezone' ); } public function testGetTimezoneIfTimezoneSet() { - $defaultTz = 'UTC'; $explicitTz = 'Europe/Berlin'; - date_default_timezone_set($defaultTz); - $user = new IcingaUser('unittest'); - $prefs = new UserPreferences(array( - 'timezone' => $explicitTz - )); + $user = new User('unittest'); + $prefs = Mockery::mock('Icinga\User\Preferences'); + $prefs->shouldReceive('get')->with('timezone')->andReturn($explicitTz); $user->setPreferences($prefs); - $this->assertEquals($user->getTimeZone(), new DateTimeZone($explicitTz), + $this->assertEquals( + new DateTimeZone($explicitTz), + $user->getTimeZone(), 'User\'s timezone does not match the timezone set by himself' ); } + public function testWhetherValidEmailsCanBeSet() + { + $user = new User('unittest'); + $user->setEmail('mySampleEmail@someDomain.org'); + + $this->assertEquals( + $user->getEmail(), + 'mySampleEmail@someDomain.org', + 'Valid emails set with setEmail are not returned by getEmail' + ); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testWhetherInvalidEmailsCannotBeSet() + { + $user = new User('unittest'); + $user->setEmail('mySampleEmail at someDomain dot org'); + } } diff --git a/test/php/library/Icinga/Util/DateTimeFactoryTest.php b/test/php/library/Icinga/Util/DateTimeFactoryTest.php new file mode 100644 index 000000000..1b7778587 --- /dev/null +++ b/test/php/library/Icinga/Util/DateTimeFactoryTest.php @@ -0,0 +1,70 @@ + 'invalid')); + } + + public function testWhetherParseWorksWithASpecificTimezone() + { + $dt = DateTimeFactory::parse('17-04-14 17:00', 'd-m-y H:i', new DateTimeZone('Europe/Berlin')); + $dt->setTimezone(new DateTimeZone('UTC')); + + $this->assertEquals( + '15', + $dt->format('H'), + 'DateTimeFactory::parse does not properly parse a given datetime or does not respect the given timezone' + ); + } + + public function testWhetherParseWorksWithoutASpecificTimezone() + { + $this->assertEquals( + '15', + DateTimeFactory::parse('17-04-14 15:00', 'd-m-y H:i')->format('H'), + 'DateTimeFactory::parse does not properly parse a given datetime' + ); + } + + public function testWhetherCreateWorksWithASpecificTimezone() + { + $dt = DateTimeFactory::create('2014-04-17 5PM', new DateTimeZone('Europe/Berlin')); + $dt->setTimezone(new DateTimeZone('UTC')); + + $this->assertEquals( + '15', + $dt->format('H'), + 'DateTimeFactory::create does not properly parse a given datetime or does not respect the given timezone' + ); + } + + public function testWhetherCreateWorksWithoutASpecificTimezone() + { + $this->assertEquals( + '15', + DateTimeFactory::create('2014-04-17 3PM')->format('H'), + 'DateTimeFactory::create does not properly parse a given datetime' + ); + } +} diff --git a/test/php/library/Icinga/Util/DimensionTest.php b/test/php/library/Icinga/Util/DimensionTest.php index dc0fe17e3..d6678258f 100644 --- a/test/php/library/Icinga/Util/DimensionTest.php +++ b/test/php/library/Icinga/Util/DimensionTest.php @@ -1,20 +1,14 @@ assertEquals(Dimension::UNIT_PT, $d->getUnit(), "Asserting the unit of pt input to be correctly parsed"); } - /** - * Test string creation from Dimension - * - */ public function testStringCreation() { $d = new Dimension(1000, Dimension::UNIT_PX); @@ -47,9 +37,6 @@ class DimensionTest extends \PHPUnit_Framework_TestCase { $this->assertEquals("40pt", (string) $d, "Asserting float values being truncated by now"); } - /** - * - */ public function testInvalidDimensions() { $d = new Dimension(-20, Dimension::UNIT_PX); diff --git a/test/php/library/Icinga/Util/StringTest.php b/test/php/library/Icinga/Util/StringTest.php new file mode 100644 index 000000000..8ecf61edc --- /dev/null +++ b/test/php/library/Icinga/Util/StringTest.php @@ -0,0 +1,29 @@ +assertEquals( + array('one', 'two', 'three'), + String::trimSplit(' one ,two , three'), + 'String::trimSplit does not properly split a string and/or trim its elements' + ); + } + + public function testWhetherTrimSplitSplitsByTheGivenDelimiter() + { + $this->assertEquals( + array('one', 'two', 'three'), + String::trimSplit('one.two.three', '.'), + 'String::trimSplit does not split a string by the given delimiter' + ); + } +} diff --git a/test/php/library/Icinga/Util/TranslatorTest.php b/test/php/library/Icinga/Util/TranslatorTest.php new file mode 100644 index 000000000..0610ba87c --- /dev/null +++ b/test/php/library/Icinga/Util/TranslatorTest.php @@ -0,0 +1,78 @@ +assertEquals( + array('de_DE', 'fr_FR'), + Translator::getAvailableLocaleCodes(), + 'Translator::getAvailableLocaleCodes does not return all available locale codes' + ); + } + + public function testWhetherSetupLocaleSetsUpTheGivenLocale() + { + Translator::setupLocale('de_DE'); + $this->assertContains( + setlocale(LC_ALL, 0), + array('de_DE', 'de_DE.UTF-8'), + 'Translator::setupLocale does not properly set up a given locale' + ); + } + + /** + * @expectedException \Exception + */ + public function testWhetherSetupLocaleThrowsAnExceptionWhenGivenAnInvalidLocale() + { + Translator::setupLocale('foobar'); + } + + public function testWhetherSetupLocaleSetsCAsLocaleWhenGivenAnInvalidLocale() + { + try { + Translator::setupLocale('foobar'); + $this->fail('Translator::setupLocale does not throw an exception when given an invalid locale'); + } catch (Exception $e) { + $this->assertEquals( + 'C', + setlocale(LC_ALL, 0), + 'Translator::setupLocale does not set C as locale in case the given one is invalid' + ); + } + } + + public function testWhetherTranslateReturnsTheCorrectMessageForTheCurrentLocale() + { + Translator::setupLocale('de_DE'); + + $this->assertEquals( + 'Lorem ipsum dolor sit amet!', + Translator::translate('Lorem ipsum dolor sit amet', 'icingatest'), + 'Translator::translate does not translate the given message correctly to German' + ); + + Translator::setupLocale('fr_FR'); + + $this->assertEquals( + 'Lorem ipsum dolor sit amet?', + Translator::translate('Lorem ipsum dolor sit amet', 'icingatest'), + 'Translator::translate does not translate the given message correctly to French' + ); + } +} diff --git a/test/php/library/Icinga/Web/Form/Element/DateTimePickerTest.php b/test/php/library/Icinga/Web/Form/Element/DateTimePickerTest.php index 5d35a5de0..7610803b2 100644 --- a/test/php/library/Icinga/Web/Form/Element/DateTimePickerTest.php +++ b/test/php/library/Icinga/Web/Form/Element/DateTimePickerTest.php @@ -1,43 +1,20 @@ new DateTimeZone('UTC'))); - $dt = new DateTimePicker( 'foo', array( @@ -73,15 +50,9 @@ class DateTimeTest extends BaseTestCase /** * Test that DateTimePicker::isValid() returns true if the input is valid in terms of being a date/time string * or a timestamp - * - * Utilizes singleton DateTimeFactory - * - * @backupStaticAttributes enabled */ public function testValidateValidInput() { - DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC'))); - $dt = new DateTimePicker( 'foo', array( @@ -112,15 +83,9 @@ class DateTimeTest extends BaseTestCase /** * Test that DateTimePicker::getValue() returns a timestamp after a successful call to isValid - * - * Utilizes singleton DateTimeFactory - * - * @backupStaticAttributes enabled */ public function testGetValueReturnsUnixTimestampAfterSuccessfulIsValidCall() { - DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC'))); - $dt = new DateTimePicker( 'foo', array( @@ -137,33 +102,4 @@ class DateTimeTest extends BaseTestCase 'getValue did not return the correct Unix timestamp according to the given date/time string' ); } - - /** - * Test that DateTimePicker::getValue() returns a timestamp respecting - * the given non-UTC time zone after a successful call to isValid - * - * Utilizes singleton DateTimeFactory - * - * @backupStaticAttributes enabled - */ - public function testGetValueIsTimeZoneAware() - { - DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('Europe/Berlin'))); - - $dt = new DateTimePicker( - 'foo', - array( - 'patterns' => array( - 'd.m.Y H:i:s' - ) - ) - ); - $dt->isValid('12.07.2013 08:03:43'); - - $this->assertEquals( - 1373609023, - $dt->getValue(), - 'getValue did not return the correct Unix timestamp according to the given date/time string and time zone' - ); - } } diff --git a/test/php/library/Icinga/Web/Form/Validator/DateFormatValidatorTest.php b/test/php/library/Icinga/Web/Form/Validator/DateFormatValidatorTest.php index 23c3fb3a3..0153412e5 100644 --- a/test/php/library/Icinga/Web/Form/Validator/DateFormatValidatorTest.php +++ b/test/php/library/Icinga/Web/Form/Validator/DateFormatValidatorTest.php @@ -1,43 +1,14 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Test\Icinga\Web\Form\Validator; +namespace Tests\Icinga\Web\Form\Validator; -require_once('Zend/Validate/Abstract.php'); -require_once(realpath('../../library/Icinga/Web/Form/Validator/DateFormatValidator.php')); +use Icinga\Test\BaseTestCase; +use Icinga\Web\Form\Validator\DateFormatValidator; -use \PHPUnit_Framework_TestCase; -use \Icinga\Web\Form\Validator\DateFormatValidator; - -class DateFormatValidatorTest extends PHPUnit_Framework_TestCase +class DateFormatValidatorTest extends BaseTestCase { - public function testValidateCorrectInput() { $validator = new DateFormatValidator(); diff --git a/test/php/library/Icinga/Web/Form/Validator/TimeFormatValidatorTest.php b/test/php/library/Icinga/Web/Form/Validator/TimeFormatValidatorTest.php index 42d3838d7..b0ad8c9ae 100644 --- a/test/php/library/Icinga/Web/Form/Validator/TimeFormatValidatorTest.php +++ b/test/php/library/Icinga/Web/Form/Validator/TimeFormatValidatorTest.php @@ -1,43 +1,14 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Test\Icinga\Web\Form\Validator; +namespace Tests\Icinga\Web\Form\Validator; -require_once('Zend/Validate/Abstract.php'); -require_once(realpath('../../library/Icinga/Web/Form/Validator/TimeFormatValidator.php')); +use Icinga\Test\BaseTestCase; +use Icinga\Web\Form\Validator\TimeFormatValidator; -use \PHPUnit_Framework_TestCase; -use \Icinga\Web\Form\Validator\TimeFormatValidator; - -class TimeFormatValidatorTest extends PHPUnit_Framework_TestCase +class TimeFormatValidatorTest extends BaseTestCase { - public function testValidateCorrectInput() { $validator = new TimeFormatValidator(); diff --git a/test/php/library/Icinga/Web/Form/Validator/WritablePathValidatorTest.php b/test/php/library/Icinga/Web/Form/Validator/WritablePathValidatorTest.php index 394db4dc5..b9e8c2ae7 100644 --- a/test/php/library/Icinga/Web/Form/Validator/WritablePathValidatorTest.php +++ b/test/php/library/Icinga/Web/Form/Validator/WritablePathValidatorTest.php @@ -1,44 +1,14 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Test\Icinga\Web\Form\Validator; +namespace Tests\Icinga\Web\Form\Validator; -require_once('Zend/Validate/Abstract.php'); -require_once(realpath('../../library/Icinga/Web/Form/Validator/WritablePathValidator.php')); -require_once(realpath('../../library/Icinga/Application/Config.php')); +use Icinga\Test\BaseTestCase; +use Icinga\Web\Form\Validator\WritablePathValidator; -use \PHPUnit_Framework_TestCase; -use \Icinga\Web\Form\Validator\WritablePathValidator; - -class WritablePathValidatorTest extends PHPUnit_Framework_TestCase +class WritablePathValidatorTest extends BaseTestCase { - public function testValidateInputWithWritablePath() { $validator = new WritablePathValidator(); diff --git a/test/php/library/Icinga/Web/FormTest.php b/test/php/library/Icinga/Web/FormTest.php index 97ca8be43..4e6ec5d92 100644 --- a/test/php/library/Icinga/Web/FormTest.php +++ b/test/php/library/Icinga/Web/FormTest.php @@ -1,107 +1,61 @@ setCancelLabel('Cancel'); - $form->buildForm(); - $this->assertCount(2, $form->getElements(), 'Asserting that the cancel label is present'); - } - - /** - * Tests whether the submit button will be added to the form - */ - function testSubmitButton() - { - $form = new TestForm(); - $form->setSubmitLabel('Submit'); - $form->buildForm(); - $this->assertCount(2, $form->getElements(), 'Asserting that the submit button is present'); - } - - /** - * Tests whether automatic form submission will be enabled for a single field - */ - function testEnableAutoSubmitSingle() - { - $form = new TestForm(); - $form->addElement('checkbox', 'example1', array()); - $form->enableAutoSubmit(array('example1')); - $this->assertArrayHasKey('data-icinga-form-autosubmit', $form->getElement('example1')->getAttribs(), - 'Asserting that auto-submit got enabled for one element'); - } - - /** - * Tests whether automatic form submission will be enabled for multiple fields - */ - function testEnableAutoSubmitMultiple() - { - $form = new TestForm(); - $form->addElement('checkbox', 'example1', array()); - $form->addElement('checkbox', 'example2', array()); - $form->enableAutoSubmit(array('example1', 'example2')); - $this->assertArrayHasKey('data-icinga-form-autosubmit', $form->getElement('example1')->getAttribs(), - 'Asserting that auto-submit got enabled for multiple elements'); - $this->assertArrayHasKey('data-icinga-form-autosubmit', $form->getElement('example2')->getAttribs(), - 'Asserting that auto-submit got enabled for multiple elements'); - } - - /** - * Tests whether automatic form submission can only be enabled for existing elements - * - * @expectedException Icinga\Exception\ProgrammingError - */ - function testEnableAutoSubmitExisting() - { - $form = new TestForm(); - $form->enableAutoSubmit(array('not_existing')); - } - - /** - * Tests whether a form will be detected as properly submitted - */ - function testFormSubmission() - { - $form = new TestForm(); - $form->setTokenDisabled(); - $form->setSubmitLabel('foo'); - $request = $this->getRequest(); - $form->setRequest($request->setMethod('GET')); - $this->assertFalse($form->isSubmittedAndValid(), - 'Asserting that it is not possible to submit a form not using POST'); - $request->setMethod('POST')->setPost(array('btn_submit' => 'foo')); - $this->assertTrue($form->isSubmittedAndValid(), - 'Asserting that it is possible to detect a form as submitted'); + $form = new Form(); + $form->addElement('text', 'someText'); + $element = $form->getElement('someText'); + + $this->assertFalse( + $element->getDecorator('HtmlTag'), + 'Form::addElement does not remove the HtmlTag-Decorator' + ); + $this->assertFalse( + $element->getDecorator('Label'), + 'Form::addElement does not remove the Label-Decorator' + ); + $this->assertFalse( + $element->getDecorator('DtDdWrapper'), + 'Form::addElement does not remove the DtDdWrapper-Decorator' + ); + } + + public function testWhetherAddElementDoesNotAddAnyOptionalDecoratorsToHiddenElements() + { + $form = new Form(); + $form->addElement('hidden', 'somethingHidden'); + $element = $form->getElement('somethingHidden'); + + $this->assertCount( + 1, + $element->getDecorators(), + 'Form::addElement adds more decorators than necessary to hidden elements' + ); + $this->assertInstanceOf( + '\Zend_Form_Decorator_ViewHelper', + $element->getDecorator('ViewHelper'), + 'Form::addElement does not add the ViewHelper-Decorator to hidden elements' + ); + } + + public function testWhetherLoadDefaultDecoratorsDoesNotAddTheHtmlTagDecorator() + { + $form = new Form(); + $form->loadDefaultDecorators(); + + $this->assertArrayNotHasKey( + 'HtmlTag', + $form->getDecorators(), + 'Form::loadDefaultDecorators adds the HtmlTag-Decorator' + ); } } diff --git a/test/php/library/Icinga/Web/Hook/Configuration/ConfigurationTabBuilderTest.php b/test/php/library/Icinga/Web/Hook/Configuration/ConfigurationTabBuilderTest.php index 7946b3d4b..e9d3bcc59 100644 --- a/test/php/library/Icinga/Web/Hook/Configuration/ConfigurationTabBuilderTest.php +++ b/test/php/library/Icinga/Web/Hook/Configuration/ConfigurationTabBuilderTest.php @@ -1,51 +1,34 @@ build(); $tabs = $builder->getTabs(); @@ -56,15 +39,15 @@ class ConfigurationTabBuilderTest extends \PHPUnit_Framework_TestCase public function testTabCreation1() { $widget = new Tabs(); - $builder = new Hook\Configuration\ConfigurationTabBuilder($widget); + $builder = new ConfigurationTabBuilder($widget); $tab1 = new ConfigurationTab('test1', '/test1', 'TEST1'); $tab2 = new ConfigurationTab('test2', '/test2', 'TEST2'); $tab3 = new ConfigurationTab('test3', '/test3', 'TEST3'); - Hook::registerObject(Hook\Configuration\ConfigurationTabBuilder::HOOK_NAMESPACE, 'test1', $tab1); - Hook::registerObject(Hook\Configuration\ConfigurationTabBuilder::HOOK_NAMESPACE, 'test2', $tab2); - Hook::registerObject(Hook\Configuration\ConfigurationTabBuilder::HOOK_NAMESPACE, 'test3', $tab3); + Hook::registerObject(ConfigurationTabBuilder::HOOK_NAMESPACE, 'test1', $tab1); + Hook::registerObject(ConfigurationTabBuilder::HOOK_NAMESPACE, 'test2', $tab2); + Hook::registerObject(ConfigurationTabBuilder::HOOK_NAMESPACE, 'test3', $tab3); $builder->build(); @@ -78,10 +61,10 @@ class ConfigurationTabBuilderTest extends \PHPUnit_Framework_TestCase public function testTabCreation2() { $widget = new Tabs(); - $builder = new Hook\Configuration\ConfigurationTabBuilder($widget); + $builder = new ConfigurationTabBuilder($widget); - $tab = new \stdClass(); - Hook::registerObject(Hook\Configuration\ConfigurationTabBuilder::HOOK_NAMESPACE, 'misc', $tab); + $tab = Mockery::mock('Tab'); + Hook::registerObject(ConfigurationTabBuilder::HOOK_NAMESPACE, 'misc', $tab); $builder->build(); $this->assertCount(5, $builder->getTabs()); diff --git a/test/php/library/Icinga/Web/Hook/Configuration/ConfigurationTabTest.php b/test/php/library/Icinga/Web/Hook/Configuration/ConfigurationTabTest.php index 610ffda53..6f9fdaeb1 100644 --- a/test/php/library/Icinga/Web/Hook/Configuration/ConfigurationTabTest.php +++ b/test/php/library/Icinga/Web/Hook/Configuration/ConfigurationTabTest.php @@ -1,14 +1,13 @@ test = $test; - } - - /** - * @return mixed - */ - public function getTest() - { - return $this->test; - } - - public function __toString() - { - return $this->getTest(); - } -} - -class HookTest extends \PHPUnit_Framework_TestCase -{ - protected function setUp() + public function setUp() { parent::setUp(); Hook::clean(); } - protected function tearDown() + public function tearDown() { parent::tearDown(); Hook::clean(); } - /** - * Test for Hook::Has() - * Note: This method is static! - * - **/ - public function testHas() + public function testWhetherHasReturnsTrueIfGivenAKnownHook() { - $this->assertFalse(Hook::has("a")); - $this->assertFalse(Hook::has("a","b")); + Hook::registerClass('TestHook', __FUNCTION__, get_class(Mockery::mock(Hook::$BASE_NS . 'TestHook'))); - Hook::registerClass("a","b","c"); - $this->assertTrue(Hook::has("a")); - $this->assertTrue(Hook::has("a","b")); + $this->assertTrue(Hook::has('TestHook'), 'Hook::has does not return true if given a known hook'); + } + + public function testWhetherHasReturnsFalseIfGivenAnUnknownHook() + { + $this->assertFalse(Hook::has('not_existing'), 'Hook::has does not return false if given an unknown hook'); + } + + public function testWhetherHooksCanBeRegisteredWithRegisterClass() + { + Hook::registerClass('TestHook', __FUNCTION__, get_class(Mockery::mock(Hook::$BASE_NS . 'TestHook'))); + + $this->assertTrue(Hook::has('TestHook'), 'Hook::registerClass does not properly register a given hook'); } /** - * Test for Hook::CreateInstance() - * Note: This method is static! - * - **/ - public function testCreateInstance() + * @depends testWhetherHooksCanBeRegisteredWithRegisterClass + */ + public function testWhetherMultipleHooksOfTheSameTypeCanBeRegisteredWithRegisterClass() { - Hook::$BASE_NS = "Tests\\Icinga\\Web\\"; - Hook::registerClass("Base","b","Tests\\Icinga\\Web\\TestHookImplementation"); - $this->assertInstanceOf("Tests\\Icinga\\Web\\TestHookImplementation",Hook::createInstance("Base","b")); - Hook::clean(); - } + $firstHook = Mockery::mock(Hook::$BASE_NS . 'TestHook'); + $secondHook = Mockery::mock('overload:' . get_class($firstHook)); - /** - * Test for Hook::CreateInstance() - * Note: This method is static! - * - * - **/ - public function testCreateInvalidInstance1() - { - $this->setExpectedException('\Icinga\Exception\ProgrammingError'); - Hook::$BASE_NS = "Tests\\Icinga\\Web\\"; - Hook::registerClass("Base","b","Tests\\Icinga\\Web\\TestBadHookImplementation"); - Hook::createInstance("Base","b"); - Hook::clean(); - } - - public function testCreateInvalidInstance2() - { - Hook::$BASE_NS = "Tests\\Icinga\\Web\\"; - $test = Hook::createInstance("Base","NOTEXIST"); - $this->assertNull($test); - } - - public function testCreateInvalidInstance3() - { - Hook::$BASE_NS = "Tests\\Icinga\\Web\\"; - Hook::register("Base","ErrorProne","Tests\\Icinga\\Web\\ErrorProneHookImplementation"); - $test = Hook::createInstance("Base","ErrorProne"); - $this->assertNull($test); - } - - /** - * Test for Hook::All() - * Note: This method is static! - * - **/ - public function testAll() - { - Hook::$BASE_NS = "Tests\\Icinga\\Web\\"; - Hook::registerClass("Base","a","Tests\\Icinga\\Web\\TestHookImplementation"); - Hook::registerClass("Base","b","Tests\\Icinga\\Web\\TestHookImplementation"); - Hook::registerClass("Base","c","Tests\\Icinga\\Web\\TestHookImplementation"); - $this->assertCount(3,Hook::all("Base")); - foreach(Hook::all("Base") as $instance) { - $this->assertInstanceOf("Tests\\Icinga\\Web\\TestHookImplementation",$instance); - } - - } - - /** - * Test for Hook::First() - * Note: This method is static! - * - **/ - public function testFirst() - { - Hook::$BASE_NS = "Tests\\Icinga\\Web\\"; - Hook::registerClass("Base","a","Tests\\Icinga\\Web\\TestHookImplementation"); - Hook::registerClass("Base","b","Tests\\Icinga\\Web\\TestHookImplementation"); - Hook::registerClass("Base","c","Tests\\Icinga\\Web\\TestHookImplementation"); - - $this->assertInstanceOf("Tests\\Icinga\\Web\\TestHookImplementation",Hook::first("Base")); - } - - public function testRegisterObject() - { - $o1 = new ObjectHookImplementation(); - $o1->setTest('$123123'); - - Hook::registerObject('Test', 'o1', $o1); - - $o2 = new ObjectHookImplementation(); - $o2->setTest('#456456'); - - Hook::registerObject('Test', 'o2', $o2); - - $this->assertInstanceOf('Tests\\Icinga\\Web\\ObjectHookImplementation', Hook::createInstance('Test', 'o1')); - $this->assertInstanceOf('Tests\\Icinga\\Web\\ObjectHookImplementation', Hook::createInstance('Test', 'o2')); - - $string = ""; - foreach (Hook::all('Test') as $hook) { - $string .= (string)$hook; - } - $this->assertEquals('$123123#456456', $string); + Hook::registerClass('TestHook', 'one', get_class($firstHook)); + Hook::registerClass('TestHook', 'two', get_class($secondHook)); + $this->assertInstanceOf( + get_class($secondHook), + Hook::createInstance('TestHook', 'two'), + 'Hook::registerClass is not able to register different hooks of the same type' + ); } /** * @expectedException Icinga\Exception\ProgrammingError - * @expectedExceptionMessage object is not an instantiated class */ - public function testErrorObjectRegistration() + public function testWhetherOnlyClassesCanBeRegisteredAsHookWithRegisterClass() { - Hook::registerObject('Test', 'e1', 'STRING'); + Hook::registerClass('TestHook', __FUNCTION__, 'nope'); } - public function testGetNullHooks() + public function testWhetherHooksCanBeRegisteredWithRegisterObject() { - $nh = Hook::all('DOES_NOT_EXIST'); - $this->assertInternalType('array', $nh); - $this->assertCount(0, $nh); + Hook::registerObject('TestHook', __FUNCTION__, Mockery::mock(Hook::$BASE_NS . 'TestHook')); + + $this->assertTrue(Hook::has('TestHook'), 'Hook::registerObject does not properly register a given hook'); + } + + /** + * @depends testWhetherHooksCanBeRegisteredWithRegisterObject + */ + public function testWhetherMultipleHooksOfTheSameTypeCanBeRegisteredWithRegisterObject() + { + $firstHook = Mockery::mock(Hook::$BASE_NS . 'TestHook'); + $secondHook = Mockery::mock('overload:' . get_class($firstHook)); + + Hook::registerObject('TestHook', 'one', $firstHook); + Hook::registerObject('TestHook', 'two', $secondHook); + $this->assertInstanceOf( + get_class($secondHook), + Hook::createInstance('TestHook', 'two'), + 'Hook::registerObject is not able to register different hooks of the same type' + ); + } + + /** + * @expectedException Icinga\Exception\ProgrammingError + */ + public function testWhetherOnlyObjectsCanBeRegisteredAsHookWithRegisterObject() + { + Hook::registerObject('TestHook', __FUNCTION__, 'nope'); + } + + public function testWhetherCreateInstanceReturnsNullIfGivenAnUnknownHookName() + { + $this->assertNull( + Hook::createInstance('not_existing', __FUNCTION__), + 'Hook::createInstance does not return null if given an unknown hook' + ); + } + + /** + * @depends testWhetherHooksCanBeRegisteredWithRegisterClass + */ + public function testWhetherCreateInstanceInitializesHooksInheritingFromAPredefinedAbstractHook() + { + $baseHook = Mockery::mock(Hook::$BASE_NS . 'TestHook'); + Hook::registerClass( + 'TestHook', + __FUNCTION__, + get_class(Mockery::mock('overload:' . get_class($baseHook))) + ); + + $this->assertInstanceOf( + get_class($baseHook), + Hook::createInstance('TestHook', __FUNCTION__), + 'Hook::createInstance does not initialize hooks inheriting from a predefined abstract hook' + ); + } + + /** + * @depends testWhetherHooksCanBeRegisteredWithRegisterClass + */ + public function testWhetherCreateInstanceDoesNotInitializeMultipleHooksForASpecificIdentifier() + { + Hook::registerClass('TestHook', __FUNCTION__, get_class(Mockery::mock(Hook::$BASE_NS . 'TestHook'))); + $secondHook = Hook::createInstance('TestHook', __FUNCTION__); + $thirdHook = Hook::createInstance('TestHook', __FUNCTION__); + + $this->assertSame( + $secondHook, + $thirdHook, + 'Hook::createInstance initializes multiple hooks for a specific identifier' + ); + } + + /** + * @depends testWhetherHooksCanBeRegisteredWithRegisterClass + */ + public function testWhetherCreateInstanceReturnsNullIfHookCannotBeInitialized() + { + Hook::registerClass('TestHook', __FUNCTION__, 'Tests\Icinga\Web\ErrorProneHookImplementation'); + + $this->assertNull(Hook::createInstance('TestHook', __FUNCTION__)); + } + + /** + * @expectedException Icinga\Exception\ProgrammingError + * @depends testWhetherHooksCanBeRegisteredWithRegisterClass + */ + public function testWhetherCreateInstanceThrowsAnErrorIfGivenAHookNotInheritingFromAPredefinedAbstractHook() + { + Mockery::mock(Hook::$BASE_NS . 'TestHook'); + Hook::registerClass('TestHook', __FUNCTION__, get_class(Mockery::mock('TestHook'))); + + Hook::createInstance('TestHook', __FUNCTION__); + } + + /** + * @depends testWhetherHooksCanBeRegisteredWithRegisterObject + */ + public function testWhetherAllReturnsAllRegisteredHooks() + { + $hook = Mockery::mock(Hook::$BASE_NS . 'TestHook'); + Hook::registerObject('TestHook', 'one', $hook); + Hook::registerObject('TestHook', 'two', $hook); + Hook::registerObject('TestHook', 'three', $hook); + + $this->assertCount(3, Hook::all('TestHook'), 'Hook::all does not return all registered hooks'); + } + + public function testWhetherAllReturnsNothingIfGivenAnUnknownHookName() + { + $this->assertEmpty( + Hook::all('not_existing'), + 'Hook::all does not return an empty array if given an unknown hook' + ); + } + + /** + * @depends testWhetherHooksCanBeRegisteredWithRegisterObject + */ + public function testWhetherFirstReturnsTheFirstRegisteredHook() + { + $firstHook = Mockery::mock(Hook::$BASE_NS . 'TestHook'); + $secondHook = Mockery::mock(Hook::$BASE_NS . 'TestHook'); + Hook::registerObject('TestHook', 'first', $firstHook); + Hook::registerObject('TestHook', 'second', $secondHook); + + $this->assertSame( + $firstHook, + Hook::first('TestHook'), + 'Hook::first does not return the first registered hook' + ); } } diff --git a/test/php/library/Icinga/Web/MenuItemTest.php b/test/php/library/Icinga/Web/MenuItemTest.php new file mode 100644 index 000000000..f8234ab5e --- /dev/null +++ b/test/php/library/Icinga/Web/MenuItemTest.php @@ -0,0 +1,29 @@ +addChild(5, new Zend_Config(array('title' => 'ccc5'))); + $item->addChild(0, new Zend_Config(array('title' => 'aaa'))); + $item->addChild(3, new Zend_Config(array('title' => 'ccc'))); + $item->addChild(2, new Zend_Config(array('title' => 'bbb'))); + $item->addChild(4, new Zend_Config(array('title' => 'ccc2'))); + $item->addChild(1, new Zend_Config(array('title' => 'bb'))); + + $this->assertEquals( + array('aaa', 'bb', 'bbb', 'ccc', 'ccc2', 'ccc5'), + array_map(function ($it) { return $it->getTitle(); }, $item->getChildren()), + 'MenuItem::getChildren does not return its elements in natural order' + ); + } +} diff --git a/test/php/library/Icinga/Web/NotificationTest.php b/test/php/library/Icinga/Web/NotificationTest.php deleted file mode 100644 index 9b4a3973e..000000000 --- a/test/php/library/Icinga/Web/NotificationTest.php +++ /dev/null @@ -1,122 +0,0 @@ -loggerPath = "/tmp/icinga2-web-notify-test"; - $this->dropLog(); - $logConfig = new \Zend_Config(array( - "debug" => array( - "enable" => 0, - "type"=>"mock", - "target"=>"target3" - ), - "type" => "stream", - "target" => $this->loggerPath - )); - - $this->logger = new Logger($logConfig); - - // $this->notification = Notification::getInstance(); - } - - protected function dropLog() - { - if (file_exists($this->loggerPath)) { - unlink($this->loggerPath); - } - } - - public function testAddMessage1() - { - $this->markTestSkipped(); - $notify = Notification::getInstance(); - $notify->setCliFlag(true); - $notify->error('OK1'); - $notify->warning('OK2'); - $notify->info('OK3'); - $this->logger->flushQueue(); - - $content = file_get_contents($this->loggerPath); - - $this->assertContains('[error] OK1', $content); - $this->assertContains('[warning] OK2', $content); - $this->assertNotContains('[info] OK3', $content); - - $this->dropLog(); - } - - public function testAddMessage2() - { - $this->markTestSkipped(); - $notify = Notification::getInstance(); - $notify->setCliFlag(false); - - $notify->success('test123'); - $notify->error('test456'); - - $this->assertTrue($notify->hasMessages()); - - $messages = $notify->getMessages(); - - $this->assertInternalType('array', $messages); - - $this->assertEquals('test123', $messages[0]->message); - $this->assertEquals('success', $messages[0]->type); - - $this->assertEquals('test456', $messages[1]->message); - $this->assertEquals('error', $messages[1]->type); - } - - /** - * @expectedException Icinga\Exception\ProgrammingError - * @expectedExceptionMessage "NOT_EXIST_123" is not a valid notification type - */ - public function testWrongType1() - { - $this->markTestSkipped(); - $notify = Notification::getInstance(); - $notify->addMessage('test', 'NOT_EXIST_123'); - } - - public function testSetterAndGetter1() - { - $this->markTestSkipped(); - $notify = Notification::getInstance(); - $notify->setCliFlag(true); - $this->assertTrue($notify->getCliFlag()); - - $notify->setCliFlag(false); - $this->assertFalse($notify->getCliFlag()); - } -} diff --git a/test/php/library/Icinga/Web/Paginator/Adapter/QueryAdapterTest.php b/test/php/library/Icinga/Web/Paginator/Adapter/QueryAdapterTest.php index cd3e7bb93..b5d119a5f 100644 --- a/test/php/library/Icinga/Web/Paginator/Adapter/QueryAdapterTest.php +++ b/test/php/library/Icinga/Web/Paginator/Adapter/QueryAdapterTest.php @@ -1,28 +1,16 @@ cacheDir = '/tmp'. Reader::STATUSDAT_DEFAULT_CACHE_PATH; if (!file_exists($this->cacheDir)) { mkdir($this->cacheDir); } - $statusdatFile = dirname(__FILE__) . '/../../../../../res/status/icinga.status.dat'; - $cacheFile = dirname(__FILE__) . '/../../../../../res/status/icinga.objects.cache'; + $statusdatFile = BaseTestCase::$testDir . '/res/status/icinga.status.dat'; + $cacheFile = BaseTestCase::$testDir . '/res/status/icinga.objects.cache'; $this->backendConfig = new Zend_Config( array( diff --git a/test/php/library/Icinga/Web/Paginator/ScrollingStyle/SlidingWithBorderTest.php b/test/php/library/Icinga/Web/Paginator/ScrollingStyle/SlidingWithBorderTest.php index a46208939..ecac14ed4 100644 --- a/test/php/library/Icinga/Web/Paginator/ScrollingStyle/SlidingWithBorderTest.php +++ b/test/php/library/Icinga/Web/Paginator/ScrollingStyle/SlidingWithBorderTest.php @@ -1,80 +1,22 @@ items[] = array( - 'a' => mt_rand(0, 100), - 'b' => mt_rand(0, 100) - ); - } - } - - /** - * Returns an collection of items for a page. - * - * @param integer $offset Page offset - * @param integer $itemCountPerPage Number of items per page - * @return array - */ - public function getItems($offset, $itemCountPerPage) - { - $out = array_slice($this->items, $offset, $itemCountPerPage, true); - } - - /** - * (PHP 5 >= 5.1.0)
- * Count elements of an object - * @link http://php.net/manual/en/countable.count.php - * @return int The custom count as an integer. - *

- *

- * The return value is cast to an integer. - */ - public function count() - { - return count($this->items); - } - -} - -/** -* -* Test class for Slidingwithborder -* Created Wed, 16 Jan 2013 15:15:16 +0000 -* -**/ -class SlidingwithborderTest extends \PHPUnit_Framework_TestCase +class SlidingwithborderTest extends BaseTestCase { private $cacheDir; @@ -82,16 +24,17 @@ class SlidingwithborderTest extends \PHPUnit_Framework_TestCase private $resourceConfig; - protected function setUp() + public function setUp() { + parent::setUp(); $this->cacheDir = '/tmp'. Reader::STATUSDAT_DEFAULT_CACHE_PATH; if (!file_exists($this->cacheDir)) { mkdir($this->cacheDir); } - $statusdatFile = dirname(__FILE__). '/../../../../../res/status/icinga.status.dat'; - $cacheFile = dirname(__FILE__). '/../../../../../res/status/icinga.objects.cache'; + $statusdatFile = BaseTestCase::$testDir . '/res/status/icinga.status.dat'; + $cacheFile = BaseTestCase::$testDir . '/res/status/icinga.objects.cache'; $this->backendConfig = new Zend_Config( array( @@ -101,7 +44,7 @@ class SlidingwithborderTest extends \PHPUnit_Framework_TestCase $this->resourceConfig = new Zend_Config( array( 'status_file' => $statusdatFile, - 'object_file' => $cacheFile, + 'object_file' => $cacheFile, 'type' => 'statusdat' ) ); @@ -110,54 +53,44 @@ class SlidingwithborderTest extends \PHPUnit_Framework_TestCase public function testGetPages1() { $backend = new Backend($this->backendConfig, $this->resourceConfig); - $query = $backend->select()->from('status'); - - $adapter = new QueryAdapter($query); + $adapter = new QueryAdapter($backend->select()->from('status')); $this->assertEquals(30, $adapter->count()); - $scrolingStyle = new \Icinga_Web_Paginator_ScrollingStyle_SlidingWithBorder(); - - $paginator = new \Zend_Paginator($adapter); - - $pages = $scrolingStyle->getPages($paginator); + $scrollingStyle = new \Icinga_Web_Paginator_ScrollingStyle_SlidingWithBorder(); + $paginator = new Zend_Paginator($adapter); + $pages = $scrollingStyle->getPages($paginator); $this->assertInternalType('array', $pages); $this->assertCount(3, $pages); } public function testGetPages2() { - $scrolingStyle = new \Icinga_Web_Paginator_ScrollingStyle_SlidingWithBorder(); - - $adapter = new TestPaginatorAdapter(); - - $paginator = new \Zend_Paginator($adapter); - - $pages = $scrolingStyle->getPages($paginator); + $scrollingStyle = new \Icinga_Web_Paginator_ScrollingStyle_SlidingWithBorder(); + $paginator = new Zend_Paginator($this->getPaginatorAdapter()); + $pages = $scrollingStyle->getPages($paginator); $this->assertInternalType('array', $pages); - $this->assertCount(13, $pages); $this->assertEquals('...', $pages[11]); } public function testGetPages3() { - $scrolingStyle = new \Icinga_Web_Paginator_ScrollingStyle_SlidingWithBorder(); - - $adapter = new TestPaginatorAdapter(); - - $paginator = new \Zend_Paginator($adapter); + $scrollingStyle = new \Icinga_Web_Paginator_ScrollingStyle_SlidingWithBorder(); + $paginator = new Zend_Paginator($this->getPaginatorAdapter()); $paginator->setCurrentPageNumber(9); - $pages = $scrolingStyle->getPages($paginator); - + $pages = $scrollingStyle->getPages($paginator); $this->assertInternalType('array', $pages); - $this->assertCount(16, $pages); $this->assertEquals('...', $pages[3]); $this->assertEquals('...', $pages[14]); } + protected function getPaginatorAdapter() + { + return Mockery::mock('\Zend_Paginator_Adapter_Interface')->shouldReceive('count')->andReturn(1000)->getMock(); + } } diff --git a/test/php/library/Icinga/Web/RequestMock.php b/test/php/library/Icinga/Web/RequestMock.php deleted file mode 100644 index 938bc4fd0..000000000 --- a/test/php/library/Icinga/Web/RequestMock.php +++ /dev/null @@ -1,89 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Tests\Icinga\Web; - -/** - * Request mock that implements all methods required by the - * Url class - * - */ -class RequestMock -{ - /** - * The path of the request - * - * @var string - */ - public $path = ""; - - /** - * The baseUrl of the request - * - * @var string - */ - public $baseUrl = '/'; - - /** - * An array of query parameters that the request should resemble - * - * @var array - */ - public $query = array(); - - /** - * Returns the path set for the request - * - * @return string - */ - public function getPathInfo() - { - return $this->path; - } - - /** - * Returns the baseUrl set for the request - * - * @return string - */ - public function getBaseUrl() - { - return $this->baseUrl; - } - - /** - * Returns the query set for the request - * - * @return array - */ - public function getQuery() - { - return $this->query; - } -} diff --git a/test/php/library/Icinga/Session/PhpSessionTest.php b/test/php/library/Icinga/Web/Session/PhpSessionTest.php similarity index 54% rename from test/php/library/Icinga/Session/PhpSessionTest.php rename to test/php/library/Icinga/Web/Session/PhpSessionTest.php index 96ded3dc7..49641c60d 100644 --- a/test/php/library/Icinga/Session/PhpSessionTest.php +++ b/test/php/library/Icinga/Web/Session/PhpSessionTest.php @@ -1,49 +1,10 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} -namespace Tests\Icinga\Authentication; - -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -// @codingStandardsIgnoreEnd +namespace Tests\Icinga\Web\Session; use Icinga\Test\BaseTestCase; - -// @codingStandardsIgnoreStart -require_once BaseTestCase::$libDir . '/Web/Session/SessionNamespace.php'; -require_once BaseTestCase::$libDir . '/Web/Session/Session.php'; -require_once BaseTestCase::$libDir . '/Web/Session/PhpSession.php'; -require_once BaseTestCase::$libDir . '/Logger/Logger.php'; -require_once BaseTestCase::$libDir . '/Exception/ConfigurationError.php'; -require_once 'Zend/Log.php'; -// @codingStandardsIgnoreEnd - use Icinga\Web\Session\PhpSession; class PhpSessionTest extends BaseTestCase @@ -102,7 +63,7 @@ class PhpSessionTest extends BaseTestCase } /** - * Test whether session namespaces are properly written and loaded + * Test whether session namespaces are properly written, cleared and loaded * * @runInSeparateProcess */ @@ -114,9 +75,45 @@ class PhpSessionTest extends BaseTestCase $namespace->set('an_array', array(1, 2, 3)); $session->write(); $session->clear(); + $this->assertFalse($session->hasNamespace('test')); $session->read(); $namespace = $session->getNamespace('test'); $this->assertEquals($namespace->get('some_key'), 'some_val'); $this->assertEquals($namespace->get('an_array'), array(1, 2, 3)); } + + /** + * Test whether session values are properly removed + * + * @runInSeparateProcess + */ + public function testValueRemoval() + { + $session = $this->getSession(); + $session->set('key', 'value'); + $session->write(); + $session->delete('key'); + $session->write(); + $session->clear(); + $session->read(); + $this->assertNull($session->get('key')); + } + + /** + * Test whether session namespaces are properly removed + * + * @runInSeparateProcess + */ + public function testNamespaceRemoval() + { + $session = $this->getSession(); + $namespace = $session->getNamespace('test'); + $namespace->key = 'value'; + $session->write(); + $session->removeNamespace('test'); + $session->write(); + $session->clear(); + $session->read(); + $this->assertFalse($session->hasNamespace('test')); + } } diff --git a/test/php/library/Icinga/Session/SessionNamespaceTest.php b/test/php/library/Icinga/Web/Session/SessionNamespaceTest.php similarity index 60% rename from test/php/library/Icinga/Session/SessionNamespaceTest.php rename to test/php/library/Icinga/Web/Session/SessionNamespaceTest.php index af269ffe0..db7be8c64 100644 --- a/test/php/library/Icinga/Session/SessionNamespaceTest.php +++ b/test/php/library/Icinga/Web/Session/SessionNamespaceTest.php @@ -1,46 +1,14 @@ - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ // {{{ICINGA_LICENSE_HEADER}}} -// @codingStandardsIgnoreStart -require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php'); -// @codingStandardsIgnoreEnd +namespace Tests\Icinga\Web\Session; +use Exception; +use Mockery; use Icinga\Test\BaseTestCase; - -// @codingStandardsIgnoreStart -require_once BaseTestCase::$libDir . '/Web/Session/SessionNamespace.php'; -// @codingStandardsIgnoreEnd - -use \Exception; use Icinga\Web\Session\SessionNamespace; - class SessionNamespaceTest extends BaseTestCase { /** @@ -105,4 +73,39 @@ class SessionNamespaceTest extends BaseTestCase $ns = new SessionNamespace(); $ns->missing; } + + /** + * Check whether iterating over session namespaces works + */ + public function testIteration() + { + $ns = new SessionNamespace(); + $values = array('key1' => 'val1', 'key2' => 'val2'); + $ns->setAll($values); + foreach ($ns as $key => $value) { + $this->assertEquals($value, $values[$key]); + } + } + + /** + * @expectedException Exception + * @expectedExceptionMessage Cannot save, session not set + */ + public function testInvalidParentWrite() + { + $ns = new SessionNamespace(); + $ns->write(); + } + + /** + * Check whether it is possible to write a namespace's parent + */ + public function testValidParentWrite() + { + $sessionMock = Mockery::mock('Icinga\Web\Session\Session'); + $sessionMock->shouldReceive('write')->atLeast()->times(1); + + $ns = new SessionNamespace($sessionMock); + $ns->write(); + } } diff --git a/test/php/library/Icinga/Web/UrlTest.php b/test/php/library/Icinga/Web/UrlTest.php index 21008f808..21a893b62 100644 --- a/test/php/library/Icinga/Web/UrlTest.php +++ b/test/php/library/Icinga/Web/UrlTest.php @@ -1,324 +1,343 @@ assertEquals('/my/test/url.html', $url->getPath(), 'Assert the parsed url path to be equal to the input path'); - $this->assertEquals($url->getPath(), '/'.$url->getRelativeUrl(), 'Assert the path of an url without query to be equal the relative path'); - } + $request = Mockery::mock('Icinga\Web\Request'); + $request->shouldReceive('getPathInfo')->andReturn('my/test/url.html') + ->shouldReceive('getBaseUrl')->andReturn('/path/to') + ->shouldReceive('getQuery')->andReturn(array('param1' => 'value1', 'param2' => 'value2')); + $this->setupIcingaMock($request); - /** - * Tests whether a simple Url without query parameters and with baseUrl is correctly parsed and returns correct Urls - * - */ - function testFromUrlWithBasePath() - { - $url = Url::fromPath('my/test/url.html', array(), new RequestMock()); - $url->setBaseUrl('the/path/to'); - $this->assertEquals('/the/path/to/my/test/url.html', $url->getAbsoluteUrl(), 'Assert the url path to be the base path with the relative path'); - } - - /** - * Tests whether query parameters in Urls are correctly recognized and decoded - * - */ - function testFromUrlWithKeyValueQuery() - { - $url = Url::fromPath('/my/test/url.html?param1=%25arg1¶m2=arg2', array(), new RequestMock()); - $this->assertEquals('/my/test/url.html', $url->getPath(), 'Assert the parsed url path to be equal to the input path'); + $url = Url::fromRequest(); $this->assertEquals( - array( - 'param1' => '%arg1', - 'param2' => 'arg2' - ), - $url->getParams(), - 'Assert single key=value Url parameters to be correctly parsed and recognized' - ); - } - - /** - * Tests whether unnamed query parameters in Urls are correctly recognized and decoded - * - */ - function testFromUrlWithArrayInQuery() - { - $url = Url::fromPath('/my/test/url.html?param[]=%25val1¶m[]=%40val2', array(), new RequestMock()); - $this->assertEquals( - array( - 'param' => array('%val1', '@val2') - ), - $url->getParams(), - 'Assert arrays in param[] = value syntax to be correctly recognized and parsed as arrays' - ); - } - - /** - * Tests whether named query parameters in Urls are correctly recognized and decoded - * - */ - function testFromUrlWithAssociativeArrayInQuery() - { - $url = Url::fromPath('/my/test/url.html?param[value]=%25val1¶m[value2]=%40val2', array(), new RequestMock()); - $this->assertEquals( - array( - 'param' => array( - 'value' => '%val1', - 'value2' => '@val2' - ) - ), - $url->getParams(), - 'Assert arrays in param[] = value syntax to be correctly recognized and parsed as arrays' - ); - } - - /** - * Tests whether simple query parameters can be correctly added on an existing query and ends up in correct Urls - * - */ - function testAddQueryParameterToUrlWithoutQuery() - { - $url = Url::fromPath( - '/my/test/url.html', - array( - 'param1' => 'val1', - 'param2' => 'val2' - ), - new RequestMock() - ); - $url->setBaseUrl('path/to'); - $this->assertEquals( - '/path/to/my/test/url.html?param1=val1¶m2=val2', + '/path/to/my/test/url.html?param1=value1&param2=value2', $url->getAbsoluteUrl(), - 'Assert additional parameters to be correctly added to the Url' + 'Url::fromRequest does not reassemble the correct url from the global request' ); } - /** - * Test whether parameters are correctly added to existing query parameters and existing ones are correctly overwritten - * if they have the same key - * - */ - function testOverwritePartialQuery() + public function testWhetherFromRequestWorksWithARequest() { - $url = Url::fromPath( - '/my/test/url.html?param1=oldval1', - array( - 'param1' => 'val1', - 'param2' => 'val2' - ), - new RequestMock() - ); - $url->setBaseUrl('path/to'); - $this->assertEquals( - '/path/to/my/test/url.html?param1=val1¶m2=val2', - $url->getAbsoluteUrl(), - 'Assert additional parameters to be correctly added to the Url and overwriting existing parameters' - ); - } + $request = Mockery::mock('Icinga\Web\Request'); + $request->shouldReceive('getPathInfo')->andReturn('my/test/url.html') + ->shouldReceive('getBaseUrl')->andReturn('/path/to') + ->shouldReceive('getQuery')->andReturn(array()); - /** - * Test whether array parameters are correctly added to an existing Url and end up in correct Urls - * - */ - function testSetQueryWithArrayParameter() - { - $url = Url::fromPath( - '/my/test/url.html', - array( - 'flatarray' => array('val1', 'val2'), - 'param' => array('value1'=>'val1', 'value2' => 'val2') - ), - new RequestMock() - ); - $url->setBaseUrl('path/to'); - $this->assertEquals( - '/path/to/my/test/url.html?flatarray'.urlencode('[0]').'=val1&'. - 'flatarray'.urlencode('[1]').'=val2&'. - 'param'.urlencode('[value1]').'=val1&'. - 'param'.urlencode('[value2]').'=val2', - $url->getAbsoluteUrl(), - 'Assert array parameters to be correctly encoded and added to the Url' - ); - } - - /** - * Test whether Urls from the request are correctly parsed when no query is given - * - */ - function testUrlFromRequestWithoutQuery() - { - $request = new RequestMock(); - $request->baseUrl = 'path/to'; - $request->path = 'my/test/url.html'; - $request->query = array(); $url = Url::fromRequest(array(), $request); $this->assertEquals( '/path/to/my/test/url.html', $url->getAbsoluteUrl(), - 'Asserting absolute path resembling the requests path appended by the baseUrl' + 'Url::fromRequest does not reassemble the correct url from a given request' + ); + } + + public function testWhetherFromRequestAcceptsAdditionalParameters() + { + $request = Mockery::mock('Icinga\Web\Request'); + $request->shouldReceive('getPathInfo')->andReturn('') + ->shouldReceive('getBaseUrl')->andReturn('/') + ->shouldReceive('getQuery')->andReturn(array('key1' => 'val1')); + + $url = Url::fromRequest(array('key1' => 'newval1', 'key2' => 'val2'), $request); + $this->assertEquals( + 'val2', + $url->getParam('key2', 'wrongval'), + 'Url::fromRequest does not accept additional parameters' + ); + $this->assertEquals( + 'newval1', + $url->getParam('key1', 'wrongval1'), + 'Url::fromRequest does not overwrite existing parameters with additional ones' ); } /** - * Test whether Urls from the request are correctly parsed when a query is given - * + * @expectedException Icinga\Exception\ProgrammingError */ - function testUrlFromRequestWithQuery() + public function testWhetherFromPathProperlyHandlesInvalidUrls() { - $request = new RequestMock(); - $request->baseUrl = 'path/to'; - $request->path = 'my/test/url.html'; - $request->query = array( - 'param1' => 'value1', - 'param2' => array('key1' => 'value1', 'key2' => 'value2') - ); - $url = Url::fromRequest(array(), $request); + Url::fromPath(null); + } + + public function testWhetherFromPathAcceptsAdditionalParameters() + { + $url = Url::fromPath('/my/test/url.html', array('key' => 'value')); + $this->assertEquals( - '/path/to/my/test/url.html?param1=value1&'. - 'param2'.urlencode('[key1]').'=value1&'. - 'param2'.urlencode('[key2]').'=value2', + 'value', + $url->getParam('key', 'wrongvalue'), + 'Url::fromPath does not accept additional parameters' + ); + } + + public function testWhetherFromPathProperlyParsesUrlsWithoutQuery() + { + $url = Url::fromPath('/my/test/url.html'); + + $this->assertEquals( + '/', + $url->getBaseUrl(), + 'Url::fromPath does not recognize the correct base url' + ); + $this->assertEquals( + 'my/test/url.html', + $url->getPath(), + 'Url::fromPath does not recognize the correct url path' + ); + } + + /** + * @depends testWhetherFromPathProperlyParsesUrlsWithoutQuery + */ + public function testWhetherFromPathProperlyRecognizesTheBaseUrl() + { + $url = Url::fromPath( + '/path/to/my/test/url.html', + array(), + Mockery::mock(array('getBaseUrl' => '/path/to')) + ); + + $this->assertEquals( + '/path/to/my/test/url.html', $url->getAbsoluteUrl(), - 'Asserting absolute path resembling the requests path appended by the baseUrl' + 'Url::fromPath does not properly differentiate between the base url and its path' ); } /** - * Test the @see Url::getParam($name, $default) function - * + * @depends testWhetherFromPathProperlyRecognizesTheBaseUrl */ - function testGetParameterByName() + public function testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters() { - $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2', array(), new RequestMock()); + $url = Url::fromPath('/my/test/url.html?param1=%25arg1¶m2=arg+2' + . '¶m3[]=1¶m3[]=2¶m3[]=3¶m4[key1]=val1¶m4[key2]=val2'); + $this->assertEquals( - "val", - $url->getParam("param", "wrongval"), - "Asserting a parameter can be fetched via getParam()" + '%arg1', + $url->getParam('param1', 'wrongval'), + 'Url::fromPath does not properly decode escaped characters in query parameter values' ); $this->assertEquals( - "val2", - $url->getParam("param2", "wrongval2"), - "Asserting a parameter can be fetched via getParam()" + 'arg 2', + $url->getParam('param2', 'wrongval'), + 'Url::fromPath does not properly decode aliases characters in query parameter values' ); $this->assertEquals( - "nonexisting", - $url->getParam("param3", "nonexisting"), - "Asserting a non existing parameter returning the default value when fetched via getParam()" + array('1', '2', '3'), + $url->getParam('param3'), + 'Url::fromPath does not properly reassemble query parameter values as sequenced values' + ); + $this->assertEquals( + array('key1' => 'val1', 'key2' => 'val2'), + $url->getParam('param4'), + 'Url::fromPath does not properly reassemble query parameters as associative arrays' ); } /** - * Test the Url::remove function with a single key passed - * + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters */ - function testRemoveSingleParameter() + public function testWhetherTranslateAliasTranslatesKnownAliases() { - $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2', array(), new RequestMock()); - $url->remove("param"); + $url = Url::fromPath('/my/test/url.html'); + $url->setAliases(array('foo' => 'bar')); + $this->assertEquals( - "val2", - $url->getParam("param2", "wrongval2"), - "Asserting other parameters (param2) not being affected by remove" - ); - $this->assertEquals( - "rightval", - $url->getParam("param", "rightval"), - "Asserting a parameter (param) can be removed via remove" + 'bar', + $url->translateAlias('foo'), + 'Url::translateAlias does not translate a known alias' ); } /** - * Test the Url::remove function with an array of keys passed - * + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters */ - function testRemoveMultipleParameters() + public function testWhetherTranslateAliasDoesNotTranslateUnknownAliases() { - $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3', array(), new RequestMock()); - $url->remove(array("param", "param2")); + $url = Url::fromPath('/my/test/url.html'); + $url->setAliases(array('foo' => 'bar')); + $this->assertEquals( - "val3", - $url->getParam("param3", "wrongval"), - "Asserting other parameters (param3) not being affected by remove" - ); - $this->assertEquals( - "rightval", - $url->getParam("param", "rightval"), - "Asserting a parameter (param) can be removed via remove in a batch" - ); - $this->assertEquals( - "rightval", - $url->getParam("param2", "rightval"), - "Asserting a parameter (param2) can be removed via remove in a batch" + 'fo', + $url->translateAlias('fo'), + 'Url::translateAlias does translate an unknown alias' ); } /** - * Test the Url::without call and whether it returns a copy instead of working on the called object - * + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters */ - function testWithoutCall() + public function testWhetherGetAbsoluteUrlReturnsTheAbsoluteUrl() { - $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3', array(), new RequestMock()); - $url2 = $url->getUrlWithout(array("param")); - $this->assertNotEquals( - $url, - $url2, - "Asserting without creating a copy of the url" - ); - $this->assertTrue( - $url->hasParam("param"), - "Asserting the original Url not being affected when calling 'without'" - ); - $this->assertFalse( - $url2->hasParam("param"), - "Asserting the returned Url being without the passed parameter when calling 'without'" - ); - } + $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2'); - function testAddParamAfterCreation() - { - $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3', array(), new RequestMock()); - $url->addParams(array( - "param4" => "val4", - "param3" => "newval3" - )); $this->assertEquals( - "val4", - $url->getParam("param4", "wrongval"), - "Asserting that a parameter can be added with addParam" - ); - $this->assertEquals( - "val3", - $url->getParam("param3", "wrongval"), - "Asserting that addParam doesn't overwrite existing parameters" + '/my/test/url.html?param=val&param2=val2', + $url->getAbsoluteUrl(), + 'Url::getAbsoluteUrl does not return the absolute url' ); } /** - * Test whether toString is the same as getAbsoluteUrl - * + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters */ - function testToString() + public function testWhetherGetRelativeUrlReturnsTheRelativeUrl() { - $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3', array(), new RequestMock()); - $this->assertEquals($url->getAbsoluteUrl(), (string) $url, "Asserting whether toString returns the absolute Url"); + $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2'); + + $this->assertEquals( + 'my/test/url.html?param=val&param2=val2', + $url->getRelativeUrl(), + 'Url::getRelativeUrl does not return the relative url' + ); + } + + /** + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters + */ + public function testWhetherGetParamReturnsTheCorrectParameter() + { + $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2'); + + $this->assertEquals( + 'val', + $url->getParam('param', 'wrongval'), + 'Url::getParam does not return the correct value for an existing parameter' + ); + $this->assertEquals( + 'val2', + $url->getParam('param2', 'wrongval2'), + 'Url::getParam does not return the correct value for an existing parameter' + ); + $this->assertEquals( + 'nonexisting', + $url->getParam('param3', 'nonexisting'), + 'Url::getParam does not return the default value for a non existing parameter' + ); + } + + /** + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters + */ + public function testWhetherRemoveRemovesAGivenSingleParameter() + { + $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2'); + $url->remove('param'); + + $this->assertEquals( + 'val2', + $url->getParam('param2', 'wrongval2'), + 'Url::remove removes not only the given parameter' + ); + $this->assertEquals( + 'rightval', + $url->getParam('param', 'rightval'), + 'Url::remove does not remove the given parameter' + ); + } + + /** + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters + */ + public function testWhetherRemoveRemovesAGivenSetOfParameters() + { + $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); + $url->remove(array('param', 'param2')); + + $this->assertEquals( + 'val3', + $url->getParam('param3', 'wrongval'), + 'Url::remove removes not only the given parameters' + ); + $this->assertEquals( + 'rightval', + $url->getParam('param', 'rightval'), + 'Url::remove does not remove all given parameters' + ); + $this->assertEquals( + 'rightval', + $url->getParam('param2', 'rightval'), + 'Url::remove does not remove all given parameters' + ); + } + + /** + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters + */ + public function testWhetherGetUrlWithoutReturnsACopyOfTheUrlWithoutAGivenSetOfParameters() + { + $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); + $url2 = $url->getUrlWithout(array('param', 'param2')); + + $this->assertNotSame($url, $url2, 'Url::getUrlWithout does not return a new copy of the url'); + $this->assertEquals( + array('param3' => 'val3'), + $url2->getParams(), + 'Url::getUrlWithout does not remove a given set of parameters from the url' + ); + } + + /** + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters + */ + public function testWhetherAddParamsDoesNotOverwriteExistingParameters() + { + $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); + $url->addParams(array('param4' => 'val4', 'param3' => 'newval3')); + + $this->assertEquals( + 'val4', + $url->getParam('param4', 'wrongval'), + 'Url::addParams does not add new parameters' + ); + $this->assertEquals( + 'val3', + $url->getParam('param3', 'wrongval'), + 'Url::addParams overwrites existing parameters' + ); + } + + /** + * @depends testWhetherFromPathProperlyRecognizesAndDecodesQueryParameters + */ + public function testWhetherOverwriteParamsOverwritesExistingParameters() + { + $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); + $url->overwriteParams(array('param4' => 'val4', 'param3' => 'newval3')); + + $this->assertEquals( + 'val4', + $url->getParam('param4', 'wrongval'), + 'Url::addParams does not add new parameters' + ); + $this->assertEquals( + 'newval3', + $url->getParam('param3', 'wrongval'), + 'Url::addParams does not overwrite existing parameters' + ); + } + + /** + * @depends testWhetherGetAbsoluteUrlReturnsTheAbsoluteUrl + */ + public function testWhetherToStringConversionReturnsTheAbsoluteUrl() + { + $url = Url::fromPath('/my/test/url.html?param=val¶m2=val2¶m3=val3'); + + $this->assertEquals( + $url->getAbsoluteUrl(), + (string) $url, + 'Converting a url to string does not return the absolute url' + ); } } diff --git a/test/php/library/Icinga/Web/ViewMock.php b/test/php/library/Icinga/Web/ViewMock.php deleted file mode 100644 index aec5c369f..000000000 --- a/test/php/library/Icinga/Web/ViewMock.php +++ /dev/null @@ -1,50 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Tests\Icinga\Web; - -require_once('Zend/View/Abstract.php'); -use \Zend_View_Abstract; - -/** - * ViewMock that does absolutely nothing - * - */ -class ViewMock extends Zend_View_Abstract -{ - /** - * No operation is performed here - */ - protected function _run() - { - } -} - -// @codingStandardsIgnoreEnd diff --git a/test/php/library/Icinga/Web/Widget/TabTest.php b/test/php/library/Icinga/Web/Widget/TabTest.php deleted file mode 100644 index 653c676de..000000000 --- a/test/php/library/Icinga/Web/Widget/TabTest.php +++ /dev/null @@ -1,166 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Tests\Icinga\Web\Widget; - -require_once('../../library/Icinga/Web/Widget/Widget.php'); -require_once('../../library/Icinga/Web/Widget/Tab.php'); -require_once('../../library/Icinga/Web/Url.php'); -require_once('library/Icinga/Web/RequestMock.php'); -require_once('library/Icinga/Web/ViewMock.php'); -require_once('Zend/View/Abstract.php'); - -use Icinga\Web\View; -use Icinga\Web\Widget\Tab; -use Icinga\Web\Url; -use Tests\Icinga\Web\RequestMock; -use \Zend_View_Abstract; -use \PHPUnit_Framework_TestCase; - -use Tests\Icinga\Web\ViewMock; - -/** - * Test creation and rendering of tabs - * - */ -class TabTest extends PHPUnit_Framework_TestCase -{ - - /** - * Test whether rendering a tab without URL is done correctly - * - */ - public function testRenderWithoutUrl() - { - $tab = new Tab(array("name" => "tab", "title" => "Title text")); - $html = $tab->render(new ViewMock()); - - $this->assertEquals( - 1, - preg_match( - '/

  • *Title text *<\/li> */i', - $html - ), - "Asserting an tab without url only showing a title, , got " . $html - ); - } - - /** - * Test whether rendering an active tab adds the 'class' property - * - */ - public function testActiveTab() - { - $tab = new Tab(array("name" => "tab", "title" => "Title text")); - $tab->setActive(true); - - $html = $tab->render(new ViewMock()); - $this->assertEquals( - 1, - preg_match( - '/
  • *Title text *<\/li> */i', - $html - ), - "Asserting an active tab having the 'active' class provided, got " . $html - ); - } - - /** - * Test whether rendering a tab with URL adds a n >a< tag correctly - * - */ - public function testTabWithUrl() - { - $tab = new Tab( - array( - "name" => "tab", - "title" => "Title text", - "url" => Url::fromPath("my/url", array(), new RequestMock()) - ) - ); - $html = $tab->render(new ViewMock()); - $this->assertEquals( - 1, - preg_match( - '/
  • Title text<\/a><\/li>/i', - $html - ), - 'Asserting an url being rendered inside an HTML anchor. got ' . $html - ); - } - - /** - * Test wheter the 'icon' property adds an img tag - * - */ - public function testTabWithIconImage() - { - $tab = new Tab( - array( - "name" => "tab", - "title" => "Title text", - "icon" => Url::fromPath("my/url", array(), new RequestMock()) - ) - ); - $html = $tab->render(new ViewMock()); - $this->assertEquals( - 1, - preg_match( - '/
  • Title text<\/li>/i', - $html - ), - 'Asserting an url being rendered inside an HTML anchor. got ' . $html - ); - } - - /** - * Test wheter the iconCls property adds an i tag with the icon - * - */ - public function testTabWithIconClass() - { - $tab = new Tab( - array( - "name" => "tab", - "title" => "Title text", - "iconCls" => "myIcon" - ) - ); - $html = $tab->render(new ViewMock()); - - $this->assertEquals( - 1, - preg_match( - '/
  • <\/i> Title text<\/li>/i', - $html - ), - 'Asserting an url being rendered inside an HTML anchor. got ' . $html - ); - } -} diff --git a/test/php/library/Icinga/Web/Widget/Tabextension/OutputFormatTest.php b/test/php/library/Icinga/Web/Widget/Tabextension/OutputFormatTest.php deleted file mode 100644 index a9963e440..000000000 --- a/test/php/library/Icinga/Web/Widget/Tabextension/OutputFormatTest.php +++ /dev/null @@ -1,88 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Tests\Icinga\Web\Widget\Tabextension; - -require_once('../../library/Icinga/Web/Widget/Widget.php'); -require_once('../../library/Icinga/Web/Widget/Tab.php'); -require_once('../../library/Icinga/Web/Widget/Tabs.php'); -require_once('../../library/Icinga/Web/Widget/Tabextension/Tabextension.php'); -require_once('../../library/Icinga/Web/Widget/Tabextension/OutputFormat.php'); -require_once('../../library/Icinga/Web/Url.php'); - -require_once('library/Icinga/Web/RequestMock.php'); -require_once('library/Icinga/Web/ViewMock.php'); - -require_once('Zend/View/Abstract.php'); - -use Icinga\Web\View; -use Icinga\Web\Url; -use Icinga\Web\Widget\Tabextension\OutputFormat; -use PHPUnit_Framework_TestCase; -use Icinga\Web\Widget\Tabs; -use Tests\Icinga\Web\RequestMock; -use Tests\Icinga\Web\ViewMock; -use \Zend_View_Abstract; - -/** - * Test for the OutputFormat Tabextension - * - */ -class OutputFormatTest extends PHPUnit_Framework_TestCase -{ - /** - * Test if a simple apply adds all tabs from the extender - * - */ - public function testApply() - { - $tabs = new Tabs(); - Url::$overwrittenRequest = new RequestMock(); - $tabs->extend(new OutputFormat()); - $this->assertEquals(3, $tabs->count(), "Asserting new tabs being available after extending the tab bar"); - Url::$overwrittenRequest = null; - } - - /** - * Test if an apply with disabled output formats doesn't add these tabs - * - */ - public function testDisableOutputFormat() - { - Url::$overwrittenRequest = new RequestMock(); - $tabs = new Tabs(); - $tabs->extend(new OutputFormat(array(OutputFormat::TYPE_PDF))); - $this->assertEquals( - 2, - $tabs->count(), - "Asserting two tabs being available after extending the tab bar and ignoring PDF" - ); - Url::$overwrittenRequest = null; - } -} diff --git a/test/php/library/Icinga/Web/Widget/TabsTest.php b/test/php/library/Icinga/Web/Widget/TabsTest.php deleted file mode 100644 index aca489a57..000000000 --- a/test/php/library/Icinga/Web/Widget/TabsTest.php +++ /dev/null @@ -1,111 +0,0 @@ - - * @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2 - * @author Icinga Development Team - * - */ -// {{{ICINGA_LICENSE_HEADER}}} - -namespace Tests\Icinga\Web\Widget; - -require_once('../../library/Icinga/Web/Widget/Widget.php'); -require_once('../../library/Icinga/Web/Widget/Tab.php'); -require_once('../../library/Icinga/Web/Widget/Tabs.php'); -require_once('../../library/Icinga/Web/Url.php'); - -require_once('library/Icinga/Web/ViewMock.php'); -require_once('Zend/View/Abstract.php'); - -use Icinga\Web\View; -use Icinga\Web\Url; -use Icinga\Web\Widget\Tabs; -use Tests\Icinga\Web\ViewMock; - -use \Zend_View_Abstract; -use \PHPUnit_Framework_TestCase; - -/** - * Test rendering of tabs and corretct tab management - * - */ -class TabsTest extends PHPUnit_Framework_TestCase -{ - - /** - * Test adding tabs and asserting for correct count - * - */ - public function testAddTabs() - { - $tabs = new Tabs(); - $this->assertEquals(0, $tabs->count(), 'Asserting a tab bar starting with no items'); - $tabs->add('tab1', array('title' => 'Tab 1')); - $tabs->add('tab2', array('title' => 'Tab 2')); - $this->assertEquals(2, $tabs->count(), 'Asserting a tab bar containing 2 items after being added'); - - $this->assertTrue( - $tabs->has('tab1'), - 'Asserting the tab bar to determine the existence of added tabs correctly (tab1)' - ); - - $this->assertTrue( - $tabs->has('tab2'), - 'Asserting the tab bar to determine the existence of added tabs correctly (tab2)' - ); - } - - /** - * Test rendering of tabs when no dropdown is requested - * - */ - public function testRenderTabsWithoutDropdown() - { - $tabs = new Tabs(); - - $tabs->add('tab1', array('title' => 'Tab 1')); - $tabs->add('tab2', array('title' => 'Tab 2')); - - $html = $tabs->render(new ViewMock()); - $this->assertContains('
  • Tab 1
  • ', $html, 'Asserting tab 1 being rendered correctly' . $html); - $this->assertContains('
  • Tab 2
  • ', $html, 'Asserting tab 2 being rendered correctly' . $html); - $this->assertNotContains('class="dropdown ', 'Asserting the dropdown to not be rendered' . $html); - } - - /** - * Test rendering of tabs when dropdown is requested - * - */ - public function testRenderDropdown() - { - $tabs = new Tabs(); - - $tabs->add('tab1', array('title' => 'Tab 1')); - $tabs->addAsDropdown('tab2', array('title' => 'Tab 2')); - - $html = $tabs->render(new ViewMock()); - $this->assertContains('
  • Tab 1
  • ', $html, 'Asserting tab 1 being rendered correctly ' . $html); - $this->assertContains('
  • Tab 2
  • ', $html, 'Asserting tab 2 being rendered correctly ' . $html); - $this->assertContains('class="dropdown ', 'Asserting the dropdown to be rendered, got ' . $html); - } -} diff --git a/test/php/phpunit.xml b/test/php/phpunit.xml index 912f526dc..b36e81fe8 100644 --- a/test/php/phpunit.xml +++ b/test/php/phpunit.xml @@ -1,5 +1,5 @@ - +