<?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 __DIR__.'/../include/CAPITest.php'; /** * @backup ids * * @onBefore prepareTestData * @onAfter clearData */ class testProxyGroup extends CAPITest { /** * Non-existent ID, type, status etc. */ private const INVALID_NUMBER = 999999; /** * @var array */ private static array $data = [ 'proxy_groupids' => [], 'proxyids' => [], 'groupids' => [], 'hostids' => [], // Created proxy groups during proxygroup.create test (deleted at the end). 'created' => [] ]; /** * Prepare data for tests. Create proxy groups, proxies, host groups, hosts. */ public function prepareTestData(): void { $this->prepareTestDataProxyGroups(); $this->prepareTestDataProxies(); $this->prepareTestDataHostGroups(); $this->prepareTestDataHosts(); } /** * Create proxy groups. */ private function prepareTestDataProxyGroups(): void { $proxy_groups = [ 'defaults' => [ 'name' => 'API test proxy group - with defaults' ], 'with_1_proxy' => [ 'name' => 'API test proxy group - with 1 proxy', 'min_online' => 3 ], 'with_3_proxies' => [ 'name' => 'API test proxy group - with 3 proxies' ], 'state_offline' => [ 'name' => 'API test proxy group - state offline' ], 'state_recovering' => [ 'name' => 'API test proxy group - state recovering' ], 'state_online' => [ 'name' => 'API test proxy group - state online' ], 'state_degrading' => [ 'name' => 'API test proxy group - state degrading' ] ]; $db_proxy_groups = CDataHelper::call('proxygroup.create', array_values($proxy_groups)); $this->assertArrayHasKey('proxy_groupids', $db_proxy_groups, __FUNCTION__.'() failed: Could not create proxy groups.' ); self::$data['proxy_groupids'] = array_combine(array_keys($proxy_groups), $db_proxy_groups['proxy_groupids']); // Manually update "proxy_group_rtdata" table. $states = [ 'state_offline' => [ 'state' => ZBX_PROXYGROUP_STATE_OFFLINE ], 'state_recovering' => [ 'state' => ZBX_PROXYGROUP_STATE_RECOVERING ], 'state_online' => [ 'state' => ZBX_PROXYGROUP_STATE_ONLINE ], 'state_degrading' => [ 'state' => ZBX_PROXYGROUP_STATE_DEGRADING ] ]; $proxy_groups = []; foreach ($states as $id_placeholder => $state) { $proxy_groups[] = [ 'values' => $state, 'where' => ['proxy_groupid' => self::$data['proxy_groupids'][$id_placeholder]] ]; } DB::update('proxy_group_rtdata', $proxy_groups); } /** * Create proxies. */ private function prepareTestDataProxies(): void { $proxies = [ 'without_proxy_group' => [ 'name' => 'API test proxy group - without proxy group', 'operating_mode' => PROXY_OPERATING_MODE_ACTIVE ], 'with_proxy_group' => [ 'name' => 'API test proxy group - with proxy group', 'proxy_groupid' => self::$data['proxy_groupids']['with_1_proxy'], 'local_address' => 'localhost', 'operating_mode' => PROXY_OPERATING_MODE_ACTIVE ], 'with_proxy_group_1' => [ 'name' => 'API test proxy group - with proxy group 1', 'proxy_groupid' => self::$data['proxy_groupids']['with_3_proxies'], 'local_address' => 'proxy1.lan', 'operating_mode' => PROXY_OPERATING_MODE_ACTIVE ], 'with_proxy_group_2' => [ 'name' => 'API test proxy group - with proxy group 2', 'proxy_groupid' => self::$data['proxy_groupids']['with_3_proxies'], 'local_address' => 'proxy2.lan', 'operating_mode' => PROXY_OPERATING_MODE_ACTIVE ], 'with_proxy_group_3' => [ 'name' => 'API test proxy group - with proxy group 3', 'proxy_groupid' => self::$data['proxy_groupids']['with_3_proxies'], 'local_address' => 'proxy3.lan', 'operating_mode' => PROXY_OPERATING_MODE_ACTIVE ] ]; $db_proxies = CDataHelper::call('proxy.create', array_values($proxies)); $this->assertArrayHasKey('proxyids', $db_proxies, __FUNCTION__.'() failed: Could not create proxies.'); self::$data['proxyids'] = array_combine(array_keys($proxies), $db_proxies['proxyids']); } /** * Create host groups. */ private function prepareTestDataHostGroups(): void { $db_hostgroups = CDataHelper::call('hostgroup.create', [ 'name' => 'API test proxy group - host group' ]); $this->assertArrayHasKey('groupids', $db_hostgroups, __FUNCTION__.'() failed: Could not create host groups.'); self::$data['groupids'] = $db_hostgroups['groupids']; } /** * Create hosts. */ private function prepareTestDataHosts(): void { $hosts = [ 'monitored_by_server' => [ 'host' => 'host_monitored_by_server', 'name' => 'API test proxy group - monitored by server', 'groups' => [ [ 'groupid' => self::$data['groupids'][0] ] ] ], 'monitored_by_proxy_without_group' => [ 'host' => 'host_monitored_by_proxy_without_group', 'name' => 'API test proxy group - monitored by proxy without group', 'monitored_by' => ZBX_MONITORED_BY_PROXY, 'proxyid' => self::$data['proxyids']['without_proxy_group'], 'groups' => [ [ 'groupid' => self::$data['groupids'][0] ] ] ], 'monitored_by_proxy_from_group' => [ 'host' => 'host_monitored_by_proxy_from_group', 'name' => 'API test proxy group - monitored by proxy from group', 'monitored_by' => ZBX_MONITORED_BY_PROXY, 'proxyid' => self::$data['proxyids']['with_proxy_group'], 'groups' => [ [ 'groupid' => self::$data['groupids'][0] ] ] ], 'monitored_by_empty_proxy_group' => [ 'host' => 'host_monitored_by_empty_proxy_group', 'name' => 'API test proxy group - monitored by empty proxy group', 'monitored_by' => ZBX_MONITORED_BY_PROXY_GROUP, 'proxy_groupid' => self::$data['proxy_groupids']['defaults'], 'groups' => [ [ 'groupid' => self::$data['groupids'][0] ] ] ], 'monitored_by_proxy_group' => [ 'host' => 'host_monitored_by_proxy_group', 'name' => 'API test proxy group - monitored by proxy group', 'monitored_by' => ZBX_MONITORED_BY_PROXY_GROUP, 'proxy_groupid' => self::$data['proxy_groupids']['with_3_proxies'], 'groups' => [ [ 'groupid' => self::$data['groupids'][0] ] ] ] ]; $db_hosts = CDataHelper::call('host.create', array_values($hosts)); $this->assertArrayHasKey('hostids', $db_hosts, __FUNCTION__.'() failed: Could not create hosts.'); self::$data['hostids'] = array_combine(array_keys($hosts), $db_hosts['hostids']); // Manually insert data into "host_proxy" table. $host_proxy = [ [ 'hostid' => self::$data['hostids']['monitored_by_proxy_group'], 'proxyid' => self::$data['proxyids']['with_proxy_group_2'] ] ]; DB::insert('host_proxy', $host_proxy); } /** * Data provider for proxygroup.get. Array contains invalid proxy group parameters. * * @return array */ public static function getProxyGroupGetDataInvalid(): array { return [ // Check unexpected params. 'Test proxygroup.get: unexpected parameter' => [ 'request' => [ 'abc' => 'abc' ], 'expected_result' => [], 'expected_error' => 'Invalid parameter "/": unexpected parameter "abc".' ], // Check "proxy_groupids" field. 'Test proxygroup.get: invalid "proxy_groupids" (empty string)' => [ 'request' => [ 'proxy_groupids' => '' ], 'expected_result' => [], 'expected_error' => 'Invalid parameter "/proxy_groupids": an array is expected.' ], 'Test proxygroup.get: invalid "proxy_groupids" (array with empty string)' => [ 'request' => [ 'proxy_groupids' => [''] ], 'expected_result' => [], 'expected_error' => 'Invalid parameter "/proxy_groupids/1": a number is expected.' ], // Check "proxyids" field. 'Test proxygroup.get: invalid "proxyids" (empty string)' => [ 'request' => [ 'proxyids' => '' ], 'expected_result' => [], 'expected_error' => 'Invalid parameter "/proxyids": an array is expected.' ], 'Test proxygroup.get: invalid "proxyids" (array with empty string)' => [ 'request' => [ 'proxyids' => [''] ], 'expected_result' => [], 'expected_error' => 'Invalid parameter "/proxyids/1": a number is expected.' ], // Check filter. 'Test proxygroup.get: invalid "filter" (empty string)' => [ 'request' => [ 'filter' => '' ], 'expected_result' => [], 'expected_error' => 'Invalid parameter "/filter": an array is expected.' ], // Check unexpected parameters that exist in object, but not in filter. 'Test proxygroup.get: unexpected parameter in "filter"' => [ 'request' => [ 'filter' => [ 'description' => 'description' ] ], 'expected_result' => [], 'expected_error' => 'Invalid parameter "/filter": unexpected parameter "description".' ], // Check "search" option. 'Test proxygroup.get: invalid "search" (string)' => [ 'request' => [ 'search' => 'abc' ], 'expected_result' => [], 'expected_error' => 'Invalid parameter "/search": an array is expected.' ], // Check unexpected parameters that exist in object, but not in search. 'Test proxygroup.get: unexpected parameter in "search"' => [ 'request' => [ 'search' => [ 'proxy_groupid' => 'proxy_groupid' ] ], 'expected_result' => [], 'expected_error' => 'Invalid parameter "/search": unexpected parameter "proxy_groupid".' ], // Check "output" option. 'Test proxygroup.get: invalid parameter "output" (string)' => [ 'request' => [ 'output' => 'abc' ], 'expected_result' => [], 'expected_error' => 'Invalid parameter "/output": value must be "extend".' ], 'Test proxygroup.get: invalid parameter "output" (array with string)' => [ 'request' => [ 'output' => ['abc'] ], 'expected_result' => [], 'expected_error' => 'Invalid parameter "/output/1": value must be one of "proxy_groupid", "name", "failover_delay", "min_online", "description", "state".' ], // Check "selectProxies" option. 'Test proxygroup.get: invalid parameter "selectProxies" (string)' => [ 'request' => [ 'selectProxies' => 'abc' ], 'expected_result' => [], 'expected_error' => 'Invalid parameter "/selectProxies": value must be one of "extend", "count".' ], 'Test proxygroup.get: invalid parameter "selectProxies" (array with string)' => [ 'request' => [ 'selectProxies' => ['abc'] ], 'expected_result' => [], 'expected_error' => 'Invalid parameter "/selectProxies/1": value must be one of "proxyid", "name", "local_address", "local_port", "operating_mode", "allowed_addresses", "address", "port", "description", "tls_connect", "tls_accept", "tls_issuer", "tls_subject", "custom_timeouts", "timeout_zabbix_agent", "timeout_simple_check", "timeout_snmp_agent", "timeout_external_check", "timeout_db_monitor", "timeout_http_agent", "timeout_ssh_agent", "timeout_telnet_agent", "timeout_script", "timeout_browser", "lastaccess", "version", "compatibility", "state".' ] ]; } /** * Data provider for proxygroup.get. Array contains valid proxy group parameters. * * @return array */ public static function getProxyGroupGetDataValid(): array { return [ // Check validity of "proxy_groupids" without getting any results. 'Test proxygroup.get: empty "proxy_groupids"' => [ 'request' => [ 'proxy_groupids' => [] ], 'expected_result' => [], 'expected_error' => null ], // Check no fields are returned on empty selection. 'Test proxygroup.get: empty "output"' => [ 'request' => [ 'output' => [], 'proxy_groupids' => ['defaults', 'with_1_proxy'] ], 'expected_result' => [ [], [] ], 'expected_error' => null ], // Filter by "proxy_groupid". 'Test proxygroup.get: filter by "proxy_groupid"' => [ 'request' => [ 'output' => ['name'], 'filter' => [ 'proxy_groupid' => 'defaults' ] ], 'expected_result' => [ [ 'name' => 'API test proxy group - with defaults' ] ], 'expected_error' => null ], // Filter by "state". 'Test proxygroup.get: filter by "state"' => [ 'request' => [ 'output' => ['name', 'state'], 'filter' => [ 'state' => ZBX_PROXYGROUP_STATE_RECOVERING ] ], 'expected_result' => [ [ 'name' => 'API test proxy group - state recovering', 'state' => (string) ZBX_PROXYGROUP_STATE_RECOVERING ] ], 'expected_error' => null ], // Search by "name". 'Test proxygroup.get: search by "name"' => [ 'request' => [ 'output' => ['name'], 'search' => [ 'name' => 'API test proxy group - state' ] ], 'expected_result' => [ ['name' => 'API test proxy group - state offline'], ['name' => 'API test proxy group - state recovering'], ['name' => 'API test proxy group - state online'], ['name' => 'API test proxy group - state degrading'] ], 'expected_error' => null ], // Check "selectProxies". 'Test proxygroup.get: selectProxies=[] excludes proxyid' => [ 'request' => [ 'output' => [], 'proxy_groupids' => 'with_1_proxy', 'selectProxies' => [] ], 'expected_result' => [[ 'proxies' => [ [] ] ]], 'expected_error' => null ], 'Test proxygroup.get: selectProxies="extend" excludes proxy_groupid' => [ 'request' => [ 'output' => [], 'proxy_groupids' => 'with_1_proxy', 'selectProxies' => API_OUTPUT_EXTEND ], 'expected_result' => [[ 'proxies' => [[ 'proxyid' => 'with_proxy_group', 'name' => 'API test proxy group - with proxy group', 'local_address' => 'localhost', 'local_port' => '10051', 'operating_mode' => (string) PROXY_OPERATING_MODE_ACTIVE, 'allowed_addresses' => '', 'address' => '127.0.0.1', 'port' => '10051', 'description' => '', 'tls_connect' => '1', 'tls_accept' => '1', 'tls_issuer' => '', 'tls_subject' => '', 'custom_timeouts' => '0', 'timeout_zabbix_agent' => '', 'timeout_simple_check' => '', 'timeout_snmp_agent' => '', 'timeout_external_check' => '', 'timeout_db_monitor' => '', 'timeout_http_agent' => '', 'timeout_ssh_agent' => '', 'timeout_telnet_agent' => '', 'timeout_script' => '', 'timeout_browser' => '', 'lastaccess' => '0', 'version' => '0', 'compatibility' => '0', 'state' => '0' ]] ]], 'expected_error' => null ], 'Test proxygroup.get: selectProxies="count"' => [ 'request' => [ 'output' => [], 'proxy_groupids' => ['with_1_proxy', 'with_3_proxies'], 'selectProxies' => API_OUTPUT_COUNT ], 'expected_result' => [ ['proxies' => '1'], ['proxies' => '3'] ], 'expected_error' => null ] ]; } /** * Test proxygroup.get with all options. * * @dataProvider getProxyGroupGetDataInvalid * @dataProvider getProxyGroupGetDataValid */ public function testProxyGroup_Get(array $request, array $expected_result, ?string $expected_error): void { // Replace ID placeholders with real IDs. $request = self::resolveIds($request); foreach ($expected_result as &$proxy_group) { $proxy_group = self::resolveIds($proxy_group); } unset($proxy_group); $result = $this->call('proxygroup.get', $request, $expected_error); if ($expected_error === null) { $this->assertSame($expected_result, $result['result']); } } /** * Data provider for proxygroup.create. * * @return array */ public static function getProxyGroupCreateData(): array { return [ 'Test proxygroup.create: empty request' => [ 'proxygroup' => [], 'expected_error' => 'Invalid parameter "/": cannot be empty.' ], 'Test proxygroup.create: unexpected parameter' => [ 'proxygroup' => [ 'abc' => 'abc' ], 'expected_error' => 'Invalid parameter "/1": unexpected parameter "abc".' ], // Check "name". 'Test proxygroup.create: missing "name"' => [ 'proxygroup' => [ 'description' => '' ], 'expected_error' => 'Invalid parameter "/1": the parameter "name" is missing.' ], 'Test proxygroup.create: invalid "name" (null)' => [ 'proxygroup' => [ 'name' => null ], 'expected_error' => 'Invalid parameter "/1/name": a character string is expected.' ], 'Test proxygroup.create: invalid "name" (boolean)' => [ 'proxygroup' => [ 'name' => false ], 'expected_error' => 'Invalid parameter "/1/name": a character string is expected.' ], 'Test proxygroup.create: invalid "name" (empty string)' => [ 'proxygroup' => [ 'name' => '' ], 'expected_error' => 'Invalid parameter "/1/name": cannot be empty.' ], 'Test proxygroup.create: invalid "name" (too long)' => [ 'proxygroup' => [ 'name' => str_repeat('a', DB::getFieldLength('proxy_group', 'name') + 1) ], 'expected_error' => 'Invalid parameter "/1/name": value is too long.' ], 'Test proxygroup.create: multiple proxy groups with the same "name"' => [ 'proxygroup' => [ [ 'name' => 'API create proxy group' ], [ 'name' => 'API create proxy group' ] ], 'expected_error' => 'Invalid parameter "/2": value (name)=(API create proxy group) already exists.' ], 'Test proxygroup.create: invalid "name" (duplicate)' => [ 'proxygroup' => [ 'name' => 'API test proxy group - with defaults' ], 'expected_error' => 'Proxy group "API test proxy group - with defaults" already exists.' ], // Check "failover_delay". 'Test proxygroup.create: invalid "failover_delay" (null)' => [ 'proxygroup' => [ 'name' => 'API create proxy group', 'failover_delay' => null ], 'expected_error' => 'Invalid parameter "/1/failover_delay": a character string is expected.' ], 'Test proxygroup.create: invalid "failover_delay" (boolean)' => [ 'proxygroup' => [ 'name' => 'API create proxy group', 'failover_delay' => false ], 'expected_error' => 'Invalid parameter "/1/failover_delay": a character string is expected.' ], 'Test proxygroup.create: invalid "failover_delay" (empty string)' => [ 'proxygroup' => [ 'name' => 'API create proxy group', 'failover_delay' => '' ], 'expected_error' => 'Invalid parameter "/1/failover_delay": cannot be empty.' ], // Check "min_online". 'Test proxygroup.create: invalid "min_online" (null)' => [ 'proxygroup' => [ 'name' => 'API create proxy group', 'min_online' => null ], 'expected_error' => 'Invalid parameter "/1/min_online": a number is expected.' ], 'Test proxygroup.create: invalid "min_online" (boolean)' => [ 'proxygroup' => [ 'name' => 'API create proxy group', 'min_online' => false ], 'expected_error' => 'Invalid parameter "/1/min_online": a number is expected.' ], 'Test proxygroup.create: invalid "min_online" (empty string)' => [ 'proxygroup' => [ 'name' => 'API create proxy group', 'min_online' => '' ], 'expected_error' => 'Invalid parameter "/1/min_online": cannot be empty.' ], // Check "description". 'Test proxygroup.create: invalid "description" (null)' => [ 'proxygroup' => [ 'name' => 'API create proxy group', 'description' => null ], 'expected_error' => 'Invalid parameter "/1/description": a character string is expected.' ], 'Test proxygroup.create: invalid "description" (boolean)' => [ 'proxygroup' => [ 'name' => 'API create proxy group', 'description' => false ], 'expected_error' => 'Invalid parameter "/1/description": a character string is expected.' ], 'Test proxygroup.create: invalid "description" (too long)' => [ 'proxygroup' => [ 'name' => 'API create proxy group', 'description' => str_repeat('a', DB::getFieldLength('proxy_group', 'description') + 1) ], 'expected_error' => 'Invalid parameter "/1/description": value is too long.' ] ]; } /** * Test proxygroup.create with errors like missing fields, optional invalid fields and valid fields. * * @dataProvider getProxyGroupCreateData */ public function testProxyGroup_Create(array $proxy_groups, ?string $expected_error): void { // Accept single and multiple objects just like API method. Work with multidimensional array in result. if (!array_key_exists(0, $proxy_groups)) { $proxy_groups = zbx_toArray($proxy_groups); } // Replace ID placeholders with real IDs. foreach ($proxy_groups as &$proxy_group) { $proxy_group = self::resolveIds($proxy_group); } unset($proxy_group); $sql_proxy_groups = 'SELECT NULL FROM proxy_group pg'; $old_hash_proxy_groups = CDBHelper::getHash($sql_proxy_groups); $result = $this->call('proxygroup.create', $proxy_groups, $expected_error); if ($expected_error === null) { // Something was changed in DB. $this->assertNotSame($old_hash_proxy_groups, CDBHelper::getHash($sql_proxy_groups)); $this->assertEquals(count($proxy_groups), count($result['result']['proxy_groupids'])); // Add proxy group IDs to create array, so they can be deleted after tests are complete. self::$data['created'] = array_merge(self::$data['created'], $result['result']['proxy_groupids']); } else { $this->assertSame($old_hash_proxy_groups, CDBHelper::getHash($sql_proxy_groups)); } } /** * Data provider for proxygroup.update. * * @return array */ public static function getProxyGroupUpdateData(): array { return [ 'Test proxygroup.update: update single proxy group without changes' => [ 'proxygroup' => [ 'proxy_groupid' => 'defaults' ], 'expected_error' => null ] ]; } /** * Test proxygroup.update method. * * @dataProvider getProxyGroupUpdateData */ public function testProxyGroup_Update(array $proxy_groups, ?string $expected_error): void { // Accept single and multiple objects just like API method. Work with multidimensional array in result. if (!array_key_exists(0, $proxy_groups)) { $proxy_groups = zbx_toArray($proxy_groups); } // Replace ID placeholders with real IDs. foreach ($proxy_groups as &$proxy_group) { $proxy_group = self::resolveIds($proxy_group); } unset($proxy_group); $sql_proxy_groups = 'SELECT NULL FROM proxy_group'; $old_hash_proxy_groups = CDBHelper::getHash($sql_proxy_groups); if ($expected_error === null) { $proxy_groupids = array_column($proxy_groups, 'proxy_groupid'); $db_proxy_groups = $this->getProxyGroups($proxy_groupids); $this->call('proxygroup.update', $proxy_groups, $expected_error); $proxy_groups_upd = $this->getProxyGroups($proxy_groupids); $db_defaults = DB::getDefaults('proxy_group'); // Compare records from DB before and after API call. foreach ($proxy_groups as $proxy_group) { $db_proxy_group = $db_proxy_groups[$proxy_group['proxy_groupid']]; $proxy_group_upd = $proxy_groups_upd[$proxy_group['proxy_groupid']]; $this->assertNotEmpty($proxy_group_upd['name']); foreach (['name', 'description'] as $field) { if (array_key_exists($field, $proxy_group)) { $this->assertSame($proxy_group[$field], $proxy_group_upd[$field]); } else { $this->assertSame($db_proxy_group[$field], $proxy_group_upd[$field]); } } } // Restore proxy group original data after each test. $this->restoreProxyGroups($db_proxy_groups); } else { // Call method and make sure it really returns the error. $this->call('proxygroup.update', $proxy_groups, $expected_error); // Make sure nothing has changed as well. $this->assertSame($old_hash_proxy_groups, CDBHelper::getHash($sql_proxy_groups)); } } /** * Data provider for proxygroup.delete. * * @return array */ public static function getProxyGroupDeleteData(): array { return [ 'Test proxygroup.delete: delete single' => [ 'proxygroup' => ['state_offline'], 'expected_error' => null ], 'Test proxygroup.delete: delete multiple' => [ 'proxygroup' => [ 'state_recovering', 'state_online', 'state_degrading' ], 'expected_error' => null ] ]; } /** * Test proxygroup.delete method. * * @dataProvider getProxyGroupDeleteData */ public function testProxyGroup_Delete(array $proxy_groupids, ?string $expected_error): void { // Replace ID placeholders with real IDs. foreach ($proxy_groupids as &$proxy_groupid) { if (self::isValidIdPlaceholder($proxy_groupid)) { $proxy_groupid = self::$data['proxy_groupids'][$proxy_groupid]; } } unset($proxy_groupid); $sql_proxy_groups = 'SELECT NULL FROM proxy_group'; $old_hash_proxy_groups = CDBHelper::getHash($sql_proxy_groups); $this->call('proxygroup.delete', $proxy_groupids, $expected_error); if ($expected_error === null) { $this->assertNotSame($old_hash_proxy_groups, CDBHelper::getHash($sql_proxy_groups)); $this->assertEquals(0, CDBHelper::getCount( 'SELECT pg.proxy_groupid FROM proxy_group pg WHERE '.dbConditionId('pg.proxy_groupid', $proxy_groupids) )); foreach ($proxy_groupids as $proxy_groupid) { $key = array_search($proxy_groupid, self::$data['proxy_groupids']); if ($key !== false) { unset(self::$data['proxy_groupids'][$key]); } } } else { $this->assertSame($old_hash_proxy_groups, CDBHelper::getHash($sql_proxy_groups)); } } /** * Get the original proxy groups before update. * * @param array $proxy_groupids * * @return array */ private function getProxyGroups(array $proxy_groupids): array { $response = $this->call('proxygroup.get', [ 'output' => ['proxy_groupid', 'name', 'failover_delay', 'min_online', 'description', 'state'], 'proxy_groupids' => $proxy_groupids, 'preservekeys' => true ]); return $response['result']; } /** * Restore proxy groups to their original state. * * @param array $proxy_groups */ private function restoreProxyGroups(array $proxy_groups): void { $upd_states = []; foreach ($proxy_groups as &$proxy_group) { $upd_states[] = [ 'values' => [ 'state' => $proxy_group['state'] ], 'where' => ['proxy_groupid' => $proxy_group['proxy_groupid']] ]; unset($proxy_group['state']); } unset($proxy_group); $this->call('proxygroup.update', $proxy_groups); DB::update('proxy_group_rtdata', $upd_states); } /** * Delete all created data after test. */ public static function clearData(): void { // Delete hosts. CDataHelper::call('host.delete', array_values(self::$data['hostids'])); // Delete host groups. CDataHelper::call('hostgroup.delete', self::$data['groupids']); // Delete proxies. CDataHelper::call('proxy.delete', self::$data['proxyids']); // Delete proxy groups. $proxy_groupids = array_values(self::$data['proxy_groupids']); $proxy_groupids = array_merge($proxy_groupids, self::$data['created']); CDataHelper::call('proxygroup.delete', $proxy_groupids); } /** * Helper method to convert placeholders to real IDs. * * @param array $request * * @return array */ private static function resolveIds(array $request): array { foreach (['proxy_groupid', 'proxyid'] as $field) { if (array_key_exists($field, $request) && self::isValidIdPlaceholder($request[$field])) { $request[$field] = self::$data[$field.'s'][$request[$field]]; } } foreach (['proxy_groupids', 'proxyids'] as $field) { if (!array_key_exists($field, $request)) { continue; } if (is_array($request[$field])) { foreach ($request[$field] as &$id) { if (self::isValidIdPlaceholder($id)) { $id = self::$data[$field][$id]; } } unset($id); } elseif (self::isValidIdPlaceholder($request[$field])) { $request[$field] = self::$data[$field][$request[$field]]; } } if (array_key_exists('proxies', $request) && is_array($request['proxies'])) { foreach ($request['proxies'] as &$proxy) { if (is_array($proxy) && array_key_exists('proxyid', $proxy) && self::isValidIdPlaceholder($proxy['proxyid'])) { $proxy['proxyid'] = self::$data['proxyids'][$proxy['proxyid']]; } } unset($proxy); } if (array_key_exists('filter', $request) && is_array($request['filter']) && array_key_exists('proxy_groupid', $request['filter'])) { if (is_array($request['filter']['proxy_groupid'])) { foreach ($request['filter']['proxy_groupid'] as &$id) { if (self::isValidIdPlaceholder($id)) { $id = self::$data['proxy_groupids'][$id]; } } unset($id); } elseif (self::isValidIdPlaceholder($request['filter']['proxy_groupid'])) { $request['filter']['proxy_groupid'] = self::$data['proxy_groupids'][$request['filter']['proxy_groupid']]; } } return $request; } /** * Helper method to check ID placeholder. * * @param $id * * @return bool */ private static function isValidIdPlaceholder($id): bool { // Do not compare != 0 (it will not work) or !== 0 or !== '0' (avoid type check here). return !is_array($id) && $id != '0' && $id !== '' && $id !== null && $id != self::INVALID_NUMBER; } }