Skip to content

Commit 7b8c7d1

Browse files
committed
Added UT for the changes
Signed-off-by: Abhishek Dosi <[email protected]>
1 parent 29be8d2 commit 7b8c7d1

File tree

3 files changed

+602
-57
lines changed

3 files changed

+602
-57
lines changed

scripts/hostcfgd

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ class FeatureHandler(object):
232232
"""
233233
Summary:
234234
Updates the state field in the FEATURE|* tables as the state field
235-
might have to be rendered based on DEVICE_METADATA table and generated Device Running Metadata
235+
might have to be rendere dbased on DEVICE_METADATA table and generated Device Running Metadata
236236
"""
237237
for feature_name in feature_table.keys():
238238
if not feature_name:
@@ -285,8 +285,7 @@ class FeatureHandler(object):
285285
self.disable_feature(feature)
286286
syslog.syslog(syslog.LOG_INFO, "Feature {} is stopped and disabled".format(feature.name))
287287

288-
if self.is_multi_npu:
289-
self.sync_feature_asic_scope(feature)
288+
self.sync_feature_asic_scope(feature)
290289

291290
return True
292291

@@ -311,7 +310,7 @@ class FeatureHandler(object):
311310
unit_file_state = self.get_systemd_unit_state("{}.{}".format(feature_name, feature_suffixes[-1]))
312311
if not unit_file_state:
313312
continue
314-
if unit_file_state == "enabled" and not feature_config.has_per_asic_scope:
313+
if unit_file_state != "disabled" and not feature_config.has_per_asic_scope:
315314
for suffix in reversed(feature_suffixes):
316315
cmds.append("sudo systemctl stop {}.{}".format(feature_name, suffix))
317316
cmds.append("sudo systemctl disable {}.{}".format(feature_name, feature_suffixes[-1]))
@@ -325,7 +324,7 @@ class FeatureHandler(object):
325324
.format(feature.name, feature_suffixes[-1]))
326325
self.set_feature_state(feature, self.FEATURE_STATE_FAILED)
327326
return
328-
self._config_db.mod_entry('FEATURE', feature_config.name, {'has_per_asic_scope': feature_config.has_per_asic_scope})
327+
self._config_db.mod_entry('FEATURE', feature_config.name, {'has_per_asic_scope': str(feature_config.has_per_asic_scope)})
329328

330329

331330

tests/hostcfgd/hostcfgd_test.py

Lines changed: 71 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import sys
33
import swsscommon as swsscommon_package
4+
from sonic_py_common import device_info
45
from swsscommon import swsscommon
56

67
from parameterized import parameterized
@@ -45,7 +46,7 @@ def checks_config_table(self, feature_table, expected_table):
4546

4647
return True if not ddiff else False
4748

