diff --git a/README.md b/README.md
index 46533562..1d070606 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ they lack some built-in mechanisms for verifying packages and finding mistakes
before uploading the package to the judge system.
As sinol-make was created specifically for the sio2 problem packages,
by default it downloads and uses sio2's deterministic mechanism of measuring
-solutions' runtime, called `oiejq`.
+solutions' runtime, called `sio2jail`.
### Installation
@@ -43,7 +43,7 @@ pip3 install sinol-make
so make sure this directory is in your `PATH`.
[Here's](https://gist.github.com/nex3/c395b2f8fd4b02068be37c961301caa7) how to add a directory to `PATH`.
-As `oiejq` works only on Linux-based operating systems,
+As `sio2jail` works only on Linux-based operating systems,
*we do not recommend* using operating systems such as Windows or macOS.
Nevertheless `sinol-make` supports those operating systems,
though there are additional installation steps required to use
@@ -67,8 +67,8 @@ activate-global-python-argcomplete
The available commands (see `sinol-make --help`) are:
- `sinol-make run` -- Runs selected solutions (by default all solutions) on selected tests (by default all tests) with a given number
-of CPUs. Measures the solutions' time with oiejq, unless specified otherwise. After running the solutions, it
-compares the solutions' scores with the ones saved in config.yml. If you're using oiejq, make sure you are not running on efficiency
+of CPUs. Measures the solutions' time with sio2jail, unless specified otherwise. After running the solutions, it
+compares the solutions' scores with the ones saved in config.yml. If you're using sio2jail, make sure you are not running on efficiency
cpu cores. You can check if you have them [like this](https://stackoverflow.com/a/71282744). To run on normal cpu cores, use
`taskset -c 8-15 sinol-make ...`, assuming that cpu cores 8-15 are not efficiency cores.
Run `sinol-make run --help` to see available flags.
@@ -113,15 +113,15 @@ There are also available short aliases for the commands:
the contest type with the `sinol_contest_type` key in config. Here is the table of available contest types and their
features:
-| Feature | `default` | `oi` | `oij` | `icpc` |
-|-----------------------------------------------------------------------------------------------------|-----------|-------|-------|--------|
-| Max score | 100 | 100 | 100 | 1 |
-| Default time tool | oiejq | oiejq | oiejq | time |
-| Full score if took less than half of the time limit,
otherwise linearly decreasing to 1. | ❌ | ✔️ | ❌ | ❌ |
-| Full score if took less than the time limit | ✔️ | ❌ | ✔️ | ✔️ |
-| Scores must sum up to 100 | ❌ | ✔️ | ✔️ | ❌ |
-| Limits can be set for individual tests | ✔️ | ❌ | ✔️ | ✔️ |
-| Verifies if tests are named correctly
(letters within groups increase, group numbers increase) | ❌ | ✔️ | ✔️ | ✔️ |
+| Feature | `default` | `oi` | `oij` | `icpc` |
+|-----------------------------------------------------------------------------------------------------|-----------|----------|----------|--------|
+| Max score | 100 | 100 | 100 | 1 |
+| Default time tool | sio2jail | sio2jail | sio2jail | time |
+| Full score if took less than half of the time limit,
otherwise linearly decreasing to 1. | ❌ | ✔️ | ❌ | ❌ |
+| Full score if took less than the time limit | ✔️ | ❌ | ✔️ | ✔️ |
+| Scores must sum up to 100 | ❌ | ✔️ | ✔️ | ❌ |
+| Limits can be set for individual tests | ✔️ | ❌ | ✔️ | ✔️ |
+| Verifies if tests are named correctly
(letters within groups increase, group numbers increase) | ❌ | ✔️ | ✔️ | ✔️ |
### Reporting bugs and contributing code
diff --git a/setup.cfg b/setup.cfg
index 85505e9f..0ed68cbf 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -51,4 +51,4 @@ testpaths =
tests
markers =
github_runner: Mark tests that require GitHub runner
- oiejq: Mark tests that require working oiejq
+ sio2jail: Mark tests that require working sio2jail
diff --git a/src/sinol_make/__init__.py b/src/sinol_make/__init__.py
index 3c1992b1..07262165 100644
--- a/src/sinol_make/__init__.py
+++ b/src/sinol_make/__init__.py
@@ -4,7 +4,7 @@
import traceback
import argcomplete
-from sinol_make import util, oiejq
+from sinol_make import util, sio2jail
# Required for side effects
from sinol_make.task_type.normal import NormalTaskType # noqa
@@ -36,19 +36,19 @@ def configure_parsers():
return parser
-def check_oiejq():
- if util.is_linux() and not oiejq.check_oiejq():
- print(util.warning('Up to date `oiejq` in `~/.local/bin/` not found, installing new version...'))
+def check_sio2jail():
+ if util.is_linux() and not sio2jail.check_sio2jail():
+ print(util.warning('Up to date `sio2jail` in `~/.local/bin/` not found, installing new version...'))
try:
- if oiejq.install_oiejq():
- print(util.info('`oiejq` was successfully installed.'))
+ if sio2jail.install_sio2jail():
+ print(util.info('Newest `sio2jail` was successfully installed.'))
else:
- util.exit_with_error('`oiejq` could not be installed.\n'
- 'You can download it from https://oij.edu.pl/zawodnik/srodowisko/oiejq.tar.gz, '
- 'unpack it to `~/.local/bin/` and rename oiejq.sh to oiejq.\n'
- 'You can also use --oiejq-path to specify path to your oiejq.')
+ util.exit_with_error('`sio2jail` could not be installed.\n'
+ 'You can download it from https://oij.edu.pl/zawodnik/srodowisko/oiejq.tar.gz '
+ 'and unpack it to `~/.local/bin/`.\n'
+ 'You can also use --sio2jail-path to specify path to your sio2jail.')
except Exception as err:
- util.exit_with_error('`oiejq` could not be installed.\n' + str(err))
+ util.exit_with_error('`sio2jail` could not be installed.\n' + str(err))
def main_exn():
@@ -74,7 +74,7 @@ def main_exn():
if not arguments:
parser.print_help()
exit(1)
- check_oiejq()
+ check_sio2jail()
for curr_args in arguments:
args = parser.parse_args(curr_args)
diff --git a/src/sinol_make/commands/init/__init__.py b/src/sinol_make/commands/init/__init__.py
index 7837c2f7..6b281078 100644
--- a/src/sinol_make/commands/init/__init__.py
+++ b/src/sinol_make/commands/init/__init__.py
@@ -38,7 +38,8 @@ def download_template(self):
if ret.returncode != 0:
util.exit_with_error("Could not access repository. Please try again.")
path = os.path.join(tmp_dir, package_dir)
- shutil.rmtree(os.path.join(path, '.git'))
+ if os.path.exists(os.path.join(path, '.git')):
+ shutil.rmtree(os.path.join(path, '.git'))
return path
def move_folder(self):
diff --git a/src/sinol_make/commands/run/__init__.py b/src/sinol_make/commands/run/__init__.py
index 3587737e..c252192e 100644
--- a/src/sinol_make/commands/run/__init__.py
+++ b/src/sinol_make/commands/run/__init__.py
@@ -13,7 +13,7 @@
from io import StringIO
from typing import Dict
-from sinol_make import contest_types, oiejq, util
+from sinol_make import contest_types, util, sio2jail
from sinol_make.structs.run_structs import ExecutionData, PrintData
from sinol_make.structs.cache_structs import CacheTest, CacheFile
from sinol_make.interfaces.BaseCommand import BaseCommand
@@ -276,11 +276,11 @@ def configure_subparser(self, subparser):
description='Runs selected solutions (by default all solutions) \
on selected tests (by default all tests) \
with a given number of cpus. \
- Measures the solutions\' time with oiejq, unless specified otherwise. \
+ Measures the solutions\' time with sio2jail, unless specified otherwise. \
After running the solutions, it compares the solutions\' scores with the ones saved in config.yml.'
)
- default_timetool = 'oiejq' if util.is_linux() else 'time'
+ default_timetool = 'sio2jail' if util.is_linux() else 'time'
parser.add_argument('-s', '--solutions', type=str, nargs='+',
help='solutions to be run, for example prog/abc{b,s}*.{cpp,py}')
@@ -291,10 +291,10 @@ def configure_subparser(self, subparser):
parser.add_argument('--ml', type=float, help='memory limit for all tests (in MB)')
parser.add_argument('--hide-memory', dest='hide_memory', action='store_true',
help='hide memory usage in report')
- parser.add_argument('-T', '--time-tool', dest='time_tool', choices=['oiejq', 'time'],
+ parser.add_argument('-T', '--time-tool', dest='time_tool', choices=['sio2jail', 'time'],
help=f'tool to measure time and memory usage (default: {default_timetool})')
- parser.add_argument('--oiejq-path', dest='oiejq_path', type=str,
- help='path to oiejq executable (default: `~/.local/bin/oiejq`)')
+ parser.add_argument('--sio2jail-path', dest='sio2jail_path', type=str,
+ help='path to sio2jail executable (default: `~/.local/bin/sio2jail`)')
parser.add_argument('-a', '--apply-suggestions', dest='apply_suggestions', action='store_true',
help='apply suggestions from expected scores report')
parser.add_argument('--ignore-expected', dest='ignore_expected', action='store_true',
@@ -765,26 +765,26 @@ def set_constants(self):
def validate_arguments(self, args):
compilers = compiler.verify_compilers(args, package_util.get_solutions(self.ID, None))
- def use_oiejq():
+ def use_sio2jail():
timetool_path = None
if not util.is_linux():
- util.exit_with_error('As `oiejq` works only on Linux-based operating systems,\n'
- 'we do not recommend using operating systems such as Windows or macOS.\n'
+ util.exit_with_error('As `sio2jail` works only on Linux-based operating systems,\n'
+ 'we do not recommend using operating systems such as macOS.\n'
'Nevertheless, you can still run sinol-make by specifying\n'
'another way of measuring time through the `--time-tool` flag.\n'
'See `sinol-make run --help` for more information about the flag.\n'
- 'See https://github.com/sio2project/sinol-make#why for more information about `oiejq`.\n')
+ 'See https://github.com/sio2project/sinol-make#why for more information about `sio2jail`.\n')
- oiejq.check_perf_counters_enabled()
- if 'oiejq_path' in args and args.oiejq_path is not None:
- if not oiejq.check_oiejq(args.oiejq_path):
- util.exit_with_error('Invalid oiejq path.')
- timetool_path = args.oiejq_path
+ sio2jail.check_perf_counters_enabled()
+ if 'sio2jail_path' in args and args.sio2jail_path is not None:
+ if not sio2jail.check_sio2jail(args.sio2jail_path):
+ util.exit_with_error('Invalid `sio2jail` path.')
+ timetool_path = args.sio2jail_path
else:
- timetool_path = oiejq.get_oiejq_path()
+ timetool_path = sio2jail.get_default_sio2jail_path()
if timetool_path is None:
- util.exit_with_error('oiejq is not installed.')
- return timetool_path, 'oiejq'
+ util.exit_with_error('`sio2jail` is not installed.')
+ return timetool_path, 'sio2jail'
def use_time():
if sys.platform == 'win32' or sys.platform == 'cygwin':
util.exit_with_error('Measuring with `time` is not supported on Windows.')
@@ -792,24 +792,24 @@ def use_time():
timetool_path, timetool_name = None, None
preferred_timetool = self.contest.preferred_timetool()
- if preferred_timetool == 'oiejq' and util.is_linux():
- use_default_timetool = use_oiejq
+ if preferred_timetool == 'sio2jail' and util.is_linux():
+ use_default_timetool = use_sio2jail
elif preferred_timetool == 'time':
use_default_timetool = use_time
else:
- use_default_timetool = use_oiejq if util.is_linux() else use_time
+ use_default_timetool = use_sio2jail if util.is_linux() else use_time
if args.time_tool is None and self.config.get('sinol_undocumented_time_tool', '') != '':
- if self.config.get('sinol_undocumented_time_tool', '') == 'oiejq':
- timetool_path, timetool_name = use_oiejq()
+ if self.config.get('sinol_undocumented_time_tool', '') == 'sio2jail':
+ timetool_path, timetool_name = use_sio2jail()
elif self.config.get('sinol_undocumented_time_tool', '') == 'time':
timetool_path, timetool_name = use_time()
else:
util.exit_with_error('Invalid time tool specified in config.yml.')
elif args.time_tool is None:
timetool_path, timetool_name = use_default_timetool()
- elif args.time_tool == 'oiejq':
- timetool_path, timetool_name = use_oiejq()
+ elif args.time_tool == 'sio2jail':
+ timetool_path, timetool_name = use_sio2jail()
elif args.time_tool == 'time':
timetool_path, timetool_name = use_time()
else:
diff --git a/src/sinol_make/contest_types/default.py b/src/sinol_make/contest_types/default.py
index 3e9bcc80..35108449 100644
--- a/src/sinol_make/contest_types/default.py
+++ b/src/sinol_make/contest_types/default.py
@@ -149,7 +149,7 @@ def preferred_timetool(self):
"""
Returns preferred time tool
"""
- return 'oiejq'
+ return 'sio2jail'
def verify_tests_order(self):
"""
diff --git a/src/sinol_make/executors/__init__.py b/src/sinol_make/executors/__init__.py
index a540377c..edd164bf 100644
--- a/src/sinol_make/executors/__init__.py
+++ b/src/sinol_make/executors/__init__.py
@@ -12,7 +12,7 @@ class BaseExecutor:
def __init__(self):
pass
- def _wrap_command(self, command: List[str], result_file_path: str) -> List[str]:
+ def _wrap_command(self, command: List[str], result_file_path: str, time_limit: int, memory_limit: int) -> List[str]:
"""
Wraps the command with the necessary tools to measure time and memory usage.
"""
@@ -44,7 +44,7 @@ def execute(self, command: List[str], time_limit, hard_time_limit, memory_limit,
Executes the command and returns the result, stdout and stderr.
"""
- command = self._wrap_command(command, result_file_path)
+ command = self._wrap_command(command, result_file_path, time_limit, memory_limit)
tle, mle, return_code, proc_stderr = self._execute(command, time_limit, hard_time_limit, memory_limit,
result_file_path, executable, execution_dir, stdin, stdout,
stderr, fds_to_close, *args, **kwargs)
diff --git a/src/sinol_make/executors/detailed.py b/src/sinol_make/executors/detailed.py
index c4eb17c5..dd1fce59 100644
--- a/src/sinol_make/executors/detailed.py
+++ b/src/sinol_make/executors/detailed.py
@@ -14,7 +14,7 @@ class DetailedExecutor(BaseExecutor):
Executor which doesn't use time or sio2jail for measuring time and memory usage.
"""
- def _wrap_command(self, command: List[str], result_file_path: str) -> List[str]:
+ def _wrap_command(self, command: List[str], result_file_path: str, time_limit: int, memory_limit: int) -> List[str]:
return command
def _execute(self, command: List[str], time_limit: int, hard_time_limit: int, memory_limit: int,
diff --git a/src/sinol_make/executors/oiejq.py b/src/sinol_make/executors/oiejq.py
deleted file mode 100644
index c30371f2..00000000
--- a/src/sinol_make/executors/oiejq.py
+++ /dev/null
@@ -1,85 +0,0 @@
-import os
-import signal
-import subprocess
-import sys
-from typing import List, Tuple, Union
-
-from sinol_make.executors import BaseExecutor
-from sinol_make.structs.status_structs import ExecutionResult, Status
-
-
-class OiejqExecutor(BaseExecutor):
- def __init__(self, oiejq_path):
- super().__init__()
- self.oiejq_path = oiejq_path
-
- def _wrap_command(self, command: List[str], result_file_path: str) -> List[str]:
- return [f'"{self.oiejq_path}"'] + command
-
- def _execute(self, command: List[str], time_limit: int, hard_time_limit: int, memory_limit: int,
- result_file_path: str, executable: str, execution_dir: str, stdin: int, stdout: int,
- stderr: Union[None, int], fds_to_close: Union[None, List[int]],
- *args, **kwargs) -> Tuple[bool, bool, int, List[str]]:
- env = os.environ.copy()
- env["MEM_LIMIT"] = f'{memory_limit}K'
- env["MEASURE_MEM"] = "1"
- env["UNDER_OIEJQ"] = "1"
-
- timeout = False
- with open(result_file_path, "w") as result_file:
- process = subprocess.Popen(' '.join(command), *args, shell=True, stdin=stdin, stdout=stdout,
- stderr=result_file, env=env, preexec_fn=os.setpgrp, cwd=execution_dir, **kwargs)
- if fds_to_close is not None:
- for fd in fds_to_close:
- os.close(fd)
-
- try:
- process.wait(timeout=hard_time_limit)
- except subprocess.TimeoutExpired:
- timeout = True
- try:
- os.killpg(process.pid, signal.SIGKILL)
- except ProcessLookupError:
- pass
- process.communicate()
-
- return timeout, False, 0, []
-
- def _parse_time(self, time_str):
- if len(time_str) < 3: return -1
- return int(time_str[:-2])
-
- def _parse_memory(self, memory_str):
- if len(memory_str) < 3: return -1
- return int(memory_str[:-2])
-
- def _parse_result(self, tle, mle, return_code, result_file_path) -> ExecutionResult:
- result = ExecutionResult()
- if not tle:
- with open(result_file_path, "r") as result_file:
- lines = result_file.readlines()
-
- stderr = []
- i = 0
- while lines[i].strip() != "-------------------------":
- stderr.append(lines[i])
- i += 1
- result.Stderr = stderr[:-1] # oiejq adds a blank line.
-
- for line in lines:
- line = line.strip()
- if ": " in line:
- (key, value) = line.split(": ")[:2]
- if key == "Time":
- result.Time = self._parse_time(value)
- elif key == "Memory":
- result.Memory = self._parse_memory(value)
- else:
- setattr(result, key, value)
-
- if lines[-2].strip() == 'Details':
- result.Error = lines[-1].strip()
- if lines[-1].startswith("process exited due to signal"):
- result.ExitSignal = int(lines[-1].strip()[len("process exited due to signal "):])
- result.Status = Status.from_str(result.Status)
- return result
diff --git a/src/sinol_make/executors/sio2jail.py b/src/sinol_make/executors/sio2jail.py
new file mode 100644
index 00000000..b87049c1
--- /dev/null
+++ b/src/sinol_make/executors/sio2jail.py
@@ -0,0 +1,91 @@
+import os
+import signal
+import subprocess
+import sys
+from typing import List, Tuple, Union
+
+from sinol_make import util
+from sinol_make.executors import BaseExecutor
+from sinol_make.structs.status_structs import ExecutionResult, Status
+
+
+class Sio2jailExecutor(BaseExecutor):
+ def __init__(self, sio2jail_path):
+ super().__init__()
+ self.sio2jail_path = sio2jail_path
+
+ def _wrap_command(self, command: List[str], result_file_path: str, time_limit: int, memory_limit: int) -> List[str]:
+ # see: https://github.com/sio2project/sioworkers/blob/738aa7a4e93216b0900ca128d6d48d40cd38bc1e/sio/workers/executors.py#L608
+ return [f'"{self.sio2jail_path}"', '--mount-namespace', 'off', '--pid-namespace', 'off', '--uts-namespace',
+ 'off', '--ipc-namespace', 'off', '--net-namespace', 'off', '--capability-drop', 'off',
+ '--user-namespace', 'off', '--instruction-count-limit', f'{int(2 * time_limit)}M',
+ '--rtimelimit', f'{int(16 * time_limit + 1000)}ms', '--memory-limit', f'{int(memory_limit)}K',
+ '--output-limit', '51200K', '--output', 'oiaug', '--stderr', '--'] + command
+
+ def _execute(self, command: List[str], time_limit: int, hard_time_limit: int, memory_limit: int,
+ result_file_path: str, executable: str, execution_dir: str, stdin: int, stdout: int,
+ stderr: Union[None, int], fds_to_close: Union[None, List[int]],
+ *args, **kwargs) -> Tuple[bool, bool, int, List[str]]:
+ env = os.environ.copy()
+ env['UNDER_SIO2JAIL'] = "1"
+ with open(result_file_path, "w") as result_file:
+ try:
+ process = subprocess.Popen(' '.join(command), *args, shell=True, stdin=stdin, stdout=stdout, env=env,
+ stderr=result_file, preexec_fn=os.setpgrp, cwd=execution_dir, **kwargs)
+ except TypeError as e:
+ print(util.error("Invalid command: " + str(command)))
+ raise e
+ if fds_to_close is not None:
+ for fd in fds_to_close:
+ os.close(fd)
+ process.wait()
+
+ return False, False, 0, []
+
+ def _parse_time(self, time_str):
+ if len(time_str) < 3: return -1
+ return int(time_str[:-2])
+
+ def _parse_memory(self, memory_str):
+ if len(memory_str) < 3: return -1
+ return int(memory_str[:-2])
+
+ def _parse_result(self, _, mle, return_code, result_file_path) -> ExecutionResult:
+ result = ExecutionResult()
+ with open(result_file_path, "r") as result_file:
+ lines = result_file.readlines()
+
+ result.stderr = lines[:-2]
+
+ status, code, time_ms, _, memory_kb, _ = lines[-2].strip().split()
+ message = lines[-1].strip()
+ result.Time = int(time_ms)
+ result.Memory = int(memory_kb)
+
+ # ignoring `status` is weird, but sio2 does it this way
+ if message == 'ok':
+ result.Status = Status.OK
+ elif message == 'time limit exceeded':
+ result.Status = Status.TL
+ elif message == 'real time limit exceeded':
+ result.Status = Status.TL
+ result.Error = message
+ elif message == 'memory limit exceeded':
+ result.Status = Status.ML
+ # TODO: sinol-make does not support "OLE"
+ result.Status = Status.RE
+ result.Error = message
+ elif message.startswith('intercepted forbidden syscall'):
+ # TODO: sinol-make does not support "RV"
+ result.Status = Status.RE
+ result.Error = message
+ elif message.startswith('process exited due to signal'):
+ code = message[len('process exited due to signal '):]
+ result.Status = Status.RE
+ result.Error = message
+ result.ExitSignal = int(code)
+ else:
+ result.Status = Status.RE
+ result.Error = 'Unrecognized Sio2jail result: ' + message
+
+ return result
diff --git a/src/sinol_make/executors/time.py b/src/sinol_make/executors/time.py
index 78a76bbb..5a6aee90 100644
--- a/src/sinol_make/executors/time.py
+++ b/src/sinol_make/executors/time.py
@@ -12,7 +12,7 @@
class TimeExecutor(BaseExecutor):
- def _wrap_command(self, command: List[str], result_file_path: str) -> List[str]:
+ def _wrap_command(self, command: List[str], result_file_path: str, time_limit: int, memory_limit: int) -> List[str]:
if sys.platform == 'darwin':
time_name = 'gtime'
elif sys.platform == 'linux':
diff --git a/src/sinol_make/oiejq/__init__.py b/src/sinol_make/oiejq/__init__.py
deleted file mode 100644
index 92f1f7f5..00000000
--- a/src/sinol_make/oiejq/__init__.py
+++ /dev/null
@@ -1,128 +0,0 @@
-import os
-import subprocess
-import sys
-import shutil
-import tarfile
-import tempfile
-import requests
-
-from sinol_make import util
-
-
-def _check_if_oiejq_executable(path):
- if not os.access(path, os.X_OK):
- return False
-
- oiejq = subprocess.Popen([path], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- oiejq.wait()
- return oiejq.returncode == 0
-
-
-def _check_sio2jail(path):
- sio2jail = subprocess.Popen(path + " --version", shell=True,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- out, _ = sio2jail.communicate()
- return out == (b"SIO2jail v1.5.0 compiled on Apr 15 2024 12:34:31 Linux 6.1.0-20-amd64 with gcc 10.2.1 20210110\n"
- b"libseccomp 2.5.4\n")
-
-
-def _check_oiejq(path):
- return util.get_file_md5(path) == '7225efe59cb3052fa533b9fbc9ebf099'
-
-
-def check_oiejq(path = None):
- """
- Function to check if oiejq is installed
- """
- if not util.is_linux():
- return False
-
- if path is not None:
- return _check_if_oiejq_executable(path) and _check_sio2jail(os.path.join(os.path.dirname(path), 'sio2jail')) \
- and _check_oiejq(path)
-
- if _check_if_oiejq_executable(os.path.expanduser('~/.local/bin/oiejq')) and \
- _check_sio2jail(os.path.expanduser('~/.local/bin/sio2jail')) and \
- _check_oiejq(os.path.expanduser('~/.local/bin/oiejq')):
- return True
- else:
- return False
-
-
-def install_oiejq():
- """
- Function to install oiejq, if not installed.
- Returns True if successful.
- """
- if not util.is_linux():
- return False
- if check_oiejq():
- return True
-
- if not os.path.exists(os.path.expanduser('~/.local/bin')):
- os.makedirs(os.path.expanduser('~/.local/bin'), exist_ok=True)
-
- if os.path.exists(os.path.expanduser('~/.local/bin/oiejq')) and \
- not _check_if_oiejq_executable(os.path.expanduser('~/.local/bin/oiejq')):
- util.exit_with_error("Couldn't install `oiejq`.\n"
- "There is a file/directory named `oiejq` in `~/.local/bin` which isn't an `oiejq` executable.\n"
- "Please rename it or remove it and try again.")
-
- try:
- request = requests.get('https://oij.edu.pl/zawodnik/srodowisko/oiejq.tar.gz')
- except requests.exceptions.ConnectionError:
- raise Exception('Couldn\'t download oiejq (https://oij.edu.pl/zawodnik/srodowisko/oiejq.tar.gz couldn\'t connect)')
- if request.status_code != 200:
- raise Exception('Couldn\'t download oiejq (https://oij.edu.pl/zawodnik/srodowisko/oiejq.tar.gz returned status code: ' + str(request.status_code) + ')')
-
- # oiejq is downloaded to a temporary directory and not to the `.cache` dir,
- # as there is no guarantee that the current directory is the package directory.
- # The `.cache` dir is only used for files that are part of the package and those
- # that the package creator might want to look into.
- with tempfile.TemporaryDirectory() as tmpdir:
- oiejq_path = os.path.join(tmpdir, 'oiejq.tar.gz')
- with open(oiejq_path, 'wb') as oiejq_file:
- oiejq_file.write(request.content)
-
- with tarfile.open(oiejq_path) as tar:
- util.extract_tar(tar, tmpdir)
- shutil.copy(os.path.join(tmpdir, 'oiejq', 'oiejq.sh'), os.path.expanduser('~/.local/bin/oiejq'))
- shutil.copy(os.path.join(tmpdir, 'oiejq', 'sio2jail'), os.path.expanduser('~/.local/bin/'))
-
- return check_oiejq()
-
-
-def get_oiejq_path():
- if _check_if_oiejq_executable(os.path.expanduser('~/.local/bin/oiejq')):
- return os.path.expanduser('~/.local/bin/oiejq')
- else:
- return None
-
-
-def check_perf_counters_enabled():
- """
- Checks if `kernel.perf_event_paranoid` is set to -1.
- :return:
- """
- if not util.is_linux() or not check_oiejq():
- return
-
- oiejq = get_oiejq_path()
- test_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'perf_test.py')
- python_executable = sys.executable
-
- # subprocess.Pipe is not used, because than the code would hang on process.communicate()
- with tempfile.TemporaryFile() as tmpfile:
- process = subprocess.Popen([oiejq, python_executable, test_file], stdout=tmpfile, stderr=subprocess.DEVNULL)
- process.wait()
- tmpfile.seek(0)
- output = tmpfile.read().decode('utf-8')
- process.terminate()
-
- if output != "Test string\n":
- util.exit_with_error("To use the recommended tool for measuring time called oiejq, please:\n"
- "- execute `sudo sysctl kernel.perf_event_paranoid=-1` to make oiejq work for\n"
- " the current system session,\n"
- "- or add `kernel.perf_event_paranoid=-1` to `/etc/sysctl.conf`\n"
- " and reboot to permanently make oiejq work.\n"
- "For more details, see https://github.com/sio2project/sio2jail#running.\n")
diff --git a/src/sinol_make/sio2jail/__init__.py b/src/sinol_make/sio2jail/__init__.py
new file mode 100644
index 00000000..a1dc03eb
--- /dev/null
+++ b/src/sinol_make/sio2jail/__init__.py
@@ -0,0 +1,102 @@
+import os
+import subprocess
+import sys
+import shutil
+import tarfile
+import tempfile
+import requests
+
+from sinol_make import util
+
+
+def sio2jail_supported():
+ return util.is_linux()
+
+
+def get_default_sio2jail_path():
+ return os.path.expanduser('~/.local/bin/sio2jail')
+
+
+def check_sio2jail(path=None):
+ if path is None:
+ path = get_default_sio2jail_path()
+ try:
+ sio2jail = subprocess.Popen([path, "--version"],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, _ = sio2jail.communicate()
+ out = out.decode(sys.stdout.encoding)
+ if not out.startswith("SIO2jail v1.5.0 "):
+ return False
+ except FileNotFoundError:
+ return False
+ return True
+
+
+def install_sio2jail(directory=None):
+ """
+ Downloads and installs sio2jail to the specified directory, creating it if it doesn't exist
+ """
+ if directory is None:
+ directory = os.path.expanduser('~/.local/bin')
+ path = os.path.join(directory, 'sio2jail')
+ if os.path.exists(path) and check_sio2jail(path):
+ return
+
+ print(util.warning(f'`sio2jail` not found in `{path}`, attempting download...'))
+
+ os.makedirs(directory, exist_ok=True)
+
+ url = 'https://oij.edu.pl/zawodnik/srodowisko/oiejq.tar.gz'
+ try:
+ request = requests.get(url)
+ except requests.exceptions.ConnectionError:
+ util.exit_with_error('Couldn\'t download sio2jail ({url} couldn\'t connect)')
+ if request.status_code != 200:
+ util.exit_with_error('Couldn\'t download sio2jail ({url} returned status code: ' + str(request.status_code) + ')')
+
+ # oiejq is downloaded to a temporary directory and not to the `.cache` dir,
+ # as there is no guarantee that the current directory is the package directory.
+ # The `.cache` dir is only used for files that are part of the package and those
+ # that the package creator might want to look into.
+ with tempfile.TemporaryDirectory() as tmpdir:
+ oiejq_path = os.path.join(tmpdir, 'oiejq.tar.gz')
+ with open(oiejq_path, 'wb') as oiejq_file:
+ oiejq_file.write(request.content)
+
+ with tarfile.open(oiejq_path) as tar:
+ util.extract_tar(tar, tmpdir)
+ shutil.copy(os.path.join(tmpdir, 'oiejq', 'sio2jail'), directory)
+
+ check_sio2jail(path)
+ print(util.info(f'`sio2jail` was successfully installed in `{path}`'))
+ return True
+
+
+def check_perf_counters_enabled():
+ """
+ Checks if `kernel.perf_event_paranoid` is set to -1.
+ :return:
+ """
+ if not util.is_linux() or not check_sio2jail():
+ return
+
+ sio2jail = get_default_sio2jail_path()
+ test_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'perf_test.py')
+ python_executable = sys.executable
+
+ # subprocess.Pipe is not used, because than the code would hang on process.communicate()
+ with tempfile.TemporaryFile() as tmpfile:
+ process = subprocess.Popen([sio2jail, '--mount-namespace', 'off', '--', python_executable, test_file],
+ stdout=tmpfile, stderr=subprocess.DEVNULL)
+ process.wait()
+ tmpfile.seek(0)
+ output = tmpfile.read().decode('utf-8')
+ process.terminate()
+
+ if output != "Test string\n":
+ util.exit_with_error("To use the recommended tool for measuring time called `sio2jail`, please:\n"
+ "- execute `sudo sysctl kernel.perf_event_paranoid=-1` to make `sio2jail` work for\n"
+ " the current system session,\n"
+ "- or add `kernel.perf_event_paranoid=-1` to `/etc/sysctl.conf`\n"
+ " and reboot to permanently make sio2jail work.\n"
+ "For more details, see https://github.com/sio2project/sio2jail#running.\n")
diff --git a/src/sinol_make/oiejq/perf_test.py b/src/sinol_make/sio2jail/perf_test.py
similarity index 100%
rename from src/sinol_make/oiejq/perf_test.py
rename to src/sinol_make/sio2jail/perf_test.py
diff --git a/src/sinol_make/task_type/__init__.py b/src/sinol_make/task_type/__init__.py
index e55cbf64..e37c20c9 100644
--- a/src/sinol_make/task_type/__init__.py
+++ b/src/sinol_make/task_type/__init__.py
@@ -4,7 +4,7 @@
from typing import Tuple, List, Type
from sinol_make import util
-from sinol_make.executors.oiejq import OiejqExecutor
+from sinol_make.executors.sio2jail import Sio2jailExecutor
from sinol_make.executors.time import TimeExecutor
from sinol_make.helpers import package_util, paths, cache
from sinol_make.helpers.classinit import RegisteredSubclassesBase
@@ -54,17 +54,17 @@ def _check_task_type_changed(self):
with open(paths.get_cache_path("task_type"), "w") as f:
f.write(name)
- def __init__(self, timetool, oiejq_path):
+ def __init__(self, timetool, sio2jail_path):
super().__init__()
self.timetool = timetool
- self.oiejq_path = oiejq_path
+ self.sio2jail_path = sio2jail_path
self.has_checker = False
self.checker_path = None
if self.timetool == 'time':
self.executor = TimeExecutor()
- elif self.timetool == 'oiejq':
- self.executor = OiejqExecutor(oiejq_path)
+ elif self.timetool == 'sio2jail':
+ self.executor = Sio2jailExecutor(sio2jail_path)
else:
util.exit_with_error(f"Unknown timetool {self.timetool}")
self._check_task_type_changed()
diff --git a/src/sinol_make/task_type/interactive.py b/src/sinol_make/task_type/interactive.py
index 80de24d6..25e47260 100644
--- a/src/sinol_make/task_type/interactive.py
+++ b/src/sinol_make/task_type/interactive.py
@@ -72,8 +72,8 @@ def identify(cls) -> Tuple[bool, int]:
def name() -> str:
return "interactive"
- def __init__(self, timetool, oiejq_path):
- super().__init__(timetool, oiejq_path)
+ def __init__(self, timetool, sio2jail_path):
+ super().__init__(timetool, sio2jail_path)
self.has_checker = False
self.interactor = None
self.interactor_executor = DetailedExecutor()
diff --git a/tests/commands/run/test_integration.py b/tests/commands/run/test_integration.py
index 993931b2..653c1397 100644
--- a/tests/commands/run/test_integration.py
+++ b/tests/commands/run/test_integration.py
@@ -8,7 +8,7 @@
from sinol_make.structs.cache_structs import CacheFile
from ...fixtures import *
from .util import *
-from sinol_make import configure_parsers, util, oiejq
+from sinol_make import configure_parsers, util, sio2jail
@pytest.mark.parametrize("create_package", [get_simple_package_path(), get_verify_status_package_path(),
@@ -525,7 +525,7 @@ def test_undocumented_time_tool_option(create_package):
assert command.timetool_path == "time"
-@pytest.mark.oiejq
+@pytest.mark.sio2jail
@pytest.mark.parametrize("create_package", [get_undocumented_options_package_path()], indirect=True)
def test_override_undocumented_time_tool_option(create_package):
"""
@@ -534,10 +534,10 @@ def test_override_undocumented_time_tool_option(create_package):
package_path = create_package
create_ins_outs(package_path)
parser = configure_parsers()
- args = parser.parse_args(["run", "--time-tool", "oiejq"])
+ args = parser.parse_args(["run", "--time-tool", "sio2jail"])
command = Command()
command.run(args)
- assert command.timetool_path == oiejq.get_oiejq_path()
+ assert command.timetool_path == sio2jail.get_default_sio2jail_path()
@pytest.mark.parametrize("create_package", [get_undocumented_options_package_path()], indirect=True)
diff --git a/tests/commands/run/test_unit.py b/tests/commands/run/test_unit.py
index 7ce66616..2ce6a818 100644
--- a/tests/commands/run/test_unit.py
+++ b/tests/commands/run/test_unit.py
@@ -1,6 +1,6 @@
import argparse, re, yaml
-from sinol_make import util, oiejq
+from sinol_make import util, sio2jail
from sinol_make.structs.status_structs import Status, ResultChange, ValidationResult
from sinol_make.helpers import package_util
from sinol_make.task_type.normal import NormalTaskType
@@ -28,7 +28,7 @@ def test_execution(create_package, time_tool):
command = get_command(package_path)
command.args.time_tool = time_tool
command.timetool_name = time_tool
- command.task_type = NormalTaskType(timetool=time_tool, oiejq_path=oiejq.get_oiejq_path())
+ command.task_type = NormalTaskType(timetool=time_tool, sio2jail_path=sio2jail.get_default_sio2jail_path())
solution = "abc.cpp"
executable = package_util.get_executable(solution)
result = command.compile_solutions([solution])
@@ -42,7 +42,7 @@ def test_execution(create_package, time_tool):
os.makedirs(paths.get_executions_path(solution), exist_ok=True)
result = command.run_solution((solution, paths.get_executables_path(executable), test, config['time_limit'],
- config['memory_limit'], oiejq.get_oiejq_path(), paths.get_executions_path()))
+ config['memory_limit'], sio2jail.get_default_sio2jail_path(), paths.get_executions_path()))
assert result.Status == Status.OK
@@ -59,9 +59,9 @@ def test_run_solutions(create_package, time_tool):
command.possible_score = command.get_possible_score(command.groups)
command.memory_limit = command.config["memory_limit"]
command.time_limit = command.config["time_limit"]
- command.timetool_path = oiejq.get_oiejq_path()
+ command.timetool_path = sio2jail.get_default_sio2jail_path()
command.timetool_name = time_tool
- command.task_type = NormalTaskType(timetool=time_tool, oiejq_path=oiejq.get_oiejq_path())
+ command.task_type = NormalTaskType(timetool=time_tool, sio2jail_path=sio2jail.get_default_sio2jail_path())
def flatten_results(results):
new_results = {}
for solution in results.keys():
diff --git a/tests/conftest.py b/tests/conftest.py
index 8882f8a2..06c3fd16 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -31,7 +31,7 @@ def pytest_addoption(parser):
parser.addoption("--github-runner", action="store_true", help="if set, will run tests specified for GitHub runner")
parser.addoption(
'--time-tool',
- choices=['oiejq', 'time'],
+ choices=['sio2jail', 'time'],
action='append',
default=[],
help='Time tool to use. Default: if linux - both, otherwise time'
@@ -93,7 +93,7 @@ def pytest_generate_tests(metafunc):
if metafunc.config.getoption("time_tool") != []:
time_tools = metafunc.config.getoption("time_tool")
elif util.is_linux():
- time_tools = ["oiejq", "time"]
+ time_tools = ["sio2jail", "time"]
else:
time_tools = ["time"]
metafunc.parametrize("time_tool", time_tools)
@@ -110,7 +110,7 @@ def pytest_collection_modifyitems(config, items: List[pytest.Item]):
item.add_marker(pytest.mark.skip(reason="only for GitHub runner"))
for item in items:
- if "oiejq" in item.keywords:
+ if "sio2jail" in item.keywords:
if not util.is_linux() or config.getoption("--time-tool") == ["time"] or \
config.getoption("--github-runner"):
- item.add_marker(pytest.mark.skip(reason="oiejq required"))
+ item.add_marker(pytest.mark.skip(reason="sio2jail required"))
diff --git a/tests/packages/lim/prog/lim2.cpp b/tests/packages/lim/prog/lim2.cpp
index 7c0923ac..662d64bb 100644
--- a/tests/packages/lim/prog/lim2.cpp
+++ b/tests/packages/lim/prog/lim2.cpp
@@ -12,7 +12,7 @@ void s2j_wait(long long instructions) {
}
int wait(int secs) {
- if (getenv("UNDER_OIEJQ") != NULL) {
+ if (getenv("UNDER_SIO2JAIL") != NULL) {
s2j_wait((long long)secs * 2'000'000'000);
return 0;
}
diff --git a/tests/packages/ovl/prog/ovl.cpp b/tests/packages/ovl/prog/ovl.cpp
index 8fe4ccff..41244b18 100644
--- a/tests/packages/ovl/prog/ovl.cpp
+++ b/tests/packages/ovl/prog/ovl.cpp
@@ -12,7 +12,7 @@ void s2j_wait(long long instructions) {
}
int wait(int secs) {
- if (getenv("UNDER_OIEJQ") != NULL) {
+ if (getenv("UNDER_SIO2JAIL") != NULL) {
s2j_wait((long long)secs * 2'000'000'000);
return 0;
}
diff --git a/tests/packages/vso/prog/vso4.cpp b/tests/packages/vso/prog/vso4.cpp
index 53053f1a..a98acba2 100644
--- a/tests/packages/vso/prog/vso4.cpp
+++ b/tests/packages/vso/prog/vso4.cpp
@@ -22,7 +22,7 @@ void s2j_wait(long long instructions) {
}
int wait(int secs) {
- if (getenv("UNDER_OIEJQ") != NULL) {
+ if (getenv("UNDER_SIO2JAIL") != NULL) {
s2j_wait((long long)secs * 2'000'000'000);
return 0;
}
diff --git a/tests/packages/vso/prog/vso7.cpp b/tests/packages/vso/prog/vso7.cpp
index f84a630e..ef1503e2 100644
--- a/tests/packages/vso/prog/vso7.cpp
+++ b/tests/packages/vso/prog/vso7.cpp
@@ -22,7 +22,7 @@ void s2j_wait(long long instructions) {
}
int wait(int secs) {
- if (getenv("UNDER_OIEJQ") != NULL) {
+ if (getenv("UNDER_SIO2JAIL") != NULL) {
s2j_wait((long long)secs * 2'000'000'000);
return 0;
}
diff --git a/tests/test_oiejq.py b/tests/test_oiejq.py
deleted file mode 100644
index 16f69bab..00000000
--- a/tests/test_oiejq.py
+++ /dev/null
@@ -1,120 +0,0 @@
-import os
-import shutil
-import sys
-from urllib.request import urlretrieve
-import pytest
-
-from sinol_make import oiejq, util
-
-
-@pytest.mark.github_runner
-def test_install_oiejq():
- if sys.platform != 'linux':
- return
-
- try:
- os.remove(os.path.expanduser('~/.local/bin/oiejq'))
- os.remove(os.path.expanduser('~/.local/bin/sio2jail'))
- except IsADirectoryError:
- shutil.rmtree(os.path.expanduser('~/.local/bin/oiejq'), ignore_errors=True)
- except FileNotFoundError:
- pass
- assert not oiejq.check_oiejq()
- assert oiejq.install_oiejq()
- assert oiejq.get_oiejq_path() == os.path.expanduser('~/.local/bin/oiejq')
-
- try:
- os.remove(os.path.expanduser('~/.local/bin/oiejq'))
- os.remove(os.path.expanduser('~/.local/bin/sio2jail'))
- except FileNotFoundError:
- pass
-
- assert not oiejq.check_oiejq()
- os.makedirs(os.path.expanduser('~/.local/bin/oiejq'))
- with pytest.raises(SystemExit):
- oiejq.install_oiejq()
-
- # Test if oiejq is reinstalled when oiejq.sh is changed
- os.rmdir(os.path.expanduser('~/.local/bin/oiejq'))
- oiejq.install_oiejq()
- with open(os.path.expanduser('~/.local/bin/oiejq'), 'a') as f:
- f.write('\n')
- assert not oiejq.check_oiejq()
- oiejq.install_oiejq()
-
-
-@pytest.mark.github_runner
-def test_check_oiejq():
- if sys.platform != 'linux':
- return
-
- try:
- os.remove(os.path.expanduser('~/.local/bin/oiejq'))
- os.remove(os.path.expanduser('~/.local/bin/sio2jail'))
- except IsADirectoryError:
- shutil.rmtree(os.path.expanduser('~/.local/bin/oiejq'), ignore_errors=True)
- except FileNotFoundError:
- pass
-
- assert not oiejq.check_oiejq()
- os.makedirs(os.path.expanduser('~/.local/bin/oiejq'), exist_ok=True)
- assert not oiejq.check_oiejq()
- os.rmdir(os.path.expanduser('~/.local/bin/oiejq'))
- with open(os.path.expanduser('~/.local/bin/oiejq'), 'w') as f:
- f.write('abcdef')
- assert not oiejq.check_oiejq()
- os.chmod(os.path.expanduser('~/.local/bin/oiejq'), 0o777)
- assert not oiejq.check_oiejq()
- with open(os.path.expanduser('~/.local/bin/oiejq'), 'w') as f:
- f.write('#!/bin/bash\necho "test"')
- assert oiejq._check_if_oiejq_executable(os.path.expanduser('~/.local/bin/oiejq'))
-
-
-@pytest.mark.github_runner
-def test_perf_counters_not_set():
- """
- Test `oiejq.check_perf_counters_enabled` with perf counters disabled
- """
- if sys.platform != 'linux':
- return
-
- oiejq.install_oiejq()
- with pytest.raises(SystemExit):
- oiejq.check_perf_counters_enabled()
-
-
-@pytest.mark.oiejq
-def test_perf_counters_set():
- """
- Test `oiejq.check_perf_counters_enabled` with perf counters enabled
- """
- if not util.is_linux():
- return
- oiejq.check_perf_counters_enabled()
-
-
-@pytest.mark.github_runner
-def test_updating():
- """
- Test updating oiejq
- """
- if sys.platform != 'linux':
- return
- try:
- os.remove(os.path.expanduser('~/.local/bin/oiejq'))
- os.remove(os.path.expanduser('~/.local/bin/sio2jail'))
- except IsADirectoryError:
- shutil.rmtree(os.path.expanduser('~/.local/bin/oiejq'), ignore_errors=True)
- except FileNotFoundError:
- pass
- assert not oiejq.check_oiejq()
- assert oiejq.install_oiejq()
- assert oiejq.get_oiejq_path() == os.path.expanduser('~/.local/bin/oiejq')
-
- # Download older sio2jail
- urlretrieve('https://github.com/sio2project/sio2jail/releases/download/v1.4.3/sio2jail',
- os.path.expanduser('~/.local/bin/sio2jail'))
- os.chmod(os.path.expanduser('~/.local/bin/sio2jail'), 0o777)
- assert not oiejq.check_oiejq()
- assert oiejq.install_oiejq()
- assert oiejq.check_oiejq()
diff --git a/tests/test_sio2jail.py b/tests/test_sio2jail.py
new file mode 100644
index 00000000..da193d17
--- /dev/null
+++ b/tests/test_sio2jail.py
@@ -0,0 +1,104 @@
+import os
+import shutil
+import sys
+from urllib.request import urlretrieve
+import pytest
+
+from sinol_make import sio2jail, util
+
+
+@pytest.mark.github_runner
+def test_install_sio2jail():
+ if sys.platform != 'linux':
+ return
+
+ try:
+ if os.path.exists(os.path.expanduser('~/.local/bin/oiejq')):
+ os.remove(os.path.expanduser('~/.local/bin/oiejq'))
+ if os.path.exists(os.path.expanduser('~/.local/bin/sio2jail')):
+ os.remove(os.path.expanduser('~/.local/bin/sio2jail'))
+ except IsADirectoryError:
+ shutil.rmtree(os.path.expanduser('~/.local/bin/oiejq'), ignore_errors=True)
+ assert not sio2jail.check_sio2jail()
+ assert sio2jail.install_sio2jail()
+ assert sio2jail.get_default_sio2jail_path() == os.path.expanduser('~/.local/bin/sio2jail')
+
+ if os.path.exists(os.path.expanduser('~/.local/bin/oiejq')):
+ os.remove(os.path.expanduser('~/.local/bin/oiejq'))
+ if os.path.exists(os.path.expanduser('~/.local/bin/sio2jail')):
+ os.remove(os.path.expanduser('~/.local/bin/sio2jail'))
+
+ assert not sio2jail.check_sio2jail()
+ sio2jail.install_sio2jail()
+
+
+@pytest.mark.github_runner
+def test_check_sio2jail():
+ if sys.platform != 'linux':
+ return
+
+ try:
+ if os.path.exists(os.path.expanduser('~/.local/bin/oiejq')):
+ os.remove(os.path.expanduser('~/.local/bin/oiejq'))
+ if os.path.exists(os.path.expanduser('~/.local/bin/sio2jail')):
+ os.remove(os.path.expanduser('~/.local/bin/sio2jail'))
+ except IsADirectoryError:
+ shutil.rmtree(os.path.expanduser('~/.local/bin/oiejq'), ignore_errors=True)
+
+ assert not sio2jail.check_sio2jail()
+ os.makedirs(os.path.expanduser('~/.local/bin/oiejq'), exist_ok=True)
+ assert not sio2jail.check_sio2jail()
+ os.rmdir(os.path.expanduser('~/.local/bin/oiejq'))
+ with open(os.path.expanduser('~/.local/bin/oiejq'), 'w') as f:
+ f.write('abcdef')
+ assert not sio2jail.check_sio2jail()
+
+
+@pytest.mark.github_runner
+def test_perf_counters_not_set():
+ """
+ Test `sio2jail.check_perf_counters_enabled` with perf counters disabled
+ """
+ if sys.platform != 'linux':
+ return
+
+ sio2jail.install_sio2jail()
+ with pytest.raises(SystemExit):
+ sio2jail.check_perf_counters_enabled()
+
+
+@pytest.mark.sio2jail
+def test_perf_counters_set():
+ """
+ Test `sio2jail.check_perf_counters_enabled` with perf counters enabled
+ """
+ if not util.is_linux():
+ return
+ sio2jail.check_perf_counters_enabled()
+
+
+@pytest.mark.github_runner
+def test_updating():
+ """
+ Test updating sio2jail
+ """
+ if sys.platform != 'linux':
+ return
+ try:
+ os.remove(os.path.expanduser('~/.local/bin/oiejq'))
+ os.remove(os.path.expanduser('~/.local/bin/sio2jail'))
+ except IsADirectoryError:
+ shutil.rmtree(os.path.expanduser('~/.local/bin/oiejq'), ignore_errors=True)
+ except FileNotFoundError:
+ pass
+ assert not sio2jail.check_sio2jail()
+ assert sio2jail.install_sio2jail()
+ assert sio2jail.get_default_sio2jail_path() == os.path.expanduser('~/.local/bin/sio2jail')
+
+ # Download older sio2jail
+ urlretrieve('https://github.com/sio2project/sio2jail/releases/download/v1.4.3/sio2jail',
+ os.path.expanduser('~/.local/bin/sio2jail'))
+ os.chmod(os.path.expanduser('~/.local/bin/sio2jail'), 0o777)
+ assert not sio2jail.check_sio2jail()
+ assert sio2jail.install_sio2jail()
+ assert sio2jail.check_sio2jail()