From 6702a5abfd42b0c444d650f8f456962f6c7972be Mon Sep 17 00:00:00 2001 From: Zapta Date: Fri, 22 Nov 2024 11:19:34 -0800 Subject: [PATCH 01/13] More tests cleanup. This focudes on the 'examples' packages install/uninstall in the end to end test. --- test/commands/test_clean.py | 38 ++++++++--------- test/conftest.py | 83 ++++++++++++++++++++++++------------- test/test_end_to_end.py | 74 ++++++++++++++------------------- 3 files changed, 104 insertions(+), 91 deletions(-) diff --git a/test/commands/test_clean.py b/test/commands/test_clean.py index 1eff97c0..ff0c6701 100644 --- a/test/commands/test_clean.py +++ b/test/commands/test_clean.py @@ -2,6 +2,8 @@ Test for the "apio clean" command """ +from pathlib import Path + # -- apio clean entry point from apio.commands.clean import cli as cmd_clean @@ -29,9 +31,7 @@ def test_clean_no_apio_ini_no_params(click_cmd_runner, setup_apio_test_env): assert result.exit_code == 0, result.output -def test_clean_no_apio_ini_params( - click_cmd_runner, setup_apio_test_env, path_in_project -): +def test_clean_no_apio_ini_params(click_cmd_runner, setup_apio_test_env): """Test: apio clean when no apio.ini file is given. Board definition comes from --board parameter. """ @@ -42,28 +42,26 @@ def test_clean_no_apio_ini_params( setup_apio_test_env() # -- Create a legacy artifact file. - path_in_project("main_tb.vcd").touch() + Path("main_tb.vcd").touch() # -- Create a current artifact file. - path_in_project("_build").mkdir() - path_in_project("_build/main_tb.vcd").touch() + Path("_build").mkdir() + Path("_build/main_tb.vcd").touch() # Confirm that the files exists - assert path_in_project("main_tb.vcd").is_file() - assert path_in_project("_build/main_tb.vcd").is_file() + assert Path("main_tb.vcd").is_file() + assert Path("_build/main_tb.vcd").is_file() # -- Execute "apio clean --board alhambra-ii" result = click_cmd_runner.invoke(cmd_clean, ["--board", "alhambra-ii"]) assert result.exit_code == 0, result.output # Confirm that the files do not exist. - assert not path_in_project("main_tb.vcd").exists() - assert not path_in_project("_build/main_tb.vcd").exists() + assert not Path("main_tb.vcd").exists() + assert not Path("_build/main_tb.vcd").exists() -def test_clean_create( - click_cmd_runner, setup_apio_test_env, path_in_project, write_apio_ini -): +def test_clean_create(click_cmd_runner, setup_apio_test_env, write_apio_ini): """Test: apio clean when there is an apio.ini file""" with click_cmd_runner.isolated_filesystem(): @@ -75,20 +73,20 @@ def test_clean_create( write_apio_ini({"board": "icezum", "top-module": "main"}) # -- Create a legacy artifact file. - path_in_project("main_tb.vcd").touch() + Path("main_tb.vcd").touch() # -- Create a current artifact file. - path_in_project("_build").mkdir() - path_in_project("_build/main_tb.vcd").touch() + Path("_build").mkdir() + Path("_build/main_tb.vcd").touch() # Confirm that the files exists - assert path_in_project("main_tb.vcd").is_file() - assert path_in_project("_build/main_tb.vcd").is_file() + assert Path("main_tb.vcd").is_file() + assert Path("_build/main_tb.vcd").is_file() # --- Execute "apio clean" result = click_cmd_runner.invoke(cmd_clean) assert result.exit_code == 0, result.output # Confirm that the files do not exist. - assert not path_in_project("main_tb.vcd").exists() - assert not path_in_project("_build/main_tb.vcd").exists() + assert not Path("main_tb.vcd").exists() + assert not Path("_build/main_tb.vcd").exists() diff --git a/test/conftest.py b/test/conftest.py index 8574d0dd..629cb728 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -7,6 +7,7 @@ # https://docs.python.org/3/library/os.html#os.environ from os import environ, listdir from pathlib import Path +from dataclasses import dataclass from typing import Dict import pytest @@ -23,6 +24,26 @@ DEBUG = True +@dataclass(frozen=True) +class TestValues: + """Contains apio tests related values.""" + + test_dir: Path + home_dir: Path + packages_dir: Path + + @staticmethod + def get(): + """Returns a filled in TestValues object.""" + # -- Current directory is the project dir. + test_dir = Path.cwd() + # -- Using unicode and space to verify that they are handled correctly. + home_dir = test_dir / " ñ" + packages_dir = home_dir / "packages" + + return TestValues(test_dir, home_dir, packages_dir) + + @pytest.fixture(scope="module") def click_cmd_runner(): """A pytest fixture that provides tests with a click commands runner.""" @@ -37,22 +58,16 @@ def setup_apio_test_env(): """ def decorator(): - # -- Current directory is the project dir. - project_dir = Path.cwd() - - # -- Set a strange directory for executing - # -- apio: it contains spaces and unicode characters - # -- for testing. It should work - apio_home_dir = project_dir / " ñ" - apio_packages_dir = apio_home_dir / "packages" + test_values = TestValues.get() - # -- Debug if DEBUG: print("") print(" --> setup_apio_test_env():") - print(f" apio project dir : {str(project_dir)}") - print(f" apio home dir : {str(apio_home_dir)}") - print(f" apio packages dir : {str(apio_packages_dir)}") + print(f" test dir : {str(test_values.test_dir)}") + print(f" apio home dir : {str(test_values.home_dir)}") + print( + " apio packages dir : " f"{str(test_values.packages_dir)}" + ) # -- Since the test run in a fresh temp directory, we expect it to be # -- empty with no left over files (such as apio.ini) from a previous @@ -61,9 +76,11 @@ def decorator(): assert not project_dir_content, project_dir_content # -- Set the apio home dir and apio packages dir to - # -- this test folder - environ["APIO_HOME_DIR"] = str(apio_home_dir) - environ["APIO_PACKAGES_DIR"] = str(apio_packages_dir) + # -- this test folder. Apio uses these as an override to the defaults. + environ["APIO_HOME_DIR"] = str(test_values.home_dir) + environ["APIO_PACKAGES_DIR"] = str(test_values.packages_dir) + + # -- TODO: This looks like a flag. Describe what it do. environ["TESTING"] = "" return decorator @@ -113,20 +130,6 @@ def decorator(properties: Dict[str, str]): return decorator -@pytest.fixture(scope="session") -def path_in_project(): - """A pytest fixutre that provides a function that convert a file name - to a path within the project. - """ - - def decorator(name: str): - """The implementation""" - - return Path.cwd() / name - - return decorator - - # -- This function is called by pytest. It addes the pytest --offline flag # -- which is is passed to tests that ask for it using the fixture # -- 'offline_flag' below. @@ -150,3 +153,25 @@ def offline_flag(request): test functionality that requires internet connectivity. """ return request.config.getoption("--offline") + + +@pytest.fixture(scope="session") +def apio_home_dir(): + """A pytest fixture that provide function that returns a path to the test + apio home dir.""" + + def decorator(): + return TestValues.get().home_dir + + return decorator + + +@pytest.fixture(scope="session") +def apio_packages_dir(): + """A pytest fixture that provide function that returns a path to the test + apio packages dir.""" + + def decorator(): + return TestValues.get().packages_dir + + return decorator diff --git a/test/test_end_to_end.py b/test/test_end_to_end.py index f4ad9c2b..d548d946 100644 --- a/test/test_end_to_end.py +++ b/test/test_end_to_end.py @@ -2,7 +2,9 @@ Test different "apio" commands """ -import pathlib +from pathlib import Path +from os import listdir +from os.path import getsize import pytest @@ -13,33 +15,7 @@ from apio.commands.examples import cli as cmd_examples -def validate_files_leds(folder): - """Check that the ledon.v file is inside the given folder""" - - # -- File to check - leds = folder / pathlib.Path("ledon.v") - - # -- The file should exists and have a size greather than 0 - assert leds.exists() and leds.stat().st_size > 0 # getsize(leds) > 0 - - -def validate_dir_leds(folder=""): - """Check that the leds folder has been created in the - dir directory - """ - - # -- Get the leds path - leds_dir = folder / pathlib.Path("Alhambra-II/ledon") - - # -- Calculate the numer of files in the leds folder - nfiles = len(list(leds_dir.glob("*"))) - - # -- The folder should exist, and it should - # -- containe more than 0 files inside - assert leds_dir.is_dir() and nfiles > 0 - - -def test_end_to_end1( +def test_end_to_end_1( click_cmd_runner, assert_apio_cmd_ok, setup_apio_test_env, offline_flag ): """Test the installation of the examples package""" @@ -115,7 +91,7 @@ def test_end_to_end1( assert "examples" in result.output -def test_end_to_end2( +def test_end_to_end_2( click_cmd_runner, assert_apio_cmd_ok, setup_apio_test_env, offline_flag ): """Test more 'apio examples' commands""" @@ -172,7 +148,7 @@ def test_end_to_end2( assert_apio_cmd_ok(result) assert "Copying Alhambra-II/ledon example files ..." in result.output assert "have been successfully created!" in result.output - validate_files_leds(pathlib.Path()) + assert getsize("ledon.v") # -- Execute "apio examples --fetch-dir Alhambra-II/ledon" result = click_cmd_runner.invoke( @@ -181,7 +157,7 @@ def test_end_to_end2( assert_apio_cmd_ok(result) assert "Creating Alhambra-II/ledon directory ..." in result.output assert "has been successfully created" in result.output - validate_dir_leds() + assert listdir("Alhambra-II/ledon") # -- Execute "apio examples --fetch-dir Alhambra-II/ledon" result = click_cmd_runner.invoke( @@ -195,13 +171,17 @@ def test_end_to_end2( assert "Do you want to replace it?" in result.output assert "Creating Alhambra-II/ledon directory ..." in result.output assert "has been successfully created" in result.output - validate_dir_leds() + assert listdir("Alhambra-II/ledon") -def test_end_to_end3( - click_cmd_runner, assert_apio_cmd_ok, setup_apio_test_env, offline_flag +def test_examples_package( + click_cmd_runner, + assert_apio_cmd_ok, + setup_apio_test_env, + apio_packages_dir, + offline_flag, ): - """Test more 'apio examples' commands""" + """Test installation, use, and uninstallation of the 'examples' package.""" # -- If the option 'offline' is passed, the test is skip # -- (These tests require internet) @@ -213,6 +193,9 @@ def test_end_to_end3( # -- Config the apio test environment setup_apio_test_env() + # -- Tests starts with packages dir non existing. + assert not apio_packages_dir().exists() + # -- Execute "apio packages --install examples" result = click_cmd_runner.invoke( cmd_packages, ["--install", "examples"] @@ -221,13 +204,16 @@ def test_end_to_end3( assert "Installing package 'examples'" in result.output assert "Download" in result.output assert "Package 'examples' installed successfully" in result.output + assert getsize( + apio_packages_dir() / "examples/Alhambra-II/ledon/ledon.v" + ) # ------------------------------------------ # -- Check the --project-dir parameter # ------------------------------------------ # -- Create a tmp dir - p = pathlib.Path("tmp/") - p.mkdir(parents=True, exist_ok=True) + tmp_dir = Path("tmp") + tmp_dir.mkdir(parents=False, exist_ok=False) # -- Execute "apio examples --fetch-files Alhambra-II/ledon # -- --project-dir=tmp" @@ -238,9 +224,7 @@ def test_end_to_end3( assert_apio_cmd_ok(result) assert "Copying Alhambra-II/ledon example files ..." in result.output assert "have been successfully created!" in result.output - - # -- Check the files in the tmp folder - validate_files_leds(p) + assert getsize(tmp_dir / "ledon.v") # -- Execute # -- "apio examples --fetch-dir Alhambra-II/ledon --project-dir=tmp" @@ -251,14 +235,17 @@ def test_end_to_end3( assert_apio_cmd_ok(result) assert "Creating Alhambra-II/ledon directory ..." in result.output assert "has been successfully created" in result.output - validate_dir_leds("tmp") + assert getsize(tmp_dir / "Alhambra-II/ledon/ledon.v") - # -- Execute "apio packages --uninstall examples" + # -- Execute "apio packages --uninstall examples" and say no. result = click_cmd_runner.invoke( cmd_packages, ["--uninstall", "examples"], input="n" ) assert result.exit_code != 0, result.output assert "User said no" in result.output + assert getsize( + apio_packages_dir() / "examples/Alhambra-II/ledon/ledon.v" + ) # -- Execute "apio packages --uninstall examples" result = click_cmd_runner.invoke( @@ -268,3 +255,6 @@ def test_end_to_end3( assert "Uninstalling package 'examples'" in result.output assert "Do you want to uninstall 1 package?" in result.output assert "Package 'examples' uninstalled successfuly" in result.output + + # -- Packages dir should be empty now. + assert not listdir(apio_packages_dir()) From 6b2e3b2f9419b1ed003b6aa237b52b840f0ae240 Mon Sep 17 00:00:00 2001 From: Zapta Date: Fri, 22 Nov 2024 23:50:03 -0800 Subject: [PATCH 02/13] Addressing issue https://github.com/FPGAwars/apio/issues/473. Now specifying to the tar extractor a 'trusted_filter' mode, if the python version is greater or equal 12.0. We expect that this will preserve the existing tar default arvhining mode in future version of python. --- apio/managers/unpacker.py | 15 +++++++++++---- apio/util.py | 7 ++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/apio/managers/unpacker.py b/apio/managers/unpacker.py index c87b31b5..00c743cd 100644 --- a/apio/managers/unpacker.py +++ b/apio/managers/unpacker.py @@ -21,8 +21,9 @@ class ArchiveBase: """DOC: TODO""" - def __init__(self, arhfileobj): + def __init__(self, arhfileobj, is_tar_file: bool): self._afo = arhfileobj + self._is_tar_file = is_tar_file def get_items(self): # pragma: no cover """DOC: TODO""" @@ -34,7 +35,13 @@ def extract_item(self, item, dest_dir): if hasattr(item, "filename") and item.filename.endswith(".gitignore"): return - self._afo.extract(item, dest_dir) + if self._is_tar_file and util.get_python_ver_tuple() >= (3, 12, 0): + # -- Special case for avoiding the tar deprecation warning. Search + # -- 'extraction_filter' in the page + # -- https://docs.python.org/3/library/tarfile.html + self._afo.extract(item, dest_dir, filter="fully_trusted") + else: + self._afo.extract(item, dest_dir) self.after_extract(item, dest_dir) def after_extract(self, item, dest_dir): @@ -48,7 +55,7 @@ def __init__(self, archpath): # R1732: Consider using 'with' for resource-allocating operations # (consider-using-with) # pylint: disable=R1732 - ArchiveBase.__init__(self, tarfile_open(archpath)) + ArchiveBase.__init__(self, tarfile_open(archpath), is_tar_file=True) def get_items(self): return self._afo.getmembers() @@ -61,7 +68,7 @@ def __init__(self, archpath): # R1732: Consider using 'with' for resource-allocating operations # (consider-using-with) # pylint: disable=R1732 - ArchiveBase.__init__(self, ZipFile(archpath)) + ArchiveBase.__init__(self, ZipFile(archpath), is_tar_file=False) @staticmethod def preserve_permissions(item, dest_dir): diff --git a/apio/util.py b/apio/util.py index 2791c028..348c4f1b 100644 --- a/apio/util.py +++ b/apio/util.py @@ -15,7 +15,7 @@ import shutil from enum import Enum from dataclasses import dataclass -from typing import Optional, Any +from typing import Optional, Any, Tuple import subprocess from threading import Thread from pathlib import Path @@ -577,6 +577,11 @@ def get_python_version() -> str: return f"{sys.version_info[0]}.{sys.version_info[1]}" +def get_python_ver_tuple() -> Tuple[int, int, int]: + """Return a tuple with the python version. e.g. (3, 12, 1).""" + return sys.version_info[:3] + + def safe_click(text, *args, **kwargs): """Prints text to the console handling potential Unicode errors, forwarding any additional arguments to click.echo. This permits From 8e3f54bbc471b454ccbe6834f2a7442bf53cd198 Mon Sep 17 00:00:00 2001 From: Zapta Date: Sat, 23 Nov 2024 00:16:19 -0800 Subject: [PATCH 03/13] Changed the 'make test' target to skip online (slow) tests. The 'make check' and 'make check_all' stays the same and tests all tests, offline and online. --- Makefile | 10 ++++++---- tox.ini | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index c666b75c..2f208e20 100644 --- a/Makefile +++ b/Makefile @@ -22,13 +22,15 @@ lint: python -m tox -e lint -# Tests only, no lint, single python version. +# Offline tests only, no lint, single python version, skipping online tests. +# This is a partial but fast test. test: - python -m tox --skip-missing-interpreters false -e py312 + python -m tox --skip-missing-interpreters false -e py312 -- --offline -# Tests and lint, single python version. -# Run this before submitting code. +# Tests and lint, single python version, all tests including online.. +# This is a thorough but slow test and sufficient for testign before +# commiting changes run this before submitting code. check: python -m tox --skip-missing-interpreters false -e lint,py312 diff --git a/tox.ini b/tox.ini index acdfa137..13689452 100644 --- a/tox.ini +++ b/tox.ini @@ -73,7 +73,7 @@ deps = pytest-cov==5.0.0 commands = - python -m pytest --cov-report html --cov apio test + python -m pytest --cov-report html --cov apio test {posargs} # ---------------------------------------------------- From f881622a05266ba7fa1f9de0fa3cb7b97095dc58 Mon Sep 17 00:00:00 2001 From: Zapta Date: Sat, 23 Nov 2024 13:30:16 -0800 Subject: [PATCH 04/13] 'apio clean' now deletes also the .sconsign.dblite file an the _build directory. --- apio/scons/scons_util.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apio/scons/scons_util.py b/apio/scons/scons_util.py index e515b97c..2700434e 100644 --- a/apio/scons/scons_util.py +++ b/apio/scons/scons_util.py @@ -773,7 +773,12 @@ def set_up_cleanup(env: SConsEnvironment) -> None: # -- Get the list of all files to clean. Scons adds to the list non # -- existing files from other targets it encountered. - files_to_clean = env.Glob(f"{BUILD_DIR_SEP}*") + env.Glob("zadig.ini") + files_to_clean = ( + env.Glob(f"{BUILD_DIR_SEP}*") + + env.Glob("zadig.ini") + + env.Glob(".sconsign.dblite") + + env.Glob("_build") + ) # -- TODO: Remove the cleanup of legacy files after releasing the first # -- release with the _build directory. @@ -792,6 +797,7 @@ def set_up_cleanup(env: SConsEnvironment) -> None: "Deleting also left-over files from previous release.", fg="yellow", ) + files_to_clean.extend(legacy_files_to_clean) # -- Create a dummy target. I From d922eb4096fbaf50d616233380be7629e3f0c7af Mon Sep 17 00:00:00 2001 From: Zapta Date: Sun, 24 Nov 2024 08:18:02 -0800 Subject: [PATCH 05/13] Cleaned up the end to end test. It now covers the entire project developement process including building, linting, and testing. --- apio/apio_context.py | 5 + apio/pkg_util.py | 15 +- test/conftest.py | 94 ++++------ test/test_end_to_end.py | 400 +++++++++++++++++++++++++--------------- 4 files changed, 297 insertions(+), 217 deletions(-) diff --git a/apio/apio_context.py b/apio/apio_context.py index 8547a73d..d475fd65 100644 --- a/apio/apio_context.py +++ b/apio/apio_context.py @@ -91,6 +91,11 @@ def __init__( fg="yellow", ) + # -- A flag to indicate if the system env was already set in this + # -- apio session. Used to avoid multiple repeated settings that + # -- make the path longer and longer. + self.env_was_already_set = False + # -- Save the load project status. self._load_project = load_project diff --git a/apio/pkg_util.py b/apio/pkg_util.py index e7c4b5c7..24086133 100644 --- a/apio/pkg_util.py +++ b/apio/pkg_util.py @@ -117,8 +117,6 @@ def set_env_for_packages(apio_ctx: ApioContext, verbose: bool = False) -> None: The function sets the environment only on first call and in latter calls skips the operation silently. """ - # pylint: disable=global-statement - global __ENV_ALREADY_SET_FLAG # -- Collect the env mutations for all packages. mutations = _get_env_mutations_for_packages(apio_ctx) @@ -126,13 +124,14 @@ def set_env_for_packages(apio_ctx: ApioContext, verbose: bool = False) -> None: if verbose: _dump_env_mutations(apio_ctx, mutations) - # -- If this is the first call, apply the mutations. These mutations are - # -- temporary for the lifetime of this process and does not affect the - # -- user's shell environment. The mutations are also inheritated by - # -- child processes such as the scons processes. - if not __ENV_ALREADY_SET_FLAG: + # -- If this is the first call in this apio invocation, apply the + # -- mutations. These mutations are temporary for the lifetime of this + # -- process and does not affect the user's shell environment. + # -- The mutations are also inheritated by child processes such as the + # -- scons processes. + if not apio_ctx.env_was_already_set: _apply_env_mutations(mutations) - __ENV_ALREADY_SET_FLAG = True + apio_ctx.env_was_already_set = True if not verbose: click.secho("Setting the envinronment.") diff --git a/test/conftest.py b/test/conftest.py index 629cb728..a6097477 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -7,7 +7,6 @@ # https://docs.python.org/3/library/os.html#os.environ from os import environ, listdir from pathlib import Path -from dataclasses import dataclass from typing import Dict import pytest @@ -24,26 +23,6 @@ DEBUG = True -@dataclass(frozen=True) -class TestValues: - """Contains apio tests related values.""" - - test_dir: Path - home_dir: Path - packages_dir: Path - - @staticmethod - def get(): - """Returns a filled in TestValues object.""" - # -- Current directory is the project dir. - test_dir = Path.cwd() - # -- Using unicode and space to verify that they are handled correctly. - home_dir = test_dir / " ñ" - packages_dir = home_dir / "packages" - - return TestValues(test_dir, home_dir, packages_dir) - - @pytest.fixture(scope="module") def click_cmd_runner(): """A pytest fixture that provides tests with a click commands runner.""" @@ -55,34 +34,57 @@ def setup_apio_test_env(): """An pytest fixture that provides tests with a function to set up the apio test environment. By default, the tests run in a temporaly folder (in /tmp/xxxxx). + + Should be called within the click_cmd_runner.isolated_filesystem() scope. """ def decorator(): - test_values = TestValues.get() + # -- Current directory is the root test dir. Should be empty. + test_dir = Path.cwd() + assert not listdir(test_dir) + + # -- Using unicode and space to verify that they are handled correctly. + # funny_marker = " fuññy " + funny_marker = "fuññy" + funny_dir = test_dir / funny_marker + funny_dir.mkdir(parents=False, exist_ok=False) + + # -- Apio dirs + apio_proj_dir = funny_dir / "proj" + apio_home_dir = funny_dir / "apio" + apio_packages_dir = apio_home_dir / "packages" if DEBUG: print("") print(" --> setup_apio_test_env():") - print(f" test dir : {str(test_values.test_dir)}") - print(f" apio home dir : {str(test_values.home_dir)}") - print( - " apio packages dir : " f"{str(test_values.packages_dir)}" - ) - - # -- Since the test run in a fresh temp directory, we expect it to be - # -- empty with no left over files (such as apio.ini) from a previous - # -- tests. - project_dir_content = listdir(".") - assert not project_dir_content, project_dir_content + print(f" test dir : {str(test_dir)}") + print(f" apio proj dir : {str(apio_proj_dir)}") + print(f" apio home dir : {str(apio_home_dir)}") + print(f" apio packages dir : {str(apio_packages_dir)}") + + # pylint: disable=fixme + # TODO: solve the problem of the over growing PATH because we run + # multiple apio invocations within one pytest process. + print() + print(f"PATH={environ['PATH']}") + print() # -- Set the apio home dir and apio packages dir to # -- this test folder. Apio uses these as an override to the defaults. - environ["APIO_HOME_DIR"] = str(test_values.home_dir) - environ["APIO_PACKAGES_DIR"] = str(test_values.packages_dir) + environ["APIO_HOME_DIR"] = str(apio_home_dir) + environ["APIO_PACKAGES_DIR"] = str(apio_packages_dir) # -- TODO: This looks like a flag. Describe what it do. environ["TESTING"] = "" + # -- Apio dirs do not exist yet. + assert not apio_proj_dir.exists() + assert not apio_home_dir.exists() + assert not apio_packages_dir.exists() + + # -- All done, return the values. + return (apio_proj_dir, apio_home_dir, apio_packages_dir) + return decorator @@ -153,25 +155,3 @@ def offline_flag(request): test functionality that requires internet connectivity. """ return request.config.getoption("--offline") - - -@pytest.fixture(scope="session") -def apio_home_dir(): - """A pytest fixture that provide function that returns a path to the test - apio home dir.""" - - def decorator(): - return TestValues.get().home_dir - - return decorator - - -@pytest.fixture(scope="session") -def apio_packages_dir(): - """A pytest fixture that provide function that returns a path to the test - apio packages dir.""" - - def decorator(): - return TestValues.get().packages_dir - - return decorator diff --git a/test/test_end_to_end.py b/test/test_end_to_end.py index d548d946..d54082ba 100644 --- a/test/test_end_to_end.py +++ b/test/test_end_to_end.py @@ -2,259 +2,355 @@ Test different "apio" commands """ -from pathlib import Path -from os import listdir +from os import listdir, chdir from os.path import getsize +from pathlib import Path import pytest # -- Entry point for apio commands. -from apio.commands.packages import cli as cmd_packages -from apio.commands.create import cli as cmd_create -from apio.commands.upload import cli as cmd_upload -from apio.commands.examples import cli as cmd_examples - - -def test_end_to_end_1( - click_cmd_runner, assert_apio_cmd_ok, setup_apio_test_env, offline_flag +from apio.commands.raw import cli as apio_raw +from apio.commands.upgrade import cli as apio_upgrade +from apio.commands.system import cli as apio_system +from apio.commands.clean import cli as apio_clean +from apio.commands.graph import cli as apio_graph +from apio.commands.test import cli as apio_test +from apio.commands.report import cli as apio_report +from apio.commands.lint import cli as apio_lint +from apio.commands.build import cli as apio_build +from apio.commands.packages import cli as apio_packages +from apio.commands.examples import cli as apio_examples + + +def test_utilities( + click_cmd_runner, + setup_apio_test_env, + assert_apio_cmd_ok, + offline_flag, ): - """Test the installation of the examples package""" + """Tests utility commands.""" # -- If the option 'offline' is passed, the test is skip - # -- (These tests require internet) + # -- (This test is slow and requires internet connectivity) if offline_flag: pytest.skip("requires internet connection") with click_cmd_runner.isolated_filesystem(): - # -- Config the apio test environment - setup_apio_test_env() + # -- Config the apio test environment. + proj_dir, _, packages_dir = setup_apio_test_env() - # -- Execute "apio packages --uninstall examples" - result = click_cmd_runner.invoke( - cmd_packages, ["--uninstall", "examples"], input="y" - ) - assert "Do you want to uninstall 1 package?" in result.output - assert "Package 'examples' was not installed" in result.output + # -- Create and change to project dir. + proj_dir.mkdir(exist_ok=False) + chdir(proj_dir) - # -- Execute "apio packages --install examples@X" + # -- Install all packages result = click_cmd_runner.invoke( - cmd_packages, ["--install", "examples@X"] + apio_packages, ["--install", "--verbose"] ) - assert "Error: package not found" in result.output + assert_apio_cmd_ok(result) + assert "'examples' installed successfully" in result.output + assert "'oss-cad-suite' installed successfully" in result.output + assert listdir(packages_dir / "examples") + assert listdir(packages_dir / "tools-oss-cad-suite") - # -- Execute "apio packages --install examples@0.0.34" - result = click_cmd_runner.invoke( - cmd_packages, ["--install", "examples@0.0.34"] - ) + # -- Run 'apio upgrade' + result = click_cmd_runner.invoke(apio_upgrade) assert_apio_cmd_ok(result) - assert "Installing package 'examples@" in result.output - assert "Download" in result.output - assert "Package 'examples' installed successfully" in result.output + assert "Lastest Apio stable version" in result.output + + # -- Run 'apio system --info' + result = click_cmd_runner.invoke(apio_system, ["--info"]) + assert_apio_cmd_ok(result) + assert "Apio version" in result.output - # -- Execute "apio packages --install examples" + # -- Run 'apio raw --env "nextpnr-ice40 --help" result = click_cmd_runner.invoke( - cmd_packages, ["--install", "examples"] + apio_raw, ["--env", "nextpnr-ice40 --help"], input="exit" ) assert_apio_cmd_ok(result) - assert "Installing package 'examples'" in result.output - assert "Download" in result.output - assert "Package 'examples' installed successfully" in result.output - # -- Execute "apio packages --install examples" again + +def test_project_ice40( + click_cmd_runner, + setup_apio_test_env, + assert_apio_cmd_ok, + offline_flag, +): + """Tests building and testing a project.""" + + # -- If the option 'offline' is passed, the test is skip + # -- (This test is slow and requires internet connectivity) + if offline_flag: + pytest.skip("requires internet connection") + + with click_cmd_runner.isolated_filesystem(): + + # -- Config the apio test environment. + proj_dir, _, packages_dir = setup_apio_test_env() + + # -- Create and change to project dir. + proj_dir.mkdir(exist_ok=False) + chdir(proj_dir) + + # -- Install all packages result = click_cmd_runner.invoke( - cmd_packages, ["--install", "examples"] + apio_packages, ["--install", "--verbose"] ) assert_apio_cmd_ok(result) - assert "Installing package 'examples'" in result.output - assert "was already installed" in result.output + assert "'examples' installed successfully" in result.output + assert "'oss-cad-suite' installed successfully" in result.output + assert listdir(packages_dir / "examples") + assert listdir(packages_dir / "tools-oss-cad-suite") - # -- Execute "apio packages --install examples --force" + # -- The current proj directory should be still empty + assert not listdir(".") + + # -- Fetch example files to current directory result = click_cmd_runner.invoke( - cmd_packages, - [ - "--install", - "examples", - "--force", - ], + apio_examples, + ["--fetch-files", "Alhambra-II/ledon"], ) assert_apio_cmd_ok(result) - assert "Installing package 'examples'" in result.output - assert "Download" in result.output - assert "Package 'examples' installed successfully" in result.output + assert "Copying Alhambra-II/ledon example files" in result.output + assert "have been successfully created!" in result.output + assert getsize("apio.ini") - # -- Execute "apio packages --list" - result = click_cmd_runner.invoke(cmd_packages, ["--list"]) - assert result.exit_code == 0, result.output - assert "No errors" in result.output - assert "Installed packages:" in result.output - assert "examples" in result.output + # -- Remember the list of project files. + project_files = listdir(".") + + # -- Build the project. + result = click_cmd_runner.invoke(apio_build) + assert_apio_cmd_ok(result) + assert "SUCCESS" in result.output + assert getsize("_build/hardware.bin") + + # -- Lint + result = click_cmd_runner.invoke(apio_lint) + assert_apio_cmd_ok(result) + assert "SUCCESS" in result.output + assert getsize("_build/hardware.vlt") + + # -- Test + result = click_cmd_runner.invoke(apio_test) + assert_apio_cmd_ok(result) + assert "SUCCESS" in result.output + assert getsize("_build/ledon_tb.out") + assert getsize("_build/ledon_tb.vcd") + # -- Report + result = click_cmd_runner.invoke(apio_report) + assert_apio_cmd_ok(result) + assert "SUCCESS" in result.output + assert "ICESTORM_LC:" in result.output + assert getsize("_build/hardware.pnr") + + # -- Graph svg + result = click_cmd_runner.invoke(apio_graph) + assert_apio_cmd_ok(result) + assert "SUCCESS" in result.output + assert getsize("_build/hardware.dot") + assert getsize("_build/hardware.svg") + + # -- Clean + result = click_cmd_runner.invoke(apio_clean) + assert_apio_cmd_ok(result) + assert "SUCCESS" in result.output + assert not Path("_build").exists() + + # -- Check that we have exactly the original project files, + assert set(listdir(".")) == set(project_files) -def test_end_to_end_2( - click_cmd_runner, assert_apio_cmd_ok, setup_apio_test_env, offline_flag + +# # R0915: Too many statements (52/50) (too-many-statements) +# # pylint: disable=R0915 +def test_packages( + click_cmd_runner, + setup_apio_test_env, + assert_apio_cmd_ok, + offline_flag, ): - """Test more 'apio examples' commands""" + """Tests listing, installation and uninstallation of packages.""" # -- If the option 'offline' is passed, the test is skip - # -- (These tests require internet) + # -- (This test is slow and requires internet connectivity) if offline_flag: pytest.skip("requires internet connection") with click_cmd_runner.isolated_filesystem(): # -- Config the apio test environment - setup_apio_test_env() + proj_dir, _, packages_dir = setup_apio_test_env() - # -- Execute "apio create --board alhambra-ii" - result = click_cmd_runner.invoke( - cmd_create, ["--board", "alhambra-ii"] - ) - assert_apio_cmd_ok(result) - assert "Creating apio.ini file ..." in result.output - assert "was created successfully" in result.output + # -- Create and change to project dir. + proj_dir.mkdir(exist_ok=False) + chdir(proj_dir) + + # -- List packages + result = click_cmd_runner.invoke(apio_packages, ["--list"]) + assert result.exit_code == 0 + assert "No errors" in result.output + assert "examples" in result.output + assert "oss-cad-suite" in result.output - # -- Execute "apio upload" - result = click_cmd_runner.invoke(cmd_upload) - assert result.exit_code == 1, result.output - assert "package 'oss-cad-suite' is not installed" in result.output + # -- Packages dir doesn't exist yet. + assert not packages_dir.exists() - # -- Execute "apio packages --install examples" + # -- Install the examples package. Package 'examples' should exist, + # -- and package 'tools-oss-cad-suite' should not. result = click_cmd_runner.invoke( - cmd_packages, ["--install", "examples"] + apio_packages, ["--install", "examples"] ) assert_apio_cmd_ok(result) - assert "Installing package 'examples'" in result.output - assert "Download" in result.output assert "Package 'examples' installed successfully" in result.output + assert listdir(packages_dir / "examples/Alhambra-II") + assert "tools-oss-cad-suite" not in listdir(packages_dir) - # -- Execute "apio examples --list" - result = click_cmd_runner.invoke(cmd_examples, ["--list"]) + # -- Install the reset of the packages. + # -- Both 'examples' and 'tools-oss-cad-suite' should exist, and + # -- maybe others, depending on the platform. + result = click_cmd_runner.invoke(apio_packages, ["--install"]) assert_apio_cmd_ok(result) - assert "leds" in result.output - assert "icezum" in result.output - - # -- Execute "apio examples --fetch-files missing_example" + assert "Package 'examples' installed successfully" not in result.output + assert ( + "Package 'oss-cad-suite' installed successfully" in result.output + ) + assert listdir(packages_dir / "examples/Alhambra-II") + assert listdir(packages_dir / "tools-oss-cad-suite/bin") + + # -- Delete a file from the examples package, we will use it as an + # -- indicator for the reinstallation of the package. + marker_file = packages_dir / "examples/Alhambra-II/ledon/ledon.v" + assert marker_file.is_file() + marker_file.unlink() + assert not marker_file.exists() + + # -- Install the examples packages without forcing. + # -- This should not do anything since it's considered to be installed. result = click_cmd_runner.invoke( - cmd_examples, ["--fetch-files", "missing_example"] + apio_packages, ["--install", "examples"] ) - assert result.exit_code == 1, result.output - assert "Warning: this example does not exist" in result.output + assert_apio_cmd_ok(result) + assert "was already install" in result.output + assert "Package 'examples' installed" not in result.output + assert not marker_file.exists() - # -- Execute "apio examples --fetch-files Alhambra-II/ledon" + # -- Install the examples packages with forcing. + # -- This should recover the file. result = click_cmd_runner.invoke( - cmd_examples, ["--fetch-files", "Alhambra-II/ledon"] + apio_packages, ["--install", "--force", "examples"] ) assert_apio_cmd_ok(result) - assert "Copying Alhambra-II/ledon example files ..." in result.output - assert "have been successfully created!" in result.output - assert getsize("ledon.v") + assert "Package 'examples' installed" in result.output + assert marker_file.is_file() - # -- Execute "apio examples --fetch-dir Alhambra-II/ledon" + # -- Try to uninstall the 'examples' package without user approval. + # -- should exit with an error message. + assert "examples" in listdir(packages_dir) result = click_cmd_runner.invoke( - cmd_examples, ["--fetch-dir", "Alhambra-II/ledon"] + apio_packages, ["--uninstall", "examples"], input="n" ) - assert_apio_cmd_ok(result) - assert "Creating Alhambra-II/ledon directory ..." in result.output - assert "has been successfully created" in result.output - assert listdir("Alhambra-II/ledon") + assert result.exit_code == 1 + assert "User said no" in result.output + assert "examples" in listdir(packages_dir) + assert "tools-oss-cad-suite" in listdir(packages_dir) - # -- Execute "apio examples --fetch-dir Alhambra-II/ledon" + # -- Uninstall the examples package. It should delete the exemples + # -- package and will live the rest. + assert "examples" in listdir(packages_dir) result = click_cmd_runner.invoke( - cmd_examples, ["--fetch-dir", "Alhambra-II/ledon"], input="y" + apio_packages, ["--uninstall", "examples"], input="y" ) assert_apio_cmd_ok(result) - assert ( - "Warning: Alhambra-II/ledon directory already exists" - in result.output + assert "examples" not in listdir(packages_dir) + assert "tools-oss-cad-suite" in listdir(packages_dir) + + # -- Uninstall all packages. This should uninstall also the + # -- oss-cad-suite package. + result = click_cmd_runner.invoke( + apio_packages, ["--uninstall", "--sayyes"] ) - assert "Do you want to replace it?" in result.output - assert "Creating Alhambra-II/ledon directory ..." in result.output - assert "has been successfully created" in result.output - assert listdir("Alhambra-II/ledon") + assert_apio_cmd_ok(result) + assert "examples" not in listdir(packages_dir) + assert "tools-oss-cad-suite" not in listdir(packages_dir) -def test_examples_package( +def test_examples( click_cmd_runner, - assert_apio_cmd_ok, setup_apio_test_env, - apio_packages_dir, + assert_apio_cmd_ok, offline_flag, ): - """Test installation, use, and uninstallation of the 'examples' package.""" + """Tests the listing and fetching apio examples.""" # -- If the option 'offline' is passed, the test is skip - # -- (These tests require internet) + # -- (This test is slow and requires internet connectivity) if offline_flag: pytest.skip("requires internet connection") with click_cmd_runner.isolated_filesystem(): # -- Config the apio test environment - setup_apio_test_env() + proj_dir, _, packages_dir = setup_apio_test_env() - # -- Tests starts with packages dir non existing. - assert not apio_packages_dir().exists() + # -- Create and change to project dir. + proj_dir.mkdir(exist_ok=False) + chdir(proj_dir) - # -- Execute "apio packages --install examples" + # -- Install the examples package. result = click_cmd_runner.invoke( - cmd_packages, ["--install", "examples"] + apio_packages, ["--install", "examples"] ) assert_apio_cmd_ok(result) - assert "Installing package 'examples'" in result.output - assert "Download" in result.output + # assert "Installing package 'examples'" in result.output + # assert "Download" in result.output assert "Package 'examples' installed successfully" in result.output - assert getsize( - apio_packages_dir() / "examples/Alhambra-II/ledon/ledon.v" - ) + assert getsize(packages_dir / "examples/Alhambra-II/ledon/ledon.v") - # ------------------------------------------ - # -- Check the --project-dir parameter - # ------------------------------------------ - # -- Create a tmp dir - tmp_dir = Path("tmp") - tmp_dir.mkdir(parents=False, exist_ok=False) + # -- List the examples + result = click_cmd_runner.invoke( + apio_examples, + ["--list"], + ) + assert_apio_cmd_ok(result) + assert "Alhambra-II/ledon" in result.output - # -- Execute "apio examples --fetch-files Alhambra-II/ledon - # -- --project-dir=tmp" + # -- Fetch example files to current directory result = click_cmd_runner.invoke( - cmd_examples, - ["--fetch-files", "Alhambra-II/ledon", "--project-dir=tmp"], + apio_examples, + ["--fetch-files", "Alhambra-II/ledon"], ) assert_apio_cmd_ok(result) - assert "Copying Alhambra-II/ledon example files ..." in result.output + assert "Copying Alhambra-II/ledon example files" in result.output assert "have been successfully created!" in result.output - assert getsize(tmp_dir / "ledon.v") + assert getsize("ledon.v") - # -- Execute - # -- "apio examples --fetch-dir Alhambra-II/ledon --project-dir=tmp" + # -- Fetch example dir to current directory result = click_cmd_runner.invoke( - cmd_examples, - ["--fetch-dir", "Alhambra-II/ledon", "--project-dir=tmp"], + apio_examples, + ["--fetch-dir", "Alhambra-II/ledon"], ) assert_apio_cmd_ok(result) - assert "Creating Alhambra-II/ledon directory ..." in result.output + assert "Creating Alhambra-II/ledon directory" in result.output assert "has been successfully created" in result.output - assert getsize(tmp_dir / "Alhambra-II/ledon/ledon.v") + assert getsize("Alhambra-II/ledon/ledon.v") - # -- Execute "apio packages --uninstall examples" and say no. + # -- Fetch example files to another project dir result = click_cmd_runner.invoke( - cmd_packages, ["--uninstall", "examples"], input="n" - ) - assert result.exit_code != 0, result.output - assert "User said no" in result.output - assert getsize( - apio_packages_dir() / "examples/Alhambra-II/ledon/ledon.v" + apio_examples, + ["--fetch-files", "Alhambra-II/ledon", "--project-dir=./dir1"], ) + assert_apio_cmd_ok(result) + assert "Copying Alhambra-II/ledon example files" in result.output + assert "have been successfully created!" in result.output + assert getsize("dir1/ledon.v") - # -- Execute "apio packages --uninstall examples" + # -- Fetch example dir to another project dir result = click_cmd_runner.invoke( - cmd_packages, ["--uninstall", "examples"], input="y" + apio_examples, + ["--fetch-dir", "Alhambra-II/ledon", "--project-dir=dir2"], ) assert_apio_cmd_ok(result) - assert "Uninstalling package 'examples'" in result.output - assert "Do you want to uninstall 1 package?" in result.output - assert "Package 'examples' uninstalled successfuly" in result.output - - # -- Packages dir should be empty now. - assert not listdir(apio_packages_dir()) + assert "Creating Alhambra-II/ledon directory" in result.output + assert "has been successfully created" in result.output + assert getsize("dir2/Alhambra-II/ledon/ledon.v") From e5f5897ffe212226589a6b20888052dcf6c83e07 Mon Sep 17 00:00:00 2001 From: Zapta Date: Sun, 24 Nov 2024 13:30:18 -0800 Subject: [PATCH 06/13] Added a TODO to conftest.py (regarding white space in packages dir). --- test/conftest.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/conftest.py b/test/conftest.py index a6097477..faa0eb51 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -43,16 +43,19 @@ def decorator(): test_dir = Path.cwd() assert not listdir(test_dir) + # -- TODO: Having a space in the funny directory name fails + # -- the test. Fix it and change to " fuññy ". The problem seems to be + # -- in the invocation of iverilog by 'apio test' when the packges dir + # -- contain a space. + # # -- Using unicode and space to verify that they are handled correctly. - # funny_marker = " fuññy " - funny_marker = "fuññy" - funny_dir = test_dir / funny_marker + funny_dir = test_dir / "fuññy" funny_dir.mkdir(parents=False, exist_ok=False) # -- Apio dirs apio_proj_dir = funny_dir / "proj" apio_home_dir = funny_dir / "apio" - apio_packages_dir = apio_home_dir / "packages" + apio_packages_dir = funny_dir / "packages" if DEBUG: print("") From b60f6dcf6c1d0e0b05e7c26037249079bf1d5984 Mon Sep 17 00:00:00 2001 From: Zapta Date: Sun, 24 Nov 2024 14:01:54 -0800 Subject: [PATCH 07/13] Renamed test variables for clarity. No semantic change. --- test-boards/Alhambra-II/test_leds.py | 16 ++++---- test/commands/test_boards.py | 6 +-- test/commands/test_build.py | 58 ++++++++++++++-------------- test/commands/test_clean.py | 14 ++++--- test/commands/test_create.py | 14 +++---- test/commands/test_drivers.py | 6 +-- test/commands/test_examples.py | 10 ++--- test/commands/test_fpgas.py | 6 +-- test/commands/test_graph.py | 10 ++--- test/commands/test_install.py | 8 ++-- test/commands/test_lint.py | 4 +- test/commands/test_modify.py | 12 +++--- test/commands/test_packages.py | 10 ++--- test/commands/test_report.py | 6 +-- test/commands/test_sim.py | 4 +- test/commands/test_system.py | 12 +++--- test/commands/test_test.py | 4 +- test/commands/test_time.py | 6 +-- test/commands/test_uninstall.py | 8 ++-- test/commands/test_upgrade.py | 4 +- test/commands/test_upload.py | 20 +++++----- test/commands/test_verify.py | 4 +- 22 files changed, 124 insertions(+), 118 deletions(-) diff --git a/test-boards/Alhambra-II/test_leds.py b/test-boards/Alhambra-II/test_leds.py index e4d54187..a253a29a 100644 --- a/test-boards/Alhambra-II/test_leds.py +++ b/test-boards/Alhambra-II/test_leds.py @@ -10,16 +10,16 @@ from click.testing import CliRunner # -- apio build entry point -from apio.commands.build import cli as cmd_build +from apio.commands.build import cli as apio_build # -- apio clean entry point -from apio.commands.clean import cli as cmd_clean +from apio.commands.clean import cli as apio_clean # -- apio verify entry point -from apio.commands.verify import cli as cmd_verify +from apio.commands.verify import cli as apio_verify # -- apio time entry point -from apio.commands.upload import cli as cmd_upload +from apio.commands.upload import cli as apio_upload # ------------------------------------------- @@ -42,7 +42,7 @@ def test_ledon_clean(): # ---------------------------- # -- Execute "apio clean" # ---------------------------- - result = CliRunner().invoke(cmd_clean) + result = CliRunner().invoke(apio_clean) # -- It should return an exit code of 0: success assert result.exit_code == 0, result.output @@ -55,7 +55,7 @@ def test_ledon_build(): # ---------------------------- # -- Execute "apio build" # ---------------------------- - result = CliRunner().invoke(cmd_build) + result = CliRunner().invoke(apio_build) # -- It should return an exit code of 0: success assert result.exit_code == 0, result.output @@ -71,7 +71,7 @@ def test_ledon_verify(): # ---------------------------- # -- Execute "apio verify" # ---------------------------- - result = CliRunner().invoke(cmd_verify) + result = CliRunner().invoke(apio_verify) # -- It should return an exit code of 0: success assert result.exit_code == 0, result.output @@ -85,7 +85,7 @@ def test_ledon_upload(): # ---------------------------- # -- Execute "apio upload" # ---------------------------- - result = CliRunner().invoke(cmd_upload) + result = CliRunner().invoke(apio_upload) # -- It should return an exit code of 0: success assert result.exit_code == 0, result.output diff --git a/test/commands/test_boards.py b/test/commands/test_boards.py index 4bc9d75c..95a93bf1 100644 --- a/test/commands/test_boards.py +++ b/test/commands/test_boards.py @@ -3,7 +3,7 @@ """ # -- apio boards entry point -from apio.commands.boards import cli as cmd_boards +from apio.commands.boards import cli as apio_boards CUSTOM_BOARDS = """ { @@ -34,7 +34,7 @@ def test_list_ok(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): setup_apio_test_env() # -- Execute "apio boards" - result = click_cmd_runner.invoke(cmd_boards) + result = click_cmd_runner.invoke(apio_boards) assert_apio_cmd_ok(result) # -- Note: pytest sees the piped version of the command's output. # -- Run 'apio build' | cat' to reproduce it. @@ -59,7 +59,7 @@ def test_custom_board( f.write(CUSTOM_BOARDS) # -- Execute "apio boards" - result = click_cmd_runner.invoke(cmd_boards) + result = click_cmd_runner.invoke(apio_boards) assert_apio_cmd_ok(result) # -- Note: pytest sees the piped version of the command's output. # -- Run 'apio build' | cat' to reproduce it. diff --git a/test/commands/test_build.py b/test/commands/test_build.py index 2ef5f8fc..9232f001 100644 --- a/test/commands/test_build.py +++ b/test/commands/test_build.py @@ -3,7 +3,7 @@ """ # -- apio build entry point -from apio.commands.build import cli as cmd_build +from apio.commands.build import cli as apio_build # pylint: disable=too-many-statements @@ -17,41 +17,41 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # -- Execute "apio build" - result = click_cmd_runner.invoke(cmd_build) + result = click_cmd_runner.invoke(apio_build) assert result.exit_code != 0, result.output assert "Info: Project has no apio.ini file" in result.output assert "Error: insufficient arguments: missing board" in result.output assert "Error: Missing FPGA" in result.output # apio build --board icestick - result = click_cmd_runner.invoke(cmd_build, ["--board", "icestick"]) + result = click_cmd_runner.invoke(apio_build, ["--board", "icestick"]) assert result.exit_code == 1, result.output assert "apio packages --install --force oss-cad-suite" in result.output # apio build --fpga iCE40-HX1K-VQ100 result = click_cmd_runner.invoke( - cmd_build, ["--fpga", "iCE40-HX1K-VQ100"] + apio_build, ["--fpga", "iCE40-HX1K-VQ100"] ) assert result.exit_code == 1, result.output assert "apio packages --install --force oss-cad-suite" in result.output # apio build --type lp --size 8k --pack cm225:4k result = click_cmd_runner.invoke( - cmd_build, ["--type", "lp", "--size", "8k", "--pack", "cm225:4k"] + apio_build, ["--type", "lp", "--size", "8k", "--pack", "cm225:4k"] ) assert result.exit_code == 1, result.output assert "Error: insufficient arguments" in result.output # apio build --board icezum --size 1k result = click_cmd_runner.invoke( - cmd_build, ["--board", "icezum", "--size", "1k"] + apio_build, ["--board", "icezum", "--size", "1k"] ) assert result.exit_code != 0, result.output assert "apio packages --install --force oss-cad-suite" in result.output # apio build --board icezum --fpga iCE40-HX1K-TQ144 --type hx result = click_cmd_runner.invoke( - cmd_build, + apio_build, [ "--board", "icezum", @@ -66,14 +66,14 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): # apio build --board icezum --pack tq144 result = click_cmd_runner.invoke( - cmd_build, ["--board", "icezum", "--pack", "tq144"] + apio_build, ["--board", "icezum", "--pack", "tq144"] ) assert result.exit_code != 0, result.output assert "apio packages --install --force oss-cad-suite" in result.output # apio build --fpga iCE40-HX1K-TQ144 --pack tq144 --size 1k result = click_cmd_runner.invoke( - cmd_build, + apio_build, ["--fpga", "iCE40-HX1K-TQ144", "--pack", "tq144", "--size", "1k"], ) assert result.exit_code != 0, result.output @@ -81,14 +81,14 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): # apio build --fpga iCE40-HX1K-TQ144 --type hx result = click_cmd_runner.invoke( - cmd_build, ["--fpga", "iCE40-HX1K-TQ144", "--type", "hx"] + apio_build, ["--fpga", "iCE40-HX1K-TQ144", "--type", "hx"] ) assert result.exit_code != 0, result.output assert "apio packages --install --force oss-cad-suite" in result.output # apio build --board icezum --size 8k result = click_cmd_runner.invoke( - cmd_build, ["--board", "icezum", "--size", "8k"] + apio_build, ["--board", "icezum", "--size", "8k"] ) assert result.exit_code != 0, result.output assert ( @@ -98,7 +98,7 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): # apio build --board icezum --fpga iCE40-HX1K-TQ144 --type lp result = click_cmd_runner.invoke( - cmd_build, + apio_build, [ "--board", "icezum", @@ -116,7 +116,7 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): # apio build --board icezum --fpga iCE40-HX1K-VQ100 result = click_cmd_runner.invoke( - cmd_build, ["--board", "icezum", "--fpga", "iCE40-HX1K-VQ100"] + apio_build, ["--board", "icezum", "--fpga", "iCE40-HX1K-VQ100"] ) assert result.exit_code != 0, result.output assert ( @@ -126,7 +126,7 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): # apio build --fpga iCE40-HX1K-TQ144 --type lp --size 8k result = click_cmd_runner.invoke( - cmd_build, + apio_build, ["--fpga", "iCE40-HX1K-TQ144", "--type", "lp", "--size", "8k"], ) assert result.exit_code != 0, result.output @@ -137,7 +137,7 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): # apio build --fpga iCE40-HX1K-TQ144 --pack vq100 result = click_cmd_runner.invoke( - cmd_build, ["--fpga", "iCE40-HX1K-TQ144", "--pack", "vq100"] + apio_build, ["--fpga", "iCE40-HX1K-TQ144", "--pack", "vq100"] ) assert result.exit_code != 0, result.output assert ( @@ -147,7 +147,7 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): # apio build --board icezum --pack vq100 result = click_cmd_runner.invoke( - cmd_build, ["--board", "icezum", "--pack", "vq100"] + apio_build, ["--board", "icezum", "--pack", "vq100"] ) assert result.exit_code != 0, result.output assert ( @@ -156,7 +156,7 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): ) # apio build --size 8k - result = click_cmd_runner.invoke(cmd_build, ["--size", "8k"]) + result = click_cmd_runner.invoke(apio_build, ["--size", "8k"]) assert result.exit_code != 0, result.output assert "Error: insufficient arguments" in result.output @@ -170,44 +170,44 @@ def test_errors_without_apio_ini_2(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # apio build --type lp - result = click_cmd_runner.invoke(cmd_build, ["--type", "lp"]) + result = click_cmd_runner.invoke(apio_build, ["--type", "lp"]) assert result.exit_code != 0, result.output assert "Error: insufficient arguments" in result.output # apio build --type lp --size 8k result = click_cmd_runner.invoke( - cmd_build, ["--type", "lp", "--size", "8k"] + apio_build, ["--type", "lp", "--size", "8k"] ) assert result.exit_code != 0, result.output assert "Error: insufficient arguments" in result.output # apio build --board icefake - result = click_cmd_runner.invoke(cmd_build, ["--board", "icefake"]) + result = click_cmd_runner.invoke(apio_build, ["--board", "icefake"]) assert result.exit_code != 0, result.output assert "Error: unknown board: icefake" in result.output # apio build --board icefake --fpga iCE40-HX1K-TQ144 result = click_cmd_runner.invoke( - cmd_build, ["--board", "icefake", "--fpga", "iCE40-HX1K-TQ144"] + apio_build, ["--board", "icefake", "--fpga", "iCE40-HX1K-TQ144"] ) assert result.exit_code != 0, result.output assert "Error: unknown board: icefake" in result.output # apio build --fpga iCE40-FAKE - result = click_cmd_runner.invoke(cmd_build, ["--fpga", "iCE40-FAKE"]) + result = click_cmd_runner.invoke(apio_build, ["--fpga", "iCE40-FAKE"]) assert result.exit_code != 0, result.output assert "Error: unknown FPGA: iCE40-FAKE" in result.output # apio build --fpga iCE40-FAKE --size 8k result = click_cmd_runner.invoke( - cmd_build, ["--fpga", "iCE40-FAKE", "--size", "8k"] + apio_build, ["--fpga", "iCE40-FAKE", "--size", "8k"] ) assert result.exit_code != 0, result.output assert "Error: unknown FPGA: iCE40-FAKE" in result.output # apio build --board icezum --fpga iCE40-FAKE result = click_cmd_runner.invoke( - cmd_build, ["--board", "icezum", "--fpga", "iCE40-FAKE"] + apio_build, ["--board", "icezum", "--fpga", "iCE40-FAKE"] ) assert result.exit_code != 0, result.output assert ( @@ -230,11 +230,11 @@ def test_errors_with_apio_ini( write_apio_ini({"board": "icezum", "top-module": "main"}) # apio build - result = click_cmd_runner.invoke(cmd_build) + result = click_cmd_runner.invoke(apio_build) assert result.exit_code != 0, result.output # apio build --board icestick - result = click_cmd_runner.invoke(cmd_build, ["--board", "icestick"]) + result = click_cmd_runner.invoke(apio_build, ["--board", "icestick"]) assert result.exit_code != 0, result.output assert ( "Info: ignoring board specification from apio.ini." @@ -243,7 +243,7 @@ def test_errors_with_apio_ini( # apio build --fpga iCE40-HX1K-VQ100 result = click_cmd_runner.invoke( - cmd_build, ["--fpga", "iCE40-HX1K-VQ100"] + apio_build, ["--fpga", "iCE40-HX1K-VQ100"] ) assert result.exit_code != 0, result.output assert ( @@ -253,7 +253,7 @@ def test_errors_with_apio_ini( # apio build --type lp --size 8k --pack cm225:4k result = click_cmd_runner.invoke( - cmd_build, ["--type", "lp", "--size", "8k", "--pack", "cm225:4k"] + apio_build, ["--type", "lp", "--size", "8k", "--pack", "cm225:4k"] ) assert result.exit_code != 0, result.output assert ( @@ -263,7 +263,7 @@ def test_errors_with_apio_ini( # apio build --type lp --size 8k result = click_cmd_runner.invoke( - cmd_build, ["--type", "lp", "--size", "8k"] + apio_build, ["--type", "lp", "--size", "8k"] ) assert result.exit_code != 0, result.output assert ( diff --git a/test/commands/test_clean.py b/test/commands/test_clean.py index ff0c6701..1139fe6c 100644 --- a/test/commands/test_clean.py +++ b/test/commands/test_clean.py @@ -5,7 +5,7 @@ from pathlib import Path # -- apio clean entry point -from apio.commands.clean import cli as cmd_clean +from apio.commands.clean import cli as apio_clean def test_clean_no_apio_ini_no_params(click_cmd_runner, setup_apio_test_env): @@ -19,7 +19,7 @@ def test_clean_no_apio_ini_no_params(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # -- Execute "apio clean" - result = click_cmd_runner.invoke(cmd_clean) + result = click_cmd_runner.invoke(apio_clean) # -- It is an error. Exit code should not be 0 assert result.exit_code != 0, result.output @@ -27,7 +27,9 @@ def test_clean_no_apio_ini_no_params(click_cmd_runner, setup_apio_test_env): assert "Error: insufficient arguments: missing board" in result.output # -- Execute "apio clean --board alhambra-ii" - result = click_cmd_runner.invoke(cmd_clean, ["--board", "alhambra-ii"]) + result = click_cmd_runner.invoke( + apio_clean, ["--board", "alhambra-ii"] + ) assert result.exit_code == 0, result.output @@ -53,7 +55,9 @@ def test_clean_no_apio_ini_params(click_cmd_runner, setup_apio_test_env): assert Path("_build/main_tb.vcd").is_file() # -- Execute "apio clean --board alhambra-ii" - result = click_cmd_runner.invoke(cmd_clean, ["--board", "alhambra-ii"]) + result = click_cmd_runner.invoke( + apio_clean, ["--board", "alhambra-ii"] + ) assert result.exit_code == 0, result.output # Confirm that the files do not exist. @@ -84,7 +88,7 @@ def test_clean_create(click_cmd_runner, setup_apio_test_env, write_apio_ini): assert Path("_build/main_tb.vcd").is_file() # --- Execute "apio clean" - result = click_cmd_runner.invoke(cmd_clean) + result = click_cmd_runner.invoke(apio_clean) assert result.exit_code == 0, result.output # Confirm that the files do not exist. diff --git a/test/commands/test_create.py b/test/commands/test_create.py index a217cdd2..445b13d3 100644 --- a/test/commands/test_create.py +++ b/test/commands/test_create.py @@ -8,7 +8,7 @@ from configobj import ConfigObj # -- apio create entry point -from apio.commands.create import cli as cmd_create +from apio.commands.create import cli as apio_create # R0801: Similar lines in 2 files @@ -36,21 +36,21 @@ def test_create(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): assert not exists(apio_ini) # -- Execute "apio create" - result = click_cmd_runner.invoke(cmd_create) + result = click_cmd_runner.invoke(apio_create) assert result.exit_code != 0, result.output assert "Error: Missing option" in result.output assert not exists(apio_ini) # -- Execute "apio create --board missed_board" result = click_cmd_runner.invoke( - cmd_create, ["--board", "missed_board"] + apio_create, ["--board", "missed_board"] ) assert result.exit_code == 1, result.output assert "Error: no such board" in result.output assert not exists(apio_ini) # -- Execute "apio create --board icezum" - result = click_cmd_runner.invoke(cmd_create, ["--board", "icezum"]) + result = click_cmd_runner.invoke(apio_create, ["--board", "icezum"]) assert_apio_cmd_ok(result) assert "file already exists" not in result.output assert "Do you want to replace it?" not in result.output @@ -61,7 +61,7 @@ def test_create(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): # -- Execute "apio create --board alhambra-ii # -- --top-module my_module" with 'y' input" result = click_cmd_runner.invoke( - cmd_create, + apio_create, ["--board", "alhambra-ii", "--top-module", "my_module"], input="y", ) @@ -78,7 +78,7 @@ def test_create(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): # -- --top-module my_module # -- --sayyse" with 'y' input result = click_cmd_runner.invoke( - cmd_create, + apio_create, ["--board", "icezum", "--top-module", "my_module", "--sayyes"], ) assert_apio_cmd_ok(result) @@ -90,7 +90,7 @@ def test_create(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): # -- Execute "apio create --board alhambra-ii # -- --top-module my_module" with 'n' input result = click_cmd_runner.invoke( - cmd_create, + apio_create, ["--board", "alhambra-ii", "--top-module", "my_module"], input="n", ) diff --git a/test/commands/test_drivers.py b/test/commands/test_drivers.py index a743c591..eb71c491 100644 --- a/test/commands/test_drivers.py +++ b/test/commands/test_drivers.py @@ -3,7 +3,7 @@ """ # -- apio drivers entry point -from apio.commands.drivers import cli as cmd_drivers +from apio.commands.drivers import cli as apio_drivers def test_drivers(click_cmd_runner, assert_apio_cmd_ok, setup_apio_test_env): @@ -15,12 +15,12 @@ def test_drivers(click_cmd_runner, assert_apio_cmd_ok, setup_apio_test_env): setup_apio_test_env() # -- Execute "apio drivers" - result = click_cmd_runner.invoke(cmd_drivers) + result = click_cmd_runner.invoke(apio_drivers) assert_apio_cmd_ok(result) # -- Execute "apio --ftdi-install, --serial-install" result = click_cmd_runner.invoke( - cmd_drivers, ["--ftdi-install", "--serial-install"] + apio_drivers, ["--ftdi-install", "--serial-install"] ) assert result.exit_code == 1, result.output assert ( diff --git a/test/commands/test_examples.py b/test/commands/test_examples.py index 8592a7e8..4bce62ee 100644 --- a/test/commands/test_examples.py +++ b/test/commands/test_examples.py @@ -3,7 +3,7 @@ """ # -- apio examples entry point -from apio.commands.examples import cli as cmd_examples +from apio.commands.examples import cli as apio_examples def test_examples(click_cmd_runner, setup_apio_test_env): @@ -15,7 +15,7 @@ def test_examples(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # -- Execute "apio examples" - result = click_cmd_runner.invoke(cmd_examples) + result = click_cmd_runner.invoke(apio_examples) assert result.exit_code == 1, result.output assert ( "One of [--list, --fetch-dir, --fetch-files] " @@ -23,20 +23,20 @@ def test_examples(click_cmd_runner, setup_apio_test_env): ) # -- Execute "apio examples --list" - result = click_cmd_runner.invoke(cmd_examples, ["--list"]) + result = click_cmd_runner.invoke(apio_examples, ["--list"]) assert result.exit_code == 1, result.output assert "Error: package 'examples' is not installed" in result.output assert "apio packages --install --force examples" in result.output # -- Execute "apio examples --fetch-dir dir" - result = click_cmd_runner.invoke(cmd_examples, ["--fetch-dir", "dir"]) + result = click_cmd_runner.invoke(apio_examples, ["--fetch-dir", "dir"]) assert result.exit_code == 1, result.output assert "Error: package 'examples' is not installed" in result.output assert "apio packages --install --force examples" in result.output # -- Execute "apio examples --files file" result = click_cmd_runner.invoke( - cmd_examples, ["--fetch-files", "file"] + apio_examples, ["--fetch-files", "file"] ) assert result.exit_code == 1, result.output assert "Error: package 'examples' is not installed" in result.output diff --git a/test/commands/test_fpgas.py b/test/commands/test_fpgas.py index 58bf3704..c242cc8f 100644 --- a/test/commands/test_fpgas.py +++ b/test/commands/test_fpgas.py @@ -3,7 +3,7 @@ """ # -- apio fpgas entry point -from apio.commands.fpgas import cli as cmd_fpgas +from apio.commands.fpgas import cli as apio_fpgas CUSTOM_FPGAS = """ { @@ -26,7 +26,7 @@ def test_fpgas_ok(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): setup_apio_test_env() # -- Execute "apio fpgas" - result = click_cmd_runner.invoke(cmd_fpgas) + result = click_cmd_runner.invoke(apio_fpgas) assert_apio_cmd_ok(result) # -- Note: pytest sees the piped version of the command's output. # -- Run 'apio fpgas' | cat' to reproduce it. @@ -50,7 +50,7 @@ def test_custom_fpga( f.write(CUSTOM_FPGAS) # -- Execute "apio boards" - result = click_cmd_runner.invoke(cmd_fpgas) + result = click_cmd_runner.invoke(apio_fpgas) assert_apio_cmd_ok(result) # -- Note: pytest sees the piped version of the command's output. # -- Run 'apio build' | cat' to reproduce it. diff --git a/test/commands/test_graph.py b/test/commands/test_graph.py index ad8fe832..407f5f2f 100644 --- a/test/commands/test_graph.py +++ b/test/commands/test_graph.py @@ -3,7 +3,7 @@ """ # -- apio graph entry point -from apio.commands.graph import cli as cmd_graph +from apio.commands.graph import cli as apio_graph def test_graph_no_apio_ini(click_cmd_runner, setup_apio_test_env): @@ -15,7 +15,7 @@ def test_graph_no_apio_ini(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # -- Execute "apio graph" - result = click_cmd_runner.invoke(cmd_graph) + result = click_cmd_runner.invoke(apio_graph) assert result.exit_code == 1, result.output assert "Error: insufficient arguments: missing board" in result.output @@ -34,19 +34,19 @@ def test_graph_with_apio_ini( write_apio_ini({"board": "icezum", "top-module": "main"}) # -- Execute "apio graph" - result = click_cmd_runner.invoke(cmd_graph) + result = click_cmd_runner.invoke(apio_graph) assert result.exit_code == 1, result.output assert "package 'oss-cad-suite' is not installed" in result.output assert "apio packages --install --force oss-cad-suite" in result.output # -- Execute "apio graph -pdf" - result = click_cmd_runner.invoke(cmd_graph) + result = click_cmd_runner.invoke(apio_graph) assert result.exit_code == 1, result.output assert "package 'oss-cad-suite' is not installed" in result.output assert "apio packages --install --force oss-cad-suite" in result.output # -- Execute "apio graph -png" - result = click_cmd_runner.invoke(cmd_graph) + result = click_cmd_runner.invoke(apio_graph) assert result.exit_code == 1, result.output assert "package 'oss-cad-suite' is not installed" in result.output assert "apio packages --install --force oss-cad-suite" in result.output diff --git a/test/commands/test_install.py b/test/commands/test_install.py index 8db4ca2c..d11a942b 100644 --- a/test/commands/test_install.py +++ b/test/commands/test_install.py @@ -3,7 +3,7 @@ """ # -- apio install entry point -from apio.commands.install import cli as cmd_install +from apio.commands.install import cli as apio_install def test_install(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): @@ -15,14 +15,14 @@ def test_install(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): setup_apio_test_env() # -- Execute "apio install" - result = click_cmd_runner.invoke(cmd_install) + result = click_cmd_runner.invoke(apio_install) assert_apio_cmd_ok(result) # -- Execute "apio install --list" - result = click_cmd_runner.invoke(cmd_install, ["--list"]) + result = click_cmd_runner.invoke(apio_install, ["--list"]) assert_apio_cmd_ok(result) # -- Execute "apio install missing_package" - result = click_cmd_runner.invoke(cmd_install, ["missing_package"]) + result = click_cmd_runner.invoke(apio_install, ["missing_package"]) assert result.exit_code == 1, result.output assert "Error: no such package" in result.output diff --git a/test/commands/test_lint.py b/test/commands/test_lint.py index 61a7cb83..394a3c00 100644 --- a/test/commands/test_lint.py +++ b/test/commands/test_lint.py @@ -3,7 +3,7 @@ """ # -- apio lint entry point -from apio.commands.lint import cli as cmd_lint +from apio.commands.lint import cli as apio_lint def test_lint_no_packages( @@ -20,7 +20,7 @@ def test_lint_no_packages( write_apio_ini({"board": "icezum", "top-module": "main"}) # -- Execute "apio lint" - result = click_cmd_runner.invoke(cmd_lint) + result = click_cmd_runner.invoke(apio_lint) assert result.exit_code == 1, result.output assert ( "Error: package 'oss-cad-suite' is not installed" in result.output diff --git a/test/commands/test_modify.py b/test/commands/test_modify.py index 92aed60f..71351d05 100644 --- a/test/commands/test_modify.py +++ b/test/commands/test_modify.py @@ -8,7 +8,7 @@ from configobj import ConfigObj # -- apio modify entry point -from apio.commands.modify import cli as cmd_modify +from apio.commands.modify import cli as apio_modify # R0801: Similar lines in 2 files @@ -37,7 +37,7 @@ def test_modify(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): # -- Execute "apio modify --top-module my_module" result = click_cmd_runner.invoke( - cmd_modify, ["--top-module", "my_module"] + apio_modify, ["--top-module", "my_module"] ) assert result.exit_code != 0, result.output assert "Error: 'apio.ini' not found" in result.output @@ -63,7 +63,7 @@ def test_modify(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): # -- Execute "apio modify --board missed_board" result = click_cmd_runner.invoke( - cmd_modify, ["--board", "missed_board"] + apio_modify, ["--board", "missed_board"] ) assert result.exit_code == 1, result.output assert "Error: no such board" in result.output @@ -78,7 +78,7 @@ def test_modify(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): # -- Execute "apio modify --board alhambra-ii" result = click_cmd_runner.invoke( - cmd_modify, ["--board", "alhambra-ii"] + apio_modify, ["--board", "alhambra-ii"] ) assert_apio_cmd_ok(result) assert "was modified successfully." in result.output @@ -93,7 +93,7 @@ def test_modify(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): # -- Execute "apio modify --top-module my_main" result = click_cmd_runner.invoke( - cmd_modify, ["--top-module", "my_main"] + apio_modify, ["--top-module", "my_main"] ) assert_apio_cmd_ok(result) assert "was modified successfully." in result.output @@ -108,7 +108,7 @@ def test_modify(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): # -- Execute "apio modify --board icezum --top-module my_top" result = click_cmd_runner.invoke( - cmd_modify, ["--board", "icezum", "--top-module", "my_top"] + apio_modify, ["--board", "icezum", "--top-module", "my_top"] ) assert_apio_cmd_ok(result) assert "was modified successfully." in result.output diff --git a/test/commands/test_packages.py b/test/commands/test_packages.py index 75f7db79..5250a1f4 100644 --- a/test/commands/test_packages.py +++ b/test/commands/test_packages.py @@ -3,7 +3,7 @@ """ # -- apio packages entry point -from apio.commands.packages import cli as cmd_packages +from apio.commands.packages import cli as apio_packages def test_packages(click_cmd_runner, setup_apio_test_env): @@ -15,7 +15,7 @@ def test_packages(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # -- Execute "apio packages" - result = click_cmd_runner.invoke(cmd_packages) + result = click_cmd_runner.invoke(apio_packages) assert result.exit_code == 1, result.output assert ( "One of [--list, --install, --uninstall, --fix] " @@ -23,20 +23,20 @@ def test_packages(click_cmd_runner, setup_apio_test_env): ) # -- Execute "apio packages --list" - result = click_cmd_runner.invoke(cmd_packages, ["--list"]) + result = click_cmd_runner.invoke(apio_packages, ["--list"]) assert result.exit_code == 0, result.output assert "No errors" in result.output # -- Execute "apio packages --install missing_package" result = click_cmd_runner.invoke( - cmd_packages, ["--install", "missing_package"] + apio_packages, ["--install", "missing_package"] ) assert result.exit_code == 1, result.output assert "Error: unknown package 'missing_package'" in result.output # -- Execute "apio packages --uninstall --sayyes missing_package" result = click_cmd_runner.invoke( - cmd_packages, ["--uninstall", "--sayyes", "missing_package"] + apio_packages, ["--uninstall", "--sayyes", "missing_package"] ) assert result.exit_code == 1, result.output assert "Error: no such package 'missing_package'" in result.output diff --git a/test/commands/test_report.py b/test/commands/test_report.py index c0bf80fb..9685fa0d 100644 --- a/test/commands/test_report.py +++ b/test/commands/test_report.py @@ -3,7 +3,7 @@ """ # -- apio report entry point -from apio.commands.report import cli as cmd_report +from apio.commands.report import cli as apio_report # R0801: Similar lines in 2 files @@ -20,7 +20,7 @@ def test_report(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # -- Execute "apio report" - result = click_cmd_runner.invoke(cmd_report) + result = click_cmd_runner.invoke(apio_report) # -- Check the result assert result.exit_code != 0, result.output @@ -39,7 +39,7 @@ def test_report_board(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # -- Execute "apio report" - result = click_cmd_runner.invoke(cmd_report, ["--board", "icezum"]) + result = click_cmd_runner.invoke(apio_report, ["--board", "icezum"]) # -- Check the result assert result.exit_code != 0, result.output diff --git a/test/commands/test_sim.py b/test/commands/test_sim.py index 87350f06..2288556b 100644 --- a/test/commands/test_sim.py +++ b/test/commands/test_sim.py @@ -3,7 +3,7 @@ """ # -- apio sim entry point -from apio.commands.sim import cli as cmd_sim +from apio.commands.sim import cli as apio_sim def test_sim(click_cmd_runner, setup_apio_test_env): @@ -18,6 +18,6 @@ def test_sim(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # -- apio sim --board icezum - result = click_cmd_runner.invoke(cmd_sim) + result = click_cmd_runner.invoke(apio_sim) assert result.exit_code != 0, result.output # -- TODO diff --git a/test/commands/test_system.py b/test/commands/test_system.py index 2b969eeb..42212592 100644 --- a/test/commands/test_system.py +++ b/test/commands/test_system.py @@ -3,7 +3,7 @@ """ # -- apio system entry point -from apio.commands.system import cli as cmd_system +from apio.commands.system import cli as apio_system def test_system(click_cmd_runner, setup_apio_test_env): @@ -15,7 +15,7 @@ def test_system(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # -- Execute "apio system" - result = click_cmd_runner.invoke(cmd_system) + result = click_cmd_runner.invoke(apio_system) assert result.exit_code == 1, result.output assert ( "One of [--lsftdi, --lsusb, --lsserial, --info, --platforms] " @@ -23,22 +23,22 @@ def test_system(click_cmd_runner, setup_apio_test_env): ) # -- Execute "apio system --lsftdi" - result = click_cmd_runner.invoke(cmd_system, ["--lsftdi"]) + result = click_cmd_runner.invoke(apio_system, ["--lsftdi"]) assert result.exit_code == 1, result.output assert "apio packages --install --force oss-cad-suite" in result.output # -- Execute "apio system --lsusb" - result = click_cmd_runner.invoke(cmd_system, ["--lsusb"]) + result = click_cmd_runner.invoke(apio_system, ["--lsusb"]) assert result.exit_code == 1, result.output assert "apio packages --install --force oss-cad-suite" in result.output # -- Execute "apio system --lsserial" - click_cmd_runner.invoke(cmd_system, ["--lsserial"]) + click_cmd_runner.invoke(apio_system, ["--lsserial"]) assert result.exit_code == 1, result.output assert "apio packages --install --force oss-cad-suite" in result.output # -- Execute "apio system --info" - result = click_cmd_runner.invoke(cmd_system, ["--info"]) + result = click_cmd_runner.invoke(apio_system, ["--info"]) assert result.exit_code == 0, result.output assert "Platform id" in result.output # -- The these env options are set by the apio text fixture. diff --git a/test/commands/test_test.py b/test/commands/test_test.py index 36cdca27..3629344a 100644 --- a/test/commands/test_test.py +++ b/test/commands/test_test.py @@ -3,7 +3,7 @@ """ # -- apio test entry point -from apio.commands.sim import cli as cmd_test +from apio.commands.sim import cli as apio_test def test_test(click_cmd_runner, setup_apio_test_env): @@ -18,6 +18,6 @@ def test_test(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # -- Execute "apio test" - result = click_cmd_runner.invoke(cmd_test) + result = click_cmd_runner.invoke(apio_test) assert result.exit_code != 0, result.output # -- TODO diff --git a/test/commands/test_time.py b/test/commands/test_time.py index ed083c9c..347084c4 100644 --- a/test/commands/test_time.py +++ b/test/commands/test_time.py @@ -3,7 +3,7 @@ """ # -- apio time entry point -from apio.commands.time import cli as cmd_time +from apio.commands.time import cli as apio_time # R0801: Similar lines in 2 files @@ -20,7 +20,7 @@ def test_time(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # -- Execute "apio time" - result = click_cmd_runner.invoke(cmd_time) + result = click_cmd_runner.invoke(apio_time) # -- Check the result assert result.exit_code != 0, result.output @@ -39,7 +39,7 @@ def test_time_board(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # -- Execute "apio time" - result = click_cmd_runner.invoke(cmd_time, ["--board", "icezum"]) + result = click_cmd_runner.invoke(apio_time, ["--board", "icezum"]) # -- Check the result assert result.exit_code != 0, result.output diff --git a/test/commands/test_uninstall.py b/test/commands/test_uninstall.py index d56c8b6a..b86baa19 100644 --- a/test/commands/test_uninstall.py +++ b/test/commands/test_uninstall.py @@ -3,7 +3,7 @@ """ # -- apio uninstall entry point -from apio.commands.uninstall import cli as cmd_uninstall +from apio.commands.uninstall import cli as apio_uninstall def test_uninstall(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): @@ -15,16 +15,16 @@ def test_uninstall(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): setup_apio_test_env() # -- Execute "apio uninstall" - result = click_cmd_runner.invoke(cmd_uninstall) + result = click_cmd_runner.invoke(apio_uninstall) assert_apio_cmd_ok(result) # -- Execute "apio uninstall --list" - result = click_cmd_runner.invoke(cmd_uninstall, ["--list"]) + result = click_cmd_runner.invoke(apio_uninstall, ["--list"]) assert_apio_cmd_ok(result) # -- Execute "apio uninstall missing_packge" result = click_cmd_runner.invoke( - cmd_uninstall, ["missing_package"], input="y" + apio_uninstall, ["missing_package"], input="y" ) assert result.exit_code == 1, result.output assert "Do you want to uninstall?" in result.output diff --git a/test/commands/test_upgrade.py b/test/commands/test_upgrade.py index 987fc9a7..7d89cbe4 100644 --- a/test/commands/test_upgrade.py +++ b/test/commands/test_upgrade.py @@ -5,7 +5,7 @@ import pytest # -- apio upgrade entry point -from apio.commands.upgrade import cli as cmd_upgrade +from apio.commands.upgrade import cli as apio_upgrade def test_upgrade( @@ -24,5 +24,5 @@ def test_upgrade( setup_apio_test_env() # -- Execute "apio upgrade" - result = click_cmd_runner.invoke(cmd_upgrade) + result = click_cmd_runner.invoke(apio_upgrade) assert_apio_cmd_ok(result) diff --git a/test/commands/test_upload.py b/test/commands/test_upload.py index 932ae650..e47ffba7 100644 --- a/test/commands/test_upload.py +++ b/test/commands/test_upload.py @@ -3,7 +3,7 @@ """ # -- apio time entry point -from apio.commands.upload import cli as cmd_upload +from apio.commands.upload import cli as apio_upload def test_upload(click_cmd_runner, setup_apio_test_env): @@ -18,7 +18,7 @@ def test_upload(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # -- Execute "apio upload" - result = click_cmd_runner.invoke(cmd_upload) + result = click_cmd_runner.invoke(apio_upload) # -- Check the result assert result.exit_code == 1, result.output @@ -37,7 +37,7 @@ def test_upload_board(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # -- Execute "apio upload --board icezum" - result = click_cmd_runner.invoke(cmd_upload, ["--board", "icezum"]) + result = click_cmd_runner.invoke(apio_upload, ["--board", "icezum"]) # -- Check the result assert result.exit_code == 1 @@ -57,26 +57,28 @@ def test_upload_complete(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # -- Execute "apio upload --serial-port COM0" - result = click_cmd_runner.invoke(cmd_upload, ["--serial-port", "COM0"]) + result = click_cmd_runner.invoke( + apio_upload, ["--serial-port", "COM0"] + ) assert result.exit_code == 1, result.output assert "Info: Project has no apio.ini file" in result.output assert "Error: insufficient arguments: missing board" in result.output # -- Execute "apio upload --ftdi-id 0" - result = click_cmd_runner.invoke(cmd_upload, ["--ftdi-id", "0"]) + result = click_cmd_runner.invoke(apio_upload, ["--ftdi-id", "0"]) assert result.exit_code == 1, result.output assert "Info: Project has no apio.ini file" in result.output assert "Error: insufficient arguments: missing board" in result.output # -- Execute "apio upload --sram" - result = click_cmd_runner.invoke(cmd_upload, ["--sram"]) + result = click_cmd_runner.invoke(apio_upload, ["--sram"]) assert result.exit_code == 1, result.output assert "Info: Project has no apio.ini file" in result.output assert "Error: insufficient arguments: missing board" in result.output # -- Execute "apio upload --board icezum --serial-port COM0" result = click_cmd_runner.invoke( - cmd_upload, ["--board", "icezum", "--serial-port", "COM0"] + apio_upload, ["--board", "icezum", "--serial-port", "COM0"] ) assert result.exit_code == 1, result.output assert ( @@ -85,7 +87,7 @@ def test_upload_complete(click_cmd_runner, setup_apio_test_env): # -- Execute "apio upload --board icezum --ftdi-id 0" result = click_cmd_runner.invoke( - cmd_upload, ["--board", "icezum", "--ftdi-id", "0"] + apio_upload, ["--board", "icezum", "--ftdi-id", "0"] ) assert result.exit_code == 1, result.output assert ( @@ -94,7 +96,7 @@ def test_upload_complete(click_cmd_runner, setup_apio_test_env): # -- Execute "apio upload --board icezum --sram" result = click_cmd_runner.invoke( - cmd_upload, ["--board", "icezum", "--sram"] + apio_upload, ["--board", "icezum", "--sram"] ) assert result.exit_code == 1, result.output assert ( diff --git a/test/commands/test_verify.py b/test/commands/test_verify.py index 7acb82c9..4a79bde6 100644 --- a/test/commands/test_verify.py +++ b/test/commands/test_verify.py @@ -3,7 +3,7 @@ """ # -- apio verify entry point -from apio.commands.verify import cli as cmd_verify +from apio.commands.verify import cli as apio_verify def test_verify(click_cmd_runner, setup_apio_test_env): @@ -18,7 +18,7 @@ def test_verify(click_cmd_runner, setup_apio_test_env): setup_apio_test_env() # -- Execute "apio verify" - result = click_cmd_runner.invoke(cmd_verify, ["--board", "icezum"]) + result = click_cmd_runner.invoke(apio_verify, ["--board", "icezum"]) # -- Check the result assert result.exit_code != 0, result.output From 269f49f726de52a0e400410325dd5df575ee8d17 Mon Sep 17 00:00:00 2001 From: Zapta Date: Sun, 24 Nov 2024 14:50:42 -0800 Subject: [PATCH 08/13] Split the end-to-end tests into 4 test files, each focuses on a seperate test topic. --- test/integration/__init__.py | 0 test/integration/test_examples.py | 94 +++++++ test/integration/test_packages.py | 124 +++++++++ test/integration/test_project_ice40.py | 111 ++++++++ test/integration/test_utilities.py | 63 +++++ test/test_end_to_end.py | 356 ------------------------- 6 files changed, 392 insertions(+), 356 deletions(-) create mode 100644 test/integration/__init__.py create mode 100644 test/integration/test_examples.py create mode 100644 test/integration/test_packages.py create mode 100644 test/integration/test_project_ice40.py create mode 100644 test/integration/test_utilities.py delete mode 100644 test/test_end_to_end.py diff --git a/test/integration/__init__.py b/test/integration/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/integration/test_examples.py b/test/integration/test_examples.py new file mode 100644 index 00000000..8817423c --- /dev/null +++ b/test/integration/test_examples.py @@ -0,0 +1,94 @@ +""" + Test different "apio" commands +""" + +from os import chdir +from os.path import getsize +import pytest + +# -- Entry point for apio commands. +from apio.commands.packages import cli as apio_packages +from apio.commands.examples import cli as apio_examples + + +# R0801: Similar lines in 2 files +# pylint: disable=R0801 +def test_examples( + click_cmd_runner, + setup_apio_test_env, + assert_apio_cmd_ok, + offline_flag, +): + """Tests the listing and fetching apio examples.""" + + # -- If the option 'offline' is passed, the test is skip + # -- (This test is slow and requires internet connectivity) + if offline_flag: + pytest.skip("requires internet connection") + + with click_cmd_runner.isolated_filesystem(): + + # -- Config the apio test environment + proj_dir, _, packages_dir = setup_apio_test_env() + + # -- Create and change to project dir. + proj_dir.mkdir(exist_ok=False) + chdir(proj_dir) + + # -- Install the examples package. + result = click_cmd_runner.invoke( + apio_packages, ["--install", "examples"] + ) + assert_apio_cmd_ok(result) + # assert "Installing package 'examples'" in result.output + # assert "Download" in result.output + assert "Package 'examples' installed successfully" in result.output + assert getsize(packages_dir / "examples/Alhambra-II/ledon/ledon.v") + + # -- List the examples + result = click_cmd_runner.invoke( + apio_examples, + ["--list"], + ) + assert_apio_cmd_ok(result) + assert "Alhambra-II/ledon" in result.output + + # -- Fetch example files to current directory + result = click_cmd_runner.invoke( + apio_examples, + ["--fetch-files", "Alhambra-II/ledon"], + ) + assert_apio_cmd_ok(result) + assert "Copying Alhambra-II/ledon example files" in result.output + assert "have been successfully created!" in result.output + assert getsize("ledon.v") + + # -- Fetch example dir to current directory + result = click_cmd_runner.invoke( + apio_examples, + ["--fetch-dir", "Alhambra-II/ledon"], + ) + assert_apio_cmd_ok(result) + assert "Creating Alhambra-II/ledon directory" in result.output + assert "has been successfully created" in result.output + assert getsize("Alhambra-II/ledon/ledon.v") + + # -- Fetch example files to another project dir + result = click_cmd_runner.invoke( + apio_examples, + ["--fetch-files", "Alhambra-II/ledon", "--project-dir=./dir1"], + ) + assert_apio_cmd_ok(result) + assert "Copying Alhambra-II/ledon example files" in result.output + assert "have been successfully created!" in result.output + assert getsize("dir1/ledon.v") + + # -- Fetch example dir to another project dir + result = click_cmd_runner.invoke( + apio_examples, + ["--fetch-dir", "Alhambra-II/ledon", "--project-dir=dir2"], + ) + assert_apio_cmd_ok(result) + assert "Creating Alhambra-II/ledon directory" in result.output + assert "has been successfully created" in result.output + assert getsize("dir2/Alhambra-II/ledon/ledon.v") diff --git a/test/integration/test_packages.py b/test/integration/test_packages.py new file mode 100644 index 00000000..0556873c --- /dev/null +++ b/test/integration/test_packages.py @@ -0,0 +1,124 @@ +""" + Test different "apio" commands +""" + +from os import listdir, chdir +import pytest + +# -- Entry point for apio commands. +from apio.commands.packages import cli as apio_packages + + +# R0801: Similar lines in 2 files +# pylint: disable=R0801 +# # R0915: Too many statements (52/50) (too-many-statements) +# # pylint: disable=R0915 +def test_packages( + click_cmd_runner, + setup_apio_test_env, + assert_apio_cmd_ok, + offline_flag, +): + """Tests listing, installation and uninstallation of packages.""" + + # -- If the option 'offline' is passed, the test is skip + # -- (This test is slow and requires internet connectivity) + if offline_flag: + pytest.skip("requires internet connection") + + with click_cmd_runner.isolated_filesystem(): + + # -- Config the apio test environment + proj_dir, _, packages_dir = setup_apio_test_env() + + # -- Create and change to project dir. + proj_dir.mkdir(exist_ok=False) + chdir(proj_dir) + + # -- List packages + result = click_cmd_runner.invoke(apio_packages, ["--list"]) + assert result.exit_code == 0 + assert "No errors" in result.output + assert "examples" in result.output + assert "oss-cad-suite" in result.output + + # -- Packages dir doesn't exist yet. + assert not packages_dir.exists() + + # -- Install the examples package. Package 'examples' should exist, + # -- and package 'tools-oss-cad-suite' should not. + result = click_cmd_runner.invoke( + apio_packages, ["--install", "examples"] + ) + assert_apio_cmd_ok(result) + assert "Package 'examples' installed successfully" in result.output + assert listdir(packages_dir / "examples/Alhambra-II") + assert "tools-oss-cad-suite" not in listdir(packages_dir) + + # -- Install the reset of the packages. + # -- Both 'examples' and 'tools-oss-cad-suite' should exist, and + # -- maybe others, depending on the platform. + result = click_cmd_runner.invoke(apio_packages, ["--install"]) + assert_apio_cmd_ok(result) + assert "Package 'examples' installed successfully" not in result.output + assert ( + "Package 'oss-cad-suite' installed successfully" in result.output + ) + assert listdir(packages_dir / "examples/Alhambra-II") + assert listdir(packages_dir / "tools-oss-cad-suite/bin") + + # -- Delete a file from the examples package, we will use it as an + # -- indicator for the reinstallation of the package. + marker_file = packages_dir / "examples/Alhambra-II/ledon/ledon.v" + assert marker_file.is_file() + marker_file.unlink() + assert not marker_file.exists() + + # -- Install the examples packages without forcing. + # -- This should not do anything since it's considered to be installed. + result = click_cmd_runner.invoke( + apio_packages, ["--install", "examples"] + ) + assert_apio_cmd_ok(result) + assert "was already install" in result.output + assert "Package 'examples' installed" not in result.output + assert not marker_file.exists() + + # -- Install the examples packages with forcing. + # -- This should recover the file. + result = click_cmd_runner.invoke( + apio_packages, ["--install", "--force", "examples"] + ) + assert_apio_cmd_ok(result) + assert "Package 'examples' installed" in result.output + assert marker_file.is_file() + + # -- Try to uninstall the 'examples' package without user approval. + # -- should exit with an error message. + assert "examples" in listdir(packages_dir) + result = click_cmd_runner.invoke( + apio_packages, ["--uninstall", "examples"], input="n" + ) + assert result.exit_code == 1 + assert "User said no" in result.output + assert "examples" in listdir(packages_dir) + assert "tools-oss-cad-suite" in listdir(packages_dir) + + # -- Uninstall the examples package. It should delete the exemples + # -- package and will live the rest. + assert "examples" in listdir(packages_dir) + result = click_cmd_runner.invoke( + apio_packages, ["--uninstall", "examples"], input="y" + ) + assert_apio_cmd_ok(result) + assert "examples" not in listdir(packages_dir) + assert "tools-oss-cad-suite" in listdir(packages_dir) + + # -- Uninstall all packages. This should uninstall also the + # -- oss-cad-suite package. + result = click_cmd_runner.invoke( + apio_packages, ["--uninstall", "--sayyes"] + ) + assert_apio_cmd_ok(result) + assert "examples" not in listdir(packages_dir) + assert "tools-oss-cad-suite" not in listdir(packages_dir) diff --git a/test/integration/test_project_ice40.py b/test/integration/test_project_ice40.py new file mode 100644 index 00000000..26ce36c4 --- /dev/null +++ b/test/integration/test_project_ice40.py @@ -0,0 +1,111 @@ +""" + Test different "apio" commands +""" + +from os import listdir, chdir +from os.path import getsize +from pathlib import Path +import pytest + +# -- Entry point for apio commands. +from apio.commands.clean import cli as apio_clean +from apio.commands.graph import cli as apio_graph +from apio.commands.test import cli as apio_test +from apio.commands.report import cli as apio_report +from apio.commands.lint import cli as apio_lint +from apio.commands.build import cli as apio_build +from apio.commands.packages import cli as apio_packages +from apio.commands.examples import cli as apio_examples + + +# R0801: Similar lines in 2 files +# pylint: disable=R0801 +def test_project_ice40( + click_cmd_runner, + setup_apio_test_env, + assert_apio_cmd_ok, + offline_flag, +): + """Tests building and testing a project.""" + + # -- If the option 'offline' is passed, the test is skip + # -- (This test is slow and requires internet connectivity) + if offline_flag: + pytest.skip("requires internet connection") + + with click_cmd_runner.isolated_filesystem(): + + # -- Config the apio test environment. + proj_dir, _, packages_dir = setup_apio_test_env() + + # -- Create and change to project dir. + proj_dir.mkdir(exist_ok=False) + chdir(proj_dir) + + # -- Install all packages + result = click_cmd_runner.invoke( + apio_packages, ["--install", "--verbose"] + ) + assert_apio_cmd_ok(result) + assert "'examples' installed successfully" in result.output + assert "'oss-cad-suite' installed successfully" in result.output + assert listdir(packages_dir / "examples") + assert listdir(packages_dir / "tools-oss-cad-suite") + + # -- The current proj directory should be still empty + assert not listdir(".") + + # -- Fetch example files to current directory + result = click_cmd_runner.invoke( + apio_examples, + ["--fetch-files", "Alhambra-II/ledon"], + ) + assert_apio_cmd_ok(result) + assert "Copying Alhambra-II/ledon example files" in result.output + assert "have been successfully created!" in result.output + assert getsize("apio.ini") + + # -- Remember the list of project files. + project_files = listdir(".") + + # -- Build the project. + result = click_cmd_runner.invoke(apio_build) + assert_apio_cmd_ok(result) + assert "SUCCESS" in result.output + assert getsize("_build/hardware.bin") + + # -- Lint + result = click_cmd_runner.invoke(apio_lint) + assert_apio_cmd_ok(result) + assert "SUCCESS" in result.output + assert getsize("_build/hardware.vlt") + + # -- Test + result = click_cmd_runner.invoke(apio_test) + assert_apio_cmd_ok(result) + assert "SUCCESS" in result.output + assert getsize("_build/ledon_tb.out") + assert getsize("_build/ledon_tb.vcd") + + # -- Report + result = click_cmd_runner.invoke(apio_report) + assert_apio_cmd_ok(result) + assert "SUCCESS" in result.output + assert "ICESTORM_LC:" in result.output + assert getsize("_build/hardware.pnr") + + # -- Graph svg + result = click_cmd_runner.invoke(apio_graph) + assert_apio_cmd_ok(result) + assert "SUCCESS" in result.output + assert getsize("_build/hardware.dot") + assert getsize("_build/hardware.svg") + + # -- Clean + result = click_cmd_runner.invoke(apio_clean) + assert_apio_cmd_ok(result) + assert "SUCCESS" in result.output + assert not Path("_build").exists() + + # -- Check that we have exactly the original project files, + assert set(listdir(".")) == set(project_files) diff --git a/test/integration/test_utilities.py b/test/integration/test_utilities.py new file mode 100644 index 00000000..f346baa9 --- /dev/null +++ b/test/integration/test_utilities.py @@ -0,0 +1,63 @@ +""" + Test different "apio" commands +""" + +from os import listdir, chdir +import pytest + +# -- Entry point for apio commands. +from apio.commands.raw import cli as apio_raw +from apio.commands.upgrade import cli as apio_upgrade +from apio.commands.system import cli as apio_system +from apio.commands.packages import cli as apio_packages + + +# R0801: Similar lines in 2 files +# pylint: disable=R0801 +def test_utilities( + click_cmd_runner, + setup_apio_test_env, + assert_apio_cmd_ok, + offline_flag, +): + """Tests utility commands.""" + + # -- If the option 'offline' is passed, the test is skip + # -- (This test is slow and requires internet connectivity) + if offline_flag: + pytest.skip("requires internet connection") + + with click_cmd_runner.isolated_filesystem(): + + # -- Config the apio test environment. + proj_dir, _, packages_dir = setup_apio_test_env() + + # -- Create and change to project dir. + proj_dir.mkdir(exist_ok=False) + chdir(proj_dir) + + # -- Install all packages + result = click_cmd_runner.invoke( + apio_packages, ["--install", "--verbose"] + ) + assert_apio_cmd_ok(result) + assert "'examples' installed successfully" in result.output + assert "'oss-cad-suite' installed successfully" in result.output + assert listdir(packages_dir / "examples") + assert listdir(packages_dir / "tools-oss-cad-suite") + + # -- Run 'apio upgrade' + result = click_cmd_runner.invoke(apio_upgrade) + assert_apio_cmd_ok(result) + assert "Lastest Apio stable version" in result.output + + # -- Run 'apio system --info' + result = click_cmd_runner.invoke(apio_system, ["--info"]) + assert_apio_cmd_ok(result) + assert "Apio version" in result.output + + # -- Run 'apio raw --env "nextpnr-ice40 --help" + result = click_cmd_runner.invoke( + apio_raw, ["--env", "nextpnr-ice40 --help"], input="exit" + ) + assert_apio_cmd_ok(result) diff --git a/test/test_end_to_end.py b/test/test_end_to_end.py deleted file mode 100644 index d54082ba..00000000 --- a/test/test_end_to_end.py +++ /dev/null @@ -1,356 +0,0 @@ -""" - Test different "apio" commands -""" - -from os import listdir, chdir -from os.path import getsize -from pathlib import Path - -import pytest - -# -- Entry point for apio commands. -from apio.commands.raw import cli as apio_raw -from apio.commands.upgrade import cli as apio_upgrade -from apio.commands.system import cli as apio_system -from apio.commands.clean import cli as apio_clean -from apio.commands.graph import cli as apio_graph -from apio.commands.test import cli as apio_test -from apio.commands.report import cli as apio_report -from apio.commands.lint import cli as apio_lint -from apio.commands.build import cli as apio_build -from apio.commands.packages import cli as apio_packages -from apio.commands.examples import cli as apio_examples - - -def test_utilities( - click_cmd_runner, - setup_apio_test_env, - assert_apio_cmd_ok, - offline_flag, -): - """Tests utility commands.""" - - # -- If the option 'offline' is passed, the test is skip - # -- (This test is slow and requires internet connectivity) - if offline_flag: - pytest.skip("requires internet connection") - - with click_cmd_runner.isolated_filesystem(): - - # -- Config the apio test environment. - proj_dir, _, packages_dir = setup_apio_test_env() - - # -- Create and change to project dir. - proj_dir.mkdir(exist_ok=False) - chdir(proj_dir) - - # -- Install all packages - result = click_cmd_runner.invoke( - apio_packages, ["--install", "--verbose"] - ) - assert_apio_cmd_ok(result) - assert "'examples' installed successfully" in result.output - assert "'oss-cad-suite' installed successfully" in result.output - assert listdir(packages_dir / "examples") - assert listdir(packages_dir / "tools-oss-cad-suite") - - # -- Run 'apio upgrade' - result = click_cmd_runner.invoke(apio_upgrade) - assert_apio_cmd_ok(result) - assert "Lastest Apio stable version" in result.output - - # -- Run 'apio system --info' - result = click_cmd_runner.invoke(apio_system, ["--info"]) - assert_apio_cmd_ok(result) - assert "Apio version" in result.output - - # -- Run 'apio raw --env "nextpnr-ice40 --help" - result = click_cmd_runner.invoke( - apio_raw, ["--env", "nextpnr-ice40 --help"], input="exit" - ) - assert_apio_cmd_ok(result) - - -def test_project_ice40( - click_cmd_runner, - setup_apio_test_env, - assert_apio_cmd_ok, - offline_flag, -): - """Tests building and testing a project.""" - - # -- If the option 'offline' is passed, the test is skip - # -- (This test is slow and requires internet connectivity) - if offline_flag: - pytest.skip("requires internet connection") - - with click_cmd_runner.isolated_filesystem(): - - # -- Config the apio test environment. - proj_dir, _, packages_dir = setup_apio_test_env() - - # -- Create and change to project dir. - proj_dir.mkdir(exist_ok=False) - chdir(proj_dir) - - # -- Install all packages - result = click_cmd_runner.invoke( - apio_packages, ["--install", "--verbose"] - ) - assert_apio_cmd_ok(result) - assert "'examples' installed successfully" in result.output - assert "'oss-cad-suite' installed successfully" in result.output - assert listdir(packages_dir / "examples") - assert listdir(packages_dir / "tools-oss-cad-suite") - - # -- The current proj directory should be still empty - assert not listdir(".") - - # -- Fetch example files to current directory - result = click_cmd_runner.invoke( - apio_examples, - ["--fetch-files", "Alhambra-II/ledon"], - ) - assert_apio_cmd_ok(result) - assert "Copying Alhambra-II/ledon example files" in result.output - assert "have been successfully created!" in result.output - assert getsize("apio.ini") - - # -- Remember the list of project files. - project_files = listdir(".") - - # -- Build the project. - result = click_cmd_runner.invoke(apio_build) - assert_apio_cmd_ok(result) - assert "SUCCESS" in result.output - assert getsize("_build/hardware.bin") - - # -- Lint - result = click_cmd_runner.invoke(apio_lint) - assert_apio_cmd_ok(result) - assert "SUCCESS" in result.output - assert getsize("_build/hardware.vlt") - - # -- Test - result = click_cmd_runner.invoke(apio_test) - assert_apio_cmd_ok(result) - assert "SUCCESS" in result.output - assert getsize("_build/ledon_tb.out") - assert getsize("_build/ledon_tb.vcd") - - # -- Report - result = click_cmd_runner.invoke(apio_report) - assert_apio_cmd_ok(result) - assert "SUCCESS" in result.output - assert "ICESTORM_LC:" in result.output - assert getsize("_build/hardware.pnr") - - # -- Graph svg - result = click_cmd_runner.invoke(apio_graph) - assert_apio_cmd_ok(result) - assert "SUCCESS" in result.output - assert getsize("_build/hardware.dot") - assert getsize("_build/hardware.svg") - - # -- Clean - result = click_cmd_runner.invoke(apio_clean) - assert_apio_cmd_ok(result) - assert "SUCCESS" in result.output - assert not Path("_build").exists() - - # -- Check that we have exactly the original project files, - assert set(listdir(".")) == set(project_files) - - -# # R0915: Too many statements (52/50) (too-many-statements) -# # pylint: disable=R0915 -def test_packages( - click_cmd_runner, - setup_apio_test_env, - assert_apio_cmd_ok, - offline_flag, -): - """Tests listing, installation and uninstallation of packages.""" - - # -- If the option 'offline' is passed, the test is skip - # -- (This test is slow and requires internet connectivity) - if offline_flag: - pytest.skip("requires internet connection") - - with click_cmd_runner.isolated_filesystem(): - - # -- Config the apio test environment - proj_dir, _, packages_dir = setup_apio_test_env() - - # -- Create and change to project dir. - proj_dir.mkdir(exist_ok=False) - chdir(proj_dir) - - # -- List packages - result = click_cmd_runner.invoke(apio_packages, ["--list"]) - assert result.exit_code == 0 - assert "No errors" in result.output - assert "examples" in result.output - assert "oss-cad-suite" in result.output - - # -- Packages dir doesn't exist yet. - assert not packages_dir.exists() - - # -- Install the examples package. Package 'examples' should exist, - # -- and package 'tools-oss-cad-suite' should not. - result = click_cmd_runner.invoke( - apio_packages, ["--install", "examples"] - ) - assert_apio_cmd_ok(result) - assert "Package 'examples' installed successfully" in result.output - assert listdir(packages_dir / "examples/Alhambra-II") - assert "tools-oss-cad-suite" not in listdir(packages_dir) - - # -- Install the reset of the packages. - # -- Both 'examples' and 'tools-oss-cad-suite' should exist, and - # -- maybe others, depending on the platform. - result = click_cmd_runner.invoke(apio_packages, ["--install"]) - assert_apio_cmd_ok(result) - assert "Package 'examples' installed successfully" not in result.output - assert ( - "Package 'oss-cad-suite' installed successfully" in result.output - ) - assert listdir(packages_dir / "examples/Alhambra-II") - assert listdir(packages_dir / "tools-oss-cad-suite/bin") - - # -- Delete a file from the examples package, we will use it as an - # -- indicator for the reinstallation of the package. - marker_file = packages_dir / "examples/Alhambra-II/ledon/ledon.v" - assert marker_file.is_file() - marker_file.unlink() - assert not marker_file.exists() - - # -- Install the examples packages without forcing. - # -- This should not do anything since it's considered to be installed. - result = click_cmd_runner.invoke( - apio_packages, ["--install", "examples"] - ) - assert_apio_cmd_ok(result) - assert "was already install" in result.output - assert "Package 'examples' installed" not in result.output - assert not marker_file.exists() - - # -- Install the examples packages with forcing. - # -- This should recover the file. - result = click_cmd_runner.invoke( - apio_packages, ["--install", "--force", "examples"] - ) - assert_apio_cmd_ok(result) - assert "Package 'examples' installed" in result.output - assert marker_file.is_file() - - # -- Try to uninstall the 'examples' package without user approval. - # -- should exit with an error message. - assert "examples" in listdir(packages_dir) - result = click_cmd_runner.invoke( - apio_packages, ["--uninstall", "examples"], input="n" - ) - assert result.exit_code == 1 - assert "User said no" in result.output - assert "examples" in listdir(packages_dir) - assert "tools-oss-cad-suite" in listdir(packages_dir) - - # -- Uninstall the examples package. It should delete the exemples - # -- package and will live the rest. - assert "examples" in listdir(packages_dir) - result = click_cmd_runner.invoke( - apio_packages, ["--uninstall", "examples"], input="y" - ) - assert_apio_cmd_ok(result) - assert "examples" not in listdir(packages_dir) - assert "tools-oss-cad-suite" in listdir(packages_dir) - - # -- Uninstall all packages. This should uninstall also the - # -- oss-cad-suite package. - result = click_cmd_runner.invoke( - apio_packages, ["--uninstall", "--sayyes"] - ) - assert_apio_cmd_ok(result) - assert "examples" not in listdir(packages_dir) - assert "tools-oss-cad-suite" not in listdir(packages_dir) - - -def test_examples( - click_cmd_runner, - setup_apio_test_env, - assert_apio_cmd_ok, - offline_flag, -): - """Tests the listing and fetching apio examples.""" - - # -- If the option 'offline' is passed, the test is skip - # -- (This test is slow and requires internet connectivity) - if offline_flag: - pytest.skip("requires internet connection") - - with click_cmd_runner.isolated_filesystem(): - - # -- Config the apio test environment - proj_dir, _, packages_dir = setup_apio_test_env() - - # -- Create and change to project dir. - proj_dir.mkdir(exist_ok=False) - chdir(proj_dir) - - # -- Install the examples package. - result = click_cmd_runner.invoke( - apio_packages, ["--install", "examples"] - ) - assert_apio_cmd_ok(result) - # assert "Installing package 'examples'" in result.output - # assert "Download" in result.output - assert "Package 'examples' installed successfully" in result.output - assert getsize(packages_dir / "examples/Alhambra-II/ledon/ledon.v") - - # -- List the examples - result = click_cmd_runner.invoke( - apio_examples, - ["--list"], - ) - assert_apio_cmd_ok(result) - assert "Alhambra-II/ledon" in result.output - - # -- Fetch example files to current directory - result = click_cmd_runner.invoke( - apio_examples, - ["--fetch-files", "Alhambra-II/ledon"], - ) - assert_apio_cmd_ok(result) - assert "Copying Alhambra-II/ledon example files" in result.output - assert "have been successfully created!" in result.output - assert getsize("ledon.v") - - # -- Fetch example dir to current directory - result = click_cmd_runner.invoke( - apio_examples, - ["--fetch-dir", "Alhambra-II/ledon"], - ) - assert_apio_cmd_ok(result) - assert "Creating Alhambra-II/ledon directory" in result.output - assert "has been successfully created" in result.output - assert getsize("Alhambra-II/ledon/ledon.v") - - # -- Fetch example files to another project dir - result = click_cmd_runner.invoke( - apio_examples, - ["--fetch-files", "Alhambra-II/ledon", "--project-dir=./dir1"], - ) - assert_apio_cmd_ok(result) - assert "Copying Alhambra-II/ledon example files" in result.output - assert "have been successfully created!" in result.output - assert getsize("dir1/ledon.v") - - # -- Fetch example dir to another project dir - result = click_cmd_runner.invoke( - apio_examples, - ["--fetch-dir", "Alhambra-II/ledon", "--project-dir=dir2"], - ) - assert_apio_cmd_ok(result) - assert "Creating Alhambra-II/ledon directory" in result.output - assert "has been successfully created" in result.output - assert getsize("dir2/Alhambra-II/ledon/ledon.v") From 44d859f23019f739fe8f002e4951a8e73ddfeebf Mon Sep 17 00:00:00 2001 From: Zapta Date: Sun, 24 Nov 2024 19:42:26 -0800 Subject: [PATCH 09/13] Added verification of --sayyes flag of 'apio packages'. Can appear only wity the '--uninstall command'. --- apio/commands/packages.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apio/commands/packages.py b/apio/commands/packages.py index de7b6d21..ec72b1b6 100644 --- a/apio/commands/packages.py +++ b/apio/commands/packages.py @@ -138,6 +138,7 @@ def _list(apio_ctx: ApioContext, verbose: bool) -> int: apio packages --install oss-cad-suite # Install a specific package. apio packages --install examples@0.0.32 # Install a specific version. apio packages --uninstall # Uninstall all packages. + apio packages --uninstall --sayyes # Same but does not ask yes/no. apio packages --uninstall oss-cad-suite # Uninstall only given package(s). apio packages --fix # Fix package errors. @@ -223,6 +224,10 @@ def cli( cmd_util.check_at_most_one_param(cmd_ctx, nameof(list_, packages)) cmd_util.check_at_most_one_param(cmd_ctx, nameof(fix, packages)) + cmd_util.check_at_most_one_param(cmd_ctx, nameof(sayyes, list_)) + cmd_util.check_at_most_one_param(cmd_ctx, nameof(sayyes, install)) + cmd_util.check_at_most_one_param(cmd_ctx, nameof(sayyes, fix)) + # -- Create the apio context. apio_ctx = ApioContext(project_dir=project_dir, load_project=False) From c4965b8621bc0c224fcf2620542322390fb5d2ff Mon Sep 17 00:00:00 2001 From: Zapta Date: Sun, 24 Nov 2024 20:31:44 -0800 Subject: [PATCH 10/13] Tweaked the flag validation error messages. --- apio/cmd_util.py | 16 ++++++++++++---- apio/commands/drivers.py | 4 ++-- apio/commands/examples.py | 2 -- test/commands/test_drivers.py | 12 ++++++++---- test/commands/test_examples.py | 4 ++-- test/commands/test_packages.py | 4 ++-- test/commands/test_system.py | 5 +++-- 7 files changed, 29 insertions(+), 18 deletions(-) diff --git a/apio/cmd_util.py b/apio/cmd_util.py index 93868ded..b8bf593b 100644 --- a/apio/cmd_util.py +++ b/apio/cmd_util.py @@ -156,13 +156,21 @@ def check_exactly_one_param( """ # The the subset of ids of params that where used in the command. specified_param_ids = _specified_params(cmd_ctx, param_ids) - # If more 2 or more print an error and exit. - if len(specified_param_ids) != 1: + # If exactly one than we are good. + if len(specified_param_ids) == 1: + return + if len(specified_param_ids) < 1: + # -- User specified Less flags than required. canonical_aliases = _params_ids_to_aliases(cmd_ctx, param_ids) aliases_str = ", ".join(canonical_aliases) - fatal_usage_error( - cmd_ctx, f"One of [{aliases_str}] must be specified." + fatal_usage_error(cmd_ctx, f"Specify one of [{aliases_str}].") + else: + # -- User specified more flags than allowed. + canonical_aliases = _params_ids_to_aliases( + cmd_ctx, specified_param_ids ) + aliases_str = ", ".join(canonical_aliases) + fatal_usage_error(cmd_ctx, f"Specify only one of [{aliases_str}].") def check_at_least_one_param( diff --git a/apio/commands/drivers.py b/apio/commands/drivers.py index b1034edb..39a2328a 100644 --- a/apio/commands/drivers.py +++ b/apio/commands/drivers.py @@ -90,8 +90,8 @@ def cli( ): """Implements the drivers command.""" - # Make sure these params are exclusive. - cmd_util.check_at_most_one_param( + # User should select exactly on of these operations. + cmd_util.check_exactly_one_param( cmd_ctx, nameof(ftdi_install, ftdi_uninstall, serial_install, serial_uninstall), ) diff --git a/apio/commands/examples.py b/apio/commands/examples.py index c091f89c..fb95d53d 100644 --- a/apio/commands/examples.py +++ b/apio/commands/examples.py @@ -90,8 +90,6 @@ def cli( """Manage verilog examples.\n Install with `apio packages --install examples`""" - cmd_ctx.get_help() - # Make sure these params are exclusive. cmd_util.check_exactly_one_param( cmd_ctx, nameof(list_, fetch_dir, fetch_files) diff --git a/test/commands/test_drivers.py b/test/commands/test_drivers.py index eb71c491..40c4d3cd 100644 --- a/test/commands/test_drivers.py +++ b/test/commands/test_drivers.py @@ -6,7 +6,7 @@ from apio.commands.drivers import cli as apio_drivers -def test_drivers(click_cmd_runner, assert_apio_cmd_ok, setup_apio_test_env): +def test_drivers(click_cmd_runner, setup_apio_test_env): """Test "apio drivers" """ with click_cmd_runner.isolated_filesystem(): @@ -16,7 +16,11 @@ def test_drivers(click_cmd_runner, assert_apio_cmd_ok, setup_apio_test_env): # -- Execute "apio drivers" result = click_cmd_runner.invoke(apio_drivers) - assert_apio_cmd_ok(result) + assert result.exit_code == 1 + assert ( + "Error: Specify one of [--ftdi-install, --ftdi-uninstall, " + "--serial-install, --serial-uninstall]" in result.output + ) # -- Execute "apio --ftdi-install, --serial-install" result = click_cmd_runner.invoke( @@ -24,6 +28,6 @@ def test_drivers(click_cmd_runner, assert_apio_cmd_ok, setup_apio_test_env): ) assert result.exit_code == 1, result.output assert ( - "Error: [--ftdi-install, --serial-install] " - "are mutually exclusive" in result.output + "Error: Specify only one of [--ftdi-install, --serial-install]" + in result.output ) diff --git a/test/commands/test_examples.py b/test/commands/test_examples.py index 4bce62ee..c220c324 100644 --- a/test/commands/test_examples.py +++ b/test/commands/test_examples.py @@ -18,8 +18,8 @@ def test_examples(click_cmd_runner, setup_apio_test_env): result = click_cmd_runner.invoke(apio_examples) assert result.exit_code == 1, result.output assert ( - "One of [--list, --fetch-dir, --fetch-files] " - "must be specified" in result.output + "Error: Specify one of [--list, --fetch-dir, --fetch-files]" + in result.output ) # -- Execute "apio examples --list" diff --git a/test/commands/test_packages.py b/test/commands/test_packages.py index 5250a1f4..a9c4513e 100644 --- a/test/commands/test_packages.py +++ b/test/commands/test_packages.py @@ -18,8 +18,8 @@ def test_packages(click_cmd_runner, setup_apio_test_env): result = click_cmd_runner.invoke(apio_packages) assert result.exit_code == 1, result.output assert ( - "One of [--list, --install, --uninstall, --fix] " - "must be specified" in result.output + "Error: Specify one of [--list, --install, --uninstall, --fix]" + in result.output ) # -- Execute "apio packages --list" diff --git a/test/commands/test_system.py b/test/commands/test_system.py index 42212592..2053d7ba 100644 --- a/test/commands/test_system.py +++ b/test/commands/test_system.py @@ -18,8 +18,9 @@ def test_system(click_cmd_runner, setup_apio_test_env): result = click_cmd_runner.invoke(apio_system) assert result.exit_code == 1, result.output assert ( - "One of [--lsftdi, --lsusb, --lsserial, --info, --platforms] " - "must be specified" in result.output + "Specify one of " + "[--lsftdi, --lsusb, --lsserial, --info, --platforms]" + in result.output ) # -- Execute "apio system --lsftdi" From 455dce3077aa6e7ee187a46ef1428d0d1dba882a Mon Sep 17 00:00:00 2001 From: Zapta Date: Mon, 25 Nov 2024 11:31:11 -0800 Subject: [PATCH 11/13] Refactored the apio test fixtures into a single ApioRunner class. Now also restoring the system path on each apio command to prevent the repeated extension of the path on each command (this happens only in testing where pytest invokes apio multiple times within the same python process). --- test/commands/test_boards.py | 27 ++- test/commands/test_build.py | 84 +++++---- test/commands/test_clean.py | 34 ++-- test/commands/test_create.py | 28 +-- test/commands/test_drivers.py | 12 +- test/commands/test_examples.py | 18 +- test/commands/test_fpgas.py | 24 +-- test/commands/test_graph.py | 26 +-- test/commands/test_install.py | 18 +- test/commands/test_lint.py | 14 +- test/commands/test_modify.py | 32 ++-- test/commands/test_packages.py | 16 +- test/commands/test_report.py | 18 +- test/commands/test_sim.py | 10 +- test/commands/test_system.py | 18 +- test/commands/test_test.py | 10 +- test/commands/test_time.py | 18 +- test/commands/test_uninstall.py | 18 +- test/commands/test_upgrade.py | 16 +- test/commands/test_upload.py | 38 ++-- test/commands/test_verify.py | 10 +- test/conftest.py | 240 +++++++++++++++---------- test/integration/test_examples.py | 40 ++--- test/integration/test_packages.py | 48 ++--- test/integration/test_project_ice40.py | 48 +++-- test/integration/test_utilities.py | 35 ++-- test/test_apio.py | 24 +-- 27 files changed, 477 insertions(+), 447 deletions(-) diff --git a/test/commands/test_boards.py b/test/commands/test_boards.py index 95a93bf1..21015543 100644 --- a/test/commands/test_boards.py +++ b/test/commands/test_boards.py @@ -2,9 +2,12 @@ Test for the "apio boards" command """ +from test.conftest import ApioRunner + # -- apio boards entry point from apio.commands.boards import cli as apio_boards + CUSTOM_BOARDS = """ { "my_custom_board": { @@ -25,17 +28,15 @@ """ -def test_list_ok(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): +def test_list_ok(apio_runner: ApioRunner): """Test normal board listing with the apio's boards.json.""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): - # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() - # -- Execute "apio boards" - result = click_cmd_runner.invoke(apio_boards) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_boards) + apio_runner.assert_ok(result) # -- Note: pytest sees the piped version of the command's output. # -- Run 'apio build' | cat' to reproduce it. assert "Loading custom 'boards.json'" not in result.output @@ -44,23 +45,21 @@ def test_list_ok(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): assert "Total of 1 board" not in result.output -def test_custom_board( - click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok -): +def test_custom_board(apio_runner: ApioRunner): """Test boards listing with a custom boards.json file.""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Write a custom boards.json file in the project's directory. with open("boards.json", "w", encoding="utf-8") as f: f.write(CUSTOM_BOARDS) # -- Execute "apio boards" - result = click_cmd_runner.invoke(apio_boards) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_boards) + apio_runner.assert_ok(result) # -- Note: pytest sees the piped version of the command's output. # -- Run 'apio build' | cat' to reproduce it. assert "Loading custom 'boards.json'" in result.output diff --git a/test/commands/test_build.py b/test/commands/test_build.py index 9232f001..eb82d003 100644 --- a/test/commands/test_build.py +++ b/test/commands/test_build.py @@ -2,55 +2,55 @@ Test for the "apio build" command """ +from test.conftest import ApioRunner + # -- apio build entry point from apio.commands.build import cli as apio_build # pylint: disable=too-many-statements -def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): +def test_errors_without_apio_ini_1(apio_runner: ApioRunner): """Test: Various errors 1/2. All tests are without apio.ini and without apio packages installed.""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio build" - result = click_cmd_runner.invoke(apio_build) + result = apio_runner.invoke(apio_build) assert result.exit_code != 0, result.output assert "Info: Project has no apio.ini file" in result.output assert "Error: insufficient arguments: missing board" in result.output assert "Error: Missing FPGA" in result.output # apio build --board icestick - result = click_cmd_runner.invoke(apio_build, ["--board", "icestick"]) + result = apio_runner.invoke(apio_build, ["--board", "icestick"]) assert result.exit_code == 1, result.output assert "apio packages --install --force oss-cad-suite" in result.output # apio build --fpga iCE40-HX1K-VQ100 - result = click_cmd_runner.invoke( - apio_build, ["--fpga", "iCE40-HX1K-VQ100"] - ) + result = apio_runner.invoke(apio_build, ["--fpga", "iCE40-HX1K-VQ100"]) assert result.exit_code == 1, result.output assert "apio packages --install --force oss-cad-suite" in result.output # apio build --type lp --size 8k --pack cm225:4k - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, ["--type", "lp", "--size", "8k", "--pack", "cm225:4k"] ) assert result.exit_code == 1, result.output assert "Error: insufficient arguments" in result.output # apio build --board icezum --size 1k - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, ["--board", "icezum", "--size", "1k"] ) assert result.exit_code != 0, result.output assert "apio packages --install --force oss-cad-suite" in result.output # apio build --board icezum --fpga iCE40-HX1K-TQ144 --type hx - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, [ "--board", @@ -65,14 +65,14 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): assert "apio packages --install --force oss-cad-suite" in result.output # apio build --board icezum --pack tq144 - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, ["--board", "icezum", "--pack", "tq144"] ) assert result.exit_code != 0, result.output assert "apio packages --install --force oss-cad-suite" in result.output # apio build --fpga iCE40-HX1K-TQ144 --pack tq144 --size 1k - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, ["--fpga", "iCE40-HX1K-TQ144", "--pack", "tq144", "--size", "1k"], ) @@ -80,14 +80,14 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): assert "apio packages --install --force oss-cad-suite" in result.output # apio build --fpga iCE40-HX1K-TQ144 --type hx - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, ["--fpga", "iCE40-HX1K-TQ144", "--type", "hx"] ) assert result.exit_code != 0, result.output assert "apio packages --install --force oss-cad-suite" in result.output # apio build --board icezum --size 8k - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, ["--board", "icezum", "--size", "8k"] ) assert result.exit_code != 0, result.output @@ -97,7 +97,7 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): ) # apio build --board icezum --fpga iCE40-HX1K-TQ144 --type lp - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, [ "--board", @@ -115,7 +115,7 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): ) # apio build --board icezum --fpga iCE40-HX1K-VQ100 - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, ["--board", "icezum", "--fpga", "iCE40-HX1K-VQ100"] ) assert result.exit_code != 0, result.output @@ -125,7 +125,7 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): ) # apio build --fpga iCE40-HX1K-TQ144 --type lp --size 8k - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, ["--fpga", "iCE40-HX1K-TQ144", "--type", "lp", "--size", "8k"], ) @@ -136,7 +136,7 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): ) # apio build --fpga iCE40-HX1K-TQ144 --pack vq100 - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, ["--fpga", "iCE40-HX1K-TQ144", "--pack", "vq100"] ) assert result.exit_code != 0, result.output @@ -146,7 +146,7 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): ) # apio build --board icezum --pack vq100 - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, ["--board", "icezum", "--pack", "vq100"] ) assert result.exit_code != 0, result.output @@ -156,57 +156,57 @@ def test_errors_without_apio_ini_1(click_cmd_runner, setup_apio_test_env): ) # apio build --size 8k - result = click_cmd_runner.invoke(apio_build, ["--size", "8k"]) + result = apio_runner.invoke(apio_build, ["--size", "8k"]) assert result.exit_code != 0, result.output assert "Error: insufficient arguments" in result.output -def test_errors_without_apio_ini_2(click_cmd_runner, setup_apio_test_env): +def test_errors_without_apio_ini_2(apio_runner: ApioRunner): """Test: Various errors 2/2. All tests are without apio.ini and without apio packages installed.""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # apio build --type lp - result = click_cmd_runner.invoke(apio_build, ["--type", "lp"]) + result = apio_runner.invoke(apio_build, ["--type", "lp"]) assert result.exit_code != 0, result.output assert "Error: insufficient arguments" in result.output # apio build --type lp --size 8k - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, ["--type", "lp", "--size", "8k"] ) assert result.exit_code != 0, result.output assert "Error: insufficient arguments" in result.output # apio build --board icefake - result = click_cmd_runner.invoke(apio_build, ["--board", "icefake"]) + result = apio_runner.invoke(apio_build, ["--board", "icefake"]) assert result.exit_code != 0, result.output assert "Error: unknown board: icefake" in result.output # apio build --board icefake --fpga iCE40-HX1K-TQ144 - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, ["--board", "icefake", "--fpga", "iCE40-HX1K-TQ144"] ) assert result.exit_code != 0, result.output assert "Error: unknown board: icefake" in result.output # apio build --fpga iCE40-FAKE - result = click_cmd_runner.invoke(apio_build, ["--fpga", "iCE40-FAKE"]) + result = apio_runner.invoke(apio_build, ["--fpga", "iCE40-FAKE"]) assert result.exit_code != 0, result.output assert "Error: unknown FPGA: iCE40-FAKE" in result.output # apio build --fpga iCE40-FAKE --size 8k - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, ["--fpga", "iCE40-FAKE", "--size", "8k"] ) assert result.exit_code != 0, result.output assert "Error: unknown FPGA: iCE40-FAKE" in result.output # apio build --board icezum --fpga iCE40-FAKE - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, ["--board", "icezum", "--fpga", "iCE40-FAKE"] ) assert result.exit_code != 0, result.output @@ -216,25 +216,23 @@ def test_errors_without_apio_ini_2(click_cmd_runner, setup_apio_test_env): ) -def test_errors_with_apio_ini( - click_cmd_runner, setup_apio_test_env, write_apio_ini -): +def test_errors_with_apio_ini(apio_runner: ApioRunner): """Test: apio build with apio create""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Write apio.ini - write_apio_ini({"board": "icezum", "top-module": "main"}) + apio_runner.write_apio_ini({"board": "icezum", "top-module": "main"}) # apio build - result = click_cmd_runner.invoke(apio_build) + result = apio_runner.invoke(apio_build) assert result.exit_code != 0, result.output # apio build --board icestick - result = click_cmd_runner.invoke(apio_build, ["--board", "icestick"]) + result = apio_runner.invoke(apio_build, ["--board", "icestick"]) assert result.exit_code != 0, result.output assert ( "Info: ignoring board specification from apio.ini." @@ -242,9 +240,7 @@ def test_errors_with_apio_ini( ) # apio build --fpga iCE40-HX1K-VQ100 - result = click_cmd_runner.invoke( - apio_build, ["--fpga", "iCE40-HX1K-VQ100"] - ) + result = apio_runner.invoke(apio_build, ["--fpga", "iCE40-HX1K-VQ100"]) assert result.exit_code != 0, result.output assert ( "Error: contradictory argument values: 'fpga' = " @@ -252,7 +248,7 @@ def test_errors_with_apio_ini( ) # apio build --type lp --size 8k --pack cm225:4k - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, ["--type", "lp", "--size", "8k", "--pack", "cm225:4k"] ) assert result.exit_code != 0, result.output @@ -262,7 +258,7 @@ def test_errors_with_apio_ini( ) # apio build --type lp --size 8k - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_build, ["--type", "lp", "--size", "8k"] ) assert result.exit_code != 0, result.output diff --git a/test/commands/test_clean.py b/test/commands/test_clean.py index 1139fe6c..20ce56c3 100644 --- a/test/commands/test_clean.py +++ b/test/commands/test_clean.py @@ -3,23 +3,25 @@ """ from pathlib import Path +from test.conftest import ApioRunner + # -- apio clean entry point from apio.commands.clean import cli as apio_clean -def test_clean_no_apio_ini_no_params(click_cmd_runner, setup_apio_test_env): +def test_clean_no_apio_ini_no_params(apio_runner: ApioRunner): """Test: apio clean when no apio.ini file is given No additional parameters are given """ - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio clean" - result = click_cmd_runner.invoke(apio_clean) + result = apio_runner.invoke(apio_clean) # -- It is an error. Exit code should not be 0 assert result.exit_code != 0, result.output @@ -27,21 +29,19 @@ def test_clean_no_apio_ini_no_params(click_cmd_runner, setup_apio_test_env): assert "Error: insufficient arguments: missing board" in result.output # -- Execute "apio clean --board alhambra-ii" - result = click_cmd_runner.invoke( - apio_clean, ["--board", "alhambra-ii"] - ) + result = apio_runner.invoke(apio_clean, ["--board", "alhambra-ii"]) assert result.exit_code == 0, result.output -def test_clean_no_apio_ini_params(click_cmd_runner, setup_apio_test_env): +def test_clean_no_apio_ini_params(apio_runner: ApioRunner): """Test: apio clean when no apio.ini file is given. Board definition comes from --board parameter. """ - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Create a legacy artifact file. Path("main_tb.vcd").touch() @@ -55,9 +55,7 @@ def test_clean_no_apio_ini_params(click_cmd_runner, setup_apio_test_env): assert Path("_build/main_tb.vcd").is_file() # -- Execute "apio clean --board alhambra-ii" - result = click_cmd_runner.invoke( - apio_clean, ["--board", "alhambra-ii"] - ) + result = apio_runner.invoke(apio_clean, ["--board", "alhambra-ii"]) assert result.exit_code == 0, result.output # Confirm that the files do not exist. @@ -65,16 +63,16 @@ def test_clean_no_apio_ini_params(click_cmd_runner, setup_apio_test_env): assert not Path("_build/main_tb.vcd").exists() -def test_clean_create(click_cmd_runner, setup_apio_test_env, write_apio_ini): +def test_clean_create(apio_runner: ApioRunner): """Test: apio clean when there is an apio.ini file""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Create apio.ini - write_apio_ini({"board": "icezum", "top-module": "main"}) + apio_runner.write_apio_ini({"board": "icezum", "top-module": "main"}) # -- Create a legacy artifact file. Path("main_tb.vcd").touch() @@ -88,7 +86,7 @@ def test_clean_create(click_cmd_runner, setup_apio_test_env, write_apio_ini): assert Path("_build/main_tb.vcd").is_file() # --- Execute "apio clean" - result = click_cmd_runner.invoke(apio_clean) + result = apio_runner.invoke(apio_clean) assert result.exit_code == 0, result.output # Confirm that the files do not exist. diff --git a/test/commands/test_create.py b/test/commands/test_create.py index 445b13d3..07fba45e 100644 --- a/test/commands/test_create.py +++ b/test/commands/test_create.py @@ -5,8 +5,10 @@ from pathlib import Path from os.path import isfile, exists from typing import Dict +from test.conftest import ApioRunner from configobj import ConfigObj + # -- apio create entry point from apio.commands.create import cli as apio_create @@ -24,34 +26,32 @@ def _check_ini_file(apio_ini: Path, expected_vars: Dict[str, str]) -> None: assert conf.dict() == {"env": expected_vars} -def test_create(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): +def test_create(apio_runner: ApioRunner): """Test "apio create" with different parameters""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() apio_ini = Path("apio.ini") assert not exists(apio_ini) # -- Execute "apio create" - result = click_cmd_runner.invoke(apio_create) + result = apio_runner.invoke(apio_create) assert result.exit_code != 0, result.output assert "Error: Missing option" in result.output assert not exists(apio_ini) # -- Execute "apio create --board missed_board" - result = click_cmd_runner.invoke( - apio_create, ["--board", "missed_board"] - ) + result = apio_runner.invoke(apio_create, ["--board", "missed_board"]) assert result.exit_code == 1, result.output assert "Error: no such board" in result.output assert not exists(apio_ini) # -- Execute "apio create --board icezum" - result = click_cmd_runner.invoke(apio_create, ["--board", "icezum"]) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_create, ["--board", "icezum"]) + apio_runner.assert_ok(result) assert "file already exists" not in result.output assert "Do you want to replace it?" not in result.output assert "Creating apio.ini file ..." in result.output @@ -60,12 +60,12 @@ def test_create(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): # -- Execute "apio create --board alhambra-ii # -- --top-module my_module" with 'y' input" - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_create, ["--board", "alhambra-ii", "--top-module", "my_module"], input="y", ) - assert_apio_cmd_ok(result) + apio_runner.assert_ok(result) assert "Warning" in result.output assert "file already exists" in result.output assert "Do you want to replace it?" in result.output @@ -77,11 +77,11 @@ def test_create(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): # -- Execute "apio create --board icezum # -- --top-module my_module # -- --sayyse" with 'y' input - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_create, ["--board", "icezum", "--top-module", "my_module", "--sayyes"], ) - assert_apio_cmd_ok(result) + apio_runner.assert_ok(result) assert "was created successfully." in result.output _check_ini_file( apio_ini, {"board": "icezum", "top-module": "my_module"} @@ -89,7 +89,7 @@ def test_create(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): # -- Execute "apio create --board alhambra-ii # -- --top-module my_module" with 'n' input - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_create, ["--board", "alhambra-ii", "--top-module", "my_module"], input="n", diff --git a/test/commands/test_drivers.py b/test/commands/test_drivers.py index 40c4d3cd..229ed72a 100644 --- a/test/commands/test_drivers.py +++ b/test/commands/test_drivers.py @@ -2,20 +2,22 @@ Test for the "apio drivers" command """ +from test.conftest import ApioRunner + # -- apio drivers entry point from apio.commands.drivers import cli as apio_drivers -def test_drivers(click_cmd_runner, setup_apio_test_env): +def test_drivers(apio_runner: ApioRunner): """Test "apio drivers" """ - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio drivers" - result = click_cmd_runner.invoke(apio_drivers) + result = apio_runner.invoke(apio_drivers) assert result.exit_code == 1 assert ( "Error: Specify one of [--ftdi-install, --ftdi-uninstall, " @@ -23,7 +25,7 @@ def test_drivers(click_cmd_runner, setup_apio_test_env): ) # -- Execute "apio --ftdi-install, --serial-install" - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_drivers, ["--ftdi-install", "--serial-install"] ) assert result.exit_code == 1, result.output diff --git a/test/commands/test_examples.py b/test/commands/test_examples.py index c220c324..ad0e92c2 100644 --- a/test/commands/test_examples.py +++ b/test/commands/test_examples.py @@ -2,20 +2,22 @@ Test for the "apio examples" command """ +from test.conftest import ApioRunner + # -- apio examples entry point from apio.commands.examples import cli as apio_examples -def test_examples(click_cmd_runner, setup_apio_test_env): +def test_examples(apio_runner: ApioRunner): """Test "apio examples" with different parameters""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio examples" - result = click_cmd_runner.invoke(apio_examples) + result = apio_runner.invoke(apio_examples) assert result.exit_code == 1, result.output assert ( "Error: Specify one of [--list, --fetch-dir, --fetch-files]" @@ -23,21 +25,19 @@ def test_examples(click_cmd_runner, setup_apio_test_env): ) # -- Execute "apio examples --list" - result = click_cmd_runner.invoke(apio_examples, ["--list"]) + result = apio_runner.invoke(apio_examples, ["--list"]) assert result.exit_code == 1, result.output assert "Error: package 'examples' is not installed" in result.output assert "apio packages --install --force examples" in result.output # -- Execute "apio examples --fetch-dir dir" - result = click_cmd_runner.invoke(apio_examples, ["--fetch-dir", "dir"]) + result = apio_runner.invoke(apio_examples, ["--fetch-dir", "dir"]) assert result.exit_code == 1, result.output assert "Error: package 'examples' is not installed" in result.output assert "apio packages --install --force examples" in result.output # -- Execute "apio examples --files file" - result = click_cmd_runner.invoke( - apio_examples, ["--fetch-files", "file"] - ) + result = apio_runner.invoke(apio_examples, ["--fetch-files", "file"]) assert result.exit_code == 1, result.output assert "Error: package 'examples' is not installed" in result.output assert "apio packages --install --force examples" in result.output diff --git a/test/commands/test_fpgas.py b/test/commands/test_fpgas.py index c242cc8f..0da5e824 100644 --- a/test/commands/test_fpgas.py +++ b/test/commands/test_fpgas.py @@ -2,6 +2,8 @@ Test for the "apio boards" command """ +from test.conftest import ApioRunner + # -- apio fpgas entry point from apio.commands.fpgas import cli as apio_fpgas @@ -17,17 +19,17 @@ """ -def test_fpgas_ok(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): +def test_fpgas_ok(apio_runner: ApioRunner): """Test "apio fpgas" command with standard fpgas.json.""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio fpgas" - result = click_cmd_runner.invoke(apio_fpgas) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_fpgas) + apio_runner.assert_ok(result) # -- Note: pytest sees the piped version of the command's output. # -- Run 'apio fpgas' | cat' to reproduce it. assert "Loading custom 'fpgas.json'" not in result.output @@ -35,23 +37,21 @@ def test_fpgas_ok(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): assert "my_custom_fpga" not in result.output -def test_custom_fpga( - click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok -): +def test_custom_fpga(apio_runner: ApioRunner): """Test "apio fpgas" command with a custom fpgas.json.""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Write a custom boards.json file in the project's directory. with open("fpgas.json", "w", encoding="utf-8") as f: f.write(CUSTOM_FPGAS) # -- Execute "apio boards" - result = click_cmd_runner.invoke(apio_fpgas) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_fpgas) + apio_runner.assert_ok(result) # -- Note: pytest sees the piped version of the command's output. # -- Run 'apio build' | cat' to reproduce it. assert "Loading custom 'fpgas.json'" in result.output diff --git a/test/commands/test_graph.py b/test/commands/test_graph.py index 407f5f2f..05c89e4b 100644 --- a/test/commands/test_graph.py +++ b/test/commands/test_graph.py @@ -2,51 +2,51 @@ Test for the "apio graph" command """ +from test.conftest import ApioRunner + # -- apio graph entry point from apio.commands.graph import cli as apio_graph -def test_graph_no_apio_ini(click_cmd_runner, setup_apio_test_env): +def test_graph_no_apio_ini(apio_runner: ApioRunner): """Test: apio graph with no apio.ini""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio graph" - result = click_cmd_runner.invoke(apio_graph) + result = apio_runner.invoke(apio_graph) assert result.exit_code == 1, result.output assert "Error: insufficient arguments: missing board" in result.output -def test_graph_with_apio_ini( - click_cmd_runner, setup_apio_test_env, write_apio_ini -): +def test_graph_with_apio_ini(apio_runner: ApioRunner): """Test: apio graph with apio.ini""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Create an apio.ini file - write_apio_ini({"board": "icezum", "top-module": "main"}) + apio_runner.write_apio_ini({"board": "icezum", "top-module": "main"}) # -- Execute "apio graph" - result = click_cmd_runner.invoke(apio_graph) + result = apio_runner.invoke(apio_graph) assert result.exit_code == 1, result.output assert "package 'oss-cad-suite' is not installed" in result.output assert "apio packages --install --force oss-cad-suite" in result.output # -- Execute "apio graph -pdf" - result = click_cmd_runner.invoke(apio_graph) + result = apio_runner.invoke(apio_graph) assert result.exit_code == 1, result.output assert "package 'oss-cad-suite' is not installed" in result.output assert "apio packages --install --force oss-cad-suite" in result.output # -- Execute "apio graph -png" - result = click_cmd_runner.invoke(apio_graph) + result = apio_runner.invoke(apio_graph) assert result.exit_code == 1, result.output assert "package 'oss-cad-suite' is not installed" in result.output assert "apio packages --install --force oss-cad-suite" in result.output diff --git a/test/commands/test_install.py b/test/commands/test_install.py index d11a942b..b931391b 100644 --- a/test/commands/test_install.py +++ b/test/commands/test_install.py @@ -2,27 +2,29 @@ Test for the "apio install" command """ +from test.conftest import ApioRunner + # -- apio install entry point from apio.commands.install import cli as apio_install -def test_install(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): +def test_install(apio_runner: ApioRunner): """Test "apio install" with different parameters""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio install" - result = click_cmd_runner.invoke(apio_install) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_install) + apio_runner.assert_ok(result) # -- Execute "apio install --list" - result = click_cmd_runner.invoke(apio_install, ["--list"]) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_install, ["--list"]) + apio_runner.assert_ok(result) # -- Execute "apio install missing_package" - result = click_cmd_runner.invoke(apio_install, ["missing_package"]) + result = apio_runner.invoke(apio_install, ["missing_package"]) assert result.exit_code == 1, result.output assert "Error: no such package" in result.output diff --git a/test/commands/test_lint.py b/test/commands/test_lint.py index 394a3c00..fe72bd37 100644 --- a/test/commands/test_lint.py +++ b/test/commands/test_lint.py @@ -2,25 +2,25 @@ Test for the "apio lint" command """ +from test.conftest import ApioRunner + # -- apio lint entry point from apio.commands.lint import cli as apio_lint -def test_lint_no_packages( - click_cmd_runner, setup_apio_test_env, write_apio_ini -): +def test_lint_no_packages(apio_runner: ApioRunner): """Test: apio lint with missing packages.""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Create apio.ini file. - write_apio_ini({"board": "icezum", "top-module": "main"}) + apio_runner.write_apio_ini({"board": "icezum", "top-module": "main"}) # -- Execute "apio lint" - result = click_cmd_runner.invoke(apio_lint) + result = apio_runner.invoke(apio_lint) assert result.exit_code == 1, result.output assert ( "Error: package 'oss-cad-suite' is not installed" in result.output diff --git a/test/commands/test_modify.py b/test/commands/test_modify.py index 71351d05..3600c59a 100644 --- a/test/commands/test_modify.py +++ b/test/commands/test_modify.py @@ -5,8 +5,10 @@ from pathlib import Path from os.path import isfile, exists from typing import Dict +from test.conftest import ApioRunner from configobj import ConfigObj + # -- apio modify entry point from apio.commands.modify import cli as apio_modify @@ -24,21 +26,19 @@ def check_ini_file(apio_ini: Path, expected_vars: Dict[str, str]) -> None: assert conf.dict() == {"env": expected_vars} -def test_modify(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): +def test_modify(apio_runner: ApioRunner): """Test "apio modify" with different parameters""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() apio_ini = Path("apio.ini") assert not exists(apio_ini) # -- Execute "apio modify --top-module my_module" - result = click_cmd_runner.invoke( - apio_modify, ["--top-module", "my_module"] - ) + result = apio_runner.invoke(apio_modify, ["--top-module", "my_module"]) assert result.exit_code != 0, result.output assert "Error: 'apio.ini' not found" in result.output assert not exists(apio_ini) @@ -62,9 +62,7 @@ def test_modify(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): ) # -- Execute "apio modify --board missed_board" - result = click_cmd_runner.invoke( - apio_modify, ["--board", "missed_board"] - ) + result = apio_runner.invoke(apio_modify, ["--board", "missed_board"]) assert result.exit_code == 1, result.output assert "Error: no such board" in result.output check_ini_file( @@ -77,10 +75,8 @@ def test_modify(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): ) # -- Execute "apio modify --board alhambra-ii" - result = click_cmd_runner.invoke( - apio_modify, ["--board", "alhambra-ii"] - ) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_modify, ["--board", "alhambra-ii"]) + apio_runner.assert_ok(result) assert "was modified successfully." in result.output check_ini_file( apio_ini, @@ -92,10 +88,8 @@ def test_modify(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): ) # -- Execute "apio modify --top-module my_main" - result = click_cmd_runner.invoke( - apio_modify, ["--top-module", "my_main"] - ) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_modify, ["--top-module", "my_main"]) + apio_runner.assert_ok(result) assert "was modified successfully." in result.output check_ini_file( apio_ini, @@ -107,10 +101,10 @@ def test_modify(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): ) # -- Execute "apio modify --board icezum --top-module my_top" - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_modify, ["--board", "icezum", "--top-module", "my_top"] ) - assert_apio_cmd_ok(result) + apio_runner.assert_ok(result) assert "was modified successfully." in result.output check_ini_file( apio_ini, diff --git a/test/commands/test_packages.py b/test/commands/test_packages.py index a9c4513e..f7b2fbb3 100644 --- a/test/commands/test_packages.py +++ b/test/commands/test_packages.py @@ -2,20 +2,22 @@ Test for the "apio packages" command """ +from test.conftest import ApioRunner + # -- apio packages entry point from apio.commands.packages import cli as apio_packages -def test_packages(click_cmd_runner, setup_apio_test_env): +def test_packages(apio_runner: ApioRunner): """Test "apio packages" with different parameters""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio packages" - result = click_cmd_runner.invoke(apio_packages) + result = apio_runner.invoke(apio_packages) assert result.exit_code == 1, result.output assert ( "Error: Specify one of [--list, --install, --uninstall, --fix]" @@ -23,19 +25,19 @@ def test_packages(click_cmd_runner, setup_apio_test_env): ) # -- Execute "apio packages --list" - result = click_cmd_runner.invoke(apio_packages, ["--list"]) + result = apio_runner.invoke(apio_packages, ["--list"]) assert result.exit_code == 0, result.output assert "No errors" in result.output # -- Execute "apio packages --install missing_package" - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_packages, ["--install", "missing_package"] ) assert result.exit_code == 1, result.output assert "Error: unknown package 'missing_package'" in result.output # -- Execute "apio packages --uninstall --sayyes missing_package" - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_packages, ["--uninstall", "--sayyes", "missing_package"] ) assert result.exit_code == 1, result.output diff --git a/test/commands/test_report.py b/test/commands/test_report.py index 9685fa0d..512c04fe 100644 --- a/test/commands/test_report.py +++ b/test/commands/test_report.py @@ -2,25 +2,27 @@ Test for the "apio report" command """ +from test.conftest import ApioRunner + # -- apio report entry point from apio.commands.report import cli as apio_report # R0801: Similar lines in 2 files # pylint: disable=R0801 -def test_report(click_cmd_runner, setup_apio_test_env): +def test_report(apio_runner: ApioRunner): """Test: apio report when no apio.ini file is given No additional parameters are given """ - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio report" - result = click_cmd_runner.invoke(apio_report) + result = apio_runner.invoke(apio_report) # -- Check the result assert result.exit_code != 0, result.output @@ -28,18 +30,18 @@ def test_report(click_cmd_runner, setup_apio_test_env): assert "Error: insufficient arguments: missing board" in result.output -def test_report_board(click_cmd_runner, setup_apio_test_env): +def test_report_board(apio_runner: ApioRunner): """Test: apio report when parameters are given """ - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio report" - result = click_cmd_runner.invoke(apio_report, ["--board", "icezum"]) + result = apio_runner.invoke(apio_report, ["--board", "icezum"]) # -- Check the result assert result.exit_code != 0, result.output diff --git a/test/commands/test_sim.py b/test/commands/test_sim.py index 2288556b..53c69b7d 100644 --- a/test/commands/test_sim.py +++ b/test/commands/test_sim.py @@ -2,22 +2,24 @@ Test for the "apio sim" command """ +from test.conftest import ApioRunner + # -- apio sim entry point from apio.commands.sim import cli as apio_sim -def test_sim(click_cmd_runner, setup_apio_test_env): +def test_sim(apio_runner: ApioRunner): """Test: apio sim when no apio.ini file is given No additional parameters are given """ - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- apio sim --board icezum - result = click_cmd_runner.invoke(apio_sim) + result = apio_runner.invoke(apio_sim) assert result.exit_code != 0, result.output # -- TODO diff --git a/test/commands/test_system.py b/test/commands/test_system.py index 2053d7ba..3392c8be 100644 --- a/test/commands/test_system.py +++ b/test/commands/test_system.py @@ -2,20 +2,22 @@ Test for the "apio system" command """ +from test.conftest import ApioRunner + # -- apio system entry point from apio.commands.system import cli as apio_system -def test_system(click_cmd_runner, setup_apio_test_env): +def test_system(apio_runner: ApioRunner): """Test "apio system" with different parameters""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio system" - result = click_cmd_runner.invoke(apio_system) + result = apio_runner.invoke(apio_system) assert result.exit_code == 1, result.output assert ( "Specify one of " @@ -24,22 +26,22 @@ def test_system(click_cmd_runner, setup_apio_test_env): ) # -- Execute "apio system --lsftdi" - result = click_cmd_runner.invoke(apio_system, ["--lsftdi"]) + result = apio_runner.invoke(apio_system, ["--lsftdi"]) assert result.exit_code == 1, result.output assert "apio packages --install --force oss-cad-suite" in result.output # -- Execute "apio system --lsusb" - result = click_cmd_runner.invoke(apio_system, ["--lsusb"]) + result = apio_runner.invoke(apio_system, ["--lsusb"]) assert result.exit_code == 1, result.output assert "apio packages --install --force oss-cad-suite" in result.output # -- Execute "apio system --lsserial" - click_cmd_runner.invoke(apio_system, ["--lsserial"]) + apio_runner.invoke(apio_system, ["--lsserial"]) assert result.exit_code == 1, result.output assert "apio packages --install --force oss-cad-suite" in result.output # -- Execute "apio system --info" - result = click_cmd_runner.invoke(apio_system, ["--info"]) + result = apio_runner.invoke(apio_system, ["--info"]) assert result.exit_code == 0, result.output assert "Platform id" in result.output # -- The these env options are set by the apio text fixture. diff --git a/test/commands/test_test.py b/test/commands/test_test.py index 3629344a..a50d0236 100644 --- a/test/commands/test_test.py +++ b/test/commands/test_test.py @@ -2,22 +2,24 @@ Test for the "apio test" command """ +from test.conftest import ApioRunner + # -- apio test entry point from apio.commands.sim import cli as apio_test -def test_test(click_cmd_runner, setup_apio_test_env): +def test_test(apio_runner: ApioRunner): """Test: apio test when no apio.ini file is given No additional parameters are given """ - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio test" - result = click_cmd_runner.invoke(apio_test) + result = apio_runner.invoke(apio_test) assert result.exit_code != 0, result.output # -- TODO diff --git a/test/commands/test_time.py b/test/commands/test_time.py index 347084c4..91b4cafd 100644 --- a/test/commands/test_time.py +++ b/test/commands/test_time.py @@ -2,25 +2,27 @@ Test for the "apio time" command """ +from test.conftest import ApioRunner + # -- apio time entry point from apio.commands.time import cli as apio_time # R0801: Similar lines in 2 files # pylint: disable=R0801 -def test_time(click_cmd_runner, setup_apio_test_env): +def test_time(apio_runner: ApioRunner): """Test: apio time when no apio.ini file is given No additional parameters are given """ - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio time" - result = click_cmd_runner.invoke(apio_time) + result = apio_runner.invoke(apio_time) # -- Check the result assert result.exit_code != 0, result.output @@ -28,18 +30,18 @@ def test_time(click_cmd_runner, setup_apio_test_env): assert "Error: insufficient arguments: missing board" in result.output -def test_time_board(click_cmd_runner, setup_apio_test_env): +def test_time_board(apio_runner: ApioRunner): """Test: apio time when parameters are given """ - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio time" - result = click_cmd_runner.invoke(apio_time, ["--board", "icezum"]) + result = apio_runner.invoke(apio_time, ["--board", "icezum"]) # -- Check the result assert result.exit_code != 0, result.output diff --git a/test/commands/test_uninstall.py b/test/commands/test_uninstall.py index b86baa19..790152b7 100644 --- a/test/commands/test_uninstall.py +++ b/test/commands/test_uninstall.py @@ -2,28 +2,30 @@ Test for the "apio uninstall" command """ +from test.conftest import ApioRunner + # -- apio uninstall entry point from apio.commands.uninstall import cli as apio_uninstall -def test_uninstall(click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok): +def test_uninstall(apio_runner: ApioRunner): """Test "apio uninstall" with different parameters""" - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio uninstall" - result = click_cmd_runner.invoke(apio_uninstall) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_uninstall) + apio_runner.assert_ok(result) # -- Execute "apio uninstall --list" - result = click_cmd_runner.invoke(apio_uninstall, ["--list"]) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_uninstall, ["--list"]) + apio_runner.assert_ok(result) # -- Execute "apio uninstall missing_packge" - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_uninstall, ["missing_package"], input="y" ) assert result.exit_code == 1, result.output diff --git a/test/commands/test_upgrade.py b/test/commands/test_upgrade.py index 7d89cbe4..c4a91eea 100644 --- a/test/commands/test_upgrade.py +++ b/test/commands/test_upgrade.py @@ -2,27 +2,27 @@ Test for the "apio upgrade" command """ +from test.conftest import ApioRunner import pytest + # -- apio upgrade entry point from apio.commands.upgrade import cli as apio_upgrade -def test_upgrade( - click_cmd_runner, setup_apio_test_env, assert_apio_cmd_ok, offline_flag -): +def test_upgrade(apio_runner: ApioRunner): """Test "apio upgrade" """ # -- If the option 'offline' is passed, the test is skip # -- (apio upgrade uses internet) - if offline_flag: + if apio_runner.offline_flag: pytest.skip("requires internet connection") - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio upgrade" - result = click_cmd_runner.invoke(apio_upgrade) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_upgrade) + apio_runner.assert_ok(result) diff --git a/test/commands/test_upload.py b/test/commands/test_upload.py index e47ffba7..8a7a1522 100644 --- a/test/commands/test_upload.py +++ b/test/commands/test_upload.py @@ -2,23 +2,25 @@ Test for the "apio upload" command """ +from test.conftest import ApioRunner + # -- apio time entry point from apio.commands.upload import cli as apio_upload -def test_upload(click_cmd_runner, setup_apio_test_env): +def test_upload(apio_runner: ApioRunner): """Test: apio upload when no apio.ini file is given No additional parameters are given """ - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio upload" - result = click_cmd_runner.invoke(apio_upload) + result = apio_runner.invoke(apio_upload) # -- Check the result assert result.exit_code == 1, result.output @@ -26,18 +28,18 @@ def test_upload(click_cmd_runner, setup_apio_test_env): assert "Error: insufficient arguments: missing board" in result.output -def test_upload_board(click_cmd_runner, setup_apio_test_env): +def test_upload_board(apio_runner: ApioRunner): """Test: apio upload --board icezum No oss-cad-suite package is installed """ - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio upload --board icezum" - result = click_cmd_runner.invoke(apio_upload, ["--board", "icezum"]) + result = apio_runner.invoke(apio_upload, ["--board", "icezum"]) # -- Check the result assert result.exit_code == 1 @@ -46,38 +48,36 @@ def test_upload_board(click_cmd_runner, setup_apio_test_env): ) -def test_upload_complete(click_cmd_runner, setup_apio_test_env): +def test_upload_complete(apio_runner: ApioRunner): """Test: apio upload with different arguments No apio.ini file is given """ - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio upload --serial-port COM0" - result = click_cmd_runner.invoke( - apio_upload, ["--serial-port", "COM0"] - ) + result = apio_runner.invoke(apio_upload, ["--serial-port", "COM0"]) assert result.exit_code == 1, result.output assert "Info: Project has no apio.ini file" in result.output assert "Error: insufficient arguments: missing board" in result.output # -- Execute "apio upload --ftdi-id 0" - result = click_cmd_runner.invoke(apio_upload, ["--ftdi-id", "0"]) + result = apio_runner.invoke(apio_upload, ["--ftdi-id", "0"]) assert result.exit_code == 1, result.output assert "Info: Project has no apio.ini file" in result.output assert "Error: insufficient arguments: missing board" in result.output # -- Execute "apio upload --sram" - result = click_cmd_runner.invoke(apio_upload, ["--sram"]) + result = apio_runner.invoke(apio_upload, ["--sram"]) assert result.exit_code == 1, result.output assert "Info: Project has no apio.ini file" in result.output assert "Error: insufficient arguments: missing board" in result.output # -- Execute "apio upload --board icezum --serial-port COM0" - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_upload, ["--board", "icezum", "--serial-port", "COM0"] ) assert result.exit_code == 1, result.output @@ -86,7 +86,7 @@ def test_upload_complete(click_cmd_runner, setup_apio_test_env): ) # -- Execute "apio upload --board icezum --ftdi-id 0" - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_upload, ["--board", "icezum", "--ftdi-id", "0"] ) assert result.exit_code == 1, result.output @@ -95,7 +95,7 @@ def test_upload_complete(click_cmd_runner, setup_apio_test_env): ) # -- Execute "apio upload --board icezum --sram" - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_upload, ["--board", "icezum", "--sram"] ) assert result.exit_code == 1, result.output diff --git a/test/commands/test_verify.py b/test/commands/test_verify.py index 4a79bde6..e8da9c8d 100644 --- a/test/commands/test_verify.py +++ b/test/commands/test_verify.py @@ -2,23 +2,25 @@ Test for the "apio verify" command """ +from test.conftest import ApioRunner + # -- apio verify entry point from apio.commands.verify import cli as apio_verify -def test_verify(click_cmd_runner, setup_apio_test_env): +def test_verify(apio_runner: ApioRunner): """Test: apio verify when no apio.ini file is given No additional parameters are given """ - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio verify" - result = click_cmd_runner.invoke(apio_verify, ["--board", "icezum"]) + result = apio_runner.invoke(apio_verify, ["--board", "icezum"]) # -- Check the result assert result.exit_code != 0, result.output diff --git a/test/conftest.py b/test/conftest.py index faa0eb51..cba73513 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -3,11 +3,10 @@ TEST configuration file """ -# os.environ: Access to environment variables -# https://docs.python.org/3/library/os.html#os.environ -from os import environ, listdir from pathlib import Path +from typing import Tuple from typing import Dict +import os import pytest @@ -22,83 +21,155 @@ # -- Debug mode on/off DEBUG = True +# -- Apio should be able to handle spaces and unicode in its home, packages, +# -- and project directory path. We insert this marker in the test pathes to +# -- test it. +# +# -- TODO: Currently apio doesn't handle well spaces in the pathes. Fix it and +# -- change this to " fuññy ". For more details see +# -- https://github.com/FPGAwars/apio/issues/474. +FUNNY_MARKER = "fuññy" -@pytest.fixture(scope="module") -def click_cmd_runner(): - """A pytest fixture that provides tests with a click commands runner.""" - return CliRunner() +# -- This function is called by pytest. It addes the pytest --offline flag +# -- which is is passed to tests that ask for it using the fixture +# -- 'offline_flag' below. +# -- +# -- More info: https://docs.pytest.org/en/7.1.x/example/simple.html +def pytest_addoption(parser: pytest.Parser): + """Register the --offline command line option when invoking pytest""" -@pytest.fixture(scope="session") -def setup_apio_test_env(): - """An pytest fixture that provides tests with a function to set up the - apio test environment. By default, the tests run in a temporaly folder - (in /tmp/xxxxx). + # -- Option: --offline + # -- It is used by the function test that requieres + # -- internet connnection for testing + parser.addoption( + "--offline", action="store_true", help="Run tests in offline mode" + ) + + +class ApioRunner: + """Apio commands test helper. An object of this class is provided to the + tests via the apio_runner fixture and a typical tests looks like this: + + def test_my_cmd(apio_runner): + with apio_runner.isolated_filesystem(): - Should be called within the click_cmd_runner.isolated_filesystem() scope. + apio_runner.setup_env() + + """ - def decorator(): + def __init__(self, request): + # -- A CliRunner instance that is used for creating temp directories + # -- and to invoke apio commands. + self._request = request + self._click_runner = CliRunner() + + # -- Save the original system path so we can restore it before each + # -- invocation since some apio commands mutate it and pytest runs + # -- multiple apio command in the same python process. + self._original_path = os.environ["PATH"] + + # -- Set later by set_env(). + self._proj_dir: Path = None + self._home_dir: Path = None + self._packages_dir: Path = None + + def in_disposable_temp_dir(self): + """Returns a context manager which creates a temp directory upon + entering it and deleting it upon existing.""" + return self._click_runner.isolated_filesystem() + + def setup_env(self) -> Tuple[Path, Path, Path]: + """Should be called by the test within the 'in_disposable_temp_dir' + scope to set up the apio specific environment.""" # -- Current directory is the root test dir. Should be empty. test_dir = Path.cwd() - assert not listdir(test_dir) + assert not os.listdir(test_dir) - # -- TODO: Having a space in the funny directory name fails - # -- the test. Fix it and change to " fuññy ". The problem seems to be - # -- in the invocation of iverilog by 'apio test' when the packges dir - # -- contain a space. - # # -- Using unicode and space to verify that they are handled correctly. - funny_dir = test_dir / "fuññy" + funny_dir = test_dir / FUNNY_MARKER funny_dir.mkdir(parents=False, exist_ok=False) # -- Apio dirs - apio_proj_dir = funny_dir / "proj" - apio_home_dir = funny_dir / "apio" - apio_packages_dir = funny_dir / "packages" + self._proj_dir = funny_dir / "proj" + self._home_dir = funny_dir / "apio" + self._packages_dir = funny_dir / "packages" if DEBUG: print("") - print(" --> setup_apio_test_env():") - print(f" test dir : {str(test_dir)}") - print(f" apio proj dir : {str(apio_proj_dir)}") - print(f" apio home dir : {str(apio_home_dir)}") - print(f" apio packages dir : {str(apio_packages_dir)}") - - # pylint: disable=fixme - # TODO: solve the problem of the over growing PATH because we run - # multiple apio invocations within one pytest process. - print() - print(f"PATH={environ['PATH']}") - print() - - # -- Set the apio home dir and apio packages dir to - # -- this test folder. Apio uses these as an override to the defaults. - environ["APIO_HOME_DIR"] = str(apio_home_dir) - environ["APIO_PACKAGES_DIR"] = str(apio_packages_dir) - - # -- TODO: This looks like a flag. Describe what it do. - environ["TESTING"] = "" + print(" --> apio_runner.setup_env():") + print(f" test dir : {str(test_dir)}") + print(f" apio proj dir : {str(self._proj_dir)}") + print(f" apio home dir : {str(self._home_dir)}") + print(f" apio packages dir : {str(self._packages_dir)}") # -- Apio dirs do not exist yet. - assert not apio_proj_dir.exists() - assert not apio_home_dir.exists() - assert not apio_packages_dir.exists() + assert not self._proj_dir.exists() + assert not self._home_dir.exists() + assert not self._packages_dir.exists() - # -- All done, return the values. - return (apio_proj_dir, apio_home_dir, apio_packages_dir) - - return decorator - - -@pytest.fixture(scope="session") -def assert_apio_cmd_ok(): - """A pytest fixture that provides a function to assert that apio click - command result were ok. - """ + # -- TODO: This looks like a flag. Describe what it do. + os.environ["TESTING"] = "" - def decorator(result: Result): - """Check if the result is ok""" + # -- All done, return the values. + return ( + self._proj_dir, + self._home_dir, + self._packages_dir, + ) + + # R0913: Too many arguments (7/5) (too-many-arguments) + # pylint: disable=R0913 + # W0622: Redefining built-in 'input' (redefined-builtin) + # pylint: disable=W0622 + # R0917: Too many positional arguments (7/5) + # pylint: disable=R0917 + def invoke( + self, + cli, + args=None, + input=None, + env=None, + catch_exceptions=True, + color=False, + **extra, + ): + """Invoke an apio command.""" + + # -- Restore the original path, since some apio commands mutate it and + # -- pytest runs multiple commands in the same python process. + os.environ["PATH"] = self._original_path + + # -- This typically fails if the test did not call setup_env() before4 + # -- invoking a command. + assert FUNNY_MARKER in str(self._home_dir) + assert FUNNY_MARKER in str(self._packages_dir) + + # -- Set the env to infrom the apio command where are the apio test + # -- home and packages dir are. + os.environ["APIO_HOME_DIR"] = str(self._home_dir) + os.environ["APIO_PACKAGES_DIR"] = str(self._packages_dir) + + # -- Double check. + assert FUNNY_MARKER in os.environ["APIO_HOME_DIR"] + assert FUNNY_MARKER in os.environ["APIO_PACKAGES_DIR"] + + # -- Invoke the command. Get back the collected results. + result = self._click_runner.invoke( + cli=cli, + args=args, + input=input, + env=env, + catch_exceptions=catch_exceptions, + color=color, + **extra, + ) + + return result + + def assert_ok(self, result: Result): + """Check if apio command results where ok""" # -- It should return an exit code of 0: success assert result.exit_code == 0, result.output @@ -109,17 +180,10 @@ def decorator(result: Result): # -- The word 'error' should NOT appear on the standard output assert "error" not in result.output.lower() - return decorator - - -@pytest.fixture(scope="session") -def write_apio_ini(): - """A pytest fixture to write a project apio.ini file. If properties - is Nonethe file apio.ini is deleted if it exists. - """ - - def decorator(properties: Dict[str, str]): - """The apio.ini actual writer""" + def write_apio_ini(self, properties: Dict[str, str]): + """Write in the current directory an apio.ini file with given + values. If an apio.ini file alread exists, it is overwritten. + if properties is None and an apio.ini file exists, it is deleted.""" path = Path("apio.ini") @@ -132,29 +196,15 @@ def decorator(properties: Dict[str, str]): for name, value in properties.items(): f.write(f"{name} = {value}\n") - return decorator + @property + def offline_flag(self) -> bool: + """Returns True if pytest was invoked with --offline to skip + tests that require internet connectivity and are slower in general.""" + return self._request.config.getoption("--offline") -# -- This function is called by pytest. It addes the pytest --offline flag -# -- which is is passed to tests that ask for it using the fixture -# -- 'offline_flag' below. -# -- -# -- More info: https://docs.pytest.org/en/7.1.x/example/simple.html -def pytest_addoption(parser: pytest.Parser): - """Register the --offline command line option when invoking pytest""" - - # -- Option: --offline - # -- It is used by the function test that requieres - # -- internet connnection for testing - parser.addoption( - "--offline", action="store_true", help="Run tests in offline mode" - ) - - -@pytest.fixture -def offline_flag(request): - """Return the value of the pytest '--offline' flag register above. - This flag can be set by the user when invoking pytest to disable - test functionality that requires internet connectivity. - """ - return request.config.getoption("--offline") +@pytest.fixture(scope="session") +def apio_runner(request): + """A pytest fixture that provides tests with a ApioRunner test + helper object.""" + return ApioRunner(request) diff --git a/test/integration/test_examples.py b/test/integration/test_examples.py index 8817423c..9bc87031 100644 --- a/test/integration/test_examples.py +++ b/test/integration/test_examples.py @@ -4,6 +4,7 @@ from os import chdir from os.path import getsize +from test.conftest import ApioRunner import pytest # -- Entry point for apio commands. @@ -13,82 +14,75 @@ # R0801: Similar lines in 2 files # pylint: disable=R0801 -def test_examples( - click_cmd_runner, - setup_apio_test_env, - assert_apio_cmd_ok, - offline_flag, -): +def test_examples(apio_runner: ApioRunner): """Tests the listing and fetching apio examples.""" # -- If the option 'offline' is passed, the test is skip # -- (This test is slow and requires internet connectivity) - if offline_flag: + if apio_runner.offline_flag: pytest.skip("requires internet connection") - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - proj_dir, _, packages_dir = setup_apio_test_env() + proj_dir, _, packages_dir = apio_runner.setup_env() # -- Create and change to project dir. proj_dir.mkdir(exist_ok=False) chdir(proj_dir) # -- Install the examples package. - result = click_cmd_runner.invoke( - apio_packages, ["--install", "examples"] - ) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_packages, ["--install", "examples"]) + apio_runner.assert_ok(result) # assert "Installing package 'examples'" in result.output # assert "Download" in result.output assert "Package 'examples' installed successfully" in result.output assert getsize(packages_dir / "examples/Alhambra-II/ledon/ledon.v") # -- List the examples - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_examples, ["--list"], ) - assert_apio_cmd_ok(result) + apio_runner.assert_ok(result) assert "Alhambra-II/ledon" in result.output # -- Fetch example files to current directory - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_examples, ["--fetch-files", "Alhambra-II/ledon"], ) - assert_apio_cmd_ok(result) + apio_runner.assert_ok(result) assert "Copying Alhambra-II/ledon example files" in result.output assert "have been successfully created!" in result.output assert getsize("ledon.v") # -- Fetch example dir to current directory - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_examples, ["--fetch-dir", "Alhambra-II/ledon"], ) - assert_apio_cmd_ok(result) + apio_runner.assert_ok(result) assert "Creating Alhambra-II/ledon directory" in result.output assert "has been successfully created" in result.output assert getsize("Alhambra-II/ledon/ledon.v") # -- Fetch example files to another project dir - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_examples, ["--fetch-files", "Alhambra-II/ledon", "--project-dir=./dir1"], ) - assert_apio_cmd_ok(result) + apio_runner.assert_ok(result) assert "Copying Alhambra-II/ledon example files" in result.output assert "have been successfully created!" in result.output assert getsize("dir1/ledon.v") # -- Fetch example dir to another project dir - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_examples, ["--fetch-dir", "Alhambra-II/ledon", "--project-dir=dir2"], ) - assert_apio_cmd_ok(result) + apio_runner.assert_ok(result) assert "Creating Alhambra-II/ledon directory" in result.output assert "has been successfully created" in result.output assert getsize("dir2/Alhambra-II/ledon/ledon.v") diff --git a/test/integration/test_packages.py b/test/integration/test_packages.py index 0556873c..27fd6c7a 100644 --- a/test/integration/test_packages.py +++ b/test/integration/test_packages.py @@ -3,6 +3,7 @@ """ from os import listdir, chdir +from test.conftest import ApioRunner import pytest # -- Entry point for apio commands. @@ -13,30 +14,25 @@ # pylint: disable=R0801 # # R0915: Too many statements (52/50) (too-many-statements) # # pylint: disable=R0915 -def test_packages( - click_cmd_runner, - setup_apio_test_env, - assert_apio_cmd_ok, - offline_flag, -): +def test_packages(apio_runner: ApioRunner): """Tests listing, installation and uninstallation of packages.""" # -- If the option 'offline' is passed, the test is skip # -- (This test is slow and requires internet connectivity) - if offline_flag: + if apio_runner.offline_flag: pytest.skip("requires internet connection") - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - proj_dir, _, packages_dir = setup_apio_test_env() + proj_dir, _, packages_dir = apio_runner.setup_env() # -- Create and change to project dir. proj_dir.mkdir(exist_ok=False) chdir(proj_dir) # -- List packages - result = click_cmd_runner.invoke(apio_packages, ["--list"]) + result = apio_runner.invoke(apio_packages, ["--list"]) assert result.exit_code == 0 assert "No errors" in result.output assert "examples" in result.output @@ -47,10 +43,8 @@ def test_packages( # -- Install the examples package. Package 'examples' should exist, # -- and package 'tools-oss-cad-suite' should not. - result = click_cmd_runner.invoke( - apio_packages, ["--install", "examples"] - ) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_packages, ["--install", "examples"]) + apio_runner.assert_ok(result) assert "Package 'examples' installed successfully" in result.output assert listdir(packages_dir / "examples/Alhambra-II") assert "tools-oss-cad-suite" not in listdir(packages_dir) @@ -58,8 +52,8 @@ def test_packages( # -- Install the reset of the packages. # -- Both 'examples' and 'tools-oss-cad-suite' should exist, and # -- maybe others, depending on the platform. - result = click_cmd_runner.invoke(apio_packages, ["--install"]) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_packages, ["--install"]) + apio_runner.assert_ok(result) assert "Package 'examples' installed successfully" not in result.output assert ( "Package 'oss-cad-suite' installed successfully" in result.output @@ -76,27 +70,25 @@ def test_packages( # -- Install the examples packages without forcing. # -- This should not do anything since it's considered to be installed. - result = click_cmd_runner.invoke( - apio_packages, ["--install", "examples"] - ) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_packages, ["--install", "examples"]) + apio_runner.assert_ok(result) assert "was already install" in result.output assert "Package 'examples' installed" not in result.output assert not marker_file.exists() # -- Install the examples packages with forcing. # -- This should recover the file. - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_packages, ["--install", "--force", "examples"] ) - assert_apio_cmd_ok(result) + apio_runner.assert_ok(result) assert "Package 'examples' installed" in result.output assert marker_file.is_file() # -- Try to uninstall the 'examples' package without user approval. # -- should exit with an error message. assert "examples" in listdir(packages_dir) - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_packages, ["--uninstall", "examples"], input="n" ) assert result.exit_code == 1 @@ -107,18 +99,16 @@ def test_packages( # -- Uninstall the examples package. It should delete the exemples # -- package and will live the rest. assert "examples" in listdir(packages_dir) - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_packages, ["--uninstall", "examples"], input="y" ) - assert_apio_cmd_ok(result) + apio_runner.assert_ok(result) assert "examples" not in listdir(packages_dir) assert "tools-oss-cad-suite" in listdir(packages_dir) # -- Uninstall all packages. This should uninstall also the # -- oss-cad-suite package. - result = click_cmd_runner.invoke( - apio_packages, ["--uninstall", "--sayyes"] - ) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_packages, ["--uninstall", "--sayyes"]) + apio_runner.assert_ok(result) assert "examples" not in listdir(packages_dir) assert "tools-oss-cad-suite" not in listdir(packages_dir) diff --git a/test/integration/test_project_ice40.py b/test/integration/test_project_ice40.py index 26ce36c4..0ae65708 100644 --- a/test/integration/test_project_ice40.py +++ b/test/integration/test_project_ice40.py @@ -5,6 +5,7 @@ from os import listdir, chdir from os.path import getsize from pathlib import Path +from test.conftest import ApioRunner import pytest # -- Entry point for apio commands. @@ -20,33 +21,26 @@ # R0801: Similar lines in 2 files # pylint: disable=R0801 -def test_project_ice40( - click_cmd_runner, - setup_apio_test_env, - assert_apio_cmd_ok, - offline_flag, -): +def test_project_ice40(apio_runner: ApioRunner): """Tests building and testing a project.""" # -- If the option 'offline' is passed, the test is skip # -- (This test is slow and requires internet connectivity) - if offline_flag: + if apio_runner.offline_flag: pytest.skip("requires internet connection") - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment. - proj_dir, _, packages_dir = setup_apio_test_env() + proj_dir, _, packages_dir = apio_runner.setup_env() # -- Create and change to project dir. proj_dir.mkdir(exist_ok=False) chdir(proj_dir) # -- Install all packages - result = click_cmd_runner.invoke( - apio_packages, ["--install", "--verbose"] - ) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_packages, ["--install", "--verbose"]) + apio_runner.assert_ok(result) assert "'examples' installed successfully" in result.output assert "'oss-cad-suite' installed successfully" in result.output assert listdir(packages_dir / "examples") @@ -56,11 +50,11 @@ def test_project_ice40( assert not listdir(".") # -- Fetch example files to current directory - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_examples, ["--fetch-files", "Alhambra-II/ledon"], ) - assert_apio_cmd_ok(result) + apio_runner.assert_ok(result) assert "Copying Alhambra-II/ledon example files" in result.output assert "have been successfully created!" in result.output assert getsize("apio.ini") @@ -69,41 +63,41 @@ def test_project_ice40( project_files = listdir(".") # -- Build the project. - result = click_cmd_runner.invoke(apio_build) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_build) + apio_runner.assert_ok(result) assert "SUCCESS" in result.output assert getsize("_build/hardware.bin") # -- Lint - result = click_cmd_runner.invoke(apio_lint) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_lint) + apio_runner.assert_ok(result) assert "SUCCESS" in result.output assert getsize("_build/hardware.vlt") # -- Test - result = click_cmd_runner.invoke(apio_test) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_test) + apio_runner.assert_ok(result) assert "SUCCESS" in result.output assert getsize("_build/ledon_tb.out") assert getsize("_build/ledon_tb.vcd") # -- Report - result = click_cmd_runner.invoke(apio_report) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_report) + apio_runner.assert_ok(result) assert "SUCCESS" in result.output assert "ICESTORM_LC:" in result.output assert getsize("_build/hardware.pnr") # -- Graph svg - result = click_cmd_runner.invoke(apio_graph) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_graph) + apio_runner.assert_ok(result) assert "SUCCESS" in result.output assert getsize("_build/hardware.dot") assert getsize("_build/hardware.svg") # -- Clean - result = click_cmd_runner.invoke(apio_clean) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_clean) + apio_runner.assert_ok(result) assert "SUCCESS" in result.output assert not Path("_build").exists() diff --git a/test/integration/test_utilities.py b/test/integration/test_utilities.py index f346baa9..a9f559be 100644 --- a/test/integration/test_utilities.py +++ b/test/integration/test_utilities.py @@ -3,8 +3,10 @@ """ from os import listdir, chdir +from test.conftest import ApioRunner import pytest + # -- Entry point for apio commands. from apio.commands.raw import cli as apio_raw from apio.commands.upgrade import cli as apio_upgrade @@ -14,50 +16,43 @@ # R0801: Similar lines in 2 files # pylint: disable=R0801 -def test_utilities( - click_cmd_runner, - setup_apio_test_env, - assert_apio_cmd_ok, - offline_flag, -): - """Tests utility commands.""" +def test_utilities(apio_runner: ApioRunner): + """Tests apio utility commands.""" # -- If the option 'offline' is passed, the test is skip # -- (This test is slow and requires internet connectivity) - if offline_flag: + if apio_runner.offline_flag: pytest.skip("requires internet connection") - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment. - proj_dir, _, packages_dir = setup_apio_test_env() + proj_dir, _, packages_dir = apio_runner.setup_env() # -- Create and change to project dir. proj_dir.mkdir(exist_ok=False) chdir(proj_dir) # -- Install all packages - result = click_cmd_runner.invoke( - apio_packages, ["--install", "--verbose"] - ) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_packages, ["--install", "--verbose"]) + apio_runner.assert_ok(result) assert "'examples' installed successfully" in result.output assert "'oss-cad-suite' installed successfully" in result.output assert listdir(packages_dir / "examples") assert listdir(packages_dir / "tools-oss-cad-suite") # -- Run 'apio upgrade' - result = click_cmd_runner.invoke(apio_upgrade) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_upgrade) + apio_runner.assert_ok(result) assert "Lastest Apio stable version" in result.output # -- Run 'apio system --info' - result = click_cmd_runner.invoke(apio_system, ["--info"]) - assert_apio_cmd_ok(result) + result = apio_runner.invoke(apio_system, ["--info"]) + apio_runner.assert_ok(result) assert "Apio version" in result.output # -- Run 'apio raw --env "nextpnr-ice40 --help" - result = click_cmd_runner.invoke( + result = apio_runner.invoke( apio_raw, ["--env", "nextpnr-ice40 --help"], input="exit" ) - assert_apio_cmd_ok(result) + apio_runner.assert_ok(result) diff --git a/test/test_apio.py b/test/test_apio.py index 9691de68..67e0c917 100644 --- a/test/test_apio.py +++ b/test/test_apio.py @@ -2,6 +2,9 @@ Test for command apio """ +from test.conftest import ApioRunner + + # ----------------------------------------------------------------------- # -- RUN manually: # -- pytest -v test/test_apio.py @@ -14,34 +17,31 @@ # -- pytest -v -s test/test_apio.py::test_apio # ------------------------------------------------------------------------ -from click.testing import CliRunner # -- Import the cli entry point: apio/__main__.py from apio.__main__ import cli as cmd_apio -def test_apio( - click_cmd_runner: CliRunner, assert_apio_cmd_ok, setup_apio_test_env -): +def test_apio(apio_runner: ApioRunner): """Test command "apio" without arguments $ apio Usage: apio [OPTIONS] COMMAND [ARGS]... [...] """ - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the apio test environment - setup_apio_test_env() + apio_runner.setup_env() # -- Invoke the apio command - result = click_cmd_runner.invoke(cmd_apio) + result = apio_runner.invoke(cmd_apio) # -- Check that everything is ok - assert_apio_cmd_ok(result) + apio_runner.assert_ok(result) -def test_apio_wrong_command(click_cmd_runner: CliRunner, setup_apio_test_env): +def test_apio_wrong_command(apio_runner: ApioRunner): """Test apio command with an invalid command $ apio wrong Usage: apio [OPTIONS] COMMAND [ARGS]... @@ -50,13 +50,13 @@ def test_apio_wrong_command(click_cmd_runner: CliRunner, setup_apio_test_env): Error: No such command 'wrong'. """ - with click_cmd_runner.isolated_filesystem(): + with apio_runner.in_disposable_temp_dir(): # -- Config the environment - setup_apio_test_env() + apio_runner.setup_env() # -- Execute "apio mmissing_command" - result = click_cmd_runner.invoke(cmd_apio, ["wrong_command"]) + result = apio_runner.invoke(cmd_apio, ["wrong_command"]) # -- Check the error code assert result.exit_code == 2, result.output From c0ee6395073b3f52b925aecae7ced8a25fcde07a Mon Sep 17 00:00:00 2001 From: Zapta Date: Mon, 25 Nov 2024 13:46:19 -0800 Subject: [PATCH 12/13] Added a project build integration test for ecp5 (was only ice40). This commit redirects the 'examples' packge to my own provate repo until the official one will be update with the latest PR. --- apio/resources/packages.json | 6 +-- apio/scons/ecp5/SConstruct | 4 +- ...test_project_ice40.py => test_projects.py} | 47 +++++++++++++++---- 3 files changed, 45 insertions(+), 12 deletions(-) rename test/integration/{test_project_ice40.py => test_projects.py} (76%) diff --git a/apio/resources/packages.json b/apio/resources/packages.json index 83f2148a..58afc98a 100644 --- a/apio/resources/packages.json +++ b/apio/resources/packages.json @@ -2,7 +2,7 @@ "examples": { "repository": { "name": "apio-examples", - "organization": "FPGAwars" + "organization": "zapta" }, "release": { "tag_name": "%V", @@ -10,7 +10,7 @@ "uncompressed_name": "apio-examples-%V", "folder_name": "examples", "extension": "zip", - "url_version": "https://github.com/FPGAwars/apio-examples/raw/master/VERSION" + "url_version": "https://github.com/zapta/apio-examples/raw/master/VERSION" }, "description": "Verilog examples", "env": {} @@ -112,4 +112,4 @@ ] } } -} \ No newline at end of file +} diff --git a/apio/scons/ecp5/SConstruct b/apio/scons/ecp5/SConstruct index b7633c89..6ac47705 100644 --- a/apio/scons/ecp5/SConstruct +++ b/apio/scons/ecp5/SConstruct @@ -48,6 +48,7 @@ from SCons.Script import ( ) from apio.scons.scons_util import ( TARGET, + BUILD_DIR, SConstructId, is_testbench, basename, @@ -168,9 +169,10 @@ env.Append(BUILDERS={"PnR": pnr_builder}) # -- Builder (icepack, bitstream generator). # -- hardware.config -> hardware.bit. bitstream_builder = Builder( - action="ecppack --compress --db {0} {1} $SOURCE hardware.bit".format( + action="ecppack --compress --db {0} {1} $SOURCE {2}/hardware.bit".format( DATABASE_PATH, "" if not FPGA_IDCODE else f"--idcode {FPGA_IDCODE}", + BUILD_DIR, ), suffix=".bit", src_suffix=".config", diff --git a/test/integration/test_project_ice40.py b/test/integration/test_projects.py similarity index 76% rename from test/integration/test_project_ice40.py rename to test/integration/test_projects.py index 0ae65708..f7320a5e 100644 --- a/test/integration/test_project_ice40.py +++ b/test/integration/test_projects.py @@ -21,8 +21,17 @@ # R0801: Similar lines in 2 files # pylint: disable=R0801 -def test_project_ice40(apio_runner: ApioRunner): - """Tests building and testing a project.""" +def _test_project( + apio_runner: ApioRunner, + *, + example: str, + testbench: str, + binary: str, + report_item: str, +): + """A common project integration test. Invoked per each tested + architecture. + """ # -- If the option 'offline' is passed, the test is skip # -- (This test is slow and requires internet connectivity) @@ -52,10 +61,10 @@ def test_project_ice40(apio_runner: ApioRunner): # -- Fetch example files to current directory result = apio_runner.invoke( apio_examples, - ["--fetch-files", "Alhambra-II/ledon"], + ["--fetch-files", example], ) apio_runner.assert_ok(result) - assert "Copying Alhambra-II/ledon example files" in result.output + assert f"Copying {example} example files" in result.output assert "have been successfully created!" in result.output assert getsize("apio.ini") @@ -66,7 +75,7 @@ def test_project_ice40(apio_runner: ApioRunner): result = apio_runner.invoke(apio_build) apio_runner.assert_ok(result) assert "SUCCESS" in result.output - assert getsize("_build/hardware.bin") + assert getsize(f"_build/{binary}") # -- Lint result = apio_runner.invoke(apio_lint) @@ -78,14 +87,14 @@ def test_project_ice40(apio_runner: ApioRunner): result = apio_runner.invoke(apio_test) apio_runner.assert_ok(result) assert "SUCCESS" in result.output - assert getsize("_build/ledon_tb.out") - assert getsize("_build/ledon_tb.vcd") + assert getsize(f"_build/{testbench}.out") + assert getsize(f"_build/{testbench}.vcd") # -- Report result = apio_runner.invoke(apio_report) apio_runner.assert_ok(result) assert "SUCCESS" in result.output - assert "ICESTORM_LC:" in result.output + assert report_item in result.output assert getsize("_build/hardware.pnr") # -- Graph svg @@ -103,3 +112,25 @@ def test_project_ice40(apio_runner: ApioRunner): # -- Check that we have exactly the original project files, assert set(listdir(".")) == set(project_files) + + +def test_project_ice40(apio_runner: ApioRunner): + """Tests building and testing an ice40 project.""" + _test_project( + apio_runner, + example="Alhambra-II/ledon", + testbench="ledon_tb", + binary="hardware.bin", + report_item="ICESTORM_LC:", + ) + + +def test_project_ecp5(apio_runner: ApioRunner): + """Tests building and testing an ecp5 project.""" + _test_project( + apio_runner, + example="ColorLight-5A-75B-V8/Ledon", + testbench="ledon_tb", + binary="hardware.bit", + report_item="ALU54B:", + ) From db2b3dc1ac4e51aeff04aebef9a0224b514a06ec Mon Sep 17 00:00:00 2001 From: Zapta Date: Mon, 25 Nov 2024 16:52:55 -0800 Subject: [PATCH 13/13] The ApioContext is now the only source for the three apio's directories, home, packages, and project (was util.py) and apio exits with an error if any of them contains a white space. This is a temporary error until we will resolve https://github.com/FPGAwars/apio/issues/474 --- apio/apio_context.py | 135 +++++++++++++++++++++++++++++++-- apio/commands/system.py | 4 +- apio/managers/installer.py | 20 ++--- apio/managers/old_installer.py | 7 +- apio/pkg_util.py | 2 +- apio/profile.py | 5 +- apio/util.py | 96 ----------------------- 7 files changed, 149 insertions(+), 120 deletions(-) diff --git a/apio/apio_context.py b/apio/apio_context.py index d475fd65..d648eebe 100644 --- a/apio/apio_context.py +++ b/apio/apio_context.py @@ -8,6 +8,7 @@ import sys import json +import re import platform from collections import OrderedDict import shutil @@ -101,9 +102,18 @@ def __init__( # -- Maps the optional project_dir option to a path. self.project_dir: Path = util.get_project_dir(project_dir) + ApioContext._check_no_spaces_in_dir(self.project_dir, "project") + + # -- Determine apio home dir + self.home_dir: Path = ApioContext._get_home_dir() + ApioContext._check_no_spaces_in_dir(self.home_dir, "home") + + # -- Determine apio home dir + self.packages_dir: Path = ApioContext._get_packages_dir(self.home_dir) + ApioContext._check_no_spaces_in_dir(self.packages_dir, "packages") # -- Profile information, from ~/.apio/profile.json - self.profile = Profile() + self.profile = Profile(self.home_dir) # -- Read the platforms information. self.platforms = self._load_resource(PLATFORMS_JSON) @@ -115,7 +125,7 @@ def __init__( self.all_packages = self._load_resource(PACKAGES_JSON) # -- Expand in place the env templates in all_packages. - ApioContext._resolve_package_envs(self.all_packages) + ApioContext._resolve_package_envs(self.all_packages, self.packages_dir) # The subset of packages that are applicable to this platform. self.platform_packages = self._select_packages_for_platform( @@ -155,6 +165,23 @@ def __init__( self._project = Project(self.project_dir) self._project.read() + @staticmethod + def _check_no_spaces_in_dir(dir_path: Path, subject: str): + """Give the user an early error message if their apio setup dir + contains white space. See https://github.com/FPGAwars/apio/issues/474 + """ + # -- Match a single white space in the dir path. + if re.search("\\s", str(dir_path)): + # -- Here space found. This is a fatal error since we don't hand + # -- it well later in the process. + click.secho( + f"Error: The apio {subject} directory path contains white " + "space.", + fg="red", + ) + click.secho(f"'{str(dir_path)}'", fg="red") + sys.exit(1) + def check_project_loaded(self): """Assert that context was created with project loading..""" assert ( @@ -284,12 +311,13 @@ def _expand_env_template(template: str, package_path: Path) -> str: raise RuntimeError(f"Invalid env template: [{template}]") @staticmethod - def _resolve_package_envs(packages: Dict[str, Dict]) -> None: + def _resolve_package_envs( + packages: Dict[str, Dict], packages_dir: Path + ) -> None: """Resolve in place the path and var value templates in the given packages dictionary. For example, %p is replaced with the package's absolute path.""" - packages_dir = util.get_packages_dir() for _, package_config in packages.items(): # -- Get the package root dir. @@ -461,7 +489,7 @@ def get_package_dir(self, package_name: str) -> Path: """Returns the root path of a package with given name.""" package_folder = self.get_package_folder_name(package_name) - package_dir = util.get_packages_dir() / package_folder + package_dir = self.packages_dir / package_folder return package_dir @@ -580,3 +608,100 @@ def is_darwin(self) -> bool: def is_windows(self) -> bool: """Returns True iff platform_id indicates windows.""" return "windows" in self.platform_id + + @staticmethod + def _get_home_dir() -> Path: + """Get the absolute apio home dir. This is the apio folder where the + profle is located and the packages are installed (unless + APIO_PACKAGES_DIR is used). + The apio home dir can be overridden using the APIO_HOME_DIR environment + varible or in the /etc/apio.json file (in + Debian). If not set, the user_HOME/.apio folder is used by default: + Ej. Linux: /home/obijuan/.apio + If the folders does not exist, they are created + """ + + # -- Get the APIO_HOME_DIR env variable + # -- It returns None if it was not defined + apio_home_dir_env = env_options.get( + env_options.APIO_HOME_DIR, default=None + ) + + # -- Get the home dir. It is what the APIO_HOME_DIR env variable + # -- says, or the default folder if None + if apio_home_dir_env: + home_dir = Path(apio_home_dir_env) + else: + home_dir = Path.home() / ".apio" + + # -- Make it absolute + home_dir = home_dir.absolute() + + # -- Create the folder if it does not exist + try: + home_dir.mkdir(parents=True, exist_ok=True) + except PermissionError: + click.secho( + f"Error: no usable home directory {home_dir}", fg="red" + ) + sys.exit(1) + + # Return the home_dir as a Path + return home_dir + + @staticmethod + def _get_packages_dir(home_dir: Path) -> Path: + """Return the base directory of apio packages. + Packages are installed in the following folder: + * Default: $APIO_HOME_DIR/packages + * $APIO_PACKAGES_DIR: if the APIO_PACKAGES_DIR env variable is set + * INPUT: + - pkg_name: Package name (Ex. 'examples') + * OUTPUT: + - The package absolute folder (PosixPath) + (Ex. '/home/obijuan/.apio/packages) + The absolute path of the returned directory is guaranteed to have + the word packages in it. + """ + + # -- Get the APIO_PACKAGES_DIR env variable + # -- It returns None if it was not defined + packaged_dir_override = env_options.get(env_options.APIO_PACKAGES_DIR) + + # -- Handle override. + if packaged_dir_override: + # -- Verify that the override dir contains the word packages in its + # -- absolute path. This is a safety mechanism to prevent + # -- uninentional bulk deletions in unintended directories. We + # -- check it each time before we perform a package deletion. + path = Path(packaged_dir_override).absolute() + if "packages" not in str(path).lower(): + click.secho( + "Error: packages directory path does not contain the word " + f"packages: {str(path)}", + fg="red", + ) + click.secho( + "For safety reasons, if you use the environment variable " + "APIO_PACKAGE_DIR to override\n" + "the packages dir, the new directory must have the word " + "'packages' (case insensitive)\n" + "in its absolute path.", + fg="yellow", + ) + sys.exit(1) + + # -- Override is OK. Use it as the packages dir. + packages_dir = Path(packaged_dir_override) + + # -- Else, use the default value. + else: + # -- Ex '/home/obijuan/.apio/packages/tools-oss-cad-suite' + # -- Guaranteed to be absolute. + packages_dir = home_dir / "packages" + + # -- Sanity check. If this fails, this is a programming error. + assert "packages" in str(packages_dir).lower(), packages_dir + + # -- All done. + return packages_dir diff --git a/apio/commands/system.py b/apio/commands/system.py index a38971b7..b3afb141 100644 --- a/apio/commands/system.py +++ b/apio/commands/system.py @@ -156,11 +156,11 @@ def cli( # -- Print apio home directory. click.secho("Apio home ", nl=False) - click.secho(util.get_home_dir(), fg="cyan") + click.secho(apio_ctx.home_dir, fg="cyan") # -- Print apio home directory. click.secho("Apio packages ", nl=False) - click.secho(util.get_packages_dir(), fg="cyan") + click.secho(apio_ctx.packages_dir, fg="cyan") cmd_ctx.exit(0) diff --git a/apio/managers/installer.py b/apio/managers/installer.py index 3dcda07f..2310c606 100644 --- a/apio/managers/installer.py +++ b/apio/managers/installer.py @@ -296,14 +296,13 @@ def install_package( print(f"Download URL: {download_url}") # -- Prepare the packages directory. - packages_dir = util.get_packages_dir() - packages_dir.mkdir(exist_ok=True) + apio_ctx.packages_dir.mkdir(exist_ok=True) # -- Prepare the package directory. package_dir = apio_ctx.get_package_dir(package_name) # -- Downlod the package file from the remote server. - local_file = _download_package_file(download_url, packages_dir) + local_file = _download_package_file(download_url, apio_ctx.packages_dir) if verbose: print(f"Local file: {local_file}") @@ -319,14 +318,14 @@ def install_package( # -- Case 1: The package include a top level wrapper directory. # # -- Unpack the package one level up, in the packages directory. - _unpack_package_file(local_file, packages_dir) + _unpack_package_file(local_file, apio_ctx.packages_dir) # -- The uncompressed name may contain a %V placeholder, Replace it # -- with target version. uncompressed_name = uncompressed_name.replace("%V", target_version) # -- Construct the local path of the wrapper dir. - wrapper_dir = packages_dir / uncompressed_name + wrapper_dir = apio_ctx.packages_dir / uncompressed_name # -- Rename the wrapper dir to the package dir. if verbose: @@ -427,9 +426,9 @@ def fix_packages( for dir_name in scan.orphan_dir_names: if verbose: print(f"Deleting unknown dir '{dir_name}'") - # -- Sanity check. Since get_packages_dir() guarranted to include + # -- Sanity check. Since apio_ctx.packages_dir is guarranted to include # -- the word packages, this can fail only due to programming error. - dir_path = util.get_packages_dir() / dir_name + dir_path = apio_ctx.packages_dir / dir_name assert "packages" in str(dir_path).lower(), dir_path # -- Delete. shutil.rmtree(dir_path) @@ -437,9 +436,10 @@ def fix_packages( for file_name in scan.orphan_file_names: if verbose: print(f"Deleting unknown file '{file_name}'") - # -- Sanity check. Since get_packages_dir() guarranted to include - # -- the word packages, this can fail only due to programming error. - file_path = util.get_packages_dir() / file_name + # -- Sanity check. Since apio_ctx.packages_dir is guarranted to + # -- include the word packages, this can fail only due to programming + # -- error. + file_path = apio_ctx.packages_dir / file_name assert "packages" in str(file_path).lower(), dir_path # -- Delete. file_path.unlink() diff --git a/apio/managers/old_installer.py b/apio/managers/old_installer.py index 96060c38..69c25018 100644 --- a/apio/managers/old_installer.py +++ b/apio/managers/old_installer.py @@ -14,6 +14,7 @@ import requests from apio import util +from apio.apio_context import ApioContext from apio.managers.downloader import FileDownloader from apio.managers.unpacker import FileUnpacker @@ -37,7 +38,7 @@ class Modifiers: def __init__( self, package: str, - apio_ctx=None, + apio_ctx: ApioContext = None, modifiers=Modifiers(force=False, checkversion=True, verbose=False), ): """Class initialization. Parameters: @@ -94,7 +95,7 @@ def __init__( # --(It is defined in the resources/packages.json file) if self.package in self.apio_ctx.platform_packages: # -- Store the package dir - self.packages_dir = util.get_home_dir() / dirname + self.packages_dir = apio_ctx.packages_dir / dirname # Get the metadata of the given package package_info = self.apio_ctx.platform_packages[self.package] @@ -141,7 +142,7 @@ def __init__( self.package in self.apio_ctx.profile.packages and modifiers.checkversion is False ): - self.packages_dir = util.get_home_dir() / dirname + self.packages_dir = apio_ctx.home_dir / dirname self.package_folder_name = "toolchain-" + package diff --git a/apio/pkg_util.py b/apio/pkg_util.py index 24086133..a8757e1b 100644 --- a/apio/pkg_util.py +++ b/apio/pkg_util.py @@ -330,7 +330,7 @@ def scan_packages(apio_ctx: ApioContext) -> PackageScanResults: result.orphan_package_ids.append(package_id) # -- Scan the packages directory and identify orphan dirs and files. - for path in util.get_packages_dir().glob("*"): + for path in apio_ctx.packages_dir.glob("*"): base_name = os.path.basename(path) if path.is_dir(): if base_name not in platform_folder_names: diff --git a/apio/profile.py b/apio/profile.py index d45e537e..e72b152b 100644 --- a/apio/profile.py +++ b/apio/profile.py @@ -9,7 +9,6 @@ from pathlib import Path import click import semantic_version -from apio import util class Profile: @@ -17,7 +16,7 @@ class Profile: ex. ~/.apio/profile.json """ - def __init__(self): + def __init__(self, home_dir: Path): # ---- Set the default parameters # Apio settings @@ -28,7 +27,7 @@ def __init__(self): # -- Get the profile path # -- Ex. '/home/obijuan/.apio' - self._profile_path = util.get_home_dir() / "profile.json" + self._profile_path = home_dir / "profile.json" # -- Read the profile from file self.load() diff --git a/apio/util.py b/apio/util.py index 348c4f1b..2222d455 100644 --- a/apio/util.py +++ b/apio/util.py @@ -22,7 +22,6 @@ import click from serial.tools.list_ports import comports import requests -from apio import env_options # ---------------------------------------- # -- Constants @@ -151,101 +150,6 @@ def get_path_in_apio_package(subpath: str) -> Path: return path -def get_home_dir() -> Path: - """Get the absolute apio home dir. This is the apio folder where the - profle is located and the packages are installed (unless APIO_PACKAGES_DIR - is used). - The apio home dir can be overridden using the APIO_HOME_DIR environment - varible or in the /etc/apio.json file (in - Debian). If not set, the user_HOME/.apio folder is used by default: - Ej. Linux: /home/obijuan/.apio - If the folders does not exist, they are created - """ - - # -- Get the APIO_HOME_DIR env variable - # -- It returns None if it was not defined - apio_home_dir_env = env_options.get( - env_options.APIO_HOME_DIR, default=None - ) - - # -- Get the home dir. It is what the APIO_HOME_DIR env variable - # -- says, or the default folder if None - if apio_home_dir_env: - home_dir = Path(apio_home_dir_env) - else: - home_dir = Path.home() / ".apio" - - # -- Make it absolute - home_dir = home_dir.absolute() - - # -- Create the folder if it does not exist - try: - home_dir.mkdir(parents=True, exist_ok=True) - except PermissionError: - click.secho(f"Error: no usable home directory {home_dir}", fg="red") - sys.exit(1) - - # Return the home_dir as a Path - return home_dir - - -def get_packages_dir() -> Path: - """Return the base directory of apio packages. - Packages are installed in the following folder: - * Default: $APIO_HOME_DIR/packages - * $APIO_PACKAGES_DIR: if the APIO_PACKAGES_DIR env variable is set - * INPUT: - - pkg_name: Package name (Ex. 'examples') - * OUTPUT: - - The package absolute folder (PosixPath) - (Ex. '/home/obijuan/.apio/packages) - The absolute path of the returned directory is guaranteed to have - the word packages in it. - """ - - # -- Get the APIO_PACKAGES_DIR env variable - # -- It returns None if it was not defined - packaged_dir_override = env_options.get(env_options.APIO_PACKAGES_DIR) - - # -- Handle override. - if packaged_dir_override: - # -- Verify that the override dir contains the word packages in its - # -- absolute path. This is a safety mechanism to prevent uninentional - # -- bulk deletions in unintended directories. We check it each time - # -- before we perform a package deletion. - path = Path(packaged_dir_override).absolute() - if "packages" not in str(path).lower(): - click.secho( - "Error: packages directory path does not contain the word " - f"packages: {str(path)}", - fg="red", - ) - click.secho( - "For safety reasons, if you use the environment variable " - "APIO_PACKAGE_DIR to override\n" - "the packages dir, the new directory must have the word " - "'packages' (case insensitive)\n" - "in its absolute path.", - fg="yellow", - ) - sys.exit(1) - - # -- Override is OK. Use it as the packages dir. - packages_dir = Path(packaged_dir_override) - - # -- Else, use the default value. - else: - # -- Ex '/home/obijuan/.apio/packages/tools-oss-cad-suite' - # -- Guaranteed to be absolute. - packages_dir = get_home_dir() / "packages" - - # -- Sanity check. If this fails, this is a programming error. - assert "packages" in str(packages_dir).lower(), packages_dir - - # -- All done. - return packages_dir - - def call(cmd): """Execute the given command."""