1919import logging
2020import sys
2121import threading
22+ from contextlib import contextmanager
2223from dataclasses import asdict
2324from typing import Any
2425from unittest import TestCase
@@ -85,12 +86,24 @@ def test_fsspec_entry_point_no_fsspec(self):
8586FAKE_SYSTEM_INSTRUCTION = [types .Text (content = "You are a helpful assistant." )]
8687
8788
89+ class ThreadSafeMagicMock (MagicMock ):
90+ def __init__ (self , * args , ** kwargs ) -> None :
91+ self .__dict__ ["_lock" ] = threading .Lock ()
92+ super ().__init__ (* args , ** kwargs )
93+
94+ def _increment_mock_call (self , / , * args , ** kwargs ):
95+ with self .__dict__ ["_lock" ]:
96+ super ()._increment_mock_call (* args , ** kwargs )
97+
98+
8899class TestFsspecUploadHook (TestCase ):
89100 def setUp (self ):
90101 self ._fsspec_patcher = patch (
91102 "opentelemetry.util.genai._fsspec_upload.fsspec_hook.fsspec"
92103 )
93104 self .mock_fsspec = self ._fsspec_patcher .start ()
105+ self .mock_fsspec .open = ThreadSafeMagicMock ()
106+
94107 self .hook = FsspecUploadHook (
95108 base_path = BASE_PATH ,
96109 max_size = MAXSIZE ,
@@ -100,6 +113,20 @@ def tearDown(self) -> None:
100113 self .hook .shutdown ()
101114 self ._fsspec_patcher .stop ()
102115
116+ @contextmanager
117+ def block_upload (self ):
118+ unblock_upload = threading .Event ()
119+
120+ def blocked_upload (* args : Any ):
121+ unblock_upload .wait ()
122+ return MagicMock ()
123+
124+ try :
125+ self .mock_fsspec .open .side_effect = blocked_upload
126+ yield
127+ finally :
128+ unblock_upload .set ()
129+
103130 def test_shutdown_no_items (self ):
104131 self .hook .shutdown ()
105132
@@ -119,46 +146,45 @@ def test_upload_then_shutdown(self):
119146 )
120147
121148 def test_upload_blocked (self ):
122- unblock_upload = threading .Event ()
123-
124- def blocked_upload (* args : Any ):
125- unblock_upload .wait ()
126- return MagicMock ()
149+ with self .block_upload ():
150+ # fill the queue
151+ for _ in range (MAXSIZE ):
152+ self .hook .upload (
153+ inputs = FAKE_INPUTS ,
154+ outputs = FAKE_OUTPUTS ,
155+ system_instruction = FAKE_SYSTEM_INSTRUCTION ,
156+ )
157+
158+ self .assertLessEqual (
159+ self .mock_fsspec .open .call_count ,
160+ MAXSIZE ,
161+ f"uploader should only be called { MAXSIZE = } times" ,
162+ )
127163
128- self .mock_fsspec .open .side_effect = blocked_upload
164+ with self .assertLogs (level = logging .WARNING ) as logs :
165+ self .hook .upload (
166+ inputs = FAKE_INPUTS ,
167+ outputs = FAKE_OUTPUTS ,
168+ system_instruction = FAKE_SYSTEM_INSTRUCTION ,
169+ )
129170
130- # fill the queue
131- for _ in range (MAXSIZE ):
132- self .hook .upload (
133- inputs = FAKE_INPUTS ,
134- outputs = FAKE_OUTPUTS ,
135- system_instruction = FAKE_SYSTEM_INSTRUCTION ,
171+ self .assertIn (
172+ "fsspec upload queue is full, dropping upload" , logs .output [0 ]
136173 )
137174
138- self .assertLessEqual (
139- self .mock_fsspec .open .call_count ,
140- MAXSIZE ,
141- f"uploader should only be called { MAXSIZE = } times" ,
142- )
143-
144- with self .assertLogs (level = logging .WARNING ) as logs :
175+ def test_shutdown_timeout (self ):
176+ with self .block_upload ():
145177 self .hook .upload (
146178 inputs = FAKE_INPUTS ,
147179 outputs = FAKE_OUTPUTS ,
148180 system_instruction = FAKE_SYSTEM_INSTRUCTION ,
149181 )
150182
151- self .assertIn (
152- "fsspec upload queue is full, dropping upload" , logs .output [0 ]
153- )
154-
155- unblock_upload .set ()
183+ # shutdown should timeout and return even though there are still items in the queue
184+ self .hook .shutdown (timeout_sec = 0.01 )
156185
157186 def test_failed_upload_logs (self ):
158- def failing_upload (* args : Any ) -> None :
159- raise RuntimeError ("failed to upload" )
160-
161- self .mock_fsspec .open = MagicMock (wraps = failing_upload )
187+ self .mock_fsspec .open .side_effect = RuntimeError ("failed to upload" )
162188
163189 with self .assertLogs (level = logging .ERROR ) as logs :
164190 self .hook .upload (
@@ -178,7 +204,7 @@ def test_upload_after_shutdown_logs(self):
178204 outputs = FAKE_OUTPUTS ,
179205 system_instruction = FAKE_SYSTEM_INSTRUCTION ,
180206 )
181- self .assertEqual (len (logs .output ), 1 )
207+ self .assertEqual (len (logs .output ), 3 )
182208 self .assertIn (
183209 "attempting to upload file after FsspecUploadHook.shutdown() was already called" ,
184210 logs .output [0 ],
0 commit comments