Skip to content

Commit f32bdd1

Browse files
committed
BMC FW update UT
Signed-off-by: Ben Levi <[email protected]>
1 parent f9119cc commit f32bdd1

File tree

2 files changed

+166
-1
lines changed

2 files changed

+166
-1
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def main():
1212
import sonic_platform
1313
from sonic_py_common.logger import Logger
1414

15-
logger = Logger('bmc-fw-update')
15+
logger = Logger('bmc_fw_update')
1616

1717
if len(sys.argv) != 2:
1818
logger.log_error("Missing firmware image path argument")

tests/bmc_fw_update_test.py

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
"""
2+
bmc_fw_update_test.py
3+
4+
Unit tests for bmc_fw_update module
5+
"""
6+
7+
import sys
8+
import pytest
9+
10+
if sys.version_info.major == 3:
11+
from unittest import mock
12+
else:
13+
import mock
14+
15+
try:
16+
from sonic_py_common import logger
17+
except ImportError:
18+
sys.modules['sonic_py_common'] = mock.MagicMock()
19+
sys.modules['sonic_py_common.logger'] = mock.MagicMock()
20+
21+
from sonic_platform_base import bmc_fw_update
22+
23+
24+
class TestBMCFWUpdate:
25+
"""Test class for bmc_fw_update module"""
26+
27+
@mock.patch('sys.exit')
28+
@mock.patch('sonic_py_common.logger.Logger')
29+
def test_main_success_bmc_firmware_updated(self, mock_logger_class, mock_exit):
30+
"""Test successful firmware update with BMC firmware component updated"""
31+
mock_logger = mock.MagicMock()
32+
mock_bmc = mock.MagicMock()
33+
mock_chassis = mock.MagicMock()
34+
mock_platform = mock.MagicMock()
35+
mock_chassis.get_bmc.return_value = mock_bmc
36+
mock_platform.get_chassis.return_value = mock_chassis
37+
mock_sonic_platform = mock.MagicMock()
38+
mock_sonic_platform.platform.Platform.return_value = mock_platform
39+
mock_logger_class.return_value = mock_logger
40+
mock_bmc.update_firmware.return_value = (0, ('Success', ['BMC_FW_0', 'OTHER_FW']))
41+
mock_bmc.get_firmware_id.return_value = 'BMC_FW_0'
42+
mock_bmc.request_bmc_reset.return_value = (0, 'BMC reset successful')
43+
44+
test_args = ['bmc_fw_update.py', '/path/to/firmware.bin']
45+
with mock.patch.dict(sys.modules, {'sonic_platform': mock_sonic_platform}):
46+
with mock.patch.object(sys, 'argv', test_args):
47+
bmc_fw_update.main()
48+
49+
mock_logger_class.assert_called_once_with('bmc_fw_update')
50+
mock_chassis.get_bmc.assert_called_once()
51+
mock_bmc.update_firmware.assert_called_once_with('/path/to/firmware.bin')
52+
mock_bmc.get_firmware_id.assert_called_once()
53+
mock_bmc.request_bmc_reset.assert_called_once()
54+
mock_exit.assert_not_called()
55+
56+
@mock.patch('sys.exit')
57+
@mock.patch('sonic_py_common.logger.Logger')
58+
def test_main_success_no_bmc_reset_needed(self, mock_logger_class, mock_exit):
59+
"""Test successful firmware update without BMC reset"""
60+
mock_logger = mock.MagicMock()
61+
mock_bmc = mock.MagicMock()
62+
mock_chassis = mock.MagicMock()
63+
mock_platform = mock.MagicMock()
64+
mock_chassis.get_bmc.return_value = mock_bmc
65+
mock_platform.get_chassis.return_value = mock_chassis
66+
mock_sonic_platform = mock.MagicMock()
67+
mock_sonic_platform.platform.Platform.return_value = mock_platform
68+
mock_logger_class.return_value = mock_logger
69+
mock_bmc.update_firmware.return_value = (0, ('Success', ['OTHER_FW_1', 'OTHER_FW_2']))
70+
mock_bmc.get_firmware_id.return_value = 'BMC_FW_0'
71+
72+
test_args = ['bmc_fw_update.py', '/path/to/firmware.bin']
73+
with mock.patch.dict(sys.modules, {'sonic_platform': mock_sonic_platform}):
74+
with mock.patch.object(sys, 'argv', test_args):
75+
bmc_fw_update.main()
76+
77+
mock_bmc.update_firmware.assert_called_once_with('/path/to/firmware.bin')
78+
mock_bmc.get_firmware_id.assert_called_once()
79+
mock_bmc.request_bmc_reset.assert_not_called()
80+
mock_exit.assert_not_called()
81+
82+
@mock.patch('sys.exit')
83+
@mock.patch('sonic_py_common.logger.Logger')
84+
def test_main_missing_arguments(self, mock_logger_class, mock_exit):
85+
"""Test main with missing arguments"""
86+
mock_logger = mock.MagicMock()
87+
mock_sonic_platform = mock.MagicMock()
88+
mock_logger_class.return_value = mock_logger
89+
90+
test_args = ['bmc_fw_update.py']
91+
with mock.patch.dict(sys.modules, {'sonic_platform': mock_sonic_platform}):
92+
with mock.patch.object(sys, 'argv', test_args):
93+
bmc_fw_update.main()
94+
95+
mock_logger.log_error.assert_any_call("Missing firmware image path argument")
96+
mock_exit.assert_called_with(1)
97+
98+
@mock.patch('sys.exit')
99+
@mock.patch('sonic_py_common.logger.Logger')
100+
def test_main_no_bmc_instance(self, mock_logger_class, mock_exit):
101+
"""Test main when BMC instance is None"""
102+
mock_logger = mock.MagicMock()
103+
mock_chassis = mock.MagicMock()
104+
mock_platform = mock.MagicMock()
105+
mock_chassis.get_bmc.return_value = None
106+
mock_platform.get_chassis.return_value = mock_chassis
107+
mock_sonic_platform = mock.MagicMock()
108+
mock_sonic_platform.platform.Platform.return_value = mock_platform
109+
mock_logger_class.return_value = mock_logger
110+
111+
test_args = ['bmc_fw_update.py', '/path/to/firmware.bin']
112+
with mock.patch.dict(sys.modules, {'sonic_platform': mock_sonic_platform}):
113+
with mock.patch.object(sys, 'argv', test_args):
114+
bmc_fw_update.main()
115+
116+
mock_logger.log_error.assert_any_call("Failed to get BMC instance from chassis")
117+
mock_exit.assert_called_with(1)
118+
119+
@mock.patch('sys.exit')
120+
@mock.patch('sonic_py_common.logger.Logger')
121+
def test_main_update_firmware_failure(self, mock_logger_class, mock_exit):
122+
"""Test main when firmware update fails"""
123+
mock_logger = mock.MagicMock()
124+
mock_bmc = mock.MagicMock()
125+
mock_chassis = mock.MagicMock()
126+
mock_platform = mock.MagicMock()
127+
mock_chassis.get_bmc.return_value = mock_bmc
128+
mock_platform.get_chassis.return_value = mock_chassis
129+
mock_sonic_platform = mock.MagicMock()
130+
mock_sonic_platform.platform.Platform.return_value = mock_platform
131+
mock_logger_class.return_value = mock_logger
132+
mock_bmc.update_firmware.return_value = (1, ('Update failed', []))
133+
134+
test_args = ['bmc_fw_update.py', '/path/to/firmware.bin']
135+
with mock.patch.dict(sys.modules, {'sonic_platform': mock_sonic_platform}):
136+
with mock.patch.object(sys, 'argv', test_args):
137+
bmc_fw_update.main()
138+
139+
mock_logger.log_error.assert_called_once_with('Failed to update BMC firmware. Error 1: Update failed')
140+
mock_exit.assert_called_once_with(1)
141+
142+
@mock.patch('sys.exit')
143+
@mock.patch('sonic_py_common.logger.Logger')
144+
def test_main_bmc_reset_failure(self, mock_logger_class, mock_exit):
145+
"""Test main when BMC reset fails"""
146+
mock_logger = mock.MagicMock()
147+
mock_bmc = mock.MagicMock()
148+
mock_chassis = mock.MagicMock()
149+
mock_platform = mock.MagicMock()
150+
mock_chassis.get_bmc.return_value = mock_bmc
151+
mock_platform.get_chassis.return_value = mock_chassis
152+
mock_sonic_platform = mock.MagicMock()
153+
mock_sonic_platform.platform.Platform.return_value = mock_platform
154+
mock_logger_class.return_value = mock_logger
155+
mock_bmc.update_firmware.return_value = (0, ('Success', ['BMC_FW_0']))
156+
mock_bmc.get_firmware_id.return_value = 'BMC_FW_0'
157+
mock_bmc.request_bmc_reset.return_value = (1, 'Reset failed')
158+
159+
test_args = ['bmc_fw_update.py', '/path/to/firmware.bin']
160+
with mock.patch.dict(sys.modules, {'sonic_platform': mock_sonic_platform}):
161+
with mock.patch.object(sys, 'argv', test_args):
162+
bmc_fw_update.main()
163+
164+
mock_logger.log_error.assert_called_once_with('Failed to restart BMC. Error 1: Reset failed')
165+
mock_exit.assert_called_once_with(1)

0 commit comments

Comments
 (0)