Skip to content

Commit 1193af7

Browse files
committed
fix broken test cases
Signed-off-by: Nikhil Suri <nikhil.suri@databricks.com>
1 parent 2b45814 commit 1193af7

File tree

2 files changed

+63
-59
lines changed

2 files changed

+63
-59
lines changed

tests/unit/test_circuit_breaker_http_client.py

Lines changed: 45 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,14 @@ def test_request_enabled_circuit_breaker_error(self):
8383
assert b"numProtoSuccess" in response.data
8484

8585
def test_request_enabled_other_error(self):
86-
"""Test request when other error occurs."""
87-
# Mock delegate to raise a different error
86+
"""Test request when other error occurs - should return mock response."""
87+
# Mock delegate to raise a different error (not rate limiting)
8888
self.mock_delegate.request.side_effect = ValueError("Network error")
8989

90-
with pytest.raises(ValueError):
91-
self.client.request(HttpMethod.POST, "https://test.com", {})
90+
# Non-rate-limit errors return mock success response
91+
response = self.client.request(HttpMethod.POST, "https://test.com", {})
92+
assert response is not None
93+
assert response.status == 200
9294

9395
def test_is_circuit_breaker_enabled(self):
9496
"""Test checking if circuit breaker is enabled."""
@@ -121,13 +123,14 @@ def test_other_error_logging(self):
121123
) as mock_logger:
122124
self.mock_delegate.request.side_effect = ValueError("Network error")
123125

124-
with pytest.raises(ValueError):
125-
self.client.request(HttpMethod.POST, "https://test.com", {})
126+
# Should return mock response, not raise
127+
response = self.client.request(HttpMethod.POST, "https://test.com", {})
128+
assert response is not None
126129

127130
# Check that debug was logged
128131
mock_logger.debug.assert_called()
129132
debug_call = mock_logger.debug.call_args[0]
130-
assert "Telemetry request failed" in debug_call[0]
133+
assert "failing silently" in debug_call[0]
131134
assert self.host in debug_call[1]
132135

133136

@@ -140,74 +143,76 @@ def setup_method(self):
140143
self.host = "test-host.example.com"
141144

142145
def test_circuit_breaker_opens_after_failures(self):
143-
"""Test that circuit breaker opens after repeated failures."""
146+
"""Test that circuit breaker opens after repeated failures (429/503 errors)."""
144147
from databricks.sql.telemetry.circuit_breaker_manager import (
145148
CircuitBreakerManager,
146-
MINIMUM_CALLS,
149+
CircuitBreakerConfig,
150+
DEFAULT_MINIMUM_CALLS as MINIMUM_CALLS,
147151
)
152+
from databricks.sql.exc import TelemetryRateLimitError
148153

149154
# Clear any existing state
150155
CircuitBreakerManager._instances.clear()
156+
CircuitBreakerManager.initialize(CircuitBreakerConfig())
151157

152158
client = CircuitBreakerTelemetryPushClient(self.mock_delegate, self.host)
153159

154-
# Simulate failures
155-
self.mock_delegate.request.side_effect = Exception("Network error")
160+
# Simulate rate limit failures (429)
161+
mock_response = Mock()
162+
mock_response.status = 429
163+
self.mock_delegate.request.return_value = mock_response
156164

157-
# Trigger failures - some will raise, some will return mock response once circuit opens
158-
exception_count = 0
165+
# All calls should return mock success (circuit breaker handles it internally)
159166
mock_response_count = 0
160167
for i in range(MINIMUM_CALLS + 5):
161-
try:
162-
response = client.request(HttpMethod.POST, "https://test.com", {})
163-
# Got a mock response - circuit is open
164-
assert response.status == 200
165-
mock_response_count += 1
166-
except Exception:
167-
# Got an exception - circuit is still closed
168-
exception_count += 1
169-
170-
# Should have some exceptions before circuit opened, then mock responses after
171-
# Circuit opens around MINIMUM_CALLS failures (might be MINIMUM_CALLS or MINIMUM_CALLS-1)
172-
assert exception_count >= MINIMUM_CALLS - 1
173-
assert mock_response_count > 0
168+
response = client.request(HttpMethod.POST, "https://test.com", {})
169+
# Always get mock response (circuit breaker prevents re-raising)
170+
assert response.status == 200
171+
mock_response_count += 1
172+
173+
# All should return mock responses (telemetry fails silently)
174+
assert mock_response_count == MINIMUM_CALLS + 5
174175

175176
def test_circuit_breaker_recovers_after_success(self):
176177
"""Test that circuit breaker recovers after successful calls."""
177178
from databricks.sql.telemetry.circuit_breaker_manager import (
178179
CircuitBreakerManager,
179-
MINIMUM_CALLS,
180-
RESET_TIMEOUT,
180+
CircuitBreakerConfig,
181+
DEFAULT_MINIMUM_CALLS as MINIMUM_CALLS,
182+
DEFAULT_RESET_TIMEOUT as RESET_TIMEOUT,
181183
)
182184
import time
183185

