librenms/tests/YamlSchemaTest.php
Jellyfrog 2b3575a5e9
Laravel 10.x Shift (#14995)
* Apply code style

* Remove explicit call to register policies

* Shift core files

* Shift config files

* Default config files

In an effort to make upgrading the constantly changing config files
easier, Shift defaulted them and merged your true customizations -
where ENV variables may not be used.

* Bump Laravel dependencies

* Add type hints for Laravel 10

* Shift cleanup

* wip

* wip

* sync translation

* Sync back config

* Public Path Binding

* QueryException

* monolog

* db::raw

* monolog

* db::raw

* fix larastan collections

* fix phpstan bug looping forever

* larastan errors

* larastan: fix column type

* styleci

* initialize array

* fixes

* fixes

---------

Co-authored-by: Shift <shift@laravelshift.com>
2023-05-24 22:21:54 +02:00

152 lines
4.6 KiB
PHP

<?php
/**
* YamlSchemaTest.php
*
* Verifies yaml files conform to the schema definitions
*
* 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 <https://www.gnu.org/licenses/>.
*
* @link https://www.librenms.org
*
* @copyright 2016 Neil Lathwood
* @author Neil Lathwood <librenms+n@laf.io>
*/
namespace LibreNMS\Tests;
use Illuminate\Support\Str;
use JsonSchema\Constraints\Constraint;
use JsonSchema\Exception\JsonDecodingException;
use LibreNMS\Config;
use PHPUnit\Framework\ExpectationFailedException;
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Yaml;
class YamlSchemaTest extends TestCase
{
private $excluded = [
'/includes/definitions/default.yaml',
'/includes/definitions/generic.yaml',
'/includes/definitions/ping.yaml',
];
public function testConfigSchema(): void
{
$this->validateFileAgainstSchema('/misc/config_definitions.json', '/misc/config_schema.json');
}
/**
* @group os
*/
public function testOSDefinitionSchema(): void
{
$this->validateYamlFilesAgainstSchema('/includes/definitions', '/misc/os_schema.json');
}
/**
* @group os
*/
public function testOSMatchFilename(): void
{
foreach ($this->listFiles('/includes/definitions/*.yaml') as $filename => $file) {
$this->assertEquals(
Yaml::parseFile($file)['os'],
substr($filename, 0, -5),
"Parameter 'os' doesn't match the filename $filename"
);
}
}
/**
* @group os
*/
public function testDiscoveryDefinitionSchema(): void
{
$this->validateYamlFilesAgainstSchema('/includes/definitions/discovery', '/misc/discovery_schema.json');
}
private function validateYamlFilesAgainstSchema($dir, $schema_file)
{
foreach ($this->listFiles($dir . '/*.yaml') as $file) {
$this->validateFileAgainstSchema($file, $schema_file);
}
}
public function listOsDefinitionFiles()
{
return $this->listFiles('/includes/definitions/*.yaml');
}
public function listDiscoveryFiles()
{
return $this->listFiles('/includes/definitions/discovery/*.yaml');
}
private function listFiles($pattern)
{
$pattern = Config::get('install_dir') . $pattern;
return collect(glob($pattern))
->reduce(function ($array, $file) {
if (Str::contains($file, $this->excluded)) {
return $array;
}
$name = basename($file);
$array[$name] = $file;
return $array;
}, []);
}
/**
* @param string $filePath
* @param string $schema_file
*/
private function validateFileAgainstSchema($filePath, $schema_file)
{
$schema = (object) ['$ref' => 'file://' . Config::get('install_dir') . $schema_file];
$filename = basename($filePath);
$filePath = Str::start($filePath, Config::get('install_dir'));
try {
$data = Str::endsWith($filePath, '.json')
? json_decode(file_get_contents($filePath))
: Yaml::parse(file_get_contents($filePath));
} catch (ParseException $e) {
throw new ExpectationFailedException("$filePath Could not be parsed", null, $e);
}
try {
$validator = new \JsonSchema\Validator;
$validator->validate(
$data,
$schema,
Constraint::CHECK_MODE_TYPE_CAST // | Constraint::CHECK_MODE_VALIDATE_SCHEMA
);
} catch (JsonDecodingException $e) {
// Output the filename so we know what file failed
echo "Json format invalid in $schema_file\n";
throw $e;
}
$errors = collect($validator->getErrors())
->reduce(function ($out, $error) {
return sprintf("%s[%s] %s\n", $out, $error['property'], $error['message']);
}, '');
$this->assertTrue($validator->isValid(), "$filename does not validate. Violations:\n$errors");
}
}