<?php /* ** Copyright (C) 2001-2025 Zabbix SIA ** ** This program is free software: you can redistribute it and/or modify it under the terms of ** the GNU Affero General Public License as published by the Free Software Foundation, version 3. ** ** 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 Affero General Public License for more details. ** ** You should have received a copy of the GNU Affero General Public License along with this program. ** If not, see <https://www.gnu.org/licenses/>. **/ require_once dirname(__FILE__).'/../../include/CWebTest.php'; require_once dirname(__FILE__).'/../behaviors/CMessageBehavior.php'; require_once dirname(__FILE__).'/../behaviors/CPreprocessingBehavior.php'; /** * Base class for Preprocessing tests. */ abstract class testFormPreprocessing extends CWebTest { /** * Attach MessageBehavior and PreprocessingBehavior to the test. * * @return array */ public function getBehaviors() { return [ CMessageBehavior::class, CPreprocessingBehavior::class ]; } public $link; public $ready_link; public $success_message; public $button; public $fail_message; const INHERITED_ITEMID = 15094; // 'testInheritanceItemPreprocessing' const CLONE_ITEMID = 99102; // 'Simple form test host' -> 'testFormItem' const INHERITED_ITEM_PROTOTYPE = 15096; // 'testInheritanceDiscoveryRule' -> 'testInheritanceItemPrototypePreprocessing' const CLONE_ITEM_PROTOTYPEID = 23804; // 'Discovery rule for triggers filtering' -> 'Discovered item {#TEST}' const CLONE_PREPROCESSING = [ [ 'type' => '1', 'params' => '123', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '2', 'params' => 'abc', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '3', 'params' => 'def', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '4', 'params' => '1a2b3c', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '5', 'params' => "regular expression pattern \noutput template", 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '6', 'params' => '', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '7', 'params' => '', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '8', 'params' => '', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '9', 'params' => '', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '11', 'params' => '/document/item/value/text()', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '12', 'params' => '$.document.item.value parameter.', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '13', 'params' => "-5\n3", 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '14', 'params' => 'regular expression pattern for matching', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '15', 'params' => 'regular expression pattern for not matching', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '16', 'params' => '/json/path', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '17', 'params' => '/xml/path', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '18', 'params' => "regular expression pattern for error matching \ntest output", 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '20', 'params' => '7', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '21', 'params' => 'test script', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '23', 'params' => 'metric', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '24', 'params' => ".\n/\n1", 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '25', 'params' => "1\n2", 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '26', 'params' => "1\ntest", 'error_handler' => 1, 'error_handler_params' => '' ], [ 'type' => '27', 'params' => '', 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '28', 'params' => "OID\n1", 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '29', 'params' => "test\nOID\n1", 'error_handler' => 0, 'error_handler_params' => '' ], [ 'type' => '30', 'params' => '1', 'error_handler' => 0, 'error_handler_params' => '' ] ]; /** * Sets rows per page to 200 so that all items are always shown on screen. */ protected function setRowsPerPage() { DB::update('users', [ 'values' => ['rows_per_page' => 200], 'where' => ['userid' => 1] // Admin (super admin role) ]); } /* * GOOD scenario data common for all - items, item prototypes and LLD. * * Comments are formatted like this: * {Preprocessing step category} - {Preprocessing step name}. * The category is shown in UI. */ public static function getCommonPreprocessingCreateData() { return [ // Text - Regular expression. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Regular expression simple', 'Key' => 'regular-expression-simple[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Regular expression', 'parameter_1' => 'test', 'parameter_2' => 'TEST' ] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Regular expression complex', 'Key' => 'regular-expression-complex[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Regular expression', 'parameter_1' => '^(\d{4}-\d{1,2}-[0123]{1}\d) test ([ππ])', 'parameter_2' => 'date \1 emoji \2' ] ] ] ], // Text - Replace. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Replace', 'Key' => 'replace[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Replace', 'parameter_1' => 'old string ', 'parameter_2' => 'NEWπstring '] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Replace - empty replacement', 'Key' => 'replace-empty-replacement[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Replace', 'parameter_1' => 'replacement'] ] ] ], // Structured data - XML XPath. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'XML XPath', 'Key' => 'xml-xpath[{#KEY}]' ], 'preprocessing' => [ ['type' => 'XML XPath', 'parameter_1' => '//div[contains(@class, "test")]'] ] ] ], // Structured data - JSONPath. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'JSONPath', 'Key' => 'jsonpath[{#KEY}]' ], 'preprocessing' => [ ['type' => 'JSONPath', 'parameter_1' => '$.test[:1].type'] ] ] ], // Structured data - CSV to JSON. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'CSV to JSON empty parameters', 'Key' => 'csv-to-json-empty-parameters[{#KEY}]' ], 'preprocessing' => [ ['type' => 'CSV to JSON'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'CSV to JSON with default parameters', 'Key' => 'csv-to-json-with-default-parameters[{#KEY}]' ], 'preprocessing' => [ ['type' => 'CSV to JSON', 'parameter_1' => ',', 'parameter_2' => '"', 'parameter_3' => true] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'CSV to JSON custom parameters', 'Key' => 'csv-to-json-custom-parameters[{#KEY}]' ], 'preprocessing' => [ ['type' => 'CSV to JSON', 'parameter_1' => ' ', 'parameter_2' => "'", 'parameter_3' => false] ] ] ], // Structured data - XML to JSON. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'XML to JSON', 'Key' => 'xml-to-json[{#KEY}]' ], 'preprocessing' => [ ['type' => 'XML to JSON'] ] ] ], // SNMP - SNMP walk value. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'SNMP walk value - Unchanged', 'Key' => 'snmp-walk-value-unchanged[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'SNMP walk value', 'parameter_1' => '1.3.6.1.2.1.1.1', 'parameter_2' => 'Unchanged' ] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'SNMP walk value - UTF-8 from Hex-STRING', 'Key' => 'snmp-walk-value-utf8-hex[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'SNMP walk value', 'parameter_1' => 'SNMPv2-MIB::sysName.0', 'parameter_2' => 'UTF-8 from Hex-STRING' ] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'SNMP walk value - MAC from Hex-STRING', 'Key' => 'snmp-walk-value-mac-hex[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'SNMP walk value', 'parameter_1' => 'iso.org.dod.internet.mgmt.mib-2.system.sysDescr', 'parameter_2' => 'MAC from Hex-STRING' ] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'SNMP walk value - Integer from BITS', 'Key' => 'snmp-walk-value-int-bits[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'SNMP walk value', 'parameter_1' => '1.2.3.4.5.6.7.8.9', 'parameter_2' => 'Integer from BITS' ] ] ] ], // SNMP - SNMP walk to JSON. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'SNMP walk to JSON - Unchanged', 'Key' => 'snmp-walk-to-json-unchanged[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'SNMP walk to JSON', 'parameter_table_1_1' => 'test', 'parameter_table_1_2' => '1.3.6.1.2.1.1.1', 'parameter_table_1_3' => 'Unchanged' ] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'SNMP walk to JSON - UTF-8 from Hex-STRING', 'Key' => 'snmp-walk-to-json-uft8-hex[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'SNMP walk to JSON', 'parameter_table_1_1' => 'fieldName', 'parameter_table_1_2' => 'SNMPv2-MIB::sysName.0', 'parameter_table_1_3' => 'UTF-8 from Hex-STRING' ] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'SNMP walk to JSON - MAC from Hex-STRING', 'Key' => 'snmp-walk-to-json-mac-hex[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'SNMP walk to JSON', 'parameter_table_1_1' => '1234', 'parameter_table_1_2' => 'iso.org.dod.internet.mgmt.mib-2.system.sysDescr', 'parameter_table_1_3' => 'MAC from Hex-STRING' ] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'SNMP walk to JSON - Integer from BITS', 'Key' => 'snmp-walk-to-json-int-bits[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'SNMP walk to JSON', 'parameter_table_1_1' => 'test.test', 'parameter_table_1_2' => '1.2.3.4.5.6.7.8.9', 'parameter_table_1_3' => 'Integer from BITS' ] ] ] ], // SNMP - SNMP get value. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'SNMP get value - UTF-8 from Hex-STRING', 'Key' => 'snmp-get-value-utf8-hex[{#KEY}]' ], 'preprocessing' => [ ['type' => 'SNMP get value', 'parameter_1' => 'UTF-8 from Hex-STRING'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'SNMP get value - MAC from Hex-STRING', 'Key' => 'snmp-get-value-mac-hex[{#KEY}]' ], 'preprocessing' => [ ['type' => 'SNMP get value', 'parameter_1' => 'MAC from Hex-STRING'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'SNMP get value - Integer from BITS', 'Key' => 'snmp-get-value-int-bits[{#KEY}]' ], 'preprocessing' => [ ['type' => 'SNMP get value', 'parameter_1' => 'Integer from BITS'] ] ] ], // Custom scripts - JavaScript. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'JavaScript', 'Key' => 'javascript[{#KEY}]' ], 'preprocessing' => [ ['type' => 'JavaScript', 'parameter_1' => 'alert("hi!");'] ] ] ], // Validation - Matches regular expression. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Matches regular expression', 'Key' => 'matches-regular-expression[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Matches regular expression', 'parameter_1' => '^test[123].*\d{4}-\d{1,2}-[0123]{1}\d$'] ] ] ], // Validation - Does not match regular expression. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Does not match regular expression', 'Key' => 'does-not-match-regular-expression[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Does not match regular expression', 'parameter_1' => '^test[123].*\d{4}-\d{1,2}-[0123]{1}\d$'] ] ] ], // Validation - Check for error in JSON. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Check for error in JSON', 'Key' => 'check-for-error-in-json[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for error in JSON', 'parameter_1' => '$.path.to.node'] ] ] ], // Validation - Check for error in XML. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Check for error in XML', 'Key' => 'check-for-error-in-xml[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for error in XML', 'parameter_1' => '//div[contains(@class, "test")]'] ] ] ], // Throttling - Discard unchanged with heartbeat. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Discard unchanged with heartbeat', 'Key' => 'discard-unchanged-with-heartbeat[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '2'] ] ] ] ]; } /* * GOOD scenario data for items and item prototypes ONLY (not LLD). * * Comments are formatted like this: * {Preprocessing step category} - {Preprocessing step name}. * The category is shown in UI. */ public function getItemPreprocessingCreateData() { return array_merge($this->getCommonPreprocessingCreateData(), [ // Text - Trim. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Trim', 'Key' => 'trim[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Trim', 'parameter_1' => ' \t\\\\'] ] ] ], // Text - Right trim. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Right trim', 'Key' => 'right-trim[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Right trim', 'parameter_1' => '\n'] ] ] ], // Text - Left trim. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Left trim', 'Key' => 'left-trim[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Left trim', 'parameter_1' => ' '] ] ] ], // Arithmetic - Custom multiplier. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Custom multiplier', 'Key' => 'custom-multiplier[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Custom multiplier', 'parameter_1' => '1.23'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Custom multiplier - scientific notation', 'Key' => 'custom-multiplier-scientific[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Custom multiplier', 'parameter_1' => '1.5617497E+20'] ] ] ], // Change - Simple change. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Simple change', 'Key' => 'simple-change[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Simple change'] ] ] ], // Change - Change per second. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Change per second', 'Key' => 'change-per-second[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Change per second'] ] ] ], // Numeral systems - Boolean to decimal. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Boolean to decimal', 'Key' => 'boolean-to-decimal[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Boolean to decimal'] ] ] ], // Numeral systems - Octal to decimal. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Octal to decimal', 'Key' => 'octal-to-decimal[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Octal to decimal'] ] ] ], // Numeral systems - Hexadecimal to decimal. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Hexadecimal to decimal', 'Key' => 'hexadecimal-to-decimal[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Hexadecimal to decimal'] ] ] ], // Validation - In range. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'In range negative float', 'Key' => 'in-range-negative-float[{#KEY}]' ], 'preprocessing' => [ ['type' => 'In range', 'parameter_1' => '-3.5', 'parameter_2' => '-1.5'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'In range zero', 'Key' => 'in-range-zero[{#KEY}]' ], 'preprocessing' => [ ['type' => 'In range', 'parameter_1' => '0', 'parameter_2' => '1'] ] ] ], // Validation - Check for error using regular expression. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Check for error using regular expression', 'Key' => 'check-for-error-using-regular-expression[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Check for error using regular expression', 'parameter_1' => '^test[123].*(\d{4}-\d{1,2}-[0123]{1})\d$', 'parameter_2' => 'output \1' ] ] ] ], // Validation - Check for not supported value. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Check for not supported value - any error', 'Key' => 'check-for-not-supported-value-any-error[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for not supported value', 'parameter_1' => 'any error'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Check for not supported value - error matches', 'Key' => 'check-for-not-supported-value-error-matches[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for not supported value', 'parameter_1' => 'error matches', 'parameter_2' => '^test.*$'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Check for not supported value - error does not match', 'Key' => 'check-for-not-supported-value-error-does-not-match[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for not supported value', 'parameter_1' => 'error does not match', 'parameter_2' => '^test.*$'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Check for not supported value - error matches + any error', 'Key' => 'check-for-not-supported-value-1[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for not supported value', 'parameter_1' => 'error matches', 'parameter_2' => '^test.*$'], ['type' => 'Check for not supported value', 'parameter_1' => 'any error'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Check for not supported value - error matches + error matches', 'Key' => 'check-for-not-supported-value-2[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for not supported value', 'parameter_1' => 'error matches', 'parameter_2' => '^test.*$'], ['type' => 'Check for not supported value', 'parameter_1' => 'error matches', 'parameter_2' => 'different'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Check for not supported value - error matches + error matches (equal parameters)', 'Key' => 'check-for-not-supported-value-3[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for not supported value', 'parameter_1' => 'error matches', 'parameter_2' => 'equal'], ['type' => 'Check for not supported value', 'parameter_1' => 'error matches', 'parameter_2' => 'equal'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Check for not supported value - error does not match + any error', 'Key' => 'check-for-not-supported-value-4[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for not supported value', 'parameter_1' => 'error does not match', 'parameter_2' => '^test.*$'], ['type' => 'Check for not supported value', 'parameter_1' => 'any error'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Check for not supported value - error does not match + error does not match', 'Key' => 'check-for-not-supported-value-5[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for not supported value', 'parameter_1' => 'error does not match', 'parameter_2' => '^test.*$'], ['type' => 'Check for not supported value', 'parameter_1' => 'error does not match', 'parameter_2' => 'different'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Check for not supported value - error does not match + error does not match (equal parameters)', 'Key' => 'check-for-not-supported-value-6[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for not supported value', 'parameter_1' => 'error does not match', 'parameter_2' => 'equal'], ['type' => 'Check for not supported value', 'parameter_1' => 'error does not match', 'parameter_2' => 'equal'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Check for not supported value - all types', 'Key' => 'check-for-not-supported-value-all-types[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for not supported value', 'parameter_1' => 'error does not match', 'parameter_2' => 'aa'], ['type' => 'Check for not supported value', 'parameter_1' => 'error matches', 'parameter_2' => '^test.*$'], ['type' => 'Check for not supported value', 'parameter_1' => 'any error'] ] ] ], // Throttling - Discard unchanged. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Discard unchanged', 'Key' => 'discard-unchanged[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Discard unchanged'] ] ] ], // All steps at once. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'All steps at once', 'Key' => 'all-steps-at-once[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for not supported value'], ['type' => 'Regular expression', 'parameter_1' => 'expression', 'parameter_2' => 'test output'], ['type' => 'Replace', 'parameter_1' => 'text', 'parameter_2' => 'REPLACEMENT'], ['type' => 'Trim', 'parameter_1' => '1a2b3c'], ['type' => 'Right trim', 'parameter_1' => 'abc'], ['type' => 'Left trim', 'parameter_1' => 'def'], ['type' => 'XML XPath', 'parameter_1' => 'def'], ['type' => 'JSONPath', 'parameter_1' => 'def'], ['type' => 'CSV to JSON','parameter_1' => ' ', 'parameter_2' => '\\', 'parameter_3' => true], ['type' => 'XML to JSON'], ['type' => 'SNMP walk value', 'parameter_1' => '1.2.3', 'parameter_2' => 'UTF-8 from Hex-STRING'], ['type' => 'SNMP walk to JSON', 'parameter_table_1_1' => 'abc', 'parameter_table_1_2' => '123'], ['type' => 'SNMP get value', 'parameter_1' => 'MAC from Hex-STRING'], ['type' => 'Custom multiplier', 'parameter_1' => '123'], ['type' => 'Simple change'], ['type' => 'Boolean to decimal'], ['type' => 'Octal to decimal'], ['type' => 'Hexadecimal to decimal'], ['type' => 'JavaScript', 'parameter_1' => 'Test JavaScript'], ['type' => 'In range', 'parameter_1' => '-5', 'parameter_2' => '9.5'], ['type' => 'Matches regular expression', 'parameter_1' => 'test'], ['type' => 'Does not match regular expression', 'parameter_1' => 'test'], ['type' => 'Check for error in JSON', 'parameter_1' => 'test'], ['type' => 'Check for error in XML', 'parameter_1' => 'abc'], ['type' => 'Check for error using regular expression', 'parameter_1' => 'test', 'parameter_2' => 'abc'], ['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '5'], ['type' => 'Prometheus pattern', 'parameter_1' => 'cpu_usage_system', 'parameter_2' => 'label', 'parameter_3' => 'label_name' ] ] ] ], // Many steps for screenshot. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Many steps for screenshot', 'Key' => 'many-steps-for-screenshot[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for not supported value'], ['type' => 'Replace', 'parameter_1' => 'text', 'parameter_2' => 'REPLACEMENT'], ['type' => 'Right trim', 'parameter_1' => 'abc'], ['type' => 'Left trim', 'parameter_1' => 'def'], ['type' => 'Trim', 'parameter_1' => '1a2b3c'], ['type' => 'CSV to JSON','parameter_1' => ' ', 'parameter_2' => '\\', 'parameter_3' => true], ['type' => 'XML to JSON'], ['type' => 'Custom multiplier', 'parameter_1' => '123'], ['type' => 'Regular expression', 'parameter_1' => 'expression', 'parameter_2' => 'test output'], ['type' => 'Boolean to decimal'], ['type' => 'Octal to decimal'], ['type' => 'Hexadecimal to decimal'], ['type' => 'JavaScript', 'parameter_1' => 'Test JavaScript'], ['type' => 'Simple change'], ['type' => 'In range', 'parameter_1' => '-5', 'parameter_2' => '9.5'], ['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '5'], ['type' => 'Prometheus pattern', 'parameter_1' => 'cpu_usage_system', 'parameter_2' => 'label', 'parameter_3' => 'label_name' ] ], 'screenshot' => true ] ], // Unicode symbols. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Unicode symbols', 'Key' => 'unicode-symbols[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Regular expression', 'parameter_1' => '01_<!@"\' ππ', 'parameter_2' => '02_<!@"\' ππ'], ['type' => 'Replace', 'parameter_1' => '03_<!@"\' ππ', 'parameter_2' => '04_<!@"\' ππ'], ['type' => 'Trim', 'parameter_1' => '05_<!@"\' ππ'], ['type' => 'Right trim', 'parameter_1' => '06_<!@"\' ππ'], ['type' => 'Left trim', 'parameter_1' => '07_<!@"\' ππ'], ['type' => 'XML XPath', 'parameter_1' => '08_<!@"\' ππ'], ['type' => 'JSONPath', 'parameter_1' => '09_<!@"\' ππ'], ['type' => 'CSV to JSON','parameter_1' => '<', 'parameter_2' => '<'], ['type' => 'SNMP walk value', 'parameter_1' => '10_<!@"\' ππ'], ['type' => 'SNMP walk to JSON', 'parameter_table_1_1' => '11_<!@"\' ππ', 'parameter_table_1_2' => '12_<!@"\' ππ'], ['type' => 'JavaScript', 'parameter_1' => '13_5d!@#$%^&*()-='], ['type' => 'Matches regular expression', 'parameter_1' => '14_<!@"\' ππ'], ['type' => 'Does not match regular expression', 'parameter_1' => '15_<!@"\' ππ'], ['type' => 'Check for error in JSON', 'parameter_1' => '16_<!@"\' ππ'], ['type' => 'Check for error in XML', 'parameter_1' => '17_<!@"\' ππ'], ['type' => 'Check for error using regular expression', 'parameter_1' => '18_<!@"\' ππ', 'parameter_2' => '19_<!@"\' ππ'] ] ] ], // Duplicate steps. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Duplicate steps', 'Key' => 'duplicate-steps[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Regular expression', 'parameter_1' => 'expression', 'parameter_2' => 'test output'], ['type' => 'Regular expression', 'parameter_1' => 'expression', 'parameter_2' => 'test output'], ['type' => 'Replace', 'parameter_1' => 'text', 'parameter_2' => 'REPLACEMENT'], ['type' => 'Replace', 'parameter_1' => 'text', 'parameter_2' => 'REPLACEMENT'], ['type' => 'Trim', 'parameter_1' => '1a2b3c'], ['type' => 'Trim', 'parameter_1' => '1a2b3c'], ['type' => 'Right trim', 'parameter_1' => 'abc'], ['type' => 'Right trim', 'parameter_1' => 'abc'], ['type' => 'Left trim', 'parameter_1' => 'def'], ['type' => 'Left trim', 'parameter_1' => 'def'], ['type' => 'XML XPath', 'parameter_1' => 'def'], ['type' => 'XML XPath', 'parameter_1' => 'def'], ['type' => 'JSONPath', 'parameter_1' => 'def'], ['type' => 'JSONPath', 'parameter_1' => 'def'], ['type' => 'CSV to JSON','parameter_1' => ' ', 'parameter_2' => '\\', 'parameter_3' => true], ['type' => 'CSV to JSON','parameter_1' => ' ', 'parameter_2' => '\\', 'parameter_3' => true], ['type' => 'XML to JSON'], ['type' => 'XML to JSON'], ['type' => 'SNMP walk value', 'parameter_1' => '1.2.3', 'parameter_2' => 'UTF-8 from Hex-STRING'], ['type' => 'SNMP walk value', 'parameter_1' => '1.2.3', 'parameter_2' => 'UTF-8 from Hex-STRING'], ['type' => 'SNMP walk to JSON', 'parameter_table_1_1' => 'abc', 'parameter_table_1_2' => '123'], ['type' => 'SNMP walk to JSON', 'parameter_table_1_1' => 'abc', 'parameter_table_1_2' => '123'], ['type' => 'SNMP get value', 'parameter_1' => 'MAC from Hex-STRING'], ['type' => 'SNMP get value', 'parameter_1' => 'MAC from Hex-STRING'], ['type' => 'Custom multiplier', 'parameter_1' => '123'], ['type' => 'Custom multiplier', 'parameter_1' => '123'], ['type' => 'Boolean to decimal'], ['type' => 'Boolean to decimal'], ['type' => 'Octal to decimal'], ['type' => 'Octal to decimal'], ['type' => 'Hexadecimal to decimal'], ['type' => 'Hexadecimal to decimal'], ['type' => 'JavaScript', 'parameter_1' => 'Test JavaScript'], ['type' => 'JavaScript', 'parameter_1' => 'Test JavaScript'], ['type' => 'In range', 'parameter_1' => '-5', 'parameter_2' => '9.5'], ['type' => 'In range', 'parameter_1' => '-5', 'parameter_2' => '9.5'], ['type' => 'Matches regular expression', 'parameter_1' => 'test'], ['type' => 'Matches regular expression', 'parameter_1' => 'test'], ['type' => 'Does not match regular expression', 'parameter_1' => 'test'], ['type' => 'Does not match regular expression', 'parameter_1' => 'test'], ['type' => 'Check for error in JSON', 'parameter_1' => 'test'], ['type' => 'Check for error in JSON', 'parameter_1' => 'test'], ['type' => 'Check for error in XML', 'parameter_1' => 'abc'], ['type' => 'Check for error in XML', 'parameter_1' => 'abc'], ['type' => 'Check for error using regular expression', 'parameter_1' => 'test', 'parameter_2' => 'abc'], ['type' => 'Check for error using regular expression', 'parameter_1' => 'test', 'parameter_2' => 'abc'] ] ] ], // User macros. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item with preprocessing rule with user macro', 'Key' => 'item-user-macro[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Replace', 'parameter_1' => '{$TEST1}', 'parameter_2' => '{$MACRO2}'], ['type' => 'Regular expression', 'parameter_1' => '{$DELIM}(.*)', 'parameter_2' => '\1'], ['type' => 'Trim', 'parameter_1' => '{$DELIM}'], ['type' => 'Right trim', 'parameter_1' => '{$MACRO}'], ['type' => 'Left trim', 'parameter_1' => '{$USER}'], ['type' => 'XML XPath', 'parameter_1' => 'number(/values/Item/value[../key=\'{$DELIM}\'])'], ['type' => 'JSONPath', 'parameter_1' => '$.data[\'{$KEY}\']'], ['type' => 'Custom multiplier', 'parameter_1' => '{$VALUE}'], ['type' => 'In range', 'parameter_1' => '{$FROM}', 'parameter_2' => '{$TO}'], ['type' => 'Matches regular expression', 'parameter_1' => '{$EXPRESSION}(.*)'], ['type' => 'Does not match regular expression', 'parameter_1' => '{$REGEXP}(.+)'], ['type' => 'JavaScript', 'parameter_1' => '{$JAVASCRIPT}'], ['type' => 'Check for error in JSON', 'parameter_1' => '{$USERMACRO}'], ['type' => 'Check for error in XML', 'parameter_1' => '/tmp/{$PATH}'], ['type' => 'Check for error using regular expression', 'parameter_1' => '^{$REGEXP}(.+)', 'parameter_2' => '\0'], ['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '{$SECONDS}'], ['type' => 'Prometheus to JSON', 'parameter_1' => '{$PATTERN}'] ] ] ], // Whitespace. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item with spaces in preprocessing', 'Key' => 'item-spaces-preprocessing[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Replace', 'parameter_1' => ' test text ', 'parameter_2' => ' replacement 1 '], ['type' => 'Regular expression', 'parameter_1' => ' pattern ', 'parameter_2' => ' \1 '], ['type' => 'Right trim', 'parameter_1' => ' 22 '], ['type' => 'Left trim', 'parameter_1' => ' 33 '], ['type' => 'Trim', 'parameter_1' => ' 0 '], ['type' => 'XML XPath', 'parameter_1' => ' number(/values/Item) '], ['type' => 'JSONPath', 'parameter_1' => ' $.data.key '], ['type' => 'Matches regular expression', 'parameter_1' => ' expression '], ['type' => 'Does not match regular expression', 'parameter_1' => ' not_expression '], ['type' => 'JavaScript', 'parameter_1' => " Test line 1 \n Test line 2 \n Test line 3 \n \n "], ['type' => 'Check for error in JSON', 'parameter_1' => ' $.error '], ['type' => 'Check for error in XML', 'parameter_1' => ' /tmp/path/ '], ['type' => 'Check for error using regular expression', 'parameter_1' => ' expression ', 'parameter_2' => ' 0 '] ] ] ] ]); } /* * BAD scenario data, common for all - items, item prototypes and LLD. * * Comments are formatted like this: * {Preprocessing step category} - {Preprocessing step name}. * The category is shown in UI. */ public static function getCommonPreprocessingValidationData() { return [ // Text - Regular expression. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Regular expression - missing both parameters', 'Key' => 'regex-empty[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Regular expression'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Regular expression - missing pattern', 'Key' => 'regex-missing-pattern[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Regular expression', 'parameter_2' => 'output'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Regular expression - missing output', 'Key' => 'regex-missing-output[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Regular expression', 'parameter_1' => 'expression'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/2": cannot be empty.' ] ], // Text - Replace. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Replace - missing search string', 'Key' => 'replace-missing-search-string[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Replace', 'parameter_2' => 'replacement'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], // Structured data - XML XPath. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'XML XPath missing', 'Key' => 'xpath-missing[{#KEY}]' ], 'preprocessing' => [ ['type' => 'XML XPath'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], // Structured data - JSONPath. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'JSONPath missing', 'Key' => 'jsonpath-missing[{#KEY}]' ], 'preprocessing' => [ ['type' => 'JSONPath'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], // SNMP - SNMP walk value. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'SNMP walk value - missing OID', 'Key' => 'snmp-walk-value-missing-oid[{#KEY}]' ], 'preprocessing' => [ ['type' => 'SNMP walk value'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], // SNMP - SNMP walk to JSON. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'SNMP walk to JSON - missing all fields', 'Key' => 'snmp-walk-to-json-missing-all[{#KEY}]' ], 'preprocessing' => [ ['type' => 'SNMP walk to JSON'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'SNMP walk to JSON - missing Field name', 'Key' => 'snmp-walk-to-json-missing-name[{#KEY}]' ], 'preprocessing' => [ ['type' => 'SNMP walk to JSON', 'parameter_table_1_2' => '1.3.6.1.2.1.1.1'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'SNMP walk to JSON - missing OID', 'Key' => 'snmp-walk-to-json-missing-oid[{#KEY}]' ], 'preprocessing' => [ ['type' => 'SNMP walk to JSON', 'parameter_table_1_1' => 'test'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/2": cannot be empty.' ] ], // Custom scripts - JavaScript. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'JavaScript missing', 'Key' => 'javascript-missing[{#KEY}]' ], 'preprocessing' => [ ['type' => 'JavaScript'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], // Validation - Does not match regular expression. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Does not match regular expression - missing parameter', 'Key' => 'does-not-match-regular-expression-missing[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Does not match regular expression'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], // Validation - Check for error in JSON. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Check for error in JSON - missing parameter', 'Key' => 'check-for-error-in-json-missing[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for error in JSON'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], // Throttling - Discard unchanged with heartbeat. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Discard unchanged with heartbeat - conflict with different values', 'Key' => 'discard-unchanged-with-heartbeat-conflict-different[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '1'], ['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '2'] ], 'error' => 'Invalid parameter "/1/preprocessing/2": only one object can exist '. 'within the combinations of (type)=((19, 20)).' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Discard unchanged with heartbeat - missing seconds', 'Key' => 'discard-unchanged-with-heartbeat-missing-seconds[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Discard unchanged with heartbeat'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Discard unchanged with heartbeat - string', 'Key' => 'discard-unchanged-with-heartbeat-string[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Discard unchanged with heartbeat', 'parameter_1' => 'abc'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": a time unit is expected.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Discard unchanged with heartbeat - string with symbols', 'Key' => 'discard-unchanged-with-heartbeat-string-symbols[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '3g!@#$%^&*()-=β¨'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": a time unit is expected.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Discard unchanged with heartbeat - decimal seconds', 'Key' => 'discard-unchanged-with-heartbeat-decimal[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '1.5'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": a time unit is expected.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Discard unchanged with heartbeat - comma as decimal point', 'Key' => 'discard-unchanged-with-heartbeat-comma[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '1,5'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": a time unit is expected.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Discard unchanged with heartbeat - negative value', 'Key' => 'discard-unchanged-with-heartbeat-negative[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '-3'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": value must be one of 1-788400000.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Discard unchanged with heartbeat - value zero', 'Key' => 'discard-unchanged-with-heartbeat-zero[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '0'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": value must be one of 1-788400000.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Discard unchanged with heartbeat - value over maximum', 'Key' => 'discard-unchanged-with-heartbeat-max[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '788400001'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": value must be one of 1-788400000.' ] ] ]; } /* * BAD scenario data for items and item prototypes ONLY (not LLD). * * Comments are formatted like this: * {Preprocessing step category} - {Preprocessing step name}. * The category is shown in UI. */ public function getItemPreprocessingValidationData() { return array_merge($this->getCommonPreprocessingValidationData(), [ // Text - Trim. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Trim - missing list of characters', 'Key' => 'trim-empty[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Trim'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], // Text - Right trim. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Right trim - missing list of characters', 'Key' => 'right-trim-empty[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Right trim'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], // Text - Left trim. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Left trim - missing list of characters', 'Key' => 'left-trim-empty[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Left trim'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], // Arithmetic - Custom multiplier. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Custom multiplier - missing multiplier', 'Key' => 'custom-multiplier-missing-multiplier[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Custom multiplier'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": a floating point value is expected.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Custom multiplier - string multiplier', 'Key' => 'custom-multiplier-string-multiplier[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Custom multiplier', 'parameter_1' => 'abc'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": a floating point value is expected.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Custom multiplier - comma as decimal point', 'Key' => 'custom-multiplier-comma[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Custom multiplier', 'parameter_1' => '0,0'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": a floating point value is expected.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Custom multiplier - invalid scientific notation', 'Key' => 'symbols-multiplier[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Custom multiplier', 'parameter_1' => '3.2e+12<$@β¨'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": a floating point value is expected.' ] ], // Change - Simple change. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Simple change - duplicate', 'Key' => 'simple-change-duplicate[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Simple change'], ['type' => 'Simple change'] ], 'error' => 'Invalid parameter "/1/preprocessing/2": only one object can exist within '. 'the combinations of (type)=((9, 10)).' ] ], // Change - Change per second. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Change per second - duplicate', 'Key' => 'change-per-second-duplicate[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Change per second'], ['type' => 'Change per second'] ], 'error' => 'Invalid parameter "/1/preprocessing/2": only one object can exist within '. 'the combinations of (type)=((9, 10)).' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Change per second - conflict with simple change', 'Key' => 'change-per-second-conflict[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Simple change'], ['type' => 'Change per second'] ], 'error' => 'Invalid parameter "/1/preprocessing/2": only one object can exist within '. 'the combinations of (type)=((9, 10)).' ] ], // Validation - In range. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'In range - missing all', 'Key' => 'in-range-missing-all[{#KEY}]' ], 'preprocessing' => [ ['type' => 'In range'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params": cannot be empty.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'In range - strings', 'Key' => 'in-range-strings[{#KEY}]' ], 'preprocessing' => [ ['type' => 'In range', 'parameter_1' => 'abc', 'parameter_2' => 'def'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": a floating point value is expected.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'In range - symbols', 'Key' => 'in-range-symbols[{#KEY}]' ], 'preprocessing' => [ ['type' => 'In range', 'parameter_1' => '1a!@#$%^&*()-=β¨', 'parameter_2' => '2b!@#$%^&*()-=β¨'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": a floating point value is expected.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'In range - comma for decimal point', 'Key' => 'in-range-comma[{#KEY}]' ], 'preprocessing' => [ ['type' => 'In range', 'parameter_1' => '1,5', 'parameter_2' => '-3,5'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": a floating point value is expected.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'In range - invalid interval', 'Key' => 'in-range-invalid-interval[{#KEY}]' ], 'preprocessing' => [ ['type' => 'In range', 'parameter_1' => '8', 'parameter_2' => '-8'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/2": cannot be less than or equal '. 'to the value of parameter "/1/preprocessing/1/params/1".' ] ], // Validation - Matches regular expression. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Matches regular expression - missing parameter', 'Key' => 'matches-regular-expression-missing[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Matches regular expression'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], // Validation - Check for error in XML. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Check for error in XML - missing parameter', 'Key' => 'check-for-error-in-xml-missing[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for error in XML'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], // Validation - Check for error using regular expression. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Check for error using regular expression - missing all', 'Key' => 'check-for-error-using-regex-missing[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for error using regular expression'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Check for error using regular expression - missing pattern', 'Key' => 'check-for-error-using-regex-missing-pattern[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for error using regular expression', 'parameter_2' => 'test'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Check for error using regular expression - missing output', 'Key' => 'check-for-error-using-regex-missing-output[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for error using regular expression', 'parameter_1' => 'test'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/2": cannot be empty.' ] ], // Validation - Check for not supported value. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Check for not supported value - duplicate', 'Key' => 'check-for-not-supported-duplicate[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Check for not supported value'], ['type' => 'Check for not supported value'] ], 'error' => 'Invalid parameter "/1/preprocessing/2": value (type, params)=(26, -1) already exists.' ] ], // Throttling - Discard unchanged. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Discard unchanged - duplicate', 'Key' => 'discard-unchanged-duplicate[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Discard unchanged'], ['type' => 'Discard unchanged'] ], 'error' => 'Invalid parameter "/1/preprocessing/2": only one object can exist within '. 'the combinations of (type)=((19, 20)).' ] ], // Throttling - Discard unchanged with heartbeat. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Discard unchanged with heartbeat - duplicate', 'Key' => 'discard-unchanged-with-heartbeat-duplicate[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '1'], ['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '1'] ], 'error' => 'Invalid parameter "/1/preprocessing/2": only one object can exist within '. 'the combinations of (type)=((19, 20)).' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Discard unchanged with heartbeat - conflict', 'Key' => 'discard-unchanged-with-heartbeat-conflict[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Discard unchanged'], ['type' => 'Discard unchanged with heartbeat', 'parameter_1' => '1'] ], 'error' => 'Invalid parameter "/1/preprocessing/2": only one object can exist within '. 'the combinations of (type)=((19, 20)).' ] ] ]); } /* * "Prometheus to JSON" data for item, item prototype and LLD. */ public static function getPrometheustoJSONData() { return [ // Prometheus to JSON validation. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus to JSON first parameter starts with digits', 'Key' => 'json-prometeus-digits-first-parameter[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '1name_of_metric'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus to JSON wrong equals operator', 'Key' => 'json-prometeus-wrong-equals-operator[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{__name__=~"<regex>"}=1'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus to JSON unsupported operator >', 'Key' => 'json-prometeus-unsupported-operator-1[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{__name__=~"<regex>"}>1'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus to JSON unsupported operator <', 'Key' => 'json-prometeus-unsupported-operator-2[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{__name__=~"<regex>"}<1'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus to JSON unsupported operator !==', 'Key' => 'json-prometeus-unsupported-operator-3[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{__name__=~"<regex>"}!==1'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus to JSON unsupported operator >=', 'Key' => 'json-prometeus-unsupported-operator-4[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{__name__=~"<regex>"}>=1'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus to JSON unsupported operator =<', 'Key' => 'json-prometeus-unsupported-operator-5[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{__name__=~"<regex>"}=<1'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus to JSON duplicate metric condition', 'Key' => 'json-duplicate-metric-condition[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => 'cpu_system{__name__="metric_name"}'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus to JSON wrong parameter - space', 'Key' => 'json-wrong-parameter-space[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => 'cpu usage_system'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus to JSON wrong parameter - slash', 'Key' => 'json-wrong-parameter-slash[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => 'cpu\\'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometheus to JSON wrong parameter - digits', 'Key' => 'json-wrong-parameter-digits[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '123'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometheus to JSON wrong first parameter - pipe', 'Key' => 'json-wrong-parameter-pipe[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => 'metric==1e|5'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometheus to JSON wrong first parameter - slash', 'Key' => 'json-wrong-parameter-slash[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{label="value\"}'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item duplicate Prometeus to JSON steps', 'Key' => 'duplicate-prometheus-to-json-steps[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => 'cpu_usage_system_1'], ['type' => 'Prometheus to JSON', 'parameter_1' => 'cpu_usage_system_1'] ], 'error' => 'Invalid parameter "/1/preprocessing/2": only one object can exist within '. 'the combinations of (type)=((22, 23)).' ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON empty first parameter', 'Key' => 'json-prometeus-empty-first-parameter[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => ''] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON first parameter +inf', 'Key' => 'json-prometeus-plus-inf[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => 'cpu_usage_system==+inf'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON first parameter inf', 'Key' => 'json-prometeus-inf[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{__name__="metric_name"}==inf'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON first parameter -inf', 'Key' => 'json-prometeus-negative-inf[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{__name__=~"<regex>"}==-inf'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON first parameter nan', 'Key' => 'json-prometeus-nan[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{__name__="metric_name"}==nan'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON first parameter exp', 'Key' => 'json-prometeus-exp[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => 'cpu_usage_system==3.5180e+11'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON first parameter ==1', 'Key' => 'json-prometeus-neutral-digit[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{__name__="metric_name"}==1'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON first parameters ==+1', 'Key' => 'json-prometeus-positive-digit[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{__name__="metric_name"}==+1'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON first parameters ==-1', 'Key' => 'json-prometeus-negative-digit[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{__name__="metric_name"}==-1'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON label operator =', 'Key' => 'json-prometeus-label-operator-equal-strong[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{label_name="name"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON label operator =~', 'Key' => 'json-prometeus-label-operator-contains[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{label_name=~"name"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON slashes in pattern', 'Key' => 'json-prometeus-slashes-pattern[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{label="value\\\\"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON user macros in parameter 1', 'Key' => 'json-prometeus-macros-1[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{$METRIC_NAME}==1'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON user macros in parameter 2', 'Key' => 'json-prometeus-macros-2[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{__name__="{$METRIC_NAME}"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON user macros in parameters 3', 'Key' => 'json-prometeus-macros-3[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{{$LABEL_NAME}="<label value>"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON user macros in parameters 4', 'Key' => 'json-prometeus-macros-4[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{label_name="{$LABEL_VALUE}"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON unsupported label operator !=', 'Key' => 'json-prometeus-unsupported-label-operator-1[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{label_name!="regex_pattern"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus to JSON unsupported label operator !~', 'Key' => 'json-prometeus-unsupported-label-operator-2[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => '{label_name!~"<regex>"}'] ] ] ] ]; } /* * Prometheus data for item and item prototype (included preprocessing step "Prometheus pattern"). */ public function getPrometheusData() { return array_merge($this->getPrometheustoJSONData(), [ // Prometheus pattern validation. [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus empty first parameter', 'Key' => 'prometeus-empty-first-parameter[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": cannot be empty.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Prometheus space in pattern', 'Key' => 'prometheus-space-in-pattern[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => 'cpu usage_metric'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Prometheus only digits in pattern', 'Key' => 'prometheus-digits-in-pattern[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '1223'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus first parameter starts with digits', 'Key' => 'prometeus-digits-first-parameter[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '1name_of_metric'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus wrong equals operator', 'Key' => 'prometeus-wrong-equals-operator[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{__name__=~"<regex>"}=1'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus unsupported operator >', 'Key' => 'prometeus-unsupported-operator-1[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{__name__=~"<regex>"}>1'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus unsupported operator <', 'Key' => 'prometeus-unsupported-operator-2[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{__name__=~"<regex>"}<1'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus unsupported operator !==', 'Key' => 'prometeus-unsupported-operator-3[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{__name__=~"<regex>"}!==1'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus unsupported operator >=', 'Key' => 'prometeus-unsupported-operator-4[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{__name__=~"<regex>"}>=1'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus unsupported operator =<', 'Key' => 'prometeus-unsupported-operator-5[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{__name__=~"<regex>"}=<1'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus duplicate metric condition', 'Key' => 'duplicate-metric-condition[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => 'cpu_system{__name__="metric_name"}'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item duplicate Prometeus steps', 'Key' => 'duplicate-prometheus-steps[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => 'cpu_usage_system'], ['type' => 'Prometheus pattern', 'parameter_1' => 'cpu_usage_system'] ], 'error' => 'Invalid parameter "/1/preprocessing/2": only one object can exist within '. 'the combinations of (type)=((22, 23)).' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus wrong second parameter - space', 'Key' => 'wrong-second-parameter-space[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Prometheus pattern', 'parameter_1' => 'cpu_usage_system', 'parameter_2' => 'label', 'parameter_3' => 'label name' ] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/3": invalid Prometheus label.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus wrong second parameter - quotes', 'Key' => 'wrong-second-parameter-quotes[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Prometheus pattern', 'parameter_1' => 'cpu_usage_system', 'parameter_2' => 'label', 'parameter_3' => '"label_name"' ] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/3": invalid Prometheus label.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus wrong second parameter - triangle quotes', 'Key' => 'wrong-second-parameter-triangle-quotes[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Prometheus pattern', 'parameter_1' => 'cpu_usage_system', 'parameter_2' => 'label', 'parameter_3' => '<label_name>' ] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/3": invalid Prometheus label.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus wrong second parameter - slash', 'Key' => 'wrong-second-parameter-slash[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Prometheus pattern', 'parameter_1' => 'cpu_usage_system', 'parameter_2' => 'label', 'parameter_3' => '\0' ] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/3": invalid Prometheus label.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus wrong second parameter - digits', 'Key' => 'wrong-second-parameter-digits[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Prometheus pattern', 'parameter_1' => 'cpu_usage_system', 'parameter_2' => 'label', 'parameter_3' => '123' ] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/3": invalid Prometheus label.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus wrong first parameter - pipe', 'Key' => 'wrong-second-parameter-pipe[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => 'metric==1e|5'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus wrong first parameter - slash', 'Key' => 'wrong-second-parameter-slash[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{label="value\"}'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus wrong first parameter =!', 'Key' => 'wrong-second-parameter-equals-exclamation[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{label_name=!"name"}'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], [ [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Item Prometeus wrong first parameter ~!', 'Key' => 'wrong-second-parameter-tilda-exclamation[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{label_name~!"name"}'] ], 'error' => 'Invalid parameter "/1/preprocessing/1/params/1": invalid Prometheus pattern.' ] ], // Successful Prometheus pattern creation. [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus empty second parameter', 'Key' => 'prometeus-empty-second-parameter[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => 'cpu_usage_system'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus both parameters present', 'Key' => 'prometeus-both-parameters-present[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Prometheus pattern', 'parameter_1' => 'cpu_usage_system', 'parameter_2' => 'label', 'parameter_3' => 'label_name' ] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus first parameter +inf', 'Key' => 'prometeus-plus-inf[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => 'cpu_usage_system==+inf'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus first parameter inf', 'Key' => 'prometeus-inf[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{__name__="metric_name"}==inf'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus first parameter -inf', 'Key' => 'prometeus-negative-inf[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{__name__=~"<regex>"}==-inf'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus first parameter nan', 'Key' => 'prometeus-nan[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{__name__="metric_name"}==nan'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus first parameter exp', 'Key' => 'prometeus-exp[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => 'cpu_usage_system==3.5180e+11'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus first parameter ==1', 'Key' => 'prometeus-neutral-digit[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{__name__="metric_name"}==1'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus first parameters ==+1', 'Key' => 'prometeus-positive-digit[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{__name__="metric_name"}==+1'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus first parameters ==-1', 'Key' => 'prometeus-negative-digit[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{__name__="metric_name"}==-1'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus label operator =', 'Key' => 'prometeus-label-operator-equal-strong[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{label_name="name"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus label operator =~', 'Key' => 'prometeus-label-operator-contains[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{label_name=~"name"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus label operator !=', 'Key' => 'prometeus-label-operator-exclamation-equals[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{label_name!="name"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus label operator !~', 'Key' => 'prometeus-label-operator-exclamation-tilda[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{label_name!~"name"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus slashes in pattern', 'Key' => 'prometeus-slashes-pattern[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{label="value\\\\"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus user macros in parameters 1', 'Key' => 'prometeus-macros-1[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Prometheus pattern', 'parameter_1' => '{$METRIC_NAME}==1', 'parameter_2' => 'label', 'parameter_3' => '{$LABEL_NAME}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus user macros in parameters 2', 'Key' => 'prometeus-macros-2[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{__name__="{$METRIC_NAME}"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus user macros in parameters 3', 'Key' => 'prometeus-macros-3[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{{$LABEL_NAME}="<label value>"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus user macros in parameters 4', 'Key' => 'prometeus-macros-4[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{label_name="{$LABEL_VALUE}"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus unsupported label operator !=', 'Key' => 'prometeus-unsupported-label-operator-1[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{label_name!="regex_pattern"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus unsupported label operator !~', 'Key' => 'prometeus-unsupported-label-operator-2[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus pattern', 'parameter_1' => '{label_name!~"<regex>"}'] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus function sum 1', 'Key' => 'prometeus-function-sum[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Prometheus pattern', 'parameter_1' => '{$METRIC_NAME}==1', 'parameter_2' => 'sum' ] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus function min 2', 'Key' => 'prometeus-function-min[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Prometheus pattern', 'parameter_1' => '{label_name!~"<regex>"}', 'parameter_2' => 'min' ] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus function max', 'Key' => 'prometeus-function-max[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Prometheus pattern', 'parameter_1' => '{{$LABEL_NAME}="<label value>"}', 'parameter_2' => 'max' ] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus function avg', 'Key' => 'prometeus-function-avg[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Prometheus pattern', 'parameter_1' => '{label="value\\\\"}', 'parameter_2' => 'avg' ] ] ] ], [ [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Item Prometeus function count', 'Key' => 'prometeus-function-count[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Prometheus pattern', 'parameter_1' => '{label_name!~"name"}', 'parameter_2' => 'count' ] ] ] ] ]); } /** * Add item and preprocessing steps. * * @param array $data data provider * @param boolean $lld true if item is lld, false if item or item prototype * * @return CFormElement|CGridFormElement * */ protected function addItemWithPreprocessing($data, $lld = false) { $this->page->login()->open($this->link); $this->query('button:'.$this->button)->waitUntilPresent()->one()->click(); $form = $lld ? $this->query('name:itemForm')->waitUntilPresent()->asForm()->one() : COverlayDialogElement::find()->one()->waitUntilready()->asForm(); $form->fill($data['fields']); $form->selectTab('Preprocessing'); $this->addPreprocessingSteps($data['preprocessing']); return $form; } /** * Check creating items, item prototypes or LLD rules with preprocessing steps. */ protected function checkCreate($data, $lld = false) { if ($data['expected'] === TEST_BAD) { $sql_items = 'SELECT * FROM items ORDER BY itemid'; $old_hash = CDBHelper::getHash($sql_items); } $form = $this->addItemWithPreprocessing($data, $lld); // Take a screenshot to test draggable object position of preprocessing steps. if (array_key_exists('screenshot', $data)) { $this->page->removeFocus(); // TODO: Added updateViewport due to not centered screenshot for an item's preprocessing // which makes unclear if result is correct. $this->page->updateViewport(); $this->assertScreenshot($this->query('id:preprocessing')->one(), 'Preprocessing'.$this->link); } $form->submit(); $this->page->waitUntilReady(); if ($data['expected'] === TEST_GOOD) { $this->assertMessage(TEST_GOOD, $this->success_message); // Check result in frontend form. $id = CDBHelper::getValue('SELECT itemid FROM items WHERE key_='.zbx_dbstr($data['fields']['Key'])); if ($lld == true) { $this->page->open($this->ready_link.$id); } else { $this->page->open($this->link)->waitUntilReady(); $this->query('link:'.$data['fields']['Name'])->one()->click(); } $form->selectTab('Preprocessing')->waitUntilReady(); $this->assertPreprocessingSteps($data['preprocessing']); } else { $this->assertMessage(TEST_BAD, $this->fail_message, $data['error']); // Check that DB hash is not changed. $this->assertEquals($old_hash, CDBHelper::getHash($sql_items)); } if (!$lld) { COverlayDialogElement::find()->one()->close(); } } /* * Preprocessing steps with spaces in fields for item, item prototype and LLD. */ public static function getCommonPreprocessingTrailingSpacesData() { return [ [ [ 'fields' => [ 'Name' => 'Prometheus to JSON trailing spaces', 'Key' => 'json-prometeus-space-in-parameter[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Prometheus to JSON', 'parameter_1' => ' metric '] ] ] ] ]; } /* * Additional preprocessing data with spaces in fields for item and item prototype. */ public function getItemPreprocessingTrailingSpacesData() { return array_merge($this->getCommonPreprocessingTrailingSpacesData(), [ [ [ 'fields' => [ 'Name' => 'Prometheus pattern trailing spaces', 'Key' => 'prometeus-space-in-parameters[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Prometheus pattern', 'parameter_1' => ' metric ', 'parameter_2' => 'label', 'parameter_3' => ' output ' ] ] ] ], [ [ 'fields' => [ 'Name' => 'Custom multiplier trailing spaces', 'Key' => 'Custom-multiplier-spaces-in-parameter[{#KEY}]' ], 'preprocessing' => [ ['type' => 'Custom multiplier', 'parameter_1' => ' 2 '] ] ] ], [ [ 'fields' => [ 'Name' => 'In range trailing spaces', 'Key' => 'in-range-spaces-in-parameter[{#KEY}]' ], 'preprocessing' => [ ['type' => 'In range', 'parameter_1' => ' 5 ', 'parameter_2' => ' 10 '] ] ] ] ]); } /** * Check spaces in preprocessing steps. */ protected function checkTrailingSpaces($data, $lld = false) { $form = $this->addItemWithPreprocessing($data, $lld); $form->submit(); $this->page->waitUntilReady(); $this->assertMessage(TEST_GOOD, $this->success_message); // Remove spaces. foreach ($data['preprocessing'] as $i => &$options) { $parameters = CTestArrayHelper::get($options, 'type') === 'Prometheus pattern' ? ['parameter_1', 'parameter_3'] : ['parameter_1', 'parameter_2']; foreach ($parameters as $parameter) { if (array_key_exists($parameter, $options)) { $options[$parameter] = trim($options[$parameter]); } } } unset($options); // Check result in frontend form. $id = CDBHelper::getValue('SELECT itemid FROM items WHERE key_='.zbx_dbstr($data['fields']['Key'])); if ($lld == true) { $this->page->open($this->ready_link.$id); } else { $this->page->open($this->link)->waitUntilReady(); $this->query('link:'.$data['fields']['Name'])->one()->click(); } $form->selectTab('Preprocessing'); $this->assertPreprocessingSteps($data['preprocessing']); if (!$lld) { COverlayDialogElement::find()->one()->close(); } } /* * Preprocessing steps with Custom on fail checks for item, item prototype and LLD. */ public static function getCommonCustomOnFailData() { $options = [ ZBX_PREPROC_FAIL_DISCARD_VALUE => 'Discard value', ZBX_PREPROC_FAIL_SET_VALUE => 'Set value to', ZBX_PREPROC_FAIL_SET_ERROR => 'Set error to' ]; $data = []; foreach ($options as $value => $label) { $case = [ 'fields' => [ 'Name' => 'Preprocessing '.$label, 'Key' => 'preprocessing-steps-discard-on-fail'.$value.'[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Regular expression', 'parameter_1' => 'expression', 'parameter_2' => '\1', 'on_fail' => true ], [ 'type' => 'XML XPath', 'parameter_1' => 'path', 'on_fail' => true ], [ 'type' => 'JSONPath', 'parameter_1' => '$.data.test', 'on_fail' => true ], [ 'type' => 'CSV to JSON', 'on_fail' => true ], [ 'type' => 'JavaScript', 'parameter_1' => 'Test Java Script' ], [ 'type' => 'Does not match regular expression', 'parameter_1' => 'Pattern', 'on_fail' => true ], [ 'type' => 'Check for error in JSON', 'parameter_1' => '$.new.path', 'on_fail' => true ], [ 'type' => 'Check for error in XML', 'parameter_1' => 'XML', 'on_fail' => true ], [ 'type' => 'Discard unchanged with heartbeat', 'parameter_1' => '30' ], [ 'type' => 'Prometheus to JSON', 'parameter_1' => 'metric', 'on_fail' => true ], [ 'type' => 'XML to JSON', 'on_fail' => true ] ], 'label' => $label, 'value' => $value ]; $data[] = [self::appendErrorHandler($case)]; } return $data; } /* * Preprocessing steps with Custom on fail checks for item and item prototype. */ public function getItemCustomOnFailData() { $data = []; foreach($this->getCommonCustomOnFailData() as $packed) { $case = $packed[0]; $case['preprocessing'] = array_merge([ [ 'type' => 'Check for not supported value', 'parameter_1' => 'any error', 'on_fail' => true ], [ 'type' => 'Trim', 'parameter_1' => '111' ], [ 'type' => 'Right trim', 'parameter_1' => '333' ], [ 'type' => 'Left trim', 'parameter_1' => '555' ], [ 'type' => 'Custom multiplier', 'parameter_1' => '2', 'on_fail' => true ], [ 'type' => 'Change per second', 'on_fail' => true ], [ 'type' => 'Boolean to decimal', 'on_fail' => true ], [ 'type' => 'Matches regular expression', 'parameter_1' => 'regular expression', 'on_fail' => true ], [ 'type' => 'Check for error using regular expression', 'parameter_1' => 'expression', 'parameter_2' => 'output', 'on_fail' => true ] ], $case['preprocessing']); $data[] = [self::appendErrorHandler($case)]; } return $data; } /** * Function for adding handler parameter to case. */ public static function appendErrorHandler($case) { foreach ($case['preprocessing'] as &$preprocessing) { if (!array_key_exists('on_fail', $preprocessing) || !$preprocessing['on_fail']) { continue; } $preprocessing['error_handler'] = $case['label']; if ($case['value'] !== ZBX_PREPROC_FAIL_DISCARD_VALUE) { $preprocessing['error_handler_params'] = 'handler parameter'. microtime(); } } unset($preprocessing); return $case; } /** * Check "Custom on fail" fields and checkbox state. */ public function checkCustomOnFail($data, $lld = null) { $form = $this->addItemWithPreprocessing($data, $lld); $steps = $this->getPreprocessingSteps(); foreach ($data['preprocessing'] as $i => $options) { $this->assertNotEquals(in_array($options['type'], [ 'Trim', 'Right trim', 'Left trim', 'JavaScript', 'Discard unchanged with heartbeat', 'Check for not supported value' ]), $steps[$i]['on_fail']->isEnabled()); } $form->submit(); $this->page->waitUntilReady(); $this->assertMessage(TEST_GOOD, $this->success_message); // Check saved preprocessing. $itemid = CDBHelper::getValue('SELECT itemid FROM items WHERE key_='.zbx_dbstr($data['fields']['Key'])); $item_name = CDBHelper::getValue('SELECT name FROM items WHERE key_='.zbx_dbstr($data['fields']['Key'])); if ($lld == true) { $this->page->open($this->ready_link.$itemid); } else { $this->page->open($this->link)->waitUntilReady(); $this->query('link:'.$item_name)->one()->click()->waitUntilReady(); } $form->selectTab('Preprocessing'); $steps = $this->assertPreprocessingSteps($data['preprocessing']); $rows = []; foreach (CDBHelper::getAll('SELECT step, error_handler FROM item_preproc WHERE itemid='.$itemid) as $row) { $rows[$row['step']] = $row['error_handler']; } foreach ($data['preprocessing'] as $i => $options) { // Check "Custom on fail" value in DB. $expected = CTestArrayHelper::get($options, 'on_fail', false) === false ? (($options['type'] === 'Check for not supported value') ? 1 : ZBX_PREPROC_FAIL_DEFAULT) : $data['value']; $this->assertEquals($expected, $rows[$i+1]); if (in_array($options['type'], [ 'Trim', 'Right trim', 'Left trim', 'JavaScript', 'Discard unchanged with heartbeat' ])) { $this->assertFalse($steps[$i]['on_fail']->isEnabled()); $this->assertFalse($steps[$i]['on_fail']->isSelected()); $this->assertTrue($steps[$i]['error_handler'] === null || !$steps[$i]['error_handler']->isVisible()); $this->assertTrue($steps[$i]['error_handler_params'] === null || !$steps[$i]['error_handler_params']->isVisible() ); } elseif (in_array($options['type'], ['Check for not supported value'])) { $this->assertFalse($steps[$i]['on_fail']->isEnabled()); $this->assertTrue($steps[$i]['on_fail']->isSelected()); $this->assertTrue($steps[$i]['error_handler']->isVisible()); } else { $this->assertTrue($steps[$i]['on_fail']->isSelected()); $this->assertTrue($steps[$i]['on_fail']->isEnabled()); } } if (!$lld) { COverlayDialogElement::find()->one()->close(); } } public static function getCustomOnFailValidationData() { $cases = [ // Custom on fail - Set value to. [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Set value empty', 'Key' => 'set-value-empty[{#KEY}]' ], 'custom_on_fail' => [ 'error_handler' => 'Set value to', 'error_handler_params' => '' ] ], [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Set value number', 'Key' => 'set-value-number[{#KEY}]' ], 'custom_on_fail' => [ 'error_handler' => 'Set value to', 'error_handler_params' => '500' ] ], [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Set value string', 'Key' => 'set-value-string[{#KEY}]' ], 'custom_on_fail' => [ 'error_handler' => 'Set error to', 'error_handler_params' => 'String' ] ], [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Set value special-symbols', 'Key' => 'set-value-special-symbols[{#KEY}]' ], 'custom_on_fail' => [ 'error_handler' => 'Set value to', 'error_handler_params' => '!@#$%^&*()_+<>,.\/' ] ], // Custom on fail - Set error to. [ 'expected' => TEST_BAD, 'fields' => [ 'Name' => 'Set error empty', 'Key' => 'set-error-empty[{#KEY}]' ], 'custom_on_fail' => [ 'error_handler' => 'Set error to', 'error_handler_params' => '' ], 'error' => 'Invalid parameter "/1/preprocessing/1/error_handler_params": cannot be empty.' ], [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Set error string', 'Key' => 'set-error-string[{#KEY}]' ], 'custom_on_fail' => [ 'error_handler' => 'Set error to', 'error_handler_params' => 'Test error' ] ], [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Set error number', 'Key' => 'set-error-number[{#KEY}]' ], 'custom_on_fail' => [ 'error_handler' => 'Set error to', 'error_handler_params' => '999' ] ], [ 'expected' => TEST_GOOD, 'fields' => [ 'Name' => 'Set error special symbols', 'Key' => 'set-error-special-symbols[{#KEY}]' ], 'custom_on_fail' => [ 'error_handler' => 'Set error to', 'error_handler_params' => '!@#$%^&*()_+<>,.\/' ] ] ]; $data = []; $preprocessing = [ [ 'type' => 'Regular expression', 'parameter_1' => 'expression', 'parameter_2' => '\1', 'on_fail' => true ], [ 'type' => 'JSONPath', 'parameter_1' => '$.data.test', 'on_fail' => true ], [ 'type' => 'Does not match regular expression', 'parameter_1' => 'Pattern', 'on_fail' => true ] ]; foreach ($cases as $case) { $case['preprocessing'] = []; foreach ($preprocessing as $step) { $case['preprocessing'][] = array_merge($step, $case['custom_on_fail']); } $data[] = [$case]; } return $data; } /* * Inheritance of preprocessing steps for Item, Item prototype and LLD. */ public static function getCommonInheritancePreprocessing() { return [ [ [ 'fields' => [ 'Name' => 'Templated Preprocessing steps', 'Key' => 'templated-preprocessing-steps[{#KEY}]' ], 'preprocessing' => [ [ 'type' => 'Regular expression', 'parameter_1' => 'expression', 'parameter_2' => '\1', 'on_fail' => true, 'error_handler' => 'Discard value' ], [ 'type' => 'XML XPath', 'parameter_1' => 'path', 'on_fail' => true, 'error_handler' => 'Set value to', 'error_handler_params' => 'Custom_text' ], [ 'type' => 'XML to JSON', 'on_fail' => true, 'error_handler' => 'Set error to', 'error_handler_params' => 'Custom_text' ], [ 'type' => 'JSONPath', 'parameter_1' => '$.data.test', 'on_fail' => true, 'error_handler' => 'Set value to', 'error_handler_params' => 'Custom_text' ], [ 'type' => 'CSV to JSON', 'parameter_1' => '.', 'parameter_2' => '/', 'parameter_3' => false, 'on_fail' => true, 'error_handler' => 'Discard value' ], [ 'type' => 'Does not match regular expression', 'parameter_1' => 'Pattern', 'on_fail' => true, 'error_handler' => 'Set error to', 'error_handler_params' => 'Custom_text' ], [ 'type' => 'Check for error in JSON', 'parameter_1' => '$.new.path', 'on_fail' => false ], [ 'type' => 'Check for error in XML', 'parameter_1' => 'path', 'on_fail' => false ], [ 'type' => 'Discard unchanged with heartbeat', 'parameter_1' => '30' ], [ 'type' => 'JavaScript', 'parameter_1' => " Test line 1\n Test line 2\nTest line 3 " ] ] ] ] ]; } /* * Inheritance of preprocessing steps for item and item prototype. */ public function getItemInheritancePreprocessing() { $data = $this->getCommonInheritancePreprocessing(); $data[0][0]['preprocessing'] = array_merge([ [ 'type' => 'Check for not supported value' ], [ 'type' => 'Right trim', 'parameter_1' => '5' ], [ 'type' => 'Custom multiplier', 'parameter_1' => '10', 'on_fail' => false ], [ 'type' => 'Simple change', 'on_fail' => false ], [ 'type' => 'Octal to decimal', 'on_fail' => true, 'error_handler' => 'Set error to', 'error_handler_params' => 'Custom_text' ], [ 'type' => 'Check for error using regular expression', 'parameter_1' => 'expression', 'parameter_2' => '\0', 'on_fail' => true, 'error_handler' => 'Set error to', 'error_handler_params' => 'Custom_text' ], [ 'type' => 'Prometheus pattern', 'parameter_1' => 'cpu_usage_system', 'parameter_2' => 'label', 'parameter_3' => 'label_name', 'on_fail' => true, 'error_handler' => 'Set error to', 'error_handler_params' => 'Custom_text' ] ], $data[0][0]['preprocessing']); return $data; } /** * Check inheritance of preprocessing steps in items or LLD rules. * * @param array $data data provider * @param string $host_link URL of host configuration */ protected function checkPreprocessingInheritance($data, $host_link, $lld = false) { // Create item on template. $form = $this->addItemWithPreprocessing($data, $lld); $form->submit(); $this->page->waitUntilReady(); $this->assertMessage(TEST_GOOD, $this->success_message); // Check preprocessing steps on host. $this->page->open($host_link); $this->query('link', $data['fields']['Name'])->waitUntilPresent()->one()->click(); $form->selectTab('Preprocessing'); $steps = $this->assertPreprocessingSteps($data['preprocessing']); foreach ($data['preprocessing'] as $i => $options) { $step = $steps[$i]; $this->assertNotNull($step['type']->getAttribute('readonly')); foreach (['parameter_1', 'parameter_2', 'parameter_3'] as $param) { if (array_key_exists($param, $options)) { $this->assertFalse($step[$param]->detect()->isEnabled()); } } $this->assertFalse($step['on_fail']->isEnabled()); switch ($options['type']) { case 'Regular expression': case 'CSV to JSON': case 'XML XPath': case 'JSONPath': case 'Does not match regular expression': case 'Octal to decimal': case 'Prometheus pattern': case 'Check for error using regular expression': case 'Check for not supported value': $this->assertTrue($step['on_fail']->isSelected()); $this->assertFalse($step['error_handler']->isEnabled()); break; case 'Custom multiplier': case 'Simple change': case 'Right trim': case 'JavaScript': case 'Check for error in JSON': case 'Check for error in XML': case 'Discard unchanged with heartbeat': $this->assertFalse($step['on_fail']->isSelected()); break; } } if (!$lld) { COverlayDialogElement::find()->one()->close(); } } /** * Check cloning of inherited preprocessing steps in items, prototypes or LLD rules. * * @param string $link cloned item, prototype or LLD URL * @param string $item what is being cloned: item, prototype or LLD rule * @param string $templated is it templated item or not */ protected function checkCloneItem($link, $item, $templated = false) { $cloned_values = [ 'Name' => 'Cloned_testInheritancePreprocessingSteps'.time(), 'Key' => 'cloned-preprocessing'.time().'[{#KEY}]' ]; // Open original item on host and get its preprocessing steps. $this->page->login()->open($link)->waitUntilReady(); if ($item === 'Discovery rule') { $form = $this->query('name:itemForm')->waitUntilPresent()->asForm()->one(); } else { $item_name = ($item === 'Item') ? CDBHelper::getValue('SELECT name FROM items WHERE itemid='.($templated ? self::INHERITED_ITEMID : self::CLONE_ITEMID)) : CDBHelper::getValue('SELECT name FROM items WHERE itemid='.($templated ? self::INHERITED_ITEM_PROTOTYPE : self::CLONE_ITEM_PROTOTYPEID)); $this->query('link', $item_name)->one()->waitUntilClickable()->click(); $dialog = COverlayDialogElement::find()->one()->waitUntilReady(); $form = $dialog->asForm(); } if ($templated) { // Check that right templated item is opened. $label = ($item === 'Discovery rule') ? 'Parent discovery rules' : 'Parent items'; $this->assertEquals('Inheritance test template', $form->getField($label)->getText()); } $form->selectTab('Preprocessing'); $original_steps = $this->listPreprocessingSteps(); $form->selectTab($item); // Clone item. if ($item === 'Item' || $item === 'Item prototype') { $dialog->getFooter()->query('button:Clone')->one()->click(); COverlayDialogElement::find()->one()->waitUntilReady(); } else { $form->query('button:Clone')->waitUntilPresent()->one()->click(); } $form->invalidate(); $form->fill($cloned_values); $this->checkPreprocessingSteps($form, $original_steps); $form->submit(); $message = ($item === 'Discovery rule') ? $item.' created' : $item.' added'; $this->assertMessage(TEST_GOOD, $message); // Open cloned item and check preprocessing steps in saved form. $id = CDBHelper::getValue('SELECT itemid FROM items WHERE key_='.zbx_dbstr($cloned_values['Key'])); if ($item === 'Discovery rule') { $this->page->open($this->ready_link.$id); } else { $this->page->open($link); $this->query('link', $cloned_values['Name'])->one()->click(); } $form->invalidate(); $this->assertEquals($cloned_values['Name'], $form->getField('Name')->getValue()); $this->checkPreprocessingSteps($form, $original_steps); if ($item === 'Item' || $item === 'Item prototype') { COverlayDialogElement::find()->one()->close(); } } /** * Select Preprocessing tab in cloned item, prototype or LLD form and assert * that steps are the same as in original item. * * @param CFormElement $form item, prototype or LLD configuration form * @param array $original_steps preprocessing steps of original item */ protected function checkPreprocessingSteps($form, $original_steps) { $form->selectTab('Preprocessing'); $this->assertEquals($original_steps, $this->listPreprocessingSteps()); // Check that preprocessing steps in cloned form are editable. foreach (array_keys($this->listPreprocessingSteps()) as $i) { $step = $this->query('id:preprocessing_'.$i.'_type')->one(); $this->assertNull($step->getAttribute('readonly')); } } /** * Please note that this data provider consists only from ONE test case with an array of steps. */ public static function getItemsParametersData() { return [ [ [ [ 'type' => 'Regular expression', 'parameters' => [ ['placeholder' => 'pattern', 'maxlength' => 255], ['placeholder' => 'output', 'maxlength' => 255] ] ], [ 'type' => 'Replace', 'parameters' => [ ['placeholder' => 'search string', 'maxlength' => 255], ['placeholder' => 'replacement', 'maxlength' => 255] ], 'on_fail_enabled' => false ], [ 'type' => 'Trim', 'parameters' => [ ['placeholder' => 'list of characters', 'maxlength' => 255] ], 'on_fail_enabled' => false ], [ 'type' => 'Right trim', 'parameters' => [ ['placeholder' => 'list of characters', 'maxlength' => 255] ], 'on_fail_enabled' => false ], [ 'type' => 'Left trim', 'parameters' => [ ['placeholder' => 'list of characters', 'maxlength' => 255] ], 'on_fail_enabled' => false ], [ 'type' => 'XML XPath', 'parameters' => [ ['placeholder' => 'XPath', 'maxlength' => 255] ] ], [ 'type' => 'JSONPath', 'parameters' => [ ['placeholder' => '$.path.to.node', 'maxlength' => 255] ] ], [ 'type' => 'CSV to JSON', 'parameters' => [ ['placeholder' => 'delimiter', 'value' => ',', 'maxlength' => 1], ['placeholder' => 'qualifier', 'value' => '"', 'maxlength' => 1], ['value' => true] ] ], [ 'type' => 'XML to JSON' ], [ 'type' => 'SNMP walk value', 'parameters' => [ ['placeholder' => 'OID', 'value' => '', 'maxlength' => 255], [ 'selector' => 'xpath:.//z-select[@name="preprocessing[0][params][1]"]', 'options' => ['Unchanged', 'UTF-8 from Hex-STRING', 'MAC from Hex-STRING', 'Integer from BITS'], 'value' => 'Unchanged' ] ] ], [ 'type' => 'SNMP walk to JSON', 'parameters' => [ [ 'selector' => 'xpath:(.//input[@name="preprocessing[0][params][]"])[1]', 'placeholder' => 'Field name', 'maxlength' => 255 ], [ 'selector' => 'xpath:(.//input[@name="preprocessing[0][params][]"])[2]', 'placeholder' => 'OID prefix', 'maxlength' => 255 ], [ 'selector' => 'xpath:.//z-select[@name="preprocessing[0][params][]"]', 'options' => ['Unchanged', 'UTF-8 from Hex-STRING', 'MAC from Hex-STRING', 'Integer from BITS'], 'value' => 'Unchanged' ] ] ], [ 'type' => 'SNMP get value', 'parameters' => [ [ 'selector' => 'xpath:.//z-select[@name="preprocessing[0][params][0]"]', 'options' => ['UTF-8 from Hex-STRING', 'MAC from Hex-STRING', 'Integer from BITS'], 'value' => 'UTF-8 from Hex-STRING' ] ] ], [ 'type' => 'Custom multiplier', 'parameters' => [ ['placeholder' => 'number', 'maxlength' => 255] ] ], [ 'type' => 'Simple change' ], [ 'type' => 'Change per second' ], [ 'type' => 'Boolean to decimal' ], [ 'type' => 'Octal to decimal' ], [ 'type' => 'Hexadecimal to decimal' ], [ 'type' => 'JavaScript', 'parameters' => [ [ 'selector' => 'xpath:.//div[@class="multilineinput-control"]/input[@type="text"]', 'placeholder' => 'script' ] ], 'on_fail_enabled' => false ], [ 'type' => 'In range', 'parameters' => [ ['placeholder' => 'min', 'maxlength' => 255], ['placeholder' => 'max', 'maxlength' => 255] ] ], [ 'type' => 'Matches regular expression', 'parameters' => [ ['placeholder' => 'pattern', 'maxlength' => 255] ] ], [ 'type' => 'Does not match regular expression', 'parameters' => [ ['placeholder' => 'pattern', 'maxlength' => 255] ] ], [ 'type' => 'Check for error in JSON', 'parameters' => [ ['placeholder' => '$.path.to.node', 'maxlength' => 255] ] ], [ 'type' => 'Check for error in XML', 'parameters' => [ ['placeholder' => 'XPath', 'maxlength' => 255] ] ], [ 'type' => 'Check for error using regular expression', 'parameters' => [ ['placeholder' => 'pattern', 'maxlength' => 255], ['placeholder' => 'output', 'maxlength' => 255] ] ], [ 'type' => 'Check for not supported value', 'parameters' => [ [ 'selector' => 'xpath:.//z-select[@name="preprocessing[0][params][0]"]', 'options' => ['any error', 'error matches', 'error does not match'], 'value' => 'any error' ] ], 'on_fail_value' => true, 'on_fail_enabled' => false ], [ 'type' => 'Discard unchanged', 'on_fail_enabled' => false ], [ 'type' => 'Discard unchanged with heartbeat', 'parameters' => [ ['placeholder' => 'seconds', 'maxlength' => 255] ], 'on_fail_enabled' => false ], [ 'type' => 'Prometheus pattern', 'parameters' => [ ['placeholder' => '<metric name>{<label name>="<label value>", ...} == <value>', 'maxlength' => 255], ['selector' => 'xpath:.//z-select[contains(@class, "preproc-param")]', 'value' => 'value'], ['placeholder' => '<label name>', 'maxlength' => 255] ] ], [ 'type' => 'Prometheus to JSON', 'parameters' => [ ['placeholder' => '<metric name>{<label name>="<label value>", ...} == <value>', 'maxlength' => 255] ] ] ] ] ]; } /** * Check layout of preprocessing tab and fields. * * @param array $data given preprocessing steps * @param array $steps list of steps options * @param boolean $lld true if LLD form is checked, false if item or item prototype */ protected function checkLayout($data, $steps, $lld = false) { $this->page->login()->open($this->link); $this->query('button:'.$this->button)->waitUntilPresent()->one()->click(); $form = $this->query('name:itemForm')->waitUntilPresent()->asForm()->one(); $form->fill( [ 'Name' => 'Item for preprocessing layout check', 'Key' => 'preproc-layout-check' ] ); $form->selectTab('Preprocessing'); // Check initial layout. $preprocessing_container = $form->getFieldContainer('Preprocessing steps'); $list_step = $preprocessing_container->query('xpath:.//li['.CXPathHelper::fromClass('preprocessing-list-item').']'); // No any step presents at the beginning. $this->assertFalse($list_step->exists()); // Check that 'Type of information' field is not visible before first step is added. $this->assertFalse($form->query('xpath:.//div[@id="item_preproc_list"]/label[text()="Type of information"]') ->one(false)->isVisible() ); $add_button = $this->query('id:param_add')->one(); $add_button->click(); // Check 1st step's visibility and buttons. $this->assertTrue($list_step->one()->isVisible()); $this->assertEquals(4, $preprocessing_container->query('button', ['Add', 'Test', 'Remove', 'Test all steps']) ->all()->filter(new CElementFilter(CElementFilter::CLICKABLE))->count() ); // Check that 'Type of information' field is visible after step is added, but not for LLD. $this->assertTrue($form->query('xpath:.//div[@id="item_preproc_list"]/label[text()="Type of information"]') ->one(false)->isVisible(!$lld) ); // Hint is present only for Items and Item prototypes. if (!$lld) { $form->getLabel('Preprocessing steps')->query('xpath:./button[@data-hintbox]')->one()->waitUntilClickable()->click(); $hint = $this->query('xpath://div[@class="overlay-dialogue wordbreak"]')->one()->waitUntilReady(); $this->assertEquals("Preprocessing is a transformation before saving the value to the database.". " It is possible to define a sequence of preprocessing steps, and those are executed in the order they are set.". "\n\nHowever, if \"Check for not supported value\" steps are configured, they are always placed and". " executed first (with \"any error\" being the last of them).", $hint->getText() ); $hint->query('xpath:.//button[@title="Close"]')->waitUntilClickable()->one()->click(); // Check 'Type of information' options. $this->assertEquals(['Numeric (unsigned)', 'Numeric (float)', 'Character', 'Log', 'Text'], $form->query('name:value_type_steps')->asDropdown()->one()->getOptions()->asText() ); } // Assert preprocessing table headers (table is actually list in HTML). $this->assertEquals("Name\nParameters\nCustom on fail\nActions", $this->query('xpath://li[contains(@class, "preprocessing-list-head")]')->one()->getText() ); // Check that one alone list item is not draggable. $disabled_sortable_element = $this->query('xpath://ul[@id="preprocessing" and contains(@class, "sortable-disabled")]'); $this->assertTrue($disabled_sortable_element->exists()); // Check steps' types in dropdown. $step_type_field = $preprocessing_container->query('xpath:.//z-select[contains(@id, "_type")]')->asDropdown()->one(); $this->assertEquals($steps, $step_type_field->getOptions()->asText()); foreach ($data as $step) { $step_type_field->fill($step['type']); /* * Check Custom on fail checkbox. Note that error handler and parameters are checked by * separate scenario _CustomOnFail and function checkCustomOnFail(). */ $on_fail_field = $preprocessing_container->query('xpath:.//input[@name="preprocessing[0][on_fail]"]') ->waitUntilPresent()->one(); $this->assertTrue($on_fail_field->isEnabled(CTestArrayHelper::get($step, 'on_fail_enabled', true))); $this->assertTrue($on_fail_field->asCheckbox()->isChecked(CTestArrayHelper::get($step, 'on_fail_value', false))); if (array_key_exists('parameters', $step)) { foreach ($step['parameters'] as $i => $parameter) { $parameter['selector'] = CTestArrayHelper::get($parameter, 'selector', 'xpath:.//input[@id="preprocessing_0_params_'.$i.'"]' ); $field = $preprocessing_container->query($parameter['selector'])->waitUntilPresent()->one(); foreach (['maxlength', 'placeholder'] as $attribute) { if (array_key_exists($attribute, $parameter)) { $this->assertEquals($parameter[$attribute], $field->getAttribute($attribute)); } } if (array_key_exists('options', $parameter)) { $field = $field->asDropdown(); $this->assertEquals($parameter['options'], $field->getOptions()->asText()); } $this->assertEquals(CTestArrayHelper::get($parameter, 'value', ''), $field->getValue()); } } else { $this->assertFalse($preprocessing_container->query('xpath:.//input[contains(@id, "preprocessing_0_params")]')->exists()); } } // Add one more step and check sortable class. $add_button->click(); $this->assertFalse($disabled_sortable_element->exists()); } }