Skip to content

Commit aebb46a

Browse files
committed
test
Signed-off-by: Sai Shree Pradhan <saishree.pradhan@databricks.com>
1 parent 9a87af3 commit aebb46a

File tree

1 file changed

+42
-27
lines changed

1 file changed

+42
-27
lines changed

tests/unit/test_telemetry.py

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -338,53 +338,68 @@ def http_client(self):
338338

339339
client.close()
340340

341-
def test_circuit_breaker_opens_after_failures(self, http_client):
342-
"""Verify the circuit opens after N consecutive failures and rejects new calls."""
341+
def test_circuit_breaker_full_lifecycle(self, http_client):
342+
"""
343+
Verifies the full lifecycle of the circuit breaker:
344+
1. Starts closed.
345+
2. Opens on the Nth consecutive failure.
346+
3. Rejects new calls immediately while open.
347+
4. Transitions to half-open after the reset timeout.
348+
5. Closes after a single successful call in the half-open state.
349+
"""
350+
343351
fail_max = 3
352+
reset_timeout = 1
344353
http_client.circuit_breaker.fail_max = fail_max
354+
http_client.circuit_breaker.reset_timeout = reset_timeout
345355

346356
with patch.object(http_client.session, "post") as mock_post:
347-
mock_post.side_effect = requests.exceptions.RequestException("Connection failed")
357+
# Define the sequence of mock behaviors: 3 failures, then 1 success
358+
mock_post.side_effect = [
359+
requests.exceptions.RequestException("Connection failed 1"),
360+
requests.exceptions.RequestException("Connection failed 2"),
361+
requests.exceptions.RequestException("Connection failed 3"),
362+
MagicMock(ok=True, status_code=200) # The successful probe call
363+
]
348364

349-
for _ in range(fail_max - 1):
350-
with pytest.raises(requests.exceptions.RequestException):
365+
# Cause N-1 Failures (Circuit should remain closed)
366+
# These first two calls should fail normally without opening the circuit.
367+
for i in range(fail_max - 1):
368+
with pytest.raises(requests.exceptions.RequestException, match=f"Connection failed {i+1}"):
351369
http_client.post("https://test.com/telemetry")
370+
371+
# Verify state: circuit is still closed, but the counter has increased
372+
assert http_client.circuit_breaker.current_state == "closed"
373+
assert mock_post.call_count == fail_max - 1
352374

375+
# Cause the Nth Failure (This will open the circuit)
376+
# This is the call that trips the breaker. We expect a CircuitBreakerError.
353377
with pytest.raises(CircuitBreakerError):
354378
http_client.post("https://test.com/telemetry")
355379

380+
# Verify state: circuit is now open and the network call was still made
356381
assert http_client.circuit_breaker.current_state == "open"
357382
assert mock_post.call_count == fail_max
358383

384+
# Verify the Circuit is Open
385+
# Any subsequent call should be rejected immediately without a network request.
359386
with pytest.raises(CircuitBreakerError):
360387
http_client.post("https://test.com/telemetry")
361-
assert mock_post.call_count == fail_max
362-
363-
def test_circuit_breaker_closes_after_timeout_and_success(self, http_client):
364-
"""Verify the circuit moves to half-open and then closes after a successful probe."""
365-
fail_max = 2
366-
reset_timeout = 0.1
367-
http_client.circuit_breaker.fail_max = fail_max
368-
http_client.circuit_breaker.reset_timeout = reset_timeout
369-
370-
with patch.object(http_client.session, "post") as mock_post:
371-
mock_post.side_effect = [
372-
requests.exceptions.RequestException("Fail 1"),
373-
requests.exceptions.RequestException("Fail 2"),
374-
MagicMock(ok=True)
375-
]
376388

377-
with pytest.raises(requests.exceptions.RequestException):
378-
http_client.post("https://test.com")
379-
with pytest.raises(CircuitBreakerError):
380-
http_client.post("https://test.com")
389+
assert mock_post.call_count == fail_max
381390

382-
assert http_client.circuit_breaker.current_state == "open"
391+
# Wait for the reset timeout to elapse.
383392
time.sleep(reset_timeout)
384393

385-
http_client.post("https://test.com")
394+
# Make one more call. Since the circuit is half-open, this will be let through.
395+
# Our mock is configured for this call to succeed.
396+
http_client.post("https://test.com/telemetry")
397+
398+
# After the successful probe, the circuit should immediately close.
386399
assert http_client.circuit_breaker.current_state == "closed"
387-
assert mock_post.call_count == 3
400+
401+
# Verify that the successful probe call was actually made
402+
assert mock_post.call_count == fail_max + 1
388403

389404
def test_circuit_breaker_reopens_if_probe_fails(self, http_client):
390405
"""Verify the circuit moves to half-open and then back to open if the probe fails."""

0 commit comments

Comments
 (0)