Speed up tests by skipping pings (#11642)

* Mock fping for module tests, there is no need.
Removes some wait time.

* fixup some rrd disabling code

* oops
This commit is contained in:
Tony Murray 2020-05-19 22:08:41 -05:00 committed by GitHub
parent b41d262537
commit f1320b6510
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 134 additions and 84 deletions

91
LibreNMS/Fping.php Normal file
View File

@ -0,0 +1,91 @@
<?php
/**
* Fping.php
*
* -Description-
*
* 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 <http://www.gnu.org/licenses/>.
*
* @package LibreNMS
* @link http://librenms.org
* @copyright 2020 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace LibreNMS;
use Log;
use Symfony\Component\Process\Process;
class Fping
{
/**
* Run fping against a hostname/ip in count mode and collect stats.
*
* @param string $host
* @param int $count (min 1)
* @param int $interval (min 20)
* @param int $timeout (not more than $interval)
* @param string $address_family ipv4 or ipv6
* @return array
*/
public function ping($host, $count = 3, $interval = 1000, $timeout = 500, $address_family = 'ipv4')
{
// Default to ipv4
$fping_name = $address_family == 'ipv6' ? 'fping6' : 'fping';
$interval = max($interval, 20);
// build the command
$cmd = [
Config::get($fping_name, $fping_name),
'-e',
'-q',
'-c',
max($count, 1),
'-p',
$interval,
'-t',
max($timeout, $interval),
$host
];
$process = app()->make(Process::class, ['command' => $cmd]);
Log::debug('[FPING] ' . $process->getCommandLine() . PHP_EOL);
$process->run();
$output = $process->getErrorOutput();
preg_match('#= (\d+)/(\d+)/(\d+)%(, min/avg/max = ([\d.]+)/([\d.]+)/([\d.]+))?$#', $output, $parsed);
[, $xmt, $rcv, $loss, , $min, $avg, $max] = array_pad($parsed, 8, 0);
if ($loss < 0) {
$xmt = 1;
$rcv = 1;
$loss = 100;
}
$response = [
'xmt' => (int)$xmt,
'rcv' => (int)$rcv,
'loss' => (int)$loss,
'min' => (float)$min,
'max' => (float)$max,
'avg' => (float)$avg,
'dup' => substr_count($output, 'duplicate'),
'exitcode' => $process->getExitCode(),
];
Log::debug('response: ', $response);
return $response;
}
}

View File

