-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathtest_basic_flow.py
More file actions
319 lines (245 loc) · 11.7 KB
/
test_basic_flow.py
File metadata and controls
319 lines (245 loc) · 11.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
from __future__ import annotations
from typing import Any, Final
import httpx
import pytest
BASE_URL: Final[str] = "http://localhost:8000"
def test_execute_endpoint_basic_flow() -> None:
timeout = httpx.Timeout(5.0, connect=5.0)
with httpx.Client(base_url=BASE_URL, timeout=timeout) as client:
try:
health_response = client.get("/health")
except httpx.TransportError as exc: # pragma: no cover - network failure path
pytest.fail(f"Failed to reach Code Interpreter service at {BASE_URL}: {exc!s}")
assert health_response.status_code == 200, health_response.text
assert health_response.json()["status"] == "ok"
execute_payload: dict[str, Any] = {
"code": "print('hello from e2e')",
"stdin": None,
"timeout_ms": 1000,
"files": [],
}
try:
execute_response = client.post("/v1/execute", json=execute_payload)
except httpx.TransportError as exc: # pragma: no cover - network failure path
pytest.fail(f"Failed to reach Code Interpreter service at {BASE_URL}: {exc!s}")
assert execute_response.status_code == 200, execute_response.text
result = execute_response.json()
# Create a detailed error message with the full result for debugging
error_msg = f"Test failed. Full result: {result}"
assert result["stdout"] == "hello from e2e\n", f"stdout mismatch. {error_msg}"
assert result["stderr"] == "", f"stderr mismatch. {error_msg}"
assert result["exit_code"] == 0, f"exit_code mismatch. {error_msg}"
assert result["timed_out"] is False, f"timed_out mismatch. {error_msg}"
assert isinstance(result["duration_ms"], int), f"duration_ms type mismatch. {error_msg}"
assert result["duration_ms"] >= 0, f"duration_ms value invalid. {error_msg}"
assert isinstance(result["files"], list), f"files type mismatch. {error_msg}"
def test_execute_edits_passed_file() -> None:
timeout = httpx.Timeout(5.0, connect=5.0)
with httpx.Client(base_url=BASE_URL, timeout=timeout) as client:
# First check health
try:
health_response = client.get("/health")
except httpx.TransportError as exc: # pragma: no cover - network failure path
pytest.fail(f"Failed to reach Code Interpreter service at {BASE_URL}: {exc!s}")
assert health_response.status_code == 200, health_response.text
# Upload the file to be edited
initial_content = "Hello World\nThis is line 2\nThis is line 3"
upload_files = {"file": ("input.txt", initial_content.encode("utf-8"), "text/plain")}
try:
upload_response = client.post("/v1/files", files=upload_files)
except httpx.TransportError as exc: # pragma: no cover - network failure path
pytest.fail(f"Failed to reach Code Interpreter service at {BASE_URL}: {exc!s}")
assert upload_response.status_code == 201, upload_response.text
file_id = upload_response.json()["file_id"]
execute_payload: dict[str, Any] = {
"code": """
from pathlib import Path
# Read the existing file
content = Path('input.txt').read_text()
print(f"Original content length: {len(content)}")
# Edit the file by appending a new line
edited_content = content + "\\nThis is a new line added by code"
Path('input.txt').write_text(edited_content)
# Read back to verify
final_content = Path('input.txt').read_text()
print(f"Final content length: {len(final_content)}")
print("File edited successfully")
""".strip(),
"stdin": None,
"timeout_ms": 2000,
"files": [
{
"path": "input.txt",
"file_id": file_id,
}
],
}
try:
execute_response = client.post("/v1/execute", json=execute_payload)
except httpx.TransportError as exc: # pragma: no cover - network failure path
pytest.fail(f"Failed to reach Code Interpreter service at {BASE_URL}: {exc!s}")
assert execute_response.status_code == 200, execute_response.text
result = execute_response.json()
# Verify execution succeeded
assert result["exit_code"] == 0, f"Execution failed: {result}"
assert result["timed_out"] is False
assert "File edited successfully" in result["stdout"]
# Find the edited file in the response
files = result.get("files", [])
edited_file = None
for file_entry in files:
if file_entry.get("path") == "input.txt":
edited_file = file_entry
break
assert edited_file is not None, "input.txt not found in response files"
assert edited_file["kind"] == "file"
# Get the file_id to download the edited file
file_id = edited_file.get("file_id")
assert isinstance(file_id, str), "file_id should be present"
# Download the file using the file_id
download_response = client.get(f"/v1/files/{file_id}")
assert download_response.status_code == 200, (
f"Failed to download file: {download_response.text}"
)
returned_content = download_response.content.decode("utf-8")
expected_content = initial_content + "\nThis is a new line added by code"
assert returned_content == expected_content, (
f"Content mismatch. Expected: {expected_content!r}, Got: {returned_content!r}"
)
def test_matplotlib_sine_wave_plot() -> None:
timeout = httpx.Timeout(10.0, connect=5.0)
with httpx.Client(base_url=BASE_URL, timeout=timeout) as client:
# First check health
try:
health_response = client.get("/health")
except httpx.TransportError as exc: # pragma: no cover - network failure path
pytest.fail(f"Failed to reach Code Interpreter service at {BASE_URL}: {exc!s}")
assert health_response.status_code == 200, health_response.text
code = """
import matplotlib
matplotlib.use('Agg') # Use non-interactive backend
import matplotlib.pyplot as plt
import numpy as np
# Generate data
x = np.linspace(0, 10, 100)
y = np.sin(x)
# Create plot
plt.figure(figsize=(10, 6))
plt.plot(x, y)
plt.title('Sine Wave')
plt.xlabel('x')
plt.ylabel('sin(x)')
plt.grid(True)
# Save plot
plt.savefig('sine_wave.png')
plt.close()
print("Plot saved successfully")
""".strip()
execute_payload: dict[str, Any] = {
"code": code,
"stdin": None,
"timeout_ms": 5000,
"files": [],
}
try:
execute_response = client.post("/v1/execute", json=execute_payload)
except httpx.TransportError as exc: # pragma: no cover - network failure path
pytest.fail(f"Failed to reach Code Interpreter service at {BASE_URL}: {exc!s}")
assert execute_response.status_code == 200, execute_response.text
result = execute_response.json()
# Verify execution succeeded
assert result["stdout"] == "Plot saved successfully\n", f"stdout mismatch: {result}"
assert result["stderr"] == "", f"stderr should be empty: {result}"
assert result["exit_code"] == 0, f"exit_code should be 0: {result}"
assert result["timed_out"] is False, f"should not timeout: {result}"
# Verify the PNG file was created and returned
files = result.get("files")
assert isinstance(files, list), "files should be a list"
# Find the sine_wave.png file
png_file = None
for file_entry in files:
if isinstance(file_entry, dict) and file_entry.get("path") == "sine_wave.png":
png_file = file_entry
break
assert png_file is not None, f"sine_wave.png not found in response files: {files}"
assert png_file["kind"] == "file"
# Verify the file has a file_id
file_id = png_file.get("file_id")
assert isinstance(file_id, str), "file_id should be present"
# Download the file and verify it's a valid PNG
download_response = client.get(f"/v1/files/{file_id}")
assert download_response.status_code == 200, (
f"Failed to download file: {download_response.text}"
)
png_bytes = download_response.content
# PNG files start with these magic bytes
assert png_bytes[:8] == b"\x89PNG\r\n\x1a\n", "File should be a valid PNG"
# Verify the file has reasonable size (should be several KB for a plot)
assert len(png_bytes) > 1000, f"PNG file too small: {len(png_bytes)} bytes"
def test_create_multiple_files() -> None:
timeout = httpx.Timeout(5.0, connect=5.0)
with httpx.Client(base_url=BASE_URL, timeout=timeout) as client:
# First check health
try:
health_response = client.get("/health")
except httpx.TransportError as exc: # pragma: no cover - network failure path
pytest.fail(f"Failed to reach Code Interpreter service at {BASE_URL}: {exc!s}")
assert health_response.status_code == 200, health_response.text
code = """
# Create multiple files
with open('file1.txt', 'w') as f:
f.write('Content of file 1')
with open('file2.txt', 'w') as f:
f.write('Content of file 2')
with open('file3.txt', 'w') as f:
f.write('Content of file 3')
print("Created 3 files")
""".strip()
execute_payload: dict[str, Any] = {
"code": code,
"stdin": None,
"timeout_ms": 2000,
"files": [],
}
try:
execute_response = client.post("/v1/execute", json=execute_payload)
except httpx.TransportError as exc: # pragma: no cover - network failure path
pytest.fail(f"Failed to reach Code Interpreter service at {BASE_URL}: {exc!s}")
assert execute_response.status_code == 200, execute_response.text
result = execute_response.json()
# Verify execution succeeded
assert result["stdout"] == "Created 3 files\n", f"stdout mismatch: {result}"
assert result["stderr"] == "", f"stderr should be empty: {result}"
assert result["exit_code"] == 0, f"exit_code should be 0: {result}"
assert result["timed_out"] is False, f"should not timeout: {result}"
# Verify all three files were created and returned
files = result.get("files")
assert isinstance(files, list), "files should be a list"
assert len(files) == 3, f"Expected 3 files, got {len(files)}: {files}"
# Check that all expected files are present
file_paths = {file_entry["path"] for file_entry in files}
expected_paths = {"file1.txt", "file2.txt", "file3.txt"}
assert file_paths == expected_paths, (
f"File paths mismatch. Expected: {expected_paths}, Got: {file_paths}"
)
# Verify each file has correct content
expected_contents = {
"file1.txt": "Content of file 1",
"file2.txt": "Content of file 2",
"file3.txt": "Content of file 3",
}
for file_entry in files:
path = file_entry["path"]
assert file_entry["kind"] == "file", f"{path} should be a file"
file_id = file_entry.get("file_id")
assert isinstance(file_id, str), f"{path} should have a file_id"
# Download and verify content
download_response = client.get(f"/v1/files/{file_id}")
assert download_response.status_code == 200, (
f"Failed to download {path}: {download_response.text}"
)
content = download_response.content.decode("utf-8")
expected_content = expected_contents[path]
assert content == expected_content, (
f"Content mismatch for {path}. Expected: {expected_content!r}, Got: {content!r}"
)