Skip to content

Flaky tests: InterfaceChoice.Default instances bind real interfaces on shared :5353 and intermittently break registration/probing tests #1800

Description

@bdraco

Problem

Several tests construct Zeroconf / AsyncZeroconf with InterfaceChoice.Default, which binds the host's real network interfaces and the wildcard 0.0.0.0:5353, and then perform real multicast I/O (announce / probe). When such a test runs in the same process as the registration/probing tests, it intermittently perturbs name-conflict probing and registration timing, producing flaky failures.

Observed once locally as 3 failures in the async_register_service / async_check_service path:

src/zeroconf/_core.py:387: in async_register_service
src/zeroconf/_core.py:388: in async_register_service
src/zeroconf/_core.py:623: in async_check_service

The run's debug output showed multiple live instances sharing the port, e.g.:

Listen socket <socket fd=19 ... 0.0.0.0:5353>, respond sockets [<... 127.0.0.1:5353>]
Sending to (224.0.0.251, 5353) via [socket 20 (('127.0.0.1', 5353))] ...

Reproduce

Intermittent (roughly 1 in 15–20 local runs on macOS):

SKIP_CYTHON=1 poetry run pytest \
  tests/test_engine.py tests/test_interface_update.py tests/utils/test_net.py \
  tests/test_core.py tests/test_asyncio.py -q

Most runs pass; occasionally 3 tests in the registration/probing path fail. It is not tied to a specific flag or to ordering (the repo does not install pytest-randomly).

Root cause

These tests are not network-isolated. Instances built with InterfaceChoice.Default join real multicast groups and send/receive on :5353, so concurrent instances in one process can answer or race each other's probes:

  • tests/test_core.py lines ~64, 72, 79, 83, 127, 140 (r.Zeroconf(interfaces=r.InterfaceChoice.Default ...))
  • tests/test_interface_update.py:216 (AsyncZeroconf(interfaces=InterfaceChoice.Default, ...))

async_check_service (probing for name uniqueness) is the sensitive path: a stray multicast answer or timing slip from another live instance can flip its result.

Suggested fixes (any of)

  • Mock zeroconf._utils.net.ifaddr.get_adapters in these tests so InterfaceChoice.Default resolves to loopback only (no real-interface binding), or
  • Run the real-interface tests under the existing run_isolated fixture (patches _MDNS_PORT to 5454) so they don't share :5353, or
  • Bind these instances to an ephemeral/unique port and avoid real multicast where the test only needs socket bookkeeping.

I can put up a PR that isolates the InterfaceChoice.Default tests (mock the adapter enumeration) if that direction is agreeable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions