mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-12 03:48:56 +00:00
test(streaming): cover the three failure branches of the abandoned-stream flush
codecov/patch was at 77.41% against an 87.23% target. The uncovered lines were all error paths, so this adds a test per branch rather than reshaping the happy path: - nothing streamed (`wrapper.chunks` empty): the flush must not assemble or record anything, and must not mark the stream as logged; - `litellm.stream_chunk_builder` raising: the failure is logged and swallowed, no half-built response is recorded, and the stream still counts as logged so a second close does not retry; - the provider stream's own `close()` raising: that must not mask the caller's error, and the reference is still dropped. `test_close_survives_provider_stream_raising` uses a real object whose `close` raises rather than a mock with a configured side effect, so the assertion is about the outcome (reference dropped, no propagation) instead of the call.
This commit is contained in:
parent
e06e7321b0
commit
49980db0b9
1 changed files with 38 additions and 0 deletions
|
|
@ -6210,3 +6210,41 @@ class TestCloseFlushesAbandonedStream:
|
|||
# the provider stream was closed and the reference dropped
|
||||
assert released == [True]
|
||||
assert wrapper.completion_stream is None
|
||||
|
||||
def test_no_flush_when_nothing_was_streamed(self):
|
||||
wrapper, logging_obj = self._wrapper_with_chunk()
|
||||
wrapper.chunks = []
|
||||
|
||||
wrapper.close_stream()
|
||||
|
||||
# nothing was served, so there is nothing to bill or log
|
||||
assert "async_complete_streaming_response" not in logging_obj.model_call_details
|
||||
assert wrapper._abandonment_logged is False
|
||||
|
||||
def test_flush_survives_stream_chunk_builder_raising(self):
|
||||
wrapper, logging_obj = self._wrapper_with_chunk()
|
||||
|
||||
def _boom(**_kwargs):
|
||||
raise RuntimeError("builder exploded")
|
||||
|
||||
with patch("litellm.stream_chunk_builder", _boom):
|
||||
wrapper.close_stream()
|
||||
|
||||
# the failure is logged, not raised, and nothing half-built is recorded
|
||||
assert "async_complete_streaming_response" not in logging_obj.model_call_details
|
||||
assert wrapper._abandonment_logged is True
|
||||
|
||||
def test_close_survives_provider_stream_raising(self):
|
||||
wrapper, _ = self._wrapper_with_chunk()
|
||||
|
||||
class _Angry:
|
||||
def close(inner_self):
|
||||
raise OSError("already closed")
|
||||
|
||||
wrapper.completion_stream = _Angry()
|
||||
|
||||
wrapper.close_stream()
|
||||
|
||||
# a provider that fails to close must not mask the caller's own error,
|
||||
# and the reference is still dropped
|
||||
assert wrapper.completion_stream is None
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue