176 lines
5.6 KiB
Python
176 lines
5.6 KiB
Python
|
|
# Copyright 2022 The Pigweed Authors
|
||
|
|
#
|
||
|
|
# 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
|
||
|
|
#
|
||
|
|
# https://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.
|
||
|
|
"""pw_ide test classes."""
|
||
|
|
|
||
|
|
from contextlib import contextmanager
|
||
|
|
from io import TextIOWrapper
|
||
|
|
from pathlib import Path
|
||
|
|
import tempfile
|
||
|
|
from typing import Generator, List, Optional, Tuple, Union
|
||
|
|
import unittest
|
||
|
|
|
||
|
|
from pw_ide.settings import PigweedIdeSettings
|
||
|
|
|
||
|
|
|
||
|
|
class TempDirTestCase(unittest.TestCase):
|
||
|
|
"""Run tests that need access to a temporary directory."""
|
||
|
|
|
||
|
|
def setUp(self) -> None:
|
||
|
|
self.temp_dir = tempfile.TemporaryDirectory()
|
||
|
|
self.temp_dir_path = Path(self.temp_dir.name)
|
||
|
|
|
||
|
|
def tearDown(self) -> None:
|
||
|
|
self.temp_dir.cleanup()
|
||
|
|
return super().tearDown()
|
||
|
|
|
||
|
|
@contextmanager
|
||
|
|
def make_temp_file(
|
||
|
|
self, filename: Union[Path, str], content: str = ''
|
||
|
|
) -> Generator[Tuple[TextIOWrapper, Path], None, None]:
|
||
|
|
"""Create a temp file in the test case's temp dir.
|
||
|
|
|
||
|
|
Returns a tuple containing the file reference and the file's path.
|
||
|
|
The file can be read immediately.
|
||
|
|
"""
|
||
|
|
path = self.temp_dir_path / filename
|
||
|
|
|
||
|
|
with open(path, 'a+', encoding='utf-8') as file:
|
||
|
|
file.write(content)
|
||
|
|
file.flush()
|
||
|
|
file.seek(0)
|
||
|
|
yield (file, path)
|
||
|
|
|
||
|
|
def touch_temp_file(
|
||
|
|
self, filename: Union[Path, str], content: str = ''
|
||
|
|
) -> None:
|
||
|
|
"""Create a temp file in the test case's temp dir, without context."""
|
||
|
|
with self.make_temp_file(filename, content):
|
||
|
|
pass
|
||
|
|
|
||
|
|
@contextmanager
|
||
|
|
def open_temp_file(
|
||
|
|
self,
|
||
|
|
filename: Union[Path, str],
|
||
|
|
) -> Generator[Tuple[TextIOWrapper, Path], None, None]:
|
||
|
|
"""Open an existing temp file in the test case's temp dir.
|
||
|
|
|
||
|
|
Returns a tuple containing the file reference and the file's path.
|
||
|
|
"""
|
||
|
|
path = self.temp_dir_path / filename
|
||
|
|
|
||
|
|
with open(path, 'r', encoding='utf-8') as file:
|
||
|
|
yield (file, path)
|
||
|
|
|
||
|
|
@contextmanager
|
||
|
|
def make_temp_files(
|
||
|
|
self, files_data: List[Tuple[Union[Path, str], str]]
|
||
|
|
) -> Generator[List[TextIOWrapper], None, None]:
|
||
|
|
"""Create several temp files in the test case's temp dir.
|
||
|
|
|
||
|
|
Provide a list of file name and content tuples. Saves you the trouble
|
||
|
|
of excessive `with self.make_temp_file, self.make_temp_file...`
|
||
|
|
nesting, and allows programmatic definition of multiple temp file
|
||
|
|
contexts. Files can be read immediately.
|
||
|
|
"""
|
||
|
|
files: List[TextIOWrapper] = []
|
||
|
|
|
||
|
|
for filename, content in files_data:
|
||
|
|
file = open(self.path_in_temp_dir(filename), 'a+', encoding='utf-8')
|
||
|
|
file.write(content)
|
||
|
|
file.flush()
|
||
|
|
file.seek(0)
|
||
|
|
files.append(file)
|
||
|
|
|
||
|
|
yield files
|
||
|
|
|
||
|
|
for file in files:
|
||
|
|
file.close()
|
||
|
|
|
||
|
|
def touch_temp_files(
|
||
|
|
self, files_data: List[Tuple[Union[Path, str], str]]
|
||
|
|
) -> None:
|
||
|
|
"""Create several temp files in the temp dir, without context."""
|
||
|
|
with self.make_temp_files(files_data):
|
||
|
|
pass
|
||
|
|
|
||
|
|
@contextmanager
|
||
|
|
def open_temp_files(
|
||
|
|
self, files_data: List[Union[Path, str]]
|
||
|
|
) -> Generator[List[TextIOWrapper], None, None]:
|
||
|
|
"""Open several existing temp files in the test case's temp dir.
|
||
|
|
|
||
|
|
Provide a list of file names. Saves you the trouble of excessive
|
||
|
|
`with self.open_temp_file, self.open_temp_file...` nesting, and allows
|
||
|
|
programmatic definition of multiple temp file contexts.
|
||
|
|
"""
|
||
|
|
files: List[TextIOWrapper] = []
|
||
|
|
|
||
|
|
for filename in files_data:
|
||
|
|
file = open(self.path_in_temp_dir(filename), 'r', encoding='utf-8')
|
||
|
|
files.append(file)
|
||
|
|
|
||
|
|
yield files
|
||
|
|
|
||
|
|
for file in files:
|
||
|
|
file.close()
|
||
|
|
|
||
|
|
def path_in_temp_dir(self, path: Union[Path, str]) -> Path:
|
||
|
|
"""Place a path into the test case's temp dir.
|
||
|
|
|
||
|
|
This only works with a relative path; with an absolute path, this is a
|
||
|
|
no-op.
|
||
|
|
"""
|
||
|
|
return self.temp_dir_path / path
|
||
|
|
|
||
|
|
def paths_in_temp_dir(self, *paths: Union[Path, str]) -> List[Path]:
|
||
|
|
"""Place several paths into the test case's temp dir.
|
||
|
|
|
||
|
|
This only works with relative paths; with absolute paths, this is a
|
||
|
|
no-op.
|
||
|
|
"""
|
||
|
|
return [self.path_in_temp_dir(path) for path in paths]
|
||
|
|
|
||
|
|
|
||
|
|
class PwIdeTestCase(TempDirTestCase):
|
||
|
|
"""A test case for testing `pw_ide`.
|
||
|
|
|
||
|
|
Provides a temp dir for testing file system actions and access to IDE
|
||
|
|
settings that wrap the temp dir.
|
||
|
|
"""
|
||
|
|
|
||
|
|
def make_ide_settings(
|
||
|
|
self,
|
||
|
|
working_dir: Optional[Union[str, Path]] = None,
|
||
|
|
targets: Optional[List[str]] = None,
|
||
|
|
) -> PigweedIdeSettings:
|
||
|
|
"""Make settings that wrap provided paths in the temp path."""
|
||
|
|
|
||
|
|
if working_dir is not None:
|
||
|
|
working_dir_path = self.path_in_temp_dir(working_dir)
|
||
|
|
else:
|
||
|
|
working_dir_path = self.temp_dir_path
|
||
|
|
|
||
|
|
if targets is None:
|
||
|
|
targets = []
|
||
|
|
|
||
|
|
return PigweedIdeSettings(
|
||
|
|
False,
|
||
|
|
False,
|
||
|
|
False,
|
||
|
|
default_config={
|
||
|
|
'working_dir': str(working_dir_path),
|
||
|
|
'targets': targets,
|
||
|
|
},
|
||
|
|
)
|