From: 
Subject: Debian changes

The Debian packaging of amqtt is maintained in git, using a workflow
similar to the one described in dgit-maint-merge(7).
The Debian delta is represented by this one combined patch; there isn't a
patch queue that can be represented as a quilt series.

A detailed breakdown of the changes is available from their canonical
representation -- git commits in the packaging repository.
For example, to see the changes made by the Debian maintainer in the first
upload of upstream version 1.2.3, you could use:

    % git clone https://git.dgit.debian.org/amqtt
    % cd amqtt
    % git log --oneline 1.2.3..debian/1.2.3-1 -- . ':!debian'

(If you have dgit, use `dgit clone amqtt`, rather than plain `git clone`.)

We don't use debian/source/options single-debian-patch because it has bugs.
Therefore, NMUs etc. may nevertheless have made additional patches.

---

diff --git a/amqtt/client.py b/amqtt/client.py
index 6a7ff99..05203b1 100644
--- a/amqtt/client.py
+++ b/amqtt/client.py
@@ -497,6 +497,7 @@ class MQTTClient:
                         self.session.broker_uri,
                         subprotocols=[websockets.Subprotocol("mqtt")],
                         additional_headers=self.additional_headers,
+                        proxy=None,
                         **kwargs,
                     ), timeout=connection_timeout)
 
diff --git a/amqtt/contrib/auth_db/topic_mgr_cli.py b/amqtt/contrib/auth_db/topic_mgr_cli.py
index deaf719..7199fc8 100644
--- a/amqtt/contrib/auth_db/topic_mgr_cli.py
+++ b/amqtt/contrib/auth_db/topic_mgr_cli.py
@@ -13,13 +13,13 @@ from amqtt.errors import MQTTError
 
 logging.basicConfig(level=logging.INFO, format="%(message)s")
 logger = logging.getLogger(__name__)