48-
def checks_systemd_config_file(self, feature_table):
49+
def checks_systemd_config_file(self, feature_table, feature_systemd_name_map=None):
4950
"""Checks whether the systemd configuration file of each feature was created or not
5051
and whether the `Restart=` field in the file is set correctly or not.
5152
@@ -68,13 +69,16 @@ def checks_systemd_config_file(self, feature_table):
6869
elif "disabled" in auto_restart_status:
6970
auto_restart_status = "disabled"
7071

71-
feature_systemd_config_file_path = systemd_config_file_path.format(feature_name)
72-
is_config_file_existing = os.path.exists(feature_systemd_config_file_path)
73-
assert is_config_file_existing, "Systemd configuration file of feature '{}' does not exist!".format(feature_name)
72+
feature_systemd_list = feature_systemd_name_map[feature_name] if feature_systemd_name_map else [feature_name]
7473

75-
with open(feature_systemd_config_file_path) as systemd_config_file:
76-
status = systemd_config_file.read().strip()
77-
assert status == '[Service]\nRestart={}'.format(truth_table[auto_restart_status])
74+
for feature_systemd in feature_systemd_list:
75+
feature_systemd_config_file_path = systemd_config_file_path.format(feature_systemd)
76+
is_config_file_existing = os.path.exists(feature_systemd_config_file_path)
77+
assert is_config_file_existing, "Systemd configuration file of feature '{}' does not exist!".format(feature_systemd)
78+
79+
with open(feature_systemd_config_file_path) as systemd_config_file:
80+
status = systemd_config_file.read().strip()
81+
assert status == '[Service]\nRestart={}'.format(truth_table[auto_restart_status])
7882

7983
def get_state_db_set_calls(self, feature_table):
8084
"""Returns a Mock call objects which recorded the `set` calls to `FEATURE` table in `STATE_DB`.
@@ -119,31 +123,40 @@ def test_sync_state_field(self, test_scenario_name, config_data, fs):
119123
MockConfigDb.set_config_db(config_data['config_db'])
120124
feature_state_table_mock = mock.Mock()
121125
with mock.patch('hostcfgd.subprocess') as mocked_subprocess:
122-
popen_mock = mock.Mock()
123-
attrs = config_data['popen_attributes']
124-
popen_mock.configure_mock(**attrs)
125-
mocked_subprocess.Popen.return_value = popen_mock
126-
127-
device_config = {}
128-
device_config['DEVICE_METADATA'] = MockConfigDb.CONFIG_DB['DEVICE_METADATA']
129-
feature_handler = hostcfgd.FeatureHandler(MockConfigDb(), feature_state_table_mock, device_config)
130-
131-
feature_table = MockConfigDb.CONFIG_DB['FEATURE']
132-
feature_handler.sync_state_field(feature_table)
133-
134-
is_any_difference = self.checks_config_table(MockConfigDb.get_config_db()['FEATURE'],
135-
config_data['expected_config_db']['FEATURE'])
136-
assert is_any_difference, "'FEATURE' table in 'CONFIG_DB' is modified unexpectedly!"
137-
138-
feature_table_state_db_calls = self.get_state_db_set_calls(feature_table)
139-
140-
self.checks_systemd_config_file(config_data['config_db']['FEATURE'])
141-
mocked_subprocess.check_call.assert_has_calls(config_data['enable_feature_subprocess_calls'],
142-
any_order=True)
143-
mocked_subprocess.check_call.assert_has_calls(config_data['daemon_reload_subprocess_call'],
144-
any_order=True)
145-
feature_state_table_mock.set.assert_has_calls(feature_table_state_db_calls)
146-
self.checks_systemd_config_file(config_data['config_db']['FEATURE'])
126+
with mock.patch("sonic_py_common.device_info.get_device_runtime_metadata", return_value=config_data['device_runtime_metadata']):
127+
with mock.patch("sonic_py_common.device_info.is_multi_npu", return_value=True if 'num_npu' in config_data else False):
128+
with mock.patch("sonic_py_common.device_info.get_num_npus", return_value=config_data['num_npu'] if 'num_npu' in config_data else 1):
129+
popen_mock = mock.Mock()
130+
attrs = config_data['popen_attributes']
131+
popen_mock.configure_mock(**attrs)
132+
mocked_subprocess.Popen.return_value = popen_mock
133+
134+
device_config = {}
135+
device_config['DEVICE_METADATA'] = MockConfigDb.CONFIG_DB['DEVICE_METADATA']
136+
feature_handler = hostcfgd.FeatureHandler(MockConfigDb(), feature_state_table_mock, device_config)
137+
138+
feature_table = MockConfigDb.CONFIG_DB['FEATURE']
139+
feature_handler.sync_state_field(feature_table)
140+
141+
feature_systemd_name_map = {}
142+
for feature_name in feature_table.keys():
143+
feature = hostcfgd.Feature(feature_name, feature_table[feature_name], device_config | config_data['device_runtime_metadata'])
144+
feature_names, _ = feature_handler.get_multiasic_feature_instances(feature)
145+
feature_systemd_name_map[feature_name] = feature_names
146+
147+
is_any_difference = self.checks_config_table(MockConfigDb.get_config_db()['FEATURE'],
148+
config_data['expected_config_db']['FEATURE'])
149+
assert is_any_difference, "'FEATURE' table in 'CONFIG_DB' is modified unexpectedly!"
150+
151+
feature_table_state_db_calls = self.get_state_db_set_calls(feature_table)
152+
153+
self.checks_systemd_config_file(config_data['config_db']['FEATURE'], feature_systemd_name_map)
154+
mocked_subprocess.check_call.assert_has_calls(config_data['enable_feature_subprocess_calls'],
155+
any_order=True)
156+
mocked_subprocess.check_call.assert_has_calls(config_data['daemon_reload_subprocess_call'],
157+
any_order=True)
158+
feature_state_table_mock.set.assert_has_calls(feature_table_state_db_calls)
159+
self.checks_systemd_config_file(config_data['config_db']['FEATURE'], feature_systemd_name_map)
147160

