Piotr Batko (f1692db6) at 02 Dec 13:07
Piotr Batko (d7d94034) at 08 Nov 21:52
Piotr Batko (a67c6834) at 08 Nov 21:19
Piotr Batko (9e3bf590) at 08 Nov 20:37
Piotr Batko (272a176f) at 03 Nov 10:59
Piotr Batko (7d24897c) at 03 Nov 10:55
Piotr Batko (b92b7ea3) at 03 Nov 08:44
Piotr Batko (61573799) at 31 Oct 17:20
Actually there is:
raise KeyError("Wrong config entry name")
But when user see this error, it's hard to figure out which key were passed (example here: https://gitlab.syncad.com/hive/hive/-/jobs/297134).
Something like this would be much easier to work with:
raise KeyError(f'Invalid config entry name "{key_to_check}".')
Consider also provide additional context. This function is used only in following call chain:
Node.dump_config
,NodeConfig.load_from_file
,NodeConfig.load_from_lines
,NodeConfig.__check_if_key_from_file_is_valid
.Exception can be catched on Node.dump_config
level and provide description such as Node dumped config with entry not known to TestTools
and this description can be followed by above Invalid config entry name "some_invalid_name"
. It can be achieved by raise Exception() from previous_exception
.
Such use case should work:
import test_tools as tt
node = tt.RemoteNode("api.hive.blog")
node.api.database.list_witnesses(start=None, limit=100, order='by_name')
but it causes following error:
Traceback (most recent call last):
File "/home/dev/workspace/hive/tests/venv/lib/python3.8/site-packages/requests/models.py", line 384, in prepare_url
scheme, auth, host, port, path, query, fragment = parse_url(url)
File "/home/dev/workspace/hive/tests/venv/lib/python3.8/site-packages/urllib3/util/url.py", line 397, in parse_url
return six.raise_from(LocationParseError(source_url), None)
File "<string>", line 3, in raise_from
urllib3.exceptions.LocationParseError: Failed to parse: http://api.hive.blog:None
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.8/code.py", line 90, in runcode
exec(code, self.locals)
File "<input>", line 1, in <module>
File "/home/dev/workspace/hive/tests/test_tools/package/test_tools/node_api/api_base.py", line 17, in __call__
response = self.__node.send(
File "/home/dev/workspace/hive/tests/test_tools/package/test_tools/__private/remote_node.py", line 31, in send
response = communication.request(
File "/home/dev/workspace/hive/tests/test_tools/package/test_tools/__private/communication.py", line 43, in __implementation
return send_request(*args, **kwargs)
File "/home/dev/workspace/hive/tests/test_tools/package/test_tools/__private/communication.py", line 69, in request
response = requests.post(url, data=message)
File "/home/dev/workspace/hive/tests/venv/lib/python3.8/site-packages/requests/api.py", line 117, in post
return request('post', url, data=data, json=json, **kwargs)
File "/home/dev/workspace/hive/tests/venv/lib/python3.8/site-packages/requests/api.py", line 61, in request
return session.request(method=method, url=url, **kwargs)
File "/home/dev/workspace/hive/tests/venv/lib/python3.8/site-packages/requests/sessions.py", line 515, in request
prep = self.prepare_request(req)
File "/home/dev/workspace/hive/tests/venv/lib/python3.8/site-packages/requests/sessions.py", line 443, in prepare_request
p.prepare(
File "/home/dev/workspace/hive/tests/venv/lib/python3.8/site-packages/requests/models.py", line 318, in prepare
self.prepare_url(url, params)
File "/home/dev/workspace/hive/tests/venv/lib/python3.8/site-packages/requests/models.py", line 386, in prepare_url
raise InvalidURL(*e.args)
requests.exceptions.InvalidURL: Failed to parse: http://api.hive.blog:None
Problem is of course because of included None
to given URL: http://api.hive.blog:None
.
In jobs:
PYTHONPATH
. There are no explanation in comment, so we don't know if it was done by accident or because of some real purpose.In both of these job definitions are following code:
both_of_above_jobs:
variables:
PYTHONPATH: $CI_PROJECT_DIR/tests/test_tools/package
live_sync_tests
are tox based, so there should be added proper TestTools instalation (see TestTools home page for details).patterns_tests
uses requirements.txt
($CI_PROJECT_DIR/tests/api_tests/comparsion_tests/requirements.txt
). So there should be added proper TestTools instalation.If I understand correctly, this code has no effect and can be removed.
From this fixture in hive/tests/functional/python_tests/direct_rc_delegations_tests/conftest.py
:
@pytest.fixture
def node(request):
init_node = tt.InitNode()
# The actual HF time does not matter as long as it's in the past
shared_file_size = request.node.get_closest_marker('node_shared_file_size')
if shared_file_size:
init_node.config.shared_file_size = shared_file_size.args[0]
init_node.run(environment_variables={"HIVE_HF26_TIME": "1598558400"})
return init_node
Should be removed:
HIVE_HF26_TIME=1598558400
environment variable.If I am right (please @bwrona or @ABW) check it, you know how HIVE_HF26_TIME
works, this code would look like:
@pytest.fixture
def node(request):
init_node = tt.InitNode()
shared_file_size = request.node.get_closest_marker('node_shared_file_size')
if shared_file_size:
init_node.config.shared_file_size = shared_file_size.args[0]
init_node.run()
return init_node
Then please show it to @kudmich, because it is possible, that his universal-node
(as he names it) do everything what is needed here, and this fixture might be completely removed.
When I was implementing TestTools' scopes mechanism (test_tools/package/test_tools/__private/scope/
), I assummed, that pytest's package fixture works in that way, that it runs my callback always, when entering every package leading to running test. So for example, when I have tests with structure:
π tests_package
ββ π first_package
| ββ π __init__.py
| ββ π test_first_file.py
| ββ π’ test_alpha
| ββ π’ test_beta
ββ π second_package
| ββ π __init__.py
| ββ π test_second_file.py
| ββ π’ test_gamma
ββ π __init__.py
Following actions should be taken when running them:
β root scope
(special predefined singleton scope, which includes all other scopes),π tests_package
package scope,π first_package
package scope,π test_first_file.py
module scope,π’ test_alpha
function scope,π’ test_alpha
,π’ test_alpha
function scope,π’ test_beta
function scope,π’ test_beta
,π’ test_beta
function scope,π test_first_file.py
module scope,π first_package
package scope,π second_package
package scope,π test_second_file.py
module scope,π’ test_gamma
function scope,π’ test_gamma
,π’ test_gamma
function scope,π test_second_file.py
module scope,π second_package
package scope,π tests_package
package scope,β root scope
.It turned out, that package scopes are not created in that way. I based my implementation on @pytest.fixture(autouse=True, scope="package")
(function package_scope
in test_tools/package/test_tools/__private/scope/scope_fixtures_definitions.py
), but it is autoused only once (not for every package, as I mistakenly expected).
Above problem can be fully solved by module_scope
autouse fixture, (which is run as expected for every module). See order of actions below:
β root scope
[pytest]
wants to run π’ test_alpha
, so has to run all preparations:
[pytest]
runs autouse module_scope
fixture,module_scope
fixture figures out, that current scope is β root scope
, but we are in π test_first_file.py
module scope, so few scopes have to be entered, so it performs:
π tests_package
package scope,π first_package
package scope,π test_first_file.py
module scope,π test_first_file.py
module scope),[pytest]
runs autouse function_scope
fixture,function_scope
fixture enters π’ test_alpha
function scope,[pytest]
executes π’ test_alpha
,[pytest]
runs cleanup (code after yield
in fixture) of autouse function_scope
fixture,function_scope
fixture exits π’ test_alpha
function scope,[pytest]
wants to run π’ test_beta
, so has to run all preparations:
module_scope
fixture was already run earlier, and correctly we are still in π test_first_file.py
module scope),[pytest]
runs autouse function_scope
fixture,function_scope
fixture enters π’ test_beta
function scope,[pytest]
executes π’ test_beta
,[pytest]
runs cleanup of autouse function_scope
fixture,function_scope
fixture exits π’ test_beta
function scope,[pytest]
runs cleanup of autouse module_scope
fixture,module_scope
fixture exits π test_first_file.py
module scope,[pytest]
wants to run π’ test_gamma
, so has to run all preparations:
[pytest]
runs autouse module_scope
fixture,module_scope
fixture figures out, that current scope is π first_package
(left after previous tests), but we are in π test_second_file.py
module scope, so few scopes have to be exited and entered, so it performs:
π first_package
package scope,π second_package
package scope,π test_second_file.py
module scope,π test_second_file.py
module scope),[pytest]
runs autouse function_scope
fixture,function_scope
fixture enters π’ test_gamma
function scope,[pytest]
executes π’ test_gamma
,[pytest]
runs cleanup of autouse function_scope
fixture,function_scope
fixture exits π’ test_gamma
function scope,[pytest]
runs cleanup of autouse module_scope
fixture,module_scope
fixture exits π test_second_file.py
module scope.π second_package
and π tests_package
package scopes and from β root scope
. Maybe it is already handled correctly by atexit
in ScopesStack.__init__
in test_tools/package/test_tools/__private/scope/scopes_stack.py
. But you have to ensure that, with trace logs.But above solution have following problems:
β root scope
(special predefined singleton scope, which includes all other scopes),π tests_package
package scope,π΄ tests_package_fixture
defined in tests_package/conftest.py
,π first_package
package scope,π΄ first_package_fixture
defined in tests_package/first_package/conftest.py
,π test_first_file.py
module scope,π’ test_alpha
function scope, pytest.fixture
to wrap tester's defined package fixtures with our code handling scopes. It has to be figured out.module_scope
fixture figures out, that current scope is (...)". It was easy to write for me above, but to solve this issue, algorithm which tells how to "figure it out" has to be written.We noticed with @mzebrak, that package scope fixtures defined by users are used really rarely (only once, for block_log_helper
in hive/tests/functional/python_tests/hived/conftest.py
, we checked Hived and HAF repositories). So some dirty and/or temporary solution/workaround for this problem might be to prohibit usage of package fixtures and somehow rewrite this single case.
I spent about 2 hours to write this issue and I think it is a great documentation of how TestTools' scopes system works. Please don't throw it to trash when issue will be closed, but move it to test_tools/package/test_tools/__private/scope/documentation.md
, which is not written in so precise and nice way.
I assigned Priority::High
, because it blocks (or at least makes harder) implementation of TestTools' config in #6.
It would allow to rewrite Node.wait_for_block_with_number
and Node.wait_number_of_blocks
based on threading.Event
set on notification about produced block. Current implementation polls (checks in loop) block number with database API get_dynamic_global_properties
method and wait 1s if it's still not requested block. With notification waiting can be a shorter, because with 1s delay, in the worst scenario you have to wait 1s after requested block was produced. It is different with notifications, because they are send immediately and immediately can interrupt waiting.
Above speed up is important in following case. When I run node speed up few times with libfaketime, current implementation caused problems, because was sleep too long. During 1s sleep too many blocks were produced. With notification will be received immediately, so even with speed up node, waiting should be precisely enough.
It would allow to wait until requested block became irreversible. I am not sure if this is needed, but surely below case is.
Common case in tests are waiting, until block containing last operation will become irreversible. Currently testers write something like below:
node.wait_number_of_blocks(21) # Waiting until above transactions become irreversible
It would be nice to be able to write something simple like:
node.wait_until_current_block_become_irreversible()
When it will be fixed, workaround ensure_that_key_generator_executable_is_missing
from test_tools/tests/unit_tests/key_generation_tests/local_tools.py
can be replaced with:
@pytest.fixture(autouse=True)
def ensure_that_key_generator_executable_is_missing():
tt.paths_to_executables.set_path_of("get_dev_key", None)
Paths to executables are currently a global singleton, (see test_tools/package/test_tools/__private/paths_to_executables.py
):
__paths = _PathsToExecutables()
When one tests changes it, the change affects all following tests.
Changes to paths should be limited to scope, in which were introduced.
Piotr Batko (f7e22230) at 31 Oct 12:14
Piotr Batko (f7e22230) at 31 Oct 12:14
Piotr Batko (360dea68) at 31 Oct 12:09
Piotr Batko (360dea68) at 31 Oct 12:09
Add set allowed peers