You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
14 KiB
195 lines
14 KiB
<?php declare(strict_types = 0);
|
|
/*
|
|
** Zabbix
|
|
** Copyright (C) 2001-2023 Zabbix SIA
|
|
**
|
|
** 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 2 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, write to the Free Software
|
|
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
**/
|
|
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class CExpressionValidatorTest extends TestCase {
|
|
|
|
/**
|
|
* An array of expressions, options and the expected results.
|
|
*/
|
|
public function dataProvider() {
|
|
return [
|
|
['avg(avg_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(avg_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['max(avg_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['min(avg_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['sum(avg_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
|
|
['histogram_quantile(1, bucket_rate_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
|
|
['avg(count_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(count_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['max(count_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['min(count_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['sum(count_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
|
|
['avg(exists_foreach(/host/key))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(exists_foreach(/host/key))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['max(exists_foreach(/host/key))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['min(exists_foreach(/host/key))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['sum(exists_foreach(/host/key))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
|
|
['avg(last_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(last_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['kurtosis(last_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['mad(last_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['max(last_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['min(last_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['skewness(last_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['stddevpop(last_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['stddevsamp(last_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['sum(last_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['sumofsquares(last_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['varpop(last_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['varsamp(last_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
|
|
['avg(max_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(max_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['max(max_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['min(max_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['sum(max_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
|
|
['avg(min_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(min_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['max(min_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['min(min_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['sum(min_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
|
|
['avg(sum_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(sum_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['max(sum_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['min(sum_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['sum(sum_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
|
|
// User macros.
|
|
['find(/host/key, {$PERIOD}:{$TIMESHIFT})', ['usermacros' => true], ['rc' => true, 'error' => null]],
|
|
['find(/host/key, {$PERIOD}:{$TIMESHIFT})', [], ['rc' => false, 'error' => 'invalid second parameter in function "find"']],
|
|
['find(/host/key, 1d, {$OP})', ['usermacros' => true], ['rc' => true, 'error' => null]],
|
|
['find(/host/key, 1d, {$OP})', [], ['rc' => false, 'error' => 'invalid third parameter in function "find"']],
|
|
['find(/host/key, 1d, "{$OP}")', ['usermacros' => true], ['rc' => true, 'error' => null]],
|
|
['find(/host/key, 1d, "{$OP}")', [], ['rc' => false, 'error' => 'invalid third parameter in function "find"']],
|
|
|
|
// LLD macros.
|
|
['find(/host/key, {#PERIOD}:{#TIMESHIFT})', ['lldmacros' => true], ['rc' => true, 'error' => null]],
|
|
['find(/host/key, {#PERIOD}:{#TIMESHIFT})', [], ['rc' => false, 'error' => 'invalid second parameter in function "find"']],
|
|
['find(/host/key, 1d, {#OP})', ['lldmacros' => true], ['rc' => true, 'error' => null]],
|
|
['find(/host/key, 1d, {#OP})', [], ['rc' => false, 'error' => 'invalid third parameter in function "find"']],
|
|
['find(/host/key, 1d, "{#OP}")', ['lldmacros' => true], ['rc' => true, 'error' => null]],
|
|
['find(/host/key, 1d, "{#OP}")', [], ['rc' => false, 'error' => 'invalid third parameter in function "find"']],
|
|
|
|
// Unknown function in trigger expression.
|
|
['avg_foreach(/host/key)', [], ['rc' => false, 'error' => 'unknown function "avg_foreach"']],
|
|
['bucket_percentile(/host/key)', [], ['rc' => false, 'error' => 'unknown function "bucket_percentile"']],
|
|
['bucket_rate_foreach(/host/key)', [], ['rc' => false, 'error' => 'unknown function "bucket_rate_foreach"']],
|
|
['count_foreach(/host/key)', [], ['rc' => false, 'error' => 'unknown function "count_foreach"']],
|
|
['exists_foreach(/host/key)', [], ['rc' => false, 'error' => 'unknown function "exists_foreach"']],
|
|
['item_count(/host/key)', [], ['rc' => false, 'error' => 'unknown function "item_count"']],
|
|
['last_foreach(/host/key)', [], ['rc' => false, 'error' => 'unknown function "last_foreach"']],
|
|
['max_foreach(/host/key)', [], ['rc' => false, 'error' => 'unknown function "max_foreach"']],
|
|
['min_foreach(/host/key)', [], ['rc' => false, 'error' => 'unknown function "min_foreach"']],
|
|
['sum_foreach(/host/key)', [], ['rc' => false, 'error' => 'unknown function "sum_foreach"']],
|
|
|
|
// Not aggregated.
|
|
['avg_foreach(/host/key, 1)', ['calculated' => true], ['rc' => false, 'error' => 'incorrect usage of function "avg_foreach"']],
|
|
['bucket_rate_foreach(/host/key, 1)', ['calculated' => true], ['rc' => false, 'error' => 'incorrect usage of function "bucket_rate_foreach"']],
|
|
['count_foreach(/host/key, 1)', ['calculated' => true], ['rc' => false, 'error' => 'incorrect usage of function "count_foreach"']],
|
|
['exists_foreach(/host/key)', ['calculated' => true], ['rc' => false, 'error' => 'incorrect usage of function "exists_foreach"']],
|
|
['last_foreach(/host/key, 1)', ['calculated' => true], ['rc' => false, 'error' => 'incorrect usage of function "last_foreach"']],
|
|
['max_foreach(/host/key, 1)', ['calculated' => true], ['rc' => false, 'error' => 'incorrect usage of function "max_foreach"']],
|
|
['min_foreach(/host/key, 1)', ['calculated' => true], ['rc' => false, 'error' => 'incorrect usage of function "min_foreach"']],
|
|
['sum_foreach(/host/key, 1)', ['calculated' => true], ['rc' => false, 'error' => 'incorrect usage of function "sum_foreach"']],
|
|
|
|
// Wildcards.
|
|
['avg(avg_foreach(/*/key[p1,p2], 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['avg(avg_foreach(/host/*, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['avg(avg_foreach(/host/key[*,p2], 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['avg(avg_foreach(/host/key[p1,*], 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['avg(avg_foreach(/host/key[*,*], 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['avg(avg_foreach(/*/key[*,*], 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['avg(avg_foreach(/*/*, 1))', ['calculated' => true], ['rc' => false, 'error' => 'invalid first parameter in function "avg_foreach"']],
|
|
['avg(/*/key[p1,p2], 1))', ['calculated' => true], ['rc' => false, 'error' => 'invalid first parameter in function "avg"']],
|
|
['avg(/host/*, 1))', ['calculated' => true], ['rc' => false, 'error' => 'invalid first parameter in function "avg"']],
|
|
['avg(/host/key[*,p2], 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['avg(/host/key[p1,*], 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['avg(/host/key[*,*], 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['item_count(/host/key[*,*]))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
|
|
// Non-aggregating math function.
|
|
['length(avg_foreach(/host/key, 1))', ['calculated' => true], ['rc' => false, 'error' => 'incorrect usage of function "avg_foreach"']],
|
|
|
|
// Non-existing math function.
|
|
['foo(avg_foreach(/host/key, 1))', ['calculated' => true], ['rc' => false, 'error' => 'unknown function "foo"']],
|
|
|
|
// More than one parameter for aggregating math function.
|
|
['avg(count_foreach(/host/key, 20m), "eq", 1)', ['calculated' => true], ['rc' => false, 'error' => 'incorrect usage of function "count_foreach"']],
|
|
['avg(count_foreach(/host/key, 20m), 1, 1)', ['calculated' => true], ['rc' => false, 'error' => 'incorrect usage of function "count_foreach"']],
|
|
['avg(count_foreach(/host/key, 20m, "eq", 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(count_foreach(/host/key, 20m, , ))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(count_foreach(/host/key, 20m), "eq", 2)', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(count_foreach(/host/key, 20m, "eq"))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(count_foreach(/host/key, 20m, "eq", ))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(count_foreach(/host/key, 20m, 1, 1), "eq", 2)', ['calculated' => true], ['rc' => false, 'error' => 'invalid third parameter in function "count_foreach"']],
|
|
['count(count_foreach(/host/key, 20m, "eq", 1), "eq", 2)', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(last_foreach(/host/key, 1))', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(last_foreach(/host/key, 1), 1, 1)', ['calculated' => true], ['rc' => false, 'error' => 'incorrect usage of function "count"']],
|
|
['count(last_foreach(/host/key, 1), "eq")', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(last_foreach(/host/key, 1), "eq", 1)', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(last_foreach(/host/key, 1), "eq", "string")', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
['count(last_foreach(/host/key, 1), "eq", 1, 1)', ['calculated' => true], ['rc' => false, 'error' => 'invalid number of parameters in function "count"']],
|
|
['sum(avg_foreach(/host/key, 1), 1)', ['calculated' => true], ['rc' => false, 'error' => 'incorrect usage of function "avg_foreach"']],
|
|
['sum(1, avg_foreach(/host/key, 1))', ['calculated' => true], ['rc' => false, 'error' => 'incorrect usage of function "avg_foreach"']],
|
|
['sum(avg_foreach(/host/key, 1), avg_foreach(/host/key, 1))', ['calculated' => true], ['rc' => false, 'error' => 'incorrect usage of function "avg_foreach"']],
|
|
|
|
// Host/key reference requirement.
|
|
['sum(1, 2, 3)', [], ['rc' => false, 'error' => 'trigger expression must contain at least one /host/key reference']],
|
|
['sum(1, 2, 3)', ['calculated' => true], ['rc' => true, 'error' => null]],
|
|
|
|
// Incorrect usage of math/history functions.
|
|
['foo(/host/item)', [], ['rc' => false, 'error' => 'unknown function "foo"']],
|
|
['abs(/host/item)', [], ['rc' => false, 'error' => 'incorrect usage of function "abs"']],
|
|
['foo(1, 2, 3)', [], ['rc' => false, 'error' => 'unknown function "foo"']],
|
|
['change(1, 2, 3)', [], ['rc' => false, 'error' => 'incorrect usage of function "change"']],
|
|
['count(123)', [], ['rc' => false, 'error' => 'incorrect usage of function "count"']],
|
|
['avg(bucket_rate_foreach(/host/*, 1))', ['calculated' => true], ['rc' => false, 'error' => 'incorrect usage of function "bucket_rate_foreach"']]
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider dataProvider
|
|
*/
|
|
public function testExpressionValidator(string $source, array $options, array $expected) {
|
|
$expression_parser = new CExpressionParser([
|
|
'usermacros' => true,
|
|
'lldmacros' => true
|
|
] + $options);
|
|
$expression_validator = new CExpressionValidator($options);
|
|
|
|
$expression_parser->parse($source);
|
|
$tokens = $expression_parser->getResult()->getTokens();
|
|
|
|
$this->assertSame($expected, [
|
|
'rc' => $expression_validator->validate($tokens),
|
|
'error' => $expression_validator->getError()
|
|
]);
|
|
}
|
|
}
|