Skip to content

Harden test/conftest.py and close the IPv6 and SASL test gaps #274

Description

@jaysonsantos

Part of the repository modernization effort.

Background

test/conftest.py starts real memcached processes. The fixtures are not robust.

Problem 1: no start check

test/test_tls.py:39-40 checks p.poll() and calls pytest.skip(...). The four fixtures in test/conftest.py do no such check.

If memcached is absent from PATH, every test fails with an opaque ConnectionRefusedError. A clear skip message is better.

Problem 2: fixed ports

The fixtures use port 11211, port 5000 (test/conftest.py:27), and port 5001 (test/test_tls.py:25). No collision check runs. Two runners on one host break each other. A leftover memcached process breaks the run.

Problem 3: fixed sleep

The fixtures call time.sleep(0.1) after start. A slow start causes a flaky failure.

Fix: poll the port or the socket until it accepts a connection. Use a timeout.

Problem 4: deprecated pytest API

test/conftest.py:12,23,33,45 use pytest.yield_fixture. This is a deprecated alias of @pytest.fixture.

Problem 5: stale unix socket

The unix socket path is /tmp/memcached.sock. See test/test_socket.py:11. If p.kill() leaves the socket file, the next run fails to bind.

Coverage gaps

IPv6 has no end-to-end test

test/conftest.py:44-56 starts a real server with -l::1. No test connects to it.

The only ::1 references live in test/test_server_parsing.py:30-60. Those tests call Protocol.split_host_port(). They parse strings. They never open a socket.

The fixture runs on every session and tests nothing.

Fix: add a real IPv6 round trip test, or delete the fixture. Do not keep an unused fixture.

SASL auth has no integration test

test/test_auth.py:16-61 mocks Protocol._get_response and feeds canned bytes. It tests the client state machine. It never starts a memcached with auth enabled.

No fixture starts an auth-enabled server.

Fix: add a fixture that starts memcached with SASL enabled. Add one test that authenticates and does a set and a get.

Distributed hashing is thin

test/test_distributed_client_hashing.py holds 12 lines. It asserts that one key maps to one server, ten times.

It never tests ring rebalance. That is the interesting property of consistent hashing.

Fix: add a test that adds or removes a server and checks the key-to-server mapping.

Coverage that is adequate

  • TLS: test/test_tls.py covers it. Run 34284112624 ran 48 of 48 TLS tests with 0 skips.
  • Compression: test/test_compression.py covers zlib, a bz2 swap, a mismatch, and the mocked toggles.
  • Unix socket: test/test_socket.py reuses MemcachedTests. It holds no socket-specific edge cases. This is thin but acceptable.

Acceptance criteria

  • Every fixture in test/conftest.py checks p.poll() after start. It calls pytest.skip() with a clear message when the process died or memcached is absent from PATH.
  • Every fixture replaces time.sleep(0.1) with a connect-retry loop and a timeout.
  • pytest.yield_fixture is replaced with @pytest.fixture at test/conftest.py:12,23,33,45.
  • The unix socket file is removed on teardown.
  • The IPv6 fixture has a test that does a set and a get over IPv6, or the fixture is deleted.
  • A SASL-enabled memcached fixture exists. One test authenticates against it and does a set and a get.
  • test/test_distributed_client_hashing.py tests the key-to-server mapping after a server changes.
  • The suite passes locally and in CI.

Files to change

test/conftest.py, test/test_distributed_client_hashing.py, test/test_auth.py, test/test_server_parsing.py. New files are acceptable, for example test/test_ipv6.py and test/test_sasl_integration.py.

Order

Independent of every other modernization issue. Run it in parallel.

Related

Issue #250 reports that the unit tests are not successful. This work can close that report. Check it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    code-qualityCode quality, typing and defectsmodernizationRepo modernization effort

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions