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.
1139 lines
32 KiB
1139 lines
32 KiB
1 year ago
|
<?php
|
||
|
/*
|
||
|
** 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.
|
||
|
**/
|
||
|
|
||
|
|
||
|
require_once dirname(__FILE__).'/../../include/CWebTest.php';
|
||
|
require_once dirname(__FILE__).'/../traits/PreprocessingTrait.php';
|
||
|
require_once dirname(__FILE__).'/../behaviors/CMessageBehavior.php';
|
||
|
|
||
|
/**
|
||
|
* Base class for "Test item" function tests.
|
||
|
*/
|
||
|
class testItemTest extends CWebTest {
|
||
|
|
||
|
const HOST_ID = 99136; // 'Test item host' monitored by 'Proxy for Discovery rule'
|
||
|
const TEMPLATE_ID = 99137; // 'Test Item Template'
|
||
|
|
||
|
use PreprocessingTrait;
|
||
|
|
||
|
/**
|
||
|
* Attach MessageBehavior to the test.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getBehaviors() {
|
||
|
return [CMessageBehavior::class];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Test item button state data for item, item prototype and LLD.
|
||
|
*/
|
||
|
public function getCommonTestButtonStateData() {
|
||
|
return [
|
||
|
['Type' => 'Zabbix agent (active)'],
|
||
|
['Type' => 'Simple check'],
|
||
|
['Type' => 'SNMP agent','SNMP OID' => '[IF-MIB::]ifInOctets.1'],
|
||
|
['Type' => 'Zabbix internal'],
|
||
|
['Type' => 'Zabbix trapper'],
|
||
|
['Type' => 'External check'],
|
||
|
['Type' => 'Database monitor', 'SQL query' => 'query'],
|
||
|
['Type' => 'HTTP agent', 'URL' => 'https://www.zabbix.com'],
|
||
|
['Type' => 'IPMI agent', 'IPMI sensor' => 'Sensor'],
|
||
|
['Type' => 'SSH agent', 'Key' => 'ssh.run[Description,127.0.0.1,50,[{#KEY}]]', 'User name' => 'Name', 'Executed script' => 'Script'],
|
||
|
['Type' => 'TELNET agent', 'Key' => 'telnet[{#KEY}]'],
|
||
|
['Type' => 'JMX agent', 'Key' => 'jmx[{#KEY}]','JMX endpoint' => 'service:jmx:rmi:///jndi/rmi://{HOST.CONN}:{HOST.PORT}/jmxrmi', 'User name' => ''],
|
||
|
['Type' => 'Dependent item', 'Key'=>'dependent[{#KEY}]', 'Master item' => 'Master item']
|
||
|
];
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Test item button state data for item and item prototype.
|
||
|
*/
|
||
|
public function getItemTestButtonStateData() {
|
||
|
return array_merge($this->getCommonTestButtonStateData(), [
|
||
|
['Type' => 'SNMP trap', 'Key' => 'snmptrap.fallback[{#KEY}]'],
|
||
|
['Type' => 'Calculated', 'Formula' => '"formula"']
|
||
|
]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check test item button state depending on item type.
|
||
|
*
|
||
|
* @param arary $data data provider
|
||
|
* @param string $item_name item given name
|
||
|
* @param string $item_type type of an item: item, prototype or lld rule
|
||
|
* @param string $success_text text part of a success message
|
||
|
* @param boolean $check_now possibility of executing item instantly
|
||
|
* @param boolean $is_host true if host, false if template
|
||
|
* @param string $id id of a host, template or LLD rule
|
||
|
* @param string $items pointer to form in URL
|
||
|
*/
|
||
|
public function checkTestButtonState($data, $item_name, $item_type, $success_text, $check_now, $is_host, $id, $items = null) {
|
||
|
$create_link = ($items === null)
|
||
|
? 'disc_prototypes.php?form=create&context=host&parent_discoveryid='.$id
|
||
|
: $items.'.php?form=create&context=host&hostid='.$id;
|
||
|
|
||
|
$saved_link = ($items === null)
|
||
|
? 'disc_prototypes.php?form=update&context=host&parent_discoveryid='.$id.'&itemid='
|
||
|
: $items.'.php?form=update&context=host&hostid='.$id.'&itemid=';
|
||
|
|
||
|
$this->page->login()->open($create_link);
|
||
|
$item_form = $this->query('name:itemForm')->asForm()->waitUntilReady()->one();
|
||
|
|
||
|
// Create item.
|
||
|
$item_form->fill([
|
||
|
'Name' => $item_name,
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'key[{#KEY}]'
|
||
|
]);
|
||
|
// Check Test item button.
|
||
|
$this->checkTestButtonInPreprocessing($item_type);
|
||
|
$this->saveFormAndCheckMessage($item_type.$success_text);
|
||
|
$itemid = CDBHelper::getValue('SELECT itemid FROM items WHERE name='.zbx_dbstr($item_name));
|
||
|
|
||
|
// Open created item and change type.
|
||
|
foreach ($data as $update) {
|
||
|
$this->page->open($saved_link.$itemid);
|
||
|
$item_form->invalidate();
|
||
|
$type = $item_form->getField('Type')->getValue();
|
||
|
|
||
|
for ($i = 0; $i < 2; $i++) {
|
||
|
if ($type === 'IPMI agent' && $is_host === false) {
|
||
|
$enabled = false;
|
||
|
}
|
||
|
else {
|
||
|
$enabled = (!in_array($type, ['Zabbix agent (active)', 'SNMP trap', 'Zabbix trapper', 'Dependent item']));
|
||
|
}
|
||
|
|
||
|
$this->checkTestButtonInPreprocessing($item_type, $enabled, $i);
|
||
|
|
||
|
// Check "Execute now" button only in host case item saved form and then change type.
|
||
|
if ($i === 0) {
|
||
|
if ($check_now) {
|
||
|
if ($type === 'Dependent item') {
|
||
|
$enabled = true;
|
||
|
}
|
||
|
$execute_button = $this->query('button:Execute now')->waitUntilVisible()->one();
|
||
|
$this->assertTrue($execute_button->isEnabled($enabled));
|
||
|
}
|
||
|
|
||
|
$item_form->fill($update);
|
||
|
// TODO: workaround for ZBXNEXT-5365
|
||
|
if ($item_type === 'Item prototype'
|
||
|
&& array_key_exists('Master item', $update)) {
|
||
|
sleep(2);
|
||
|
$item_form->getFieldContainer('Master item')->asMultiselect()->select($update['Master item']);
|
||
|
}
|
||
|
|
||
|
$type = $update['Type'];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$this->saveFormAndCheckMessage($item_type.' updated');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Test item button data for item, item prototype and LLD.
|
||
|
*/
|
||
|
public function getCommonTestItemData() {
|
||
|
return [
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'key.macro.in.preproc.steps'
|
||
|
],
|
||
|
'macros' => [
|
||
|
[
|
||
|
'macro' => '{$1}',
|
||
|
'value' => 'Numeric macro'
|
||
|
],
|
||
|
[
|
||
|
'macro' => '{$A}',
|
||
|
'value' => 'Some text'
|
||
|
],
|
||
|
[
|
||
|
'macro' => '{$_}',
|
||
|
'value' => 'Underscore'
|
||
|
]
|
||
|
],
|
||
|
'preprocessing' => [
|
||
|
['type' => 'Regular expression', 'parameter_1' => '{$A}', 'parameter_2' => '{$1}'],
|
||
|
['type' => 'JSONPath', 'parameter_1' => '{$_}']
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'macro.in.key.and.preproc.steps[{$DEFAULT_DELAY}]'
|
||
|
],
|
||
|
'macros' => [
|
||
|
[
|
||
|
'macro' => '{$1}',
|
||
|
'value' => 'Numeric macro'
|
||
|
],
|
||
|
[
|
||
|
'macro' => '{$A}',
|
||
|
'value' => 'Some text'
|
||
|
],
|
||
|
[
|
||
|
'macro' => '{$_}',
|
||
|
'value' => 'Underscore'
|
||
|
],
|
||
|
[
|
||
|
'macro' => '{$DEFAULT_DELAY}',
|
||
|
'value' => '30'
|
||
|
]
|
||
|
],
|
||
|
'preprocessing' => [
|
||
|
['type' => 'Regular expression', 'parameter_1' => '{$A}', 'parameter_2' => '{$1}'],
|
||
|
['type' => 'JSONPath', 'parameter_1' => '{$_}']
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'test.item.key'
|
||
|
]
|
||
|
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Simple check',
|
||
|
'Key' => 'test.item.key'
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'SNMP agent',
|
||
|
'Key' => 'test.item.no.host.value'
|
||
|
],
|
||
|
'snmp_fields' => [
|
||
|
'version' => 'SNMPv2'
|
||
|
],
|
||
|
'host_value' => false
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'SNMP agent',
|
||
|
'Key' => 'snmp.v2'
|
||
|
],
|
||
|
'host_interface' => '127.0.0.2:161',
|
||
|
'snmp_fields' => [
|
||
|
'version' => 'SNMPv2',
|
||
|
'community' => 'public'
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'SNMP agent',
|
||
|
'Key' => 'snmp.v1'
|
||
|
],
|
||
|
'host_interface' => '127.0.0.5:161',
|
||
|
'snmp_fields' => [
|
||
|
'version' => 'SNMPv1',
|
||
|
'community' => 'public'
|
||
|
],
|
||
|
'interface_text_part' => 'SNMPv1, Community: {$SNMP_COMMUNITY}'
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'SNMP agent',
|
||
|
'Key' => 'snmp.v3'
|
||
|
],
|
||
|
'host_interface' => '127.0.0.6:161',
|
||
|
'snmp_fields' => [
|
||
|
'version' => 'SNMPv3',
|
||
|
'context' => 'test_context',
|
||
|
'security' => 'test_security_name',
|
||
|
'security_level' => 'authPriv',
|
||
|
'authentication_protocol' => 'SHA1',
|
||
|
'authentication_passphrase' => '{$TEST}',
|
||
|
'privacy_protocol' => 'AES128',
|
||
|
'privacy_passphrase' => 'test_privpassphrase'
|
||
|
],
|
||
|
'interface_text_part' => 'SNMPv3, Context name: test_context, (priv: AES128, auth: SHA1)'
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix internal',
|
||
|
'Key' => 'test.zabbix.internal'
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'External check',
|
||
|
'Key' => 'test.external.check'
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Database monitor',
|
||
|
'Key' => 'test.db.monitor'
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'HTTP agent',
|
||
|
'Key' => 'test.http.agent'
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'IPMI agent',
|
||
|
'Key' => 'test.ipmi.agent'
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'SSH agent',
|
||
|
'Key' => 'test.ssh.agent'
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'TELNET agent',
|
||
|
'Key' => 'test.telnet.agent'
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'JMX agent',
|
||
|
'Key' => 'test.jmx.agent',
|
||
|
'JMX endpoint' => 'service:jmx:rmi:///jndi/rmi://{HOST.CONN}:{HOST.PORT}/jmxrmi'
|
||
|
],
|
||
|
'macros' => [
|
||
|
[
|
||
|
'macro' => '{HOST.CONN}',
|
||
|
'value' => '127.0.0.4'
|
||
|
],
|
||
|
[
|
||
|
'macro' => '{HOST.PORT}',
|
||
|
'value' => '12345'
|
||
|
]
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_BAD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => ''
|
||
|
],
|
||
|
'error' => 'Incorrect value for field "key_": key is empty.'
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_BAD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'key space'
|
||
|
],
|
||
|
'error' => 'Incorrect value for field "key_": incorrect syntax near " space".'
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_BAD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'test.item.preproc.no.fist.param'
|
||
|
],
|
||
|
'preprocessing' => [
|
||
|
['type' => 'Regular expression', 'parameter_1' => '', 'parameter_2' => '2']
|
||
|
],
|
||
|
'error' => 'Invalid parameter "/1/params/1": cannot be empty.'
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_BAD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'test.item.preproc.no.second.param'
|
||
|
],
|
||
|
'preprocessing' => [
|
||
|
['type' => 'Regular expression', 'parameter_1' => '1', 'parameter_2' => '']
|
||
|
],
|
||
|
'error' => 'Invalid parameter "/1/params/2": cannot be empty.'
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_BAD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'test.item.preproc.no.params'
|
||
|
],
|
||
|
'preprocessing' => [
|
||
|
['type' => 'XML XPath', 'parameter_1' => '']
|
||
|
],
|
||
|
'error' => 'Invalid parameter "/1/params/1": cannot be empty.'
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_BAD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'test.item.preproc.no.custom.error'
|
||
|
],
|
||
|
'preprocessing' => [
|
||
|
['type' => 'Regular expression',
|
||
|
'parameter_1' => '1',
|
||
|
'parameter_2' => '2',
|
||
|
'on_fail' => true,
|
||
|
'error_handler' => 'Set error to',
|
||
|
'error_handler_params' => '']
|
||
|
],
|
||
|
'error' => 'Invalid parameter "/1/error_handler_params": cannot be empty.'
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'key.macro.preproc[param,{$A},{$1}]'
|
||
|
],
|
||
|
'macros' => [
|
||
|
[
|
||
|
'macro' => '{$A}',
|
||
|
'value' => 'Some text'
|
||
|
],
|
||
|
[
|
||
|
'macro' => '{$1}',
|
||
|
'value' => 'Numeric macro'
|
||
|
]
|
||
|
],
|
||
|
'preprocessing' => [
|
||
|
['type' => 'Prometheus to JSON', 'parameter_1' => 'cpu_usage_system'],
|
||
|
['type' => 'JSONPath', 'parameter_1' => '$.path']
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'test.item.preproc.discard.unchanged.with.heartbeat'
|
||
|
],
|
||
|
'preprocessing' => [
|
||
|
['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '1']
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'test.item.preproc.discard.unchanged.with.heartbeat'
|
||
|
],
|
||
|
'host_value' => false,
|
||
|
'preprocessing' => [
|
||
|
['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '1']
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'test.item.interface.trailing.spaces'
|
||
|
],
|
||
|
'interface' => ['address' => ' 127.0.0.1 ', 'port' => ' 10050 ']
|
||
|
]
|
||
|
]
|
||
|
];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Test item button data for item.
|
||
|
*/
|
||
|
public function getItemTestItemData() {
|
||
|
return array_merge($this->getCommonTestItemData(), [
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_BAD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Calculated',
|
||
|
'Key' => 'calculated0'
|
||
|
],
|
||
|
'test_error' => 'Incorrect value for field "Formula": incorrect expression starting from "".'
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_BAD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Calculated',
|
||
|
'Key' => 'calculated1',
|
||
|
'Formula' => '((),9'
|
||
|
],
|
||
|
'test_error' => 'Incorrect value for field "Formula": incorrect expression starting from "),9".'
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_BAD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Calculated',
|
||
|
'Key' => 'calculated2',
|
||
|
'Formula' => '{{?{{?{{?'
|
||
|
],
|
||
|
'test_error' => 'Incorrect value for field "Formula": incorrect expression starting from "{{?{{?{{?".'
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Calculated',
|
||
|
'Key' => 'test.calculated',
|
||
|
'Formula' => 'avg(/Zabbix Server/zabbix[wcache,values],10m)'
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'test.item.preproc.discard.unchanged'
|
||
|
],
|
||
|
'preprocessing' => [
|
||
|
['type' => 'Discard unchanged']
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'test.item.preproc.discard.unchanged'
|
||
|
],
|
||
|
'host_value' => false,
|
||
|
'preprocessing' => [
|
||
|
['type' => 'Discard unchanged']
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'test.item.preproc.simple.change'
|
||
|
],
|
||
|
'preprocessing' => [
|
||
|
['type' => 'Simple change']
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'test.item.preproc.simple.change'
|
||
|
],
|
||
|
'host_value' => false,
|
||
|
'preprocessing' => [
|
||
|
['type' => 'Simple change']
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'test.item.preproc.change.per.second'
|
||
|
],
|
||
|
'preprocessing' => [
|
||
|
['type' => 'Change per second']
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'test.item.preproc.change.per.second'
|
||
|
],
|
||
|
'host_value' => false,
|
||
|
'preprocessing' => [
|
||
|
['type' => 'Change per second']
|
||
|
]
|
||
|
]
|
||
|
]
|
||
|
]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Test item button data for item prototype.
|
||
|
*/
|
||
|
public function getPrototypeTestItemData() {
|
||
|
return array_merge($this->getItemTestItemData(), [
|
||
|
[
|
||
|
[
|
||
|
'expected' => TEST_GOOD,
|
||
|
'fields' => [
|
||
|
'Type' => 'Zabbix agent',
|
||
|
'Key' => 'prototype.with.lld.macros[{#KEY1},{#KEY2}]'
|
||
|
],
|
||
|
'macros' => [
|
||
|
[
|
||
|
'macro' => '{#KEY1}',
|
||
|
'value' => '{#KEY1}'
|
||
|
],
|
||
|
[
|
||
|
'macro' => '{#KEY2}',
|
||
|
'value' => '{#KEY2}'
|
||
|
]
|
||
|
],
|
||
|
'preprocessing' => [
|
||
|
['type' => 'Prometheus to JSON', 'parameter_1' => 'cpu_usage_system'],
|
||
|
['type' => 'JSONPath', 'parameter_1' => '$.path']
|
||
|
]
|
||
|
]
|
||
|
]
|
||
|
]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check test item form.
|
||
|
*
|
||
|
* @param arary $data data provider
|
||
|
* @param boolean $is_host true if host, false if template
|
||
|
* @param string $id id of a host, template or LLD rule
|
||
|
* @param string $items pointer to form in URL
|
||
|
* @param boolean $lld true if lld, false if item or item prototype
|
||
|
*/
|
||
|
public function checkTestItem($data, $is_host, $id, $items = null, $lld = false) {
|
||
|
$create_link = ($items === null)
|
||
|
? 'disc_prototypes.php?form=create&context=host&parent_discoveryid='.$id
|
||
|
: $items.'.php?form=create&context=host&hostid='.$id;
|
||
|
|
||
|
if (!$is_host && $data['fields']['Type'] === 'IPMI agent') {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$this->page->login()->open($create_link);
|
||
|
$item_form = $this->query('name:itemForm')->asForm()->waitUntilReady()->one();
|
||
|
$item_form->fill($data['fields']);
|
||
|
|
||
|
if ($is_host) {
|
||
|
// If host fill interface.
|
||
|
if (CTestArrayHelper::get($data, 'host_interface')) {
|
||
|
/**
|
||
|
* The value of an SNMP interface option element contains not only the IP and port, but also the
|
||
|
* interface type and context name or community. In this case the address and details must be merged.
|
||
|
*/
|
||
|
$interface = $data['host_interface'].CTestArrayHelper::get($data, 'interface_text_part', '');
|
||
|
|
||
|
$item_form->getField('Host interface')->fill($interface);
|
||
|
}
|
||
|
// Get ip and port separately.
|
||
|
$host_interface = explode(':', $item_form->getField('Host interface')->getText(), 2);
|
||
|
}
|
||
|
|
||
|
if (CTestArrayHelper::get($data, 'preprocessing')){
|
||
|
$item_form->selectTab('Preprocessing');
|
||
|
$this->addPreprocessingSteps($data['preprocessing']);
|
||
|
}
|
||
|
|
||
|
// Open Test item dialog form.
|
||
|
$this->query('id:test_item')->waitUntilVisible()->one()->click();
|
||
|
$overlay = COverlayDialogElement::find()->one()->waitUntilReady();
|
||
|
|
||
|
switch ($data['expected']) {
|
||
|
case TEST_GOOD:
|
||
|
$this->assertEquals('Test item', $overlay->getTitle());
|
||
|
$test_form = $this->query('id:preprocessing-test-form')->asForm()->waitUntilReady()->one();
|
||
|
|
||
|
// Check "Get value from host" checkbox.
|
||
|
$get_host_value = $test_form->query('id:get_value')->asCheckbox()->one();
|
||
|
$this->assertTrue($get_host_value->isEnabled());
|
||
|
$this->assertTrue($get_host_value->isChecked());
|
||
|
|
||
|
if ($lld === false) {
|
||
|
$not_supported = $test_form->query('id:not_supported')->asCheckbox()->one();
|
||
|
$this->assertFalse($not_supported->isEnabled());
|
||
|
}
|
||
|
else {
|
||
|
$not_supported = null;
|
||
|
}
|
||
|
|
||
|
if (CTestArrayHelper::get($data, 'snmp_fields.version') === 'SNMPv3') {
|
||
|
$elements = [
|
||
|
'address' => 'id:interface_address',
|
||
|
'port' => 'id:interface_port',
|
||
|
'proxy' => 'id:proxyid',
|
||
|
'version' => 'id:interface_details_version',
|
||
|
'context' => 'id:interface_details_contextname',
|
||
|
'security' => 'id:interface_details_securityname',
|
||
|
'security_level' => 'id:interface_details_securitylevel',
|
||
|
'authentication_protocol' => 'name:interfaces[details][authprotocol]',
|
||
|
'authentication_passphrase' => 'id:interface_details_authpassphrase',
|
||
|
'privacy_protocol' => 'name:interfaces[details][privprotocol]',
|
||
|
'privacy_passphrase' => 'id:interface_details_privpassphrase'
|
||
|
];
|
||
|
}
|
||
|
elseif (in_array(CTestArrayHelper::get($data, 'snmp_fields.version'), ['SNMPv1', 'SNMPv2'])) {
|
||
|
$elements = [
|
||
|
'address' => 'id:interface_address',
|
||
|
'port' => 'id:interface_port',
|
||
|
'proxy' => 'id:proxyid',
|
||
|
'version' => 'id:interface_details_version',
|
||
|
'community' => 'id:interface_details_community'
|
||
|
];
|
||
|
}
|
||
|
else {
|
||
|
$elements = [
|
||
|
'address' => 'id:interface_address',
|
||
|
'port' => 'id:interface_port',
|
||
|
'proxy' => 'id:proxyid'
|
||
|
];
|
||
|
}
|
||
|
|
||
|
foreach ($elements as $name => $selector) {
|
||
|
$elements[$name] = $test_form->query($selector)->one()->detect();
|
||
|
}
|
||
|
|
||
|
$proxy = CDBHelper::getValue("SELECT name FROM proxy WHERE proxyid IN ".
|
||
|
"(SELECT proxyid FROM hosts WHERE host = 'Test item host')");
|
||
|
|
||
|
// Check test item form fields depending on item type.
|
||
|
switch ($data['fields']['Type']) {
|
||
|
case 'Zabbix agent':
|
||
|
case 'IPMI agent':
|
||
|
if ($is_host) {
|
||
|
$fields_value = [
|
||
|
'address' => $host_interface[0],
|
||
|
'port' => $host_interface[1],
|
||
|
'proxy' => $proxy
|
||
|
];
|
||
|
}
|
||
|
else {
|
||
|
$fields_value = [
|
||
|
'address' => '',
|
||
|
'port' => '',
|
||
|
'proxy' => '(no proxy)'
|
||
|
];
|
||
|
}
|
||
|
$fields_state = ['address' => true, 'port' => true, 'proxy' => true];
|
||
|
break;
|
||
|
|
||
|
case 'SNMP agent':
|
||
|
if (CTestArrayHelper::get($data, 'snmp_fields.version') === 'SNMPv3') {
|
||
|
if ($is_host) {
|
||
|
$fields_value = [
|
||
|
'address' => $host_interface[0],
|
||
|
'port' => $host_interface[1],
|
||
|
'proxy' => $proxy,
|
||
|
'version' => 'SNMPv3',
|
||
|
'context' => $data['snmp_fields']['context'],
|
||
|
'security' => $data['snmp_fields']['security'],
|
||
|
'security_level' => $data['snmp_fields']['security_level'],
|
||
|
'authentication_protocol' => $data['snmp_fields']['authentication_protocol'],
|
||
|
'authentication_passphrase' => $data['snmp_fields']['authentication_passphrase'],
|
||
|
'privacy_protocol' => $data['snmp_fields']['privacy_protocol'],
|
||
|
'privacy_passphrase' => $data['snmp_fields']['privacy_passphrase']
|
||
|
];
|
||
|
}
|
||
|
else {
|
||
|
$fields_value = [
|
||
|
'address' => '',
|
||
|
'port' => '',
|
||
|
'proxy' => '(no proxy)',
|
||
|
'version' => 'SNMPv2',
|
||
|
'context' => '',
|
||
|
'security' => '',
|
||
|
'security_level' => 'noAuthNoPriv',
|
||
|
'authentication_protocol' => 'MD5',
|
||
|
'authentication_passphrase' => '',
|
||
|
'privacy_protocol' => 'DES',
|
||
|
'privacy_passphrase' => ''
|
||
|
];
|
||
|
}
|
||
|
|
||
|
$fields_state = [
|
||
|
'address' => true,
|
||
|
'port' => true,
|
||
|
'proxy' => true,
|
||
|
'version' => true,
|
||
|
'context' => true,
|
||
|
'security' => true,
|
||
|
'security_level' => true,
|
||
|
'authentication_protocol' => true,
|
||
|
'authentication_passphrase' => true,
|
||
|
'privacy_protocol' => true,
|
||
|
'privacy_passphrase' => true
|
||
|
];
|
||
|
}
|
||
|
else {
|
||
|
if ($is_host) {
|
||
|
$fields_value = [
|
||
|
'address' => $host_interface[0],
|
||
|
'port' => $host_interface[1],
|
||
|
'proxy' => $proxy,
|
||
|
'version' => CTestArrayHelper::get($data, 'snmp_fields.version', 'SNMPv2'),
|
||
|
'community' => CTestArrayHelper::get($data, 'snmp_fields.community', 'public')
|
||
|
];
|
||
|
}
|
||
|
else {
|
||
|
$fields_value = [
|
||
|
'address' => '',
|
||
|
'port' => '',
|
||
|
'proxy' => '(no proxy)',
|
||
|
'version' => 'SNMPv2',
|
||
|
'community' => ''
|
||
|
];
|
||
|
}
|
||
|
|
||
|
$fields_state = [
|
||
|
'address' => true,
|
||
|
'port' => true,
|
||
|
'proxy' => true,
|
||
|
'version' => true,
|
||
|
'community' => true
|
||
|
];
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'SSH agent':
|
||
|
case 'TELNET agent':
|
||
|
case 'Simple check':
|
||
|
$fields_value = [
|
||
|
'address' => $is_host ? $host_interface[0] : '',
|
||
|
'port' => '',
|
||
|
'proxy' => $is_host ? $proxy : '(no proxy)'
|
||
|
];
|
||
|
$fields_state = ['address' => true, 'port' => false, 'proxy' => true];
|
||
|
break;
|
||
|
|
||
|
case 'Zabbix internal':
|
||
|
case 'External check':
|
||
|
case 'Database monitor':
|
||
|
case 'HTTP agent':
|
||
|
case 'JMX agent':
|
||
|
$fields_value = [
|
||
|
'address' => '',
|
||
|
'port' => '',
|
||
|
'proxy' => $is_host ? $proxy : '(no proxy)'
|
||
|
];
|
||
|
$fields_state = ['address' => false, 'port' => false, 'proxy' => true];
|
||
|
break;
|
||
|
|
||
|
case 'Calculated':
|
||
|
$fields_value = ['address' => '', 'port' => '', 'proxy' => '(no proxy)'];
|
||
|
$fields_state = ['address' => false, 'port' => false, 'proxy' => false];
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
foreach ($fields_value as $field => $value) {
|
||
|
$this->assertEquals($elements[$field]->getValue(), $value);
|
||
|
}
|
||
|
foreach ($fields_state as $field => $state) {
|
||
|
$this->assertTrue($elements[$field]->isEnabled($state));
|
||
|
}
|
||
|
|
||
|
// Check value fields.
|
||
|
$this->checkValueFields($data, $not_supported, $lld);
|
||
|
|
||
|
// Change interface fields in testing form.
|
||
|
if (CTestArrayHelper::get($data, 'interface')) {
|
||
|
$elements['address']->fill($data['interface']['address']);
|
||
|
$elements['port']->fill($data['interface']['port']);
|
||
|
}
|
||
|
|
||
|
if ($is_host || array_key_exists('interface', $data) || in_array($data['fields']['Type'],
|
||
|
['Zabbix internal', 'External check', 'Database monitor', 'HTTP agent', 'JMX agent',
|
||
|
'Calculated'])) {
|
||
|
$details = 'Connection to Zabbix server "localhost:10051" refused. Possible reasons:';
|
||
|
}
|
||
|
else {
|
||
|
$details = ($data['fields']['Type'] === 'SNMP agent')
|
||
|
? 'Incorrect value for field "SNMP community": cannot be empty.'
|
||
|
: 'Incorrect value for field "Host address": cannot be empty.';
|
||
|
}
|
||
|
|
||
|
// Click Get value button.
|
||
|
$button = $test_form->query('button:Get value')->one();
|
||
|
$button->click();
|
||
|
$this->assertMessage(TEST_BAD, null, $details);
|
||
|
$test_form->getOverlayMessage()->close();
|
||
|
|
||
|
// Click Test button in test form.
|
||
|
$overlay->query('button:Get value and test')->one()->waitUntilVisible()->click();
|
||
|
$this->assertMessage(TEST_BAD, null, $details);
|
||
|
$test_form->getOverlayMessage()->close();
|
||
|
|
||
|
// Check empty interface fields.
|
||
|
if (in_array($data['fields']['Type'], ['Zabbix agent', 'SNMP agent', 'IPMI agent', 'Simple check'])) {
|
||
|
if ($data['fields']['Type'] !== 'Simple check') {
|
||
|
$elements['port']->clear();
|
||
|
$button->click();
|
||
|
|
||
|
if (!$is_host && !array_key_exists('interface', $data)) {
|
||
|
$details = ($data['fields']['Type'] === 'SNMP agent')
|
||
|
? 'Incorrect value for field "SNMP community": cannot be empty.'
|
||
|
: 'Incorrect value for field "Host address": cannot be empty.';
|
||
|
}
|
||
|
else {
|
||
|
$details = 'Incorrect value for field "Port": cannot be empty.';
|
||
|
}
|
||
|
|
||
|
$this->assertMessage(TEST_BAD, null, $details);
|
||
|
$test_form->getOverlayMessage()->close();
|
||
|
}
|
||
|
|
||
|
$elements['address']->clear();
|
||
|
$button->click();
|
||
|
$details = (!$is_host && $data['fields']['Type'] === 'SNMP agent')
|
||
|
? 'Incorrect value for field "SNMP community": cannot be empty.'
|
||
|
: 'Incorrect value for field "Host address": cannot be empty.';
|
||
|
$this->assertMessage(TEST_BAD, null, $details);
|
||
|
$test_form->getOverlayMessage()->close();
|
||
|
|
||
|
// Check SNMP empty fields for Template.
|
||
|
if (!$is_host && (CTestArrayHelper::get($data, 'snmp_fields.community'))) {
|
||
|
$test_form->fill(['id:interface_details_community' => $data['snmp_fields']['community']]);
|
||
|
$button->click();
|
||
|
$this->assertMessage(TEST_BAD, null, 'Incorrect value for field "Host address": cannot be empty.');
|
||
|
$test_form->getOverlayMessage()->close();
|
||
|
|
||
|
$elements['address']->fill('127.0.0.1');
|
||
|
$button->click();
|
||
|
$this->assertMessage(TEST_BAD, null, 'Incorrect value for field "Port": cannot be empty.');
|
||
|
$test_form->getOverlayMessage()->close();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Uncheck "Get value from host" checkbox.
|
||
|
if (CTestArrayHelper::get($data, 'host_value', true) === false) {
|
||
|
$get_host_value->uncheck();
|
||
|
|
||
|
// Check that interface and proxy fields disappeared.
|
||
|
foreach (['address', 'port', 'proxy'] as $field) {
|
||
|
$elements[$field]->waitUntilNotVisible();
|
||
|
}
|
||
|
$button->waitUntilNotVisible();
|
||
|
// Check that Test button changed its name.
|
||
|
$this->assertFalse($overlay->query('button:Get value and test')->one(false)->isValid());
|
||
|
$overlay->query('button:Test')->waitUntilVisible()->one();
|
||
|
|
||
|
if ($lld === false) {
|
||
|
$this->assertTrue($not_supported->isEnabled());
|
||
|
$this->assertFalse($not_supported->isChecked());
|
||
|
}
|
||
|
|
||
|
// Check that value fields still present after "Get value from host" checkbox is unset.
|
||
|
$this->checkValueFields($data, $not_supported, $lld);
|
||
|
}
|
||
|
|
||
|
// Compare data macros with macros from test table.
|
||
|
$macros = [
|
||
|
'expected' => CTestArrayHelper::get($data, 'macros'),
|
||
|
'actual' => []
|
||
|
];
|
||
|
|
||
|
// Global macros values for items on template are empty.
|
||
|
if (!$is_host && $data['fields']['Type'] === 'JMX agent') {
|
||
|
foreach ($macros['expected'] as &$macro) {
|
||
|
if (in_array(substr($macro['macro'], 1, 1), ['$', '#'])) {
|
||
|
continue;
|
||
|
}
|
||
|
$macro['value'] = '';
|
||
|
}
|
||
|
unset($macro);
|
||
|
}
|
||
|
|
||
|
if ($macros['expected']){
|
||
|
foreach ($test_form->query('class:textarea-flexible-container')->asTable()->one()->getRows() as $row) {
|
||
|
$columns = $row->getColumns()->asArray();
|
||
|
/*
|
||
|
* Macro columns are represented in following way:
|
||
|
* (0)macro (1)=> (2)value
|
||
|
*/
|
||
|
$macros['actual'][] = [
|
||
|
'macro' => $columns[0]->getText(),
|
||
|
'value' => $columns[2]->getText()
|
||
|
];
|
||
|
}
|
||
|
foreach ($macros as &$array) {
|
||
|
usort($array, function ($a, $b) {
|
||
|
return strcmp($a['macro'], $b['macro']);
|
||
|
});
|
||
|
}
|
||
|
unset ($array);
|
||
|
|
||
|
$this->assertEquals($macros['expected'], $macros['actual']);
|
||
|
}
|
||
|
|
||
|
// Compare preprocessing from data with steps from test table.
|
||
|
if (CTestArrayHelper::get($data, 'preprocessing')) {
|
||
|
$preprocessing_table = $test_form->query('id:preprocessing-steps')->asTable()->one();
|
||
|
|
||
|
foreach ($data['preprocessing'] as $i => $step) {
|
||
|
$this->assertEquals(($i+1).': '.$step['type'], $preprocessing_table->getRow($i)->getText());
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case TEST_BAD:
|
||
|
if (CTestArrayHelper::get($data, 'test_error')) {
|
||
|
$overlay->query('button:Get value and test')->one()->click();
|
||
|
$data['error'] = $data['test_error'];
|
||
|
}
|
||
|
|
||
|
$this->assertMessage(TEST_BAD, null, $data['error']);
|
||
|
$overlay->close();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Function for checking presence of fields and their editability, depending on specific preprocessing steps.
|
||
|
*
|
||
|
* @param array $data data provider
|
||
|
* @param CCheckboxElement $not_supported "Not supported" checkbox
|
||
|
* @param boolean $lld true if lld, false if item or prototype
|
||
|
*/
|
||
|
private function checkValueFields($data, $not_supported, $lld = false) {
|
||
|
$test_form = $this->query('id:preprocessing-test-form')->waitUntilReady()->one();
|
||
|
$get_host_value = $test_form->query('id:get_value')->asCheckbox()->one();
|
||
|
$checked = $get_host_value->isChecked();
|
||
|
$prev_enabled = false;
|
||
|
$value = $test_form->query('id:value')->asMultiline()->one();
|
||
|
|
||
|
if (!$checked) {
|
||
|
/*
|
||
|
* If item has at least one of following preprocessing steps,
|
||
|
* previous value and time field should become editable.
|
||
|
*/
|
||
|
if (CTestArrayHelper::get($data, 'preprocessing')){
|
||
|
$prev_enabled = false;
|
||
|
foreach ($data['preprocessing'] as $step) {
|
||
|
if (in_array($step['type'], ['Discard unchanged with heartbeat',
|
||
|
'Simple change', 'Change per second', 'Discard unchanged'])
|
||
|
) {
|
||
|
$prev_enabled = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ($lld === false){
|
||
|
$not_supported->check();
|
||
|
$this->assertFalse($value->isEnabled());
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
$this->assertTrue($value->isEnabled(!$checked));
|
||
|
}
|
||
|
|
||
|
$this->assertTrue($test_form->query('id:prev_value')->asMultiline()->one()->isEnabled($checked && $prev_enabled));
|
||
|
$this->assertTrue($test_form->query('id:prev_time')->one()->isEnabled($prev_enabled));
|
||
|
$this->assertFalse($test_form->query('id:time')->one()->isEnabled());
|
||
|
$this->assertTrue($test_form->query('id:eol')->one()->isEnabled());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Function for checking if Test button is enabled or disabled.
|
||
|
*
|
||
|
* @param string $item_type type of an item: item, prototype or lld rule
|
||
|
* @param boolean $enabled status of an element, true is enabled, false if disabled
|
||
|
* @param int $i index number of preprocessing step
|
||
|
*/
|
||
|
private function checkTestButtonInPreprocessing($item_type, $enabled = true, $i = 0) {
|
||
|
$item_form = $this->query('name:itemForm')->waitUntilPresent()->asForm()->one();
|
||
|
$test_button = $this->query('id:test_item')->waitUntilVisible()->one();
|
||
|
|
||
|
$this->assertTrue($test_button->isEnabled($enabled));
|
||
|
$item_form->selectTab('Preprocessing');
|
||
|
$this->assertTrue($test_button->isEnabled($enabled));
|
||
|
$this->query('id:param_add')->one()->click();
|
||
|
$this->assertTrue($test_button->isEnabled($enabled));
|
||
|
$this->query('name:preprocessing['.$i.'][remove]')->one()->click();
|
||
|
$item_form->selectTab($item_type);
|
||
|
}
|
||
|
|
||
|
private function saveFormAndCheckMessage($message) {
|
||
|
$item_form = $this->query('name:itemForm')->waitUntilPresent()->asForm()->one();
|
||
|
$item_form->submit();
|
||
|
$this->page->waitUntilReady();
|
||
|
$this->assertMessage(TEST_GOOD, $message);
|
||
|
}
|
||
|
}
|