aboutsummaryrefslogtreecommitdiffstats
path: root/library/python/testing
diff options
context:
space:
mode:
authorprettyboy <prettyboy@yandex-team.com>2022-09-25 13:06:29 +0300
committerprettyboy <prettyboy@yandex-team.com>2022-09-25 13:06:29 +0300
commita56f9bf1dd89a3bf9b12b3075311c0c93e84fbb2 (patch)
tree1471279703beb18e586d8aad8d1fabe5ded1182b /library/python/testing
parente14c5ad0a3b4044dab6d6c9aad1d5d76360494a7 (diff)
downloadydb-a56f9bf1dd89a3bf9b12b3075311c0c93e84fbb2.tar.gz
[library/python/testing/yatest_common] Relaxed runtime methods for non-standalone runs
Diffstat (limited to 'library/python/testing')
-rw-r--r--library/python/testing/yatest_common/yatest/common/__init__.py1
-rw-r--r--library/python/testing/yatest_common/yatest/common/canonical.py72
-rw-r--r--library/python/testing/yatest_common/yatest/common/errors.py2
-rw-r--r--library/python/testing/yatest_common/yatest/common/legacy.py12
-rw-r--r--library/python/testing/yatest_common/yatest/common/network.py11
-rw-r--r--library/python/testing/yatest_common/yatest/common/process.py181
-rw-r--r--library/python/testing/yatest_common/yatest/common/runtime.py94
-rw-r--r--library/python/testing/yatest_common/yatest/common/tags.py5
8 files changed, 284 insertions, 94 deletions
diff --git a/library/python/testing/yatest_common/yatest/common/__init__.py b/library/python/testing/yatest_common/yatest/common/__init__.py
index cf57779e27e..e450e64a71e 100644
--- a/library/python/testing/yatest_common/yatest/common/__init__.py
+++ b/library/python/testing/yatest_common/yatest/common/__init__.py
@@ -5,4 +5,3 @@ from .misc import * # noqa
from .path import * # noqa
from .process import * # noqa
from .runtime import * # noqa
-from .tags import * # noqa
diff --git a/library/python/testing/yatest_common/yatest/common/canonical.py b/library/python/testing/yatest_common/yatest/common/canonical.py
index b6a136d3e9b..8688c56a65e 100644
--- a/library/python/testing/yatest_common/yatest/common/canonical.py
+++ b/library/python/testing/yatest_common/yatest/common/canonical.py
@@ -21,7 +21,10 @@ def _copy(src, dst, universal_lines=False):
shutil.copy(src, dst)
-def canonical_file(path, diff_tool=None, local=False, universal_lines=False, diff_file_name=None, diff_tool_timeout=None):
+@runtime.default_arg0
+def canonical_file(
+ path, diff_tool=None, local=False, universal_lines=False, diff_file_name=None, diff_tool_timeout=None
+):
"""
Create canonical file that can be returned from a test
:param path: path to the file
@@ -44,9 +47,12 @@ def canonical_file(path, diff_tool=None, local=False, universal_lines=False, dif
raise Exception("Invalid custom diff-tool: not cmd")
except:
raise Exception("Invalid custom diff-tool: not binary path")
- return runtime._get_ya_plugin_instance().file(safe_path, diff_tool=diff_tool, local=local, diff_file_name=diff_file_name, diff_tool_timeout=diff_tool_timeout)
+ return runtime._get_ya_plugin_instance().file(
+ safe_path, diff_tool=diff_tool, local=local, diff_file_name=diff_file_name, diff_tool_timeout=diff_tool_timeout
+ )
+@runtime.default_arg0
def canonical_dir(path, diff_tool=None, diff_file_name=None, diff_tool_timeout=None):
abs_path = os.path.abspath(path)
assert os.path.exists(abs_path), "Canonical path {} does not exist".format(path)
@@ -56,15 +62,28 @@ def canonical_dir(path, diff_tool=None, diff_file_name=None, diff_tool_timeout=N
tempdir = tempfile.mkdtemp()
safe_path = os.path.join(tempdir, os.path.basename(abs_path))
shutil.copytree(abs_path, safe_path)
- return runtime._get_ya_plugin_instance().file(safe_path, diff_tool=diff_tool, diff_file_name=diff_file_name, diff_tool_timeout=diff_tool_timeout)
+ return runtime._get_ya_plugin_instance().file(
+ safe_path, diff_tool=diff_tool, diff_file_name=diff_file_name, diff_tool_timeout=diff_tool_timeout
+ )
def canonical_execute(
- binary, args=None, check_exit_code=True,
- shell=False, timeout=None, cwd=None,
- env=None, stdin=None, stderr=None, creationflags=0,
- file_name=None, save_locally=False, close_fds=False,
- diff_tool=None, diff_file_name=None, diff_tool_timeout=None,
+ binary,
+ args=None,
+ check_exit_code=True,
+ shell=False,
+ timeout=None,
+ cwd=None,
+ env=None,
+ stdin=None,
+ stderr=None,
+ creationflags=0,
+ file_name=None,
+ save_locally=False,
+ close_fds=False,
+ diff_tool=None,
+ diff_file_name=None,
+ diff_tool_timeout=None,
):
"""
Shortcut to execute a binary and canonize its stdout
@@ -101,15 +120,28 @@ def canonical_execute(
del execute_args["diff_tool_timeout"]
if not file_name and stdin:
file_name = os.path.basename(stdin.name)
- return _canonical_execute(process.execute, execute_args, file_name, save_locally, diff_tool, diff_file_name, diff_tool_timeout)
+ return _canonical_execute(
+ process.execute, execute_args, file_name, save_locally, diff_tool, diff_file_name, diff_tool_timeout
+ )
def canonical_py_execute(
- script_path, args=None, check_exit_code=True,
- shell=False, timeout=None, cwd=None, env=None,
- stdin=None, stderr=None, creationflags=0,
- file_name=None, save_locally=False, close_fds=False,
- diff_tool=None, diff_file_name=None, diff_tool_timeout=None,
+ script_path,
+ args=None,
+ check_exit_code=True,
+ shell=False,
+ timeout=None,
+ cwd=None,
+ env=None,
+ stdin=None,
+ stderr=None,
+ creationflags=0,
+ file_name=None,
+ save_locally=False,
+ close_fds=False,
+ diff_tool=None,
+ diff_file_name=None,
+ diff_tool_timeout=None,
):
"""
Shortcut to execute a python script and canonize its stdout
@@ -140,7 +172,9 @@ def canonical_py_execute(
del execute_args["diff_tool"]
del execute_args["diff_file_name"]
del execute_args["diff_tool_timeout"]
- return _canonical_execute(process.py_execute, execute_args, file_name, save_locally, diff_tool, diff_file_name, diff_tool_timeout)
+ return _canonical_execute(
+ process.py_execute, execute_args, file_name, save_locally, diff_tool, diff_file_name, diff_tool_timeout
+ )
def _prepare_args(args):
@@ -173,4 +207,10 @@ def _canonical_execute(excutor, kwargs, file_name, save_locally, diff_tool, diff
with open(err_file_path, "wb") as err_file:
err_file.write(res.std_err)
- return canonical_file(out_file_path, local=save_locally, diff_tool=diff_tool, diff_file_name=diff_file_name, diff_tool_timeout=diff_tool_timeout)
+ return canonical_file(
+ out_file_path,
+ local=save_locally,
+ diff_tool=diff_tool,
+ diff_file_name=diff_file_name,
+ diff_tool_timeout=diff_tool_timeout,
+ )
diff --git a/library/python/testing/yatest_common/yatest/common/errors.py b/library/python/testing/yatest_common/yatest/common/errors.py
index 8c038fc381b..d7c444465b2 100644
--- a/library/python/testing/yatest_common/yatest/common/errors.py
+++ b/library/python/testing/yatest_common/yatest/common/errors.py
@@ -3,7 +3,6 @@ import sys
class RestartTestException(Exception):
-
def __init__(self, *args, **kwargs):
super(RestartTestException, self).__init__(*args, **kwargs)
sys.stderr.write("##restart-test##\n")
@@ -12,7 +11,6 @@ class RestartTestException(Exception):
class InfrastructureException(Exception):
-
def __init__(self, *args, **kwargs):
super(InfrastructureException, self).__init__(*args, **kwargs)
sys.stderr.write("##infrastructure-error##\n")
diff --git a/library/python/testing/yatest_common/yatest/common/legacy.py b/library/python/testing/yatest_common/yatest/common/legacy.py
deleted file mode 100644
index 459972d2532..00000000000
--- a/library/python/testing/yatest_common/yatest/common/legacy.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from . import canonical
-
-
-def old_canonical_file(output_file_name, storage_md5):
- import yalibrary.svn
- yalibrary.svn.run_svn([
- 'export',
- 'svn+ssh://arcadia.yandex.ru/arc/trunk/arcadia_tests_data/tests_canonical_output/' + storage_md5,
- output_file_name,
- "--force"
- ])
- return canonical.canonical_file(output_file_name)
diff --git a/library/python/testing/yatest_common/yatest/common/network.py b/library/python/testing/yatest_common/yatest/common/network.py
index 37bcb1b8e08..395fed58091 100644
--- a/library/python/testing/yatest_common/yatest/common/network.py
+++ b/library/python/testing/yatest_common/yatest/common/network.py
@@ -126,8 +126,11 @@ class PortManager(object):
# Can't find required number of ports without gap in the current range
drop_candidates()
- raise PortManagerException("Failed to find valid port range (start_port: {} count: {}) (range: {} used: {})".format(
- start_port, count, self._valid_range, self._filelocks))
+ raise PortManagerException(
+ "Failed to find valid port range (start_port: {} count: {}) (range: {} used: {})".format(
+ start_port, count, self._valid_range, self._filelocks
+ )
+ )
def _count_valid_ports(self):
res = 0
@@ -157,7 +160,9 @@ class PortManager(object):
continue
return probe_port
- raise PortManagerException("Failed to find valid port (range: {} used: {})".format(self._valid_range, self._filelocks))
+ raise PortManagerException(
+ "Failed to find valid port (range: {} used: {})".format(self._valid_range, self._filelocks)
+ )
def _capture_port(self, port, sock_type):
with self._lock:
diff --git a/library/python/testing/yatest_common/yatest/common/process.py b/library/python/testing/yatest_common/yatest/common/process.py
index c2dec1f7c12..66a1b9d56b4 100644
--- a/library/python/testing/yatest_common/yatest/common/process.py
+++ b/library/python/testing/yatest_common/yatest/common/process.py
@@ -38,7 +38,7 @@ def truncate(s, size):
elif len(s) <= size:
return s
else:
- return (b'...' if isinstance(s, bytes) else '...') + s[-(size - 3):]
+ return (b'...' if isinstance(s, bytes) else '...') + s[-(size - 3) :]
def get_command_name(command):
@@ -46,19 +46,19 @@ def get_command_name(command):
class ExecutionError(Exception):
-
def __init__(self, execution_result):
if not isinstance(execution_result.command, six.string_types):
command = " ".join(str(arg) for arg in execution_result.command)
else:
command = execution_result.command
message = "Command '{command}' has failed with code {code}.\nErrors:\n{err}\n".format(
- command=command,
- code=execution_result.exit_code,
- err=_format_error(execution_result.std_err))
+ command=command, code=execution_result.exit_code, err=_format_error(execution_result.std_err)
+ )
if cores:
if execution_result.backtrace:
- message += "Backtrace:\n[[rst]]{}[[bad]]\n".format(cores.colorize_backtrace(execution_result._backtrace))
+ message += "Backtrace:\n[[rst]]{}[[bad]]\n".format(
+ cores.colorize_backtrace(execution_result._backtrace)
+ )
else:
message += "Backtrace is not available: module cores isn't available"
@@ -91,11 +91,21 @@ class InvalidCommandError(Exception):
class _Execution(object):
-
- def __init__(self, command, process, out_file, err_file,
- process_progress_listener=None, cwd=None, collect_cores=True,
- check_sanitizer=True, started=0, user_stdout=False, user_stderr=False,
- core_pattern=None):
+ def __init__(
+ self,
+ command,
+ process,
+ out_file,
+ err_file,
+ process_progress_listener=None,
+ cwd=None,
+ collect_cores=True,
+ check_sanitizer=True,
+ started=0,
+ user_stdout=False,
+ user_stderr=False,
+ core_pattern=None,
+ ):
self._command = command
self._process = process
@@ -132,7 +142,12 @@ class _Execution(object):
# DEVTOOLS-2347
yatest_logger.debug("Process status before wait_for: %s", self.running)
try:
- wait_for(lambda: not self.running, timeout=5, fail_message="Could not kill process {}".format(self._process.pid), sleep_time=.1)
+ wait_for(
+ lambda: not self.running,
+ timeout=5,
+ fail_message="Could not kill process {}".format(self._process.pid),
+ sleep_time=0.1,
+ )
except TimeoutError:
yatest_logger.debug("Process status after wait_for: %s", self.running)
yatest_logger.debug("Process %d info: %s", self._process.pid, _get_proc_tree_info([self._process.pid]))
@@ -264,16 +279,14 @@ class _Execution(object):
self._out_file = None
def _recover_core(self):
- core_path = cores.recover_core_dump_file(
- self.command[0],
- self._cwd,
- self.process.pid,
- self.core_pattern)
+ core_path = cores.recover_core_dump_file(self.command[0], self._cwd, self.process.pid, self.core_pattern)
if core_path:
# Core dump file recovering may be disabled (for distbuild for example) - produce only bt
store_cores = runtime._get_ya_config().collect_cores
if store_cores:
- new_core_path = path.get_unique_file_path(runtime.output_path(), "{}.{}.core".format(os.path.basename(self.command[0]), self._process.pid))
+ new_core_path = path.get_unique_file_path(
+ runtime.output_path(), "{}.{}.core".format(os.path.basename(self.command[0]), self._process.pid)
+ )
# Copy core dump file, because it may be overwritten
yatest_logger.debug("Coping core dump file from '%s' to the '%s'", core_path, new_core_path)
shutil.copyfile(core_path, new_core_path)
@@ -284,7 +297,10 @@ class _Execution(object):
if os.path.exists(runtime.gdb_path()):
self._backtrace = cores.get_gdb_full_backtrace(self.command[0], core_path, runtime.gdb_path())
- bt_filename = path.get_unique_file_path(runtime.output_path(), "{}.{}.backtrace".format(os.path.basename(self.command[0]), self._process.pid))
+ bt_filename = path.get_unique_file_path(
+ runtime.output_path(),
+ "{}.{}.backtrace".format(os.path.basename(self.command[0]), self._process.pid),
+ )
with open(bt_filename, "wb") as afile:
afile.write(six.ensure_binary(self._backtrace))
# generate pretty html version of backtrace aka Tri Korochki
@@ -292,7 +308,9 @@ class _Execution(object):
backtrace_to_html(bt_filename, pbt_filename)
if store_cores:
- runtime._register_core(os.path.basename(self.command[0]), self.command[0], core_path, bt_filename, pbt_filename)
+ runtime._register_core(
+ os.path.basename(self.command[0]), self.command[0], core_path, bt_filename, pbt_filename
+ )
else:
runtime._register_core(os.path.basename(self.command[0]), None, None, bt_filename, pbt_filename)
@@ -333,7 +351,9 @@ class _Execution(object):
except OSError as exc:
if exc.errno == errno.ECHILD:
- yatest_logger.debug("Process resource usage is not available as process finished before wait4 was called")
+ yatest_logger.debug(
+ "Process resource usage is not available as process finished before wait4 was called"
+ )
else:
raise
except SignalInterruptionError:
@@ -352,7 +372,13 @@ class _Execution(object):
process_is_finished = lambda: not self.running
fail_message = "Command '%s' stopped by %d seconds timeout" % (self._command, timeout)
try:
- wait_for(process_is_finished, timeout, fail_message, sleep_time=0.1, on_check_condition=self._process_progress_listener)
+ wait_for(
+ process_is_finished,
+ timeout,
+ fail_message,
+ sleep_time=0.1,
+ on_check_condition=self._process_progress_listener,
+ )
except TimeoutError as e:
if on_timeout:
yatest_logger.debug("Calling user specified on_timeout function")
@@ -378,8 +404,12 @@ class _Execution(object):
def _finalise(self, check_exit_code):
# Set the signal (negative number) which caused the process to exit
if check_exit_code and self.exit_code != 0:
- yatest_logger.error("Execution failed with exit code: %s\n\t,std_out:%s\n\tstd_err:%s\n",
- self.exit_code, truncate(self.std_out, MAX_OUT_LEN), truncate(self.std_err, MAX_OUT_LEN))
+ yatest_logger.error(
+ "Execution failed with exit code: %s\n\t,std_out:%s\n\tstd_err:%s\n",
+ self.exit_code,
+ truncate(self.std_out, MAX_OUT_LEN),
+ truncate(self.std_err, MAX_OUT_LEN),
+ )
raise ExecutionError(self)
# Don't search for sanitize errors if stderr was redirected
@@ -407,12 +437,18 @@ class _Execution(object):
if self.command[0].startswith(build_path):
match = re.search(SANITIZER_ERROR_PATTERN, self._std_err)
if match:
- yatest_logger.error("%s sanitizer found errors:\n\tstd_err:%s\n", match.group(1), truncate(self.std_err, MAX_OUT_LEN))
+ yatest_logger.error(
+ "%s sanitizer found errors:\n\tstd_err:%s\n",
+ match.group(1),
+ truncate(self.std_err, MAX_OUT_LEN),
+ )
raise ExecutionError(self)
else:
yatest_logger.debug("No sanitizer errors found")
else:
- yatest_logger.debug("'%s' doesn't belong to '%s' - no check for sanitize errors", self.command[0], build_path)
+ yatest_logger.debug(
+ "'%s' doesn't belong to '%s' - no check for sanitize errors", self.command[0], build_path
+ )
def on_timeout_gen_coredump(exec_obj, _):
@@ -429,13 +465,23 @@ def on_timeout_gen_coredump(exec_obj, _):
def execute(
- command, check_exit_code=True,
- shell=False, timeout=None,
- cwd=None, env=None,
- stdin=None, stdout=None, stderr=None,
- creationflags=0, wait=True,
- process_progress_listener=None, close_fds=False,
- collect_cores=True, check_sanitizer=True, preexec_fn=None, on_timeout=None,
+ command,
+ check_exit_code=True,
+ shell=False,
+ timeout=None,
+ cwd=None,
+ env=None,
+ stdin=None,
+ stdout=None,
+ stderr=None,
+ creationflags=0,
+ wait=True,
+ process_progress_listener=None,
+ close_fds=False,
+ collect_cores=True,
+ check_sanitizer=True,
+ preexec_fn=None,
+ on_timeout=None,
executor=_Execution,
core_pattern=None,
popen_kwargs=None,
@@ -527,7 +573,9 @@ def execute(
stat = os.stat(executable)
else:
stat = None
- raise InvalidCommandError("Target program is not a file: {} (exists: {} stat: {})".format(executable, exists, stat))
+ raise InvalidCommandError(
+ "Target program is not a file: {} (exists: {} stat: {})".format(executable, exists, stat)
+ )
if not os.access(executable, os.X_OK) and not os.access(executable + ".exe", os.X_OK):
raise InvalidCommandError("Target program is not executable: {}".format(executable))
@@ -543,9 +591,17 @@ def execute(
started = time.time()
process = subprocess.Popen(
- command, shell=shell, universal_newlines=True,
- stdout=out_file, stderr=err_file, stdin=in_file,
- cwd=cwd, env=env, creationflags=creationflags, close_fds=close_fds, preexec_fn=preexec_fn,
+ command,
+ shell=shell,
+ universal_newlines=True,
+ stdout=out_file,
+ stderr=err_file,
+ stdin=in_file,
+ cwd=cwd,
+ env=env,
+ creationflags=creationflags,
+ close_fds=close_fds,
+ preexec_fn=preexec_fn,
**popen_kwargs
)
yatest_logger.debug("Command pid: %s", process.pid)
@@ -563,8 +619,18 @@ def execute(
if 'core_pattern' in executor_args:
kwargs.update([('core_pattern', core_pattern)])
- res = executor(command, process, out_file, err_file, process_progress_listener,
- cwd, collect_cores, check_sanitizer, started, **kwargs)
+ res = executor(
+ command,
+ process,
+ out_file,
+ err_file,
+ process_progress_listener,
+ cwd,
+ collect_cores,
+ check_sanitizer,
+ started,
+ **kwargs
+ )
if wait:
res.wait(check_exit_code, timeout, on_timeout)
return res
@@ -582,6 +648,7 @@ def _get_command_output_file(cmd, ext):
# if execution is performed from test, save out / err to the test logs dir
import yatest.common
import library.python.pytest.plugins.ya
+
if getattr(library.python.pytest.plugins.ya, 'pytest_config', None) is None:
raise ImportError("not in test")
filename = path.get_unique_file_path(yatest.common.output_path(), filename)
@@ -595,17 +662,26 @@ def _get_proc_tree_info(pids):
if os.name == 'nt':
return 'Not supported'
else:
- stdout, _ = subprocess.Popen(["/bin/ps", "-wufp"] + [str(p) for p in pids], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
+ stdout, _ = subprocess.Popen(
+ ["/bin/ps", "-wufp"] + [str(p) for p in pids], stdout=subprocess.PIPE, stderr=subprocess.PIPE
+ ).communicate()
return stdout
def py_execute(
- command, check_exit_code=True,
- shell=False, timeout=None,
- cwd=None, env=None,
- stdin=None, stdout=None, stderr=None,
- creationflags=0, wait=True,
- process_progress_listener=None, close_fds=False
+ command,
+ check_exit_code=True,
+ shell=False,
+ timeout=None,
+ cwd=None,
+ env=None,
+ stdin=None,
+ stdout=None,
+ stderr=None,
+ creationflags=0,
+ wait=True,
+ process_progress_listener=None,
+ close_fds=False,
):
"""
Executes a command with the arcadia python
@@ -701,7 +777,9 @@ def _nix_kill_process_tree(pid, target_pid_signal=None):
os.kill(pid, sig)
yatest_logger.debug("Sent signal %d to the pid %d", sig, pid)
except Exception as exc:
- yatest_logger.debug("Error while sending signal {sig} to pid {pid}: {error}".format(sig=sig, pid=pid, error=str(exc)))
+ yatest_logger.debug(
+ "Error while sending signal {sig} to pid {pid}: {error}".format(sig=sig, pid=pid, error=str(exc))
+ )
try_to_send_signal(pid, signal.SIGSTOP) # Stop the process to prevent it from starting any child processes.
@@ -729,7 +807,11 @@ def _win_kill_process_tree(pid):
def _run_readelf(binary_path):
- return str(subprocess.check_output([runtime.binary_path('contrib/python/pyelftools/readelf/readelf'), '-s', runtime.binary_path(binary_path)]))
+ return str(
+ subprocess.check_output(
+ [runtime.binary_path('contrib/python/pyelftools/readelf/readelf'), '-s', runtime.binary_path(binary_path)]
+ )
+ )
def check_glibc_version(binary_path):
@@ -745,6 +827,7 @@ def check_glibc_version(binary_path):
def backtrace_to_html(bt_filename, output):
try:
from library.python import coredump_filter
+
with open(output, "w") as afile:
coredump_filter.filter_stackdump(bt_filename, stream=afile)
except ImportError as e:
@@ -754,7 +837,7 @@ def backtrace_to_html(bt_filename, output):
def _try_convert_bytes_to_string(source):
- """ Function is necessary while this code Python2/3 compatible, because bytes in Python3 is a real bytes and in Python2 is not """
+ """Function is necessary while this code Python2/3 compatible, because bytes in Python3 is a real bytes and in Python2 is not"""
# Bit ugly typecheck, because in Python2 isinstance(str(), bytes) and "type(str()) is bytes" working as True as well
if 'bytes' not in str(type(source)):
# We already got not bytes. Nothing to do here.
diff --git a/library/python/testing/yatest_common/yatest/common/runtime.py b/library/python/testing/yatest_common/yatest/common/runtime.py
index b8d5964d1d2..aaae9bb8739 100644
--- a/library/python/testing/yatest_common/yatest/common/runtime.py
+++ b/library/python/testing/yatest_common/yatest/common/runtime.py
@@ -2,6 +2,7 @@ import errno
import functools
import json
import os
+import sys
import threading
import six
@@ -12,14 +13,20 @@ _lock = threading.Lock()
_config = None
+class NoRuntimeFormed(NotImplementedError):
+ pass
+
+
def _set_ya_config(config=None, ya=None):
global _config
if config:
_config = config
elif ya:
+
class Config:
def __init__(self):
self.ya = None
+
_config = Config()
_config.ya = ya
@@ -30,9 +37,10 @@ def _get_ya_config():
else:
try:
import pytest
+
return pytest.config
except (ImportError, AttributeError):
- raise NotImplementedError("yatest.common.* is only available from the testing runtime")
+ raise NoRuntimeFormed("yatest.common.* is only available from the testing runtime")
def _get_ya_plugin_instance():
@@ -48,6 +56,52 @@ def _norm_path(path):
return os.path.normpath(path)
+def _is_binary():
+ return getattr(sys, 'is_standalone_binary', False)
+
+
+def default_arg0(func):
+ return default_arg(func, 0)
+
+
+def default_arg1(func):
+ return default_arg(func, 1)
+
+
+def default_arg(func, narg):
+ # Always try to call func, before checking standaloneness.
+ # The context file might be provided and func might return
+ # result even if it's not a standalone binary run.
+ @functools.wraps(func)
+ def wrapper(*args, **kw):
+ try:
+ return func(*args, **kw)
+ except NoRuntimeFormed:
+ if not _is_binary():
+ if len(args) > narg:
+ return args[narg]
+ return None
+ raise
+
+ return wrapper
+
+
+def default_value(value):
+ def decorator(func):
+ @functools.wraps(func)
+ def wrapper(*args, **kw):
+ try:
+ return func(*args, **kw)
+ except NoRuntimeFormed:
+ if not _is_binary():
+ return value
+ raise
+
+ return wrapper
+
+ return decorator
+
+
def _join_path(main_path, path):
if not path:
return main_path
@@ -60,13 +114,16 @@ def not_test(func):
:param func:
:return:
"""
+
@functools.wraps(func)
def wrapper(*args, **kwds):
return func(*args, **kwds)
+
setattr(wrapper, '__test__', False)
return wrapper
+@default_arg0
def source_path(path=None):
"""
Get source path inside arcadia
@@ -76,6 +133,7 @@ def source_path(path=None):
return _join_path(_get_ya_plugin_instance().source_root, path)
+@default_arg0
def build_path(path=None):
"""
Get path inside build directory
@@ -91,6 +149,7 @@ def java_path():
:return: absolute path to java
"""
from . import runtime_java
+
return runtime_java.get_java_path(binary_path(os.path.join('contrib', 'tools', 'jdk')))
@@ -99,9 +158,12 @@ def java_home():
Get jdk directory path
"""
from . import runtime_java
+
jdk_dir = runtime_java.get_build_java_dir(binary_path('jdk'))
if not jdk_dir:
- raise Exception("Cannot find jdk - make sure 'jdk' is added to the DEPENDS section and exists for the current platform")
+ raise Exception(
+ "Cannot find jdk - make sure 'jdk' is added to the DEPENDS section and exists for the current platform"
+ )
return jdk_dir
@@ -113,6 +175,7 @@ def java_bin():
return os.path.join(java_home(), "bin", "java")
+@default_arg0
def data_path(path=None):
"""
Get path inside arcadia_tests_data directory
@@ -122,6 +185,7 @@ def data_path(path=None):
return _join_path(_get_ya_plugin_instance().data_root, path)
+@default_arg0
def output_path(path=None):
"""
Get path inside the current test suite output dir.
@@ -132,6 +196,7 @@ def output_path(path=None):
return _join_path(_get_ya_plugin_instance().output_dir, path)
+@default_arg0
def ram_drive_path(path=None):
"""
:param path: path relative to the ram drive.
@@ -143,6 +208,7 @@ def ram_drive_path(path=None):
return _join_path(get_param("ram_drive_path"), path)
+@default_arg0
def output_ram_drive_path(path=None):
"""
Returns path inside ram drive directory which will be saved in the testing_out_stuff directory after testing.
@@ -155,6 +221,7 @@ def output_ram_drive_path(path=None):
return _join_path(_get_ya_plugin_instance().get_context("test_output_ram_drive_path"), path)
+@default_arg0
def binary_path(path=None):
"""
Get path to the built binary
@@ -165,6 +232,7 @@ def binary_path(path=None):
return _get_ya_plugin_instance().get_binary(path)
+@default_arg0
def work_path(path=None):
"""
Get path inside the current test suite working directory. Creating files in the work directory does not guarantee
@@ -173,12 +241,11 @@ def work_path(path=None):
:return: absolute path inside the test suite working dir
"""
return _join_path(
- os.environ.get("TEST_WORK_PATH") or
- _get_ya_plugin_instance().get_context("work_path") or
- os.getcwd(),
- path)
+ os.environ.get("TEST_WORK_PATH") or _get_ya_plugin_instance().get_context("work_path") or os.getcwd(), path
+ )
+@default_value("python")
def python_path():
"""
Get path to the arcadia python.
@@ -192,6 +259,7 @@ def python_path():
return _get_ya_plugin_instance().python_path
+@default_value("valgrind")
def valgrind_path():
"""
Get path to valgrind
@@ -200,6 +268,7 @@ def valgrind_path():
return _get_ya_plugin_instance().valgrind_path
+@default_arg1
def get_param(key, default=None):
"""
Get arbitrary parameter passed via command line
@@ -210,6 +279,7 @@ def get_param(key, default=None):
return _get_ya_plugin_instance().get_param(key, default)
+@default_value(lambda _: {})
def get_param_dict_copy():
"""
Return copy of dictionary with all parameters. Changes to this dictionary do *not* change parameters.
@@ -240,10 +310,13 @@ def project_path(path=None):
return _join_path(os.path.join(build_path(), context.project_path), path)
+@default_value("gdb")
def gdb_path():
"""
Get path to the gdb
"""
+ if not _is_binary():
+ return "gdb"
return _get_ya_plugin_instance().gdb_path
@@ -307,34 +380,42 @@ class Context(object):
"""
@property
+ @default_value(None)
def build_type(self):
return _get_ya_plugin_instance().get_context("build_type")
@property
+ @default_value(None)
def project_path(self):
return _get_ya_plugin_instance().get_context("project_path")
@property
+ @default_value(False)
def test_stderr(self):
return _get_ya_plugin_instance().get_context("test_stderr")
@property
+ @default_value(False)
def test_debug(self):
return _get_ya_plugin_instance().get_context("test_debug")
@property
+ @default_value(None)
def test_traceback(self):
return _get_ya_plugin_instance().get_context("test_traceback")
@property
+ @default_value(None)
def test_name(self):
return _get_ya_config().current_test_name
@property
+ @default_value("test_tool")
def test_tool_path(self):
return _get_ya_plugin_instance().get_context("test_tool_path")
@property
+ @default_value(False)
def sanitize(self):
"""
Detect if current test run is under sanitizer
@@ -344,6 +425,7 @@ class Context(object):
return _get_ya_plugin_instance().get_context("sanitize")
@property
+ @default_value(lambda _: {})
def flags(self):
_flags = _get_ya_plugin_instance().get_context("flags")
if _flags:
diff --git a/library/python/testing/yatest_common/yatest/common/tags.py b/library/python/testing/yatest_common/yatest/common/tags.py
deleted file mode 100644
index 9e7a74cdf50..00000000000
--- a/library/python/testing/yatest_common/yatest/common/tags.py
+++ /dev/null
@@ -1,5 +0,0 @@
-try:
- import pytest
- ya_external = getattr(pytest.mark, "ya:external")
-except ImportError:
- ya_external = None