Skip to content

Commit 7958f58

Browse files
committed
end to end tests
1 parent 35f963d commit 7958f58

File tree

8 files changed

+190
-118
lines changed

8 files changed

+190
-118
lines changed

tests/smoketests/sdk/test_async_blueprint.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ async def test_create_devbox_from_blueprint(self, async_sdk_client: AsyncRunloop
222222
try:
223223
# Create devbox from the blueprint
224224
devbox = await async_sdk_client.devbox.create_from_blueprint_id(
225-
blueprint.id,
225+
blueprint_id=blueprint.id,
226226
name=unique_name("sdk-async-devbox-from-blueprint"),
227227
launch_parameters={"resource_size_request": "SMALL", "keep_alive_time_seconds": 60 * 5},
228228
)
@@ -235,9 +235,10 @@ async def test_create_devbox_from_blueprint(self, async_sdk_client: AsyncRunloop
235235
assert info.status == "running"
236236

237237
# Verify the blueprint's software is installed
238-
result = await devbox.cmd.exec("which python3")
238+
result = await devbox.cmd.exec(command="which python3")
239239
assert result.exit_code == 0
240240
assert result.success is True
241+
assert "python" in await result.stdout(num_lines=1)
241242
finally:
242243
await devbox.shutdown()
243244
finally:
@@ -255,14 +256,14 @@ async def test_create_multiple_devboxes_from_blueprint(self, async_sdk_client: A
255256
try:
256257
# Create first devbox
257258
devbox1 = await async_sdk_client.devbox.create_from_blueprint_id(
258-
blueprint.id,
259+
blueprint_id=blueprint.id,
259260
name=unique_name("sdk-async-devbox-1"),
260261
launch_parameters={"resource_size_request": "SMALL", "keep_alive_time_seconds": 60 * 5},
261262
)
262263

263264
# Create second devbox
264265
devbox2 = await async_sdk_client.devbox.create_from_blueprint_id(
265-
blueprint.id,
266+
blueprint_id=blueprint.id,
266267
name=unique_name("sdk-async-devbox-2"),
267268
launch_parameters={"resource_size_request": "SMALL", "keep_alive_time_seconds": 60 * 5},
268269
)

tests/smoketests/sdk/test_async_devbox.py

Lines changed: 60 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -106,27 +106,28 @@ class TestAsyncDevboxCommandExecution:
106106
@pytest.mark.timeout(THIRTY_SECOND_TIMEOUT)
107107
async def test_exec_simple_command(self, shared_devbox: AsyncDevbox) -> None:
108108
"""Test executing a simple command asynchronously."""
109-
result = await shared_devbox.cmd.exec("echo 'Hello from async SDK!'")
109+
result = await shared_devbox.cmd.exec(command="echo 'Hello from async SDK!'")
110110

111111
assert result is not None
112112
assert result.exit_code == 0
113113
assert result.success is True
114114

115-
stdout = await result.stdout()
115+
stdout = await result.stdout(num_lines=1)
116116
assert "Hello from async SDK!" in stdout
117117

118118
@pytest.mark.timeout(THIRTY_SECOND_TIMEOUT)
119119
async def test_exec_with_exit_code(self, shared_devbox: AsyncDevbox) -> None:
120120
"""Test command execution captures exit codes correctly."""
121-
result = await shared_devbox.cmd.exec("exit 42")
121+
result = await shared_devbox.cmd.exec(command="exit 42")
122122

123123
assert result.exit_code == 42
124124
assert result.success is False
125+
assert await result.stdout(num_lines=1) == ""
125126

126127
@pytest.mark.timeout(THIRTY_SECOND_TIMEOUT)
127128
async def test_exec_async_command(self, shared_devbox: AsyncDevbox) -> None:
128129
"""Test executing a command asynchronously with exec_async."""
129-
execution = await shared_devbox.cmd.exec_async("echo 'Async command' && sleep 1")
130+
execution = await shared_devbox.cmd.exec_async(command="echo 'Async command' && sleep 1")
130131

131132
assert execution is not None
132133
assert execution.execution_id is not None
@@ -136,7 +137,7 @@ async def test_exec_async_command(self, shared_devbox: AsyncDevbox) -> None:
136137
assert result.exit_code == 0
137138
assert result.success is True
138139

139-
stdout = await result.stdout()
140+
stdout = await result.stdout(num_lines=2)
140141
assert "Async command" in stdout
141142

142143
@pytest.mark.timeout(THIRTY_SECOND_TIMEOUT)
@@ -148,13 +149,16 @@ def stdout_callback(line: str) -> None:
148149
stdout_lines.append(line)
149150

150151
result = await shared_devbox.cmd.exec(
151-
'echo "line1" && echo "line2" && echo "line3"',
152+
command='echo "line1" && echo "line2" && echo "line3"',
152153
stdout=stdout_callback,
153154
)
154155

155156
assert result.success is True
156157
assert result.exit_code == 0
157158

159+
combined_stdout = await result.stdout(num_lines=3)
160+
assert "line1" in combined_stdout
161+
158162
# Verify callback received output
159163
assert len(stdout_lines) > 0
160164
stdout_combined = "".join(stdout_lines)
@@ -171,19 +175,36 @@ def stderr_callback(line: str) -> None:
171175
stderr_lines.append(line)
172176

173177
result = await shared_devbox.cmd.exec(
174-
'echo "error1" >&2 && echo "error2" >&2',
178+
command='echo "error1" >&2 && echo "error2" >&2',
175179
stderr=stderr_callback,
176180
)
177181

178182
assert result.success is True
179183
assert result.exit_code == 0
180184

185+
combined_stderr = await result.stderr(num_lines=2)
186+
assert "error1" in combined_stderr
187+
181188
# Verify callback received stderr output
182189
assert len(stderr_lines) > 0
183190
stderr_combined = "".join(stderr_lines)
184191
assert "error1" in stderr_combined
185192
assert "error2" in stderr_combined
186193

194+
@pytest.mark.timeout(THIRTY_SECOND_TIMEOUT)
195+
async def test_exec_with_large_stdout(self, shared_devbox: AsyncDevbox) -> None:
196+
"""Ensure we capture all stdout lines (similar to TS last_n coverage)."""
197+
result = await shared_devbox.cmd.exec(
198+
command="; ".join([f"echo line {i}" for i in range(1, 7)]),
199+
)
200+
201+
assert result.exit_code == 0
202+
lines = (await result.stdout()).strip().split("\n")
203+
assert lines == [f"line {i}" for i in range(1, 7)]
204+
205+
tail = (await result.stdout(num_lines=3)).strip().split("\n")
206+
assert tail == ["line 4", "line 5", "line 6"]
207+
187208
@pytest.mark.timeout(THIRTY_SECOND_TIMEOUT)
188209
async def test_exec_with_output_callback(self, shared_devbox: AsyncDevbox) -> None:
189210
"""Test command execution with combined output callback."""
@@ -193,13 +214,16 @@ def output_callback(line: str) -> None:
193214
output_lines.append(line)
194215

195216
result = await shared_devbox.cmd.exec(
196-
'echo "stdout1" && echo "stderr1" >&2 && echo "stdout2"',
217+
command='echo "stdout1" && echo "stderr1" >&2 && echo "stdout2"',
197218
output=output_callback,
198219
)
199220

200221
assert result.success is True
201222
assert result.exit_code == 0
202223

224+
stdout_capture = await result.stdout(num_lines=2)
225+
assert "stdout1" in stdout_capture or "stdout2" in stdout_capture
226+
203227
# Verify callback received both stdout and stderr
204228
assert len(output_lines) > 0
205229
output_combined = "".join(output_lines)
@@ -214,7 +238,7 @@ def stdout_callback(line: str) -> None:
214238
stdout_lines.append(line)
215239

216240
execution = await shared_devbox.cmd.exec_async(
217-
'echo "async output"',
241+
command='echo "async output"',
218242
stdout=stdout_callback,
219243
)
220244

@@ -225,6 +249,9 @@ def stdout_callback(line: str) -> None:
225249
assert result.success is True
226250
assert result.exit_code == 0
227251

252+
async_stdout = await result.stdout(num_lines=1)
253+
assert "async output" in async_stdout
254+
228255
# Verify streaming captured output
229256
assert len(stdout_lines) > 0
230257
stdout_combined = "".join(stdout_lines)
@@ -241,10 +268,10 @@ async def test_file_write_and_read(self, shared_devbox: AsyncDevbox) -> None:
241268
content = "Hello from async SDK file operations!"
242269

243270
# Write file
244-
await shared_devbox.file.write(file_path, content)
271+
await shared_devbox.file.write(file_path=file_path, contents=content)
245272

246273
# Read file
247-
read_content = await shared_devbox.file.read(file_path)
274+
read_content = await shared_devbox.file.read(file_path=file_path)
248275
assert read_content == content
249276

250277
@pytest.mark.timeout(THIRTY_SECOND_TIMEOUT)
@@ -254,10 +281,10 @@ async def test_file_write_bytes(self, shared_devbox: AsyncDevbox) -> None:
254281
content = b"Binary content from async SDK"
255282

256283
# Write bytes
257-
await shared_devbox.file.write(file_path, content)
284+
await shared_devbox.file.write(file_path=file_path, contents=content.decode("utf-8"))
258285

259286
# Read and verify
260-
read_content = await shared_devbox.file.read(file_path)
287+
read_content = await shared_devbox.file.read(file_path=file_path)
261288
assert read_content == content.decode("utf-8")
262289

263290
@pytest.mark.timeout(THIRTY_SECOND_TIMEOUT)
@@ -267,10 +294,10 @@ async def test_file_download(self, shared_devbox: AsyncDevbox) -> None:
267294
content = "Content to download"
268295

269296
# Write file first
270-
await shared_devbox.file.write(file_path, content)
297+
await shared_devbox.file.write(file_path=file_path, contents=content)
271298

272299
# Download file
273-
downloaded = await shared_devbox.file.download(file_path)
300+
downloaded = await shared_devbox.file.download(path=file_path)
274301
assert isinstance(downloaded, bytes)
275302
assert downloaded.decode("utf-8") == content
276303

@@ -285,10 +312,10 @@ async def test_file_upload(self, shared_devbox: AsyncDevbox) -> None:
285312
try:
286313
# Upload file
287314
remote_path = "~/uploaded_async_test.txt"
288-
await shared_devbox.file.upload(remote_path, Path(tmp_path))
315+
await shared_devbox.file.upload(path=remote_path, file=Path(tmp_path))
289316

290317
# Verify by reading
291-
content = await shared_devbox.file.read(remote_path)
318+
content = await shared_devbox.file.read(file_path=remote_path)
292319
assert content == "Uploaded content from async SDK"
293320
finally:
294321
# Cleanup temp file
@@ -309,6 +336,10 @@ async def test_suspend_and_resume(self, async_sdk_client: AsyncRunloopSDK) -> No
309336
try:
310337
# Suspend the devbox
311338
suspended_info = await devbox.suspend()
339+
if suspended_info.status != "suspended":
340+
suspended_info = await devbox.await_suspended(
341+
polling_config=PollingConfig(timeout_seconds=120.0, interval_seconds=5.0)
342+
)
312343
assert suspended_info.status == "suspended"
313344

314345
# Verify suspended state
@@ -317,6 +348,10 @@ async def test_suspend_and_resume(self, async_sdk_client: AsyncRunloopSDK) -> No
317348

318349
# Resume the devbox
319350
resumed_info = await devbox.resume()
351+
if resumed_info.status != "running":
352+
resumed_info = await devbox.await_running(
353+
polling_config=PollingConfig(timeout_seconds=120.0, interval_seconds=5.0)
354+
)
320355
assert resumed_info.status == "running"
321356

322357
# Verify running state
@@ -402,7 +437,7 @@ async def test_create_from_blueprint_id(self, async_sdk_client: AsyncRunloopSDK)
402437
try:
403438
# Create devbox from blueprint
404439
devbox = await async_sdk_client.devbox.create_from_blueprint_id(
405-
blueprint.id,
440+
blueprint_id=blueprint.id,
406441
name=unique_name("sdk-async-devbox-from-blueprint-id"),
407442
launch_parameters={"resource_size_request": "SMALL", "keep_alive_time_seconds": 60 * 5},
408443
)
@@ -430,7 +465,7 @@ async def test_create_from_blueprint_name(self, async_sdk_client: AsyncRunloopSD
430465
try:
431466
# Create devbox from blueprint name
432467
devbox = await async_sdk_client.devbox.create_from_blueprint_name(
433-
blueprint_name,
468+
blueprint_name=blueprint_name,
434469
name=unique_name("sdk-async-devbox-from-blueprint-name"),
435470
launch_parameters={"resource_size_request": "SMALL", "keep_alive_time_seconds": 60 * 5},
436471
)
@@ -455,7 +490,9 @@ async def test_create_from_snapshot(self, async_sdk_client: AsyncRunloopSDK) ->
455490

456491
try:
457492
# Create a file in the devbox
458-
await source_devbox.file.write("/tmp/test_async_snapshot.txt", "Async snapshot test content")
493+
await source_devbox.file.write(
494+
file_path="/tmp/test_async_snapshot.txt", contents="Async snapshot test content"
495+
)
459496

460497
# Create snapshot
461498
snapshot = await source_devbox.snapshot_disk(
@@ -465,7 +502,7 @@ async def test_create_from_snapshot(self, async_sdk_client: AsyncRunloopSDK) ->
465502
try:
466503
# Create devbox from snapshot
467504
devbox = await async_sdk_client.devbox.create_from_snapshot(
468-
snapshot.id,
505+
snapshot_id=snapshot.id,
469506
name=unique_name("sdk-async-devbox-from-snapshot"),
470507
launch_parameters={"resource_size_request": "SMALL", "keep_alive_time_seconds": 60 * 5},
471508
)
@@ -476,7 +513,7 @@ async def test_create_from_snapshot(self, async_sdk_client: AsyncRunloopSDK) ->
476513
assert info.status == "running"
477514

478515
# Verify snapshot content is present
479-
content = await devbox.file.read("/tmp/test_async_snapshot.txt")
516+
content = await devbox.file.read(file_path="/tmp/test_async_snapshot.txt")
480517
assert content == "Async snapshot test content"
481518
finally:
482519
await devbox.shutdown()
@@ -532,7 +569,7 @@ async def test_snapshot_disk(self, async_sdk_client: AsyncRunloopSDK) -> None:
532569

533570
try:
534571
# Create a file to snapshot
535-
await devbox.file.write("/tmp/async_snapshot_test.txt", "Async snapshot content")
572+
await devbox.file.write(file_path="/tmp/async_snapshot_test.txt", contents="Async snapshot content")
536573

537574
# Create snapshot (waits for completion)
538575
snapshot = await devbox.snapshot_disk(

0 commit comments

Comments
 (0)