Commit 313e7ad8 authored by Dom Sekotill's avatar Dom Sekotill
Browse files

Add unit tests for TempDir

parent 8a2ff3a9
Loading
Loading
Loading
Loading
Loading
+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()