From 9744c66ec07900220834859f1d61b49169a67613 Mon Sep 17 00:00:00 2001
From: Frederik Hennig <frederik.hennig@fau.de>
Date: Mon, 2 Dec 2024 09:22:36 +0100
Subject: [PATCH] move cmdline tests to generator script test suite

---
 pytest.ini                                    |  6 ++-
 src/pystencilssfg/generator.py                |  8 ++++
 tests/generator/test_config.py                | 29 ------------
 .../config/TestConfigModule_cfg.py            | 14 ++++++
 .../scripts/TestConfigModule.py               | 15 ++++++
 .../scripts/TestExtraCommandLineArgs.py       |  6 +++
 .../scripts/TestIllegalArgs.py                |  4 ++
 .../test_generator_scripts.py                 | 47 ++++++++++++++++++-
 8 files changed, 97 insertions(+), 32 deletions(-)
 create mode 100644 tests/generator_scripts/config/TestConfigModule_cfg.py
 create mode 100644 tests/generator_scripts/scripts/TestConfigModule.py
 create mode 100644 tests/generator_scripts/scripts/TestExtraCommandLineArgs.py
 create mode 100644 tests/generator_scripts/scripts/TestIllegalArgs.py

diff --git a/pytest.ini b/pytest.ini
index 5d05ec3..7dc0d38 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -3,6 +3,10 @@ testpaths = src/pystencilssfg tests/
 python_files = "test_*.py"
 #   Need to ignore the generator scripts, otherwise they would be executed
 #   during test collection
-addopts = --doctest-modules --ignore=tests/generator_scripts/scripts --ignore=--ignore=tests/data
+addopts = 
+    --doctest-modules
+    --ignore=tests/generator_scripts/scripts
+    --ignore=tests/generator_scripts/config
+    --ignore=tests/data
 
 doctest_optionflags = NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL
diff --git a/src/pystencilssfg/generator.py b/src/pystencilssfg/generator.py
index d145abd..cc9cd62 100644
--- a/src/pystencilssfg/generator.py
+++ b/src/pystencilssfg/generator.py
@@ -5,6 +5,7 @@ from .config import SfgConfig, CommandLineParameters, OutputMode, GLOBAL_NAMESPA
 from .context import SfgContext
 from .composer import SfgComposer
 from .emission import AbstractEmitter, OutputSpec
+from .exceptions import SfgException
 
 
 class SourceFileGenerator:
@@ -33,6 +34,13 @@ class SourceFileGenerator:
 
         import __main__
 
+        if not hasattr(__main__, "__file__"):
+            raise SfgException(
+                "Invalid execution environment: "
+                "It seems that you are trying to run the `SourceFileGenerator` in an environment "
+                "without a valid entry point, such as a REPL or a multiprocessing fork."
+            )
+
         scriptpath = __main__.__file__
         scriptname = path.split(scriptpath)[1]
         basename = path.splitext(scriptname)[0]
diff --git a/tests/generator/test_config.py b/tests/generator/test_config.py
index 8942f6a..b22e4e5 100644
--- a/tests/generator/test_config.py
+++ b/tests/generator/test_config.py
@@ -89,32 +89,3 @@ def test_from_commandline(sample_config_module):
     assert cli_args.configuration_module is not None
     assert cli_args.configuration_module.magic_string == "Spam and eggs"
     assert cli_args.configuration_module.magic_number == 0xCAFE
