fm-weck 1.5.1__py3-none-any.whl → 1.5.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fm_weck/__init__.py +1 -1
- fm_weck/cli.py +96 -18
- fm_weck/config.py +4 -6
- fm_weck/engine.py +3 -3
- fm_weck/resources/__init__.py +4 -4
- fm_weck/run_result.py +15 -11
- fm_weck/runexec_mode.py +37 -7
- fm_weck/smoke_test_mode.py +65 -22
- {fm_weck-1.5.1.dist-info → fm_weck-1.5.3.dist-info}/METADATA +1 -1
- {fm_weck-1.5.1.dist-info → fm_weck-1.5.3.dist-info}/RECORD +12 -12
- {fm_weck-1.5.1.dist-info → fm_weck-1.5.3.dist-info}/WHEEL +0 -0
- {fm_weck-1.5.1.dist-info → fm_weck-1.5.3.dist-info}/entry_points.txt +0 -0
fm_weck/__init__.py
CHANGED
fm_weck/cli.py
CHANGED
|
@@ -581,6 +581,9 @@ def main_runexec(args: argparse.Namespace):
|
|
|
581
581
|
command=args.argument_list,
|
|
582
582
|
)
|
|
583
583
|
|
|
584
|
+
if result is None:
|
|
585
|
+
return 1 # Indicate failure due to runexec setup issues
|
|
586
|
+
|
|
584
587
|
return result.exit_code
|
|
585
588
|
|
|
586
589
|
|
|
@@ -725,9 +728,60 @@ def check_client_options(timelimit_arg, output_path=None):
|
|
|
725
728
|
return timelimit, output_path
|
|
726
729
|
|
|
727
730
|
|
|
731
|
+
def _do_smoke_test_mode(fm_data, shelve_space, tool, gitlab_ci_mode) -> int:
|
|
732
|
+
from .smoke_test_mode import (
|
|
733
|
+
run_smoke_test,
|
|
734
|
+
run_smoke_test_gitlab_ci,
|
|
735
|
+
)
|
|
736
|
+
|
|
737
|
+
# GitLab CI mode installs packages directly and runs the script on the host
|
|
738
|
+
if gitlab_ci_mode:
|
|
739
|
+
from subprocess import CalledProcessError
|
|
740
|
+
|
|
741
|
+
try:
|
|
742
|
+
run_smoke_test_gitlab_ci(fm_data, shelve_space)
|
|
743
|
+
return 0
|
|
744
|
+
except CalledProcessError as e:
|
|
745
|
+
logger.error(
|
|
746
|
+
"Smoke test script failed in GitLab CI mode (exit code %d).\n- Tool: %s\n- Script directory: %s\n",
|
|
747
|
+
e.returncode,
|
|
748
|
+
tool.stem,
|
|
749
|
+
shelve_space,
|
|
750
|
+
)
|
|
751
|
+
return e.returncode
|
|
752
|
+
|
|
753
|
+
# Containerized mode: run script inside the configured image
|
|
754
|
+
result = run_smoke_test(fm_data, shelve_space, Config())
|
|
755
|
+
if result.exit_code != 0:
|
|
756
|
+
# Print a concise but informative error for CI logs
|
|
757
|
+
output_lines = result.raw_output.splitlines()
|
|
758
|
+
tail = "\n".join(output_lines[-50:]) if output_lines else "<no output captured>"
|
|
759
|
+
logger.error(
|
|
760
|
+
"Smoke test failed (exit code %d).\n"
|
|
761
|
+
"- Tool: %s\n"
|
|
762
|
+
"- Tool cache dir (host): %s\n"
|
|
763
|
+
"- Script name: smoketest.sh\n"
|
|
764
|
+
"Last 50 lines of output:\n%s",
|
|
765
|
+
result.exit_code,
|
|
766
|
+
tool.stem,
|
|
767
|
+
shelve_space,
|
|
768
|
+
tail,
|
|
769
|
+
)
|
|
770
|
+
return result.exit_code
|
|
771
|
+
|
|
772
|
+
return 0
|
|
773
|
+
|
|
774
|
+
|
|
728
775
|
def main_smoke_test(args: argparse.Namespace):
|
|
776
|
+
from fm_tools.exceptions import DownloadUnsuccessfulException, UnsupportedDOIException
|
|
777
|
+
|
|
729
778
|
from .serve import setup_fm_tool
|
|
730
|
-
from .smoke_test_mode import
|
|
779
|
+
from .smoke_test_mode import (
|
|
780
|
+
NoSmokeTestFileError,
|
|
781
|
+
SmokeTestError,
|
|
782
|
+
SmokeTestFileIsEmptyError,
|
|
783
|
+
SmokeTestFileIsNotExecutableError,
|
|
784
|
+
)
|
|
731
785
|
|
|
732
786
|
try:
|
|
733
787
|
tool = resolve_tool(args.TOOL)
|
|
@@ -753,26 +807,50 @@ def main_smoke_test(args: argparse.Namespace):
|
|
|
753
807
|
logger.error("No competition participation found for year %d in tool %s", args.competition_year, tool.stem)
|
|
754
808
|
return 1
|
|
755
809
|
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
return 0
|
|
810
|
+
try:
|
|
811
|
+
fm_data, shelve_space = setup_fm_tool(
|
|
812
|
+
fm_tool=tool,
|
|
813
|
+
version=version,
|
|
814
|
+
configuration=Config(),
|
|
815
|
+
)
|
|
816
|
+
except (DownloadUnsuccessfulException, UnsupportedDOIException) as e:
|
|
817
|
+
if "code: 504" in str(e).lower():
|
|
818
|
+
print(
|
|
819
|
+
"Failed to download the tool due to a timeout (504 Gateway Timeout). "
|
|
820
|
+
"This issue is likely caused by Zenodo. Retry by rerunning the smoke test.",
|
|
821
|
+
)
|
|
822
|
+
else:
|
|
823
|
+
print(f"There was an error while downloading and unpacking the tool:\n{e}")
|
|
771
824
|
|
|
772
825
|
try:
|
|
773
|
-
|
|
826
|
+
return _do_smoke_test_mode(fm_data, shelve_space, tool, args.gitlab_ci_mode)
|
|
827
|
+
except NoSmokeTestFileError as e:
|
|
828
|
+
print(
|
|
829
|
+
f"{e}\n"
|
|
830
|
+
"Expected a smoke test script named 'smoketest.sh' in the tool directory.\n"
|
|
831
|
+
"Action: Add a minimal script 'smoketest.sh' to the root of the tool directory that exercises the tool.\n"
|
|
832
|
+
"The top level contents of the tool directory were:\n"
|
|
833
|
+
f"{os.linesep.join([str(p.name) for p in shelve_space.iterdir()])}",
|
|
834
|
+
)
|
|
835
|
+
return 1
|
|
836
|
+
except SmokeTestFileIsEmptyError as e:
|
|
837
|
+
print(
|
|
838
|
+
f"{e}\nAction: Populate the smoke test script with at least one command that validates basic startup.",
|
|
839
|
+
)
|
|
840
|
+
return 1
|
|
841
|
+
except SmokeTestFileIsNotExecutableError as e:
|
|
842
|
+
print(
|
|
843
|
+
f"{e}\nAction: Make the smoke test script executable. On linux, you can do this by running:\n"
|
|
844
|
+
f" chmod +x {e.smoke_test_file}",
|
|
845
|
+
)
|
|
846
|
+
return 1
|
|
774
847
|
except ValueError as e:
|
|
775
|
-
|
|
848
|
+
# e.g., invalid shelve space path, or other validation errors
|
|
849
|
+
print(f"Smoke test setup failed: {e}")
|
|
850
|
+
return 1
|
|
851
|
+
except SmokeTestError as e:
|
|
852
|
+
# Fallback for any other smoke-test specific errors
|
|
853
|
+
print(f"Error starting the smoke test: {e}")
|
|
776
854
|
return 1
|
|
777
855
|
|
|
778
856
|
|
fm_weck/config.py
CHANGED
|
@@ -14,8 +14,6 @@ from functools import cache
|
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
from typing import TYPE_CHECKING, Any, Callable, Iterable, Optional, Tuple, TypeVar
|
|
16
16
|
|
|
17
|
-
from werkzeug.utils import secure_filename
|
|
18
|
-
|
|
19
17
|
try:
|
|
20
18
|
from fm_tools.fmtool import FmTool
|
|
21
19
|
from fm_tools.fmtoolversion import FmToolVersion
|
|
@@ -37,7 +35,7 @@ except ImportError:
|
|
|
37
35
|
raise ImportError("fm_tools is not imported.")
|
|
38
36
|
|
|
39
37
|
|
|
40
|
-
from fm_weck.resources import RUN_WITH_OVERLAY
|
|
38
|
+
from fm_weck.resources import RUN_WITH_OVERLAY
|
|
41
39
|
|
|
42
40
|
from .file_util import copy_ensuring_unix_line_endings
|
|
43
41
|
|
|
@@ -135,6 +133,7 @@ class Config(object):
|
|
|
135
133
|
"""Makes sure relative Paths in the config are relative to the config file."""
|
|
136
134
|
|
|
137
135
|
path = fn(self, *args, **kwargs)
|
|
136
|
+
path = path.expanduser()
|
|
138
137
|
|
|
139
138
|
if not self._config_source:
|
|
140
139
|
return path
|
|
@@ -169,6 +168,8 @@ class Config(object):
|
|
|
169
168
|
return self.cache_location / ".checksums.dbm"
|
|
170
169
|
|
|
171
170
|
def get_shelve_space_for(self, fm_data: FmToolVersion) -> Path:
|
|
171
|
+
from werkzeug.utils import secure_filename
|
|
172
|
+
|
|
172
173
|
shelve = self.cache_location
|
|
173
174
|
# Remove leading http:// or https:// from the raw archive location
|
|
174
175
|
raw_location = fm_data.get_archive_location().raw
|
|
@@ -194,9 +195,6 @@ class Config(object):
|
|
|
194
195
|
def _system_is_not_posix():
|
|
195
196
|
return not (sys.platform.startswith("linux") or sys.platform == "darwin")
|
|
196
197
|
|
|
197
|
-
def make_runexec_script_available(self) -> Path | None:
|
|
198
|
-
return self.make_script_available(RUNEXEC_SCRIPT)
|
|
199
|
-
|
|
200
198
|
def make_script_available(self, target_name: str = RUN_WITH_OVERLAY) -> Path | None:
|
|
201
199
|
script_dir = self.cache_location / ".scripts"
|
|
202
200
|
target = script_dir / target_name
|
fm_weck/engine.py
CHANGED
|
@@ -66,7 +66,7 @@ class Engine(ABC):
|
|
|
66
66
|
overlay_tool_dir: Optional[str] = None
|
|
67
67
|
image: Optional[str] = None
|
|
68
68
|
dry_run: bool = False
|
|
69
|
-
work_dir:
|
|
69
|
+
work_dir: Path = Path(CWD_MOUNT_LOCATION)
|
|
70
70
|
|
|
71
71
|
def __init__(self, image: Union[str, FmImageConfig]):
|
|
72
72
|
self._tmp_output_dir = Path(mkdtemp("fm_weck_output")).resolve()
|
|
@@ -84,7 +84,7 @@ class Engine(ABC):
|
|
|
84
84
|
shutil.rmtree(self._tmp_output_dir)
|
|
85
85
|
|
|
86
86
|
def get_workdir(self) -> str:
|
|
87
|
-
return
|
|
87
|
+
return self.work_dir.as_posix()
|
|
88
88
|
|
|
89
89
|
def set_log_file(self, log_file: Path):
|
|
90
90
|
self.log_file = log_file
|
|
@@ -142,7 +142,7 @@ class Engine(ABC):
|
|
|
142
142
|
"--entrypoint",
|
|
143
143
|
'[""]',
|
|
144
144
|
"-v",
|
|
145
|
-
f"{Path.cwd().absolute()}:{
|
|
145
|
+
f"{Path.cwd().absolute()}:{Path(CWD_MOUNT_LOCATION).as_posix()}",
|
|
146
146
|
"-v",
|
|
147
147
|
f"{Config().cache_location}:{CACHE_MOUNT_LOCATION}",
|
|
148
148
|
"-v",
|
fm_weck/resources/__init__.py
CHANGED
|
@@ -9,8 +9,6 @@ import importlib.resources as pkg_resources
|
|
|
9
9
|
from functools import cache
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
12
|
-
from . import fm_tools, properties
|
|
13
|
-
|
|
14
12
|
# During the build of the wheel file, the fm-tools/data directory is copied
|
|
15
13
|
# to the wheel file under fm_weck/resources/fm_tools
|
|
16
14
|
|
|
@@ -20,7 +18,8 @@ RUNEXEC_SCRIPT = "runexec"
|
|
|
20
18
|
|
|
21
19
|
|
|
22
20
|
def iter_fm_data():
|
|
23
|
-
|
|
21
|
+
root = pkg_resources.files(__package__) / "fm_tools"
|
|
22
|
+
for entry in root.iterdir():
|
|
24
23
|
if entry.name.endswith((".yml", ".yaml")):
|
|
25
24
|
with pkg_resources.as_file(entry) as path:
|
|
26
25
|
fm_data_path = Path(path)
|
|
@@ -29,7 +28,8 @@ def iter_fm_data():
|
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
def iter_properties():
|
|
32
|
-
|
|
31
|
+
root = pkg_resources.files(__package__) / "properties"
|
|
32
|
+
for entry in root.iterdir():
|
|
33
33
|
with pkg_resources.as_file(entry) as path:
|
|
34
34
|
prop_path = Path(path)
|
|
35
35
|
if prop_path.is_file():
|
fm_weck/run_result.py
CHANGED
|
@@ -6,12 +6,11 @@
|
|
|
6
6
|
# SPDX-License-Identifier: Apache-2.0
|
|
7
7
|
|
|
8
8
|
from dataclasses import dataclass
|
|
9
|
-
from
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
from benchexec.
|
|
13
|
-
from fm_tools.fmtoolversion import FmToolVersion
|
|
14
|
-
from fm_tools.run import get_tool_info
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from benchexec.tools.template import BaseTool2
|
|
13
|
+
from fm_tools.fmtoolversion import FmToolVersion
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
@dataclass(frozen=True)
|
|
@@ -21,6 +20,9 @@ class RunResult:
|
|
|
21
20
|
raw_output: str
|
|
22
21
|
|
|
23
22
|
def as_benchexec_run(self):
|
|
23
|
+
from benchexec.tools.template import BaseTool2
|
|
24
|
+
from benchexec.util import ProcessExitCode
|
|
25
|
+
|
|
24
26
|
return BaseTool2.Run(
|
|
25
27
|
cmdline=self.command,
|
|
26
28
|
exit_code=ProcessExitCode.create(value=self.exit_code),
|
|
@@ -28,11 +30,13 @@ class RunResult:
|
|
|
28
30
|
termination_reason=False, # TODO: We do not know about this
|
|
29
31
|
)
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
def determine_result(self, tool: "BaseTool2 | FmToolVersion") -> str:
|
|
34
|
+
from benchexec.tools.template import BaseTool2
|
|
35
|
+
|
|
36
|
+
if isinstance(tool, BaseTool2):
|
|
37
|
+
return tool.determine_result(self.as_benchexec_run())
|
|
38
|
+
|
|
39
|
+
from fm_tools.run import get_tool_info
|
|
34
40
|
|
|
35
|
-
@determine_result.register
|
|
36
|
-
def _(self, tool: FmToolVersion) -> str:
|
|
37
41
|
tool_ = get_tool_info(tool)
|
|
38
|
-
return
|
|
42
|
+
return tool_.determine_result(self.as_benchexec_run())
|
fm_weck/runexec_mode.py
CHANGED
|
@@ -7,11 +7,13 @@
|
|
|
7
7
|
|
|
8
8
|
import importlib.resources as pkg_resources
|
|
9
9
|
import logging
|
|
10
|
+
import os
|
|
10
11
|
import shutil
|
|
11
12
|
from pathlib import Path
|
|
13
|
+
from tempfile import NamedTemporaryFile
|
|
12
14
|
from typing import TYPE_CHECKING, Optional
|
|
13
15
|
|
|
14
|
-
from fm_weck.resources import BENCHEXEC_WHL
|
|
16
|
+
from fm_weck.resources import BENCHEXEC_WHL, RUNEXEC_SCRIPT
|
|
15
17
|
from fm_weck.runexec_util import mountable_absolute_paths_of_command
|
|
16
18
|
|
|
17
19
|
from .config import Config
|
|
@@ -20,16 +22,38 @@ from .engine import CACHE_MOUNT_LOCATION, Engine
|
|
|
20
22
|
logger = logging.getLogger(__name__)
|
|
21
23
|
|
|
22
24
|
if TYPE_CHECKING:
|
|
25
|
+
from tempfile import _TemporaryFileWrapper
|
|
26
|
+
|
|
23
27
|
from fm_weck.run_result import RunResult
|
|
24
28
|
|
|
25
29
|
|
|
30
|
+
def _setup_script_in_cache(target: "_TemporaryFileWrapper[bytes]") -> Path:
|
|
31
|
+
# When running multiple instances in parallel it can happen, that two processes interfere
|
|
32
|
+
# when copying the script causing a "Text file is busy" error.
|
|
33
|
+
# Using a temp file avoids this problem.
|
|
34
|
+
# The cleaner solution would be to use a direct bind mount from the package resource, but this does not
|
|
35
|
+
# work on the benchcloud right now.
|
|
36
|
+
|
|
37
|
+
with pkg_resources.path("fm_weck.resources", RUNEXEC_SCRIPT) as source_path:
|
|
38
|
+
shutil.copy(source_path, target.name)
|
|
39
|
+
|
|
40
|
+
target_path = Path(target.name)
|
|
41
|
+
mode = target_path.stat().st_mode
|
|
42
|
+
# make the temp file executable
|
|
43
|
+
target_path.chmod(mode | os.X_OK)
|
|
44
|
+
target.flush()
|
|
45
|
+
target.close()
|
|
46
|
+
|
|
47
|
+
return target_path
|
|
48
|
+
|
|
49
|
+
|
|
26
50
|
def run_runexec(
|
|
27
51
|
benchexec_package: Optional[Path],
|
|
28
52
|
use_image: Optional[str],
|
|
29
53
|
configuration: Config,
|
|
30
54
|
extra_container_args: list[list[str]],
|
|
31
55
|
command: list[str],
|
|
32
|
-
) -> "RunResult":
|
|
56
|
+
) -> "RunResult| None":
|
|
33
57
|
if use_image is not None:
|
|
34
58
|
configuration.set_default_image(use_image)
|
|
35
59
|
|
|
@@ -38,7 +62,7 @@ def run_runexec(
|
|
|
38
62
|
engine.add_mounting_capabilities = False
|
|
39
63
|
|
|
40
64
|
if benchexec_package is not None:
|
|
41
|
-
engine.mount(benchexec_package.parent.absolute(), "/home/__fm_weck_benchexec")
|
|
65
|
+
engine.mount(str(benchexec_package.parent.absolute()), "/home/__fm_weck_benchexec")
|
|
42
66
|
engine.env["PYTHONPATH"] = f"/home/__fm_weck_benchexec/{benchexec_package.name}"
|
|
43
67
|
else:
|
|
44
68
|
# Default to the bundled benchexec package
|
|
@@ -52,13 +76,19 @@ def run_runexec(
|
|
|
52
76
|
return None
|
|
53
77
|
|
|
54
78
|
for path in mountable_absolute_paths_of_command(Path.cwd().absolute(), command):
|
|
55
|
-
engine.mount(path, str(path) + ":ro")
|
|
79
|
+
engine.mount(str(path), str(path) + ":ro")
|
|
56
80
|
|
|
57
81
|
for arg in extra_container_args:
|
|
58
82
|
engine.add_container_long_opt(arg)
|
|
59
83
|
|
|
60
|
-
configuration.make_runexec_script_available()
|
|
61
|
-
|
|
62
84
|
engine.handle_io = False
|
|
63
85
|
|
|
64
|
-
|
|
86
|
+
with (
|
|
87
|
+
NamedTemporaryFile(
|
|
88
|
+
prefix="runexec_", dir=str(configuration.cache_location / ".scripts"), delete=True, delete_on_close=False
|
|
89
|
+
) as tmp_file,
|
|
90
|
+
):
|
|
91
|
+
script_path = _setup_script_in_cache(tmp_file)
|
|
92
|
+
|
|
93
|
+
rel_path = script_path.relative_to(configuration.cache_location)
|
|
94
|
+
return engine.run(f"{CACHE_MOUNT_LOCATION}/{rel_path}", *command)
|
fm_weck/smoke_test_mode.py
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
# SPDX-License-Identifier: Apache-2.0
|
|
7
7
|
|
|
8
8
|
import logging
|
|
9
|
+
import os
|
|
9
10
|
import subprocess
|
|
10
11
|
from pathlib import Path
|
|
11
12
|
|
|
@@ -16,6 +17,63 @@ from .engine import CACHE_MOUNT_LOCATION, Engine
|
|
|
16
17
|
logger = logging.getLogger(__name__)
|
|
17
18
|
|
|
18
19
|
|
|
20
|
+
class SmokeTestError(Exception):
|
|
21
|
+
"""Custom exception for smoke test errors."""
|
|
22
|
+
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class NoSmokeTestFileError(SmokeTestError):
|
|
27
|
+
"""Exception raised when no smoke test file is found."""
|
|
28
|
+
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class SmokeTestFileIsEmptyError(SmokeTestError):
|
|
33
|
+
"""Exception raised when the smoke test file is empty."""
|
|
34
|
+
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class SmokeTestFileIsNotExecutableError(SmokeTestError):
|
|
39
|
+
"""Exception raised when the smoke test file is not executable."""
|
|
40
|
+
|
|
41
|
+
smoke_test_file: Path
|
|
42
|
+
|
|
43
|
+
def __init__(self, smoke_test_file: Path):
|
|
44
|
+
self.smoke_test_file = smoke_test_file
|
|
45
|
+
super().__init__(f"Smoke test file is not executable: {smoke_test_file}")
|
|
46
|
+
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def locate_and_check_smoke_test_file(shelve_space: Path) -> str:
|
|
51
|
+
"""Check if the smoke test file exists, is executable, and is not empty.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
shelve_space: Path to the shelve space directory.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
The relative path to the smoke test file as a string.
|
|
58
|
+
|
|
59
|
+
Raises:
|
|
60
|
+
NoSmokeTestFileError: If the smoke test file does not exist.
|
|
61
|
+
SmokeTestFileIsEmptyError: If the smoke test file is empty.
|
|
62
|
+
SmokeTestFileIsNotExecutableError: If the smoke test file is not executable.
|
|
63
|
+
"""
|
|
64
|
+
file_path = shelve_space / "smoketest.sh"
|
|
65
|
+
if not file_path.exists():
|
|
66
|
+
raise NoSmokeTestFileError(f"Smoke test file 'smoketest.sh' not found in: {shelve_space}")
|
|
67
|
+
|
|
68
|
+
if not file_path.stat().st_mode & os.X_OK:
|
|
69
|
+
raise SmokeTestFileIsNotExecutableError(file_path.relative_to(shelve_space))
|
|
70
|
+
|
|
71
|
+
if file_path.stat().st_size == 0:
|
|
72
|
+
raise SmokeTestFileIsEmptyError(f"Smoke test file is empty: {file_path}")
|
|
73
|
+
|
|
74
|
+
return f"./{file_path.name}"
|
|
75
|
+
|
|
76
|
+
|
|
19
77
|
def run_smoke_test(fm_data, shelve_space, config):
|
|
20
78
|
if not shelve_space.exists() or not shelve_space.is_dir():
|
|
21
79
|
raise ValueError(f"Invalid shelve space path: {shelve_space}")
|
|
@@ -25,15 +83,10 @@ def run_smoke_test(fm_data, shelve_space, config):
|
|
|
25
83
|
tool_dir = shelve_space.relative_to(config.cache_location)
|
|
26
84
|
engine.work_dir = CACHE_MOUNT_LOCATION / tool_dir
|
|
27
85
|
|
|
28
|
-
|
|
29
|
-
if (shelve_space / "smoketest.sh").exists():
|
|
30
|
-
command = "./smoketest.sh"
|
|
31
|
-
elif (shelve_space / "smoke_test.sh").exists():
|
|
32
|
-
command = "./smoke_test.sh"
|
|
33
|
-
else:
|
|
34
|
-
raise ValueError(f"Smoke test script not found in {shelve_space}. Expected ./smoketest.sh or ./smoke_test.sh")
|
|
86
|
+
command = locate_and_check_smoke_test_file(shelve_space)
|
|
35
87
|
|
|
36
|
-
|
|
88
|
+
# Return the result so callers can react to failures and print diagnostics
|
|
89
|
+
return engine.run(command)
|
|
37
90
|
|
|
38
91
|
|
|
39
92
|
def run_smoke_test_gitlab_ci(fm_data: FmToolVersion, tool_dir: Path):
|
|
@@ -43,7 +96,7 @@ def run_smoke_test_gitlab_ci(fm_data: FmToolVersion, tool_dir: Path):
|
|
|
43
96
|
|
|
44
97
|
Args:
|
|
45
98
|
fm_data: The FmToolVersion object containing tool information
|
|
46
|
-
tool_dir: The directory containing the tool's
|
|
99
|
+
tool_dir: The directory containing the tool's smoketest.sh script
|
|
47
100
|
"""
|
|
48
101
|
# Get required packages from fm_data
|
|
49
102
|
required_packages = fm_data.get_images().required_packages
|
|
@@ -61,21 +114,11 @@ def run_smoke_test_gitlab_ci(fm_data: FmToolVersion, tool_dir: Path):
|
|
|
61
114
|
else:
|
|
62
115
|
logger.info("No required packages specified for this tool")
|
|
63
116
|
|
|
64
|
-
|
|
65
|
-
# Check for smoketest.sh first, then smoke_test.sh
|
|
66
|
-
smoke_test_script = tool_dir / "smoketest.sh"
|
|
67
|
-
if not smoke_test_script.exists():
|
|
68
|
-
smoke_test_script = tool_dir / "smoke_test.sh"
|
|
69
|
-
|
|
70
|
-
if not smoke_test_script.exists():
|
|
71
|
-
raise ValueError(
|
|
72
|
-
f"Smoke test script not found in downloaded tool directory: {tool_dir}. "
|
|
73
|
-
f"Expected ./smoketest.sh or ./smoke_test.sh"
|
|
74
|
-
)
|
|
117
|
+
script_command = locate_and_check_smoke_test_file(tool_dir)
|
|
75
118
|
|
|
76
|
-
logger.info("Running smoke test script: %s",
|
|
119
|
+
logger.info("Running smoke test script: %s", script_command)
|
|
77
120
|
try:
|
|
78
|
-
subprocess.run([
|
|
121
|
+
subprocess.run([script_command], cwd=tool_dir, check=True)
|
|
79
122
|
logger.info("Smoke test completed successfully")
|
|
80
123
|
except subprocess.CalledProcessError as e:
|
|
81
124
|
logger.error("Smoke test failed with return code %d", e.returncode)
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
fm_weck/__init__.py,sha256=
|
|
1
|
+
fm_weck/__init__.py,sha256=XKFqL4QIrZPlt9h9GadbHOpCIMJiY650ZjDdLbYQWa8,351
|
|
2
2
|
fm_weck/__main__.py,sha256=IfNDAqM6MK6P7KsQoW3wOHPOscB8evdVlS9C7R4wd_0,391
|
|
3
3
|
fm_weck/cache_mgr.py,sha256=3-OQFmCeswazXmX08ND4oEHFOR07ZDCwWzjmFTDkOSE,1373
|
|
4
4
|
fm_weck/capture.py,sha256=iogn3JvCZEjD0SQL8Xa3TzmZAWifd9ZIP81c3JIsdUQ,982
|
|
5
|
-
fm_weck/cli.py,sha256=
|
|
6
|
-
fm_weck/config.py,sha256=
|
|
7
|
-
fm_weck/engine.py,sha256=
|
|
5
|
+
fm_weck/cli.py,sha256=sY9MYVqma0b7abXyqoLZ2rh0JkP6y72WUayble_cPVY,29149
|
|
6
|
+
fm_weck/config.py,sha256=N7PgJRHXrhwNbfussz7NTGGMAVaFy9YiUbYFIXlRzVE,8009
|
|
7
|
+
fm_weck/engine.py,sha256=P48zCTeMHI3imE0ho5AxhDNTRY3mX0Nzd0gBzjqRCX4,21729
|
|
8
8
|
fm_weck/exceptions.py,sha256=AfqTt6gxZPUQ0rKqwgdGTyfIjWmU3xBFIJxQnMLbLGo,2465
|
|
9
9
|
fm_weck/file_util.py,sha256=FG_uBuNWGWbSivBv0dYzwugMkGfdS_iFY-hG6GLDD54,799
|
|
10
10
|
fm_weck/image_mgr.py,sha256=lkn1nWuwKtMhtVf_PFZOOJftY5uyE0EydY2f-sefHGE,1943
|
|
11
|
-
fm_weck/run_result.py,sha256=
|
|
12
|
-
fm_weck/runexec_mode.py,sha256=
|
|
11
|
+
fm_weck/run_result.py,sha256=58SIkYpdZY3l5A7UKk4Uz2V8W57uo_nfKQPZD3V4-Iw,1377
|
|
12
|
+
fm_weck/runexec_mode.py,sha256=ws1FwQxLFumh8iklFXeFRMgWXRLSWNX2eUlh-QcMqo8,3359
|
|
13
13
|
fm_weck/runexec_util.py,sha256=YBvVIPpmEousZVxbZ5NS8jzpKPLyws31kIFE2z3Ki2E,1370
|
|
14
14
|
fm_weck/serve.py,sha256=RUz_3v15By_CvcBJlNBw-mKuDubAiIha5EfayFBnqps,10728
|
|
15
|
-
fm_weck/smoke_test_mode.py,sha256=
|
|
15
|
+
fm_weck/smoke_test_mode.py,sha256=FAUftedyDl_-xxsU74CcX4RxYH_cPR0zsNkIZwkk2Os,4060
|
|
16
16
|
fm_weck/tmp_file.py,sha256=oJiE8VGTPxhl-bXdtbM8eNqQ4e9ECPG1jDmiboVDo_k,1956
|
|
17
17
|
fm_weck/version_listing.py,sha256=caaoC3n9R-Ao2sEQ_ngOVO3bnKr7cNVeH6EiA8jO5Sc,864
|
|
18
18
|
fm_weck/grpc_service/__init__.py,sha256=TvQSR0pVeh4MMMT40VfzJFyZTHpAOI7C808vjJpWiOs,390
|
|
@@ -30,7 +30,7 @@ fm_weck/grpc_service/proto/generate_protocol_files.sh,sha256=F9dd95qKejtB7B3P-x9
|
|
|
30
30
|
fm_weck/resources/BenchExec-3.27-py3-none-any.whl,sha256=g-db8LM8HfqLhbnl7n5lvUbMnF2tZ4MHAVOxTGxqO8w,732849
|
|
31
31
|
fm_weck/resources/BenchExec-3.27-py3-none-any.whl.license,sha256=Nq2Mwgn_pyr6ZZrTT095QPtFP3hr15ZeIRIaY0B7eC8,201
|
|
32
32
|
fm_weck/resources/Containerfile,sha256=HpPkrzJe1IKsmLOfbe5LbT-suaV6eJn1fT4csSvEkOk,390
|
|
33
|
-
fm_weck/resources/__init__.py,sha256=
|
|
33
|
+
fm_weck/resources/__init__.py,sha256=c3WqvUoTCFCM1SVxYEDQs4FqFxcNRiJkpeN5g-OA5VU,1550
|
|
34
34
|
fm_weck/resources/c_program_example.c,sha256=WOTAn4XyQL8TlplI6M8FbKiUxiwnvHUy2o6n0hLIe6o,21862
|
|
35
35
|
fm_weck/resources/run_with_overlay.sh,sha256=v1gV_6kMQ0v9BQ3chgDqI1MAOLHbPWeeTC52aCqVpEM,1162
|
|
36
36
|
fm_weck/resources/runexec,sha256=ogIBO38HLu9C9kDTTANBgAqVnH-UIF1bSJ9d3DSjyF4,462
|
|
@@ -165,7 +165,7 @@ fm_weck/resources/fm_tools/wit4java.yml,sha256=ylfze2XbV4zKkVUH57Veqn7G49gW0Byxd
|
|
|
165
165
|
fm_weck/resources/fm_tools/witch.yml,sha256=wwe6lrI2sxGKVZbLeipa38rPhB2pcSUFi9uVngtXGUQ,1795
|
|
166
166
|
fm_weck/resources/fm_tools/witnesslint.yml,sha256=EvMBcm5fx6lgSLRmHSKXSxXIJKZ-BrxLwTXI4GQ6FMs,6812
|
|
167
167
|
fm_weck/resources/fm_tools/witnessmap.yml,sha256=FyZtEloxpWBBjLn9kyqoen2kPjOkH2r4fxAj5gfV8Bg,1692
|
|
168
|
-
fm_weck-1.5.
|
|
169
|
-
fm_weck-1.5.
|
|
170
|
-
fm_weck-1.5.
|
|
171
|
-
fm_weck-1.5.
|
|
168
|
+
fm_weck-1.5.3.dist-info/METADATA,sha256=m_4VrPdPCvQesR-70_0l0y_wSZf1fROQ01QOoZFpUKo,3339
|
|
169
|
+
fm_weck-1.5.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
170
|
+
fm_weck-1.5.3.dist-info/entry_points.txt,sha256=toWpKCSY1u593MPnI_xW5gnwlnkerP4AvmPQ1s2nPgY,50
|
|
171
|
+
fm_weck-1.5.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|