diff --git a/src/runloop_api_client/sdk/__init__.py b/src/runloop_api_client/sdk/__init__.py index 5773b9d53..170389e4c 100644 --- a/src/runloop_api_client/sdk/__init__.py +++ b/src/runloop_api_client/sdk/__init__.py @@ -22,20 +22,24 @@ from .scorer import Scorer from .scenario import Scenario from .snapshot import Snapshot +from .benchmark import Benchmark from .blueprint import Blueprint from .execution import Execution from .async_agent import AsyncAgent from .async_devbox import AsyncDevbox, AsyncNamedShell from .async_scorer import AsyncScorer from .scenario_run import ScenarioRun +from .benchmark_run import BenchmarkRun from .async_scenario import AsyncScenario from .async_snapshot import AsyncSnapshot from .storage_object import StorageObject +from .async_benchmark import AsyncBenchmark from .async_blueprint import AsyncBlueprint from .async_execution import AsyncExecution from .execution_result import ExecutionResult from .scenario_builder import ScenarioBuilder from .async_scenario_run import AsyncScenarioRun +from .async_benchmark_run import AsyncBenchmarkRun from .async_storage_object import AsyncStorageObject from .async_execution_result import AsyncExecutionResult from .async_scenario_builder import AsyncScenarioBuilder @@ -85,4 +89,8 @@ "AsyncStorageObject", "NamedShell", "AsyncNamedShell", + "BenchmarkRun", + "AsyncBenchmarkRun", + "Benchmark", + "AsyncBenchmark", ] diff --git a/src/runloop_api_client/sdk/_types.py b/src/runloop_api_client/sdk/_types.py index 6bf9da020..4685b3401 100644 --- a/src/runloop_api_client/sdk/_types.py +++ b/src/runloop_api_client/sdk/_types.py @@ -1,33 +1,39 @@ from typing import Union, Callable, Optional from typing_extensions import TypedDict +from ..types import ( + InputContext, + ScenarioView, + AgentListParams, + DevboxListParams, + ObjectListParams, + AgentCreateParams, + DevboxCreateParams, + ObjectCreateParams, + ScenarioListParams, + BlueprintListParams, + ObjectDownloadParams, + ScenarioUpdateParams, + BenchmarkUpdateParams, + BlueprintCreateParams, + DevboxUploadFileParams, + DevboxCreateTunnelParams, + DevboxDownloadFileParams, + DevboxRemoveTunnelParams, + DevboxSnapshotDiskParams, + DevboxReadFileContentsParams, + DevboxWriteFileContentsParams, +) from .._types import Body, Query, Headers, Timeout, NotGiven from ..lib.polling import PollingConfig from ..types.devboxes import DiskSnapshotListParams, DiskSnapshotUpdateParams from ..types.scenarios import ScorerListParams, ScorerCreateParams, ScorerUpdateParams, ScorerValidateParams from ..types.benchmarks import RunListScenarioRunsParams -from ..types.input_context import InputContext -from ..types.scenario_view import ScenarioView -from ..types.agent_list_params import AgentListParams -from ..types.devbox_list_params import DevboxListParams -from ..types.object_list_params import ObjectListParams -from ..types.agent_create_params import AgentCreateParams -from ..types.devbox_create_params import DevboxCreateParams, DevboxBaseCreateParams -from ..types.object_create_params import ObjectCreateParams -from ..types.scenario_list_params import ScenarioListParams -from ..types.blueprint_list_params import BlueprintListParams -from ..types.object_download_params import ObjectDownloadParams -from ..types.scenario_update_params import ScenarioUpdateParams -from ..types.blueprint_create_params import BlueprintCreateParams -from ..types.devbox_upload_file_params import DevboxUploadFileParams +from ..types.devbox_create_params import DevboxBaseCreateParams from ..types.scenario_start_run_params import ScenarioStartRunBaseParams -from ..types.devbox_create_tunnel_params import DevboxCreateTunnelParams -from ..types.devbox_download_file_params import DevboxDownloadFileParams +from ..types.benchmark_start_run_params import BenchmarkSelfStartRunParams +from ..types.benchmarks.run_list_params import RunSelfListParams from ..types.devbox_execute_async_params import DevboxNiceExecuteAsyncParams -from ..types.devbox_remove_tunnel_params import DevboxRemoveTunnelParams -from ..types.devbox_snapshot_disk_params import DevboxSnapshotDiskParams -from ..types.devbox_read_file_contents_params import DevboxReadFileContentsParams -from ..types.devbox_write_file_contents_params import DevboxWriteFileContentsParams LogCallback = Callable[[str], None] @@ -206,6 +212,17 @@ class ScenarioPreview(ScenarioView): """The input context for the Scenario.""" -# Benchmark Run params +class SDKBenchmarkUpdateParams(BenchmarkUpdateParams, LongRequestOptions): + pass + + +class SDKBenchmarkStartRunParams(BenchmarkSelfStartRunParams, LongRequestOptions): + pass + + +class SDKBenchmarkListRunsParams(RunSelfListParams, BaseRequestOptions): + pass + + class SDKBenchmarkRunListScenarioRunsParams(RunListScenarioRunsParams, BaseRequestOptions): pass diff --git a/src/runloop_api_client/sdk/async_benchmark.py b/src/runloop_api_client/sdk/async_benchmark.py new file mode 100644 index 000000000..63443e37b --- /dev/null +++ b/src/runloop_api_client/sdk/async_benchmark.py @@ -0,0 +1,164 @@ +"""AsyncBenchmark resource class for asynchronous operations.""" + +from __future__ import annotations + +from typing import List +from typing_extensions import Unpack, override + +from ..types import BenchmarkView +from ._types import ( + BaseRequestOptions, + LongRequestOptions, + SDKBenchmarkUpdateParams, + SDKBenchmarkListRunsParams, + SDKBenchmarkStartRunParams, +) +from .._types import SequenceNotStr +from .._client import AsyncRunloop +from .async_benchmark_run import AsyncBenchmarkRun + + +class AsyncBenchmark: + """A benchmark for evaluating agent performance across scenarios (async). + + Provides async methods for retrieving benchmark details, updating the benchmark, + managing scenarios, and starting benchmark runs. Obtain instances via + ``runloop.benchmark.from_id()`` or ``runloop.benchmark.list()``. + + Example: + >>> benchmark = runloop.benchmark.from_id("bmd_xxx") + >>> info = await benchmark.get_info() + >>> run = await benchmark.start_run(run_name="evaluation-v1") + >>> for scenario_id in info.scenario_ids: + ... scenario = await runloop.scenario.from_id(scenario_id) + ... scenario_run = await scenario.run(benchmark_run_id=run.id, run_name="evaluation-v1") + """ + + def __init__(self, client: AsyncRunloop, benchmark_id: str) -> None: + """Create an AsyncBenchmark instance. + + :param client: AsyncRunloop client instance + :type client: AsyncRunloop + :param benchmark_id: Benchmark ID + :type benchmark_id: str + """ + self._client = client + self._id = benchmark_id + + @override + def __repr__(self) -> str: + return f"" + + @property + def id(self) -> str: + """Return the benchmark ID. + + :return: Unique benchmark ID + :rtype: str + """ + return self._id + + async def get_info( + self, + **options: Unpack[BaseRequestOptions], + ) -> BenchmarkView: + """Retrieve current benchmark details. + + :param options: See :typeddict:`~runloop_api_client.sdk._types.BaseRequestOptions` for available options + :return: Current benchmark info + :rtype: BenchmarkView + """ + return await self._client.benchmarks.retrieve( + self._id, + **options, + ) + + async def update( + self, + **params: Unpack[SDKBenchmarkUpdateParams], + ) -> BenchmarkView: + """Update the benchmark. + + Only provided fields will be updated. + + :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKBenchmarkUpdateParams` for available parameters + :return: Updated benchmark info + :rtype: BenchmarkView + """ + return await self._client.benchmarks.update( + self._id, + **params, + ) + + async def start_run( + self, + **params: Unpack[SDKBenchmarkStartRunParams], + ) -> AsyncBenchmarkRun: + """Start a new benchmark run. + + Creates a new benchmark run and returns an AsyncBenchmarkRun instance for + managing the run lifecycle. + + :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKBenchmarkStartRunParams` for available parameters + :return: AsyncBenchmarkRun instance for managing the run + :rtype: AsyncBenchmarkRun + """ + run_view = await self._client.benchmarks.start_run( + benchmark_id=self._id, + **params, + ) + return AsyncBenchmarkRun(self._client, run_view.id, run_view.benchmark_id) + + async def add_scenarios( + self, + scenario_ids: SequenceNotStr[str], + **options: Unpack[LongRequestOptions], + ) -> BenchmarkView: + """Add scenarios to the benchmark. + + :param scenario_ids: List of scenario IDs to add + :type scenario_ids: SequenceNotStr[str] + :param options: See :typeddict:`~runloop_api_client.sdk._types.LongRequestOptions` for available options + :return: Updated benchmark info + :rtype: BenchmarkView + """ + return await self._client.benchmarks.update_scenarios( + self._id, + scenarios_to_add=scenario_ids, + **options, + ) + + async def remove_scenarios( + self, + scenario_ids: SequenceNotStr[str], + **options: Unpack[LongRequestOptions], + ) -> BenchmarkView: + """Remove scenarios from the benchmark. + + :param scenario_ids: List of scenario IDs to remove + :type scenario_ids: SequenceNotStr[str] + :param options: See :typeddict:`~runloop_api_client.sdk._types.LongRequestOptions` for available options + :return: Updated benchmark info + :rtype: BenchmarkView + """ + return await self._client.benchmarks.update_scenarios( + self._id, + scenarios_to_remove=scenario_ids, + **options, + ) + + async def list_runs( + self, + **params: Unpack[SDKBenchmarkListRunsParams], + ) -> List[AsyncBenchmarkRun]: + """List all runs for this benchmark. + + :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKBenchmarkListRunsParams` for available parameters + :return: List of async benchmark runs + :rtype: List[AsyncBenchmarkRun] + """ + page = await self._client.benchmarks.runs.list( + benchmark_id=self._id, + **params, + ) + return [AsyncBenchmarkRun(self._client, run.id, run.benchmark_id) for run in page.runs] diff --git a/src/runloop_api_client/sdk/async_benchmark_run.py b/src/runloop_api_client/sdk/async_benchmark_run.py index fed2f5b00..f498d1408 100644 --- a/src/runloop_api_client/sdk/async_benchmark_run.py +++ b/src/runloop_api_client/sdk/async_benchmark_run.py @@ -16,11 +16,11 @@ class AsyncBenchmarkRun: Provides async methods for monitoring run status, managing the run lifecycle, and accessing scenario run results. Obtain instances via - ``benchmark.run()`` or ``benchmark.list_runs()``. + ``benchmark.start_run()`` or ``benchmark.list_runs()``. Example: >>> benchmark = runloop.benchmark.from_id("bench-xxx") - >>> run = await benchmark.run(run_name="evaluation-v1") + >>> run = await benchmark.start_run(run_name="evaluation-v1") >>> info = await run.get_info() >>> scenario_runs = await run.list_scenario_runs() """ diff --git a/src/runloop_api_client/sdk/benchmark.py b/src/runloop_api_client/sdk/benchmark.py new file mode 100644 index 000000000..7e8ed826d --- /dev/null +++ b/src/runloop_api_client/sdk/benchmark.py @@ -0,0 +1,164 @@ +"""Benchmark resource class for synchronous operations.""" + +from __future__ import annotations + +from typing import List +from typing_extensions import Unpack, override + +from ..types import BenchmarkView +from ._types import ( + BaseRequestOptions, + LongRequestOptions, + SDKBenchmarkUpdateParams, + SDKBenchmarkListRunsParams, + SDKBenchmarkStartRunParams, +) +from .._types import SequenceNotStr +from .._client import Runloop +from .benchmark_run import BenchmarkRun + + +class Benchmark: + """A benchmark for evaluating agent performance across scenarios. + + Provides methods for retrieving benchmark details, updating the benchmark, + managing scenarios, and starting benchmark runs. Obtain instances via + ``runloop.benchmark.from_id()`` or ``runloop.benchmark.list()``. + + Example: + >>> benchmark = runloop.benchmark.from_id("bmd_xxx") + >>> info = benchmark.get_info() + >>> run = benchmark.start_run(run_name="evaluation-v1") + >>> for scenario_id in info.scenario_ids: + ... scenario = runloop.scenario.from_id(scenario_id) + ... scenario_run = scenario.run(benchmark_run_id=run.id, run_name="evaluation-v1") + """ + + def __init__(self, client: Runloop, benchmark_id: str) -> None: + """Create a Benchmark instance. + + :param client: Runloop client instance + :type client: Runloop + :param benchmark_id: Benchmark ID + :type benchmark_id: str + """ + self._client = client + self._id = benchmark_id + + @override + def __repr__(self) -> str: + return f"" + + @property + def id(self) -> str: + """Return the benchmark ID. + + :return: Unique benchmark ID + :rtype: str + """ + return self._id + + def get_info( + self, + **options: Unpack[BaseRequestOptions], + ) -> BenchmarkView: + """Retrieve current benchmark details. + + :param options: See :typeddict:`~runloop_api_client.sdk._types.BaseRequestOptions` for available options + :return: Current benchmark info + :rtype: BenchmarkView + """ + return self._client.benchmarks.retrieve( + self._id, + **options, + ) + + def update( + self, + **params: Unpack[SDKBenchmarkUpdateParams], + ) -> BenchmarkView: + """Update the benchmark. + + Only provided fields will be updated. + + :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKBenchmarkUpdateParams` for available parameters + :return: Updated benchmark info + :rtype: BenchmarkView + """ + return self._client.benchmarks.update( + self._id, + **params, + ) + + def start_run( + self, + **params: Unpack[SDKBenchmarkStartRunParams], + ) -> BenchmarkRun: + """Start a new benchmark run. + + Creates a new benchmark run and returns a BenchmarkRun instance for + managing the run lifecycle. + + :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKBenchmarkStartRunParams` for available parameters + :return: BenchmarkRun instance for managing the run + :rtype: BenchmarkRun + """ + run_view = self._client.benchmarks.start_run( + benchmark_id=self._id, + **params, + ) + return BenchmarkRun(self._client, run_view.id, run_view.benchmark_id) + + def add_scenarios( + self, + scenario_ids: SequenceNotStr[str], + **options: Unpack[LongRequestOptions], + ) -> BenchmarkView: + """Add scenarios to the benchmark. + + :param scenario_ids: List of scenario IDs to add + :type scenario_ids: SequenceNotStr[str] + :param options: See :typeddict:`~runloop_api_client.sdk._types.LongRequestOptions` for available options + :return: Updated benchmark info + :rtype: BenchmarkView + """ + return self._client.benchmarks.update_scenarios( + self._id, + scenarios_to_add=scenario_ids, + **options, + ) + + def remove_scenarios( + self, + scenario_ids: SequenceNotStr[str], + **options: Unpack[LongRequestOptions], + ) -> BenchmarkView: + """Remove scenarios from the benchmark. + + :param scenario_ids: List of scenario IDs to remove + :type scenario_ids: SequenceNotStr[str] + :param options: See :typeddict:`~runloop_api_client.sdk._types.LongRequestOptions` for available options + :return: Updated benchmark info + :rtype: BenchmarkView + """ + return self._client.benchmarks.update_scenarios( + self._id, + scenarios_to_remove=scenario_ids, + **options, + ) + + def list_runs( + self, + **params: Unpack[SDKBenchmarkListRunsParams], + ) -> List[BenchmarkRun]: + """List all runs for this benchmark. + + :param params: See :typeddict:`~runloop_api_client.sdk._types.SDKBenchmarkListRunsParams` for available parameters + :return: List of benchmark runs + :rtype: List[BenchmarkRun] + """ + page = self._client.benchmarks.runs.list( + benchmark_id=self._id, + **params, + ) + return [BenchmarkRun(self._client, run.id, run.benchmark_id) for run in page.runs] diff --git a/src/runloop_api_client/sdk/benchmark_run.py b/src/runloop_api_client/sdk/benchmark_run.py index ff6ed567a..10da7ba05 100644 --- a/src/runloop_api_client/sdk/benchmark_run.py +++ b/src/runloop_api_client/sdk/benchmark_run.py @@ -16,11 +16,11 @@ class BenchmarkRun: Provides methods for monitoring run status, managing the run lifecycle, and accessing scenario run results. Obtain instances via - ``benchmark.run()`` or ``benchmark.list_runs()``. + ``benchmark.start_run()`` or ``benchmark.list_runs()``. Example: >>> benchmark = runloop.benchmark.from_id("bench-xxx") - >>> run = benchmark.run(run_name="evaluation-v1") + >>> run = benchmark.start_run(run_name="evaluation-v1") >>> info = run.get_info() >>> scenario_runs = run.list_scenario_runs() """ diff --git a/src/runloop_api_client/types/benchmark_start_run_params.py b/src/runloop_api_client/types/benchmark_start_run_params.py index 7655ff5ad..edd65ca7c 100644 --- a/src/runloop_api_client/types/benchmark_start_run_params.py +++ b/src/runloop_api_client/types/benchmark_start_run_params.py @@ -11,10 +11,9 @@ __all__ = ["BenchmarkStartRunParams"] -class BenchmarkStartRunParams(TypedDict, total=False): - benchmark_id: Required[str] - """ID of the Benchmark to run.""" - +# Split into separate params so that OO SDK start_run params can omit the benchmark_id +# Neither of these params are exposed to the user, only the derived SDKBenchmarkStartRunParams +class BenchmarkSelfStartRunParams(TypedDict, total=False): metadata: Optional[Dict[str, str]] """User defined metadata to attach to the benchmark run for organization.""" @@ -23,3 +22,8 @@ class BenchmarkStartRunParams(TypedDict, total=False): run_profile: Annotated[Optional[RunProfile], PropertyInfo(alias="runProfile")] """Runtime configuration to use for this benchmark run""" + + +class BenchmarkStartRunParams(BenchmarkSelfStartRunParams, total=False): + benchmark_id: Required[str] + """ID of the Benchmark to run.""" diff --git a/src/runloop_api_client/types/benchmarks/run_list_params.py b/src/runloop_api_client/types/benchmarks/run_list_params.py index 072a0dbe1..a75e1b592 100644 --- a/src/runloop_api_client/types/benchmarks/run_list_params.py +++ b/src/runloop_api_client/types/benchmarks/run_list_params.py @@ -7,10 +7,9 @@ __all__ = ["RunListParams"] -class RunListParams(TypedDict, total=False): - benchmark_id: str - """The Benchmark ID to filter by.""" - +# Split into separate params so that OO SDK list_runs params can omit the benchmark_id +# Neither of these params are exposed to the user, only the derived SDKBenchmarkListRunsParams +class RunSelfListParams(TypedDict, total=False): limit: int """The limit of items to return. Default is 20. Max is 5000.""" @@ -19,3 +18,8 @@ class RunListParams(TypedDict, total=False): starting_after: str """Load the next page of data starting after the item with the given ID.""" + + +class RunListParams(RunSelfListParams, total=False): + benchmark_id: str + """The Benchmark ID to filter by.""" diff --git a/tests/sdk/async_devbox/test_core.py b/tests/sdk/async_devbox/test_core.py index 5d3405c80..9925fa724 100644 --- a/tests/sdk/async_devbox/test_core.py +++ b/tests/sdk/async_devbox/test_core.py @@ -26,21 +26,21 @@ class TestAsyncDevbox: def test_init(self, mock_async_client: AsyncMock) -> None: """Test AsyncDevbox initialization.""" - devbox = AsyncDevbox(mock_async_client, "dev_123") - assert devbox.id == "dev_123" + devbox = AsyncDevbox(mock_async_client, "dbx_123") + assert devbox.id == "dbx_123" def test_repr(self, mock_async_client: AsyncMock) -> None: """Test AsyncDevbox string representation.""" - devbox = AsyncDevbox(mock_async_client, "dev_123") - assert repr(devbox) == "" + devbox = AsyncDevbox(mock_async_client, "dbx_123") + assert repr(devbox) == "" @pytest.mark.asyncio async def test_context_manager_enter_exit(self, mock_async_client: AsyncMock, devbox_view: MockDevboxView) -> None: """Test context manager behavior with successful shutdown.""" mock_async_client.devboxes.shutdown = AsyncMock(return_value=devbox_view) - async with AsyncDevbox(mock_async_client, "dev_123") as devbox: - assert devbox.id == "dev_123" + async with AsyncDevbox(mock_async_client, "dbx_123") as devbox: + assert devbox.id == "dbx_123" call_kwargs = mock_async_client.devboxes.shutdown.call_args[1] assert "timeout" not in call_kwargs @@ -51,7 +51,7 @@ async def test_context_manager_exception_handling(self, mock_async_client: Async mock_async_client.devboxes.shutdown = AsyncMock(side_effect=RuntimeError("Shutdown failed")) with pytest.raises(ValueError, match="Test error"): - async with AsyncDevbox(mock_async_client, "dev_123"): + async with AsyncDevbox(mock_async_client, "dbx_123"): raise ValueError("Test error") # Shutdown should be called even when body raises exception @@ -62,7 +62,7 @@ async def test_get_info(self, mock_async_client: AsyncMock, devbox_view: MockDev """Test get_info method.""" mock_async_client.devboxes.retrieve = AsyncMock(return_value=devbox_view) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") result = await devbox.get_info( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -72,7 +72,7 @@ async def test_get_info(self, mock_async_client: AsyncMock, devbox_view: MockDev assert result == devbox_view mock_async_client.devboxes.retrieve.assert_called_once_with( - "dev_123", + "dbx_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, @@ -85,12 +85,12 @@ async def test_await_running(self, mock_async_client: AsyncMock, devbox_view: Mo mock_async_client.devboxes.await_running = AsyncMock(return_value=devbox_view) polling_config = PollingConfig(timeout_seconds=60.0) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") result = await devbox.await_running(polling_config=polling_config) assert result == devbox_view mock_async_client.devboxes.await_running.assert_called_once_with( - "dev_123", + "dbx_123", polling_config=polling_config, ) @@ -100,12 +100,12 @@ async def test_await_suspended(self, mock_async_client: AsyncMock, devbox_view: mock_async_client.devboxes.await_suspended = AsyncMock(return_value=devbox_view) polling_config = PollingConfig(timeout_seconds=60.0) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") result = await devbox.await_suspended(polling_config=polling_config) assert result == devbox_view mock_async_client.devboxes.await_suspended.assert_called_once_with( - "dev_123", + "dbx_123", polling_config=polling_config, ) @@ -114,7 +114,7 @@ async def test_shutdown(self, mock_async_client: AsyncMock, devbox_view: MockDev """Test shutdown method.""" mock_async_client.devboxes.shutdown = AsyncMock(return_value=devbox_view) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") result = await devbox.shutdown( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -125,7 +125,7 @@ async def test_shutdown(self, mock_async_client: AsyncMock, devbox_view: MockDev assert result == devbox_view mock_async_client.devboxes.shutdown.assert_called_once_with( - "dev_123", + "dbx_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, @@ -138,7 +138,7 @@ async def test_suspend(self, mock_async_client: AsyncMock, devbox_view: MockDevb """Test suspend method.""" mock_async_client.devboxes.suspend = AsyncMock(return_value=devbox_view) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") result = await devbox.suspend( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -149,7 +149,7 @@ async def test_suspend(self, mock_async_client: AsyncMock, devbox_view: MockDevb assert result == devbox_view mock_async_client.devboxes.suspend.assert_called_once_with( - "dev_123", + "dbx_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, @@ -162,7 +162,7 @@ async def test_resume(self, mock_async_client: AsyncMock, devbox_view: MockDevbo """Test resume method.""" mock_async_client.devboxes.resume = AsyncMock(return_value=devbox_view) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") result = await devbox.resume( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -173,7 +173,7 @@ async def test_resume(self, mock_async_client: AsyncMock, devbox_view: MockDevbo assert result == devbox_view mock_async_client.devboxes.resume.assert_called_once_with( - "dev_123", + "dbx_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, @@ -186,7 +186,7 @@ async def test_keep_alive(self, mock_async_client: AsyncMock) -> None: """Test keep_alive method.""" mock_async_client.devboxes.keep_alive = AsyncMock(return_value=object()) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") result = await devbox.keep_alive( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -197,7 +197,7 @@ async def test_keep_alive(self, mock_async_client: AsyncMock) -> None: assert result is not None # Verify return value is propagated mock_async_client.devboxes.keep_alive.assert_called_once_with( - "dev_123", + "dbx_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, @@ -208,13 +208,13 @@ async def test_keep_alive(self, mock_async_client: AsyncMock) -> None: @pytest.mark.asyncio async def test_snapshot_disk(self, mock_async_client: AsyncMock) -> None: """Test snapshot_disk waits for completion.""" - snapshot_data = SimpleNamespace(id="snap_123") + snapshot_data = SimpleNamespace(id="snp_123") snapshot_status = SimpleNamespace(status="completed") mock_async_client.devboxes.snapshot_disk_async = AsyncMock(return_value=snapshot_data) mock_async_client.devboxes.disk_snapshots.await_completed = AsyncMock(return_value=snapshot_status) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") polling_config = PollingConfig(timeout_seconds=60.0) snapshot = await devbox.snapshot_disk( name="test-snapshot", @@ -223,7 +223,7 @@ async def test_snapshot_disk(self, mock_async_client: AsyncMock) -> None: extra_headers={"X-Custom": "value"}, ) - assert snapshot.id == "snap_123" + assert snapshot.id == "snp_123" mock_async_client.devboxes.snapshot_disk_async.assert_called_once() call_kwargs = mock_async_client.devboxes.snapshot_disk_async.call_args[1] assert "commit_message" not in call_kwargs @@ -240,17 +240,17 @@ async def test_snapshot_disk(self, mock_async_client: AsyncMock) -> None: @pytest.mark.asyncio async def test_snapshot_disk_async(self, mock_async_client: AsyncMock) -> None: """Test snapshot_disk_async returns immediately.""" - snapshot_data = SimpleNamespace(id="snap_123") + snapshot_data = SimpleNamespace(id="snp_123") mock_async_client.devboxes.snapshot_disk_async = AsyncMock(return_value=snapshot_data) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") snapshot = await devbox.snapshot_disk_async( name="test-snapshot", metadata={"key": "value"}, extra_headers={"X-Custom": "value"}, ) - assert snapshot.id == "snap_123" + assert snapshot.id == "snp_123" mock_async_client.devboxes.snapshot_disk_async.assert_called_once() call_kwargs = mock_async_client.devboxes.snapshot_disk_async.call_args[1] assert "commit_message" not in call_kwargs @@ -265,7 +265,7 @@ async def test_close(self, mock_async_client: AsyncMock, devbox_view: MockDevbox """Test close method calls shutdown.""" mock_async_client.devboxes.shutdown = AsyncMock(return_value=devbox_view) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") await devbox.close() mock_async_client.devboxes.shutdown.assert_called_once() @@ -274,21 +274,21 @@ async def test_close(self, mock_async_client: AsyncMock, devbox_view: MockDevbox def test_cmd_property(self, mock_async_client: AsyncMock) -> None: """Test cmd property returns AsyncCommandInterface.""" - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") cmd = devbox.cmd assert isinstance(cmd, AsyncCommandInterface) assert cmd._devbox is devbox def test_file_property(self, mock_async_client: AsyncMock) -> None: """Test file property returns AsyncFileInterface.""" - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") file_interface = devbox.file assert isinstance(file_interface, AsyncFileInterface) assert file_interface._devbox is devbox def test_net_property(self, mock_async_client: AsyncMock) -> None: """Test net property returns AsyncNetworkInterface.""" - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") net = devbox.net assert isinstance(net, AsyncNetworkInterface) assert net._devbox is devbox diff --git a/tests/sdk/async_devbox/test_edge_cases.py b/tests/sdk/async_devbox/test_edge_cases.py index fa5b89c7a..94d9e661b 100644 --- a/tests/sdk/async_devbox/test_edge_cases.py +++ b/tests/sdk/async_devbox/test_edge_cases.py @@ -21,6 +21,6 @@ async def test_async_network_error(self, mock_async_client: AsyncMock) -> None: """Test handling of network errors in async.""" mock_async_client.devboxes.retrieve = AsyncMock(side_effect=httpx.NetworkError("Connection failed")) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") with pytest.raises(httpx.NetworkError): await devbox.get_info() diff --git a/tests/sdk/async_devbox/test_interfaces.py b/tests/sdk/async_devbox/test_interfaces.py index bcb2a306b..52c439c22 100644 --- a/tests/sdk/async_devbox/test_interfaces.py +++ b/tests/sdk/async_devbox/test_interfaces.py @@ -27,7 +27,7 @@ async def test_exec_without_callbacks( mock_async_client.devboxes.execute_async = AsyncMock(return_value=execution_view) mock_async_client.devboxes.executions.await_completed = AsyncMock(return_value=execution_view) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") result = await devbox.cmd.exec("echo hello") assert result.exit_code == 0 @@ -42,13 +42,13 @@ async def test_exec_without_callbacks( async def test_exec_with_stdout_callback(self, mock_async_client: AsyncMock, mock_async_stream: AsyncMock) -> None: """Test exec with stdout callback.""" execution_async = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", ) execution_completed = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="output", @@ -61,7 +61,7 @@ async def test_exec_with_stdout_callback(self, mock_async_client: AsyncMock, moc stdout_calls: list[str] = [] - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") result = await devbox.cmd.exec("echo hello", stdout=stdout_calls.append) assert result.exit_code == 0 @@ -73,19 +73,19 @@ async def test_exec_async_returns_execution( ) -> None: """Test exec_async returns AsyncExecution object.""" execution_async = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", ) mock_async_client.devboxes.execute_async = AsyncMock(return_value=execution_async) mock_async_client.devboxes.executions.stream_stdout_updates = AsyncMock(return_value=mock_async_stream) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") execution = await devbox.cmd.exec_async("long-running command") - assert execution.execution_id == "exec_123" - assert execution.devbox_id == "dev_123" + assert execution.execution_id == "exn_123" + assert execution.devbox_id == "dbx_123" mock_async_client.devboxes.execute_async.assert_called_once() @@ -97,7 +97,7 @@ async def test_read(self, mock_async_client: AsyncMock) -> None: """Test file read.""" mock_async_client.devboxes.read_file_contents = AsyncMock(return_value="file content") - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") result = await devbox.file.read(file_path="/path/to/file") assert result == "file content" @@ -109,7 +109,7 @@ async def test_write_string(self, mock_async_client: AsyncMock) -> None: execution_detail = SimpleNamespace() mock_async_client.devboxes.write_file_contents = AsyncMock(return_value=execution_detail) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") result = await devbox.file.write(file_path="/path/to/file", contents="content") assert result == execution_detail @@ -121,7 +121,7 @@ async def test_write_bytes(self, mock_async_client: AsyncMock) -> None: execution_detail = SimpleNamespace() mock_async_client.devboxes.write_file_contents = AsyncMock(return_value=execution_detail) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") result = await devbox.file.write(file_path="/path/to/file", contents="content") assert result == execution_detail @@ -134,7 +134,7 @@ async def test_download(self, mock_async_client: AsyncMock) -> None: mock_response.read = AsyncMock(return_value=b"file content") mock_async_client.devboxes.download_file = AsyncMock(return_value=mock_response) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") result = await devbox.file.download(path="/path/to/file") assert result == b"file content" @@ -146,7 +146,7 @@ async def test_upload(self, mock_async_client: AsyncMock, tmp_path: Path) -> Non execution_detail = SimpleNamespace() mock_async_client.devboxes.upload_file = AsyncMock(return_value=execution_detail) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") # Create a temporary file for upload temp_file = tmp_path / "test_file.txt" temp_file.write_text("test content") @@ -166,7 +166,7 @@ async def test_create_ssh_key(self, mock_async_client: AsyncMock) -> None: ssh_key_response = SimpleNamespace(public_key="ssh-rsa ...") mock_async_client.devboxes.create_ssh_key = AsyncMock(return_value=ssh_key_response) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") result = await devbox.net.create_ssh_key( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -184,7 +184,7 @@ async def test_create_tunnel(self, mock_async_client: AsyncMock) -> None: tunnel_view = SimpleNamespace(tunnel_id="tunnel_123") mock_async_client.devboxes.create_tunnel = AsyncMock(return_value=tunnel_view) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") result = await devbox.net.create_tunnel( port=8080, extra_headers={"X-Custom": "value"}, @@ -202,7 +202,7 @@ async def test_remove_tunnel(self, mock_async_client: AsyncMock) -> None: """Test remove tunnel.""" mock_async_client.devboxes.remove_tunnel = AsyncMock(return_value=object()) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") result = await devbox.net.remove_tunnel( port=8080, extra_headers={"X-Custom": "value"}, diff --git a/tests/sdk/async_devbox/test_streaming.py b/tests/sdk/async_devbox/test_streaming.py index cd33a8f26..3bb3e1a7b 100644 --- a/tests/sdk/async_devbox/test_streaming.py +++ b/tests/sdk/async_devbox/test_streaming.py @@ -25,8 +25,8 @@ class TestAsyncDevboxStreaming: def test_start_streaming_no_callbacks(self, mock_async_client: AsyncMock) -> None: """Test _start_streaming returns None when no callbacks.""" - devbox = AsyncDevbox(mock_async_client, "dev_123") - result = devbox._start_streaming("exec_123", stdout=None, stderr=None, output=None) + devbox = AsyncDevbox(mock_async_client, "dbx_123") + result = devbox._start_streaming("exn_123", stdout=None, stderr=None, output=None) assert result is None @pytest.mark.asyncio @@ -46,9 +46,9 @@ async def async_iter(): mock_async_client.devboxes.executions.stream_stdout_updates = AsyncMock(return_value=mock_async_stream) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") stdout_calls: list[str] = [] - result = devbox._start_streaming("exec_123", stdout=stdout_calls.append, stderr=None, output=None) + result = devbox._start_streaming("exn_123", stdout=stdout_calls.append, stderr=None, output=None) assert result is not None assert isinstance(result, _AsyncStreamingGroup) @@ -76,9 +76,9 @@ async def async_iter(): mock_async_client.devboxes.executions.stream_stderr_updates = AsyncMock(return_value=mock_async_stream) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") stderr_calls: list[str] = [] - result = devbox._start_streaming("exec_123", stdout=None, stderr=stderr_calls.append, output=None) + result = devbox._start_streaming("exn_123", stdout=None, stderr=stderr_calls.append, output=None) assert result is not None assert isinstance(result, _AsyncStreamingGroup) @@ -107,9 +107,9 @@ async def async_iter(): mock_async_client.devboxes.executions.stream_stdout_updates = AsyncMock(return_value=mock_async_stream) mock_async_client.devboxes.executions.stream_stderr_updates = AsyncMock(return_value=mock_async_stream) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") output_calls: list[str] = [] - result = devbox._start_streaming("exec_123", stdout=None, stderr=None, output=output_calls.append) + result = devbox._start_streaming("exn_123", stdout=None, stderr=None, output=output_calls.append) assert result is not None assert isinstance(result, _AsyncStreamingGroup) @@ -136,7 +136,7 @@ async def async_iter() -> AsyncIterator[SimpleNamespace]: mock_async_stream.__aenter__ = AsyncMock(return_value=mock_async_stream) mock_async_stream.__aexit__ = AsyncMock(return_value=None) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") calls: list[str] = [] async def stream_factory() -> AsyncStream[ExecutionUpdateChunk]: @@ -166,7 +166,7 @@ async def async_iter() -> AsyncIterator[SimpleNamespace]: mock_async_stream.__aenter__ = AsyncMock(return_value=mock_async_stream) mock_async_stream.__aexit__ = AsyncMock(return_value=None) - devbox = AsyncDevbox(mock_async_client, "dev_123") + devbox = AsyncDevbox(mock_async_client, "dbx_123") calls: list[str] = [] async def stream_factory() -> AsyncStream[ExecutionUpdateChunk]: diff --git a/tests/sdk/conftest.py b/tests/sdk/conftest.py index 10ddf6254..f22b542c6 100644 --- a/tests/sdk/conftest.py +++ b/tests/sdk/conftest.py @@ -15,13 +15,17 @@ # Test ID constants TEST_IDS = { - "devbox": "dev_123", - "execution": "exec_123", - "snapshot": "snap_123", - "blueprint": "bp_123", + "devbox": "dbx_123", + "execution": "exn_123", + "snapshot": "snp_123", + "blueprint": "bpt_123", "object": "obj_123", - "scorer": "scorer_123", - "agent": "agent_123", + "scorer": "sco_123", + "agent": "agt_123", + "scenario": "scn_123", + "scenario_run": "scr_123", + "benchmark": "bmd_123", + "benchmark_run": "bmr_123", } # Test URL constants @@ -42,7 +46,7 @@ class MockDevboxView: """Mock DevboxView for testing.""" - id: str = "dev_123" + id: str = TEST_IDS["devbox"] status: str = "running" name: str = "test-devbox" @@ -51,8 +55,8 @@ class MockDevboxView: class MockExecutionView: """Mock DevboxAsyncExecutionDetailView for testing.""" - execution_id: str = "exec_123" - devbox_id: str = "dev_123" + execution_id: str = TEST_IDS["execution"] + devbox_id: str = TEST_IDS["devbox"] status: str = "completed" exit_status: int = 0 stdout: str = "output" @@ -65,7 +69,7 @@ class MockExecutionView: class MockSnapshotView: """Mock DevboxSnapshotView for testing.""" - id: str = "snap_123" + id: str = TEST_IDS["snapshot"] status: str = "completed" name: str = "test-snapshot" @@ -74,7 +78,7 @@ class MockSnapshotView: class MockBlueprintView: """Mock BlueprintView for testing.""" - id: str = "bp_123" + id: str = TEST_IDS["blueprint"] status: str = "built" name: str = "test-blueprint" @@ -83,7 +87,7 @@ class MockBlueprintView: class MockObjectView: """Mock ObjectView for testing.""" - id: str = "obj_123" + id: str = TEST_IDS["object"] upload_url: str = "https://upload.example.com/obj_123" name: str = "test-object" @@ -92,7 +96,7 @@ class MockObjectView: class MockScorerView: """Mock ScorerView for testing.""" - id: str = "scorer_123" + id: str = TEST_IDS["scorer"] bash_script: str = "echo 'score=1.0'" type: str = "test_scorer" @@ -101,7 +105,7 @@ class MockScorerView: class MockAgentView: """Mock AgentView for testing.""" - id: str = "agent_123" + id: str = TEST_IDS["agent"] name: str = "test-agent" create_time_ms: int = 1234567890000 is_public: bool = False @@ -112,7 +116,7 @@ class MockAgentView: class MockScenarioView: """Mock ScenarioView for testing.""" - id: str = "scn_123" + id: str = TEST_IDS["scenario"] name: str = "test-scenario" metadata: Dict[str, str] = field(default_factory=dict) @@ -121,20 +125,30 @@ class MockScenarioView: class MockScenarioRunView: """Mock ScenarioRunView for testing.""" - id: str = "run_123" - devbox_id: str = "dev_123" - scenario_id: str = "scn_123" + id: str = TEST_IDS["scenario_run"] + devbox_id: str = TEST_IDS["devbox"] + scenario_id: str = TEST_IDS["scenario"] state: str = "running" metadata: Dict[str, str] = field(default_factory=dict) scoring_contract_result: object = None +@dataclass +class MockBenchmarkView: + """Mock BenchmarkView for testing.""" + + id: str = TEST_IDS["benchmark"] + name: str = "test-benchmark" + metadata: Dict[str, str] = field(default_factory=dict) + scenario_ids: list[str] = field(default_factory=list) + + @dataclass class MockBenchmarkRunView: """Mock BenchmarkRunView for testing.""" - id: str = "bench_run_123" - benchmark_id: str = "bench_123" + id: str = TEST_IDS["benchmark_run"] + benchmark_id: str = TEST_IDS["benchmark"] state: str = "running" metadata: Dict[str, str] = field(default_factory=dict) start_time_ms: int = 1234567890000 @@ -261,6 +275,12 @@ def scenario_run_view() -> MockScenarioRunView: return MockScenarioRunView() +@pytest.fixture +def benchmark_view() -> MockBenchmarkView: + """Create a mock BenchmarkView.""" + return MockBenchmarkView() + + @pytest.fixture def benchmark_run_view() -> MockBenchmarkRunView: """Create a mock BenchmarkRunView.""" diff --git a/tests/sdk/devbox/test_core.py b/tests/sdk/devbox/test_core.py index b482e030b..c12b02485 100644 --- a/tests/sdk/devbox/test_core.py +++ b/tests/sdk/devbox/test_core.py @@ -29,20 +29,20 @@ class TestDevbox: def test_init(self, mock_client: Mock) -> None: """Test Devbox initialization.""" - devbox = Devbox(mock_client, "dev_123") - assert devbox.id == "dev_123" + devbox = Devbox(mock_client, "dbx_123") + assert devbox.id == "dbx_123" def test_repr(self, mock_client: Mock) -> None: """Test Devbox string representation.""" - devbox = Devbox(mock_client, "dev_123") - assert repr(devbox) == "" + devbox = Devbox(mock_client, "dbx_123") + assert repr(devbox) == "" def test_context_manager_enter_exit(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: """Test context manager behavior with successful shutdown.""" mock_client.devboxes.shutdown.return_value = devbox_view - with Devbox(mock_client, "dev_123") as devbox: - assert devbox.id == "dev_123" + with Devbox(mock_client, "dbx_123") as devbox: + assert devbox.id == "dbx_123" call_kwargs = mock_client.devboxes.shutdown.call_args[1] assert "timeout" not in call_kwargs @@ -52,7 +52,7 @@ def test_context_manager_exception_handling(self, mock_client: Mock) -> None: mock_client.devboxes.shutdown.side_effect = RuntimeError("Shutdown failed") with pytest.raises(ValueError, match="Test error"): - with Devbox(mock_client, "dev_123"): + with Devbox(mock_client, "dbx_123"): raise ValueError("Test error") # Shutdown should be called even when body raises exception @@ -62,7 +62,7 @@ def test_get_info(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: """Test get_info method.""" mock_client.devboxes.retrieve.return_value = devbox_view - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.get_info( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -72,7 +72,7 @@ def test_get_info(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: assert result == devbox_view mock_client.devboxes.retrieve.assert_called_once_with( - "dev_123", + "dbx_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, @@ -84,12 +84,12 @@ def test_await_running(self, mock_client: Mock, devbox_view: MockDevboxView) -> mock_client.devboxes.await_running.return_value = devbox_view polling_config = PollingConfig(timeout_seconds=60.0) - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.await_running(polling_config=polling_config) assert result == devbox_view mock_client.devboxes.await_running.assert_called_once_with( - "dev_123", + "dbx_123", polling_config=polling_config, ) @@ -98,12 +98,12 @@ def test_await_suspended(self, mock_client: Mock, devbox_view: MockDevboxView) - mock_client.devboxes.await_suspended.return_value = devbox_view polling_config = PollingConfig(timeout_seconds=60.0) - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.await_suspended(polling_config=polling_config) assert result == devbox_view mock_client.devboxes.await_suspended.assert_called_once_with( - "dev_123", + "dbx_123", polling_config=polling_config, ) @@ -111,7 +111,7 @@ def test_shutdown(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: """Test shutdown method.""" mock_client.devboxes.shutdown.return_value = devbox_view - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.shutdown( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -122,7 +122,7 @@ def test_shutdown(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: assert result == devbox_view mock_client.devboxes.shutdown.assert_called_once_with( - "dev_123", + "dbx_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, @@ -136,7 +136,7 @@ def test_suspend(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: mock_client.devboxes.await_suspended.return_value = devbox_view polling_config = PollingConfig(timeout_seconds=60.0) - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.suspend( polling_config=polling_config, extra_headers={"X-Custom": "value"}, @@ -148,7 +148,7 @@ def test_suspend(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: assert result == devbox_view mock_client.devboxes.suspend.assert_called_once_with( - "dev_123", + "dbx_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, @@ -156,7 +156,7 @@ def test_suspend(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: idempotency_key="key-123", ) mock_client.devboxes.await_suspended.assert_called_once_with( - "dev_123", + "dbx_123", polling_config=polling_config, ) @@ -166,7 +166,7 @@ def test_resume(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: mock_client.devboxes.await_running.return_value = devbox_view polling_config = PollingConfig(timeout_seconds=60.0) - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.resume( polling_config=polling_config, extra_headers={"X-Custom": "value"}, @@ -178,7 +178,7 @@ def test_resume(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: assert result == devbox_view mock_client.devboxes.resume.assert_called_once_with( - "dev_123", + "dbx_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, @@ -186,7 +186,7 @@ def test_resume(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: idempotency_key="key-123", ) mock_client.devboxes.await_running.assert_called_once_with( - "dev_123", + "dbx_123", polling_config=polling_config, ) @@ -194,7 +194,7 @@ def test_keep_alive(self, mock_client: Mock) -> None: """Test keep_alive method.""" mock_client.devboxes.keep_alive.return_value = object() - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.keep_alive( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -205,7 +205,7 @@ def test_keep_alive(self, mock_client: Mock) -> None: assert result is not None # Verify return value is propagated mock_client.devboxes.keep_alive.assert_called_once_with( - "dev_123", + "dbx_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, @@ -215,13 +215,13 @@ def test_keep_alive(self, mock_client: Mock) -> None: def test_snapshot_disk(self, mock_client: Mock) -> None: """Test snapshot_disk waits for completion.""" - snapshot_data = SimpleNamespace(id="snap_123") + snapshot_data = SimpleNamespace(id="snp_123") snapshot_status = SimpleNamespace(status="completed") mock_client.devboxes.snapshot_disk_async.return_value = snapshot_data mock_client.devboxes.disk_snapshots.await_completed.return_value = snapshot_status - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") polling_config = PollingConfig(timeout_seconds=60.0) snapshot = devbox.snapshot_disk( name="test-snapshot", @@ -230,7 +230,7 @@ def test_snapshot_disk(self, mock_client: Mock) -> None: extra_headers={"X-Custom": "value"}, ) - assert snapshot.id == "snap_123" + assert snapshot.id == "snp_123" call_kwargs = mock_client.devboxes.snapshot_disk_async.call_args[1] assert "commit_message" not in call_kwargs or call_kwargs["commit_message"] in (omit, None) assert call_kwargs["metadata"] == {"key": "value"} @@ -244,17 +244,17 @@ def test_snapshot_disk(self, mock_client: Mock) -> None: def test_snapshot_disk_async(self, mock_client: Mock) -> None: """Test snapshot_disk_async returns immediately.""" - snapshot_data = SimpleNamespace(id="snap_123") + snapshot_data = SimpleNamespace(id="snp_123") mock_client.devboxes.snapshot_disk_async.return_value = snapshot_data - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") snapshot = devbox.snapshot_disk_async( name="test-snapshot", metadata={"key": "value"}, extra_headers={"X-Custom": "value"}, ) - assert snapshot.id == "snap_123" + assert snapshot.id == "snp_123" call_kwargs = mock_client.devboxes.snapshot_disk_async.call_args[1] assert "commit_message" not in call_kwargs or call_kwargs["commit_message"] in (omit, None) assert call_kwargs["metadata"] == {"key": "value"} @@ -270,7 +270,7 @@ def test_close(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: """Test close method calls shutdown.""" mock_client.devboxes.shutdown.return_value = devbox_view - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") devbox.close() call_kwargs = mock_client.devboxes.shutdown.call_args[1] @@ -278,21 +278,21 @@ def test_close(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: def test_cmd_property(self, mock_client: Mock) -> None: """Test cmd property returns CommandInterface.""" - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") cmd = devbox.cmd assert isinstance(cmd, CommandInterface) assert cmd._devbox is devbox def test_file_property(self, mock_client: Mock) -> None: """Test file property returns FileInterface.""" - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") file_interface = devbox.file assert isinstance(file_interface, FileInterface) assert file_interface._devbox is devbox def test_net_property(self, mock_client: Mock) -> None: """Test net property returns NetworkInterface.""" - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") net = devbox.net assert isinstance(net, NetworkInterface) assert net._devbox is devbox diff --git a/tests/sdk/devbox/test_edge_cases.py b/tests/sdk/devbox/test_edge_cases.py index ff2491f66..23341f0c0 100644 --- a/tests/sdk/devbox/test_edge_cases.py +++ b/tests/sdk/devbox/test_edge_cases.py @@ -31,7 +31,7 @@ def test_network_error(self, mock_client: Mock) -> None: """Test handling of network errors.""" mock_client.devboxes.retrieve.side_effect = httpx.NetworkError("Connection failed") - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") with pytest.raises(httpx.NetworkError): devbox.get_info() @@ -50,7 +50,7 @@ def test_api_error(self, mock_client: Mock, status_code: int, message: str) -> N mock_client.devboxes.retrieve.side_effect = error - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") with pytest.raises(APIStatusError): devbox.get_info() @@ -58,7 +58,7 @@ def test_timeout_error(self, mock_client: Mock) -> None: """Test handling of timeout errors.""" mock_client.devboxes.retrieve.side_effect = httpx.TimeoutException("Request timed out") - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") with pytest.raises(httpx.TimeoutException): devbox.get_info(timeout=1.0) @@ -68,19 +68,19 @@ class TestDevboxEdgeCases: def test_empty_responses(self, mock_client: Mock) -> None: """Test handling of empty responses.""" - empty_view = SimpleNamespace(id="dev_123", status="", name="") + empty_view = SimpleNamespace(id="dbx_123", status="", name="") mock_client.devboxes.retrieve.return_value = empty_view - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.get_info() assert result == empty_view def test_none_values(self, mock_client: Mock) -> None: """Test handling of None values.""" - view_with_none = SimpleNamespace(id="dev_123", status=None, name=None) + view_with_none = SimpleNamespace(id="dbx_123", status=None, name=None) mock_client.devboxes.retrieve.return_value = view_with_none - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.get_info() assert result.status is None assert result.name is None @@ -89,9 +89,9 @@ def test_concurrent_operations( self, mock_client: Mock, thread_cleanup: tuple[list[threading.Thread], list[threading.Event]] ) -> None: """Test concurrent operations.""" - mock_client.devboxes.retrieve.return_value = SimpleNamespace(id="dev_123", status="running") + mock_client.devboxes.retrieve.return_value = SimpleNamespace(id="dbx_123", status="running") - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") results: list[DevboxView] = [] def get_info() -> None: @@ -118,13 +118,13 @@ def test_context_manager_vs_manual_cleanup(self, mock_client: Mock, devbox_view: mock_client.devboxes.shutdown.return_value = devbox_view # Context manager approach (Pythonic) - with Devbox(mock_client, "dev_123"): + with Devbox(mock_client, "dbx_123"): pass mock_client.devboxes.shutdown.assert_called_once() # Manual cleanup (TypeScript-like) - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") devbox.shutdown() assert mock_client.devboxes.shutdown.call_count == 2 diff --git a/tests/sdk/devbox/test_interfaces.py b/tests/sdk/devbox/test_interfaces.py index a8ca574ba..66ef8fa7b 100644 --- a/tests/sdk/devbox/test_interfaces.py +++ b/tests/sdk/devbox/test_interfaces.py @@ -24,7 +24,7 @@ def test_exec_without_callbacks(self, mock_client: Mock, execution_view: MockExe mock_client.devboxes.execute_async.return_value = execution_view mock_client.devboxes.executions.await_completed.return_value = execution_view - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.cmd.exec("echo hello") assert result.exit_code == 0 @@ -38,13 +38,13 @@ def test_exec_without_callbacks(self, mock_client: Mock, execution_view: MockExe def test_exec_with_stdout_callback(self, mock_client: Mock, mock_stream: Mock) -> None: """Test exec with stdout callback.""" execution_async = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", ) execution_completed = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="output", @@ -57,7 +57,7 @@ def test_exec_with_stdout_callback(self, mock_client: Mock, mock_stream: Mock) - stdout_calls: list[str] = [] - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.cmd.exec("echo hello", stdout=stdout_calls.append) assert result.exit_code == 0 @@ -67,13 +67,13 @@ def test_exec_with_stdout_callback(self, mock_client: Mock, mock_stream: Mock) - def test_exec_with_stderr_callback(self, mock_client: Mock, mock_stream: Mock) -> None: """Test exec with stderr callback.""" execution_async = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", ) execution_completed = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="", @@ -86,7 +86,7 @@ def test_exec_with_stderr_callback(self, mock_client: Mock, mock_stream: Mock) - stderr_calls: list[str] = [] - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.cmd.exec("echo hello", stderr=stderr_calls.append) assert result.exit_code == 0 @@ -95,13 +95,13 @@ def test_exec_with_stderr_callback(self, mock_client: Mock, mock_stream: Mock) - def test_exec_with_output_callback(self, mock_client: Mock, mock_stream: Mock) -> None: """Test exec with output callback.""" execution_async = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", ) execution_completed = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="output", @@ -115,7 +115,7 @@ def test_exec_with_output_callback(self, mock_client: Mock, mock_stream: Mock) - output_calls: list[str] = [] - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.cmd.exec("echo hello", output=output_calls.append) assert result.exit_code == 0 @@ -124,13 +124,13 @@ def test_exec_with_output_callback(self, mock_client: Mock, mock_stream: Mock) - def test_exec_with_all_callbacks(self, mock_client: Mock, mock_stream: Mock) -> None: """Test exec with all callbacks.""" execution_async = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", ) execution_completed = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="output", @@ -146,7 +146,7 @@ def test_exec_with_all_callbacks(self, mock_client: Mock, mock_stream: Mock) -> stderr_calls: list[str] = [] output_calls: list[str] = [] - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.cmd.exec( "echo hello", stdout=stdout_calls.append, @@ -160,19 +160,19 @@ def test_exec_with_all_callbacks(self, mock_client: Mock, mock_stream: Mock) -> def test_exec_async_returns_execution(self, mock_client: Mock, mock_stream: Mock) -> None: """Test exec_async returns Execution object.""" execution_async = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", ) mock_client.devboxes.execute_async.return_value = execution_async mock_client.devboxes.executions.stream_stdout_updates.return_value = mock_stream - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") execution = devbox.cmd.exec_async("long-running command") - assert execution.execution_id == "exec_123" - assert execution.devbox_id == "dev_123" + assert execution.execution_id == "exn_123" + assert execution.devbox_id == "dbx_123" mock_client.devboxes.execute_async.assert_called_once() @@ -183,7 +183,7 @@ def test_read(self, mock_client: Mock) -> None: """Test file read.""" mock_client.devboxes.read_file_contents.return_value = "file content" - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.file.read(file_path="/path/to/file") assert result == "file content" @@ -196,7 +196,7 @@ def test_write_string(self, mock_client: Mock) -> None: execution_detail = SimpleNamespace() mock_client.devboxes.write_file_contents.return_value = execution_detail - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.file.write(file_path="/path/to/file", contents="content") assert result == execution_detail @@ -210,7 +210,7 @@ def test_write_bytes(self, mock_client: Mock) -> None: execution_detail = SimpleNamespace() mock_client.devboxes.write_file_contents.return_value = execution_detail - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.file.write(file_path="/path/to/file", contents="content") assert result == execution_detail @@ -225,7 +225,7 @@ def test_download(self, mock_client: Mock) -> None: mock_response.read.return_value = b"file content" mock_client.devboxes.download_file.return_value = mock_response - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.file.download(path="/path/to/file") assert result == b"file content" @@ -238,7 +238,7 @@ def test_upload(self, mock_client: Mock, tmp_path: Path) -> None: execution_detail = SimpleNamespace() mock_client.devboxes.upload_file.return_value = execution_detail - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") # Create a temporary file for upload temp_file = tmp_path / "test_file.txt" temp_file.write_text("test content") @@ -260,7 +260,7 @@ def test_create_ssh_key(self, mock_client: Mock) -> None: ssh_key_response = SimpleNamespace(public_key="ssh-rsa ...") mock_client.devboxes.create_ssh_key.return_value = ssh_key_response - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.net.create_ssh_key( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -271,7 +271,7 @@ def test_create_ssh_key(self, mock_client: Mock) -> None: assert result == ssh_key_response mock_client.devboxes.create_ssh_key.assert_called_once_with( - "dev_123", + "dbx_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, @@ -284,7 +284,7 @@ def test_create_tunnel(self, mock_client: Mock) -> None: tunnel_view = SimpleNamespace(port=8080) mock_client.devboxes.create_tunnel.return_value = tunnel_view - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.net.create_tunnel( port=8080, extra_headers={"X-Custom": "value"}, @@ -296,7 +296,7 @@ def test_create_tunnel(self, mock_client: Mock) -> None: assert result == tunnel_view mock_client.devboxes.create_tunnel.assert_called_once_with( - "dev_123", + "dbx_123", port=8080, extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -309,7 +309,7 @@ def test_remove_tunnel(self, mock_client: Mock) -> None: """Test remove tunnel.""" mock_client.devboxes.remove_tunnel.return_value = object() - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") result = devbox.net.remove_tunnel( port=8080, extra_headers={"X-Custom": "value"}, @@ -321,7 +321,7 @@ def test_remove_tunnel(self, mock_client: Mock) -> None: assert result is not None # Verify return value is propagated mock_client.devboxes.remove_tunnel.assert_called_once_with( - "dev_123", + "dbx_123", port=8080, extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, diff --git a/tests/sdk/devbox/test_streaming.py b/tests/sdk/devbox/test_streaming.py index 4550b94a2..6d44a4e5e 100644 --- a/tests/sdk/devbox/test_streaming.py +++ b/tests/sdk/devbox/test_streaming.py @@ -26,17 +26,17 @@ class TestDevboxStreaming: def test_start_streaming_no_callbacks(self, mock_client: Mock) -> None: """Test _start_streaming returns None when no callbacks.""" - devbox = Devbox(mock_client, "dev_123") - result = devbox._start_streaming("exec_123", stdout=None, stderr=None, output=None) + devbox = Devbox(mock_client, "dbx_123") + result = devbox._start_streaming("exn_123", stdout=None, stderr=None, output=None) assert result is None def test_start_streaming_stdout_only(self, mock_client: Mock, mock_stream: Mock) -> None: """Test _start_streaming with stdout callback only.""" mock_client.devboxes.executions.stream_stdout_updates.return_value = mock_stream - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") stdout_calls: list[str] = [] - result = devbox._start_streaming("exec_123", stdout=stdout_calls.append, stderr=None, output=None) + result = devbox._start_streaming("exn_123", stdout=stdout_calls.append, stderr=None, output=None) assert result is not None assert isinstance(result, _StreamingGroup) @@ -47,9 +47,9 @@ def test_start_streaming_stderr_only(self, mock_client: Mock, mock_stream: Mock) """Test _start_streaming with stderr callback only.""" mock_client.devboxes.executions.stream_stderr_updates.return_value = mock_stream - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") stderr_calls: list[str] = [] - result = devbox._start_streaming("exec_123", stdout=None, stderr=stderr_calls.append, output=None) + result = devbox._start_streaming("exn_123", stdout=None, stderr=stderr_calls.append, output=None) assert result is not None assert isinstance(result, _StreamingGroup) @@ -61,9 +61,9 @@ def test_start_streaming_output_only(self, mock_client: Mock, mock_stream: Mock) mock_client.devboxes.executions.stream_stdout_updates.return_value = mock_stream mock_client.devboxes.executions.stream_stderr_updates.return_value = mock_stream - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") output_calls: list[str] = [] - result = devbox._start_streaming("exec_123", stdout=None, stderr=None, output=output_calls.append) + result = devbox._start_streaming("exn_123", stdout=None, stderr=None, output=output_calls.append) assert result is not None assert isinstance(result, _StreamingGroup) @@ -74,12 +74,12 @@ def test_start_streaming_all_callbacks(self, mock_client: Mock, mock_stream: Moc mock_client.devboxes.executions.stream_stdout_updates.return_value = mock_stream mock_client.devboxes.executions.stream_stderr_updates.return_value = mock_stream - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") stdout_calls: list[str] = [] stderr_calls: list[str] = [] output_calls: list[str] = [] result = devbox._start_streaming( - "exec_123", + "exn_123", stdout=stdout_calls.append, stderr=stderr_calls.append, output=output_calls.append, @@ -104,7 +104,7 @@ def test_spawn_stream_thread( mock_stream.__enter__ = Mock(return_value=mock_stream) mock_stream.__exit__ = Mock(return_value=None) - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") stop_event = threading.Event() calls: list[str] = [] @@ -147,7 +147,7 @@ def test_spawn_stream_thread_stop_event( mock_stream.__enter__ = Mock(return_value=mock_stream) mock_stream.__exit__ = Mock(return_value=None) - devbox = Devbox(mock_client, "dev_123") + devbox = Devbox(mock_client, "dbx_123") stop_event = threading.Event() calls: list[str] = [] diff --git a/tests/sdk/test_agent.py b/tests/sdk/test_agent.py index 7580b44d8..f1bbb083d 100644 --- a/tests/sdk/test_agent.py +++ b/tests/sdk/test_agent.py @@ -13,19 +13,19 @@ class TestAgent: def test_init(self, mock_client: Mock) -> None: """Test Agent initialization.""" - agent = Agent(mock_client, "agent_123") - assert agent.id == "agent_123" + agent = Agent(mock_client, "agt_123") + assert agent.id == "agt_123" def test_repr(self, mock_client: Mock) -> None: """Test Agent string representation.""" - agent = Agent(mock_client, "agent_123") - assert repr(agent) == "" + agent = Agent(mock_client, "agt_123") + assert repr(agent) == "" def test_get_info(self, mock_client: Mock, agent_view: MockAgentView) -> None: """Test get_info method.""" mock_client.agents.retrieve.return_value = agent_view - agent = Agent(mock_client, "agent_123") + agent = Agent(mock_client, "agt_123") result = agent.get_info( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -35,7 +35,7 @@ def test_get_info(self, mock_client: Mock, agent_view: MockAgentView) -> None: assert result == agent_view mock_client.agents.retrieve.assert_called_once_with( - "agent_123", + "agt_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, diff --git a/tests/sdk/test_async_agent.py b/tests/sdk/test_async_agent.py index a2bb9496c..be7efa845 100644 --- a/tests/sdk/test_async_agent.py +++ b/tests/sdk/test_async_agent.py @@ -15,20 +15,20 @@ class TestAsyncAgent: def test_init(self, mock_async_client: AsyncMock) -> None: """Test AsyncAgent initialization.""" - agent = AsyncAgent(mock_async_client, "agent_123") - assert agent.id == "agent_123" + agent = AsyncAgent(mock_async_client, "agt_123") + assert agent.id == "agt_123" def test_repr(self, mock_async_client: AsyncMock) -> None: """Test AsyncAgent string representation.""" - agent = AsyncAgent(mock_async_client, "agent_123") - assert repr(agent) == "" + agent = AsyncAgent(mock_async_client, "agt_123") + assert repr(agent) == "" @pytest.mark.asyncio async def test_get_info(self, mock_async_client: AsyncMock, agent_view: MockAgentView) -> None: """Test get_info method.""" mock_async_client.agents.retrieve = AsyncMock(return_value=agent_view) - agent = AsyncAgent(mock_async_client, "agent_123") + agent = AsyncAgent(mock_async_client, "agt_123") result = await agent.get_info( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -38,7 +38,7 @@ async def test_get_info(self, mock_async_client: AsyncMock, agent_view: MockAgen assert result == agent_view mock_async_client.agents.retrieve.assert_called_once_with( - "agent_123", + "agt_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, diff --git a/tests/sdk/test_async_benchmark.py b/tests/sdk/test_async_benchmark.py new file mode 100644 index 000000000..d7d72daad --- /dev/null +++ b/tests/sdk/test_async_benchmark.py @@ -0,0 +1,130 @@ +"""Comprehensive tests for async AsyncBenchmark class.""" + +from __future__ import annotations + +from types import SimpleNamespace +from unittest.mock import AsyncMock + +from tests.sdk.conftest import MockBenchmarkView, MockBenchmarkRunView +from runloop_api_client.sdk.async_benchmark import AsyncBenchmark +from runloop_api_client.sdk.async_benchmark_run import AsyncBenchmarkRun + + +class TestAsyncBenchmark: + """Tests for AsyncBenchmark class.""" + + def test_init(self, mock_async_client: AsyncMock) -> None: + """Test AsyncBenchmark initialization.""" + benchmark = AsyncBenchmark(mock_async_client, "bmd_123") + assert benchmark.id == "bmd_123" + assert repr(benchmark) == "" + + async def test_get_info(self, mock_async_client: AsyncMock, benchmark_view: MockBenchmarkView) -> None: + """Test get_info method.""" + mock_async_client.benchmarks.retrieve = AsyncMock(return_value=benchmark_view) + + benchmark = AsyncBenchmark(mock_async_client, "bmd_123") + result = await benchmark.get_info() + + assert result == benchmark_view + mock_async_client.benchmarks.retrieve.assert_awaited_once_with("bmd_123") + + async def test_update(self, mock_async_client: AsyncMock, benchmark_view: MockBenchmarkView) -> None: + """Test update method.""" + benchmark_view.name = "updated-name" + mock_async_client.benchmarks.update = AsyncMock(return_value=benchmark_view) + + benchmark = AsyncBenchmark(mock_async_client, "bmd_123") + result = await benchmark.update(name="updated-name") + + assert result == benchmark_view + mock_async_client.benchmarks.update.assert_awaited_once_with("bmd_123", name="updated-name") + + async def test_run(self, mock_async_client: AsyncMock, benchmark_run_view: MockBenchmarkRunView) -> None: + """Test run method.""" + mock_async_client.benchmarks.start_run = AsyncMock(return_value=benchmark_run_view) + + benchmark = AsyncBenchmark(mock_async_client, "bmd_123") + result = await benchmark.start_run(run_name="test-run", metadata={"key": "value"}) + + assert isinstance(result, AsyncBenchmarkRun) + assert result.id == benchmark_run_view.id + assert result.benchmark_id == benchmark_run_view.benchmark_id + mock_async_client.benchmarks.start_run.assert_awaited_once_with( + benchmark_id="bmd_123", run_name="test-run", metadata={"key": "value"} + ) + + async def test_add_scenarios(self, mock_async_client: AsyncMock, benchmark_view: MockBenchmarkView) -> None: + """Test add_scenarios method.""" + benchmark_view.scenario_ids = ["scn_001", "scn_002"] + mock_async_client.benchmarks.update_scenarios = AsyncMock(return_value=benchmark_view) + + benchmark = AsyncBenchmark(mock_async_client, "bmd_123") + result = await benchmark.add_scenarios(["scn_001", "scn_002"]) + + assert result == benchmark_view + mock_async_client.benchmarks.update_scenarios.assert_awaited_once_with( + "bmd_123", scenarios_to_add=["scn_001", "scn_002"] + ) + + async def test_remove_scenarios(self, mock_async_client: AsyncMock, benchmark_view: MockBenchmarkView) -> None: + """Test remove_scenarios method.""" + mock_async_client.benchmarks.update_scenarios = AsyncMock(return_value=benchmark_view) + + benchmark = AsyncBenchmark(mock_async_client, "bmd_123") + result = await benchmark.remove_scenarios(["scn_001"]) + + assert result == benchmark_view + mock_async_client.benchmarks.update_scenarios.assert_awaited_once_with( + "bmd_123", scenarios_to_remove=["scn_001"] + ) + + async def test_list_runs_single( + self, mock_async_client: AsyncMock, benchmark_run_view: MockBenchmarkRunView + ) -> None: + """Test list_runs method with single result.""" + page = SimpleNamespace(runs=[benchmark_run_view]) + mock_async_client.benchmarks.runs.list = AsyncMock(return_value=page) + + benchmark = AsyncBenchmark(mock_async_client, "bmd_123") + result = await benchmark.list_runs() + + assert len(result) == 1 + assert isinstance(result[0], AsyncBenchmarkRun) + assert result[0].id == benchmark_run_view.id + assert result[0].benchmark_id == benchmark_run_view.benchmark_id + mock_async_client.benchmarks.runs.list.assert_awaited_once_with(benchmark_id="bmd_123") + + async def test_list_runs_multiple(self, mock_async_client: AsyncMock) -> None: + """Test list_runs method with multiple results.""" + run_view1 = MockBenchmarkRunView(id="bmr_001") + run_view2 = MockBenchmarkRunView(id="bmr_002") + page = SimpleNamespace(runs=[run_view1, run_view2]) + mock_async_client.benchmarks.runs.list = AsyncMock(return_value=page) + + benchmark = AsyncBenchmark(mock_async_client, "bmd_123") + result = await benchmark.list_runs() + + assert len(result) == 2 + assert isinstance(result[0], AsyncBenchmarkRun) + assert isinstance(result[1], AsyncBenchmarkRun) + assert result[0].id == run_view1.id + assert result[0].benchmark_id == run_view1.benchmark_id + assert result[1].id == run_view2.id + assert result[1].benchmark_id == run_view2.benchmark_id + mock_async_client.benchmarks.runs.list.assert_awaited_once_with(benchmark_id="bmd_123") + + async def test_list_runs_with_params( + self, mock_async_client: AsyncMock, benchmark_run_view: MockBenchmarkRunView + ) -> None: + """Test list_runs method with filtering parameters.""" + page = SimpleNamespace(runs=[benchmark_run_view]) + mock_async_client.benchmarks.runs.list = AsyncMock(return_value=page) + + benchmark = AsyncBenchmark(mock_async_client, "bmd_123") + result = await benchmark.list_runs(limit=10, name="test-run") + + assert len(result) == 1 + mock_async_client.benchmarks.runs.list.assert_awaited_once_with( + benchmark_id="bmd_123", limit=10, name="test-run" + ) diff --git a/tests/sdk/test_async_benchmark_run.py b/tests/sdk/test_async_benchmark_run.py index 1785f683a..dd6e230d2 100644 --- a/tests/sdk/test_async_benchmark_run.py +++ b/tests/sdk/test_async_benchmark_run.py @@ -15,59 +15,59 @@ class TestAsyncBenchmarkRun: def test_init(self, mock_async_client: AsyncMock) -> None: """Test AsyncBenchmarkRun initialization.""" - run = AsyncBenchmarkRun(mock_async_client, "bench_run_123", "bench_123") - assert run.id == "bench_run_123" - assert run.benchmark_id == "bench_123" + run = AsyncBenchmarkRun(mock_async_client, "bmr_123", "bmd_123") + assert run.id == "bmr_123" + assert run.benchmark_id == "bmd_123" def test_repr(self, mock_async_client: AsyncMock) -> None: """Test AsyncBenchmarkRun string representation.""" - run = AsyncBenchmarkRun(mock_async_client, "bench_run_123", "bench_123") - assert repr(run) == "" + run = AsyncBenchmarkRun(mock_async_client, "bmr_123", "bmd_123") + assert repr(run) == "" async def test_get_info(self, mock_async_client: AsyncMock, benchmark_run_view: MockBenchmarkRunView) -> None: """Test get_info method.""" mock_async_client.benchmarks.runs.retrieve = AsyncMock(return_value=benchmark_run_view) - run = AsyncBenchmarkRun(mock_async_client, "bench_run_123", "bench_123") + run = AsyncBenchmarkRun(mock_async_client, "bmr_123", "bmd_123") result = await run.get_info() assert result == benchmark_run_view - mock_async_client.benchmarks.runs.retrieve.assert_awaited_once_with("bench_run_123") + mock_async_client.benchmarks.runs.retrieve.assert_awaited_once_with("bmr_123") async def test_cancel(self, mock_async_client: AsyncMock, benchmark_run_view: MockBenchmarkRunView) -> None: """Test cancel method.""" benchmark_run_view.state = "canceled" mock_async_client.benchmarks.runs.cancel = AsyncMock(return_value=benchmark_run_view) - run = AsyncBenchmarkRun(mock_async_client, "bench_run_123", "bench_123") + run = AsyncBenchmarkRun(mock_async_client, "bmr_123", "bmd_123") result = await run.cancel() assert result == benchmark_run_view assert result.state == "canceled" - mock_async_client.benchmarks.runs.cancel.assert_awaited_once_with("bench_run_123") + mock_async_client.benchmarks.runs.cancel.assert_awaited_once_with("bmr_123") async def test_complete(self, mock_async_client: AsyncMock, benchmark_run_view: MockBenchmarkRunView) -> None: """Test complete method.""" benchmark_run_view.state = "completed" mock_async_client.benchmarks.runs.complete = AsyncMock(return_value=benchmark_run_view) - run = AsyncBenchmarkRun(mock_async_client, "bench_run_123", "bench_123") + run = AsyncBenchmarkRun(mock_async_client, "bmr_123", "bmd_123") result = await run.complete() assert result == benchmark_run_view assert result.state == "completed" - mock_async_client.benchmarks.runs.complete.assert_awaited_once_with("bench_run_123") + mock_async_client.benchmarks.runs.complete.assert_awaited_once_with("bmr_123") async def test_list_scenario_runs_empty(self, mock_async_client: AsyncMock) -> None: """Test list_scenario_runs method with empty results.""" page = SimpleNamespace(runs=[]) mock_async_client.benchmarks.runs.list_scenario_runs = AsyncMock(return_value=page) - run = AsyncBenchmarkRun(mock_async_client, "bench_run_123", "bench_123") + run = AsyncBenchmarkRun(mock_async_client, "bmr_123", "bmd_123") result = await run.list_scenario_runs() assert len(result) == 0 - mock_async_client.benchmarks.runs.list_scenario_runs.assert_awaited_once_with("bench_run_123") + mock_async_client.benchmarks.runs.list_scenario_runs.assert_awaited_once_with("bmr_123") async def test_list_scenario_runs_single( self, mock_async_client: AsyncMock, scenario_run_view: MockScenarioRunView @@ -76,31 +76,31 @@ async def test_list_scenario_runs_single( page = SimpleNamespace(runs=[scenario_run_view]) mock_async_client.benchmarks.runs.list_scenario_runs = AsyncMock(return_value=page) - run = AsyncBenchmarkRun(mock_async_client, "bench_run_123", "bench_123") + run = AsyncBenchmarkRun(mock_async_client, "bmr_123", "bmd_123") result = await run.list_scenario_runs() assert len(result) == 1 assert isinstance(result[0], AsyncScenarioRun) assert result[0].id == scenario_run_view.id assert result[0].devbox_id == scenario_run_view.devbox_id - mock_async_client.benchmarks.runs.list_scenario_runs.assert_awaited_once_with("bench_run_123") + mock_async_client.benchmarks.runs.list_scenario_runs.assert_awaited_once_with("bmr_123") async def test_list_scenario_runs_multiple(self, mock_async_client: AsyncMock) -> None: """Test list_scenario_runs method with multiple results.""" - scenario_run_view1 = MockScenarioRunView(id="run_001", devbox_id="dev_001") - scenario_run_view2 = MockScenarioRunView(id="run_002", devbox_id="dev_002") + scenario_run_view1 = MockScenarioRunView(id="scr_001", devbox_id="dev_001") + scenario_run_view2 = MockScenarioRunView(id="scr_002", devbox_id="dev_002") page = SimpleNamespace(runs=[scenario_run_view1, scenario_run_view2]) mock_async_client.benchmarks.runs.list_scenario_runs = AsyncMock(return_value=page) - run = AsyncBenchmarkRun(mock_async_client, "bench_run_123", "bench_123") + run = AsyncBenchmarkRun(mock_async_client, "bmr_123", "bmd_123") result = await run.list_scenario_runs() assert len(result) == 2 assert isinstance(result[0], AsyncScenarioRun) assert isinstance(result[1], AsyncScenarioRun) - assert result[0].id == "run_001" - assert result[1].id == "run_002" - mock_async_client.benchmarks.runs.list_scenario_runs.assert_awaited_once_with("bench_run_123") + assert result[0].id == "scr_001" + assert result[1].id == "scr_002" + mock_async_client.benchmarks.runs.list_scenario_runs.assert_awaited_once_with("bmr_123") async def test_list_scenario_runs_with_params( self, mock_async_client: AsyncMock, scenario_run_view: MockScenarioRunView @@ -109,12 +109,12 @@ async def test_list_scenario_runs_with_params( page = SimpleNamespace(runs=[scenario_run_view]) mock_async_client.benchmarks.runs.list_scenario_runs = AsyncMock(return_value=page) - run = AsyncBenchmarkRun(mock_async_client, "bench_run_123", "bench_123") + run = AsyncBenchmarkRun(mock_async_client, "bmr_123", "bmd_123") result = await run.list_scenario_runs(limit=10, state="completed") assert len(result) == 1 assert isinstance(result[0], AsyncScenarioRun) assert result[0].id == scenario_run_view.id mock_async_client.benchmarks.runs.list_scenario_runs.assert_awaited_once_with( - "bench_run_123", limit=10, state="completed" + "bmr_123", limit=10, state="completed" ) diff --git a/tests/sdk/test_async_blueprint.py b/tests/sdk/test_async_blueprint.py index 75901a445..4c7de1e22 100644 --- a/tests/sdk/test_async_blueprint.py +++ b/tests/sdk/test_async_blueprint.py @@ -16,20 +16,20 @@ class TestAsyncBlueprint: def test_init(self, mock_async_client: AsyncMock) -> None: """Test AsyncBlueprint initialization.""" - blueprint = AsyncBlueprint(mock_async_client, "bp_123") - assert blueprint.id == "bp_123" + blueprint = AsyncBlueprint(mock_async_client, "bpt_123") + assert blueprint.id == "bpt_123" def test_repr(self, mock_async_client: AsyncMock) -> None: """Test AsyncBlueprint string representation.""" - blueprint = AsyncBlueprint(mock_async_client, "bp_123") - assert repr(blueprint) == "" + blueprint = AsyncBlueprint(mock_async_client, "bpt_123") + assert repr(blueprint) == "" @pytest.mark.asyncio async def test_get_info(self, mock_async_client: AsyncMock, blueprint_view: MockBlueprintView) -> None: """Test get_info method.""" mock_async_client.blueprints.retrieve = AsyncMock(return_value=blueprint_view) - blueprint = AsyncBlueprint(mock_async_client, "bp_123") + blueprint = AsyncBlueprint(mock_async_client, "bpt_123") result = await blueprint.get_info( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -46,7 +46,7 @@ async def test_logs(self, mock_async_client: AsyncMock) -> None: logs_view = SimpleNamespace(logs=[]) mock_async_client.blueprints.logs = AsyncMock(return_value=logs_view) - blueprint = AsyncBlueprint(mock_async_client, "bp_123") + blueprint = AsyncBlueprint(mock_async_client, "bpt_123") result = await blueprint.logs( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -62,7 +62,7 @@ async def test_delete(self, mock_async_client: AsyncMock) -> None: """Test delete method.""" mock_async_client.blueprints.delete = AsyncMock(return_value=object()) - blueprint = AsyncBlueprint(mock_async_client, "bp_123") + blueprint = AsyncBlueprint(mock_async_client, "bpt_123") result = await blueprint.delete( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -78,7 +78,7 @@ async def test_create_devbox(self, mock_async_client: AsyncMock, devbox_view: Mo """Test create_devbox method.""" mock_async_client.devboxes.create_and_await_running = AsyncMock(return_value=devbox_view) - blueprint = AsyncBlueprint(mock_async_client, "bp_123") + blueprint = AsyncBlueprint(mock_async_client, "bpt_123") devbox = await blueprint.create_devbox( name="test-devbox", metadata={"key": "value"}, @@ -86,5 +86,5 @@ async def test_create_devbox(self, mock_async_client: AsyncMock, devbox_view: Mo extra_headers={"X-Custom": "value"}, ) - assert devbox.id == "dev_123" + assert devbox.id == "dbx_123" mock_async_client.devboxes.create_and_await_running.assert_awaited_once() diff --git a/tests/sdk/test_async_execution.py b/tests/sdk/test_async_execution.py index 06629cf63..f05633263 100644 --- a/tests/sdk/test_async_execution.py +++ b/tests/sdk/test_async_execution.py @@ -91,9 +91,9 @@ class TestAsyncExecution: def test_init(self, mock_async_client: AsyncMock, execution_view: MockExecutionView) -> None: """Test AsyncExecution initialization.""" - execution = AsyncExecution(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] - assert execution.execution_id == "exec_123" - assert execution.devbox_id == "dev_123" + execution = AsyncExecution(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] + assert execution.execution_id == "exn_123" + assert execution.devbox_id == "dbx_123" assert execution._initial_result == execution_view @pytest.mark.asyncio @@ -113,19 +113,19 @@ async def task() -> None: async_task_cleanup.extend(tasks) streaming_group = _AsyncStreamingGroup(tasks) - execution = AsyncExecution(mock_async_client, "dev_123", execution_view, streaming_group) # type: ignore[arg-type] + execution = AsyncExecution(mock_async_client, "dbx_123", execution_view, streaming_group) # type: ignore[arg-type] assert execution._streaming_group is streaming_group def test_properties(self, mock_async_client: AsyncMock, execution_view: MockExecutionView) -> None: """Test AsyncExecution properties.""" - execution = AsyncExecution(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] - assert execution.execution_id == "exec_123" - assert execution.devbox_id == "dev_123" + execution = AsyncExecution(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] + assert execution.execution_id == "exn_123" + assert execution.devbox_id == "dbx_123" def test_repr(self, mock_async_client: AsyncMock, execution_view: MockExecutionView) -> None: """Test AsyncExecution repr formatting.""" - execution = AsyncExecution(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] - assert repr(execution) == "" + execution = AsyncExecution(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] + assert repr(execution) == "" @pytest.mark.asyncio async def test_result_already_completed( @@ -134,14 +134,14 @@ async def test_result_already_completed( """Test result when execution is already completed.""" mock_async_client.devboxes.wait_for_command = AsyncMock(return_value=execution_view) - execution = AsyncExecution(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] + execution = AsyncExecution(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] result = await execution.result() assert result.exit_code == 0 assert await result.stdout(num_lines=10) == "output" mock_async_client.devboxes.wait_for_command.assert_awaited_once_with( - "exec_123", - devbox_id="dev_123", + "exn_123", + devbox_id="dbx_123", statuses=["completed"], ) @@ -149,13 +149,13 @@ async def test_result_already_completed( async def test_result_needs_polling(self, mock_async_client: AsyncMock) -> None: """Test result when execution needs polling.""" running_execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", ) completed_execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="output", @@ -166,14 +166,14 @@ async def test_result_needs_polling(self, mock_async_client: AsyncMock) -> None: mock_async_client.devboxes.wait_for_command = AsyncMock(return_value=completed_execution) - execution = AsyncExecution(mock_async_client, "dev_123", running_execution) # type: ignore[arg-type] + execution = AsyncExecution(mock_async_client, "dbx_123", running_execution) # type: ignore[arg-type] result = await execution.result() assert result.exit_code == 0 assert await result.stdout(num_lines=10) == "output" mock_async_client.devboxes.wait_for_command.assert_awaited_once_with( - "exec_123", - devbox_id="dev_123", + "exn_123", + devbox_id="dbx_123", statuses=["completed"], ) @@ -181,13 +181,13 @@ async def test_result_needs_polling(self, mock_async_client: AsyncMock) -> None: async def test_result_with_streaming_group(self, mock_async_client: AsyncMock) -> None: """Test result with streaming group cleanup.""" running_execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", ) completed_execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="output", @@ -202,7 +202,7 @@ async def task() -> None: tasks = [asyncio.create_task(task())] streaming_group = _AsyncStreamingGroup(tasks) - execution = AsyncExecution(mock_async_client, "dev_123", running_execution, streaming_group) # type: ignore[arg-type] + execution = AsyncExecution(mock_async_client, "dbx_123", running_execution, streaming_group) # type: ignore[arg-type] result = await execution.result() assert result.exit_code == 0 @@ -213,8 +213,8 @@ async def task() -> None: async def test_result_passes_options(self, mock_async_client: AsyncMock) -> None: """Ensure result forwards options to wait_for_command.""" execution_view = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="output", @@ -223,12 +223,12 @@ async def test_result_passes_options(self, mock_async_client: AsyncMock) -> None mock_async_client.devboxes.wait_for_command = AsyncMock(return_value=execution_view) - execution = AsyncExecution(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] + execution = AsyncExecution(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] await execution.result(timeout=30.0, idempotency_key="abc123") mock_async_client.devboxes.wait_for_command.assert_awaited_once_with( - "exec_123", - devbox_id="dev_123", + "exn_123", + devbox_id="dbx_123", statuses=["completed"], timeout=30.0, idempotency_key="abc123", @@ -238,20 +238,20 @@ async def test_result_passes_options(self, mock_async_client: AsyncMock) -> None async def test_get_state(self, mock_async_client: AsyncMock, execution_view: MockExecutionView) -> None: """Test get_state method.""" updated_execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", ) mock_async_client.devboxes.executions.retrieve = AsyncMock(return_value=updated_execution) - execution = AsyncExecution(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] + execution = AsyncExecution(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] result = await execution.get_state() assert result == updated_execution assert execution._initial_result == execution_view mock_async_client.devboxes.executions.retrieve.assert_awaited_once_with( - "exec_123", - devbox_id="dev_123", + "exn_123", + devbox_id="dbx_123", ) @pytest.mark.asyncio @@ -259,10 +259,10 @@ async def test_kill(self, mock_async_client: AsyncMock, execution_view: MockExec """Test kill method.""" mock_async_client.devboxes.executions.kill = AsyncMock(return_value=None) - execution = AsyncExecution(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] + execution = AsyncExecution(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] await execution.kill() mock_async_client.devboxes.executions.kill.assert_awaited_once_with( - "exec_123", - devbox_id="dev_123", + "exn_123", + devbox_id="dbx_123", ) diff --git a/tests/sdk/test_async_execution_result.py b/tests/sdk/test_async_execution_result.py index cf8a23caa..58802cc4f 100644 --- a/tests/sdk/test_async_execution_result.py +++ b/tests/sdk/test_async_execution_result.py @@ -16,31 +16,31 @@ class TestAsyncExecutionResult: def test_init(self, mock_async_client: AsyncMock, execution_view: MockExecutionView) -> None: """Test AsyncExecutionResult initialization.""" - result = AsyncExecutionResult(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] # Verify via public API - assert result.devbox_id == "dev_123" - assert result.execution_id == "exec_123" + assert result.devbox_id == "dbx_123" + assert result.execution_id == "exn_123" def test_devbox_id_property(self, mock_async_client: AsyncMock, execution_view: MockExecutionView) -> None: """Test devbox_id property.""" - result = AsyncExecutionResult(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] - assert result.devbox_id == "dev_123" + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] + assert result.devbox_id == "dbx_123" def test_execution_id_property(self, mock_async_client: AsyncMock, execution_view: MockExecutionView) -> None: """Test execution_id property.""" - result = AsyncExecutionResult(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] - assert result.execution_id == "exec_123" + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] + assert result.execution_id == "exn_123" def test_exit_code_property(self, mock_async_client: AsyncMock, execution_view: MockExecutionView) -> None: """Test exit_code property.""" - result = AsyncExecutionResult(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] assert result.exit_code == 0 def test_exit_code_none(self, mock_async_client: AsyncMock) -> None: """Test exit_code property when exit_status is None.""" execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", exit_status=None, stdout="", @@ -48,19 +48,19 @@ def test_exit_code_none(self, mock_async_client: AsyncMock) -> None: stdout_truncated=False, stderr_truncated=False, ) - result = AsyncExecutionResult(mock_async_client, "dev_123", execution) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution) # type: ignore[arg-type] assert result.exit_code is None def test_success_property(self, mock_async_client: AsyncMock, execution_view: MockExecutionView) -> None: """Test success property.""" - result = AsyncExecutionResult(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] assert result.success is True def test_success_false(self, mock_async_client: AsyncMock) -> None: """Test success property when exit code is non-zero.""" execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=1, stdout="", @@ -68,19 +68,19 @@ def test_success_false(self, mock_async_client: AsyncMock) -> None: stdout_truncated=False, stderr_truncated=False, ) - result = AsyncExecutionResult(mock_async_client, "dev_123", execution) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution) # type: ignore[arg-type] assert result.success is False def test_failed_property(self, mock_async_client: AsyncMock, execution_view: MockExecutionView) -> None: """Test failed property when exit code is zero.""" - result = AsyncExecutionResult(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] assert result.failed is False def test_failed_true(self, mock_async_client: AsyncMock) -> None: """Test failed property when exit code is non-zero.""" execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=1, stdout="", @@ -88,14 +88,14 @@ def test_failed_true(self, mock_async_client: AsyncMock) -> None: stdout_truncated=False, stderr_truncated=False, ) - result = AsyncExecutionResult(mock_async_client, "dev_123", execution) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution) # type: ignore[arg-type] assert result.failed is True def test_failed_none(self, mock_async_client: AsyncMock) -> None: """Test failed property when exit_status is None.""" execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", exit_status=None, stdout="", @@ -103,13 +103,13 @@ def test_failed_none(self, mock_async_client: AsyncMock) -> None: stdout_truncated=False, stderr_truncated=False, ) - result = AsyncExecutionResult(mock_async_client, "dev_123", execution) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution) # type: ignore[arg-type] assert result.failed is False @pytest.mark.asyncio async def test_stdout(self, mock_async_client: AsyncMock, execution_view: MockExecutionView) -> None: """Test stdout method.""" - result = AsyncExecutionResult(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] assert await result.stdout() == "output" assert await result.stdout(num_lines=10) == "output" @@ -117,8 +117,8 @@ async def test_stdout(self, mock_async_client: AsyncMock, execution_view: MockEx async def test_stdout_empty(self, mock_async_client: AsyncMock) -> None: """Test stdout method when stdout is None.""" execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout=None, @@ -126,15 +126,15 @@ async def test_stdout_empty(self, mock_async_client: AsyncMock) -> None: stdout_truncated=False, stderr_truncated=False, ) - result = AsyncExecutionResult(mock_async_client, "dev_123", execution) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution) # type: ignore[arg-type] assert await result.stdout() == "" @pytest.mark.asyncio async def test_stderr(self, mock_async_client: AsyncMock) -> None: """Test stderr method.""" execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=1, stdout="", @@ -142,19 +142,19 @@ async def test_stderr(self, mock_async_client: AsyncMock) -> None: stdout_truncated=False, stderr_truncated=False, ) - result = AsyncExecutionResult(mock_async_client, "dev_123", execution) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution) # type: ignore[arg-type] assert await result.stderr() == "error message" assert await result.stderr(num_lines=20) == "error message" @pytest.mark.asyncio async def test_stderr_empty(self, mock_async_client: AsyncMock, execution_view: MockExecutionView) -> None: """Test stderr method when stderr is None.""" - result = AsyncExecutionResult(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] assert await result.stderr() == "" def test_result_property(self, mock_async_client: AsyncMock, execution_view: MockExecutionView) -> None: """Test result property.""" - result = AsyncExecutionResult(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] assert result.result == execution_view @pytest.mark.asyncio @@ -176,8 +176,8 @@ async def mock_iter(): mock_async_client.devboxes.executions.stream_stdout_updates = AsyncMock(return_value=mock_async_stream) execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="partial", @@ -185,13 +185,13 @@ async def mock_iter(): stdout_truncated=True, stderr_truncated=False, ) - result = AsyncExecutionResult(mock_async_client, "dev_123", execution) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution) # type: ignore[arg-type] # Should stream full output output = await result.stdout() assert output == "line1\nline2\nline3\n" mock_async_client.devboxes.executions.stream_stdout_updates.assert_awaited_once_with( - "exec_123", devbox_id="dev_123" + "exn_123", devbox_id="dbx_123" ) @pytest.mark.asyncio @@ -212,8 +212,8 @@ async def mock_iter(): mock_async_client.devboxes.executions.stream_stderr_updates = AsyncMock(return_value=mock_async_stream) execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="", @@ -221,13 +221,13 @@ async def mock_iter(): stdout_truncated=False, stderr_truncated=True, ) - result = AsyncExecutionResult(mock_async_client, "dev_123", execution) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution) # type: ignore[arg-type] # Should stream full output output = await result.stderr() assert output == "error1\nerror2\n" mock_async_client.devboxes.executions.stream_stderr_updates.assert_awaited_once_with( - "exec_123", devbox_id="dev_123" + "exn_123", devbox_id="dbx_123" ) @pytest.mark.asyncio @@ -248,8 +248,8 @@ async def mock_iter(): mock_async_client.devboxes.executions.stream_stdout_updates = AsyncMock(return_value=mock_async_stream) execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="line1\n", @@ -257,7 +257,7 @@ async def mock_iter(): stdout_truncated=True, stderr_truncated=False, ) - result = AsyncExecutionResult(mock_async_client, "dev_123", execution) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution) # type: ignore[arg-type] # Should stream and return last 2 lines output = await result.stdout(num_lines=2) @@ -267,8 +267,8 @@ async def mock_iter(): async def test_stdout_no_streaming_when_not_truncated(self, mock_async_client: AsyncMock) -> None: """Test stdout doesn't stream when not truncated.""" execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="complete output", @@ -276,7 +276,7 @@ async def test_stdout_no_streaming_when_not_truncated(self, mock_async_client: A stdout_truncated=False, stderr_truncated=False, ) - result = AsyncExecutionResult(mock_async_client, "dev_123", execution) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution) # type: ignore[arg-type] # Should return existing output without streaming output = await result.stdout() @@ -286,8 +286,8 @@ async def test_stdout_no_streaming_when_not_truncated(self, mock_async_client: A async def test_stdout_with_num_lines_no_truncation(self, mock_async_client: AsyncMock) -> None: """Test stdout with num_lines when not truncated.""" execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="line1\nline2\nline3\nline4\nline5", @@ -295,7 +295,7 @@ async def test_stdout_with_num_lines_no_truncation(self, mock_async_client: Asyn stdout_truncated=False, stderr_truncated=False, ) - result = AsyncExecutionResult(mock_async_client, "dev_123", execution) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution) # type: ignore[arg-type] # Should return last 2 lines without streaming output = await result.stdout(num_lines=2) @@ -303,7 +303,7 @@ async def test_stdout_with_num_lines_no_truncation(self, mock_async_client: Asyn def test_count_non_empty_lines(self, mock_async_client: AsyncMock, execution_view: MockExecutionView) -> None: """Test the _count_non_empty_lines helper method.""" - result = AsyncExecutionResult(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] # Test various input strings assert result._count_non_empty_lines("") == 0 @@ -315,7 +315,7 @@ def test_count_non_empty_lines(self, mock_async_client: AsyncMock, execution_vie def test_get_last_n_lines(self, mock_async_client: AsyncMock, execution_view: MockExecutionView) -> None: """Test the _get_last_n_lines helper method.""" - result = AsyncExecutionResult(mock_async_client, "dev_123", execution_view) # type: ignore[arg-type] + result = AsyncExecutionResult(mock_async_client, "dbx_123", execution_view) # type: ignore[arg-type] # Test various scenarios assert result._get_last_n_lines("", 5) == "" diff --git a/tests/sdk/test_async_ops.py b/tests/sdk/test_async_ops.py index 5a7cd2a75..41da4f737 100644 --- a/tests/sdk/test_async_ops.py +++ b/tests/sdk/test_async_ops.py @@ -56,7 +56,7 @@ async def test_create(self, mock_async_client: AsyncMock, devbox_view: MockDevbo ) assert isinstance(devbox, AsyncDevbox) - assert devbox.id == "dev_123" + assert devbox.id == "dbx_123" mock_async_client.devboxes.create_and_await_running.assert_awaited_once() @pytest.mark.asyncio @@ -66,13 +66,13 @@ async def test_create_from_blueprint_id(self, mock_async_client: AsyncMock, devb ops = AsyncDevboxOps(mock_async_client) devbox = await ops.create_from_blueprint_id( - "bp_123", + "bpt_123", name="test-devbox", ) assert isinstance(devbox, AsyncDevbox) call_kwargs = mock_async_client.devboxes.create_and_await_running.call_args[1] - assert call_kwargs["blueprint_id"] == "bp_123" + assert call_kwargs["blueprint_id"] == "bpt_123" @pytest.mark.asyncio async def test_create_from_blueprint_name(self, mock_async_client: AsyncMock, devbox_view: MockDevboxView) -> None: @@ -96,21 +96,21 @@ async def test_create_from_snapshot(self, mock_async_client: AsyncMock, devbox_v ops = AsyncDevboxOps(mock_async_client) devbox = await ops.create_from_snapshot( - "snap_123", + "snp_123", name="test-devbox", ) assert isinstance(devbox, AsyncDevbox) call_kwargs = mock_async_client.devboxes.create_and_await_running.call_args[1] - assert call_kwargs["snapshot_id"] == "snap_123" + assert call_kwargs["snapshot_id"] == "snp_123" def test_from_id(self, mock_async_client: AsyncMock) -> None: """Test from_id method.""" ops = AsyncDevboxOps(mock_async_client) - devbox = ops.from_id("dev_123") + devbox = ops.from_id("dbx_123") assert isinstance(devbox, AsyncDevbox) - assert devbox.id == "dev_123" + assert devbox.id == "dbx_123" # Verify from_id does not wait for running status if hasattr(mock_async_client.devboxes, "await_running"): assert not mock_async_client.devboxes.await_running.called @@ -142,7 +142,7 @@ async def test_list_single(self, mock_async_client: AsyncMock, devbox_view: Mock assert len(devboxes) == 1 assert isinstance(devboxes[0], AsyncDevbox) - assert devboxes[0].id == "dev_123" + assert devboxes[0].id == "dbx_123" mock_async_client.devboxes.list.assert_awaited_once() @pytest.mark.asyncio @@ -174,7 +174,7 @@ async def test_list_empty(self, mock_async_client: AsyncMock) -> None: mock_async_client.devboxes.disk_snapshots.list = AsyncMock(return_value=page) ops = AsyncSnapshotOps(mock_async_client) - snapshots = await ops.list(devbox_id="dev_123", limit=10) + snapshots = await ops.list(devbox_id="dbx_123", limit=10) assert len(snapshots) == 0 mock_async_client.devboxes.disk_snapshots.list.assert_awaited_once() @@ -187,14 +187,14 @@ async def test_list_single(self, mock_async_client: AsyncMock, snapshot_view: Mo ops = AsyncSnapshotOps(mock_async_client) snapshots = await ops.list( - devbox_id="dev_123", + devbox_id="dbx_123", limit=10, starting_after="snap_000", ) assert len(snapshots) == 1 assert isinstance(snapshots[0], AsyncSnapshot) - assert snapshots[0].id == "snap_123" + assert snapshots[0].id == "snp_123" mock_async_client.devboxes.disk_snapshots.list.assert_awaited_once() @pytest.mark.asyncio @@ -206,7 +206,7 @@ async def test_list_multiple(self, mock_async_client: AsyncMock) -> None: mock_async_client.devboxes.disk_snapshots.list = AsyncMock(return_value=page) ops = AsyncSnapshotOps(mock_async_client) - snapshots = await ops.list(devbox_id="dev_123", limit=10) + snapshots = await ops.list(devbox_id="dbx_123", limit=10) assert len(snapshots) == 2 assert isinstance(snapshots[0], AsyncSnapshot) @@ -218,10 +218,10 @@ async def test_list_multiple(self, mock_async_client: AsyncMock) -> None: def test_from_id(self, mock_async_client: AsyncMock) -> None: """Test from_id method.""" ops = AsyncSnapshotOps(mock_async_client) - snapshot = ops.from_id("snap_123") + snapshot = ops.from_id("snp_123") assert isinstance(snapshot, AsyncSnapshot) - assert snapshot.id == "snap_123" + assert snapshot.id == "snp_123" class TestAsyncBlueprintOps: @@ -239,16 +239,16 @@ async def test_create(self, mock_async_client: AsyncMock, blueprint_view: MockBl ) assert isinstance(blueprint, AsyncBlueprint) - assert blueprint.id == "bp_123" + assert blueprint.id == "bpt_123" mock_async_client.blueprints.create_and_await_build_complete.assert_awaited_once() def test_from_id(self, mock_async_client: AsyncMock) -> None: """Test from_id method.""" ops = AsyncBlueprintOps(mock_async_client) - blueprint = ops.from_id("bp_123") + blueprint = ops.from_id("bpt_123") assert isinstance(blueprint, AsyncBlueprint) - assert blueprint.id == "bp_123" + assert blueprint.id == "bpt_123" @pytest.mark.asyncio async def test_list_empty(self, mock_async_client: AsyncMock) -> None: @@ -277,7 +277,7 @@ async def test_list_single(self, mock_async_client: AsyncMock, blueprint_view: M assert len(blueprints) == 1 assert isinstance(blueprints[0], AsyncBlueprint) - assert blueprints[0].id == "bp_123" + assert blueprints[0].id == "bpt_123" mock_async_client.blueprints.list.assert_awaited_once() @pytest.mark.asyncio @@ -712,16 +712,16 @@ async def test_create(self, mock_async_client: AsyncMock, scorer_view: MockScore ) assert isinstance(scorer, AsyncScorer) - assert scorer.id == "scorer_123" + assert scorer.id == "sco_123" mock_async_client.scenarios.scorers.create.assert_awaited_once() def test_from_id(self, mock_async_client: AsyncMock) -> None: """Test from_id method.""" ops = AsyncScorerOps(mock_async_client) - scorer = ops.from_id("scorer_123") + scorer = ops.from_id("sco_123") assert isinstance(scorer, AsyncScorer) - assert scorer.id == "scorer_123" + assert scorer.id == "sco_123" @pytest.mark.asyncio async def test_list_empty(self, mock_async_client: AsyncMock) -> None: @@ -756,7 +756,7 @@ async def async_iter(): assert len(scorers) == 1 assert isinstance(scorers[0], AsyncScorer) - assert scorers[0].id == "scorer_123" + assert scorers[0].id == "sco_123" mock_async_client.scenarios.scorers.list.assert_awaited_once() @pytest.mark.asyncio @@ -797,16 +797,16 @@ async def test_create(self, mock_async_client: AsyncMock, agent_view: MockAgentV ) assert isinstance(agent, AsyncAgent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_async_client.agents.create.assert_called_once() def test_from_id(self, mock_async_client: AsyncMock) -> None: """Test from_id method.""" client = AsyncAgentOps(mock_async_client) - agent = client.from_id("agent_123") + agent = client.from_id("agt_123") assert isinstance(agent, AsyncAgent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" @pytest.mark.asyncio async def test_list(self, mock_async_client: AsyncMock) -> None: @@ -906,7 +906,7 @@ async def test_create_from_npm(self, mock_async_client: AsyncMock, agent_view: M ) assert isinstance(agent, AsyncAgent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_async_client.agents.create.assert_awaited_once_with( source={ "type": "npm", @@ -936,7 +936,7 @@ async def test_create_from_npm_with_all_options( ) assert isinstance(agent, AsyncAgent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_async_client.agents.create.assert_awaited_once_with( source={ "type": "npm", @@ -977,7 +977,7 @@ async def test_create_from_pip(self, mock_async_client: AsyncMock, agent_view: M ) assert isinstance(agent, AsyncAgent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_async_client.agents.create.assert_awaited_once_with( source={ "type": "pip", @@ -1006,7 +1006,7 @@ async def test_create_from_pip_with_all_options( ) assert isinstance(agent, AsyncAgent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_async_client.agents.create.assert_awaited_once_with( source={ "type": "pip", @@ -1033,7 +1033,7 @@ async def test_create_from_git(self, mock_async_client: AsyncMock, agent_view: M ) assert isinstance(agent, AsyncAgent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_async_client.agents.create.assert_awaited_once_with( source={ "type": "git", @@ -1062,7 +1062,7 @@ async def test_create_from_git_with_all_options( ) assert isinstance(agent, AsyncAgent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_async_client.agents.create.assert_awaited_once_with( source={ "type": "git", @@ -1089,7 +1089,7 @@ async def test_create_from_object(self, mock_async_client: AsyncMock, agent_view ) assert isinstance(agent, AsyncAgent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_async_client.agents.create.assert_awaited_once_with( source={ "type": "object", @@ -1117,7 +1117,7 @@ async def test_create_from_object_with_agent_setup( ) assert isinstance(agent, AsyncAgent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_async_client.agents.create.assert_awaited_once_with( source={ "type": "object", diff --git a/tests/sdk/test_async_scenario.py b/tests/sdk/test_async_scenario.py index 22a8f457a..cffca9b82 100644 --- a/tests/sdk/test_async_scenario.py +++ b/tests/sdk/test_async_scenario.py @@ -99,8 +99,8 @@ async def test_run_async(self, mock_async_client: AsyncMock, scenario_run_view: scenario = AsyncScenario(mock_async_client, "scn_123") run = await scenario.run_async(run_name="test-run") - assert run.id == "run_123" - assert run.devbox_id == "dev_123" + assert run.id == "scr_123" + assert run.devbox_id == "dbx_123" mock_async_client.scenarios.start_run.assert_awaited_once_with( scenario_id="scn_123", run_name="test-run", @@ -113,8 +113,8 @@ async def test_run(self, mock_async_client: AsyncMock, scenario_run_view: MockSc scenario = AsyncScenario(mock_async_client, "scn_123") run = await scenario.run(run_name="test-run") - assert run.id == "run_123" - assert run.devbox_id == "dev_123" + assert run.id == "scr_123" + assert run.devbox_id == "dbx_123" mock_async_client.scenarios.start_run_and_await_env_ready.assert_awaited_once_with( scenario_id="scn_123", run_name="test-run", diff --git a/tests/sdk/test_async_scenario_run.py b/tests/sdk/test_async_scenario_run.py index 010ad6cbb..c034524a0 100644 --- a/tests/sdk/test_async_scenario_run.py +++ b/tests/sdk/test_async_scenario_run.py @@ -15,31 +15,31 @@ class TestAsyncScenarioRun: def test_init(self, mock_async_client: AsyncMock) -> None: """Test AsyncScenarioRun initialization.""" - run = AsyncScenarioRun(mock_async_client, "run_123", "dev_123") - assert run.id == "run_123" - assert run.devbox_id == "dev_123" + run = AsyncScenarioRun(mock_async_client, "scr_123", "dbx_123") + assert run.id == "scr_123" + assert run.devbox_id == "dbx_123" def test_repr(self, mock_async_client: AsyncMock) -> None: """Test AsyncScenarioRun string representation.""" - run = AsyncScenarioRun(mock_async_client, "run_123", "dev_123") - assert repr(run) == "" + run = AsyncScenarioRun(mock_async_client, "scr_123", "dbx_123") + assert repr(run) == "" def test_devbox_property(self, mock_async_client: AsyncMock) -> None: """Test devbox property returns AsyncDevbox wrapper.""" - run = AsyncScenarioRun(mock_async_client, "run_123", "dev_123") + run = AsyncScenarioRun(mock_async_client, "scr_123", "dbx_123") devbox = run.devbox - assert devbox.id == "dev_123" + assert devbox.id == "dbx_123" async def test_get_info(self, mock_async_client: AsyncMock, scenario_run_view: MockScenarioRunView) -> None: """Test get_info method.""" mock_async_client.scenarios.runs.retrieve = AsyncMock(return_value=scenario_run_view) - run = AsyncScenarioRun(mock_async_client, "run_123", "dev_123") + run = AsyncScenarioRun(mock_async_client, "scr_123", "dbx_123") result = await run.get_info() assert result == scenario_run_view - mock_async_client.scenarios.runs.retrieve.assert_awaited_once_with("run_123") + mock_async_client.scenarios.runs.retrieve.assert_awaited_once_with("scr_123") async def test_await_env_ready( self, @@ -51,10 +51,10 @@ async def test_await_env_ready( mock_async_client.devboxes.await_running = AsyncMock(return_value=devbox_view) mock_async_client.scenarios.runs.retrieve = AsyncMock(return_value=scenario_run_view) - run = AsyncScenarioRun(mock_async_client, "run_123", "dev_123") + run = AsyncScenarioRun(mock_async_client, "scr_123", "dbx_123") result = await run.await_env_ready() - mock_async_client.devboxes.await_running.assert_awaited_once_with("dev_123", polling_config=None) + mock_async_client.devboxes.await_running.assert_awaited_once_with("dbx_123", polling_config=None) assert result == scenario_run_view async def test_score(self, mock_async_client: AsyncMock, scenario_run_view: MockScenarioRunView) -> None: @@ -62,33 +62,33 @@ async def test_score(self, mock_async_client: AsyncMock, scenario_run_view: Mock scenario_run_view.state = "scoring" mock_async_client.scenarios.runs.score = AsyncMock(return_value=scenario_run_view) - run = AsyncScenarioRun(mock_async_client, "run_123", "dev_123") + run = AsyncScenarioRun(mock_async_client, "scr_123", "dbx_123") result = await run.score() assert result == scenario_run_view - mock_async_client.scenarios.runs.score.assert_awaited_once_with("run_123") + mock_async_client.scenarios.runs.score.assert_awaited_once_with("scr_123") async def test_await_scored(self, mock_async_client: AsyncMock, scenario_run_view: MockScenarioRunView) -> None: """Test await_scored method.""" scenario_run_view.state = "scored" mock_async_client.scenarios.runs.await_scored = AsyncMock(return_value=scenario_run_view) - run = AsyncScenarioRun(mock_async_client, "run_123", "dev_123") + run = AsyncScenarioRun(mock_async_client, "scr_123", "dbx_123") result = await run.await_scored() assert result == scenario_run_view - mock_async_client.scenarios.runs.await_scored.assert_awaited_once_with("run_123") + mock_async_client.scenarios.runs.await_scored.assert_awaited_once_with("scr_123") async def test_score_and_await(self, mock_async_client: AsyncMock, scenario_run_view: MockScenarioRunView) -> None: """Test score_and_await method.""" scenario_run_view.state = "scored" mock_async_client.scenarios.runs.score_and_await = AsyncMock(return_value=scenario_run_view) - run = AsyncScenarioRun(mock_async_client, "run_123", "dev_123") + run = AsyncScenarioRun(mock_async_client, "scr_123", "dbx_123") result = await run.score_and_await() assert result == scenario_run_view - mock_async_client.scenarios.runs.score_and_await.assert_awaited_once_with("run_123") + mock_async_client.scenarios.runs.score_and_await.assert_awaited_once_with("scr_123") async def test_score_and_complete( self, mock_async_client: AsyncMock, scenario_run_view: MockScenarioRunView @@ -97,33 +97,33 @@ async def test_score_and_complete( scenario_run_view.state = "completed" mock_async_client.scenarios.runs.score_and_complete = AsyncMock(return_value=scenario_run_view) - run = AsyncScenarioRun(mock_async_client, "run_123", "dev_123") + run = AsyncScenarioRun(mock_async_client, "scr_123", "dbx_123") result = await run.score_and_complete() assert result == scenario_run_view - mock_async_client.scenarios.runs.score_and_complete.assert_awaited_once_with("run_123") + mock_async_client.scenarios.runs.score_and_complete.assert_awaited_once_with("scr_123") async def test_complete(self, mock_async_client: AsyncMock, scenario_run_view: MockScenarioRunView) -> None: """Test complete method.""" scenario_run_view.state = "completed" mock_async_client.scenarios.runs.complete = AsyncMock(return_value=scenario_run_view) - run = AsyncScenarioRun(mock_async_client, "run_123", "dev_123") + run = AsyncScenarioRun(mock_async_client, "scr_123", "dbx_123") result = await run.complete() assert result == scenario_run_view - mock_async_client.scenarios.runs.complete.assert_awaited_once_with("run_123") + mock_async_client.scenarios.runs.complete.assert_awaited_once_with("scr_123") async def test_cancel(self, mock_async_client: AsyncMock, scenario_run_view: MockScenarioRunView) -> None: """Test cancel method.""" scenario_run_view.state = "canceled" mock_async_client.scenarios.runs.cancel = AsyncMock(return_value=scenario_run_view) - run = AsyncScenarioRun(mock_async_client, "run_123", "dev_123") + run = AsyncScenarioRun(mock_async_client, "scr_123", "dbx_123") result = await run.cancel() assert result == scenario_run_view - mock_async_client.scenarios.runs.cancel.assert_awaited_once_with("run_123") + mock_async_client.scenarios.runs.cancel.assert_awaited_once_with("scr_123") async def test_download_logs(self, mock_async_client: AsyncMock, tmp_path: Path) -> None: """Test download_logs method writes to file.""" @@ -131,11 +131,11 @@ async def test_download_logs(self, mock_async_client: AsyncMock, tmp_path: Path) mock_response.write_to_file = AsyncMock() mock_async_client.scenarios.runs.download_logs = AsyncMock(return_value=mock_response) - run = AsyncScenarioRun(mock_async_client, "run_123", "dev_123") + run = AsyncScenarioRun(mock_async_client, "scr_123", "dbx_123") output_path = tmp_path / "logs.zip" await run.download_logs(output_path) - mock_async_client.scenarios.runs.download_logs.assert_awaited_once_with("run_123") + mock_async_client.scenarios.runs.download_logs.assert_awaited_once_with("scr_123") mock_response.write_to_file.assert_awaited_once_with(output_path) async def test_get_score_when_scored(self, mock_async_client: AsyncMock) -> None: @@ -144,19 +144,19 @@ async def test_get_score_when_scored(self, mock_async_client: AsyncMock) -> None run_view = MockScenarioRunView(state="scored", scoring_contract_result=scoring_result) mock_async_client.scenarios.runs.retrieve = AsyncMock(return_value=run_view) - run = AsyncScenarioRun(mock_async_client, "run_123", "dev_123") + run = AsyncScenarioRun(mock_async_client, "scr_123", "dbx_123") result = await run.get_score() assert result == scoring_result - mock_async_client.scenarios.runs.retrieve.assert_awaited_once_with("run_123") + mock_async_client.scenarios.runs.retrieve.assert_awaited_once_with("scr_123") async def test_get_score_when_not_scored(self, mock_async_client: AsyncMock) -> None: """Test get_score returns None when not scored.""" run_view = MockScenarioRunView(state="running", scoring_contract_result=None) mock_async_client.scenarios.runs.retrieve = AsyncMock(return_value=run_view) - run = AsyncScenarioRun(mock_async_client, "run_123", "dev_123") + run = AsyncScenarioRun(mock_async_client, "scr_123", "dbx_123") result = await run.get_score() assert result is None - mock_async_client.scenarios.runs.retrieve.assert_awaited_once_with("run_123") + mock_async_client.scenarios.runs.retrieve.assert_awaited_once_with("scr_123") diff --git a/tests/sdk/test_async_scorer.py b/tests/sdk/test_async_scorer.py index a3eeea884..253ae9585 100644 --- a/tests/sdk/test_async_scorer.py +++ b/tests/sdk/test_async_scorer.py @@ -16,20 +16,20 @@ class TestAsyncScorer: def test_init(self, mock_async_client: AsyncMock) -> None: """Test AsyncScorer initialization.""" - scorer = AsyncScorer(mock_async_client, "scorer_123") - assert scorer.id == "scorer_123" + scorer = AsyncScorer(mock_async_client, "sco_123") + assert scorer.id == "sco_123" def test_repr(self, mock_async_client: AsyncMock) -> None: """Test AsyncScorer string representation.""" - scorer = AsyncScorer(mock_async_client, "scorer_123") - assert repr(scorer) == "" + scorer = AsyncScorer(mock_async_client, "sco_123") + assert repr(scorer) == "" @pytest.mark.asyncio async def test_get_info(self, mock_async_client: AsyncMock, scorer_view: MockScorerView) -> None: """Test get_info method.""" mock_async_client.scenarios.scorers.retrieve = AsyncMock(return_value=scorer_view) - scorer = AsyncScorer(mock_async_client, "scorer_123") + scorer = AsyncScorer(mock_async_client, "sco_123") result = await scorer.get_info() assert result == scorer_view @@ -38,10 +38,10 @@ async def test_get_info(self, mock_async_client: AsyncMock, scorer_view: MockSco @pytest.mark.asyncio async def test_update(self, mock_async_client: AsyncMock) -> None: """Test update method.""" - update_response = SimpleNamespace(id="scorer_123", type="updated_scorer", bash_script="echo 'score=1.0'") + update_response = SimpleNamespace(id="sco_123", type="updated_scorer", bash_script="echo 'score=1.0'") mock_async_client.scenarios.scorers.update = AsyncMock(return_value=update_response) - scorer = AsyncScorer(mock_async_client, "scorer_123") + scorer = AsyncScorer(mock_async_client, "sco_123") result = await scorer.update( type="updated_scorer", bash_script="echo 'score=1.0'", @@ -60,7 +60,7 @@ async def test_validate(self, mock_async_client: AsyncMock) -> None: ) mock_async_client.scenarios.scorers.validate = AsyncMock(return_value=validate_response) - scorer = AsyncScorer(mock_async_client, "scorer_123") + scorer = AsyncScorer(mock_async_client, "sco_123") result = await scorer.validate( scoring_context={"test": "context"}, ) diff --git a/tests/sdk/test_async_snapshot.py b/tests/sdk/test_async_snapshot.py index a7b946c11..e9dca48bc 100644 --- a/tests/sdk/test_async_snapshot.py +++ b/tests/sdk/test_async_snapshot.py @@ -17,20 +17,20 @@ class TestAsyncSnapshot: def test_init(self, mock_async_client: AsyncMock) -> None: """Test AsyncSnapshot initialization.""" - snapshot = AsyncSnapshot(mock_async_client, "snap_123") - assert snapshot.id == "snap_123" + snapshot = AsyncSnapshot(mock_async_client, "snp_123") + assert snapshot.id == "snp_123" def test_repr(self, mock_async_client: AsyncMock) -> None: """Test AsyncSnapshot string representation.""" - snapshot = AsyncSnapshot(mock_async_client, "snap_123") - assert repr(snapshot) == "" + snapshot = AsyncSnapshot(mock_async_client, "snp_123") + assert repr(snapshot) == "" @pytest.mark.asyncio async def test_get_info(self, mock_async_client: AsyncMock, snapshot_view: MockSnapshotView) -> None: """Test get_info method.""" mock_async_client.devboxes.disk_snapshots.query_status = AsyncMock(return_value=snapshot_view) - snapshot = AsyncSnapshot(mock_async_client, "snap_123") + snapshot = AsyncSnapshot(mock_async_client, "snp_123") result = await snapshot.get_info( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -44,10 +44,10 @@ async def test_get_info(self, mock_async_client: AsyncMock, snapshot_view: MockS @pytest.mark.asyncio async def test_update(self, mock_async_client: AsyncMock) -> None: """Test update method.""" - updated_snapshot = SimpleNamespace(id="snap_123", name="updated-name") + updated_snapshot = SimpleNamespace(id="snp_123", name="updated-name") mock_async_client.devboxes.disk_snapshots.update = AsyncMock(return_value=updated_snapshot) - snapshot = AsyncSnapshot(mock_async_client, "snap_123") + snapshot = AsyncSnapshot(mock_async_client, "snp_123") result = await snapshot.update( commit_message="Update message", metadata={"key": "value"}, @@ -67,7 +67,7 @@ async def test_delete(self, mock_async_client: AsyncMock) -> None: """Test delete method.""" mock_async_client.devboxes.disk_snapshots.delete = AsyncMock(return_value=object()) - snapshot = AsyncSnapshot(mock_async_client, "snap_123") + snapshot = AsyncSnapshot(mock_async_client, "snp_123") result = await snapshot.delete( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -85,7 +85,7 @@ async def test_await_completed(self, mock_async_client: AsyncMock, snapshot_view mock_async_client.devboxes.disk_snapshots.await_completed = AsyncMock(return_value=snapshot_view) polling_config = PollingConfig(timeout_seconds=60.0) - snapshot = AsyncSnapshot(mock_async_client, "snap_123") + snapshot = AsyncSnapshot(mock_async_client, "snp_123") result = await snapshot.await_completed( polling_config=polling_config, extra_headers={"X-Custom": "value"}, @@ -102,7 +102,7 @@ async def test_create_devbox(self, mock_async_client: AsyncMock, devbox_view: Mo """Test create_devbox method.""" mock_async_client.devboxes.create_and_await_running = AsyncMock(return_value=devbox_view) - snapshot = AsyncSnapshot(mock_async_client, "snap_123") + snapshot = AsyncSnapshot(mock_async_client, "snp_123") devbox = await snapshot.create_devbox( name="test-devbox", metadata={"key": "value"}, @@ -110,5 +110,5 @@ async def test_create_devbox(self, mock_async_client: AsyncMock, devbox_view: Mo extra_headers={"X-Custom": "value"}, ) - assert devbox.id == "dev_123" + assert devbox.id == "dbx_123" mock_async_client.devboxes.create_and_await_running.assert_awaited_once() diff --git a/tests/sdk/test_benchmark.py b/tests/sdk/test_benchmark.py new file mode 100644 index 000000000..1f4f12751 --- /dev/null +++ b/tests/sdk/test_benchmark.py @@ -0,0 +1,122 @@ +"""Comprehensive tests for sync Benchmark class.""" + +from __future__ import annotations + +from types import SimpleNamespace +from unittest.mock import Mock + +from tests.sdk.conftest import MockBenchmarkView, MockBenchmarkRunView +from runloop_api_client.sdk.benchmark import Benchmark +from runloop_api_client.sdk.benchmark_run import BenchmarkRun + + +class TestBenchmark: + """Tests for Benchmark class.""" + + def test_init(self, mock_client: Mock) -> None: + """Test Benchmark initialization.""" + benchmark = Benchmark(mock_client, "bmd_123") + assert benchmark.id == "bmd_123" + assert repr(benchmark) == "" + + def test_get_info(self, mock_client: Mock, benchmark_view: MockBenchmarkView) -> None: + """Test get_info method.""" + mock_client.benchmarks.retrieve.return_value = benchmark_view + + benchmark = Benchmark(mock_client, "bmd_123") + result = benchmark.get_info() + + assert result == benchmark_view + mock_client.benchmarks.retrieve.assert_called_once_with("bmd_123") + + def test_update(self, mock_client: Mock, benchmark_view: MockBenchmarkView) -> None: + """Test update method.""" + benchmark_view.name = "updated-name" + mock_client.benchmarks.update.return_value = benchmark_view + + benchmark = Benchmark(mock_client, "bmd_123") + result = benchmark.update(name="updated-name") + + assert result == benchmark_view + mock_client.benchmarks.update.assert_called_once_with("bmd_123", name="updated-name") + + def test_run(self, mock_client: Mock, benchmark_run_view: MockBenchmarkRunView) -> None: + """Test run method.""" + mock_client.benchmarks.start_run.return_value = benchmark_run_view + + benchmark = Benchmark(mock_client, "bmd_123") + result = benchmark.start_run(run_name="test-run", metadata={"key": "value"}) + + assert isinstance(result, BenchmarkRun) + assert result.id == benchmark_run_view.id + assert result.benchmark_id == benchmark_run_view.benchmark_id + mock_client.benchmarks.start_run.assert_called_once_with( + benchmark_id="bmd_123", run_name="test-run", metadata={"key": "value"} + ) + + def test_add_scenarios(self, mock_client: Mock, benchmark_view: MockBenchmarkView) -> None: + """Test add_scenarios method.""" + benchmark_view.scenario_ids = ["scn_001", "scn_002"] + mock_client.benchmarks.update_scenarios.return_value = benchmark_view + + benchmark = Benchmark(mock_client, "bmd_123") + result = benchmark.add_scenarios(["scn_001", "scn_002"]) + + assert result == benchmark_view + mock_client.benchmarks.update_scenarios.assert_called_once_with( + "bmd_123", scenarios_to_add=["scn_001", "scn_002"] + ) + + def test_remove_scenarios(self, mock_client: Mock, benchmark_view: MockBenchmarkView) -> None: + """Test remove_scenarios method.""" + mock_client.benchmarks.update_scenarios.return_value = benchmark_view + + benchmark = Benchmark(mock_client, "bmd_123") + result = benchmark.remove_scenarios(["scn_001"]) + + assert result == benchmark_view + mock_client.benchmarks.update_scenarios.assert_called_once_with("bmd_123", scenarios_to_remove=["scn_001"]) + + def test_list_runs_single(self, mock_client: Mock, benchmark_run_view: MockBenchmarkRunView) -> None: + """Test list_runs method with single result.""" + page = SimpleNamespace(runs=[benchmark_run_view]) + mock_client.benchmarks.runs.list.return_value = page + + benchmark = Benchmark(mock_client, "bmd_123") + result = benchmark.list_runs() + + assert len(result) == 1 + assert isinstance(result[0], BenchmarkRun) + assert result[0].id == benchmark_run_view.id + assert result[0].benchmark_id == benchmark_run_view.benchmark_id + mock_client.benchmarks.runs.list.assert_called_once_with(benchmark_id="bmd_123") + + def test_list_runs_multiple(self, mock_client: Mock) -> None: + """Test list_runs method with multiple results.""" + run_view1 = MockBenchmarkRunView(id="bmr_001") + run_view2 = MockBenchmarkRunView(id="bmr_002") + page = SimpleNamespace(runs=[run_view1, run_view2]) + mock_client.benchmarks.runs.list.return_value = page + + benchmark = Benchmark(mock_client, "bmd_123") + result = benchmark.list_runs() + + assert len(result) == 2 + assert isinstance(result[0], BenchmarkRun) + assert isinstance(result[1], BenchmarkRun) + assert result[0].id == run_view1.id + assert result[0].benchmark_id == run_view1.benchmark_id + assert result[1].id == run_view2.id + assert result[1].benchmark_id == run_view2.benchmark_id + mock_client.benchmarks.runs.list.assert_called_once_with(benchmark_id="bmd_123") + + def test_list_runs_with_params(self, mock_client: Mock, benchmark_run_view: MockBenchmarkRunView) -> None: + """Test list_runs method with filtering parameters.""" + page = SimpleNamespace(runs=[benchmark_run_view]) + mock_client.benchmarks.runs.list.return_value = page + + benchmark = Benchmark(mock_client, "bmd_123") + result = benchmark.list_runs(limit=10, name="test-run") + + assert len(result) == 1 + mock_client.benchmarks.runs.list.assert_called_once_with(benchmark_id="bmd_123", limit=10, name="test-run") diff --git a/tests/sdk/test_benchmark_run.py b/tests/sdk/test_benchmark_run.py index d54fb9432..e7a826a90 100644 --- a/tests/sdk/test_benchmark_run.py +++ b/tests/sdk/test_benchmark_run.py @@ -15,102 +15,100 @@ class TestBenchmarkRun: def test_init(self, mock_client: Mock) -> None: """Test BenchmarkRun initialization.""" - run = BenchmarkRun(mock_client, "bench_run_123", "bench_123") - assert run.id == "bench_run_123" - assert run.benchmark_id == "bench_123" + run = BenchmarkRun(mock_client, "bmr_123", "bmd_123") + assert run.id == "bmr_123" + assert run.benchmark_id == "bmd_123" def test_repr(self, mock_client: Mock) -> None: """Test BenchmarkRun string representation.""" - run = BenchmarkRun(mock_client, "bench_run_123", "bench_123") - assert repr(run) == "" + run = BenchmarkRun(mock_client, "bmr_123", "bmd_123") + assert repr(run) == "" def test_get_info(self, mock_client: Mock, benchmark_run_view: MockBenchmarkRunView) -> None: """Test get_info method.""" mock_client.benchmarks.runs.retrieve.return_value = benchmark_run_view - run = BenchmarkRun(mock_client, "bench_run_123", "bench_123") + run = BenchmarkRun(mock_client, "bmr_123", "bmd_123") result = run.get_info() assert result == benchmark_run_view - mock_client.benchmarks.runs.retrieve.assert_called_once_with("bench_run_123") + mock_client.benchmarks.runs.retrieve.assert_called_once_with("bmr_123") def test_cancel(self, mock_client: Mock, benchmark_run_view: MockBenchmarkRunView) -> None: """Test cancel method.""" benchmark_run_view.state = "canceled" mock_client.benchmarks.runs.cancel.return_value = benchmark_run_view - run = BenchmarkRun(mock_client, "bench_run_123", "bench_123") + run = BenchmarkRun(mock_client, "bmr_123", "bmd_123") result = run.cancel() assert result == benchmark_run_view assert result.state == "canceled" - mock_client.benchmarks.runs.cancel.assert_called_once_with("bench_run_123") + mock_client.benchmarks.runs.cancel.assert_called_once_with("bmr_123") def test_complete(self, mock_client: Mock, benchmark_run_view: MockBenchmarkRunView) -> None: """Test complete method.""" benchmark_run_view.state = "completed" mock_client.benchmarks.runs.complete.return_value = benchmark_run_view - run = BenchmarkRun(mock_client, "bench_run_123", "bench_123") + run = BenchmarkRun(mock_client, "bmr_123", "bmd_123") result = run.complete() assert result == benchmark_run_view assert result.state == "completed" - mock_client.benchmarks.runs.complete.assert_called_once_with("bench_run_123") + mock_client.benchmarks.runs.complete.assert_called_once_with("bmr_123") def test_list_scenario_runs_empty(self, mock_client: Mock) -> None: """Test list_scenario_runs method with empty results.""" page = SimpleNamespace(runs=[]) mock_client.benchmarks.runs.list_scenario_runs.return_value = page - run = BenchmarkRun(mock_client, "bench_run_123", "bench_123") + run = BenchmarkRun(mock_client, "bmr_123", "bmd_123") result = run.list_scenario_runs() assert len(result) == 0 - mock_client.benchmarks.runs.list_scenario_runs.assert_called_once_with("bench_run_123") + mock_client.benchmarks.runs.list_scenario_runs.assert_called_once_with("bmr_123") def test_list_scenario_runs_single(self, mock_client: Mock, scenario_run_view: MockScenarioRunView) -> None: """Test list_scenario_runs method with single result.""" page = SimpleNamespace(runs=[scenario_run_view]) mock_client.benchmarks.runs.list_scenario_runs.return_value = page - run = BenchmarkRun(mock_client, "bench_run_123", "bench_123") + run = BenchmarkRun(mock_client, "bmr_123", "bmd_123") result = run.list_scenario_runs() assert len(result) == 1 assert isinstance(result[0], ScenarioRun) assert result[0].id == scenario_run_view.id assert result[0].devbox_id == scenario_run_view.devbox_id - mock_client.benchmarks.runs.list_scenario_runs.assert_called_once_with("bench_run_123") + mock_client.benchmarks.runs.list_scenario_runs.assert_called_once_with("bmr_123") def test_list_scenario_runs_multiple(self, mock_client: Mock) -> None: """Test list_scenario_runs method with multiple results.""" - scenario_run_view1 = MockScenarioRunView(id="run_001", devbox_id="dev_001") - scenario_run_view2 = MockScenarioRunView(id="run_002", devbox_id="dev_002") + scenario_run_view1 = MockScenarioRunView(id="scr_001", devbox_id="dev_001") + scenario_run_view2 = MockScenarioRunView(id="scr_002", devbox_id="dev_002") page = SimpleNamespace(runs=[scenario_run_view1, scenario_run_view2]) mock_client.benchmarks.runs.list_scenario_runs.return_value = page - run = BenchmarkRun(mock_client, "bench_run_123", "bench_123") + run = BenchmarkRun(mock_client, "bmr_123", "bmd_123") result = run.list_scenario_runs() assert len(result) == 2 assert isinstance(result[0], ScenarioRun) assert isinstance(result[1], ScenarioRun) - assert result[0].id == "run_001" - assert result[1].id == "run_002" - mock_client.benchmarks.runs.list_scenario_runs.assert_called_once_with("bench_run_123") + assert result[0].id == "scr_001" + assert result[1].id == "scr_002" + mock_client.benchmarks.runs.list_scenario_runs.assert_called_once_with("bmr_123") def test_list_scenario_runs_with_params(self, mock_client: Mock, scenario_run_view: MockScenarioRunView) -> None: """Test list_scenario_runs method with filtering parameters.""" page = SimpleNamespace(runs=[scenario_run_view]) mock_client.benchmarks.runs.list_scenario_runs.return_value = page - run = BenchmarkRun(mock_client, "bench_run_123", "bench_123") + run = BenchmarkRun(mock_client, "bmr_123", "bmd_123") result = run.list_scenario_runs(limit=10, state="completed") assert len(result) == 1 assert isinstance(result[0], ScenarioRun) assert result[0].id == scenario_run_view.id - mock_client.benchmarks.runs.list_scenario_runs.assert_called_once_with( - "bench_run_123", limit=10, state="completed" - ) + mock_client.benchmarks.runs.list_scenario_runs.assert_called_once_with("bmr_123", limit=10, state="completed") diff --git a/tests/sdk/test_blueprint.py b/tests/sdk/test_blueprint.py index 2c6bc6580..40cbed3f6 100644 --- a/tests/sdk/test_blueprint.py +++ b/tests/sdk/test_blueprint.py @@ -14,19 +14,19 @@ class TestBlueprint: def test_init(self, mock_client: Mock) -> None: """Test Blueprint initialization.""" - blueprint = Blueprint(mock_client, "bp_123") - assert blueprint.id == "bp_123" + blueprint = Blueprint(mock_client, "bpt_123") + assert blueprint.id == "bpt_123" def test_repr(self, mock_client: Mock) -> None: """Test Blueprint string representation.""" - blueprint = Blueprint(mock_client, "bp_123") - assert repr(blueprint) == "" + blueprint = Blueprint(mock_client, "bpt_123") + assert repr(blueprint) == "" def test_get_info(self, mock_client: Mock, blueprint_view: MockBlueprintView) -> None: """Test get_info method.""" mock_client.blueprints.retrieve.return_value = blueprint_view - blueprint = Blueprint(mock_client, "bp_123") + blueprint = Blueprint(mock_client, "bpt_123") result = blueprint.get_info( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -36,7 +36,7 @@ def test_get_info(self, mock_client: Mock, blueprint_view: MockBlueprintView) -> assert result == blueprint_view mock_client.blueprints.retrieve.assert_called_once_with( - "bp_123", + "bpt_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, @@ -48,7 +48,7 @@ def test_logs(self, mock_client: Mock) -> None: logs_view = SimpleNamespace(logs=[]) mock_client.blueprints.logs.return_value = logs_view - blueprint = Blueprint(mock_client, "bp_123") + blueprint = Blueprint(mock_client, "bpt_123") result = blueprint.logs( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -58,7 +58,7 @@ def test_logs(self, mock_client: Mock) -> None: assert result == logs_view mock_client.blueprints.logs.assert_called_once_with( - "bp_123", + "bpt_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, @@ -69,7 +69,7 @@ def test_delete(self, mock_client: Mock) -> None: """Test delete method.""" mock_client.blueprints.delete.return_value = object() - blueprint = Blueprint(mock_client, "bp_123") + blueprint = Blueprint(mock_client, "bpt_123") result = blueprint.delete( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -79,7 +79,7 @@ def test_delete(self, mock_client: Mock) -> None: assert result is not None # Verify return value is propagated mock_client.blueprints.delete.assert_called_once_with( - "bp_123", + "bpt_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, @@ -90,7 +90,7 @@ def test_create_devbox(self, mock_client: Mock, devbox_view: MockDevboxView) -> """Test create_devbox method.""" mock_client.devboxes.create_and_await_running.return_value = devbox_view - blueprint = Blueprint(mock_client, "bp_123") + blueprint = Blueprint(mock_client, "bpt_123") devbox = blueprint.create_devbox( name="test-devbox", metadata={"key": "value"}, @@ -98,9 +98,9 @@ def test_create_devbox(self, mock_client: Mock, devbox_view: MockDevboxView) -> extra_headers={"X-Custom": "value"}, ) - assert devbox.id == "dev_123" + assert devbox.id == "dbx_123" mock_client.devboxes.create_and_await_running.assert_called_once() call_kwargs = mock_client.devboxes.create_and_await_running.call_args[1] - assert call_kwargs["blueprint_id"] == "bp_123" + assert call_kwargs["blueprint_id"] == "bpt_123" assert call_kwargs["name"] == "test-devbox" assert call_kwargs["metadata"] == {"key": "value"} diff --git a/tests/sdk/test_execution.py b/tests/sdk/test_execution.py index 63b244d0e..249d670bf 100644 --- a/tests/sdk/test_execution.py +++ b/tests/sdk/test_execution.py @@ -83,9 +83,9 @@ class TestExecution: def test_init(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test Execution initialization.""" - execution = Execution(mock_client, "dev_123", execution_view) # type: ignore[arg-type] - assert execution.execution_id == "exec_123" - assert execution.devbox_id == "dev_123" + execution = Execution(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] + assert execution.execution_id == "exn_123" + assert execution.devbox_id == "dbx_123" assert execution._initial_result == execution_view def test_init_with_streaming_group(self, mock_client: Mock, execution_view: MockExecutionView) -> None: @@ -94,46 +94,46 @@ def test_init_with_streaming_group(self, mock_client: Mock, execution_view: Mock stop_event = threading.Event() streaming_group = _StreamingGroup(threads, stop_event) - execution = Execution(mock_client, "dev_123", execution_view, streaming_group) # type: ignore[arg-type] + execution = Execution(mock_client, "dbx_123", execution_view, streaming_group) # type: ignore[arg-type] assert execution._streaming_group is streaming_group def test_properties(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test Execution properties.""" - execution = Execution(mock_client, "dev_123", execution_view) # type: ignore[arg-type] - assert execution.execution_id == "exec_123" - assert execution.devbox_id == "dev_123" + execution = Execution(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] + assert execution.execution_id == "exn_123" + assert execution.devbox_id == "dbx_123" def test_repr(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test Execution repr formatting.""" - execution = Execution(mock_client, "dev_123", execution_view) # type: ignore[arg-type] - assert repr(execution) == "" + execution = Execution(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] + assert repr(execution) == "" def test_result_already_completed(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test result delegates to wait_for_command when already completed.""" mock_client.devboxes = Mock() mock_client.devboxes.wait_for_command.return_value = execution_view - execution = Execution(mock_client, "dev_123", execution_view) # type: ignore[arg-type] + execution = Execution(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] result = execution.result() assert result.exit_code == 0 assert result.stdout(num_lines=10) == "output" mock_client.devboxes.wait_for_command.assert_called_once_with( - "exec_123", - devbox_id="dev_123", + "exn_123", + devbox_id="dbx_123", statuses=["completed"], ) def test_result_needs_polling(self, mock_client: Mock) -> None: """Test result when execution needs to poll for completion.""" running_execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", ) completed_execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="output", @@ -145,27 +145,27 @@ def test_result_needs_polling(self, mock_client: Mock) -> None: mock_client.devboxes = Mock() mock_client.devboxes.wait_for_command.return_value = completed_execution - execution = Execution(mock_client, "dev_123", running_execution) # type: ignore[arg-type] + execution = Execution(mock_client, "dbx_123", running_execution) # type: ignore[arg-type] result = execution.result() assert result.exit_code == 0 assert result.stdout(num_lines=10) == "output" mock_client.devboxes.wait_for_command.assert_called_once_with( - "exec_123", - devbox_id="dev_123", + "exn_123", + devbox_id="dbx_123", statuses=["completed"], ) def test_result_with_streaming_group(self, mock_client: Mock) -> None: """Test result waits for streaming group to finish.""" running_execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", ) completed_execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="output", @@ -180,7 +180,7 @@ def test_result_with_streaming_group(self, mock_client: Mock) -> None: thread.start() streaming_group = _StreamingGroup([thread], stop_event) - execution = Execution(mock_client, "dev_123", running_execution, streaming_group) # type: ignore[arg-type] + execution = Execution(mock_client, "dbx_123", running_execution, streaming_group) # type: ignore[arg-type] result = execution.result() assert result.exit_code == 0 @@ -190,8 +190,8 @@ def test_result_with_streaming_group(self, mock_client: Mock) -> None: def test_result_passes_options(self, mock_client: Mock) -> None: """Ensure options are forwarded to wait_for_command.""" execution_view = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="output", @@ -201,12 +201,12 @@ def test_result_passes_options(self, mock_client: Mock) -> None: mock_client.devboxes = Mock() mock_client.devboxes.wait_for_command.return_value = execution_view - execution = Execution(mock_client, "dev_123", execution_view) # type: ignore[arg-type] + execution = Execution(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] execution.result(timeout=30.0, idempotency_key="abc123") mock_client.devboxes.wait_for_command.assert_called_once_with( - "exec_123", - devbox_id="dev_123", + "exn_123", + devbox_id="dbx_123", statuses=["completed"], timeout=30.0, idempotency_key="abc123", @@ -215,31 +215,31 @@ def test_result_passes_options(self, mock_client: Mock) -> None: def test_get_state(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test get_state method.""" updated_execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", ) mock_client.devboxes.executions = Mock() mock_client.devboxes.executions.retrieve.return_value = updated_execution - execution = Execution(mock_client, "dev_123", execution_view) # type: ignore[arg-type] + execution = Execution(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] result = execution.get_state() assert result == updated_execution assert execution._initial_result == execution_view mock_client.devboxes.executions.retrieve.assert_called_once_with( - "exec_123", - devbox_id="dev_123", + "exn_123", + devbox_id="dbx_123", ) def test_kill(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test kill method.""" mock_client.devboxes.executions.kill.return_value = None - execution = Execution(mock_client, "dev_123", execution_view) # type: ignore[arg-type] + execution = Execution(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] execution.kill() mock_client.devboxes.executions.kill.assert_called_once_with( - "exec_123", - devbox_id="dev_123", + "exn_123", + devbox_id="dbx_123", ) diff --git a/tests/sdk/test_execution_result.py b/tests/sdk/test_execution_result.py index 689b108d5..7bc4fbfef 100644 --- a/tests/sdk/test_execution_result.py +++ b/tests/sdk/test_execution_result.py @@ -14,31 +14,31 @@ class TestExecutionResult: def test_init(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test ExecutionResult initialization.""" - result = ExecutionResult(mock_client, "dev_123", execution_view) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] # Verify via public API - assert result.devbox_id == "dev_123" - assert result.execution_id == "exec_123" + assert result.devbox_id == "dbx_123" + assert result.execution_id == "exn_123" def test_devbox_id_property(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test devbox_id property.""" - result = ExecutionResult(mock_client, "dev_123", execution_view) # type: ignore[arg-type] - assert result.devbox_id == "dev_123" + result = ExecutionResult(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] + assert result.devbox_id == "dbx_123" def test_execution_id_property(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test execution_id property.""" - result = ExecutionResult(mock_client, "dev_123", execution_view) # type: ignore[arg-type] - assert result.execution_id == "exec_123" + result = ExecutionResult(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] + assert result.execution_id == "exn_123" def test_exit_code_property(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test exit_code property.""" - result = ExecutionResult(mock_client, "dev_123", execution_view) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] assert result.exit_code == 0 def test_exit_code_none(self, mock_client: Mock) -> None: """Test exit_code property when exit_status is None.""" execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", exit_status=None, stdout="", @@ -46,19 +46,19 @@ def test_exit_code_none(self, mock_client: Mock) -> None: stdout_truncated=False, stderr_truncated=False, ) - result = ExecutionResult(mock_client, "dev_123", execution) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution) # type: ignore[arg-type] assert result.exit_code is None def test_success_property(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test success property.""" - result = ExecutionResult(mock_client, "dev_123", execution_view) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] assert result.success is True def test_success_false(self, mock_client: Mock) -> None: """Test success property when exit code is non-zero.""" execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=1, stdout="", @@ -66,19 +66,19 @@ def test_success_false(self, mock_client: Mock) -> None: stdout_truncated=False, stderr_truncated=False, ) - result = ExecutionResult(mock_client, "dev_123", execution) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution) # type: ignore[arg-type] assert result.success is False def test_failed_property(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test failed property when exit code is zero.""" - result = ExecutionResult(mock_client, "dev_123", execution_view) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] assert result.failed is False def test_failed_true(self, mock_client: Mock) -> None: """Test failed property when exit code is non-zero.""" execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=1, stdout="", @@ -86,14 +86,14 @@ def test_failed_true(self, mock_client: Mock) -> None: stdout_truncated=False, stderr_truncated=False, ) - result = ExecutionResult(mock_client, "dev_123", execution) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution) # type: ignore[arg-type] assert result.failed is True def test_failed_none(self, mock_client: Mock) -> None: """Test failed property when exit_status is None.""" execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="running", exit_status=None, stdout="", @@ -101,20 +101,20 @@ def test_failed_none(self, mock_client: Mock) -> None: stdout_truncated=False, stderr_truncated=False, ) - result = ExecutionResult(mock_client, "dev_123", execution) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution) # type: ignore[arg-type] assert result.failed is False def test_stdout(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test stdout method.""" - result = ExecutionResult(mock_client, "dev_123", execution_view) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] assert result.stdout() == "output" assert result.stdout(num_lines=10) == "output" def test_stdout_empty(self, mock_client: Mock) -> None: """Test stdout method when stdout is None.""" execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout=None, @@ -122,14 +122,14 @@ def test_stdout_empty(self, mock_client: Mock) -> None: stdout_truncated=False, stderr_truncated=False, ) - result = ExecutionResult(mock_client, "dev_123", execution) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution) # type: ignore[arg-type] assert result.stdout() == "" def test_stderr(self, mock_client: Mock) -> None: """Test stderr method.""" execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=1, stdout="", @@ -137,18 +137,18 @@ def test_stderr(self, mock_client: Mock) -> None: stdout_truncated=False, stderr_truncated=False, ) - result = ExecutionResult(mock_client, "dev_123", execution) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution) # type: ignore[arg-type] assert result.stderr() == "error message" assert result.stderr(num_lines=20) == "error message" def test_stderr_empty(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test stderr method when stderr is None.""" - result = ExecutionResult(mock_client, "dev_123", execution_view) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] assert result.stderr() == "" def test_result_property(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test result property.""" - result = ExecutionResult(mock_client, "dev_123", execution_view) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] assert result.result == execution_view def test_stdout_with_truncation_and_streaming(self, mock_client: Mock, mock_stream: Mock) -> None: @@ -165,8 +165,8 @@ def test_stdout_with_truncation_and_streaming(self, mock_client: Mock, mock_stre mock_client.devboxes.executions.stream_stdout_updates = Mock(return_value=mock_stream) execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="partial", @@ -174,12 +174,12 @@ def test_stdout_with_truncation_and_streaming(self, mock_client: Mock, mock_stre stdout_truncated=True, stderr_truncated=False, ) - result = ExecutionResult(mock_client, "dev_123", execution) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution) # type: ignore[arg-type] # Should stream full output output = result.stdout() assert output == "line1\nline2\nline3\n" - mock_client.devboxes.executions.stream_stdout_updates.assert_called_once_with("exec_123", devbox_id="dev_123") + mock_client.devboxes.executions.stream_stdout_updates.assert_called_once_with("exn_123", devbox_id="dbx_123") def test_stderr_with_truncation_and_streaming(self, mock_client: Mock, mock_stream: Mock) -> None: """Test stderr streams full output when truncated.""" @@ -194,8 +194,8 @@ def test_stderr_with_truncation_and_streaming(self, mock_client: Mock, mock_stre mock_client.devboxes.executions.stream_stderr_updates = Mock(return_value=mock_stream) execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="", @@ -203,12 +203,12 @@ def test_stderr_with_truncation_and_streaming(self, mock_client: Mock, mock_stre stdout_truncated=False, stderr_truncated=True, ) - result = ExecutionResult(mock_client, "dev_123", execution) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution) # type: ignore[arg-type] # Should stream full output output = result.stderr() assert output == "error1\nerror2\n" - mock_client.devboxes.executions.stream_stderr_updates.assert_called_once_with("exec_123", devbox_id="dev_123") + mock_client.devboxes.executions.stream_stderr_updates.assert_called_once_with("exn_123", devbox_id="dbx_123") def test_stdout_with_num_lines_when_truncated(self, mock_client: Mock, mock_stream: Mock) -> None: """Test stdout with num_lines parameter when truncated.""" @@ -223,8 +223,8 @@ def test_stdout_with_num_lines_when_truncated(self, mock_client: Mock, mock_stre mock_client.devboxes.executions.stream_stdout_updates = Mock(return_value=mock_stream) execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="line1\n", @@ -232,7 +232,7 @@ def test_stdout_with_num_lines_when_truncated(self, mock_client: Mock, mock_stre stdout_truncated=True, stderr_truncated=False, ) - result = ExecutionResult(mock_client, "dev_123", execution) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution) # type: ignore[arg-type] # Should stream and return last 2 lines output = result.stdout(num_lines=2) @@ -241,8 +241,8 @@ def test_stdout_with_num_lines_when_truncated(self, mock_client: Mock, mock_stre def test_stdout_no_streaming_when_not_truncated(self, mock_client: Mock) -> None: """Test stdout doesn't stream when not truncated.""" execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="complete output", @@ -250,7 +250,7 @@ def test_stdout_no_streaming_when_not_truncated(self, mock_client: Mock) -> None stdout_truncated=False, stderr_truncated=False, ) - result = ExecutionResult(mock_client, "dev_123", execution) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution) # type: ignore[arg-type] # Should return existing output without streaming output = result.stdout() @@ -259,8 +259,8 @@ def test_stdout_no_streaming_when_not_truncated(self, mock_client: Mock) -> None def test_stdout_with_num_lines_no_truncation(self, mock_client: Mock) -> None: """Test stdout with num_lines when not truncated.""" execution = SimpleNamespace( - execution_id="exec_123", - devbox_id="dev_123", + execution_id="exn_123", + devbox_id="dbx_123", status="completed", exit_status=0, stdout="line1\nline2\nline3\nline4\nline5", @@ -268,7 +268,7 @@ def test_stdout_with_num_lines_no_truncation(self, mock_client: Mock) -> None: stdout_truncated=False, stderr_truncated=False, ) - result = ExecutionResult(mock_client, "dev_123", execution) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution) # type: ignore[arg-type] # Should return last 2 lines without streaming output = result.stdout(num_lines=2) @@ -276,7 +276,7 @@ def test_stdout_with_num_lines_no_truncation(self, mock_client: Mock) -> None: def test_count_non_empty_lines(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test the _count_non_empty_lines helper method.""" - result = ExecutionResult(mock_client, "dev_123", execution_view) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] # Test various input strings assert result._count_non_empty_lines("") == 0 @@ -288,7 +288,7 @@ def test_count_non_empty_lines(self, mock_client: Mock, execution_view: MockExec def test_get_last_n_lines(self, mock_client: Mock, execution_view: MockExecutionView) -> None: """Test the _get_last_n_lines helper method.""" - result = ExecutionResult(mock_client, "dev_123", execution_view) # type: ignore[arg-type] + result = ExecutionResult(mock_client, "dbx_123", execution_view) # type: ignore[arg-type] # Test various scenarios assert result._get_last_n_lines("", 5) == "" diff --git a/tests/sdk/test_ops.py b/tests/sdk/test_ops.py index e66c7f097..0a2d9bd56 100644 --- a/tests/sdk/test_ops.py +++ b/tests/sdk/test_ops.py @@ -55,7 +55,7 @@ def test_create(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: ) assert isinstance(devbox, Devbox) - assert devbox.id == "dev_123" + assert devbox.id == "dbx_123" mock_client.devboxes.create_and_await_running.assert_called_once() def test_create_from_blueprint_id(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: @@ -64,15 +64,15 @@ def test_create_from_blueprint_id(self, mock_client: Mock, devbox_view: MockDevb ops = DevboxOps(mock_client) devbox = ops.create_from_blueprint_id( - "bp_123", + "bpt_123", name="test-devbox", metadata={"key": "value"}, ) assert isinstance(devbox, Devbox) - assert devbox.id == "dev_123" + assert devbox.id == "dbx_123" call_kwargs = mock_client.devboxes.create_and_await_running.call_args[1] - assert call_kwargs["blueprint_id"] == "bp_123" + assert call_kwargs["blueprint_id"] == "bpt_123" def test_create_from_blueprint_name(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: """Test create_from_blueprint_name method.""" @@ -94,24 +94,24 @@ def test_create_from_snapshot(self, mock_client: Mock, devbox_view: MockDevboxVi ops = DevboxOps(mock_client) devbox = ops.create_from_snapshot( - "snap_123", + "snp_123", name="test-devbox", ) assert isinstance(devbox, Devbox) call_kwargs = mock_client.devboxes.create_and_await_running.call_args[1] - assert call_kwargs["snapshot_id"] == "snap_123" + assert call_kwargs["snapshot_id"] == "snp_123" def test_from_id(self, mock_client: Mock, devbox_view: MockDevboxView) -> None: """Test from_id method waits for running.""" mock_client.devboxes.await_running.return_value = devbox_view ops = DevboxOps(mock_client) - devbox = ops.from_id("dev_123") + devbox = ops.from_id("dbx_123") assert isinstance(devbox, Devbox) - assert devbox.id == "dev_123" - mock_client.devboxes.await_running.assert_called_once_with("dev_123") + assert devbox.id == "dbx_123" + mock_client.devboxes.await_running.assert_called_once_with("dbx_123") def test_list_empty(self, mock_client: Mock) -> None: """Test list method with empty results.""" @@ -138,7 +138,7 @@ def test_list_single(self, mock_client: Mock, devbox_view: MockDevboxView) -> No assert len(devboxes) == 1 assert isinstance(devboxes[0], Devbox) - assert devboxes[0].id == "dev_123" + assert devboxes[0].id == "dbx_123" mock_client.devboxes.list.assert_called_once() def test_list_multiple(self, mock_client: Mock) -> None: @@ -168,7 +168,7 @@ def test_list_empty(self, mock_client: Mock) -> None: mock_client.devboxes.disk_snapshots.list.return_value = page ops = SnapshotOps(mock_client) - snapshots = ops.list(devbox_id="dev_123", limit=10) + snapshots = ops.list(devbox_id="dbx_123", limit=10) assert len(snapshots) == 0 mock_client.devboxes.disk_snapshots.list.assert_called_once() @@ -180,14 +180,14 @@ def test_list_single(self, mock_client: Mock, snapshot_view: MockSnapshotView) - ops = SnapshotOps(mock_client) snapshots = ops.list( - devbox_id="dev_123", + devbox_id="dbx_123", limit=10, starting_after="snap_000", ) assert len(snapshots) == 1 assert isinstance(snapshots[0], Snapshot) - assert snapshots[0].id == "snap_123" + assert snapshots[0].id == "snp_123" mock_client.devboxes.disk_snapshots.list.assert_called_once() def test_list_multiple(self, mock_client: Mock) -> None: @@ -198,7 +198,7 @@ def test_list_multiple(self, mock_client: Mock) -> None: mock_client.devboxes.disk_snapshots.list.return_value = page ops = SnapshotOps(mock_client) - snapshots = ops.list(devbox_id="dev_123", limit=10) + snapshots = ops.list(devbox_id="dbx_123", limit=10) assert len(snapshots) == 2 assert isinstance(snapshots[0], Snapshot) @@ -210,10 +210,10 @@ def test_list_multiple(self, mock_client: Mock) -> None: def test_from_id(self, mock_client: Mock) -> None: """Test from_id method.""" ops = SnapshotOps(mock_client) - snapshot = ops.from_id("snap_123") + snapshot = ops.from_id("snp_123") assert isinstance(snapshot, Snapshot) - assert snapshot.id == "snap_123" + assert snapshot.id == "snp_123" class TestBlueprintOps: @@ -230,16 +230,16 @@ def test_create(self, mock_client: Mock, blueprint_view: MockBlueprintView) -> N ) assert isinstance(blueprint, Blueprint) - assert blueprint.id == "bp_123" + assert blueprint.id == "bpt_123" mock_client.blueprints.create_and_await_build_complete.assert_called_once() def test_from_id(self, mock_client: Mock) -> None: """Test from_id method.""" ops = BlueprintOps(mock_client) - blueprint = ops.from_id("bp_123") + blueprint = ops.from_id("bpt_123") assert isinstance(blueprint, Blueprint) - assert blueprint.id == "bp_123" + assert blueprint.id == "bpt_123" def test_list_empty(self, mock_client: Mock) -> None: """Test list method with empty results.""" @@ -266,7 +266,7 @@ def test_list_single(self, mock_client: Mock, blueprint_view: MockBlueprintView) assert len(blueprints) == 1 assert isinstance(blueprints[0], Blueprint) - assert blueprints[0].id == "bp_123" + assert blueprints[0].id == "bpt_123" mock_client.blueprints.list.assert_called_once() def test_list_multiple(self, mock_client: Mock) -> None: @@ -660,16 +660,16 @@ def test_create(self, mock_client: Mock, scorer_view: MockScorerView) -> None: ) assert isinstance(scorer, Scorer) - assert scorer.id == "scorer_123" + assert scorer.id == "sco_123" mock_client.scenarios.scorers.create.assert_called_once() def test_from_id(self, mock_client: Mock) -> None: """Test from_id method.""" ops = ScorerOps(mock_client) - scorer = ops.from_id("scorer_123") + scorer = ops.from_id("sco_123") assert isinstance(scorer, Scorer) - assert scorer.id == "scorer_123" + assert scorer.id == "sco_123" def test_list_empty(self, mock_client: Mock) -> None: """Test list method with empty results.""" @@ -693,7 +693,7 @@ def test_list_single(self, mock_client: Mock, scorer_view: MockScorerView) -> No assert len(scorers) == 1 assert isinstance(scorers[0], Scorer) - assert scorers[0].id == "scorer_123" + assert scorers[0].id == "sco_123" mock_client.scenarios.scorers.list.assert_called_once() def test_list_multiple(self, mock_client: Mock) -> None: @@ -727,16 +727,16 @@ def test_create(self, mock_client: Mock, agent_view: MockAgentView) -> None: ) assert isinstance(agent, Agent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_client.agents.create.assert_called_once() def test_from_id(self, mock_client: Mock) -> None: """Test from_id method.""" client = AgentOps(mock_client) - agent = client.from_id("agent_123") + agent = client.from_id("agt_123") assert isinstance(agent, Agent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" def test_list(self, mock_client: Mock) -> None: """Test list method.""" @@ -822,7 +822,7 @@ def test_create_from_npm(self, mock_client: Mock, agent_view: MockAgentView) -> ) assert isinstance(agent, Agent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_client.agents.create.assert_called_once_with( source={ "type": "npm", @@ -849,7 +849,7 @@ def test_create_from_npm_with_all_options(self, mock_client: Mock, agent_view: M ) assert isinstance(agent, Agent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_client.agents.create.assert_called_once_with( source={ "type": "npm", @@ -888,7 +888,7 @@ def test_create_from_pip(self, mock_client: Mock, agent_view: MockAgentView) -> ) assert isinstance(agent, Agent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_client.agents.create.assert_called_once_with( source={ "type": "pip", @@ -914,7 +914,7 @@ def test_create_from_pip_with_all_options(self, mock_client: Mock, agent_view: M ) assert isinstance(agent, Agent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_client.agents.create.assert_called_once_with( source={ "type": "pip", @@ -940,7 +940,7 @@ def test_create_from_git(self, mock_client: Mock, agent_view: MockAgentView) -> ) assert isinstance(agent, Agent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_client.agents.create.assert_called_once_with( source={ "type": "git", @@ -966,7 +966,7 @@ def test_create_from_git_with_all_options(self, mock_client: Mock, agent_view: M ) assert isinstance(agent, Agent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_client.agents.create.assert_called_once_with( source={ "type": "git", @@ -992,7 +992,7 @@ def test_create_from_object(self, mock_client: Mock, agent_view: MockAgentView) ) assert isinstance(agent, Agent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_client.agents.create.assert_called_once_with( source={ "type": "object", @@ -1017,7 +1017,7 @@ def test_create_from_object_with_agent_setup(self, mock_client: Mock, agent_view ) assert isinstance(agent, Agent) - assert agent.id == "agent_123" + assert agent.id == "agt_123" mock_client.agents.create.assert_called_once_with( source={ "type": "object", diff --git a/tests/sdk/test_scenario.py b/tests/sdk/test_scenario.py index 3504c1714..e3aa5f1c8 100644 --- a/tests/sdk/test_scenario.py +++ b/tests/sdk/test_scenario.py @@ -99,8 +99,8 @@ def test_run_async(self, mock_client: Mock, scenario_run_view: MockScenarioRunVi scenario = Scenario(mock_client, "scn_123") run = scenario.run_async(run_name="test-run") - assert run.id == "run_123" - assert run.devbox_id == "dev_123" + assert run.id == "scr_123" + assert run.devbox_id == "dbx_123" mock_client.scenarios.start_run.assert_called_once_with( scenario_id="scn_123", run_name="test-run", @@ -113,8 +113,8 @@ def test_run(self, mock_client: Mock, scenario_run_view: MockScenarioRunView) -> scenario = Scenario(mock_client, "scn_123") run = scenario.run(run_name="test-run") - assert run.id == "run_123" - assert run.devbox_id == "dev_123" + assert run.id == "scr_123" + assert run.devbox_id == "dbx_123" mock_client.scenarios.start_run_and_await_env_ready.assert_called_once_with( scenario_id="scn_123", run_name="test-run", diff --git a/tests/sdk/test_scenario_run.py b/tests/sdk/test_scenario_run.py index 54ea6e89b..339e365f8 100644 --- a/tests/sdk/test_scenario_run.py +++ b/tests/sdk/test_scenario_run.py @@ -15,31 +15,31 @@ class TestScenarioRun: def test_init(self, mock_client: Mock) -> None: """Test ScenarioRun initialization.""" - run = ScenarioRun(mock_client, "run_123", "dev_123") - assert run.id == "run_123" - assert run.devbox_id == "dev_123" + run = ScenarioRun(mock_client, "scr_123", "dbx_123") + assert run.id == "scr_123" + assert run.devbox_id == "dbx_123" def test_repr(self, mock_client: Mock) -> None: """Test ScenarioRun string representation.""" - run = ScenarioRun(mock_client, "run_123", "dev_123") - assert repr(run) == "" + run = ScenarioRun(mock_client, "scr_123", "dbx_123") + assert repr(run) == "" def test_devbox_property(self, mock_client: Mock) -> None: """Test devbox property returns Devbox wrapper.""" - run = ScenarioRun(mock_client, "run_123", "dev_123") + run = ScenarioRun(mock_client, "scr_123", "dbx_123") devbox = run.devbox - assert devbox.id == "dev_123" + assert devbox.id == "dbx_123" def test_get_info(self, mock_client: Mock, scenario_run_view: MockScenarioRunView) -> None: """Test get_info method.""" mock_client.scenarios.runs.retrieve.return_value = scenario_run_view - run = ScenarioRun(mock_client, "run_123", "dev_123") + run = ScenarioRun(mock_client, "scr_123", "dbx_123") result = run.get_info() assert result == scenario_run_view - mock_client.scenarios.runs.retrieve.assert_called_once_with("run_123") + mock_client.scenarios.runs.retrieve.assert_called_once_with("scr_123") def test_await_env_ready( self, mock_client: Mock, scenario_run_view: MockScenarioRunView, devbox_view: MockDevboxView @@ -48,10 +48,10 @@ def test_await_env_ready( mock_client.devboxes.await_running.return_value = devbox_view mock_client.scenarios.runs.retrieve.return_value = scenario_run_view - run = ScenarioRun(mock_client, "run_123", "dev_123") + run = ScenarioRun(mock_client, "scr_123", "dbx_123") result = run.await_env_ready() - mock_client.devboxes.await_running.assert_called_once_with("dev_123", polling_config=None) + mock_client.devboxes.await_running.assert_called_once_with("dbx_123", polling_config=None) assert result == scenario_run_view def test_score(self, mock_client: Mock, scenario_run_view: MockScenarioRunView) -> None: @@ -59,66 +59,66 @@ def test_score(self, mock_client: Mock, scenario_run_view: MockScenarioRunView) scenario_run_view.state = "scoring" mock_client.scenarios.runs.score.return_value = scenario_run_view - run = ScenarioRun(mock_client, "run_123", "dev_123") + run = ScenarioRun(mock_client, "scr_123", "dbx_123") result = run.score() assert result == scenario_run_view - mock_client.scenarios.runs.score.assert_called_once_with("run_123") + mock_client.scenarios.runs.score.assert_called_once_with("scr_123") def test_await_scored(self, mock_client: Mock, scenario_run_view: MockScenarioRunView) -> None: """Test await_scored method.""" scenario_run_view.state = "scored" mock_client.scenarios.runs.await_scored.return_value = scenario_run_view - run = ScenarioRun(mock_client, "run_123", "dev_123") + run = ScenarioRun(mock_client, "scr_123", "dbx_123") result = run.await_scored() assert result == scenario_run_view - mock_client.scenarios.runs.await_scored.assert_called_once_with("run_123") + mock_client.scenarios.runs.await_scored.assert_called_once_with("scr_123") def test_score_and_await(self, mock_client: Mock, scenario_run_view: MockScenarioRunView) -> None: """Test score_and_await method.""" scenario_run_view.state = "scored" mock_client.scenarios.runs.score_and_await.return_value = scenario_run_view - run = ScenarioRun(mock_client, "run_123", "dev_123") + run = ScenarioRun(mock_client, "scr_123", "dbx_123") result = run.score_and_await() assert result == scenario_run_view - mock_client.scenarios.runs.score_and_await.assert_called_once_with("run_123") + mock_client.scenarios.runs.score_and_await.assert_called_once_with("scr_123") def test_score_and_complete(self, mock_client: Mock, scenario_run_view: MockScenarioRunView) -> None: """Test score_and_complete method.""" scenario_run_view.state = "completed" mock_client.scenarios.runs.score_and_complete.return_value = scenario_run_view - run = ScenarioRun(mock_client, "run_123", "dev_123") + run = ScenarioRun(mock_client, "scr_123", "dbx_123") result = run.score_and_complete() assert result == scenario_run_view - mock_client.scenarios.runs.score_and_complete.assert_called_once_with("run_123") + mock_client.scenarios.runs.score_and_complete.assert_called_once_with("scr_123") def test_complete(self, mock_client: Mock, scenario_run_view: MockScenarioRunView) -> None: """Test complete method.""" scenario_run_view.state = "completed" mock_client.scenarios.runs.complete.return_value = scenario_run_view - run = ScenarioRun(mock_client, "run_123", "dev_123") + run = ScenarioRun(mock_client, "scr_123", "dbx_123") result = run.complete() assert result == scenario_run_view - mock_client.scenarios.runs.complete.assert_called_once_with("run_123") + mock_client.scenarios.runs.complete.assert_called_once_with("scr_123") def test_cancel(self, mock_client: Mock, scenario_run_view: MockScenarioRunView) -> None: """Test cancel method.""" scenario_run_view.state = "canceled" mock_client.scenarios.runs.cancel.return_value = scenario_run_view - run = ScenarioRun(mock_client, "run_123", "dev_123") + run = ScenarioRun(mock_client, "scr_123", "dbx_123") result = run.cancel() assert result == scenario_run_view - mock_client.scenarios.runs.cancel.assert_called_once_with("run_123") + mock_client.scenarios.runs.cancel.assert_called_once_with("scr_123") def test_download_logs(self, mock_client: Mock, tmp_path: Path) -> None: """Test download_logs method writes to file.""" @@ -126,11 +126,11 @@ def test_download_logs(self, mock_client: Mock, tmp_path: Path) -> None: mock_response.write_to_file = Mock() mock_client.scenarios.runs.download_logs.return_value = mock_response - run = ScenarioRun(mock_client, "run_123", "dev_123") + run = ScenarioRun(mock_client, "scr_123", "dbx_123") output_path = tmp_path / "logs.zip" run.download_logs(output_path) - mock_client.scenarios.runs.download_logs.assert_called_once_with("run_123") + mock_client.scenarios.runs.download_logs.assert_called_once_with("scr_123") mock_response.write_to_file.assert_called_once_with(output_path) def test_get_score_when_scored(self, mock_client: Mock) -> None: @@ -139,19 +139,19 @@ def test_get_score_when_scored(self, mock_client: Mock) -> None: run_view = MockScenarioRunView(state="scored", scoring_contract_result=scoring_result) mock_client.scenarios.runs.retrieve.return_value = run_view - run = ScenarioRun(mock_client, "run_123", "dev_123") + run = ScenarioRun(mock_client, "scr_123", "dbx_123") result = run.get_score() assert result == scoring_result - mock_client.scenarios.runs.retrieve.assert_called_once_with("run_123") + mock_client.scenarios.runs.retrieve.assert_called_once_with("scr_123") def test_get_score_when_not_scored(self, mock_client: Mock) -> None: """Test get_score returns None when not scored.""" run_view = MockScenarioRunView(state="running", scoring_contract_result=None) mock_client.scenarios.runs.retrieve.return_value = run_view - run = ScenarioRun(mock_client, "run_123", "dev_123") + run = ScenarioRun(mock_client, "scr_123", "dbx_123") result = run.get_score() assert result is None - mock_client.scenarios.runs.retrieve.assert_called_once_with("run_123") + mock_client.scenarios.runs.retrieve.assert_called_once_with("scr_123") diff --git a/tests/sdk/test_scorer.py b/tests/sdk/test_scorer.py index 761a487cb..91b430db0 100644 --- a/tests/sdk/test_scorer.py +++ b/tests/sdk/test_scorer.py @@ -14,30 +14,30 @@ class TestScorer: def test_init(self, mock_client: Mock) -> None: """Test Scorer initialization.""" - scorer = Scorer(mock_client, "scorer_123") - assert scorer.id == "scorer_123" + scorer = Scorer(mock_client, "sco_123") + assert scorer.id == "sco_123" def test_repr(self, mock_client: Mock) -> None: """Test Scorer string representation.""" - scorer = Scorer(mock_client, "scorer_123") - assert repr(scorer) == "" + scorer = Scorer(mock_client, "sco_123") + assert repr(scorer) == "" def test_get_info(self, mock_client: Mock, scorer_view: MockScorerView) -> None: """Test get_info method.""" mock_client.scenarios.scorers.retrieve.return_value = scorer_view - scorer = Scorer(mock_client, "scorer_123") + scorer = Scorer(mock_client, "sco_123") result = scorer.get_info() assert result == scorer_view - mock_client.scenarios.scorers.retrieve.assert_called_once_with("scorer_123") + mock_client.scenarios.scorers.retrieve.assert_called_once_with("sco_123") def test_update(self, mock_client: Mock) -> None: """Test update method.""" - update_response = SimpleNamespace(id="scorer_123", type="updated_scorer", bash_script="echo 'score=1.0'") + update_response = SimpleNamespace(id="sco_123", type="updated_scorer", bash_script="echo 'score=1.0'") mock_client.scenarios.scorers.update.return_value = update_response - scorer = Scorer(mock_client, "scorer_123") + scorer = Scorer(mock_client, "sco_123") result = scorer.update( type="updated_scorer", bash_script="echo 'score=1.0'", @@ -45,7 +45,7 @@ def test_update(self, mock_client: Mock) -> None: assert result == update_response mock_client.scenarios.scorers.update.assert_called_once_with( - "scorer_123", + "sco_123", type="updated_scorer", bash_script="echo 'score=1.0'", ) @@ -59,13 +59,13 @@ def test_validate(self, mock_client: Mock) -> None: ) mock_client.scenarios.scorers.validate.return_value = validate_response - scorer = Scorer(mock_client, "scorer_123") + scorer = Scorer(mock_client, "sco_123") result = scorer.validate( scoring_context={"test": "context"}, ) assert result == validate_response mock_client.scenarios.scorers.validate.assert_called_once_with( - "scorer_123", + "sco_123", scoring_context={"test": "context"}, ) diff --git a/tests/sdk/test_snapshot.py b/tests/sdk/test_snapshot.py index 383e812cc..4b066e29a 100644 --- a/tests/sdk/test_snapshot.py +++ b/tests/sdk/test_snapshot.py @@ -15,19 +15,19 @@ class TestSnapshot: def test_init(self, mock_client: Mock) -> None: """Test Snapshot initialization.""" - snapshot = Snapshot(mock_client, "snap_123") - assert snapshot.id == "snap_123" + snapshot = Snapshot(mock_client, "snp_123") + assert snapshot.id == "snp_123" def test_repr(self, mock_client: Mock) -> None: """Test Snapshot string representation.""" - snapshot = Snapshot(mock_client, "snap_123") - assert repr(snapshot) == "" + snapshot = Snapshot(mock_client, "snp_123") + assert repr(snapshot) == "" def test_get_info(self, mock_client: Mock, snapshot_view: MockSnapshotView) -> None: """Test get_info method.""" mock_client.devboxes.disk_snapshots.query_status.return_value = snapshot_view - snapshot = Snapshot(mock_client, "snap_123") + snapshot = Snapshot(mock_client, "snp_123") result = snapshot.get_info( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -37,7 +37,7 @@ def test_get_info(self, mock_client: Mock, snapshot_view: MockSnapshotView) -> N assert result == snapshot_view mock_client.devboxes.disk_snapshots.query_status.assert_called_once_with( - "snap_123", + "snp_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, @@ -46,10 +46,10 @@ def test_get_info(self, mock_client: Mock, snapshot_view: MockSnapshotView) -> N def test_update(self, mock_client: Mock) -> None: """Test update method.""" - updated_snapshot = SimpleNamespace(id="snap_123", name="updated-name") + updated_snapshot = SimpleNamespace(id="snp_123", name="updated-name") mock_client.devboxes.disk_snapshots.update.return_value = updated_snapshot - snapshot = Snapshot(mock_client, "snap_123") + snapshot = Snapshot(mock_client, "snp_123") result = snapshot.update( commit_message="Update message", metadata={"key": "value"}, @@ -63,7 +63,7 @@ def test_update(self, mock_client: Mock) -> None: assert result == updated_snapshot mock_client.devboxes.disk_snapshots.update.assert_called_once_with( - "snap_123", + "snp_123", commit_message="Update message", metadata={"key": "value"}, name="updated-name", @@ -78,7 +78,7 @@ def test_delete(self, mock_client: Mock) -> None: """Test delete method.""" mock_client.devboxes.disk_snapshots.delete.return_value = object() - snapshot = Snapshot(mock_client, "snap_123") + snapshot = Snapshot(mock_client, "snp_123") result = snapshot.delete( extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -89,7 +89,7 @@ def test_delete(self, mock_client: Mock) -> None: assert result is not None # Verify return value is propagated mock_client.devboxes.disk_snapshots.delete.assert_called_once_with( - "snap_123", + "snp_123", extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, extra_body={"key": "value"}, @@ -102,7 +102,7 @@ def test_await_completed(self, mock_client: Mock, snapshot_view: MockSnapshotVie mock_client.devboxes.disk_snapshots.await_completed.return_value = snapshot_view polling_config = PollingConfig(timeout_seconds=60.0) - snapshot = Snapshot(mock_client, "snap_123") + snapshot = Snapshot(mock_client, "snp_123") result = snapshot.await_completed( polling_config=polling_config, extra_headers={"X-Custom": "value"}, @@ -113,7 +113,7 @@ def test_await_completed(self, mock_client: Mock, snapshot_view: MockSnapshotVie assert result == snapshot_view mock_client.devboxes.disk_snapshots.await_completed.assert_called_once_with( - "snap_123", + "snp_123", polling_config=polling_config, extra_headers={"X-Custom": "value"}, extra_query={"param": "value"}, @@ -125,7 +125,7 @@ def test_create_devbox(self, mock_client: Mock, devbox_view: MockDevboxView) -> """Test create_devbox method.""" mock_client.devboxes.create_and_await_running.return_value = devbox_view - snapshot = Snapshot(mock_client, "snap_123") + snapshot = Snapshot(mock_client, "snp_123") devbox = snapshot.create_devbox( name="test-devbox", metadata={"key": "value"}, @@ -133,9 +133,9 @@ def test_create_devbox(self, mock_client: Mock, devbox_view: MockDevboxView) -> extra_headers={"X-Custom": "value"}, ) - assert devbox.id == "dev_123" + assert devbox.id == "dbx_123" mock_client.devboxes.create_and_await_running.assert_called_once() call_kwargs = mock_client.devboxes.create_and_await_running.call_args[1] - assert call_kwargs["snapshot_id"] == "snap_123" + assert call_kwargs["snapshot_id"] == "snp_123" assert call_kwargs["name"] == "test-devbox" assert call_kwargs["metadata"] == {"key": "value"} diff --git a/tests/smoketests/sdk/test_async_benchmark.py b/tests/smoketests/sdk/test_async_benchmark.py new file mode 100644 index 000000000..640d874f4 --- /dev/null +++ b/tests/smoketests/sdk/test_async_benchmark.py @@ -0,0 +1,197 @@ +"""Asynchronous SDK smoke tests for AsyncBenchmark operations. + +These tests validate the AsyncBenchmark class against the real API. +We create a dedicated smoketest benchmark and scenarios with consistent names +so that resources are reused across test runs (since there's no delete endpoint). +""" + +from __future__ import annotations + +from typing import List, Tuple + +import pytest + +from runloop_api_client import AsyncRunloopSDK +from runloop_api_client.sdk import AsyncScenario, AsyncBenchmark, AsyncScenarioRun, AsyncBenchmarkRun + +pytestmark = [pytest.mark.smoketest] + +TWO_MINUTE_TIMEOUT = 120 + +# Consistent names for smoketest resources +SMOKETEST_BENCHMARK_NAME = "sdk-smoketest-benchmark" +SMOKETEST_SCENARIO_1_NAME = "sdk-smoketest-scenario-1" +SMOKETEST_SCENARIO_2_NAME = "sdk-smoketest-scenario-2" + + +async def get_or_create_scenario( + async_sdk_client: AsyncRunloopSDK, + name: str, + problem_statement: str, +) -> AsyncScenario: + """Get an existing scenario by name or create a new one.""" + # Check if scenario already exists + scenarios = await async_sdk_client.scenario.list(name=name, limit=1) + for scenario in scenarios: + # Return the first matching scenario + return scenario + + # Create a new scenario using the SDK builder + return await ( + async_sdk_client.scenario.builder(name) + .with_problem_statement(problem_statement) + .add_shell_command_scorer("pass-scorer", command="exit 0") + .push() + ) + + +async def get_or_create_benchmark( + async_sdk_client: AsyncRunloopSDK, + name: str, + scenario_ids: List[str], +) -> AsyncBenchmark: + """Get an existing benchmark by name or create a new one.""" + # Check if benchmark already exists + benchmarks_page = await async_sdk_client.api.benchmarks.list(name=name, limit=1) + for benchmark in benchmarks_page.benchmarks: + # Return the first matching benchmark + return AsyncBenchmark(async_sdk_client.api, benchmark.id) + + # Create a new benchmark + return AsyncBenchmark( + async_sdk_client.api, + ( + await async_sdk_client.api.benchmarks.create( + name=name, + scenario_ids=scenario_ids, + description="Smoketest benchmark for SDK testing", + ) + ).id, + ) + + +@pytest.fixture(scope="module") +async def smoketest_benchmark( + async_sdk_client: AsyncRunloopSDK, +) -> Tuple[AsyncBenchmark, List[str]]: + """Create or retrieve the smoketest benchmark and scenario IDs.""" + # Create or get scenarios + scenario_1 = await get_or_create_scenario( + async_sdk_client, + SMOKETEST_SCENARIO_1_NAME, + "Smoketest scenario 1 - basic validation", + ) + scenario_2 = await get_or_create_scenario( + async_sdk_client, + SMOKETEST_SCENARIO_2_NAME, + "Smoketest scenario 2 - basic validation", + ) + + scenario_ids = [scenario_1.id, scenario_2.id] + + # Create or get benchmark + benchmark = await get_or_create_benchmark( + async_sdk_client, + SMOKETEST_BENCHMARK_NAME, + scenario_ids, + ) + + return benchmark, scenario_ids + + +class TestAsyncBenchmarkRun: + """Test AsyncBenchmark run operations.""" + + @pytest.mark.timeout(TWO_MINUTE_TIMEOUT) + async def test_benchmark_run_and_cancel( + self, + async_sdk_client: AsyncRunloopSDK, + smoketest_benchmark: Tuple[AsyncBenchmark, List[str]], + ) -> None: + """Test starting and canceling a benchmark run. + + This test: + 1. Uses the smoketest benchmark fixture + 2. Starts a new benchmark run via the AsyncBenchmark class + 3. Validates the run object + 4. Cancels the run + """ + benchmark, scenario_ids = smoketest_benchmark + + # Start a run + run = await benchmark.start_run(run_name="sdk-smoketest-async-benchmark-run") + scenario_runs: List[AsyncScenarioRun] = [] + + try: + assert isinstance(run, AsyncBenchmarkRun) + assert run.id is not None + assert run.benchmark_id == benchmark.id + + # Get run info + info = await run.get_info() + assert info.id == run.id + assert info.state == "running" + + # Run the scenarios + for scenario_id in scenario_ids: + scenario = async_sdk_client.scenario.from_id(scenario_id) + scenario_runs.append( + await scenario.run_async( + benchmark_run_id=run.id, run_name="sdk-smoketest-async-benchmark-run-scenario" + ) + ) + + benchmark_scenario_runs = await run.list_scenario_runs() + assert isinstance(benchmark_scenario_runs, list) + assert len(benchmark_scenario_runs) == len(scenario_runs) + for scenario_run in benchmark_scenario_runs: + assert isinstance(scenario_run, AsyncScenarioRun) + assert any( + scenario_run.id == scenario_run.id and scenario_run.devbox_id == scenario_run.devbox_id + for scenario_run in scenario_runs + ) + + # Cancel the scenario run + for scenario_run in scenario_runs: + scenario_result = await scenario_run.cancel() + assert scenario_result.state in ["canceled", "completed"] + + # Cancel the benchmark run + result = await run.cancel() + assert result.state in ["canceled", "completed"] + + except Exception: + # Ensure cleanup on any error + for scenario_run in scenario_runs: + await scenario_run.cancel() + await run.cancel() + raise + + +class TestAsyncBenchmarkListRuns: + """Test AsyncBenchmark list_runs operations.""" + + @pytest.mark.timeout(TWO_MINUTE_TIMEOUT) + async def test_list_runs( + self, + smoketest_benchmark: Tuple[AsyncBenchmark, List[str]], + ) -> None: + """Test listing benchmark runs. + + This test: + 1. Uses the smoketest benchmark fixture + 2. Lists its runs + 3. Validates returned objects are AsyncBenchmarkRun instances + """ + benchmark, _ = smoketest_benchmark + + runs = await benchmark.list_runs() + assert isinstance(runs, list) + if not runs: + pytest.skip("No runs available to test") + + # Verify returned items are AsyncBenchmarkRun objects + for run in runs: + assert isinstance(run, AsyncBenchmarkRun) + assert run.id is not None + assert run.benchmark_id == benchmark.id diff --git a/tests/smoketests/sdk/test_async_benchmark_run.py b/tests/smoketests/sdk/test_async_benchmark_run.py deleted file mode 100644 index 3eab471b5..000000000 --- a/tests/smoketests/sdk/test_async_benchmark_run.py +++ /dev/null @@ -1,145 +0,0 @@ -"""Asynchronous SDK smoke tests for AsyncBenchmarkRun operations. - -These tests validate the AsyncBenchmarkRun class against the real API. -Until AsyncBenchmarkOps is available (PR3), we use the raw async API client -to find or create benchmark runs for testing. -""" - -from __future__ import annotations - -import pytest - -from runloop_api_client.sdk import AsyncRunloopSDK -from runloop_api_client.sdk.async_scenario_run import AsyncScenarioRun -from runloop_api_client.sdk.async_benchmark_run import AsyncBenchmarkRun - -pytestmark = [pytest.mark.smoketest] - -TWO_MINUTE_TIMEOUT = 120 - - -class TestAsyncBenchmarkRunRetrieval: - """Test AsyncBenchmarkRun retrieval operations.""" - - @pytest.mark.timeout(TWO_MINUTE_TIMEOUT) - async def test_benchmark_run_from_existing(self, async_sdk_client: AsyncRunloopSDK) -> None: - """Test creating AsyncBenchmarkRun from existing benchmark run. - - This test: - 1. Lists benchmark runs via raw async API - 2. Creates an AsyncBenchmarkRun wrapper - 3. Validates get_info returns correct data - """ - # List existing benchmark runs via raw API - runs_page = await async_sdk_client.api.benchmarks.runs.list(limit=1) - runs = runs_page.runs - - if not runs: - pytest.skip("No benchmark runs available to test") - - run_data = runs[0] - - # Create AsyncBenchmarkRun wrapper - benchmark_run = AsyncBenchmarkRun( - client=async_sdk_client.api, - run_id=run_data.id, - benchmark_id=run_data.benchmark_id, - ) - - assert benchmark_run.id == run_data.id - assert benchmark_run.benchmark_id == run_data.benchmark_id - - # Test get_info - info = await benchmark_run.get_info() - assert info.id == run_data.id - assert info.benchmark_id == run_data.benchmark_id - - @pytest.mark.timeout(TWO_MINUTE_TIMEOUT) - async def test_benchmark_run_list_scenario_runs(self, async_sdk_client: AsyncRunloopSDK) -> None: - """Test AsyncBenchmarkRun.list_scenario_runs method. - - This test: - 1. Finds an existing benchmark run - 2. Lists its scenario runs - """ - # List existing benchmark runs via raw API - runs_page = await async_sdk_client.api.benchmarks.runs.list(limit=1) - runs = runs_page.runs - - if not runs: - pytest.skip("No benchmark runs available to test") - - run_data = runs[0] - - # Create AsyncBenchmarkRun wrapper - benchmark_run = AsyncBenchmarkRun( - client=async_sdk_client.api, - run_id=run_data.id, - benchmark_id=run_data.benchmark_id, - ) - - # List scenario runs (might be empty, that's okay) - scenario_runs = await benchmark_run.list_scenario_runs() - assert isinstance(scenario_runs, list) - - # Verify returned items are AsyncScenarioRun objects - for scenario_run in scenario_runs: - assert isinstance(scenario_run, AsyncScenarioRun) - assert scenario_run.id is not None - assert scenario_run.devbox_id is not None - - -class TestAsyncBenchmarkRunLifecycle: - """Test AsyncBenchmarkRun lifecycle operations.""" - - @pytest.mark.timeout(TWO_MINUTE_TIMEOUT) - async def test_benchmark_run_create_and_cancel(self, async_sdk_client: AsyncRunloopSDK) -> None: - """Test creating a benchmark run and canceling it. - - This test: - 1. Finds an existing benchmark - 2. Starts a new benchmark run - 3. Creates an AsyncBenchmarkRun wrapper - 4. Cancels the run - """ - # Find an existing benchmark via raw API - benchmarks_page = await async_sdk_client.api.benchmarks.list(limit=1) - benchmarks = benchmarks_page.benchmarks - - if not benchmarks: - pytest.skip("No benchmarks available to test") - - benchmark = benchmarks[0] - - # Start a new benchmark run - run_data = await async_sdk_client.api.benchmarks.start_run( - benchmark_id=benchmark.id, - run_name="sdk-smoketest-async-benchmark-run", - ) - - try: - # Create AsyncBenchmarkRun wrapper - benchmark_run = AsyncBenchmarkRun( - client=async_sdk_client.api, - run_id=run_data.id, - benchmark_id=run_data.benchmark_id, - ) - - assert benchmark_run.id == run_data.id - - # Get info - info = await benchmark_run.get_info() - assert info.id == run_data.id - assert info.state in ["running", "completed", "canceled"] - - # Cancel the run - result = await benchmark_run.cancel() - assert result.state in ["canceled", "completed"] # May already be completed - - except Exception: - # Ensure cleanup on any error - try: - await async_sdk_client.api.benchmarks.runs.cancel(run_data.id) - except Exception: - pass - raise diff --git a/tests/smoketests/sdk/test_benchmark.py b/tests/smoketests/sdk/test_benchmark.py new file mode 100644 index 000000000..70658fb9d --- /dev/null +++ b/tests/smoketests/sdk/test_benchmark.py @@ -0,0 +1,193 @@ +"""Synchronous SDK smoke tests for Benchmark operations. + +These tests validate the Benchmark class against the real API. +We create a dedicated smoketest benchmark and scenarios with consistent names +so that resources are reused across test runs (since there's no delete endpoint). +""" + +from __future__ import annotations + +from typing import List, Tuple + +import pytest + +from runloop_api_client import RunloopSDK +from runloop_api_client.sdk import Scenario, Benchmark, ScenarioRun, BenchmarkRun + +pytestmark = [pytest.mark.smoketest] + +TWO_MINUTE_TIMEOUT = 120 + +# Consistent names for smoketest resources +SMOKETEST_BENCHMARK_NAME = "sdk-smoketest-benchmark" +SMOKETEST_SCENARIO_1_NAME = "sdk-smoketest-scenario-1" +SMOKETEST_SCENARIO_2_NAME = "sdk-smoketest-scenario-2" + + +def get_or_create_scenario( + sdk_client: RunloopSDK, + name: str, + problem_statement: str, +) -> Scenario: + """Get an existing scenario by name or create a new one.""" + # Check if scenario already exists + scenarios = sdk_client.scenario.list(name=name, limit=1) + for scenario in scenarios: + # Return the first matching scenario + return scenario + + # Create a new scenario using the SDK builder + return ( + sdk_client.scenario.builder(name) + .with_problem_statement(problem_statement) + .add_shell_command_scorer("pass-scorer", command="exit 0") + .push() + ) + + +def get_or_create_benchmark( + sdk_client: RunloopSDK, + name: str, + scenario_ids: List[str], +) -> Benchmark: + """Get an existing benchmark by name or create a new one.""" + # Check if benchmark already exists + benchmarks_page = sdk_client.api.benchmarks.list(name=name, limit=1) + for benchmark in benchmarks_page.benchmarks: + # Return the first matching benchmark + return Benchmark(sdk_client.api, benchmark.id) + + # Create a new benchmark + return Benchmark( + sdk_client.api, + sdk_client.api.benchmarks.create( + name=name, + scenario_ids=scenario_ids, + description="Smoketest benchmark for SDK testing", + ).id, + ) + + +@pytest.fixture(scope="module") +def smoketest_benchmark( + sdk_client: RunloopSDK, +) -> Tuple[Benchmark, List[str]]: + """Create or retrieve the smoketest benchmark and scenarios.""" + # Create or get scenarios + scenario_1 = get_or_create_scenario( + sdk_client, + SMOKETEST_SCENARIO_1_NAME, + "Smoketest scenario 1 - basic validation", + ) + scenario_2 = get_or_create_scenario( + sdk_client, + SMOKETEST_SCENARIO_2_NAME, + "Smoketest scenario 2 - basic validation", + ) + + scenario_ids = [scenario_1.id, scenario_2.id] + + # Create or get benchmark + benchmark = get_or_create_benchmark( + sdk_client, + SMOKETEST_BENCHMARK_NAME, + scenario_ids, + ) + + return benchmark, scenario_ids + + +class TestBenchmarkRun: + """Test Benchmark run operations.""" + + @pytest.mark.timeout(TWO_MINUTE_TIMEOUT) + def test_benchmark_run_lifecycle( + self, + sdk_client: RunloopSDK, + smoketest_benchmark: Tuple[Benchmark, List[str]], + ) -> None: + """Test starting and canceling a benchmark run. + + This test: + 1. Uses the smoketest benchmark fixture + 2. Starts a new benchmark run via the Benchmark class + 3. Validates the run object + 4. Cancels the run + """ + benchmark, scenario_ids = smoketest_benchmark + + # Start a run + run = benchmark.start_run(run_name="sdk-smoketest-benchmark-run") + scenario_runs: List[ScenarioRun] = [] + + try: + assert isinstance(run, BenchmarkRun) + assert run.id is not None + assert run.benchmark_id == benchmark.id + + # Get run info + info = run.get_info() + assert info.id == run.id + assert info.state == "running" + + # Start a scenario run + for scenario_id in scenario_ids: + scenario = sdk_client.scenario.from_id(scenario_id) + scenario_runs.append( + scenario.run(benchmark_run_id=run.id, run_name="sdk-smoketest-benchmark-run-scenario") + ) + + benchmark_scenario_runs = run.list_scenario_runs() + assert isinstance(benchmark_scenario_runs, list) + assert len(benchmark_scenario_runs) == len(scenario_runs) + for scenario_run in benchmark_scenario_runs: + assert isinstance(scenario_run, ScenarioRun) + assert any( + scenario_run.id == scenario_run.id and scenario_run.devbox_id == scenario_run.devbox_id + for scenario_run in scenario_runs + ) + + # Cancel the scenario runs + for scenario_run in scenario_runs: + scenario_result = scenario_run.cancel() + assert scenario_result.state in ["canceled", "completed"] + + # Cancel the benchmark run + result = run.cancel() + assert result.state in ["canceled", "completed"] + + except Exception: + # Ensure cleanup on any error + for scenario_run in scenario_runs: + scenario_run.cancel() + run.cancel() + raise + + +class TestBenchmarkListRuns: + """Test Benchmark list_runs operations.""" + + @pytest.mark.timeout(TWO_MINUTE_TIMEOUT) + def test_list_runs( + self, + smoketest_benchmark: Tuple[Benchmark, List[str]], + ) -> None: + """Test listing benchmark runs. + + This test: + 1. Uses the smoketest benchmark fixture + 2. Lists its runs + 3. Validates returned objects are BenchmarkRun instances + """ + benchmark, _ = smoketest_benchmark + + runs = benchmark.list_runs() + assert isinstance(runs, list) + if not runs: + pytest.skip("No runs available to test") + + # Verify returned items are BenchmarkRun objects + for run in runs: + assert isinstance(run, BenchmarkRun) + assert run.id is not None + assert run.benchmark_id == benchmark.id diff --git a/tests/smoketests/sdk/test_benchmark_run.py b/tests/smoketests/sdk/test_benchmark_run.py deleted file mode 100644 index f21e9e87e..000000000 --- a/tests/smoketests/sdk/test_benchmark_run.py +++ /dev/null @@ -1,142 +0,0 @@ -"""Synchronous SDK smoke tests for BenchmarkRun operations. - -These tests validate the BenchmarkRun class against the real API. -Until BenchmarkOps is available (PR3), we use the raw API client to -find or create benchmark runs for testing. -""" - -from __future__ import annotations - -import pytest - -from runloop_api_client.sdk import RunloopSDK -from runloop_api_client.sdk.scenario_run import ScenarioRun -from runloop_api_client.sdk.benchmark_run import BenchmarkRun - -pytestmark = [pytest.mark.smoketest] - -TWO_MINUTE_TIMEOUT = 120 - - -class TestBenchmarkRunRetrieval: - """Test BenchmarkRun retrieval operations.""" - - @pytest.mark.timeout(TWO_MINUTE_TIMEOUT) - def test_benchmark_run_from_existing(self, sdk_client: RunloopSDK) -> None: - """Test creating BenchmarkRun from existing benchmark run. - - This test: - 1. Lists benchmark runs via raw API - 2. Creates a BenchmarkRun wrapper - 3. Validates get_info returns correct data - """ - # List existing benchmark runs via raw API - runs = sdk_client.api.benchmarks.runs.list(limit=1).runs - - if not runs: - pytest.skip("No benchmark runs available to test") - - run_data = runs[0] - - # Create BenchmarkRun wrapper - benchmark_run = BenchmarkRun( - client=sdk_client.api, - run_id=run_data.id, - benchmark_id=run_data.benchmark_id, - ) - - assert benchmark_run.id == run_data.id - assert benchmark_run.benchmark_id == run_data.benchmark_id - - # Test get_info - info = benchmark_run.get_info() - assert info.id == run_data.id - assert info.benchmark_id == run_data.benchmark_id - - @pytest.mark.timeout(TWO_MINUTE_TIMEOUT) - def test_benchmark_run_list_scenario_runs(self, sdk_client: RunloopSDK) -> None: - """Test BenchmarkRun.list_scenario_runs method. - - This test: - 1. Finds an existing benchmark run - 2. Lists its scenario runs - """ - # List existing benchmark runs via raw API - runs = sdk_client.api.benchmarks.runs.list(limit=1).runs - - if not runs: - pytest.skip("No benchmark runs available to test") - - run_data = runs[0] - - # Create BenchmarkRun wrapper - benchmark_run = BenchmarkRun( - client=sdk_client.api, - run_id=run_data.id, - benchmark_id=run_data.benchmark_id, - ) - - # List scenario runs (might be empty, that's okay) - scenario_runs = benchmark_run.list_scenario_runs() - assert isinstance(scenario_runs, list) - - # Verify returned items are ScenarioRun objects - for scenario_run in scenario_runs: - assert isinstance(scenario_run, ScenarioRun) - assert scenario_run.id is not None - assert scenario_run.devbox_id is not None - - -class TestBenchmarkRunLifecycle: - """Test BenchmarkRun lifecycle operations.""" - - @pytest.mark.timeout(TWO_MINUTE_TIMEOUT) - def test_benchmark_run_create_and_cancel(self, sdk_client: RunloopSDK) -> None: - """Test creating a benchmark run and canceling it. - - This test: - 1. Finds an existing benchmark - 2. Starts a new benchmark run - 3. Creates a BenchmarkRun wrapper - 4. Cancels the run - """ - # Find an existing benchmark via raw API - benchmarks = sdk_client.api.benchmarks.list(limit=1).benchmarks - - if not benchmarks: - pytest.skip("No benchmarks available to test") - - benchmark = benchmarks[0] - - # Start a new benchmark run - run_data = sdk_client.api.benchmarks.start_run( - benchmark_id=benchmark.id, - run_name="sdk-smoketest-benchmark-run", - ) - - try: - # Create BenchmarkRun wrapper - benchmark_run = BenchmarkRun( - client=sdk_client.api, - run_id=run_data.id, - benchmark_id=run_data.benchmark_id, - ) - - assert benchmark_run.id == run_data.id - - # Get info - info = benchmark_run.get_info() - assert info.id == run_data.id - assert info.state in ["running", "completed", "canceled"] - - # Cancel the run - result = benchmark_run.cancel() - assert result.state in ["canceled", "completed"] # May already be completed - - except Exception: - # Ensure cleanup on any error - try: - sdk_client.api.benchmarks.runs.cancel(run_data.id) - except Exception: - pass - raise