@ -92,11 +92,11 @@ class ModuleTestHelper
$this->json_file = $this->json_dir . $this->file_name . ".json";
// never store time series data
Config::set('norrd', true);
Config::set('rrd.enable', false);
Config::set('hide_rrd_disabled', true);
Config::set('noinfluxdb', true);
$influxdb = false;
Config::set('nographite', true);
Config::set('influxdb.enable', false);
Config::set('graphite.enable', false);
Config::set('prometheus.enable', false);
if (is_null(self::$module_tables)) {
// only load the yaml once, then keep it in memory
@ -505,6 +505,7 @@ class ModuleTestHelper
public function generateTestData(Snmpsim $snmpsim, $no_save = false)
{
global $device, $debug, $vdebug;
Config::set('rrd.enable', false); // disable rrd
if (!is_file($this->snmprec_file)) {
throw new FileNotFoundException("$this->snmprec_file does not exist!");

View File

@ -21,6 +21,7 @@ use LibreNMS\Exceptions\HostUnreachablePingException;
use LibreNMS\Exceptions\InvalidPortAssocModeException;
use LibreNMS\Exceptions\LockException;
use LibreNMS\Exceptions\SnmpVersionUnsupportedException;
use LibreNMS\Fping;
use LibreNMS\Util\IPv4;
use LibreNMS\Util\IPv6;
use LibreNMS\Util\MemcacheLock;
@ -676,7 +677,7 @@ function isPingable($hostname, $address_family = 'ipv4', $attribs = [])
];
}
$status = fping(
$status = app()->make(Fping::class)->ping(
$hostname,
Config::get('fping_options.count', 3),
Config::get('fping_options.interval', 500),
@ -1459,70 +1460,6 @@ function device_has_ip($ip)
return false; // not an ipv4 or ipv6 address...
}
/**
* Run fping against a hostname/ip in count mode and collect stats.
*
* @param string $host
* @param int $count (min 1)
* @param int $interval (min 20)
* @param int $timeout (not more than $interval)
* @param string $address_family ipv4 or ipv6
* @return array
*/
function fping($host, $count = 3, $interval = 1000, $timeout = 500, $address_family = 'ipv4')
{
// Default to ipv4
$fping_name = $address_family == 'ipv6' ? 'fping6' : 'fping';
$interval = max($interval, 20);
// build the command
$cmd = [
Config::get($fping_name, $fping_name),
'-e',
'-q',
'-c',
max($count, 1),
'-p',
$interval,
'-t',
max($timeout, $interval),
$host
];
$process = app()->make(Process::class, ['command' => $cmd]);
d_echo('[FPING] ' . $process->getCommandLine() . PHP_EOL);
$process->run();
$output = $process->getErrorOutput();
preg_match('#= (\d+)/(\d+)/(\d+)%(, min/avg/max = ([\d.]+)/([\d.]+)/([\d.]+))?$#', $output, $parsed);
[, $xmt, $rcv, $loss, , $min, $avg, $max] = array_pad($parsed, 8, 0);
if ($loss < 0) {
$xmt = 1;
$rcv = 1;
$loss = 100;
}
$response = [
'xmt' => (int)$xmt,
'rcv' => (int)$rcv,
'loss' => (int)$loss,
'min' => (float)$min,
'max' => (float)$max,
'avg' => (float)$avg,
'dup' => substr_count($output, 'duplicate'),
'exitcode' => $process->getExitCode(),
];
d_echo($response);
return $response;
}
function function_check($function)
{
return function_exists($function);
}
/**
* Try to determine the address family (IPv4 or IPv6) associated with an SNMP
* transport specifier (like "udp", "udp6", etc.).

View File

@ -2,6 +2,7 @@
<?php
use App\Jobs\PingCheck;
use LibreNMS\Data\Store\Datastore;
$init_modules = ['alerts', 'laravel', 'nodb'];
require __DIR__ . '/includes/init.php';
@ -27,9 +28,7 @@ if (isset($options['v'])) {
$vdebug = true;
}
if (isset($options['r'])) {
Config::set('norrd', true);
}
Datastore::init($options);
if (isset($options['g'])) {
$groups = explode(',', $options['g']);

View File

@ -11,8 +11,8 @@ $init_modules = array();
require $install_dir . '/includes/init.php';
$options = getopt('dh:e:', array("help"));
Config::set('norrd', true);
Config::set('noinfluxdb', true);
Config::set('rrd.enable', false);
Config::set('influxdb.enable', false);
Config::set('nographite', true);
function print_help()

View File

@ -25,6 +25,7 @@
namespace LibreNMS\Tests;
use LibreNMS\Fping;
use Symfony\Component\Process\Process;
class FpingTest extends TestCase
@ -45,7 +46,7 @@ class FpingTest extends TestCase
"exitcode" => 0,
];
$actual = fping('192.168.1.3');
$actual = app()->make(Fping::class)->ping('192.168.1.3');
$this->assertSame($expected, $actual);
}
@ -66,7 +67,7 @@ class FpingTest extends TestCase
"exitcode" => 0,
];
$actual = fping('192.168.1.7');
$actual = app()->make(Fping::class)->ping('192.168.1.7');
$this->assertSame($expected, $actual);
}
@ -87,7 +88,7 @@ class FpingTest extends TestCase
"exitcode" => 1,
];
$actual = fping('192.168.53.1');
$actual = app()->make(Fping::class)->ping('192.168.53.1');
$this->assertSame($expected, $actual);
}
@ -113,7 +114,7 @@ OUT;
"exitcode" => 1,
];
$actual = fping('192.168.1.2');
$actual = app()->make(Fping::class)->ping('192.168.1.2');
$this->assertSame($expected, $actual);
}

View File

@ -29,6 +29,7 @@ use DeviceCache;
use LibreNMS\Config;
use LibreNMS\Exceptions\FileNotFoundException;
use LibreNMS\Exceptions\InvalidModuleException;
use LibreNMS\Fping;
use LibreNMS\Util\ModuleTestHelper;
class OSModulesTest extends DBTestCase
@ -82,12 +83,8 @@ class OSModulesTest extends DBTestCase
public function testOS($os, $variant, $modules)
{
$this->requireSnmpsim(); // require snmpsim for tests
// stub out Log::event, we don't need to store them for these tests
$this->app->bind('log', function ($app) {
return \Mockery::mock('\App\Facades\LogManager[event]', [$app])
->shouldReceive('event');
});
// stub out Log::event and Fping->ping, we don't need to store them for these tests
$this->stubClasses();
try {
set_debug(false); // avoid all undefined index errors in the legacy code
@ -158,4 +155,28 @@ class OSModulesTest extends DBTestCase
return [[false, false, $e->getMessage()]];
}
}
private function stubClasses(): void
{
$this->app->bind('log', function ($app) {
return \Mockery::mock('\App\Facades\LogManager[event]', [$app])
->shouldReceive('event');
});
$this->app->bind(Fping::class, function ($app) {
$mock = \Mockery::mock('\LibreNMS\Fping');
$mock->shouldReceive('ping')->andReturn([
"xmt" => 3,
"rcv" => 3,
"loss" => 0,
"min" => 0.62,
"max" => 0.93,
"avg" => 0.71,
"dup" => 0,
"exitcode" => 0,
]);
return $mock;
});
}
}