From e80a385b7f66aad6b959660f557cbfbca4bbf66e Mon Sep 17 00:00:00 2001 From: Tony Murray Date: Mon, 22 Aug 2016 10:32:05 -0500 Subject: [PATCH] RRDtool dual process (remote creation/check) (#4104) * Prepare for dual rrdtool processes Disabled at this time Split out rrdtool version checks into rrdtool_create_command() Tests for rrdtool_create_command() Fixes a few small issues. * Enable dual process and remote rrd check/creation * remove full path for remote commands * Doc updates minor fix to rrdtool_tune() * Set up bootstrap for phpunit Fix issues with FileExistsException * Attempt to fix phpunit * Fix classloader and bootstrap to use full paths only (not depending on $config) * Fix phpunit tests, config.php does not exist. --- LibreNMS/ClassLoader.php | 76 ++++++++++-- check-services.php | 4 +- html/graph.php | 4 +- includes/functions.php | 10 +- includes/rrdtool.inc.php | 253 +++++++++++++++++++++++---------------- phpunit.xml | 4 +- poll-billing.php | 4 +- poller.php | 4 +- tests/RrdtoolTest.php | 101 ++++++++++++++++ tests/SyslogTest.php | 26 +++- tests/bootstrap.php | 40 +++++++ 11 files changed, 400 insertions(+), 126 deletions(-) create mode 100644 tests/RrdtoolTest.php create mode 100644 tests/bootstrap.php diff --git a/LibreNMS/ClassLoader.php b/LibreNMS/ClassLoader.php index ea63d8a9b6..b14f25bc47 100644 --- a/LibreNMS/ClassLoader.php +++ b/LibreNMS/ClassLoader.php @@ -33,16 +33,22 @@ namespace LibreNMS; class ClassLoader { /** - * @var array stores dynamically added class > file mappings + * @var array stores dynamically added class > file mappings ($classMap[fullclass] = $file) */ private $classMap; + /** + * @var array stores dynamically added namespace > directory mappings ($dirMap[namespace][$dir] =1) + */ + private $dirMap; + /** * ClassLoader constructor. */ public function __construct() { $this->classMap = array(); + $this->dirMap = array(); } /** @@ -52,9 +58,10 @@ class ClassLoader */ public static function psrLoad($name) { - global $config, $vdebug; + global $vdebug; + $file = str_replace(array('\\', '_'), DIRECTORY_SEPARATOR, $name) . '.php'; - $fullFile = $config['install_dir'] ? $config['install_dir'] . '/' . $file : $file; + $fullFile = realpath(__DIR__ . '/..') . DIRECTORY_SEPARATOR . $file; if($vdebug) { echo __CLASS__ . " [[ $name > $fullFile ]]\n"; @@ -73,7 +80,8 @@ class ClassLoader public function customLoad($name) { global $vdebug; - if (array_key_exists($name, $this->classMap)) { + + if (isset($this->classMap[$name])) { $file = $this->classMap[$name]; if($vdebug) { @@ -82,31 +90,72 @@ class ClassLoader if (is_readable($file)) { include $file; + return; + } + } + + list($namespace, $class) = $this->splitNamespace($name); + if (isset($this->dirMap[$namespace])) { + foreach (array_keys($this->dirMap[$namespace]) as $dir) { + $file = $dir . DIRECTORY_SEPARATOR . $class . '.php'; + + if($vdebug) { + echo __CLASS__ . " (( $name > $file ))\n"; + } + + if (is_readable($file)) { + include $file; + return; + } } } } /** - * Add or set a custom class > file mapping + * Register a custom class > file mapping * * @param string $class The full class name * @param string $file The path to the file containing the class, full path is preferred */ - public function mapClass($class, $file) + public function registerClass($class, $file) { $this->classMap[$class] = $file; } /** - * Remove a class from the list of class > file mappings + * Unregister a class from the list of class > file mappings * * @param string $class The full class name */ - public function unMapClass($class) + public function unregisterClass($class) { unset($this->classMap[$class]); } + /** + * Register a directory to search for classes in. + * If a namespace is specified, it will search for + * classes with that exact namespace in those directories. + * + * @param string $dir directory containing classes with filename = class.php + * @param string $namespace the namespace of the classes + */ + public function registerDir($dir, $namespace = '') + { + $this->dirMap[$namespace][$dir] = 1; + } + + /** + * Unregister a directory + * + * @param string $dir the directory to remove + * @param string $namespace the namespace of the classes + */ + public function unregisterDir($dir, $namespace = '') + { + unset($this->dirMap[$namespace][$dir]); + } + /** * Register this autoloader * Custom mappings will take precedence over PSR-0 @@ -125,4 +174,15 @@ class ClassLoader spl_autoload_unregister(array($this, 'customLoad')); spl_autoload_unregister(__NAMESPACE__.'\ClassLoader::psrLoad'); } + + /** + * Split a class into namspace/classname + * @param string $class the full class name to split + * @return array of the split class [namespace, classname] + */ + private function splitNamespace($class) { + $parts = explode('\\', $class); + $last = array_pop($parts); + return array(implode('\\', $parts), $last); + } } diff --git a/check-services.php b/check-services.php index fd408e7852..e418c8d385 100755 --- a/check-services.php +++ b/check-services.php @@ -46,11 +46,11 @@ if ($config['noinfluxdb'] !== true && $config['influxdb']['enable'] === true) { $influxdb = false; } -rrdtool_pipe_open($rrd_process, $rrd_pipes); +rrdtool_initialize(); foreach (dbFetchRows('SELECT * FROM `devices` AS D, `services` AS S WHERE S.device_id = D.device_id ORDER by D.device_id DESC') as $service) { // Run the polling function poll_service($service); } //end foreach -rrdtool_pipe_close($rrd_process, $rrd_pipes); +rrdtool_terminate(); diff --git a/html/graph.php b/html/graph.php index 7efba5e6a1..96b712c54b 100644 --- a/html/graph.php +++ b/html/graph.php @@ -37,8 +37,8 @@ require_once '../includes/definitions.inc.php'; // initialize the class loader and add custom mappings require_once $config['install_dir'] . '/LibreNMS/ClassLoader.php'; $classLoader = new LibreNMS\ClassLoader(); -$classLoader->mapClass('Console_Color2', $config['install_dir'] . '/includes/console_colour.php'); -$classLoader->mapClass('PasswordHash', $config['install_dir'] . '/html/lib/PasswordHash.php'); +$classLoader->registerClass('Console_Color2', $config['install_dir'] . '/includes/console_colour.php'); +$classLoader->registerClass('PasswordHash', $config['install_dir'] . '/html/lib/PasswordHash.php'); $classLoader->register(); require_once '../includes/common.php'; diff --git a/includes/functions.php b/includes/functions.php index 5c6e463f5f..dd4c3cfa24 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -23,11 +23,11 @@ use LibreNMS\Exceptions\SnmpVersionUnsupportedException; // initialize the class loader and add custom mappings require_once $config['install_dir'] . '/LibreNMS/ClassLoader.php'; $classLoader = new LibreNMS\ClassLoader(); -$classLoader->mapClass('Console_Color2', $config['install_dir'] . '/includes/console_colour.php'); -$classLoader->mapClass('Console_Table', $config['install_dir'] . '/includes/console_table.php'); -$classLoader->mapClass('PHPMailer', $config['install_dir'] . "/includes/phpmailer/class.phpmailer.php"); -$classLoader->mapClass('SMTP', $config['install_dir'] . "/includes/phpmailer/class.smtp.php"); -$classLoader->mapClass('PasswordHash', $config['install_dir'] . '/html/lib/PasswordHash.php'); +$classLoader->registerClass('Console_Color2', $config['install_dir'] . '/includes/console_colour.php'); +$classLoader->registerClass('Console_Table', $config['install_dir'] . '/includes/console_table.php'); +$classLoader->registerClass('PHPMailer', $config['install_dir'] . "/includes/phpmailer/class.phpmailer.php"); +$classLoader->registerClass('SMTP', $config['install_dir'] . "/includes/phpmailer/class.smtp.php"); +$classLoader->registerClass('PasswordHash', $config['install_dir'] . '/html/lib/PasswordHash.php'); $classLoader->register(); // Include from PEAR diff --git a/includes/rrdtool.inc.php b/includes/rrdtool.inc.php index bd4eff76aa..3f1a8c45e0 100644 --- a/includes/rrdtool.inc.php +++ b/includes/rrdtool.inc.php @@ -1,71 +1,100 @@ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * @package LibreNMS + * @link http://librenms.org * @copyright (C) 2006 - 2012 Adam Armstrong + * @copyright 2016 Tony Murray + * @author Adam Armstrong + * @author Tony Murray */ +use LibreNMS\Exceptions\FileExistsException; + /** * Opens up a pipe to RRDTool using handles provided * - * @param $rrd_process - * @param $rrd_pipes - * @global $config - * @return boolean + * @param bool $dual_process start an additional process that's output should be read after every command + * @return bool the process(s) have been successfully started */ -function rrdtool_pipe_open(&$rrd_process, &$rrd_pipes) +function rrdtool_initialize($dual_process = true) { - global $config; + global $config, $rrd_async_process, $rrd_async_pipes, $rrd_sync_process, $rrd_sync_pipes; - $command = $config['rrdtool'].' -'; + $command = $config['rrdtool'] . ' -'; - $descriptorspec = array( - 0 => array( - 'pipe', - 'r', - ), - // stdin is a pipe that the child will read from - 1 => array( - 'pipe', - 'w', - ), - // stdout is a pipe that the child will write to - 2 => array( - 'pipe', - 'w', - ), - // stderr is a pipe that the child will write to + $descriptor_spec = array( + 0 => array('pipe', 'r'), // stdin is a pipe that the child will read from + 1 => array('pipe', 'w'), // stdout is a pipe that the child will write to + 2 => array('pipe', 'w'), // stderr is a pipe that the child will write to ); $cwd = $config['rrd_dir']; $env = array(); - $rrd_process = proc_open($command, $descriptorspec, $rrd_pipes, $cwd, $env); + if(!is_resource($rrd_async_process)) { + $rrd_async_process = proc_open($command, $descriptor_spec, $rrd_async_pipes, $cwd, $env); + stream_set_blocking($rrd_async_pipes[1], false); + stream_set_blocking($rrd_async_pipes[2], false); + } - stream_set_blocking($rrd_pipes[1], false); - stream_set_blocking($rrd_pipes[2], false); + if ($dual_process && !is_resource($rrd_sync_process)) { + $rrd_sync_process = proc_open($command, $descriptor_spec, $rrd_sync_pipes, $cwd, $env); + stream_set_blocking($rrd_sync_pipes[1], false); + stream_set_blocking($rrd_sync_pipes[2], false); + } - return is_resource($rrd_process); + return is_resource($rrd_async_process) && ($dual_process ? is_resource($rrd_sync_process) : true); } +/** + * Close all open rrdtool processes. + * This should be done before exiting a script that has called rrdtool_initilize() + * + * @return bool indicates success + */ +function rrdtool_terminate() { + global $rrd_async_process, $rrd_async_pipes, $rrd_sync_process, $rrd_sync_pipes; + + $ret = rrdtool_pipe_close($rrd_async_process, $rrd_async_pipes); + if ($rrd_sync_pipes) { + $ret = rrdtool_pipe_close($rrd_sync_process, $rrd_sync_pipes) && $ret; + } + + return $ret; +} /** * Closes the pipe to RRDTool * + * @internal * @param resource $rrd_process * @param array $rrd_pipes * @return integer */ function rrdtool_pipe_close($rrd_process, &$rrd_pipes) { - d_echo(stream_get_contents($rrd_pipes[1])); - d_echo(stream_get_contents($rrd_pipes[2])); + global $vdebug; + if ($vdebug) { + d_echo(stream_get_contents($rrd_pipes[1])); + d_echo(stream_get_contents($rrd_pipes[2])); + } fclose($rrd_pipes[0]); fclose($rrd_pipes[1]); @@ -73,9 +102,7 @@ function rrdtool_pipe_close($rrd_process, &$rrd_pipes) // It is important that you close any pipes before calling // proc_close in order to avoid a deadlock - $return_value = proc_close($rrd_process); - - return $return_value; + return proc_close($rrd_process); } @@ -89,39 +116,30 @@ function rrdtool_pipe_close($rrd_process, &$rrd_pipes) */ function rrdtool_graph($graph_file, $options) { - global $config, $debug; + global $config, $debug, $rrd_async_pipes; - rrdtool_pipe_open($rrd_process, $rrd_pipes); - - if (is_resource($rrd_process)) { - // $pipes now looks like this: - // 0 => writeable handle connected to child stdin - // 1 => readable handle connected to child stdout - // Any error output will be appended to /tmp/error-output.txt + if (rrdtool_initialize(false)) { if ($config['rrdcached']) { $options = str_replace(array($config['rrd_dir'].'/', $config['rrd_dir']), '', $options); - - fwrite($rrd_pipes[0], 'graph --daemon ' . $config['rrdcached'] . " $graph_file $options"); + fwrite($rrd_async_pipes[0], 'graph --daemon ' . $config['rrdcached'] . " $graph_file $options"); } else { - fwrite($rrd_pipes[0], "graph $graph_file $options"); + fwrite($rrd_async_pipes[0], "graph $graph_file $options"); } - fclose($rrd_pipes[0]); + fclose($rrd_async_pipes[0]); $line = ""; $data = ""; while (strlen($line) < 1) { - $line = fgets($rrd_pipes[1], 1024); + $line = fgets($rrd_async_pipes[1], 1024); $data .= $line; } - $return_value = rrdtool_pipe_close($rrd_process, $rrd_pipes); + $return_value = rrdtool_terminate(); if ($debug) { echo '

'; - if ($debug) { - echo "graph $graph_file $options"; - } + echo "graph $graph_file $options"; echo '

'; echo "command returned $return_value ($data)\n"; @@ -142,59 +160,42 @@ function rrdtool_graph($graph_file, $options) * @param string $command create, update, updatev, graph, graphv, dump, restore, fetch, tune, first, last, lastupdate, info, resize, xport, flushcached * @param string $filename The full patth to the rrd file * @param string $options rrdtool command options - * @param integer $timeout seconds give up waiting for output, default 0 * @return array the output of stdout and stderr in an array * @global $config * @global $debug * @global $rrd_pipes */ -function rrdtool($command, $filename, $options, $timeout = 0) +function rrdtool($command, $filename, $options) { - global $config, $debug, $vdebug, $rrd_pipes; + global $config, $debug, $vdebug, $rrd_async_pipes, $rrd_sync_pipes; - // do not ovewrite files when creating - if ($command == 'create' && version_compare($config['rrdtool_version'], '1.4.3', '>=')) { - $options .= ' -O'; - } - // rrdcached commands: >=1.5.5: all, >=1.5 all: except tune, <1.5: all except tune and create - if ($config['rrdcached'] && - (version_compare($config['rrdtool_version'], '1.5.5', '>=') || - (version_compare($config['rrdtool_version'], '1.5', '>=') && $command != "tune") || - ($command != "create" && $command != "tune")) - ) { - - // only relative paths if using rrdcached - $filename = str_replace(array($config['rrd_dir'].'/', $config['rrd_dir']), '', $filename); - - // using rrdcached, append --daemon - $cmd = "$command $filename $options --daemon ".$config['rrdcached']; - } else { - $cmd = "$command $filename $options"; + try { + $cmd = rrdtool_build_command($command, $filename, $options); + } catch (FileExistsException $e) { + c_echo('RRD[%g' . $filename . " already exists%n]\n", $debug); + return array(null, null); } c_echo("RRD[%g$cmd%n]\n", $debug); // do not write rrd files, but allow read-only commands - if ($config['norrd'] && !in_array($command, - array('graph', 'graphv', 'dump', 'fetch', 'first', 'last', 'lastupdate', 'info', 'xport')) - ) { - c_echo("[%rRRD Disabled%n]\n"); - $output = array(null, null); - } elseif ($command == 'create' && version_compare($config['rrdtool_version'], '1.4.3', '<') && is_file($filename)) { - // do not overwrite RRD if it already exists and RRDTool ver. < 1.4.3 - c_echo("RRD[%g$filename already exists%n]\n", $debug); - $output = array(null, null); + $ro_commands = array('graph', 'graphv', 'dump', 'fetch', 'first', 'last', 'lastupdate', 'info', 'xport'); + if ($config['norrd'] && !in_array($command, $ro_commands)) { + c_echo('[%rRRD Disabled%n]'); + return array(null, null); + } + + // send the command! + if($command == 'last' && $rrd_sync_pipes) { + fwrite($rrd_sync_pipes[0], $cmd . "\n"); + + // this causes us to block until we receive output for up to the timeout in seconds + stream_select($r = $rrd_sync_pipes, $w = null, $x = null, 10); + $output = array(stream_get_contents($rrd_sync_pipes[1]), stream_get_contents($rrd_sync_pipes[2])); + } else { - if ($timeout > 0 && stream_select($r = $rrd_pipes, $w = null, $x = null, 0)) { - // dump existing data - stream_get_contents($rrd_pipes[1]); - } - - fwrite($rrd_pipes[0], $cmd . "\n"); - - // this causes us to block until we receive output for up to $timeout seconds - stream_select($r = $rrd_pipes, $w = null, $x = null, $timeout); - $output = array(stream_get_contents($rrd_pipes[1]), stream_get_contents($rrd_pipes[2])); + fwrite($rrd_async_pipes[0], $cmd . "\n"); + $output = array(stream_get_contents($rrd_async_pipes[1]), stream_get_contents($rrd_async_pipes[2])); } if ($vdebug) { @@ -207,15 +208,62 @@ function rrdtool($command, $filename, $options, $timeout = 0) } /** - * Checks if the rrd file exists on the server - * This will perform a remote check if using rrdcached and rrdtool >= 1.5 (broken) + * Build a command for rrdtool + * Shortens the filename as needed + * Determines if --daemon and -O should be used * - * @param $filename - * @return bool + * @internal + * @param string $command The base rrdtool command. Usually create, update, last. + * @param string $filename The full path to the rrd file + * @param string $options Options for the command possibly including the rrd definition + * @return string returns a full command ready to be piped to rrdtool + * @throws FileExistsException if rrdtool <1.4.3 and the rrd file exists locally + */ +function rrdtool_build_command($command, $filename, $options) +{ + global $config; + + if ($command == 'create') { + // <1.4.3 doesn't support -O, so make sure the file doesn't exist + if (version_compare($config['rrdtool_version'], '1.4.3', '<')) { + if (is_file($filename)) { + throw new FileExistsException(); + } + } else { + $options .= ' -O'; + } + } + + // no remote for create < 1.5.5 and tune < 1.5 + if ($config['rrdcached'] && + !($command == 'create' && version_compare($config['rrdtool_version'], '1.5.5', '<')) && + !($command == 'tune' && $config['rrdcached'] && version_compare($config['rrdtool_version'], '1.5', '<')) + ) { + // only relative paths if using rrdcached + $filename = str_replace(array($config['rrd_dir'].'/', $config['rrd_dir']), '', $filename); + + return "$command $filename $options --daemon " . $config['rrdcached']; + } + + return "$command $filename $options"; +} + +/** + * Checks if the rrd file exists on the server + * This will perform a remote check if using rrdcached and rrdtool >= 1.5 + * + * @param string $filename full path to the rrd file + * @return bool whether or not the passed rrd file exists */ function rrdtool_check_rrd_exists($filename) { - return is_file($filename); + global $config; + if ($config['rrdcached'] && version_compare($config['rrdtool_version'], '1.5', '>=')) { + $chk = rrdtool('last', $filename, ''); + return strpos(implode($chk), "$filename': No such file or directory") === false; + } else { + return is_file($filename); + } } /** @@ -348,6 +396,7 @@ function rrdtool_tune($type, $filename, $max) $options = "--maximum " . implode(":$max --maximum ", $fields) . ":$max"; rrdtool('tune', $filename, $options); } + return true; } // rrdtool_tune @@ -383,7 +432,7 @@ function rrdtool_data_update($device, $measurement, $tags, $fields) $rrd = rrd_name($device['hostname'], $rrd_name); } - if ($tags['rrd_def']) { + if ($tags['rrd_def'] && !rrdtool_check_rrd_exists($rrd)) { $rrd_def = is_array($tags['rrd_def']) ? $tags['rrd_def'] : array($tags['rrd_def']); // add the --step and the rra definitions to the command $newdef = "--step $step " . implode(' ', $rrd_def) . $config['rrd_rra']; diff --git a/phpunit.xml b/phpunit.xml index 26bc37ed3b..439342dd3d 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,8 +1,8 @@ - + - ./tests/ + tests/ diff --git a/poll-billing.php b/poll-billing.php index 8bc7be9a4d..f1a29d4c5c 100755 --- a/poll-billing.php +++ b/poll-billing.php @@ -22,7 +22,7 @@ require 'includes/functions.php'; $iter = '0'; -rrdtool_pipe_open($rrd_process, $rrd_pipes); +rrdtool_initialize(); $poller_start = microtime(true); echo "Starting Polling Session ... \n\n"; @@ -158,4 +158,4 @@ if ($poller_time > 300) { } echo "\nCompleted in $poller_time sec\n"; -rrdtool_pipe_close($rrd_process, $rrd_pipes); +rrdtool_terminate(); \ No newline at end of file diff --git a/poller.php b/poller.php index 78254d8192..5a6d5b47dc 100755 --- a/poller.php +++ b/poller.php @@ -125,7 +125,7 @@ else { $influxdb = false; } -rrdtool_pipe_open($rrd_process, $rrd_pipes); +rrdtool_initialize(); echo "Starting polling run:\n\n"; $polled_devices = 0; @@ -158,7 +158,7 @@ echo ("\n".'MySQL: Cell['.($db_stats['fetchcell'] + 0).'/'.round(($db_stats['fet echo "\n"; logfile($string); -rrdtool_pipe_close($rrd_process, $rrd_pipes); +rrdtool_terminate(); unset($config); // Remove this for testing // print_r(get_defined_vars()); diff --git a/tests/RrdtoolTest.php b/tests/RrdtoolTest.php new file mode 100644 index 0000000000..261b38b9bd --- /dev/null +++ b/tests/RrdtoolTest.php @@ -0,0 +1,101 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2016 Tony Murray + * @author Tony Murray + */ + +namespace LibreNMS\Tests; + +class RrdtoolTest extends \PHPUnit_Framework_TestCase +{ + + public function testBuildCommandLocal() + { + global $config; + $config['rrdcached'] = ''; + $config['rrdtool_version'] = '1.4'; + $config['rrd_dir'] = '/opt/librenms/rrd'; + + $cmd = rrdtool_build_command('create', '/opt/librenms/rrd/f', 'o'); + $this->assertEquals('create /opt/librenms/rrd/f o', $cmd); + + $cmd = rrdtool_build_command('tune', '/opt/librenms/rrd/f', 'o'); + $this->assertEquals('tune /opt/librenms/rrd/f o', $cmd); + + $cmd = rrdtool_build_command('update', '/opt/librenms/rrd/f', 'o'); + $this->assertEquals('update /opt/librenms/rrd/f o', $cmd); + + + $config['rrdtool_version'] = '1.6'; + + $cmd = rrdtool_build_command('create', '/opt/librenms/rrd/f', 'o'); + $this->assertEquals('create /opt/librenms/rrd/f o -O', $cmd); + + $cmd = rrdtool_build_command('tune', '/opt/librenms/rrd/f', 'o'); + $this->assertEquals('tune /opt/librenms/rrd/f o', $cmd); + + $cmd = rrdtool_build_command('update', '/opt/librenms/rrd/f', 'o'); + $this->assertEquals('update /opt/librenms/rrd/f o', $cmd); + } + + public function testBuildCommandRemote() + { + global $config; + $config['rrdcached'] = 'server:42217'; + $config['rrdtool_version'] = '1.4'; + $config['rrd_dir'] = '/opt/librenms/rrd'; + + $cmd = rrdtool_build_command('create', '/opt/librenms/rrd/f', 'o'); + $this->assertEquals('create /opt/librenms/rrd/f o', $cmd); + + $cmd = rrdtool_build_command('tune', '/opt/librenms/rrd/f', 'o'); + $this->assertEquals('tune /opt/librenms/rrd/f o', $cmd); + + $cmd = rrdtool_build_command('update', '/opt/librenms/rrd/f', 'o'); + $this->assertEquals('update f o --daemon server:42217', $cmd); + + + $config['rrdtool_version'] = '1.6'; + + $cmd = rrdtool_build_command('create', '/opt/librenms/rrd/f', 'o'); + $this->assertEquals('create f o -O --daemon server:42217', $cmd); + + $cmd = rrdtool_build_command('tune', '/opt/librenms/rrd/f', 'o'); + $this->assertEquals('tune f o --daemon server:42217', $cmd); + + $cmd = rrdtool_build_command('update', '/opt/librenms/rrd/f', 'o'); + $this->assertEquals('update f o --daemon server:42217', $cmd); + + } + + public function testBuildCommandException() + { + global $config; + $config['rrdcached'] = ''; + $config['rrdtool_version'] = '1.4'; + + $this->setExpectedException('LibreNMS\Exceptions\FileExistsException'); + // use this file, since it is guaranteed to exist + rrdtool_build_command('create', __FILE__, 'o'); + } + +} diff --git a/tests/SyslogTest.php b/tests/SyslogTest.php index 1d78ffeef3..b8b70b25cf 100644 --- a/tests/SyslogTest.php +++ b/tests/SyslogTest.php @@ -1,5 +1,29 @@ . + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2016 Tony Murray + * @author Tony Murray + */ + +namespace LibreNMS\Tests; class SyslogTest extends \PHPUnit_Framework_TestCase { diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000000..c7a3507dc5 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,40 @@ +. + * + * @package LibreNMS + * @link http://librenms.org + * @copyright 2016 Tony Murray + * @author Tony Murray + */ + +// get the current LibreNMS install directory +$install_dir = realpath(__DIR__ . '/..'); + +require_once $install_dir . '/LibreNMS/ClassLoader.php'; + +// initialize the class loader +$loader = new LibreNMS\ClassLoader(); +$loader->registerDir($install_dir . '/tests', 'LibreNMS\Tests'); +$loader->register(); + +require_once $install_dir . '/includes/defaults.inc.php'; + +require_once $install_dir . '/includes/rrdtool.inc.php'; +require_once $install_dir . '/includes/syslog.php'; +