Skip to content

refactor: add shared pubsub test fixtures and wait_for polling helper#1298

Open
yashksaini-coder wants to merge 2 commits intolibp2p:mainfrom
yashksaini-coder:refactor/378-pubsub-test-shared-fixtures
Open

refactor: add shared pubsub test fixtures and wait_for polling helper#1298
yashksaini-coder wants to merge 2 commits intolibp2p:mainfrom
yashksaini-coder:refactor/378-pubsub-test-shared-fixtures

Conversation

@yashksaini-coder
Copy link
Copy Markdown
Contributor

Summary

Introduces shared test infrastructure for the pubsub test suite restructuring (PR 1 of 6 per the plan in #378):

  • tests/utils/pubsub/wait.pywait_for() generic polling helper and wait_for_convergence() multi-node convergence helper, replacing inline definitions
  • tests/core/pubsub/conftest.pyGossipSubHarness dataclass with .pubsubs, .hosts, .routers properties, plus gossipsub_nodes(), connected_gossipsub_nodes(), subscribed_mesh() context managers and a connected_gossipsub_pair fixture
  • tests/core/pubsub/test_dummyaccount_demo.py — migrated to import wait_for_convergence from the shared module; removed 9 redundant @pytest.mark.trio decorators (covered by trio_mode = true in 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

  • All 9 tests in test_dummyaccount_demo.py pass
  • All 395 pubsub tests collect successfully with the new conftest.py
  • CI passes

Closes #378

cc @IronJam11 @seetadev

Copilot AI review requested due to automatic review settings April 3, 2026 07:46
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.py with reusable polling (wait_for) and multi-node convergence (wait_for_convergence) helpers.
  • Add tests/core/pubsub/conftest.py with a GossipSubHarness wrapper plus context managers/fixtures for creating connected/subscribed gossipsub nodes.
  • Refactor test_dummyaccount_demo.py to reuse the shared convergence helper and rely on global trio_mode = true instead 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.

Comment on lines +32 to +39
_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:
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +64 to +66
async with gossipsub_nodes(n, **kwargs) as harness:
await dense_connect(harness.hosts)
await trio.sleep(0.1)
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

connected_gossipsub_nodes() uses a fixed trio.sleep(0.1) after dense_connect(). This makes the fixture timing-dependent and can still be flaky (or unnecessarily slow) since pubsub peer registration is asynchronous; the codebase already has event-based helpers like Pubsub.wait_for_peer() intended to replace arbitrary sleeps. Suggest replacing the fixed sleep with a deterministic wait (e.g., wait until each pubsub observes at least one peer when n > 1, or otherwise expose a configurable settle/wait strategy) so the fixture actually guarantees “connected” semantics.

Suggested change
async with gossipsub_nodes(n, **kwargs) as harness:
await dense_connect(harness.hosts)
await trio.sleep(0.1)
peer_wait_timeout = kwargs.pop("peer_wait_timeout", 5.0)
async with gossipsub_nodes(n, **kwargs) as harness:
await dense_connect(harness.hosts)
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())

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Revisit high-level structure of pubsub tests after move to trio

2 participants