@@ -140,3 +140,180 @@ def test_execute_edits_passed_file() -> None:
140140 assert returned_content == expected_content , (
141141 f"Content mismatch. Expected: { expected_content !r} , Got: { returned_content !r} "
142142 )
143+
144+
145+ def test_matplotlib_sine_wave_plot () -> None :
146+ timeout = httpx .Timeout (10.0 , connect = 5.0 )
147+
148+ with httpx .Client (base_url = BASE_URL , timeout = timeout ) as client :
149+ # First check health
150+ try :
151+ health_response = client .get ("/health" )
152+ except httpx .TransportError as exc : # pragma: no cover - network failure path
153+ pytest .fail (f"Failed to reach Code Interpreter service at { BASE_URL } : { exc !s} " )
154+
155+ assert health_response .status_code == 200 , health_response .text
156+
157+ code = """
158+ import matplotlib
159+ matplotlib.use('Agg') # Use non-interactive backend
160+ import matplotlib.pyplot as plt
161+ import numpy as np
162+
163+ # Generate data
164+ x = np.linspace(0, 10, 100)
165+ y = np.sin(x)
166+
167+ # Create plot
168+ plt.figure(figsize=(10, 6))
169+ plt.plot(x, y)
170+ plt.title('Sine Wave')
171+ plt.xlabel('x')
172+ plt.ylabel('sin(x)')
173+ plt.grid(True)
174+
175+ # Save plot
176+ plt.savefig('sine_wave.png')
177+ plt.close()
178+ print("Plot saved successfully")
179+ """ .strip ()
180+
181+ execute_payload : dict [str , Any ] = {
182+ "code" : code ,
183+ "stdin" : None ,
184+ "timeout_ms" : 5000 ,
185+ "files" : [],
186+ }
187+
188+ try :
189+ execute_response = client .post ("/v1/execute" , json = execute_payload )
190+ except httpx .TransportError as exc : # pragma: no cover - network failure path
191+ pytest .fail (f"Failed to reach Code Interpreter service at { BASE_URL } : { exc !s} " )
192+
193+ assert execute_response .status_code == 200 , execute_response .text
194+
195+ result = execute_response .json ()
196+
197+ # Verify execution succeeded
198+ assert result ["stdout" ] == "Plot saved successfully\n " , f"stdout mismatch: { result } "
199+ assert result ["stderr" ] == "" , f"stderr should be empty: { result } "
200+ assert result ["exit_code" ] == 0 , f"exit_code should be 0: { result } "
201+ assert result ["timed_out" ] is False , f"should not timeout: { result } "
202+
203+ # Verify the PNG file was created and returned
204+ files = result .get ("files" )
205+ assert isinstance (files , list ), "files should be a list"
206+
207+ # Find the sine_wave.png file
208+ png_file = None
209+ for file_entry in files :
210+ if isinstance (file_entry , dict ) and file_entry .get ("path" ) == "sine_wave.png" :
211+ png_file = file_entry
212+ break
213+
214+ assert png_file is not None , f"sine_wave.png not found in response files: { files } "
215+ assert png_file ["kind" ] == "file"
216+
217+ # Verify the file has a file_id
218+ file_id = png_file .get ("file_id" )
219+ assert isinstance (file_id , str ), "file_id should be present"
220+
221+ # Download the file and verify it's a valid PNG
222+ download_response = client .get (f"/v1/files/{ file_id } " )
223+ assert download_response .status_code == 200 , (
224+ f"Failed to download file: { download_response .text } "
225+ )
226+ png_bytes = download_response .content
227+
228+ # PNG files start with these magic bytes
229+ assert png_bytes [:8 ] == b"\x89 PNG\r \n \x1a \n " , "File should be a valid PNG"
230+
231+ # Verify the file has reasonable size (should be several KB for a plot)
232+ assert len (png_bytes ) > 1000 , f"PNG file too small: { len (png_bytes )} bytes"
233+
234+
235+ def test_create_multiple_files () -> None :
236+ timeout = httpx .Timeout (5.0 , connect = 5.0 )
237+
238+ with httpx .Client (base_url = BASE_URL , timeout = timeout ) as client :
239+ # First check health
240+ try :
241+ health_response = client .get ("/health" )
242+ except httpx .TransportError as exc : # pragma: no cover - network failure path
243+ pytest .fail (f"Failed to reach Code Interpreter service at { BASE_URL } : { exc !s} " )
244+
245+ assert health_response .status_code == 200 , health_response .text
246+
247+ code = """
248+ # Create multiple files
249+ with open('file1.txt', 'w') as f:
250+ f.write('Content of file 1')
251+
252+ with open('file2.txt', 'w') as f:
253+ f.write('Content of file 2')
254+
255+ with open('file3.txt', 'w') as f:
256+ f.write('Content of file 3')
257+
258+ print("Created 3 files")
259+ """ .strip ()
260+
261+ execute_payload : dict [str , Any ] = {
262+ "code" : code ,
263+ "stdin" : None ,
264+ "timeout_ms" : 2000 ,
265+ "files" : [],
266+ }
267+
268+ try :
269+ execute_response = client .post ("/v1/execute" , json = execute_payload )
270+ except httpx .TransportError as exc : # pragma: no cover - network failure path
271+ pytest .fail (f"Failed to reach Code Interpreter service at { BASE_URL } : { exc !s} " )
272+
273+ assert execute_response .status_code == 200 , execute_response .text
274+
275+ result = execute_response .json ()
276+
277+ # Verify execution succeeded
278+ assert result ["stdout" ] == "Created 3 files\n " , f"stdout mismatch: { result } "
279+ assert result ["stderr" ] == "" , f"stderr should be empty: { result } "
280+ assert result ["exit_code" ] == 0 , f"exit_code should be 0: { result } "
281+ assert result ["timed_out" ] is False , f"should not timeout: { result } "
282+
283+ # Verify all three files were created and returned
284+ files = result .get ("files" )
285+ assert isinstance (files , list ), "files should be a list"
286+ assert len (files ) == 3 , f"Expected 3 files, got { len (files )} : { files } "
287+
288+ # Check that all expected files are present
289+ file_paths = {file_entry ["path" ] for file_entry in files }
290+ expected_paths = {"file1.txt" , "file2.txt" , "file3.txt" }
291+ assert file_paths == expected_paths , (
292+ f"File paths mismatch. Expected: { expected_paths } , Got: { file_paths } "
293+ )
294+
295+ # Verify each file has correct content
296+ expected_contents = {
297+ "file1.txt" : "Content of file 1" ,
298+ "file2.txt" : "Content of file 2" ,
299+ "file3.txt" : "Content of file 3" ,
300+ }
301+
302+ for file_entry in files :
303+ path = file_entry ["path" ]
304+ assert file_entry ["kind" ] == "file" , f"{ path } should be a file"
305+
306+ file_id = file_entry .get ("file_id" )
307+ assert isinstance (file_id , str ), f"{ path } should have a file_id"
308+
309+ # Download and verify content
310+ download_response = client .get (f"/v1/files/{ file_id } " )
311+ assert download_response .status_code == 200 , (
312+ f"Failed to download { path } : { download_response .text } "
313+ )
314+
315+ content = download_response .content .decode ("utf-8" )
316+ expected_content = expected_contents [path ]
317+ assert content == expected_content , (
318+ f"Content mismatch for { path } . Expected: { expected_content !r} , Got: { content !r} "
319+ )
0 commit comments