|
2 | 2 | import os |
3 | 3 | import pathlib |
4 | 4 | import unittest |
| 5 | +from unittest.mock import mock_open, patch |
5 | 6 |
|
6 | 7 | import canopen |
7 | 8 | from canopen.objectdictionary.eds import _signed_int_from_hex |
@@ -297,6 +298,31 @@ def test_export_eds_to_file_unknown_extension(self): |
297 | 298 | buf.name = "mock.eds" |
298 | 299 | self.verify_od(buf, "eds") |
299 | 300 |
|
| 301 | + def test_export_eds_auto_close(self): |
| 302 | + m_open = mock_open() |
| 303 | + with patch("canopen.objectdictionary.open", m_open): |
| 304 | + canopen.export_od(self.od, m_open) |
| 305 | + fd = m_open() |
| 306 | + # File object already passed in must NOT be closed |
| 307 | + fd.close.assert_not_called() |
| 308 | + for path in ("mock.eds", pathlib.Path("mock.eds")): |
| 309 | + with self.subTest(path=path): |
| 310 | + m_open = mock_open() |
| 311 | + with patch("canopen.objectdictionary.open", m_open): |
| 312 | + canopen.export_od(self.od, path) |
| 313 | + fd = m_open() |
| 314 | + # File object opened at path must be closed before return |
| 315 | + fd.close.assert_called_once() |
| 316 | + |
| 317 | + def test_export_eds_auto_close_exception(self): |
| 318 | + m_open = mock_open() |
| 319 | + fd = m_open() |
| 320 | + fd.write.side_effect = IOError("Simulated write failure") |
| 321 | + with patch("canopen.objectdictionary.open", m_open), self.assertRaises(IOError): |
| 322 | + canopen.export_od(self.od, "mock.eds") |
| 323 | + # File object opened at path must be closed on inner exception |
| 324 | + fd.close.assert_called_once() |
| 325 | + |
300 | 326 | def test_export_eds_unknown_doctype(self): |
301 | 327 | filelike_object = io.StringIO() |
302 | 328 | self.addCleanup(filelike_object.close) |
@@ -334,7 +360,6 @@ def test_export_eds_to_stdout(self): |
334 | 360 | buf.name = "mock.eds" |
335 | 361 | self.verify_od(buf, "eds") |
336 | 362 |
|
337 | | - |
338 | 363 | def verify_od(self, source, doctype): |
339 | 364 | exported_od = canopen.import_od(source) |
340 | 365 |
|
|
0 commit comments