Repository navigation
test(redis): make the fake server's AUTH refusal deterministic (LAB-8767) - #569
Conversation
refuse_from_now() shut down the server's side of each open connection, but redis-py's pool reconnects a pooled connection only if it already sees it closed, and the client sees the server's close only once the kernel delivers it. A command sent before then failed on the old connection with a reset or EOF instead of reaching AUTH, so a provider-backend wrongpass row failed its AuthenticationError precondition, or quietly ran as a dropped case. The backend's redis-py pool now drops its connections before the command runs, so the command always opens a new connection and its AUTH is refused. refuse_from_now() then waits for the server to see every connection it accepted close, and fails if one stays open.
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 52 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Code Review Completed! 🔥The code review was successfully completed based on your current configurations. Kody Guide: Usage and ConfigurationInteracting with Kody
Providing Context (Files & MCPs)Add these hints in your PR description (or a comment) to unlock deeper checks:
Current Kody ConfigurationReview OptionsThe following review options are enabled or disabled:
|
_FakeRedis.refuse_from_now()now makes the backend's next command re-authenticate on every run. The backend's redis-py pool drops its connections before the command runs, so the command opens a new connection and its AUTH meets WRONGPASS, whatever the kernel has delivered by then.The flake
refuse_from_now()shut down the server's side of each open connection and relied on the client noticing. redis-py's pool reconnects a pooled connection only ifcan_read()already sees it closed when the pool hands it out, and a pool connection gets no retry. The client sees the server's close only once the kernel delivers it. So a command sent before then went out on the old connection and failed with aConnectionError(a reset, or EOF) instead of reaching AUTH.A provider backend's init ping leaves exactly such a connection in its pool, so only provider-backend rows were exposed:
provider-backendrow oftest_an_interrupt_while_classifying_a_failure_clears_the_failures_frames_too, and everywrongpassrow oftest_provider_backend_failure_reaches_no_frame_holding_the_password, failed itsAuthenticationErrorprecondition.wrongpassrow oftest_a_cancel_during_a_failing_lock_attempt_reaches_no_frame_holding_the_passwordfailed with a transientConnectionErrorinstead of the cancel.provider-backend-wrongpassrow oftest_a_failed_write_is_freed_without_the_cyclic_gcpassed, but as adroppedcase: the server never sent WRONGPASS.RedisBackendrows and the provider's init ping open their first connection inside the operation, so they never raced.The fix
All of it is in
tests/unit/backends/test_redis_error_frames.py. Nothing undersrc/changes.refuse_from_now(backend)sets the server refusing, then callsconnection_pool.disconnect()on the backend's redis-py client, when the backend holds one.disconnect()clears each connection's socket before closing it, so the pool's nextconnect()opens a new socket and sends AUTH.wrongpasscase would quietly run asdropped. This replaces the server-side shutdown and itsOSErrorrule, which guarded the same thing.AuthenticationErrorprecondition and the_assert_cleared(...)call after it are as they were, and_FAILURESstill mapswrongpasstoredis.AuthenticationError.Verification
can_read()call inget_connection) see nothing, as it does when the server's close has not reached the client yet. Onmainthat fails exactly the rows listed above, and the gc row passes with no WRONGPASS sent. On this branch the whole file passes, and everywrongpassand interrupt-classifying row gets its WRONGPASS.uv run pytest tests/unit/backends/test_redis_error_frames.py -q -k "interrupt or signal", and of the whole file, pass under sustained CPU and loopback-traffic load.Noneinstead of the backend in the gc test fails itsprovider-backendrow with "a connection authenticated before the refusal is still open".uv run pytest tests/unit -m "not slow"passes, and ruff and basedpyright are clean.