From d50831a74cb803803c697dbc8814ff8dd140f5e5 Mon Sep 17 00:00:00 2001 From: kyvyt0n Date: Wed, 3 Jul 2024 18:32:19 +0100 Subject: [PATCH 1/5] Expand ~ in paths for cmdline_for_next_invocation --- rebench/executor.py | 6 ++++- rebench/model/benchmark_suite.py | 2 +- rebench/model/executor.py | 2 +- rebench/model/run_id.py | 5 +++- rebench/tests/model/runs_config_test.py | 24 +++++++++++++++++++ rebench/tests/small.conf | 2 +- rebench/tests/small_expand_user.conf | 32 +++++++++++++++++++++++++ rebench/tests/small_support_tilda.conf | 32 +++++++++++++++++++++++++ 8 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 rebench/tests/small_expand_user.conf create mode 100644 rebench/tests/small_support_tilda.conf diff --git a/rebench/executor.py b/rebench/executor.py index bd8461be..3b58d5a8 100644 --- a/rebench/executor.py +++ b/rebench/executor.py @@ -523,8 +523,12 @@ def _keep_alive(seconds): self.ui.warning( "Keep alive, current job runs for %dmin\n" % (seconds / 60), run_id, cmdline) + location = run_id.location + if location: + location = os.path.expanduser(location) + (return_code, output, _) = subprocess_timeout.run( - cmdline, env=run_id.env, cwd=run_id.location, stdout=subprocess.PIPE, + cmdline, env=run_id.env, cwd=location, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, verbose=self.debug, timeout=run_id.max_invocation_time, keep_alive_output=_keep_alive, diff --git a/rebench/model/benchmark_suite.py b/rebench/model/benchmark_suite.py index 081274f7..939606a9 100644 --- a/rebench/model/benchmark_suite.py +++ b/rebench/model/benchmark_suite.py @@ -32,7 +32,7 @@ def compile(cls, suite_name, suite, executor, build_commands): command = suite.get('command') location = suite.get('location', executor.path) - if location: + if location and not location.startswith('~'): location = os.path.abspath(location) build = BuildCommand.create_commands(suite.get('build'), build_commands, location) benchmarks_config = suite.get('benchmarks') diff --git a/rebench/model/executor.py b/rebench/model/executor.py index e2d9c803..f03794e3 100644 --- a/rebench/model/executor.py +++ b/rebench/model/executor.py @@ -31,7 +31,7 @@ class Executor(object): @classmethod def compile(cls, executor_name, executor, run_details, variables, build_commands, action): path = executor.get('path') - if path: + if path and not path.startswith('~'): path = os.path.abspath(path) executable = executor.get('executable') args = executor.get('args') diff --git a/rebench/model/run_id.py b/rebench/model/run_id.py index b880f146..b7b8c124 100644 --- a/rebench/model/run_id.py +++ b/rebench/model/run_id.py @@ -17,6 +17,7 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. +import os import re from .benchmark import Benchmark @@ -278,7 +279,9 @@ def cmdline(self): def cmdline_for_next_invocation(self): """Replace the invocation number in the command line""" - return self.cmdline() % {'invocation': self.completed_invocations + 1} + cmdline = self.cmdline() % {'invocation': self.completed_invocations + 1} + cmdline = cmdline.replace("~", os.path.expanduser("~")) + return cmdline def _construct_cmdline(self): cmdline = "" diff --git a/rebench/tests/model/runs_config_test.py b/rebench/tests/model/runs_config_test.py index 68a405ed..6a058185 100644 --- a/rebench/tests/model/runs_config_test.py +++ b/rebench/tests/model/runs_config_test.py @@ -17,6 +17,7 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. +import os from ...model.data_point import DataPoint from ...model.measurement import Measurement from ...model.termination_check import TerminationCheck @@ -79,3 +80,26 @@ def test_too_many_fails(self): check.indicate_failed_execution() self.assertTrue(check.should_terminate(0, None)) + + def test_expand_user(self): + self._cnf = Configurator(load_config(self._path + '/small_expand_user.conf'), DataStore(self.ui), + self.ui, None, data_file=self._tmp_file) + runs = self._cnf.get_runs() + sorted_runs = sorted(list(runs), key=lambda r: r.cmdline()) + self._run = sorted_runs[0] + expected_cmdline = os.path.expanduser( + '~/PycharmProjects/ReBench/rebench/tests/test-vm1.py 1 TestBenchMarks Bench1') + self.assertEqual(self._run.cmdline_for_next_invocation(), expected_cmdline) + self.assertNotIn("~", self._run.cmdline_for_next_invocation()) + + def test_command_path_expansion(self): + self._cnf = Configurator(load_config(self._path + '/small_support_tilda.conf'), DataStore(self.ui), + self.ui, None, data_file=self._tmp_file) + runs = self._cnf.get_runs() + sorted_runs = sorted(list(runs), key=lambda r: r.cmdline()) + self._run = sorted_runs[0] + expected_command = '~/PycharmProjects/ReBench/rebench/tests/test-vm1.py 1 TestBenchMarks ~/suiteFolder/Bench1'.replace('~', os.path.expanduser('~')) + + next_invocation_cmdline = self._run.cmdline_for_next_invocation() + self.assertNotIn("~", next_invocation_cmdline) + self.assertEqual(expected_command, next_invocation_cmdline) \ No newline at end of file diff --git a/rebench/tests/small.conf b/rebench/tests/small.conf index d7ce6d14..ca3d7f74 100644 --- a/rebench/tests/small.conf +++ b/rebench/tests/small.conf @@ -36,4 +36,4 @@ experiments: - Suite executions: - TestRunner1 - - TestRunner2 + - TestRunner2 \ No newline at end of file diff --git a/rebench/tests/small_expand_user.conf b/rebench/tests/small_expand_user.conf new file mode 100644 index 00000000..ded52ded --- /dev/null +++ b/rebench/tests/small_expand_user.conf @@ -0,0 +1,32 @@ +# Config file for ReBench +# Config format is YAML (see http://yaml.org/ for detailed spec) + +# this run definition will be chosen if no parameters are given to rebench.py +default_experiment: Test +default_data_file: 'small.data' + +# general configuration for runs +runs: + invocations: 10 + retries_after_failure: 3 + +benchmark_suites: + Suite: + gauge_adapter: TestExecutor + command: TestBenchMarks %(benchmark)s + benchmarks: + - Bench1 + - Bench2 + +executors: + TestRunner1: + path: ~/PycharmProjects/ReBench/rebench/tests + executable: test-vm1.py %(cores)s + cores: [1] + +experiments: + Test: + suites: + - Suite + executions: + - TestRunner1 \ No newline at end of file diff --git a/rebench/tests/small_support_tilda.conf b/rebench/tests/small_support_tilda.conf new file mode 100644 index 00000000..1a97c47b --- /dev/null +++ b/rebench/tests/small_support_tilda.conf @@ -0,0 +1,32 @@ +# Config file for ReBench +# Config format is YAML (see http://yaml.org/ for detailed spec) + +# this run definition will be chosen if no parameters are given to rebench.py +default_experiment: Test +default_data_file: 'small.data' + +# general configuration for runs +runs: + invocations: 10 + retries_after_failure: 3 + +benchmark_suites: + Suite: + gauge_adapter: TestExecutor + command: TestBenchMarks ~/suiteFolder/%(benchmark)s + benchmarks: + - Bench1 + - Bench2 + +executors: + TestRunner1: + path: ~/PycharmProjects/ReBench/rebench/tests + executable: test-vm1.py %(cores)s + cores: [1] + +experiments: + Test: + suites: + - Suite + executions: + - TestRunner1 \ No newline at end of file From e80f8823715ef337a21bd51a31fcd02403f5d864 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Fri, 5 Jul 2024 16:51:19 +0100 Subject: [PATCH 2/5] Simplify tests We only need a single test, since it covers both tested scenarios, the location, and the use of ~ in a command. Signed-off-by: Stefan Marr --- rebench/tests/model/runs_config_test.py | 24 ++++++------------- rebench/tests/small.conf | 2 +- rebench/tests/small_expand_user.conf | 8 +++---- rebench/tests/small_support_tilda.conf | 32 ------------------------- 4 files changed, 12 insertions(+), 54 deletions(-) delete mode 100644 rebench/tests/small_support_tilda.conf diff --git a/rebench/tests/model/runs_config_test.py b/rebench/tests/model/runs_config_test.py index 6a058185..a6ba50b8 100644 --- a/rebench/tests/model/runs_config_test.py +++ b/rebench/tests/model/runs_config_test.py @@ -17,7 +17,7 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -import os +from os.path import expanduser from ...model.data_point import DataPoint from ...model.measurement import Measurement from ...model.termination_check import TerminationCheck @@ -81,25 +81,15 @@ def test_too_many_fails(self): check.indicate_failed_execution() self.assertTrue(check.should_terminate(0, None)) - def test_expand_user(self): - self._cnf = Configurator(load_config(self._path + '/small_expand_user.conf'), DataStore(self.ui), - self.ui, None, data_file=self._tmp_file) + def test_command_user_path_expansion(self): + self._cnf = Configurator( + load_config(self._path + '/small_expand_user.conf'), DataStore(self.ui), + self.ui, None, data_file=self._tmp_file) runs = self._cnf.get_runs() sorted_runs = sorted(list(runs), key=lambda r: r.cmdline()) self._run = sorted_runs[0] - expected_cmdline = os.path.expanduser( - '~/PycharmProjects/ReBench/rebench/tests/test-vm1.py 1 TestBenchMarks Bench1') - self.assertEqual(self._run.cmdline_for_next_invocation(), expected_cmdline) - self.assertNotIn("~", self._run.cmdline_for_next_invocation()) - - def test_command_path_expansion(self): - self._cnf = Configurator(load_config(self._path + '/small_support_tilda.conf'), DataStore(self.ui), - self.ui, None, data_file=self._tmp_file) - runs = self._cnf.get_runs() - sorted_runs = sorted(list(runs), key=lambda r: r.cmdline()) - self._run = sorted_runs[0] - expected_command = '~/PycharmProjects/ReBench/rebench/tests/test-vm1.py 1 TestBenchMarks ~/suiteFolder/Bench1'.replace('~', os.path.expanduser('~')) + expected_cmd = '~/tests/vm1.py 1 Bench ~/suiteFolder/Bench1'.replace('~', expanduser('~')) next_invocation_cmdline = self._run.cmdline_for_next_invocation() self.assertNotIn("~", next_invocation_cmdline) - self.assertEqual(expected_command, next_invocation_cmdline) \ No newline at end of file + self.assertEqual(expected_cmd, next_invocation_cmdline) diff --git a/rebench/tests/small.conf b/rebench/tests/small.conf index ca3d7f74..d7ce6d14 100644 --- a/rebench/tests/small.conf +++ b/rebench/tests/small.conf @@ -36,4 +36,4 @@ experiments: - Suite executions: - TestRunner1 - - TestRunner2 \ No newline at end of file + - TestRunner2 diff --git a/rebench/tests/small_expand_user.conf b/rebench/tests/small_expand_user.conf index ded52ded..f15c132b 100644 --- a/rebench/tests/small_expand_user.conf +++ b/rebench/tests/small_expand_user.conf @@ -13,15 +13,15 @@ runs: benchmark_suites: Suite: gauge_adapter: TestExecutor - command: TestBenchMarks %(benchmark)s + command: Bench ~/suiteFolder/%(benchmark)s benchmarks: - Bench1 - Bench2 executors: TestRunner1: - path: ~/PycharmProjects/ReBench/rebench/tests - executable: test-vm1.py %(cores)s + path: ~/tests + executable: vm1.py %(cores)s cores: [1] experiments: @@ -29,4 +29,4 @@ experiments: suites: - Suite executions: - - TestRunner1 \ No newline at end of file + - TestRunner1 diff --git a/rebench/tests/small_support_tilda.conf b/rebench/tests/small_support_tilda.conf deleted file mode 100644 index 1a97c47b..00000000 --- a/rebench/tests/small_support_tilda.conf +++ /dev/null @@ -1,32 +0,0 @@ -# Config file for ReBench -# Config format is YAML (see http://yaml.org/ for detailed spec) - -# this run definition will be chosen if no parameters are given to rebench.py -default_experiment: Test -default_data_file: 'small.data' - -# general configuration for runs -runs: - invocations: 10 - retries_after_failure: 3 - -benchmark_suites: - Suite: - gauge_adapter: TestExecutor - command: TestBenchMarks ~/suiteFolder/%(benchmark)s - benchmarks: - - Bench1 - - Bench2 - -executors: - TestRunner1: - path: ~/PycharmProjects/ReBench/rebench/tests - executable: test-vm1.py %(cores)s - cores: [1] - -experiments: - Test: - suites: - - Suite - executions: - - TestRunner1 \ No newline at end of file From 34aab6dd45fe20f6710938944bdc8b7ec7d438c4 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Fri, 5 Jul 2024 16:59:03 +0100 Subject: [PATCH 3/5] =?UTF-8?q?Change=20test=20to=20include=20a=20~=20that?= =?UTF-8?q?=E2=80=99s=20not=20a=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stefan Marr --- rebench/tests/small_expand_user.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebench/tests/small_expand_user.conf b/rebench/tests/small_expand_user.conf index f15c132b..50ba72fe 100644 --- a/rebench/tests/small_expand_user.conf +++ b/rebench/tests/small_expand_user.conf @@ -13,7 +13,7 @@ runs: benchmark_suites: Suite: gauge_adapter: TestExecutor - command: Bench ~/suiteFolder/%(benchmark)s + command: Bench ~/suiteFolder/%(benchmark)s -message "a string with a ~" benchmarks: - Bench1 - Bench2 From ad2c4deb7f20230646f85736c89e0b52b3dc2bc0 Mon Sep 17 00:00:00 2001 From: kyvyt0n Date: Fri, 5 Jul 2024 17:28:39 +0100 Subject: [PATCH 4/5] Handle "~" in shell strings --- rebench/model/run_id.py | 7 ++++++- rebench/tests/model/runs_config_test.py | 7 ++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/rebench/model/run_id.py b/rebench/model/run_id.py index b7b8c124..726d63ab 100644 --- a/rebench/model/run_id.py +++ b/rebench/model/run_id.py @@ -19,6 +19,7 @@ # IN THE SOFTWARE. import os import re +import shlex from .benchmark import Benchmark from .termination_check import TerminationCheck @@ -280,7 +281,11 @@ def cmdline(self): def cmdline_for_next_invocation(self): """Replace the invocation number in the command line""" cmdline = self.cmdline() % {'invocation': self.completed_invocations + 1} - cmdline = cmdline.replace("~", os.path.expanduser("~")) + # split will change the type of quotes, which may cause issues with shell variables + parts = shlex.split(cmdline) + for i, part in enumerate(parts): + parts[i] = os.path.expanduser(part) + cmdline = shlex.join(parts) return cmdline def _construct_cmdline(self): diff --git a/rebench/tests/model/runs_config_test.py b/rebench/tests/model/runs_config_test.py index a6ba50b8..ae41f66b 100644 --- a/rebench/tests/model/runs_config_test.py +++ b/rebench/tests/model/runs_config_test.py @@ -88,8 +88,9 @@ def test_command_user_path_expansion(self): runs = self._cnf.get_runs() sorted_runs = sorted(list(runs), key=lambda r: r.cmdline()) self._run = sorted_runs[0] + print(self._run.cmdline()) expected_cmd = '~/tests/vm1.py 1 Bench ~/suiteFolder/Bench1'.replace('~', expanduser('~')) - + self.assertNotIn("~", expected_cmd) + expected_cmd += " -message 'a string with a ~'" next_invocation_cmdline = self._run.cmdline_for_next_invocation() - self.assertNotIn("~", next_invocation_cmdline) - self.assertEqual(expected_cmd, next_invocation_cmdline) + self.assertEqual(expected_cmd, next_invocation_cmdline) \ No newline at end of file From 780a18fab50e4e881e18155122b0a940ddff33f6 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Fri, 5 Jul 2024 17:36:06 +0100 Subject: [PATCH 5/5] Drop support for Python 3.7 and require Python 3.8 as minimum version Signed-off-by: Stefan Marr --- .github/workflows/ci.yml | 4 ++-- rebench/tests/model/runs_config_test.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f75c19bf..4959dd92 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,9 +8,9 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.7", "3.12", "pypy3.10"] + python-version: ["3.8", "3.12", "pypy3.10"] include: - - python-version: 3.7 + - python-version: 3.8 coverage: "--cov=rebench" name: "Ubuntu-latest: Python ${{ matrix.python-version }}" steps: diff --git a/rebench/tests/model/runs_config_test.py b/rebench/tests/model/runs_config_test.py index ae41f66b..1765af47 100644 --- a/rebench/tests/model/runs_config_test.py +++ b/rebench/tests/model/runs_config_test.py @@ -88,9 +88,9 @@ def test_command_user_path_expansion(self): runs = self._cnf.get_runs() sorted_runs = sorted(list(runs), key=lambda r: r.cmdline()) self._run = sorted_runs[0] - print(self._run.cmdline()) + expected_cmd = '~/tests/vm1.py 1 Bench ~/suiteFolder/Bench1'.replace('~', expanduser('~')) self.assertNotIn("~", expected_cmd) expected_cmd += " -message 'a string with a ~'" next_invocation_cmdline = self._run.cmdline_for_next_invocation() - self.assertEqual(expected_cmd, next_invocation_cmdline) \ No newline at end of file + self.assertEqual(expected_cmd, next_invocation_cmdline)