-
-
-def test_generator_config(monkeypatch, tmp_path, sample_config_module):
-    import sys
-
-    args = [
-        "genscript.py",
-        "--sfg-file-extensions",
-        ".c++,.h++",
-        "--sfg-config-module",
-        sample_config_module,
-        "test1",
-        "test2",
-    ]
-    monkeypatch.setattr(sys, "argv", args)
-
-    cfg = SfgConfig(output_directory=str(tmp_path.absolute()))
-
-    with SourceFileGenerator(cfg) as sfg:
-        ctx = sfg.context
-
-        assert ctx.outer_namespace == "myproject"
-        assert ctx.argv == ["test1", "test2"]
-        assert isinstance(ctx.project_info, dict)
-        assert ctx.project_info == {
-            "use_openmp": True,
-            "use_cuda": True,
-            "float_format": "float32",
-        }
diff --git a/tests/generator_scripts/config/TestConfigModule_cfg.py b/tests/generator_scripts/config/TestConfigModule_cfg.py
new file mode 100644
index 0000000..e118b43
--- /dev/null
+++ b/tests/generator_scripts/config/TestConfigModule_cfg.py
@@ -0,0 +1,14 @@
+from pystencilssfg import SfgConfig
+
+
+def configure_sfg(cfg: SfgConfig):
+    cfg.outer_namespace = "myproject"
+    cfg.codestyle.indent_width = 3
+
+
+def project_info():
+    return {
+        "use_openmp": True,
+        "use_cuda": True,
+        "float_format": "float32",
+    }
diff --git a/tests/generator_scripts/scripts/TestConfigModule.py b/tests/generator_scripts/scripts/TestConfigModule.py
new file mode 100644
index 0000000..35b4192
--- /dev/null
+++ b/tests/generator_scripts/scripts/TestConfigModule.py
@@ -0,0 +1,15 @@
+from pystencilssfg import SourceFileGenerator
+
+with SourceFileGenerator() as sfg:
+    ctx = sfg.context
+
+    assert ctx.outer_namespace == "myproject"
+    assert ctx.codestyle.indent_width == 3
+
+    assert not ctx.argv
+    assert isinstance(ctx.project_info, dict)
+    assert ctx.project_info == {
+        "use_openmp": True,
+        "use_cuda": True,
+        "float_format": "float32",
+    }
diff --git a/tests/generator_scripts/scripts/TestExtraCommandLineArgs.py b/tests/generator_scripts/scripts/TestExtraCommandLineArgs.py
new file mode 100644
index 0000000..2cf9893
--- /dev/null
+++ b/tests/generator_scripts/scripts/TestExtraCommandLineArgs.py
@@ -0,0 +1,6 @@
+from pystencilssfg import SourceFileGenerator
+
+with SourceFileGenerator(keep_unknown_argv=True) as sfg:
+    ctx = sfg.context
+
+    assert ctx.argv == ["--precision", "float32", "test1", "test2"]
diff --git a/tests/generator_scripts/scripts/TestIllegalArgs.py b/tests/generator_scripts/scripts/TestIllegalArgs.py
new file mode 100644
index 0000000..ce0a0cb
--- /dev/null
+++ b/tests/generator_scripts/scripts/TestIllegalArgs.py
@@ -0,0 +1,4 @@
+from pystencilssfg import SourceFileGenerator
+
+with SourceFileGenerator() as sfg:
+    ...
diff --git a/tests/generator_scripts/test_generator_scripts.py b/tests/generator_scripts/test_generator_scripts.py
index d3173dc..16adba2 100644
--- a/tests/generator_scripts/test_generator_scripts.py
+++ b/tests/generator_scripts/test_generator_scripts.py
@@ -9,6 +9,7 @@ import subprocess
 
 THIS_DIR = path.split(__file__)[0]
 SCRIPTS_DIR = path.join(THIS_DIR, "scripts")
+CONFIG_DIR = path.join(THIS_DIR, "config")
 EXPECTED_DIR = path.join(THIS_DIR, "expected")
 
 
@@ -30,6 +31,12 @@ class ScriptInfo:
     Output files will all be placed in the ``out`` folder.
     """
 
+    args: tuple[str, ...] = ()
+    """Command-line arguments to be passed to the generator script"""
+
+    should_fail: bool = False
+    """Whether the exeuction of this script should fail."""
+
     compilable_output: str | None = None
     """File extension of the output file that can be compiled.
 
@@ -50,6 +57,37 @@ When adding new generator scripts to the `scripts` directory,
 do not forget to include them here.
 """
 SCRIPTS = [
+    ScriptInfo.make(
+        "TestConfigModule",
+        ("h++", "c++"),
+        args=(
+            "--sfg-file-extensions",
+            ".c++,.h++",
+            "--sfg-config-module",
+            path.join(CONFIG_DIR, "TestConfigModule_cfg.py"),
+        ),
+    ),
+    ScriptInfo.make(
+        "TestIllegalArgs",
+        ("h++", "c++"),
+        args=(
+            "--sfg-file-extensionss",
+            ".c++,.h++",
+        ),
+        should_fail=True
+    ),
+    ScriptInfo.make(
+        "TestExtraCommandLineArgs",
+        ("h++", "c++"),
+        args=(
+            "--sfg-file-extensions",
+            ".c++,.h++",
+            "--precision",
+            "float32",
+            "test1",
+            "test2"
+        ),
+    ),
     ScriptInfo.make("Structural", ("hpp", "cpp")),
     ScriptInfo.make("SimpleJacobi", ("hpp", "cpp"), compilable_output="cpp"),
     ScriptInfo.make("SimpleClasses", ("hpp", "cpp")),
@@ -75,12 +113,17 @@ def test_generator_script(script_info: ScriptInfo):
         shutil.rmtree(output_dir)
     os.makedirs(output_dir, exist_ok=True)
 
-    args = ["python", script_file, "--sfg-output-dir", output_dir]
+    args = ["python", script_file, "--sfg-output-dir", output_dir] + list(script_info.args)
 
     result = subprocess.run(args)
 
+    if script_info.should_fail:
+        if result.returncode == 0:
+            pytest.fail(f"Generator script {script_name} was supposed to fail, but didn't.")
+        return
+
     if result.returncode != 0:
-        raise AssertionError(f"Generator script {script_name} failed.")
+        pytest.fail(f"Generator script {script_name} failed.")
 
     #   Check generated files
     expected_files = set(
-- 
GitLab