librenms/tests/MibTest.php

203 lines
5.9 KiB
PHP
Raw Normal View History

<?php
/**
* MibTest.php
*
* Test Mib files for errors
*
* 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 2017 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace LibreNMS\Tests;
use Exception;
use LibreNMS\Config;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use SplFileInfo;
/**
* Class MibTest
* @package LibreNMS\Tests
*
* Tests mib files for errors.
* Will not be run by default, use --group=mibs to test.
* You may test specific directories or files by specifying them with filter. Example: --filter=@RFC1284-MIB
*/
class MibTest extends TestCase
{
/**
* Test mib file in a directory for errors
*
* @group mibs
* @dataProvider mibDirs
* @param $dir
*/
public function testMibDirectory($dir)
{
$output = shell_exec("snmptranslate -M +" . Config::get('mib_dir') . ":$dir -m +ALL SNMPv2-MIB::system 2>&1");
$errors = str_replace("SNMPv2-MIB::system\n", '', $output);
$this->assertEmpty($errors, "MIBs in $dir have errors!\n$errors");
}
/**
* Test that each mib only exists once.
*
* @group mibs
* @dataProvider mibFiles
* @param $path
* @param $file
* @param $mib_name
*/
public function testDuplicateMibs($path, $file, $mib_name)
{
global $console_color;
$file_path = "$path/$file";
$highligted_mib = $console_color->convert("%r$mib_name%n");
static $existing_mibs;
if (is_null($existing_mibs)) {
$existing_mibs = array();
}
if (isset($existing_mibs[$mib_name])) {
$existing_mibs[$mib_name][] = $file_path;
$this->fail("$highligted_mib has duplicates: " . implode(', ', $existing_mibs[$mib_name]));
} else {
$existing_mibs[$mib_name] = array($file_path);
}
}
/**
* Test that the file name matches the mib name
*
* @group mibs
* @dataProvider mibFiles
* @param $path
* @param $file
* @param $mib_name
*/
public function testMibNameMatches($path, $file, $mib_name)
{
global $console_color;
$file_path = "$path/$file";
$highlighted_file = $console_color->convert("%r$file_path%n");
$this->assertEquals($mib_name, $file, "$highlighted_file should be named $mib_name");
}
/**
* Test each mib file for errors
*
* @group mibs
* @dataProvider mibFiles
* @param $path
* @param $file
* @param $mib_name
*/
public function testMibContents($path, $file, $mib_name)
{
global $console_color;
$file_path = "$path/$file";
$highlighted_file = $console_color->convert("%r$file_path%n");
$output = shell_exec("snmptranslate -M +" . Config::get('mib_dir') . ":$path -m +$mib_name SNMPv2-MIB::system 2>&1");
$errors = str_replace("SNMPv2-MIB::system\n", '', $output);
$this->assertEmpty($errors, "$highlighted_file has errors!\n$errors");
}
/**
* Get a list of all mib files with the name of the mib.
* Called for each test that uses it before class setup.
* @return array path, filename, mib_name
*/
public function mibFiles()
{
$file_list = array();
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(Config::get('mib_dir'))) as $file) {
/** @var SplFileInfo $file */
if ($file->isDir()) {
continue;
}
$mib_path = str_replace(Config::get('mib_dir') . '/', '', $file->getPathName());
$file_list[$mib_path] = array(
str_replace(Config::get('install_dir'), '.', $file->getPath()),
$file->getFilename(),
$this->extractMibName($file->getPathname())
);
}
return $file_list;
}
/**
* List all directories inside the mib directory
* @return array
*/
public function mibDirs()
{
$dirs = glob(Config::get('mib_dir') . '/*', GLOB_ONLYDIR);
array_unshift($dirs, Config::get('mib_dir'));
$final_list = array();
foreach ($dirs as $dir) {
$relative_dir = str_replace(Config::get('mib_dir') . '/', '', $dir);
$final_list[$relative_dir] = array($dir);
}
return $final_list;
}
/**
* Extract the mib name from a file
*
* @param $file
* @return mixed
* @throws Exception
*/
private function extractMibName($file)
{
// extract the mib name (tried regex, but was too complex and I had to read the whole file)
$mib_name = null;
if ($handle = fopen($file, "r")) {
$header = '';
while (($line = fgets($handle)) !== false) {
$trimmed = trim($line);
if (empty($trimmed) || starts_with($trimmed, '--')) {
continue;
}
$header .= " $trimmed";
if (str_contains($trimmed, 'DEFINITIONS')) {
preg_match('/(\S+)\s+(?=DEFINITIONS)/', $header, $matches);
fclose($handle);
return $matches[1];
}
}
fclose($handle);
}
throw new Exception("Could not extract mib name from file ($file)");
}
}