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:
parent
b41d262537
commit
f1320b6510
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -92,11 +92,11 @@ class ModuleTestHelper
|
||||||
$this->json_file = $this->json_dir . $this->file_name . ".json";
|
$this->json_file = $this->json_dir . $this->file_name . ".json";
|
||||||
|
|
||||||
// never store time series data
|
// never store time series data
|
||||||
Config::set('norrd', true);
|
Config::set('rrd.enable', false);
|
||||||
Config::set('hide_rrd_disabled', true);
|
Config::set('hide_rrd_disabled', true);
|
||||||
Config::set('noinfluxdb', true);
|
Config::set('influxdb.enable', false);
|
||||||
$influxdb = false;
|
Config::set('graphite.enable', false);
|
||||||
Config::set('nographite', true);
|
Config::set('prometheus.enable', false);
|
||||||
|
|
||||||
if (is_null(self::$module_tables)) {
|
if (is_null(self::$module_tables)) {
|
||||||
// only load the yaml once, then keep it in memory
|
// only load the yaml once, then keep it in memory
|
||||||
|
@ -505,6 +505,7 @@ class ModuleTestHelper
|
||||||
public function generateTestData(Snmpsim $snmpsim, $no_save = false)
|
public function generateTestData(Snmpsim $snmpsim, $no_save = false)
|
||||||
{
|
{
|
||||||
global $device, $debug, $vdebug;
|
global $device, $debug, $vdebug;
|
||||||
|
Config::set('rrd.enable', false); // disable rrd
|
||||||
|
|
||||||
if (!is_file($this->snmprec_file)) {
|
if (!is_file($this->snmprec_file)) {
|
||||||
throw new FileNotFoundException("$this->snmprec_file does not exist!");
|
throw new FileNotFoundException("$this->snmprec_file does not exist!");
|
||||||
|
|
|
@ -21,6 +21,7 @@ use LibreNMS\Exceptions\HostUnreachablePingException;
|
||||||
use LibreNMS\Exceptions\InvalidPortAssocModeException;
|
use LibreNMS\Exceptions\InvalidPortAssocModeException;
|
||||||
use LibreNMS\Exceptions\LockException;
|
use LibreNMS\Exceptions\LockException;
|
||||||
use LibreNMS\Exceptions\SnmpVersionUnsupportedException;
|
use LibreNMS\Exceptions\SnmpVersionUnsupportedException;
|
||||||
|
use LibreNMS\Fping;
|
||||||
use LibreNMS\Util\IPv4;
|
use LibreNMS\Util\IPv4;
|
||||||
use LibreNMS\Util\IPv6;
|
use LibreNMS\Util\IPv6;
|
||||||
use LibreNMS\Util\MemcacheLock;
|
use LibreNMS\Util\MemcacheLock;
|
||||||
|
@ -676,7 +677,7 @@ function isPingable($hostname, $address_family = 'ipv4', $attribs = [])
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$status = fping(
|
$status = app()->make(Fping::class)->ping(
|
||||||
$hostname,
|
$hostname,
|
||||||
Config::get('fping_options.count', 3),
|
Config::get('fping_options.count', 3),
|
||||||
Config::get('fping_options.interval', 500),
|
Config::get('fping_options.interval', 500),
|
||||||
|
@ -1459,70 +1460,6 @@ function device_has_ip($ip)
|
||||||
return false; // not an ipv4 or ipv6 address...
|
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
|
* Try to determine the address family (IPv4 or IPv6) associated with an SNMP
|
||||||
* transport specifier (like "udp", "udp6", etc.).
|
* transport specifier (like "udp", "udp6", etc.).
|
||||||
|
|
5
ping.php
5
ping.php
|
@ -2,6 +2,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Jobs\PingCheck;
|
use App\Jobs\PingCheck;
|
||||||
|
use LibreNMS\Data\Store\Datastore;
|
||||||
|
|
||||||
$init_modules = ['alerts', 'laravel', 'nodb'];
|
$init_modules = ['alerts', 'laravel', 'nodb'];
|
||||||
require __DIR__ . '/includes/init.php';
|
require __DIR__ . '/includes/init.php';
|
||||||
|
@ -27,9 +28,7 @@ if (isset($options['v'])) {
|
||||||
$vdebug = true;
|
$vdebug = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($options['r'])) {
|
Datastore::init($options);
|
||||||
Config::set('norrd', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($options['g'])) {
|
if (isset($options['g'])) {
|
||||||
$groups = explode(',', $options['g']);
|
$groups = explode(',', $options['g']);
|
||||||
|
|
|
@ -11,8 +11,8 @@ $init_modules = array();
|
||||||
require $install_dir . '/includes/init.php';
|
require $install_dir . '/includes/init.php';
|
||||||
$options = getopt('dh:e:', array("help"));
|
$options = getopt('dh:e:', array("help"));
|
||||||
|
|
||||||
Config::set('norrd', true);
|
Config::set('rrd.enable', false);
|
||||||
Config::set('noinfluxdb', true);
|
Config::set('influxdb.enable', false);
|
||||||
Config::set('nographite', true);
|
Config::set('nographite', true);
|
||||||
|
|
||||||
function print_help()
|
function print_help()
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
namespace LibreNMS\Tests;
|
namespace LibreNMS\Tests;
|
||||||
|
|
||||||
|
use LibreNMS\Fping;
|
||||||
use Symfony\Component\Process\Process;
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
class FpingTest extends TestCase
|
class FpingTest extends TestCase
|
||||||
|
@ -45,7 +46,7 @@ class FpingTest extends TestCase
|
||||||
"exitcode" => 0,
|
"exitcode" => 0,
|
||||||
];
|
];
|
||||||
|
|
||||||
$actual = fping('192.168.1.3');
|
$actual = app()->make(Fping::class)->ping('192.168.1.3');
|
||||||
|
|
||||||
$this->assertSame($expected, $actual);
|
$this->assertSame($expected, $actual);
|
||||||
}
|
}
|
||||||
|
@ -66,7 +67,7 @@ class FpingTest extends TestCase
|
||||||
"exitcode" => 0,
|
"exitcode" => 0,
|
||||||
];
|
];
|
||||||
|
|
||||||
$actual = fping('192.168.1.7');
|
$actual = app()->make(Fping::class)->ping('192.168.1.7');
|
||||||
|
|
||||||
$this->assertSame($expected, $actual);
|
$this->assertSame($expected, $actual);
|
||||||
}
|
}
|
||||||
|
@ -87,7 +88,7 @@ class FpingTest extends TestCase
|
||||||
"exitcode" => 1,
|
"exitcode" => 1,
|
||||||
];
|
];
|
||||||
|
|
||||||
$actual = fping('192.168.53.1');
|
$actual = app()->make(Fping::class)->ping('192.168.53.1');
|
||||||
|
|
||||||
$this->assertSame($expected, $actual);
|
$this->assertSame($expected, $actual);
|
||||||
}
|
}
|
||||||
|
@ -113,7 +114,7 @@ OUT;
|
||||||
"exitcode" => 1,
|
"exitcode" => 1,
|
||||||
];
|
];
|
||||||
|
|
||||||
$actual = fping('192.168.1.2');
|
$actual = app()->make(Fping::class)->ping('192.168.1.2');
|
||||||
|
|
||||||
$this->assertSame($expected, $actual);
|
$this->assertSame($expected, $actual);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ use DeviceCache;
|
||||||
use LibreNMS\Config;
|
use LibreNMS\Config;
|
||||||
use LibreNMS\Exceptions\FileNotFoundException;
|
use LibreNMS\Exceptions\FileNotFoundException;
|
||||||
use LibreNMS\Exceptions\InvalidModuleException;
|
use LibreNMS\Exceptions\InvalidModuleException;
|
||||||
|
use LibreNMS\Fping;
|
||||||
use LibreNMS\Util\ModuleTestHelper;
|
use LibreNMS\Util\ModuleTestHelper;
|
||||||
|
|
||||||
class OSModulesTest extends DBTestCase
|
class OSModulesTest extends DBTestCase
|
||||||
|
@ -82,12 +83,8 @@ class OSModulesTest extends DBTestCase
|
||||||
public function testOS($os, $variant, $modules)
|
public function testOS($os, $variant, $modules)
|
||||||
{
|
{
|
||||||
$this->requireSnmpsim(); // require snmpsim for tests
|
$this->requireSnmpsim(); // require snmpsim for tests
|
||||||
|
// stub out Log::event and Fping->ping, we don't need to store them for these tests
|
||||||
// stub out Log::event, we don't need to store them for these tests
|
$this->stubClasses();
|
||||||
$this->app->bind('log', function ($app) {
|
|
||||||
return \Mockery::mock('\App\Facades\LogManager[event]', [$app])
|
|
||||||
->shouldReceive('event');
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
set_debug(false); // avoid all undefined index errors in the legacy code
|
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()]];
|
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;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue