Loading tests/unit/test_resources.py 0 → 100644 +95 −0 Original line number Diff line number Diff line # Copyright 2022 Dominik Sekotill <dom.sekotill@kodo.org.uk> # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Tests for the project_templates.resources module """ import atexit import tempfile import unittest from pathlib import Path from unittest.mock import Mock from unittest.mock import patch from project_templates import resources TEMP_DIR = Path(tempfile.mkdtemp()) TEMP_DIR.joinpath("test-file").touch() atexit.register(TEMP_DIR.rmdir) atexit.register(TEMP_DIR.joinpath("test-file").unlink) @patch("pathlib.Path.unlink") @patch("pathlib.Path.rmdir") @patch("tempfile.mkdtemp", return_value=TEMP_DIR.as_posix()) class TempDirTests(unittest.TestCase): """ Tests for the TempDir class """ def test_create(self, mkdtemp: Mock, rmdir: Mock, unlink: Mock) -> None: """ Check that a temporary directory is created safely and destroyed """ with self.subTest("create"): temp = resources.TempDir() mkdtemp.assert_called() with self.subTest("destroy"): temp.cleanup() rmdir.assert_called() unlink.assert_called() def test_context(self, mkdtemp: Mock, rmdir: Mock, unlink: Mock) -> None: """ Check use as a context manager """ with resources.TempDir(): pass mkdtemp.assert_called() rmdir.assert_called() unlink.assert_called() def test_idempotent_cleanup(self, mkdtemp: Mock, rmdir: Mock, unlink: Mock) -> None: """ Check that calling cleanup after the directory has been removed causes no problems """ temp = resources.TempDir() with patch("pathlib.Path.exists", return_value=False): temp.cleanup() rmdir.assert_not_called() unlink.assert_not_called() def test_fail_safe(self, mkdtemp: Mock, rmdir: Mock, unlink: Mock) -> None: """ If an instance points at a non-temporary location, check nothing is damaged In the event that a TempDir is accidentally created pointing to a path not in the directory pointed to by `tempfile.gettempdir`, the class should safely refuse to clean up, to avoid damaging non-temporary files. """ mkdtemp.return_value = "/some-other/path" temp = resources.TempDir() with self.assertRaises(RuntimeError): temp.cleanup() rmdir.assert_not_called() unlink.assert_not_called() Loading
tests/unit/test_resources.py 0 → 100644 +95 −0 Original line number Diff line number Diff line # Copyright 2022 Dominik Sekotill <dom.sekotill@kodo.org.uk> # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Tests for the project_templates.resources module """ import atexit import tempfile import unittest from pathlib import Path from unittest.mock import Mock from unittest.mock import patch from project_templates import resources TEMP_DIR = Path(tempfile.mkdtemp()) TEMP_DIR.joinpath("test-file").touch() atexit.register(TEMP_DIR.rmdir) atexit.register(TEMP_DIR.joinpath("test-file").unlink) @patch("pathlib.Path.unlink") @patch("pathlib.Path.rmdir") @patch("tempfile.mkdtemp", return_value=TEMP_DIR.as_posix()) class TempDirTests(unittest.TestCase): """ Tests for the TempDir class """ def test_create(self, mkdtemp: Mock, rmdir: Mock, unlink: Mock) -> None: """ Check that a temporary directory is created safely and destroyed """ with self.subTest("create"): temp = resources.TempDir() mkdtemp.assert_called() with self.subTest("destroy"): temp.cleanup() rmdir.assert_called() unlink.assert_called() def test_context(self, mkdtemp: Mock, rmdir: Mock, unlink: Mock) -> None: """ Check use as a context manager """ with resources.TempDir(): pass mkdtemp.assert_called() rmdir.assert_called() unlink.assert_called() def test_idempotent_cleanup(self, mkdtemp: Mock, rmdir: Mock, unlink: Mock) -> None: """ Check that calling cleanup after the directory has been removed causes no problems """ temp = resources.TempDir() with patch("pathlib.Path.exists", return_value=False): temp.cleanup() rmdir.assert_not_called() unlink.assert_not_called() def test_fail_safe(self, mkdtemp: Mock, rmdir: Mock, unlink: Mock) -> None: """ If an instance points at a non-temporary location, check nothing is damaged In the event that a TempDir is accidentally created pointing to a path not in the directory pointed to by `tempfile.gettempdir`, the class should safely refuse to clean up, to avoid damaging non-temporary files. """ mkdtemp.return_value = "/some-other/path" temp = resources.TempDir() with self.assertRaises(RuntimeError): temp.cleanup() rmdir.assert_not_called() unlink.assert_not_called()