Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/codspeed.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: CodSpeed

on:
push:
branches: [main]
pull_request:
# `workflow_dispatch` allows CodSpeed to trigger backtest
# performance analysis in order to generate initial data.
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read
id-token: write

jobs:
codspeed:
name: Run benchmarks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Install uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
enable-cache: true
prune-cache: false
- name: Set up Python
run: uv python install '3.14'
- name: Prepare project for development
run: uv sync
- name: Run benchmarks
uses: CodSpeedHQ/action@3194d9a39c4d46684cb44bf7207fc56626aad8fd # v4.15.1
with:
mode: simulation
run: uv run pytest tests/test_benchmarks.py --codspeed
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/miketheman/pytest-socket/main.svg)](https://results.pre-commit.ci/latest/github/miketheman/pytest-socket/main)
[![Maintainability](https://api.codeclimate.com/v1/badges/1608a75b1c3a20211992/maintainability)](https://codeclimate.com/github/miketheman/pytest-socket/maintainability)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![CodSpeed](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/miketheman/pytest-socket?utm_source=badge)

A plugin to use with Pytest to disable or restrict `socket` calls during
tests to ensure network calls are prevented.
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dev = [
"coverage[toml] >= 7.9",
"httpx >= 0.28.1",
"mypy >= 1.20",
"pytest-codspeed>=5.0.2",
"pytest-randomly >= 3.15.0",
"starlette >= 0.47.1",
]
Expand Down
113 changes: 113 additions & 0 deletions tests/test_benchmarks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"""
Performance benchmarks for pytest-socket.

These benchmarks track the performance of the core utility functions
used by the plugin to resolve, validate, and partition host allow-lists.
"""

from __future__ import annotations

from pytest_socket import (
_partition_allowed,
disable_socket,
enable_socket,
host_from_address,
host_from_connect_args,
is_ipaddress,
normalize_allowed_hosts,
)

# ---------------------------------------------------------------------------
# is_ipaddress
# ---------------------------------------------------------------------------


def test_bench_is_ipaddress_valid_ipv4(benchmark):
benchmark(is_ipaddress, "192.168.1.1")


def test_bench_is_ipaddress_valid_ipv6(benchmark):
benchmark(is_ipaddress, "::1")


def test_bench_is_ipaddress_invalid(benchmark):
benchmark(is_ipaddress, "not-an-ip")


# ---------------------------------------------------------------------------
# host_from_address / host_from_connect_args
# ---------------------------------------------------------------------------


def test_bench_host_from_address(benchmark):
benchmark(host_from_address, ("127.0.0.1", 80))


def test_bench_host_from_connect_args(benchmark):
benchmark(host_from_connect_args, (("10.0.0.1", 443),))


def test_bench_host_from_connect_args_unix(benchmark):
"""Benchmark with a non-tuple address (e.g. Unix socket path)."""
benchmark(host_from_connect_args, ("/var/run/app.sock",))


# ---------------------------------------------------------------------------
# _partition_allowed
# ---------------------------------------------------------------------------


def test_bench_partition_allowed_hosts_only(benchmark):
hosts = ["127.0.0.1", "10.0.0.1", "::1", "localhost"]
benchmark(_partition_allowed, hosts)


def test_bench_partition_allowed_mixed(benchmark):
hosts = [
"127.0.0.1",
"10.0.0.0/8",
"::1",
"192.168.0.0/16",
"localhost",
"172.16.0.0/12",
]
benchmark(_partition_allowed, hosts)


def test_bench_partition_allowed_large(benchmark):
hosts = [f"10.0.{i}.0/24" for i in range(50)] + [
f"192.168.1.{i}" for i in range(50)
]
benchmark(_partition_allowed, hosts)


# ---------------------------------------------------------------------------
# normalize_allowed_hosts
# ---------------------------------------------------------------------------


def test_bench_normalize_allowed_hosts_ips(benchmark):
hosts = ["127.0.0.1", "10.0.0.1", "192.168.1.1"]
benchmark(normalize_allowed_hosts, hosts)


def test_bench_normalize_allowed_hosts_with_cache(benchmark):
cache: dict[str, set[str]] = {}
hosts = ["127.0.0.1", "10.0.0.1"]
benchmark(normalize_allowed_hosts, hosts, cache)


# ---------------------------------------------------------------------------
# disable_socket / enable_socket cycle
# ---------------------------------------------------------------------------


def _disable_enable_cycle():
disable_socket(allow_unix_socket=False)
enable_socket()


def test_bench_disable_enable_socket(benchmark):
benchmark(_disable_enable_cycle)
# Ensure socket is restored after benchmark
enable_socket()
75 changes: 74 additions & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading