refactor: add shared pubsub test fixtures and wait_for polling helper#1298
refactor: add shared pubsub test fixtures and wait_for polling helper#1298yashksaini-coder wants to merge 10 commits intolibp2p:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds shared pubsub test infrastructure to support the upcoming pubsub test suite refactor (per #378), centralizing synchronization helpers and common gossipsub fixtures/context managers.
Changes:
- Introduce
tests/utils/pubsub/wait.pywith reusable polling (wait_for) and multi-node convergence (wait_for_convergence) helpers. - Add
tests/core/pubsub/conftest.pywith aGossipSubHarnesswrapper plus context managers/fixtures for creating connected/subscribed gossipsub nodes. - Refactor
test_dummyaccount_demo.pyto reuse the shared convergence helper and rely on globaltrio_mode = trueinstead of per-test@pytest.mark.trio.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| tests/utils/pubsub/wait.py | New shared polling/convergence utilities for pubsub test synchronization. |
| tests/core/pubsub/conftest.py | New shared harness + context managers/fixtures for creating connected/subscribed GossipSub test topologies. |
| tests/core/pubsub/test_dummyaccount_demo.py | Swaps inline convergence helper for shared import; removes redundant trio markers. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| _is_async = inspect.iscoroutinefunction(predicate) | ||
| start = trio.current_time() | ||
| last_exc: Exception | None = None | ||
|
|
||
| while True: | ||
| try: | ||
| result = (await predicate()) if _is_async else predicate() # type: ignore[misc] | ||
| if result: |
There was a problem hiding this comment.
wait_for() determines async-ness via inspect.iscoroutinefunction(predicate), which misses common patterns like lambda: async_fn() or functools.partial(async_fn, ...). In those cases predicate() returns a coroutine object (truthy) and the helper will return immediately without awaiting it, potentially causing false positives and "coroutine was never awaited" warnings. Consider calling predicate() each loop and then await if the returned value is awaitable (e.g., inspect.isawaitable(result)), and update the type hint accordingly to avoid the type: ignore.
There was a problem hiding this comment.
@copilot apply changes based on this feedback
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
Hello @yashksaini-coder Thanks for this PR. AI PR Review: #1298PR: refactor: add shared pubsub test fixtures and wait_for polling helper 1. Summary of ChangesThis PR introduces shared test infrastructure for the ongoing pubsub test-suite refactor tracked under #378 (meta-issue describing duplicated setup, ~253 sync sleeps, mixed router-extraction patterns, redundant What changed:
Architecture: Changes are confined to tests under pubsub ( Breaking changes: None. Issue linkage: PR body says Closes #378. Issue #378 is the umbrella “revisit pubsub tests” item; the PR description positions this as “PR 1 of 6”, so closing the issue on merge may be premature (see §4 and §10). 2. Branch Sync Status and Merge ConflictsBranch sync status
Merge conflict analysis
3. Strengths
4. Issues FoundCriticalNone identified in the reviewed diff; full test suite passed locally. Major
_is_async = inspect.iscoroutinefunction(predicate)
start = trio.current_time()
last_exc: Exception | None = None
while True:
try:
result = (await predicate()) if _is_async else predicate() # type: ignore[misc]
if result:
return
Minor
5. Security Review
6. Documentation and Examples
7. Newsfragment RequirementStatus: The PR diff contains no
Blocker (process):
8. Tests and ValidationLogs under
Notes:
9. Recommendations for Improvement
10. Questions for the Author
11. Overall Assessment
|
- wait_for(): use inspect.isawaitable(result) instead of inspect.iscoroutinefunction(predicate) so lambdas returning coroutines are properly awaited (prevents false positives and "coroutine was never awaited" warnings) - subscribed_mesh: add TODO(libp2p#378) on settle_time sleep - add newsfragments/378.internal.rst for towncrier
Findings (ordered by severity)
|
|
Other than that, keeping luca's concerns in mind (as in the review above), it looks well drafted and well coded. well done @yashksaini-coder |
|
Thanks @acul71 for the thorough review and @IronJam11 for the follow-up — all feedback has been addressed:
All changes are in commit 77dbab8. Could you give this a final look when you get a chance? Happy to address anything else before merge. |
|
Hi @yashksaini-coder thanks, all changes looks good. This can be merged @seetadev .
Full review here: AI PR Review: #1298PR: refactor: add shared pubsub test fixtures and wait_for polling helper 1. Summary of ChangesThis PR introduces shared pubsub test infrastructure for issue #378, focused on improving maintainability and reducing flaky synchronization patterns in tests.
The changes are test-focused ( 2. Branch Sync Status and Merge ConflictsBranch Sync Status
Merge Conflict Analysis
✅ No merge conflicts detected. The PR branch can be merged cleanly into 3. Strengths
4. Issues FoundCriticalNone. MajorNone. Minor
if n > 1:
with trio.fail_after(peer_wait_timeout):
for index, pubsub in enumerate(harness.pubsubs):
target_host = harness.hosts[(index + 1) % n]
await pubsub.wait_for_peer(target_host.get_id())5. Security Review
6. Documentation and Examples
7. Newsfragment Requirement
No blocker found in this section. 8. Tests and ValidationArtifacts reviewed from
No validation blockers were observed. 9. Recommendations for Improvement
10. Questions for the Author
11. Overall Assessment
|
Default behaviour is unchanged: each node waits for exactly one expected neighbour after dense_connect, which keeps the fixture fast for the common case. Pass strict=True to wait until every node has observed every other expected peer, for topology-sensitive tests that assert exact peer counts or full fanout. Addresses acul71's minor improvement on PR libp2p#1298.
|
Thanks @acul71 for the review. On the minor improvementWent with option (a) — kept the default lightweight and added an opt-in async with connected_gossipsub_nodes(4, strict=True) as harness:
# every node has observed every other expected peer before we yieldWhen Answering your questions
Yes — went with a keyword-only
Yes — #1307 is the canonical tracker for that item. The Validation
Happy to squash/rebase before @seetadev merges. |
Summary
Introduces shared test infrastructure for the pubsub test suite restructuring (PR 1 of 6 per the plan in #378):
tests/utils/pubsub/wait.py—wait_for()generic polling helper andwait_for_convergence()multi-node convergence helper, replacing inline definitionstests/core/pubsub/conftest.py—GossipSubHarnessdataclass with.pubsubs,.hosts,.routersproperties, plusgossipsub_nodes(),connected_gossipsub_nodes(),subscribed_mesh()context managers and aconnected_gossipsub_pairfixturetests/core/pubsub/test_dummyaccount_demo.py— migrated to importwait_for_convergencefrom the shared module; removed 9 redundant@pytest.mark.triodecorators (covered bytrio_mode = truein pyproject.toml)This lays the foundation for subsequent PRs that will replace ~253 synchronization sleeps, standardize router extraction, flatten class-based tests, consolidate overlapping files, and tag slow tests.
Test plan
test_dummyaccount_demo.pypassconftest.pyRefs #378
cc @IronJam11 @seetadev