Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b591be4868 | ||
|
|
b6c195a56c | ||
|
|
6abcdfc22e | ||
|
|
58fd7ccc05 | ||
|
|
ba526fad5a | ||
|
|
efe674b265 | ||
|
|
5d692a7d63 | ||
|
|
5e795d88e7 | ||
|
|
2329d3454f |
@@ -39,7 +39,7 @@ repos:
|
|||||||
language: python
|
language: python
|
||||||
additional_dependencies: [pygments, restructuredtext_lint]
|
additional_dependencies: [pygments, restructuredtext_lint]
|
||||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
rev: v0.991
|
rev: v1.0.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: mypy
|
- id: mypy
|
||||||
files: ^(src/|testing/)
|
files: ^(src/|testing/)
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
pytest-xdist 3.2.1 (2023-03-12)
|
||||||
|
===============================
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
- `#884 <https://github.com/pytest-dev/pytest-xdist/issues/884>`_: Fixed hang in ``worksteal`` scheduler.
|
||||||
|
|
||||||
|
|
||||||
pytest-xdist 3.2.0 (2023-02-07)
|
pytest-xdist 3.2.0 (2023-02-07)
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
|
|||||||
@@ -221,7 +221,6 @@ Example:
|
|||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
worker_id = os.environ.get("PYTEST_XDIST_WORKER")
|
worker_id = os.environ.get("PYTEST_XDIST_WORKER")
|
||||||
if worker_id is not None:
|
if worker_id is not None:
|
||||||
log_file = config.getini("worker_log_file")
|
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
format=config.getini("log_file_format"),
|
format=config.getini("log_file_format"),
|
||||||
filename=f"tests_{worker_id}.log",
|
filename=f"tests_{worker_id}.log",
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ def worker_title(title):
|
|||||||
|
|
||||||
class WorkerInteractor:
|
class WorkerInteractor:
|
||||||
SHUTDOWN_MARK = object()
|
SHUTDOWN_MARK = object()
|
||||||
|
QUEUE_REPLACED_MARK = object()
|
||||||
|
|
||||||
def __init__(self, config, channel):
|
def __init__(self, config, channel):
|
||||||
self.config = config
|
self.config = config
|
||||||
@@ -72,6 +73,15 @@ class WorkerInteractor:
|
|||||||
def _make_queue(self):
|
def _make_queue(self):
|
||||||
return self.channel.gateway.execmodel.queue.Queue()
|
return self.channel.gateway.execmodel.queue.Queue()
|
||||||
|
|
||||||
|
def _get_next_item_index(self):
|
||||||
|
"""Gets the next item from test queue. Handles the case when the queue
|
||||||
|
is replaced concurrently in another thread.
|
||||||
|
"""
|
||||||
|
result = self.torun.get()
|
||||||
|
while result is self.QUEUE_REPLACED_MARK:
|
||||||
|
result = self.torun.get()
|
||||||
|
return result
|
||||||
|
|
||||||
def sendevent(self, name, **kwargs):
|
def sendevent(self, name, **kwargs):
|
||||||
self.log("sending", name, kwargs)
|
self.log("sending", name, kwargs)
|
||||||
self.channel.send((name, kwargs))
|
self.channel.send((name, kwargs))
|
||||||
@@ -136,19 +146,22 @@ class WorkerInteractor:
|
|||||||
self.torun.put(i)
|
self.torun.put(i)
|
||||||
|
|
||||||
self.sendevent("unscheduled", indices=stolen)
|
self.sendevent("unscheduled", indices=stolen)
|
||||||
|
old_queue.put(self.QUEUE_REPLACED_MARK)
|
||||||
|
|
||||||
@pytest.hookimpl
|
@pytest.hookimpl
|
||||||
def pytest_runtestloop(self, session):
|
def pytest_runtestloop(self, session):
|
||||||
self.log("entering main loop")
|
self.log("entering main loop")
|
||||||
self.channel.setcallback(self.handle_command, endmarker=self.SHUTDOWN_MARK)
|
self.channel.setcallback(self.handle_command, endmarker=self.SHUTDOWN_MARK)
|
||||||
self.nextitem_index = self.torun.get()
|
self.nextitem_index = self._get_next_item_index()
|
||||||
while self.nextitem_index is not self.SHUTDOWN_MARK:
|
while self.nextitem_index is not self.SHUTDOWN_MARK:
|
||||||
self.run_one_test()
|
self.run_one_test()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def run_one_test(self):
|
def run_one_test(self):
|
||||||
|
self.item_index = self.nextitem_index
|
||||||
|
self.nextitem_index = self._get_next_item_index()
|
||||||
|
|
||||||
items = self.session.items
|
items = self.session.items
|
||||||
self.item_index, self.nextitem_index = self.nextitem_index, self.torun.get()
|
|
||||||
item = items[self.item_index]
|
item = items[self.item_index]
|
||||||
if self.nextitem_index is self.SHUTDOWN_MARK:
|
if self.nextitem_index is self.SHUTDOWN_MARK:
|
||||||
nextitem = None
|
nextitem = None
|
||||||
|
|||||||
@@ -271,6 +271,40 @@ class TestWorkerInteractor:
|
|||||||
ev = worker.popevent("workerfinished")
|
ev = worker.popevent("workerfinished")
|
||||||
assert "workeroutput" in ev.kwargs
|
assert "workeroutput" in ev.kwargs
|
||||||
|
|
||||||
|
def test_steal_empty_queue(self, worker: WorkerSetup, unserialize_report) -> None:
|
||||||
|
worker.pytester.makepyfile(
|
||||||
|
"""
|
||||||
|
def test_func(): pass
|
||||||
|
def test_func2(): pass
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
worker.setup()
|
||||||
|
ev = worker.popevent("collectionfinish")
|
||||||
|
ids = ev.kwargs["ids"]
|
||||||
|
assert len(ids) == 2
|
||||||
|
worker.sendcommand("runtests_all")
|
||||||
|
|
||||||
|
for when in ["setup", "call", "teardown"]:
|
||||||
|
ev = worker.popevent("testreport")
|
||||||
|
rep = unserialize_report(ev.kwargs["data"])
|
||||||
|
assert rep.nodeid.endswith("::test_func")
|
||||||
|
assert rep.when == when
|
||||||
|
|
||||||
|
worker.sendcommand("steal", indices=[0, 1])
|
||||||
|
ev = worker.popevent("unscheduled")
|
||||||
|
assert ev.kwargs["indices"] == []
|
||||||
|
|
||||||
|
worker.sendcommand("shutdown")
|
||||||
|
|
||||||
|
for when in ["setup", "call", "teardown"]:
|
||||||
|
ev = worker.popevent("testreport")
|
||||||
|
rep = unserialize_report(ev.kwargs["data"])
|
||||||
|
assert rep.nodeid.endswith("::test_func2")
|
||||||
|
assert rep.when == when
|
||||||
|
|
||||||
|
ev = worker.popevent("workerfinished")
|
||||||
|
assert "workeroutput" in ev.kwargs
|
||||||
|
|
||||||
|
|
||||||
def test_remote_env_vars(pytester: pytest.Pytester) -> None:
|
def test_remote_env_vars(pytester: pytest.Pytester) -> None:
|
||||||
pytester.makepyfile(
|
pytester.makepyfile(
|
||||||
|
|||||||
Reference in New Issue
Block a user