184186
# Clear any existing state
185187
CircuitBreakerManager._instances.clear()
188+
CircuitBreakerManager.initialize(CircuitBreakerConfig())
186189

187190
client = CircuitBreakerTelemetryPushClient(self.mock_delegate, self.host)
188191

189-
# Simulate failures first
190-
self.mock_delegate.request.side_effect = Exception("Network error")
192+
# Simulate rate limit failures first (429)
193+
mock_rate_limit_response = Mock()
194+
mock_rate_limit_response.status = 429
195+
self.mock_delegate.request.return_value = mock_rate_limit_response
191196

192-
# Trigger enough failures to open circuit
197+
# Trigger enough rate limit failures to open circuit
193198
for i in range(MINIMUM_CALLS + 5):
194-
try:
195-
client.request(HttpMethod.POST, "https://test.com", {})
196-
except Exception:
197-
pass # Expected during failures
199+
response = client.request(HttpMethod.POST, "https://test.com", {})
200+
assert response.status == 200 # Returns mock success
198201

199-
# Circuit should be open now - returns mock response
202+
# Circuit should be open now - still returns mock response
200203
response = client.request(HttpMethod.POST, "https://test.com", {})
201204
assert response is not None
202205
assert response.status == 200 # Mock success response
203206

204207
# Wait for reset timeout
205208
time.sleep(RESET_TIMEOUT + 1.0)
206209

207-
# Simulate successful calls
208-
self.mock_delegate.request.side_effect = None
209-
self.mock_delegate.request.return_value = Mock()
210+
# Simulate successful calls (200 response)
211+
mock_success_response = Mock()
212+
mock_success_response.status = 200
213+
self.mock_delegate.request.return_value = mock_success_response
210214

211-
# Should work again
215+
# Should work again with actual success response
212216
response = client.request(HttpMethod.POST, "https://test.com", {})
213217
assert response is not None
218+
assert response.status == 200

tests/unit/test_telemetry_circuit_breaker_integration.py

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -239,29 +239,26 @@ def test_circuit_breaker_configuration_from_client_context(self):
239239

240240
def test_circuit_breaker_logging(self):
241241
"""Test that circuit breaker events are properly logged."""
242-
with patch("databricks.sql.telemetry.telemetry_client.logger") as mock_logger:
242+
with patch(
243+
"databricks.sql.telemetry.telemetry_push_client.logger"
244+
) as mock_logger:
243245
# Mock circuit breaker error
244246
with patch.object(
245-
self.telemetry_client._telemetry_push_client,
246-
"request",
247+
self.telemetry_client._telemetry_push_client._circuit_breaker,
248+
"call",
247249
side_effect=CircuitBreakerError("Circuit is open"),
248250
):
249-
try:
250-
self.telemetry_client._send_with_unified_client(
251-
"https://test.com/telemetry",
252-
'{"test": "data"}',
253-
{"Content-Type": "application/json"},
254-
)
255-
except CircuitBreakerError:
256-
pass
251+
# CircuitBreakerError is caught and returns mock response
252+
self.telemetry_client._send_with_unified_client(
253+
"https://test.com/telemetry",
254+
'{"test": "data"}',
255+
{"Content-Type": "application/json"},
256+
)
257257

258-
# Check that warning was logged
259-
mock_logger.warning.assert_called()
260-
warning_call = mock_logger.warning.call_args[0]
261-
assert "Telemetry request blocked by circuit breaker" in warning_call[0]
262-
assert (
263-
"test-session" in warning_call[1]
264-
) # session_id_hex is the second argument
258+
# Check that debug was logged (not warning - telemetry silently drops)
259+
mock_logger.debug.assert_called()
260+
debug_call = mock_logger.debug.call_args[0]
261+
assert "Circuit breaker is open" in debug_call[0]
265262

266263

267264
class TestTelemetryCircuitBreakerThreadSafety:
@@ -341,7 +338,9 @@ def make_request():
341338
errors.append(type(e).__name__)
342339

343340
# Create multiple threads (enough to trigger circuit breaker)
344-
from databricks.sql.telemetry.circuit_breaker_manager import MINIMUM_CALLS
341+
from databricks.sql.telemetry.circuit_breaker_manager import (
342+
DEFAULT_MINIMUM_CALLS as MINIMUM_CALLS,
343+
)
345344

346345
num_threads = MINIMUM_CALLS + 5 # Enough to open the circuit
347346
threads = []

0 commit comments

Comments
 (0)