-topic_app = typer.Typer(no_args_is_help=True)
+topic_app = typer.Typer(invoke_without_command=True)
 
 
 @topic_app.callback()
 def main(
         ctx: typer.Context,
-        db_type: Annotated[DBType, typer.Option("--db", "-d", help="db type", count=False)],
+        db_type: Annotated[DBType | None, typer.Option("--db", "-d", help="db type", count=False)] = None,
         db_username: Annotated[str, typer.Option("--username", "-u", help="db username", show_default=False)] = "",
         db_port: Annotated[int, typer.Option("--port", "-p", help="database port (defaults to db type)", show_default=False)] = 0,
         db_host: Annotated[str, typer.Option("--host", "-h", help="database host")] = "localhost",
@@ -33,6 +33,12 @@ def main(
     If you need to create users programmatically, see `amqtt.contrib.auth_db.managers.TopicManager` which provides
     the underlying functionality to this command line interface.
     """
+    if ctx.invoked_subcommand is None:
+        typer.echo(ctx.get_help())
+        raise typer.Exit(code=2)
+    if db_type is None:
+        raise typer.BadParameter("--db is required")
+
     if db_type == DBType.SQLITE and ctx.invoked_subcommand == "sync" and not Path(db_filename).exists():
         pass
     elif db_type == DBType.SQLITE and not Path(db_filename).exists():
diff --git a/amqtt/contrib/auth_db/user_mgr_cli.py b/amqtt/contrib/auth_db/user_mgr_cli.py
index d881653..ceee8db 100644
--- a/amqtt/contrib/auth_db/user_mgr_cli.py
+++ b/amqtt/contrib/auth_db/user_mgr_cli.py
@@ -11,13 +11,13 @@ from amqtt.errors import MQTTError
 
 logging.basicConfig(level=logging.INFO, format="%(message)s")
 logger = logging.getLogger(__name__)
-user_app = typer.Typer(no_args_is_help=True)
+user_app = typer.Typer(invoke_without_command=True)
 
 
 @user_app.callback()
 def main(
         ctx: typer.Context,
-        db_type: Annotated[DBType, typer.Option(..., "--db", "-d", help="db type", show_default=False)],
+        db_type: Annotated[DBType | None, typer.Option("--db", "-d", help="db type", show_default=False)] = None,
         db_username: Annotated[str, typer.Option("--username", "-u", help="db username", show_default=False)] = "",
         db_port: Annotated[int, typer.Option("--port", "-p", help="database port (defaults to db type)", show_default=False)] = 0,
         db_host: Annotated[str, typer.Option("--host", "-h", help="database host")] = "localhost",
@@ -36,6 +36,12 @@ def main(
         <p>Use NIST or other password guidelines when calling functions that set or update passwords.</p>
     </details>
     """
+    if ctx.invoked_subcommand is None:
+        typer.echo(ctx.get_help())
+        raise typer.Exit(code=2)
+    if db_type is None:
+        raise typer.BadParameter("--db is required")
+
     if db_type == DBType.SQLITE and ctx.invoked_subcommand == "sync" and not Path(db_filename).exists():
         pass
     elif db_type == DBType.SQLITE and not Path(db_filename).exists():
diff --git a/samples/broker_acl.py b/samples/broker_acl.py
index 9fd4cbc..6e710d5 100644
--- a/samples/broker_acl.py
+++ b/samples/broker_acl.py
@@ -1,5 +1,6 @@
 import asyncio
 import logging
+import os
 from pathlib import Path
 
 from amqtt.broker import Broker
@@ -14,10 +15,10 @@ config = {
     "listeners": {
         "default": {
             "type": "tcp",
-            "bind": "0.0.0.0:1883",
+            "bind": f"127.0.0.1:{os.environ.get('AMQTT_BROKER_PORT', '1883')}",
         },
         "ws-mqtt": {
-            "bind": "127.0.0.1:8080",
+            "bind": f"127.0.0.1:{os.environ.get('AMQTT_WS_PORT', '8080')}",
             "type": "ws",
             "max_connections": 10,
         },
diff --git a/samples/broker_simple.py b/samples/broker_simple.py
index 40f1c5b..fc9b819 100644
--- a/samples/broker_simple.py
+++ b/samples/broker_simple.py
@@ -1,6 +1,7 @@
 import asyncio
 from asyncio import CancelledError
 import logging
+import os
 
 from amqtt.broker import Broker
 
@@ -13,7 +14,9 @@ logging.basicConfig(level=logging.INFO, format=formatter)
 
 
 async def run_server() -> None:
-    broker = Broker()
+    port = os.environ.get("AMQTT_BROKER_PORT")
+    config = {"listeners": {"default": {"type": "tcp", "bind": f"127.0.0.1:{port}"}}} if port else None
+    broker = Broker(config)
     try:
         await broker.start()
         while True:
diff --git a/samples/broker_start.py b/samples/broker_start.py
index e0c9231..7829661 100644
--- a/samples/broker_start.py
+++ b/samples/broker_start.py
@@ -1,5 +1,6 @@
 import asyncio
 import logging
+import os
 from pathlib import Path
 
 from amqtt.broker import Broker
@@ -14,10 +15,10 @@ config = {
     "listeners": {
         "default": {
             "type": "tcp",
-            "bind": "0.0.0.0:1883",
+            "bind": f"127.0.0.1:{os.environ.get('AMQTT_BROKER_PORT', '1883')}",
         },
         "ws-mqtt": {
-            "bind": "127.0.0.1:8080",
+            "bind": f"127.0.0.1:{os.environ.get('AMQTT_WS_PORT', '8080')}",
             "type": "ws",
             "max_connections": 10,
         },
diff --git a/samples/broker_taboo.py b/samples/broker_taboo.py
index 19cfbd1..3a34a55 100644
--- a/samples/broker_taboo.py
+++ b/samples/broker_taboo.py
@@ -1,5 +1,6 @@
 import asyncio
 import logging
+import os
 from pathlib import Path
 
 from amqtt.broker import Broker
@@ -14,10 +15,10 @@ config = {
     "listeners": {
         "default": {
             "type": "tcp",
-            "bind": "0.0.0.0:1883",
+            "bind": f"127.0.0.1:{os.environ.get('AMQTT_BROKER_PORT', '1883')}",
         },
         "ws-mqtt": {
-            "bind": "127.0.0.1:8080",
+            "bind": f"127.0.0.1:{os.environ.get('AMQTT_WS_PORT', '8080')}",
             "type": "ws",
             "max_connections": 10,
         },
diff --git a/samples/client_keepalive.py b/samples/client_keepalive.py
index 5de40c5..5c72182 100644
--- a/samples/client_keepalive.py
+++ b/samples/client_keepalive.py
@@ -1,6 +1,7 @@
 import asyncio
 from asyncio import CancelledError
 import logging
+import os
 
 from amqtt.client import MQTTClient
 
@@ -19,7 +20,7 @@ async def main() -> None:
     client = MQTTClient(config=config)
 
     try:
-        await client.connect("mqtt://localhost:1883/")
+        await client.connect(os.environ.get("AMQTT_CLIENT_URL", "mqtt://localhost:1883/"))
         logger.info("client connected")
         await asyncio.sleep(7)
     except CancelledError:
diff --git a/samples/client_publish.py b/samples/client_publish.py
index 83ee5d9..c97a100 100644
--- a/samples/client_publish.py
+++ b/samples/client_publish.py
@@ -1,5 +1,6 @@
 import asyncio
 import logging
+import os
 
 from amqtt.client import ConnectError, MQTTClient
 from amqtt.mqtt.constants import QOS_1, QOS_2
@@ -22,7 +23,7 @@ config = {
 
 async def test_coro1() -> None:
     client = MQTTClient()
-    await client.connect("mqtt://localhost:1883/")
+    await client.connect(os.environ.get("AMQTT_CLIENT_URL", "mqtt://localhost:1883/"))
     tasks = [
         asyncio.ensure_future(client.publish("a/b", b"TEST MESSAGE WITH QOS_0")),
         asyncio.ensure_future(client.publish("a/b", b"TEST MESSAGE WITH QOS_1", qos=QOS_1)),
@@ -36,7 +37,7 @@ async def test_coro1() -> None:
 async def test_coro2() -> None:
     try:
         client = MQTTClient(config={"auto_reconnect": False, "connection_timeout": 1})
-        await client.connect("mqtt://localhost:1884/")
+        await client.connect(os.environ.get("AMQTT_CLIENT_FAIL_URL", "mqtt://localhost:1884/"))
         await client.publish("a/b", b"TEST MESSAGE WITH QOS_0", qos=0x00)
         await client.publish("a/b", b"TEST MESSAGE WITH QOS_1", qos=0x01)
         await client.publish("a/b", b"TEST MESSAGE WITH QOS_2", qos=0x02)
diff --git a/samples/client_publish_acl.py b/samples/client_publish_acl.py
index 99a4cd3..47de4f2 100644
--- a/samples/client_publish_acl.py
+++ b/samples/client_publish_acl.py
@@ -1,5 +1,6 @@
 import asyncio
 import logging
+import os
 
 from amqtt.client import ConnectError, MQTTClient
 from amqtt.mqtt.constants import QOS_1
@@ -15,7 +16,7 @@ logger = logging.getLogger(__name__)
 async def test_coro() -> None:
     try:
         client = MQTTClient()
-        await client.connect("mqtt://0.0.0.0:1883")
+        await client.connect(os.environ.get("AMQTT_CLIENT_URL", "mqtt://0.0.0.0:1883"))
         await client.publish("data/classified", b"TOP SECRET", qos=QOS_1)
         await client.publish("data/memes", b"REAL FUN", qos=QOS_1)
         await client.publish("repositories/amqtt/master", b"NEW STABLE RELEASE", qos=QOS_1)
diff --git a/samples/client_publish_ssl.py b/samples/client_publish_ssl.py
index a0ae79b..7a1f1ce 100644
--- a/samples/client_publish_ssl.py
+++ b/samples/client_publish_ssl.py
@@ -1,6 +1,7 @@
 import argparse
 import asyncio
 import logging
+import os
 
 from amqtt.client import MQTTClient
 from amqtt.mqtt.constants import QOS_1, QOS_2
@@ -42,7 +43,7 @@ async def test_coro(certfile: str) -> None:
     config["certfile"] = certfile
     client = MQTTClient(config=config)
 
-    await client.connect("mqtts://localhost:8883")
+    await client.connect(os.environ.get("AMQTT_CLIENT_URL", "mqtts://localhost:8883"))
     tasks = [
         asyncio.ensure_future(client.publish("a/b", b"TEST MESSAGE WITH QOS_0")),
         asyncio.ensure_future(client.publish("a/b", b"TEST MESSAGE WITH QOS_1", qos=QOS_1)),
diff --git a/samples/client_publish_ws.py b/samples/client_publish_ws.py
index e02c73e..97998f0 100644
--- a/samples/client_publish_ws.py
+++ b/samples/client_publish_ws.py
@@ -1,5 +1,6 @@
 import asyncio
 import logging
+import os
 
 from amqtt.client import MQTTClient
 from amqtt.mqtt.constants import QOS_1, QOS_2
@@ -22,7 +23,7 @@ client = MQTTClient(config=config)
 
 
 async def test_coro() -> None:
-    await client.connect("ws://localhost:8080/")
+    await client.connect(os.environ.get("AMQTT_CLIENT_URL", "ws://localhost:8080/"))
     tasks = [
         asyncio.ensure_future(client.publish("a/b", b"TEST MESSAGE WITH QOS_0")),
         asyncio.ensure_future(client.publish("a/b", b"TEST MESSAGE WITH QOS_1", qos=QOS_1)),
diff --git a/samples/client_subscribe.py b/samples/client_subscribe.py
index c0f4982..3658da5 100644
--- a/samples/client_subscribe.py
+++ b/samples/client_subscribe.py
@@ -1,5 +1,6 @@
 import asyncio
 import logging
+import os
 
 from amqtt.client import ClientError, MQTTClient
 from amqtt.mqtt.constants import QOS_1, QOS_2
@@ -13,7 +14,7 @@ logger = logging.getLogger(__name__)
 
 async def uptime_coro() -> None:
     client = MQTTClient(config={"auto_reconnect": False})
-    await client.connect("mqtt://localhost:1883")
+    await client.connect(os.environ.get("AMQTT_CLIENT_URL", "mqtt://localhost:1883"))
 
     await client.subscribe(
         [
diff --git a/samples/client_subscribe_acl.py b/samples/client_subscribe_acl.py
index e5c1399..9345aa2 100644
--- a/samples/client_subscribe_acl.py
+++ b/samples/client_subscribe_acl.py
@@ -1,5 +1,6 @@
 import asyncio
 import logging
+import os
 
 from amqtt.client import ClientError, MQTTClient
 from amqtt.mqtt.constants import QOS_1
@@ -15,7 +16,7 @@ logger = logging.getLogger(__name__)
 
 async def uptime_coro() -> None:
     client = MQTTClient()
-    await client.connect("mqtt://test:test@0.0.0.0:1883")
+    await client.connect(os.environ.get("AMQTT_CLIENT_URL", "mqtt://test:test@0.0.0.0:1883"))
 
     result = await client.subscribe(
         [
@@ -42,13 +43,7 @@ async def uptime_coro() -> None:
 def __main__():
     formatter = "[%(asctime)s] {%(filename)s:%(lineno)d} %(levelname)s - %(message)s"
     logging.basicConfig(level=logging.INFO, format=formatter)
-
-    loop = asyncio.new_event_loop()
-    asyncio.set_event_loop(loop)
-    loop.run_until_complete(uptime_coro())
-
-
-
+    asyncio.run(uptime_coro())
 
 if __name__ == "__main__":
     __main__()
diff --git a/samples/http_server_integration.py b/samples/http_server_integration.py
index cc80e3d..2b2c85a 100644
--- a/samples/http_server_integration.py
+++ b/samples/http_server_integration.py
@@ -1,6 +1,7 @@
 import asyncio
 import io
 import logging
+import os
 import ssl
 
 import aiohttp
@@ -137,7 +138,6 @@ def main():
     # create an `aiohttp` server
     lp = asyncio.new_event_loop()
     asyncio.set_event_loop(lp)
-
     app = web.Application()
     app.add_routes(
         [
@@ -150,7 +150,7 @@ def main():
 
     # make sure that both `aiohttp` server and `amqtt` broker run in the same loop
     #  so the server can hand off the connection to the broker (prevents attached-to-a-different-loop `RuntimeError`)
-    web.run_app(app, loop=lp)
+    web.run_app(app, host="127.0.0.1", port=int(os.environ.get("AMQTT_HTTP_PORT", "8080")), loop=lp)
 
 
 async def run_broker(_app):
@@ -160,7 +160,10 @@ async def run_broker(_app):
     # standard TCP connection as well as an externalized-listener
     cfg = BrokerConfig(
         listeners={
-            "default":ListenerConfig(type=ListenerType.TCP, bind="127.0.0.1:1883"),
+            "default":ListenerConfig(
+                type=ListenerType.TCP,
+                bind=f"127.0.0.1:{os.environ.get('AMQTT_BROKER_PORT', '1883')}",
+            ),
             MQTT_LISTENER_NAME: ListenerConfig(type=ListenerType.EXTERNAL),
         }
     )
diff --git a/tests/test_samples.py b/tests/test_samples.py
index 8fcde3d..10ebe74 100644
--- a/tests/test_samples.py
+++ b/tests/test_samples.py
@@ -1,8 +1,10 @@
 import ast
 import asyncio
 import logging
+import os
 import multiprocessing
 import signal
+import socket
 import subprocess
 import sys
 
@@ -24,6 +26,28 @@ from samples.broker_dollar_topics import config as broker_dollar_topics_config
 
 logger = logging.getLogger(__name__)
 
+def unused_tcp_port() -> int:
+    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
+        sock.bind(("127.0.0.1", 0))
+        return sock.getsockname()[1]
+
+
+def listener_port(broker: Broker, listener_name: str = "default") -> int:
+    return broker._servers[listener_name].instance.sockets[0].getsockname()[1]
+
+
+def sample_env(url: str) -> dict[str, str]:
+    return {**os.environ, "AMQTT_CLIENT_URL": url}
+
+
+def sample_broker_env() -> dict[str, str]:
+    return {
+        **os.environ,
+        "AMQTT_BROKER_PORT": str(unused_tcp_port()),
+        "AMQTT_WS_PORT": str(unused_tcp_port()),
+    }
+
+
 SAMPLES_DIR = Path(__file__).parent.parent / "samples"
 IGNORED_SAMPLE_FILES = frozenset()
 
@@ -73,7 +97,12 @@ def test_all_sample_files_are_accounted_for():
 @pytest.mark.sample("broker_acl.py")
 async def test_broker_acl():
     broker_acl_script = Path(__file__).parent.parent / "samples/broker_acl.py"
-    process = subprocess.Popen([sys.executable, broker_acl_script], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    process = subprocess.Popen(
+        [sys.executable, broker_acl_script],
+        stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE,
+        env=sample_broker_env(),
+    )
     # Send the interrupt signal
     await asyncio.sleep(2)
     process.send_signal(signal.SIGINT)
@@ -103,7 +132,12 @@ async def test_broker_custom_plugin():
 @pytest.mark.sample("broker_simple.py")
 async def test_broker_simple():
     broker_simple_script = Path(__file__).parent.parent / "samples/broker_simple.py"
-    process = subprocess.Popen([sys.executable, broker_simple_script], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    process = subprocess.Popen(
+        [sys.executable, broker_simple_script],
+        stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE,
+        env=sample_broker_env(),
+    )
     await asyncio.sleep(2)
 
     # Send the interrupt signal
@@ -120,7 +154,12 @@ async def test_broker_simple():
 @pytest.mark.sample("broker_start.py")
 async def test_broker_start():
     broker_start_script = Path(__file__).parent.parent / "samples/broker_start.py"
-    process = subprocess.Popen([sys.executable, broker_start_script], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    process = subprocess.Popen(
+        [sys.executable, broker_start_script],
+        stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE,
+        env=sample_broker_env(),
+    )
     await asyncio.sleep(2)
 
     # Send the interrupt signal to stop broker
@@ -136,7 +175,12 @@ async def test_broker_start():
 @pytest.mark.sample("broker_taboo.py")
 async def test_broker_taboo():
     broker_taboo_script = Path(__file__).parent.parent / "samples/broker_taboo.py"
-    process = subprocess.Popen([sys.executable, broker_taboo_script], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    process = subprocess.Popen(
+        [sys.executable, broker_taboo_script],
+        stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE,
+        env=sample_broker_env(),
+    )
     await asyncio.sleep(2)
 
     # Send the interrupt signal to stop broker
@@ -151,13 +195,17 @@ async def test_broker_taboo():
 @pytest.mark.asyncio
 @pytest.mark.sample("client_keepalive.py")
 async def test_client_keepalive():
-
-    broker = Broker()
+    broker = Broker({"listeners": {"default": {"type": "tcp", "bind": "127.0.0.1:0"}}})
     await broker.start()
     await asyncio.sleep(2)
 
     keep_alive_script = Path(__file__).parent.parent / "samples/client_keepalive.py"
-    process = subprocess.Popen([sys.executable, keep_alive_script], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    process = subprocess.Popen(
+        [sys.executable, keep_alive_script],
+        stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE,
+        env=sample_env(f"mqtt://127.0.0.1:{listener_port(broker)}/"),
+    )
     await asyncio.sleep(1)
 
     stdout, stderr = await asyncio.to_thread(process.communicate)
@@ -170,12 +218,17 @@ async def test_client_keepalive():
 @pytest.mark.asyncio
 @pytest.mark.sample("client_publish.py")
 async def test_client_publish():
-    broker = Broker()
+    broker = Broker({"listeners": {"default": {"type": "tcp", "bind": "127.0.0.1:0"}}})
     await broker.start()
     await asyncio.sleep(2)
 
     client_publish = Path(__file__).parent.parent / "samples/client_publish.py"
-    process = subprocess.Popen([sys.executable, client_publish], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    process = subprocess.Popen(
+        [sys.executable, client_publish],
+        stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE,
+        env=sample_env(f"mqtt://127.0.0.1:{listener_port(broker)}/"),
+    )
     await asyncio.sleep(2)
 
     stdout, stderr = process.communicate()
@@ -192,16 +245,16 @@ def broker_ssl_config(rsa_keys):
         "listeners": {
             "default": {
                 "type": "tcp",
-                "bind": "0.0.0.0:8883",
+                "bind": "127.0.0.1:0",
                 "ssl": True,
                 "certfile": certfile,
                 "keyfile": keyfile,
             }
         },
-        "auth": {
-            "allow-anonymous": True,
-            "plugins": ["auth_anonymous"]
-        }
+        "plugins": {
+            "amqtt.plugins.authentication.AnonymousAuthPlugin": {"allow_anonymous": True},
+            "amqtt.plugins.sys.broker.BrokerSysPlugin": {"sys_interval": 0},
+        },
     }
 
 @pytest.mark.asyncio
@@ -216,7 +269,12 @@ async def test_client_publish_ssl(broker_ssl_config, rsa_keys):
     await asyncio.sleep(2)
     # run the sample
     client_publish_ssl_script = Path(__file__).parent.parent / "samples/client_publish_ssl.py"
-    process = subprocess.Popen([sys.executable, client_publish_ssl_script, '--cert', certfile], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    process = subprocess.Popen(
+        [sys.executable, client_publish_ssl_script, '--cert', certfile],
+        stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE,
+        env=sample_env(f"mqtts://localhost:{listener_port(broker)}"),
+    )
     await asyncio.sleep(2)
     stdout, stderr = process.communicate()
 
@@ -230,12 +288,17 @@ async def test_client_publish_ssl(broker_ssl_config, rsa_keys):
 @pytest.mark.sample("client_publish_acl.py")
 async def test_client_publish_acl():
 
-    broker = Broker()
+    broker = Broker({"listeners": {"default": {"type": "tcp", "bind": "127.0.0.1:0"}}})
     await broker.start()
     await asyncio.sleep(2)
 
     broker_simple_script = Path(__file__).parent.parent / "samples/client_publish_acl.py"
-    process = subprocess.Popen([sys.executable, broker_simple_script], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    process = subprocess.Popen(
+        [sys.executable, broker_simple_script],
+        stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE,
+        env=sample_env(f"mqtt://127.0.0.1:{listener_port(broker)}"),
+    )
     # Send the interrupt signal
     await asyncio.sleep(2)
 
@@ -250,13 +313,13 @@ broker_ws_config = {
     "listeners": {
         "default": {
             "type": "ws",
-            "bind": "0.0.0.0:8080",
+            "bind": "127.0.0.1:0",
         }
     },
-    "auth": {
-        "allow-anonymous": True,
-        "plugins": ["auth_anonymous"]
-    }
+    "plugins": {
+        "amqtt.plugins.authentication.AnonymousAuthPlugin": {"allow_anonymous": True},
+        "amqtt.plugins.sys.broker.BrokerSysPlugin": {"sys_interval": 0},
+    },
 }
 
 @pytest.mark.asyncio
@@ -269,21 +332,27 @@ async def test_client_publish_ws():
     # run the sample
 
     client_publish_ssl_script = Path(__file__).parent.parent / "samples/client_publish_ws.py"
-    process = subprocess.Popen([sys.executable, client_publish_ssl_script], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-    await asyncio.sleep(2)
-    stdout, stderr = process.communicate()
-
-    assert "ERROR" not in stderr.decode("utf-8")
-    assert "Exception" not in stderr.decode("utf-8")
-
-    await broker.shutdown()
+    try:
+        process = await asyncio.create_subprocess_exec(
+            sys.executable,
+            client_publish_ssl_script,
+            stdout=asyncio.subprocess.PIPE,
+            stderr=asyncio.subprocess.PIPE,
+            env=sample_env(f"ws://127.0.0.1:{listener_port(broker)}/"),
+        )
+        stdout, stderr = await process.communicate()
+
+        assert "ERROR" not in stderr.decode("utf-8")
+        assert "Exception" not in stderr.decode("utf-8")
+    finally:
+        await broker.shutdown()
 
 
 broker_std_config = {
     "listeners": {
         "default": {
             "type": "tcp",
-            "bind": "0.0.0.0:1883",
+            "bind": "127.0.0.1:0",
         }
     },
     'sys_interval':2,
@@ -310,7 +379,8 @@ async def test_client_subscribe():
         sys.executable,
         str(client_subscribe_script),
         stdout=asyncio.subprocess.PIPE,
-        stderr=asyncio.subprocess.PIPE
+        stderr=asyncio.subprocess.PIPE,
+        env=sample_env(f"mqtt://127.0.0.1:{listener_port(broker)}"),
     )
 
     stdout, stderr = await process.communicate()
@@ -326,11 +396,18 @@ async def test_client_subscribe():
 @pytest.mark.asyncio
 @pytest.mark.sample("client_subscribe_acl.py")
 async def test_client_subscribe_plugin_acl():
+    broker_acl_config["listeners"]["default"]["bind"] = "127.0.0.1:0"
+    broker_acl_config["listeners"]["ws-mqtt"]["bind"] = "127.0.0.1:0"
     broker = Broker(config=broker_acl_config)
     await broker.start()
 
     broker_simple_script = Path(__file__).parent.parent / "samples/client_subscribe_acl.py"
-    process = subprocess.Popen([sys.executable, broker_simple_script], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    process = subprocess.Popen(
+        [sys.executable, broker_simple_script],
+        stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE,
+        env=sample_env(f"mqtt://test:test@127.0.0.1:{listener_port(broker)}"),
+    )
     # Send the interrupt signal
     await asyncio.sleep(2)
     process.send_signal(signal.SIGINT)
@@ -346,11 +423,18 @@ async def test_client_subscribe_plugin_acl():
 @pytest.mark.asyncio
 @pytest.mark.sample("client_subscribe_acl.py")
 async def test_client_subscribe_plugin_taboo():
+    broker_taboo_config["listeners"]["default"]["bind"] = "127.0.0.1:0"
+    broker_taboo_config["listeners"]["ws-mqtt"]["bind"] = "127.0.0.1:0"
     broker = Broker(config=broker_taboo_config)
     await broker.start()
 
     broker_simple_script = Path(__file__).parent.parent / "samples/client_subscribe_acl.py"
-    process = subprocess.Popen([sys.executable, broker_simple_script], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    process = subprocess.Popen(
+        [sys.executable, broker_simple_script],
+        stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE,
+        env=sample_env(f"mqtt://test:test@127.0.0.1:{listener_port(broker)}"),
+    )
     # Send the interrupt signal
     await asyncio.sleep(2)
     process.send_signal(signal.SIGINT)
@@ -364,14 +448,18 @@ async def test_client_subscribe_plugin_taboo():
 
 
 @pytest.fixture
-def external_http_server():
+def external_http_server(monkeypatch):
+    http_port = unused_tcp_port()
+    broker_port = unused_tcp_port()
+    monkeypatch.setenv("AMQTT_HTTP_PORT", str(http_port))
+    monkeypatch.setenv("AMQTT_BROKER_PORT", str(broker_port))
     # Force "spawn" so the child starts a fresh interpreter with no event loop.
     # On Linux the default start method is "fork", which would inherit the running
     # pytest-asyncio event loop and break `web.run_app` inside the sample's main().
     ctx = multiprocessing.get_context("spawn")
     p = ctx.Process(target=http_server_main)
     p.start()
-    yield p
+    yield http_port
     p.terminate()
     p.join()
 
@@ -397,7 +485,7 @@ async def test_external_http_server(external_http_server):
 
     await _wait_for_port("127.0.0.1", 8080)
     client = MQTTClient(config={'auto_reconnect': False})
-    await client.connect("ws://127.0.0.1:8080/mqtt")
+    await client.connect(f"ws://127.0.0.1:{external_http_server}/mqtt")
     assert client.session is not None
     await client.publish("my/topic", b'test message')
     await client.disconnect()
diff --git a/tests/test_session_monitor.py b/tests/test_session_monitor.py
index 438f2fd..536758c 100644
--- a/tests/test_session_monitor.py
+++ b/tests/test_session_monitor.py
@@ -9,6 +9,9 @@ from amqtt.contexts import BrokerConfig, ListenerConfig, ConnectionConfig, Clien
 
 logger = logging.getLogger(__name__)
 
+def listener_port(broker: Broker, listener_name: str = "default") -> int:
+    return broker._servers[listener_name].instance.sockets[0].getsockname()[1]
+
 @pytest.fixture
 def session_broker_config():
      return BrokerConfig(
@@ -37,16 +40,18 @@ def session_broker_config():
 async def test_clear_session_expiration(caplog, session_broker_config, username, clean_session, session_count, expiration):
     caplog.set_level(logging.DEBUG)
 
+    session_broker_config.listeners["default"].bind = "127.0.0.1:0"
     session_broker_config.session_expiry_interval = expiration
     session_broker_config.plugins = {'amqtt.plugins.authentication.AnonymousAuthPlugin': {'allow_anonymous': username == ""}}
 
     broker = Broker(config=session_broker_config)
     await broker.start()
+    port = listener_port(broker)
     await asyncio.sleep(0.1)
     assert len(broker._sessions) < 1
 
     c = MQTTClient(config=ClientConfig(cleansession=clean_session, auto_reconnect=False))
-    await c.connect(f'mqtt://{username}127.0.0.1:1883')
+    await c.connect(f'mqtt://{username}127.0.0.1:{port}')
     await asyncio.sleep(0.1)
     assert len(broker._sessions) == 1, "client should be connected"
     await asyncio.sleep(0.1)
