diff --git a/LibreNMS/Util/ModuleTestHelper.php b/LibreNMS/Util/ModuleTestHelper.php index a4b2700385..ae06d216ed 100644 --- a/LibreNMS/Util/ModuleTestHelper.php +++ b/LibreNMS/Util/ModuleTestHelper.php @@ -201,6 +201,11 @@ class ModuleTestHelper // generate a full list of modules $full_list = array(); foreach ($modules as $module) { + // only allow valid modules + if (!(Config::has("poller_modules.$module") || Config::has("discovery_modules.$module"))) { + continue; + } + if (isset($module_deps[$module])) { $full_list = array_merge($full_list, $module_deps[$module]); } else { @@ -339,8 +344,8 @@ class ModuleTestHelper $output = implode(PHP_EOL, $results) . PHP_EOL; if ($write) { - $this->qPrint("Updated snmprec data $this->snmprec_file\n"); - $this->qPrint("Verify these files do not contain any private data before submitting\n"); + $this->qPrint("\nUpdated snmprec data $this->snmprec_file\n"); + $this->qPrint("\nVerify this file does not contain any private data before submitting!\n"); file_put_contents($this->snmprec_file, $output); } diff --git a/doc/Developing/os/Test-Units.md b/doc/Developing/os/Test-Units.md index 54403ba019..4da024e5af 100644 --- a/doc/Developing/os/Test-Units.md +++ b/doc/Developing/os/Test-Units.md @@ -32,9 +32,15 @@ one variant, please do not specify one. After you have saved your test data, you should run `./scripts/pre-commit.php -p -u` verify they pass. -If you would like to test the data for a specific OS, use `./scripts/pre-commit.php -p --os osname`. +To run the full suite of tests enable database and snmpsim reliant tests: `./scripts/pre-commit.php --db --snmpsim -p -u` -To run the full suite of tests enable db and snmpsim reliant tests: `./scripts/pre-commit.php --db --snmpsim -p -u` +#### Specific OS + +`./scripts/pre-commit.php -p -o osname` + +#### Specific Module + +`./scripts/pre-commit.php -p -m modulename` ## Using snmpsim for testing diff --git a/scripts/pre-commit.php b/scripts/pre-commit.php index 37adcd11fd..96c2bdce85 100755 --- a/scripts/pre-commit.php +++ b/scripts/pre-commit.php @@ -7,12 +7,13 @@ chdir($install_dir); require $install_dir . '/vendor/autoload.php'; -$short_opts = 'lsufpcho:'; +$short_opts = 'lsufpcho:m:'; $long_opts = array( 'lint', 'style', 'unit', 'os:', + 'module:', 'fail-fast', 'passthru', 'snmpsim', @@ -28,7 +29,8 @@ Running $filename without options runs all checks. -l, --lint Run php lint checks to test for valid syntax -s, --style Run phpcs check to check for PSR-2 compliance -u, --unit Run phpunit tests - -o, --os Specific OS to run tests on. Implies --unit + -o, --os Specific OS to run tests on. Implies --unit, --db, --snmpsim + -m, --module Specific Module to run tests on. Implies --unit, --db, --snmpsim -f, --fail-fast Quit when any failure is encountered -p, --passthru Display output from checks as it comes --db Run unit tests that require a database @@ -56,6 +58,14 @@ if ($os = check_opt($options, 'os', 'o')) { $options['db'] = false; } +if ($module = check_opt($options, 'm', 'module')) { + putenv("TEST_MODULES=$module"); + // enable unit tests, snmpsim, and db + $options['u'] = false; + $options['snmpsim'] = false; + $options['db'] = false; +} + $all = !check_opt($options, 'l', 'lint', 's', 'style', 'u', 'unit'); if ($all) { // no test specified, run all tests in this order @@ -78,7 +88,7 @@ foreach (array_keys($options) as $opt) { } elseif ($opt == 's' || $opt == 'style') { $ret = run_check('style', $passthru, $command_only); } elseif ($opt == 'u' || $opt == 'unit') { - $ret = run_check('unit', $passthru, $command_only, $fail_fast, $os); + $ret = run_check('unit', $passthru, $command_only, compact('fail_fast', 'os', 'module')); } if ($fail_fast && $ret !== 0 && $ret !== 250) { @@ -102,11 +112,10 @@ exit($return); //return the combined/single return value of tests * @param string $type type of check lint, style, or unit * @param bool $passthru display the output as comes in * @param bool $command_only only display the intended command, no checks - * @param bool $fail_fast Quit as soon as possible if error or failure - * @param string $os Only check a specific OS + * @param array $options command specific options * @return int the return value from the check (0 = success) */ -function run_check($type, $passthru, $command_only, $fail_fast = false, $os = null) +function run_check($type, $passthru, $command_only, $options = array()) { global $completed_tests; if (getenv('SKIP_' . strtoupper($type) . '_CHECK') || $completed_tests[$type]) { @@ -117,7 +126,7 @@ function run_check($type, $passthru, $command_only, $fail_fast = false, $os = nu $function = 'check_' . $type; if (function_exists($function)) { $completed_tests[$type] = true; - return $function($passthru, $command_only, $fail_fast, $os); + return $function($passthru, $command_only, $options); } return 1; @@ -217,22 +226,25 @@ function check_style($passthru = false, $command_only = false) * * @param bool $passthru display the output as comes in * @param bool $command_only only display the intended command, no checks - * @param bool $fail_fast Stop when any error or failure is encountered - * @param string $os only check a specific OS + * @param array $options Supported: fail_fast, os, module * @return int the return value from phpunit (0 = success) */ -function check_unit($passthru = false, $command_only = false, $fail_fast = false, $os = null) +function check_unit($passthru = false, $command_only = false, $options = array()) { $phpunit_bin = check_exec('phpunit'); $phpunit_cmd = "$phpunit_bin --colors=always"; - if ($fail_fast) { + if ($options['fail_fast']) { $phpunit_cmd .= ' --stop-on-error --stop-on-failure'; } - if (!is_null($os)) { - $phpunit_cmd .= " --group os --filter \"@$os.*\""; + if ($options['os']) { + $phpunit_cmd .= " --group os --filter \"@{$options['os']}.*\""; + } + + if ($options['module']) { + $phpunit_cmd .= ' tests/OSModulesTest.php'; } if ($command_only) { diff --git a/scripts/save-test-data.php b/scripts/save-test-data.php index 3807a05b68..013a9200b4 100755 --- a/scripts/save-test-data.php +++ b/scripts/save-test-data.php @@ -12,9 +12,10 @@ $install_dir = realpath(__DIR__ . '/..'); chdir($install_dir); $options = getopt( - 'h:dnm:o:v:f:', + 'h:dncm:o:v:f:', array( 'debug', + 'collect-only', 'no-save', 'prefer-new', 'hostname:', @@ -69,20 +70,21 @@ if (isset($hostname)) { } if (isset($options['help']) || empty($target_os)) { - echo "Script to extract test data from devices or update test data + echo "Script to extract test data from devices or update test data. +Snmp data is saved in tests/snmpsim and database data is saved in tests/data. Usage: You must specify a valid hostname or os. - -h, --hostname ID, IP, or hostname of the device to extract data from - If this is not given, the existing snmp data will be used - -o, --os Name of the OS to save test data for - -v, --variant The variant of the OS to use, usually the device model - -m, --modules The discovery/poller module(s) to collect data for, comma delimited - -f, --file File to save the database entries to. Default is in tests/data/ - -d, --debug Enable debug output - -n, --prefer-new Prefer new snmprec data over existing data - --no-save Don't save database entries, print them out instead - --snmpsim Just run snmpsimd.py for manual testing. + -h, --hostname ID, IP, or hostname of the device to extract data from + If this is not given, the existing snmp data will be used + -o, --os Name of the OS to save test data for + -v, --variant The variant of the OS to use, usually the device model + -m, --modules The discovery/poller module(s) to collect data for, comma delimited + -c, --collect-only Only collect snmpsim data (does not require snmpsim) + -d, --debug Enable debug output + -n, --prefer-new Prefer new snmprec data over existing data + --no-save Don't save database entries, print them out instead + --snmpsim Just run snmpsimd.py for manual testing. "; exit; } @@ -112,7 +114,6 @@ if ($variant) { } echo PHP_EOL; - $tester = new ModuleTestHelper($modules, $target_os, $variant); @@ -122,6 +123,11 @@ if ($device) { $prefer_new_snmprec = isset($options['n']) || isset($options['prefer-new']); $tester->captureFromDevice($device['device_id'], true, $prefer_new_snmprec); + if (isset($options['c']) || isset($options['collect-only'])) { + // just capture, don't generate json + exit; + } + echo PHP_EOL; } diff --git a/tests/OSModulesTest.php b/tests/OSModulesTest.php index 7b9fdbb41b..f7bc588c5b 100644 --- a/tests/OSModulesTest.php +++ b/tests/OSModulesTest.php @@ -36,10 +36,11 @@ class OSModulesTest extends DBTestCase * * @group os * @dataProvider dumpedDataProvider - * @param string $target_os - * @param string $filename + * @param string $target_os name of the (and variant) to test + * @param string $filename file name of the json data + * @param array $modules modules to test for this os */ - public function testOS($target_os, $filename) + public function testOS($target_os, $filename, $modules) { $this->requreSnmpsim(); // require snmpsim for tests global $snmpsim; @@ -48,23 +49,27 @@ class OSModulesTest extends DBTestCase $expected_data = json_decode(file_get_contents($file), true); list($os, $variant) = explode('_', $target_os, 2); - $modules = array_keys($expected_data); + $helper = new ModuleTestHelper($modules, $os, $variant); $helper->setQuiet(); $results = $helper->generateTestData($snmpsim, true); - foreach ($expected_data as $module => $data) { + foreach ($modules as $module) { $this->assertEquals( - $data['discovery'], + $expected_data[$module]['discovery'], $results[$module]['discovery'], - "OS $target_os: Discovered $module data does not match that found in $filename\n" . $helper->getLastDiscoveryOutput() + "OS $target_os: Discovered $module data does not match that found in $filename\n" + . $helper->getLastDiscoveryOutput() + . "\nOS $target_os: Polled $module data does not match that found in $filename" ); $this->assertEquals( - $data['poller'] == 'matches discovery' ? $data['discovery'] : $data['poller'], + $expected_data[$module]['poller'] == 'matches discovery' ? $expected_data[$module]['discovery'] : $expected_data[$module]['poller'], $results[$module]['poller'], - "OS $target_os: Polled $module data does not match that found in $filename\n" . $helper->getLastPollerOutput() + "OS $target_os: Polled $module data does not match that found in $filename\n" + . $helper->getLastPollerOutput() + . "\nOS $target_os: Polled $module data does not match that found in $filename" ); } } @@ -75,14 +80,23 @@ class OSModulesTest extends DBTestCase $install_dir = Config::get('install_dir'); $dump_files = glob("$install_dir/tests/data/*.json"); $data = array(); + $modules = getenv('TEST_MODULES') ? explode(',', getenv('TEST_MODULES')) : array(); foreach ($dump_files as $file) { $os = basename($file, '.json'); $short_file = str_replace($install_dir.'/', '', $file); + $data_modules = array_keys(json_decode(file_get_contents($file), true)); + + if (count(array_diff($modules, $data_modules)) !== 0) { + continue; // no test data for selected modules + } + + $test_modules = empty($modules) ? $data_modules : array_intersect($modules, $data_modules); $data[$os] = array( $os, - $short_file + $short_file, + $test_modules, ); }