148161
@parameterized.expand(HOSTCFGD_TEST_VECTOR)
149162
@patchfs
@@ -164,25 +177,32 @@ def test_handler(self, test_scenario_name, config_data, fs):
164177
MockConfigDb.set_config_db(config_data['config_db'])
165178
feature_state_table_mock = mock.Mock()
166179
with mock.patch('hostcfgd.subprocess') as mocked_subprocess:
167-
popen_mock = mock.Mock()
168-
attrs = config_data['popen_attributes']
169-
popen_mock.configure_mock(**attrs)
170-
mocked_subprocess.Popen.return_value = popen_mock
171-
172-
device_config = {}
173-
device_config['DEVICE_METADATA'] = MockConfigDb.CONFIG_DB['DEVICE_METADATA']
174-
feature_handler = hostcfgd.FeatureHandler(MockConfigDb(), feature_state_table_mock, device_config)
175-
176-
feature_table = MockConfigDb.CONFIG_DB['FEATURE']
177-
178-
for feature_name, feature_config in feature_table.items():
179-
feature_handler.handler(feature_name, 'SET', feature_config)
180-
181-
self.checks_systemd_config_file(config_data['config_db']['FEATURE'])
182-
mocked_subprocess.check_call.assert_has_calls(config_data['enable_feature_subprocess_calls'],
183-
any_order=True)
184-
mocked_subprocess.check_call.assert_has_calls(config_data['daemon_reload_subprocess_call'],
185-
any_order=True)
180+
with mock.patch("sonic_py_common.device_info.get_device_runtime_metadata", return_value=config_data['device_runtime_metadata']):
181+
with mock.patch("sonic_py_common.device_info.is_multi_npu", return_value=True if 'num_npu' in config_data else False):
182+
with mock.patch("sonic_py_common.device_info.get_num_npus", return_value=config_data['num_npu'] if 'num_npu' in config_data else 1):
183+
popen_mock = mock.Mock()
184+
attrs = config_data['popen_attributes']
185+
popen_mock.configure_mock(**attrs)
186+
mocked_subprocess.Popen.return_value = popen_mock
187+
188+
device_config = {}
189+
device_config['DEVICE_METADATA'] = MockConfigDb.CONFIG_DB['DEVICE_METADATA']
190+
feature_handler = hostcfgd.FeatureHandler(MockConfigDb(), feature_state_table_mock, device_config)
191+
192+
feature_table = MockConfigDb.CONFIG_DB['FEATURE']
193+
194+
feature_systemd_name_map = {}
195+
for feature_name, feature_config in feature_table.items():
196+
feature_handler.handler(feature_name, 'SET', feature_config)
197+
feature = hostcfgd.Feature(feature_name, feature_table[feature_name], device_config | config_data['device_runtime_metadata'])
198+
feature_names, _ = feature_handler.get_multiasic_feature_instances(feature)
199+
feature_systemd_name_map[feature_name] = feature_names
200+
201+
self.checks_systemd_config_file(config_data['config_db']['FEATURE'], feature_systemd_name_map)
202+
mocked_subprocess.check_call.assert_has_calls(config_data['enable_feature_subprocess_calls'],
203+
any_order=True)
204+
mocked_subprocess.check_call.assert_has_calls(config_data['daemon_reload_subprocess_call'],
205+
any_order=True)
186206

187207
def test_feature_config_parsing(self):
188208
swss_feature = hostcfgd.Feature('swss', {

0 commit comments

Comments
 (0)