From 2e0fd2f46286580a27076a7e56391f87bfe3d595 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 13 Nov 2026 21:15:29 +0000 Subject: [PATCH 1/5] test(js-sdk): enforce retainOutput type assertions with vitest typecheck Co-Authored-By: mish@e2b.dev --- .../tests/sandbox/commands/connect.test.ts | 3 +- .../sandbox/commands/retainOutput.test-d.ts | 41 +++++++++++++++++++ .../js-sdk/tests/sandbox/commands/run.test.ts | 39 +----------------- packages/js-sdk/tsconfig.typecheck.json | 7 ++++ packages/js-sdk/vitest.config.mts | 12 ++++++ 5 files changed, 63 insertions(+), 39 deletions(-) create mode 100644 packages/js-sdk/tests/sandbox/commands/retainOutput.test-d.ts create mode 100644 packages/js-sdk/tsconfig.typecheck.json diff --git a/packages/js-sdk/tests/sandbox/commands/connect.test.ts b/packages/js-sdk/tests/sandbox/commands/connect.test.ts index e19696619a..80c4904d60 100644 --- a/packages/js-sdk/tests/sandbox/commands/connect.test.ts +++ b/packages/js-sdk/tests/sandbox/commands/connect.test.ts @@ -1,4 +1,4 @@ -import { assert, expect, expectTypeOf } from 'vitest' +import { assert, expect } from 'vitest' import { sandboxTest } from '../../setup.js' sandboxTest('connect to process', async ({ sandbox }) => { @@ -30,7 +30,6 @@ sandboxTest('connect without retaining output', async ({ sandbox }) => { }, }) - expectTypeOf(handle.stdout).toEqualTypeOf() const result = await handle.wait() assert.isUndefined(result.stdout) diff --git a/packages/js-sdk/tests/sandbox/commands/retainOutput.test-d.ts b/packages/js-sdk/tests/sandbox/commands/retainOutput.test-d.ts new file mode 100644 index 0000000000..84066e3182 --- /dev/null +++ b/packages/js-sdk/tests/sandbox/commands/retainOutput.test-d.ts @@ -0,0 +1,41 @@ +import { expectTypeOf, test } from 'vitest' + +import type { CommandStartOpts, Sandbox } from '../../../src/index.js' + +declare const sandbox: Sandbox +declare const opts: CommandStartOpts + +test('retained output types stdout as a string', async () => { + expectTypeOf( + (await sandbox.commands.run('echo')).stdout + ).toEqualTypeOf() + expectTypeOf( + (await sandbox.commands.run('echo', {})).stdout + ).toEqualTypeOf() + expectTypeOf( + (await sandbox.commands.run('echo', { retainOutput: true })).stdout + ).toEqualTypeOf() +}) + +test('retainOutput: false types stdout as undefined', async () => { + expectTypeOf( + (await sandbox.commands.run('echo', { retainOutput: false })).stdout + ).toEqualTypeOf() + expectTypeOf( + ( + await sandbox.commands.run('echo', { + background: true, + retainOutput: false, + }) + ).stdout + ).toEqualTypeOf() + expectTypeOf( + (await sandbox.commands.connect(1, { retainOutput: false })).stdout + ).toEqualTypeOf() +}) + +test('non-literal retainOutput types stdout as possibly undefined', async () => { + expectTypeOf((await sandbox.commands.run('echo', opts)).stdout).toEqualTypeOf< + string | undefined + >() +}) diff --git a/packages/js-sdk/tests/sandbox/commands/run.test.ts b/packages/js-sdk/tests/sandbox/commands/run.test.ts index a236a3e8ec..4b4454c229 100644 --- a/packages/js-sdk/tests/sandbox/commands/run.test.ts +++ b/packages/js-sdk/tests/sandbox/commands/run.test.ts @@ -1,11 +1,7 @@ -import { expect, assert, expectTypeOf } from 'vitest' +import { expect, assert } from 'vitest' import { sandboxTest } from '../../setup.js' -import { - CommandStartOpts, - InvalidArgumentError, - TimeoutError, -} from '../../../src/index.js' +import { InvalidArgumentError, TimeoutError } from '../../../src/index.js' sandboxTest('run', async ({ sandbox }) => { const text = 'Hello, World!' @@ -71,7 +67,6 @@ sandboxTest('run without retaining output', async ({ sandbox }) => { }, }) - expectTypeOf(cmd.stdout).toEqualTypeOf() assert.equal(cmd.exitCode, 0) assert.isUndefined(cmd.stdout) assert.isUndefined(cmd.stderr) @@ -87,7 +82,6 @@ sandboxTest( retainOutput: false, }) - expectTypeOf(handle.stdout).toEqualTypeOf() const result = await handle.wait() assert.equal(result.exitCode, 0) @@ -97,27 +91,6 @@ sandboxTest( } ) -sandboxTest('run retains output by default', async ({ sandbox }) => { - const cmd = await sandbox.commands.run('echo out', { retainOutput: true }) - - expectTypeOf(cmd.stdout).toEqualTypeOf() - assert.equal(cmd.stdout, 'out\n') -}) - -sandboxTest( - 'run types non-literal retainOutput as possibly undefined', - async ({ sandbox }) => { - const opts: CommandStartOpts = { retainOutput: false } - const cmd = await sandbox.commands.run('echo out', opts) - - expectTypeOf(cmd.stdout).toEqualTypeOf() - assert.isUndefined(cmd.stdout) - - const defaults = await sandbox.commands.run('echo out', {}) - expectTypeOf(defaults.stdout).toEqualTypeOf() - } -) - sandboxTest('run with custom shell', async ({ sandbox }) => { const cmd = await sandbox.commands.run('print(6 * 7)', { shell: ['python3', '-c'], @@ -147,11 +120,3 @@ sandboxTest('run with string shell', async ({ sandbox }) => { }) ).rejects.toThrowError(InvalidArgumentError) }) - -sandboxTest('run with non-array shell', async ({ sandbox }) => { - await expect( - sandbox.commands.run('echo hello', { - shell: new Set(['/bin/sh', '-c']) as unknown as string[], - }) - ).rejects.toThrowError(InvalidArgumentError) -}) diff --git a/packages/js-sdk/tsconfig.typecheck.json b/packages/js-sdk/tsconfig.typecheck.json new file mode 100644 index 0000000000..743fc3b792 --- /dev/null +++ b/packages/js-sdk/tsconfig.typecheck.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true + }, + "include": ["src", "tests/**/*.test-d.ts"] +} diff --git a/packages/js-sdk/vitest.config.mts b/packages/js-sdk/vitest.config.mts index a45cd7e179..8ee220e869 100644 --- a/packages/js-sdk/vitest.config.mts +++ b/packages/js-sdk/vitest.config.mts @@ -51,6 +51,18 @@ export default defineConfig({ setupFiles: ['tests/globalFetchFallback.setup.ts'], }, }, + { + test: { + name: 'types', + include: [], + typecheck: { + enabled: true, + only: true, + include: ['tests/**/*.test-d.ts'], + tsconfig: './tsconfig.typecheck.json', + }, + }, + }, { test: { name: 'connectionConfig', From 1ee3da1024706297ca6e004a6abfebf7aa536554 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 13 Nov 2026 21:15:29 +0000 Subject: [PATCH 2/5] test(js-sdk): drop tests that check their own fake or duplicate a sibling Co-Authored-By: mish@e2b.dev --- packages/js-sdk/tests/api/snapshot.test.ts | 12 ------ packages/js-sdk/tests/paginator.test.ts | 10 +---- .../tests/sandbox/commands/sendStdin.test.ts | 21 ---------- .../js-sdk/tests/sandbox/snapshot-api.test.ts | 42 ------------------- .../js-sdk/tests/template/apiDefaults.test.ts | 17 -------- .../js-sdk/tests/template/boundOpts.test.ts | 2 +- .../template/utils/getAllFilesInPath.test.ts | 34 ++++++--------- 7 files changed, 15 insertions(+), 123 deletions(-) diff --git a/packages/js-sdk/tests/api/snapshot.test.ts b/packages/js-sdk/tests/api/snapshot.test.ts index a0a52308ae..ce5e0d59e9 100644 --- a/packages/js-sdk/tests/api/snapshot.test.ts +++ b/packages/js-sdk/tests/api/snapshot.test.ts @@ -3,18 +3,6 @@ import { assert } from 'vitest' import { sandboxTest, isDebug } from '../setup.js' import { Sandbox } from '../../src' -sandboxTest.skipIf(isDebug)( - 'pause sandbox', - async ({ sandbox }) => { - await Sandbox.pause(sandbox.sandboxId) - assert.isFalse( - await sandbox.isRunning(), - 'Sandbox should not be running after pause' - ) - }, - 120_000 -) - sandboxTest.skipIf(isDebug)( 'resume sandbox', async ({ sandbox }) => { diff --git a/packages/js-sdk/tests/paginator.test.ts b/packages/js-sdk/tests/paginator.test.ts index 67169b6abb..cd4d82525a 100644 --- a/packages/js-sdk/tests/paginator.test.ts +++ b/packages/js-sdk/tests/paginator.test.ts @@ -1,4 +1,4 @@ -import { assert, expect, test } from 'vitest' +import { assert, test } from 'vitest' import { Paginator } from '../src/paginator' @@ -52,11 +52,3 @@ test('paginator exposes pagination state and advances across pages', async () => assert.isFalse(paginator.hasNext) assert.isUndefined(paginator.nextToken) }) - -test('paginator throws once exhausted', async () => { - const paginator = new FakePaginator([{ items: [], nextToken: undefined }]) - await paginator.nextItems() - - assert.isFalse(paginator.hasNext) - await expect(paginator.nextItems()).rejects.toThrow('No more items to fetch') -}) diff --git a/packages/js-sdk/tests/sandbox/commands/sendStdin.test.ts b/packages/js-sdk/tests/sandbox/commands/sendStdin.test.ts index da0831c92d..3184e5b00d 100644 --- a/packages/js-sdk/tests/sandbox/commands/sendStdin.test.ts +++ b/packages/js-sdk/tests/sandbox/commands/sendStdin.test.ts @@ -43,27 +43,6 @@ sandboxTest('send Uint8Array stdin to process', async ({ sandbox }) => { assert.equal(cmd.stdout, text) }) -sandboxTest('send stdin via command handle', async ({ sandbox }) => { - const text = 'Hello, World!' - const cmd = await sandbox.commands.run('cat', { - background: true, - stdin: true, - }) - - await cmd.sendStdin(text) - - for (let i = 0; i < 5; i++) { - if (cmd.stdout === text) { - break - } - await new Promise((r) => setTimeout(r, 500)) - } - - await cmd.kill() - - assert.equal(cmd.stdout, text) -}) - sandboxTest('close stdin via command handle', async ({ sandbox }) => { const text = 'Hello, World!' const cmd = await sandbox.commands.run('cat', { diff --git a/packages/js-sdk/tests/sandbox/snapshot-api.test.ts b/packages/js-sdk/tests/sandbox/snapshot-api.test.ts index 3c69a3e5be..098760aa19 100644 --- a/packages/js-sdk/tests/sandbox/snapshot-api.test.ts +++ b/packages/js-sdk/tests/sandbox/snapshot-api.test.ts @@ -205,48 +205,6 @@ sandboxTest.skipIf(isDebug)('delete snapshot', async ({ sandbox }) => { assert.isFalse(deletedAgain) }) -sandboxTest.skipIf(isDebug)( - 'snapshot preserves file system state', - async ({ sandbox, sandboxTestId }) => { - const appDir = '/home/user/app' - const configPath = `${appDir}/config.json` - const configContent = '{"env": "test"}' - const dataPath = `${appDir}/data.txt` - const dataContent = 'important data' - - await sandbox.files.makeDir(appDir) - await sandbox.files.write(configPath, configContent) - await sandbox.files.write(dataPath, dataContent) - - const snapshot = await sandbox.createSnapshot() - - try { - const newSandbox = await Sandbox.create(snapshot.snapshotId, { - metadata: { sandboxTestId: `${sandboxTestId}-fs-test` }, - requestTimeoutMs: SNAPSHOT_CREATE_REQUEST_TIMEOUT_MS, - }) - - try { - // Verify directory exists - const dirExists = await newSandbox.files.exists(appDir) - assert.isTrue(dirExists) - - // Verify files exist with correct content - const config = await newSandbox.files.read(configPath) - const data = await newSandbox.files.read(dataPath) - - assert.equal(config, configContent) - assert.equal(data, dataContent) - } finally { - await newSandbox.kill() - } - } finally { - await Sandbox.deleteSnapshot(snapshot.snapshotId) - } - }, - 180_000 -) - sandboxTest.skipIf(isDebug)( 'create a filesystem-only snapshot', async ({ sandbox, sandboxTestId, skip }) => { diff --git a/packages/js-sdk/tests/template/apiDefaults.test.ts b/packages/js-sdk/tests/template/apiDefaults.test.ts index 3f87f833ce..0c1fcbb7f7 100644 --- a/packages/js-sdk/tests/template/apiDefaults.test.ts +++ b/packages/js-sdk/tests/template/apiDefaults.test.ts @@ -50,20 +50,3 @@ test('template build request sends explicit cpuCount and memoryMB', async () => expect(lastBuildBody?.cpuCount).toBe(1) expect(lastBuildBody?.memoryMB).toBe(512) }) - -test('template build request omits maxCpuCount when unset', async () => { - await requestBuild(client(), { name: 'test-template', cpuCount: 2 }) - - expect(lastBuildBody).not.toHaveProperty('maxCpuCount') -}) - -test('template build request sends explicit maxCpuCount', async () => { - await requestBuild(client(), { - name: 'test-template', - cpuCount: 2, - maxCpuCount: 4, - }) - - expect(lastBuildBody?.cpuCount).toBe(2) - expect(lastBuildBody?.maxCpuCount).toBe(4) -}) diff --git a/packages/js-sdk/tests/template/boundOpts.test.ts b/packages/js-sdk/tests/template/boundOpts.test.ts index c7292b5ef5..270b3f8a80 100644 --- a/packages/js-sdk/tests/template/boundOpts.test.ts +++ b/packages/js-sdk/tests/template/boundOpts.test.ts @@ -226,7 +226,7 @@ test.each([ }) test.each([ - [{}, {}], + [{ cpuCount: 2 }, { cpuCount: 2 }], [ { cpuCount: 2, maxCpuCount: 4 }, { cpuCount: 2, maxCpuCount: 4 }, diff --git a/packages/js-sdk/tests/template/utils/getAllFilesInPath.test.ts b/packages/js-sdk/tests/template/utils/getAllFilesInPath.test.ts index 86bdf328ce..2b1ca1058c 100644 --- a/packages/js-sdk/tests/template/utils/getAllFilesInPath.test.ts +++ b/packages/js-sdk/tests/template/utils/getAllFilesInPath.test.ts @@ -8,8 +8,7 @@ import { afterEach, vi, } from 'vitest' -import { createHash, randomBytes } from 'crypto' -import fs, { statSync } from 'fs' +import { randomBytes } from 'crypto' import { appendFile, writeFile, mkdir, mkdtemp, rm, symlink } from 'fs/promises' import { tmpdir } from 'os' import { join, basename, relative } from 'path' @@ -585,28 +584,21 @@ describe('calculateFilesHash', () => { test('should hash file content spanning multiple read chunks', async () => { const content = randomBytes(3 * 1024 * 1024 + 123) const filePath = join(testDir, 'big.bin') + const hash = () => + calculateFilesHash('big.bin', '/app', testDir, [], false, undefined) + await writeFile(filePath, content) - const stats = statSync(filePath) - - const expected = createHash('sha256') - .update('COPY big.bin /app') - .update('big.bin') - .update(stats.mode.toString()) - .update(stats.size.toString()) - .update(content) - .digest('hex') - - expect( - await calculateFilesHash('big.bin', '/app', testDir, [], false, undefined) - ).toBe(expected) - }) + const original = await hash() - test('should not read whole files into memory', async () => { - await writeFile(join(testDir, 'big.bin'), randomBytes(2 * 1024 * 1024)) - const readFileSync = vi.spyOn(fs, 'readFileSync') + // Flip one byte in the final, partial chunk; same size and mode. + content[content.length - 1] ^= 0xff + await writeFile(filePath, content) + const changed = await hash() - await calculateFilesHash('big.bin', '/app', testDir, [], false, undefined) + content[content.length - 1] ^= 0xff + await writeFile(filePath, content) - expect(readFileSync).not.toHaveBeenCalled() + expect(changed).not.toBe(original) + expect(await hash()).toBe(original) }) }) From 3ce3ccf33c98ae138e7218dc5830a8538abbf1c8 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 13 Nov 2026 21:15:29 +0000 Subject: [PATCH 3/5] test(python-sdk): cover stream_input pty data and deadline at the public seam Co-Authored-By: mish@e2b.dev --- .../commands/test_stream_input.py | 15 +++++ .../tests/test_stream_input_sync.py | 60 ------------------- 2 files changed, 15 insertions(+), 60 deletions(-) delete mode 100644 packages/python-sdk/tests/test_stream_input_sync.py diff --git a/packages/python-sdk/tests/sync/sandbox_sync/commands/test_stream_input.py b/packages/python-sdk/tests/sync/sandbox_sync/commands/test_stream_input.py index b75c670d6a..9745c90be5 100644 --- a/packages/python-sdk/tests/sync/sandbox_sync/commands/test_stream_input.py +++ b/packages/python-sdk/tests/sync/sandbox_sync/commands/test_stream_input.py @@ -140,3 +140,18 @@ def test_stream_input_sends_start_then_ordered_utf8_data(fake_envd_sandbox: Sand base64.b64decode(message["data"]["input"]["stdin"]) for message in messages[1:] ] assert data == [b"first", b"caf\xc3\xa9", b"second"] + + +def test_pty_stream_input_sends_pty_data_under_the_stream_timeout( + fake_envd_sandbox: Sandbox, +): + fake_envd_sandbox.pty.stream_input(42, ["a", b"b"], timeout=5) + + [(path, headers, messages)] = _FakeEnvdHandler.requests + assert path == "/process.Process/StreamInput" + assert headers["connect-timeout-ms"] == "5000" + assert messages[0] == {"start": {"process": {"pid": 42}}} + data = [ + base64.b64decode(message["data"]["input"]["pty"]) for message in messages[1:] + ] + assert data == [b"a", b"b"] diff --git a/packages/python-sdk/tests/test_stream_input_sync.py b/packages/python-sdk/tests/test_stream_input_sync.py deleted file mode 100644 index 1abd7b016d..0000000000 --- a/packages/python-sdk/tests/test_stream_input_sync.py +++ /dev/null @@ -1,60 +0,0 @@ -from typing import cast - -import pytest -from connectrpc.code import Code -from connectrpc.errors import ConnectError - -from e2b.envd.process import process_connect -from e2b.exceptions import InvalidArgumentException, NotFoundException -from e2b.sandbox.commands.stream_input import stream_input_sync - - -class _FakeRpc: - def __init__(self, error=None): - self.requests = [] - self.timeout_ms = None - self._error = error - - def stream_input(self, requests, timeout_ms=None): - self.timeout_ms = timeout_ms - self.requests = list(requests) - if self._error is not None: - raise self._error - - -def _client(rpc: _FakeRpc) -> process_connect.ProcessClientSync: - return cast(process_connect.ProcessClientSync, rpc) - - -@pytest.mark.parametrize("input_kind", ["stdin", "pty"]) -def test_sends_start_then_data_events(input_kind): - rpc = _FakeRpc() - - stream_input_sync(_client(rpc), 42, input_kind, ["a", b"b"], 5, lambda: True) - - start, *data = rpc.requests - assert start.event.field == "start" - assert start.event.value.process.selector.value == 42 - assert [(r.event.field, r.event.value.input.input.field) for r in data] == [ - ("data", input_kind), - ("data", input_kind), - ] - assert [r.event.value.input.input.value for r in data] == [b"a", b"b"] - assert rpc.timeout_ms == 5000 - - -@pytest.mark.parametrize("chunk", ["data", b"data", bytearray(b"data")]) -def test_rejects_single_chunk(chunk): - rpc = _FakeRpc() - - with pytest.raises(InvalidArgumentException): - stream_input_sync(_client(rpc), 1, "stdin", chunk, None, lambda: True) - - assert rpc.requests == [] - - -def test_maps_rpc_errors(): - rpc = _FakeRpc(error=ConnectError(Code.NOT_FOUND, "missing")) - - with pytest.raises(NotFoundException): - stream_input_sync(_client(rpc), 1, "pty", ["x"], None, lambda: True) From 56755c452abe7f78fba610bfe28ce8ce598128d2 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 13 Nov 2026 21:15:29 +0000 Subject: [PATCH 4/5] test(python-sdk): rewrite private-helper and mocked-factory tests at public seams Co-Authored-By: mish@e2b.dev --- .../sandbox_async/test_config_propagation.py | 79 +++++++++++-------- .../tests/shared/sandbox/test_api_defaults.py | 46 +++++++++-- .../shared/sandbox/test_on_resume_request.py | 39 +++++++-- .../sandbox_sync/test_config_propagation.py | 79 +++++++++++-------- .../tests/test_envd_stream_request_timeout.py | 49 +++++++----- 5 files changed, 190 insertions(+), 102 deletions(-) diff --git a/packages/python-sdk/tests/async/sandbox_async/test_config_propagation.py b/packages/python-sdk/tests/async/sandbox_async/test_config_propagation.py index f43eff0cd8..ea01b8ff00 100644 --- a/packages/python-sdk/tests/async/sandbox_async/test_config_propagation.py +++ b/packages/python-sdk/tests/async/sandbox_async/test_config_propagation.py @@ -3,16 +3,13 @@ import time from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from typing import Dict, List, Tuple -from unittest.mock import AsyncMock import httpx import pytest from local_api_server import connect_recording_proxy from e2b import AsyncSandbox -from e2b.api import SandboxCreateResponse from e2b.connection_config import ConnectionConfig -import e2b.sandbox_async.main as sandbox_async_main BASE_DOMAIN = "base.e2b.dev" BASE_REQUEST_TIMEOUT = 11 @@ -160,39 +157,53 @@ async def test_pause_request_timeout_override_wins(fake_api, test_api_key): assert await sandbox.pause(request_timeout=5) is True -@pytest.mark.skip_debug() -async def test_connect_sets_stable_host_routing_headers(monkeypatch, test_api_key): - mock_connect = AsyncMock( - return_value=SandboxCreateResponse( - sandbox_id="sbx-test", - sandbox_domain="e2b.app", - envd_version="0.4.0", - envd_access_token="tok", - traffic_access_token="traffic", - ) - ) - monkeypatch.setattr(sandbox_async_main.SandboxApi, "_cls_connect", mock_connect) +class _FakeEnvdHandler(BaseHTTPRequestHandler): + """Answers envd file reads and records each request's headers.""" - monkeypatch.setattr(ConnectionConfig, "_integration", "testing/version") - config = ConnectionConfig( - api_key=test_api_key, - api_headers=BASE_HEADERS, - ) + headers_seen: List[Dict[str, str]] = [] + + def log_message(self, *args): # noqa: A003 - silence the default stderr log + pass + + def do_GET(self): + type(self).headers_seen.append({k.lower(): v for k, v in self.headers.items()}) + body = b"hello" + self.send_response(200) + self.send_header("Content-Type", "text/plain") + self.send_header("Content-Length", str(len(body))) + self.end_headers() + self.wfile.write(body) + + +@pytest.fixture +def fake_envd(): + _FakeEnvdHandler.headers_seen = [] + server = ThreadingHTTPServer(("127.0.0.1", 0), _FakeEnvdHandler) + threading.Thread(target=server.serve_forever, daemon=True).start() + try: + yield f"http://127.0.0.1:{server.server_port}" + finally: + server.shutdown() + server.server_close() + + +@pytest.mark.skip_debug() +async def test_connect_sends_stable_host_routing_headers_to_envd( + fake_api, fake_envd, test_api_key +): sandbox = await AsyncSandbox.connect( "sbx-test", - **config.get_api_params(), + api_key=test_api_key, + api_url=fake_api(), + sandbox_url=fake_envd, + api_headers=BASE_HEADERS, ) - assert sandbox.envd_api_url == "https://sandbox.e2b.app" - assert "X-Test" not in sandbox.connection_config.sandbox_headers - assert sandbox.connection_config.sandbox_headers["User-Agent"].startswith( - "e2b-python-sdk/" - ) - assert sandbox.connection_config.sandbox_headers["User-Agent"].endswith( - " testing/version" - ) - assert sandbox.connection_config.sandbox_headers["E2b-Sandbox-Id"] == "sbx-test" - assert sandbox.connection_config.sandbox_headers["E2b-Sandbox-Port"] == str( - ConnectionConfig.envd_port - ) - assert sandbox.connection_config.sandbox_headers["X-Access-Token"] == "tok" + assert await sandbox.files.read("/hello.txt") == "hello" + + [headers] = _FakeEnvdHandler.headers_seen + assert "x-test" not in headers + assert headers["user-agent"].startswith("e2b-python-sdk/") + assert headers["e2b-sandbox-id"] == "sbx-test" + assert headers["e2b-sandbox-port"] == str(ConnectionConfig.envd_port) + assert headers["x-access-token"] == "tok" diff --git a/packages/python-sdk/tests/shared/sandbox/test_api_defaults.py b/packages/python-sdk/tests/shared/sandbox/test_api_defaults.py index 6ffefc2131..cef3ee40f7 100644 --- a/packages/python-sdk/tests/shared/sandbox/test_api_defaults.py +++ b/packages/python-sdk/tests/shared/sandbox/test_api_defaults.py @@ -17,9 +17,8 @@ post_sandboxes_sandbox_id_pause, post_sandboxes_sandbox_id_snapshots, ) -from e2b.api.client.models import ListedSandbox, SandboxDetail from e2b.api.client.models import Sandbox as SandboxModel -from e2b.sandbox.sandbox_api import SandboxInfo +from local_api_server import Reply, local_api_server def _created_sandbox(): @@ -432,11 +431,13 @@ async def test_async_connect_raises_guest_unresponsive(monkeypatch, test_api_key assert exc.value.status_code == 409 -@pytest.mark.parametrize( +ENVD_UNRESPONSIVE_CASES = pytest.mark.parametrize( "state, value, expected", [("paused", True, True), ("paused", None, None), ("running", None, None)], ) -def test_sandbox_info_maps_envd_unresponsive_at_pause(state, value, expected): + + +def _sandbox_reply(state, value): data = { "templateID": "base", "sandboxID": "sbx-test", @@ -452,8 +453,39 @@ def test_sandbox_info_maps_envd_unresponsive_at_pause(state, value, expected): if value is not None: data["envdUnresponsiveAtPause"] = value - detail = SandboxInfo._from_sandbox_detail(SandboxDetail.from_dict(data)) - listed = SandboxInfo._from_listed_sandbox(ListedSandbox.from_dict(data)) + def reply(method: str, path: str) -> Reply: + path = path.split("?")[0] + if method == "GET" and path == "/sandboxes/sbx-test": + return 200, data, None + if method == "GET" and path == "/v2/sandboxes": + return 200, [data], None + return 404, {"code": 404, "message": "not found"}, None - assert detail.envd_unresponsive_at_pause is expected + return reply + + +@ENVD_UNRESPONSIVE_CASES +def test_sandbox_info_maps_envd_unresponsive_at_pause( + state, value, expected, test_api_key +): + with local_api_server(_sandbox_reply(state, value)) as api: + info = Sandbox.get_info("sbx-test", api_key=test_api_key, api_url=api.url) + [listed] = Sandbox.list(api_key=test_api_key, api_url=api.url).next_items() + + assert info.envd_unresponsive_at_pause is expected + assert listed.envd_unresponsive_at_pause is expected + + +@ENVD_UNRESPONSIVE_CASES +async def test_async_sandbox_info_maps_envd_unresponsive_at_pause( + state, value, expected, test_api_key +): + with local_api_server(_sandbox_reply(state, value)) as api: + info = await AsyncSandbox.get_info( + "sbx-test", api_key=test_api_key, api_url=api.url + ) + paginator = AsyncSandbox.list(api_key=test_api_key, api_url=api.url) + [listed] = await paginator.next_items() + + assert info.envd_unresponsive_at_pause is expected assert listed.envd_unresponsive_at_pause is expected diff --git a/packages/python-sdk/tests/shared/sandbox/test_on_resume_request.py b/packages/python-sdk/tests/shared/sandbox/test_on_resume_request.py index 1ab2f9e7b9..c7b7e47d0a 100644 --- a/packages/python-sdk/tests/shared/sandbox/test_on_resume_request.py +++ b/packages/python-sdk/tests/shared/sandbox/test_on_resume_request.py @@ -1,4 +1,3 @@ -import inspect from types import SimpleNamespace from typing import Any, Dict, Optional, cast from unittest.mock import AsyncMock, Mock @@ -167,12 +166,40 @@ async def test_async_connect_keeps_timeout_and_logger_positional( assert body["memory"] is False -@pytest.mark.parametrize("sandbox", [Sandbox, AsyncSandbox], ids=["sync", "async"]) -def test_on_resume_is_keyword_only_on_the_instance_form(sandbox): - signature = inspect.signature(sandbox.connect) +def test_instance_connect_takes_on_resume_only_by_keyword(monkeypatch, test_api_key): + request = Mock(return_value=_connected_sandbox()) + monkeypatch.setattr(post_v_2_sandboxes_sandbox_id_connect, "sync_detailed", request) + sandbox = Sandbox.connect(SANDBOX_ID, api_key=test_api_key) + request.reset_mock() + + with pytest.raises(TypeError): + cast(Any, sandbox.connect)(300, "reboot") + request.assert_not_called() - assert signature.parameters["on_resume"].kind is inspect.Parameter.KEYWORD_ONLY - assert signature.parameters["timeout"].kind is not inspect.Parameter.KEYWORD_ONLY + sandbox.connect(300, on_resume="reboot") + body = request.call_args.kwargs["body"].to_dict() + assert body["timeout"] == 300 + assert body["memory"] is False + + +async def test_async_instance_connect_takes_on_resume_only_by_keyword( + monkeypatch, test_api_key +): + request = AsyncMock(return_value=_connected_sandbox()) + monkeypatch.setattr( + post_v_2_sandboxes_sandbox_id_connect, "asyncio_detailed", request + ) + sandbox = await AsyncSandbox.connect(SANDBOX_ID, api_key=test_api_key) + request.reset_mock() + + with pytest.raises(TypeError): + await cast(Any, sandbox.connect)(300, "reboot") + request.assert_not_called() + + await sandbox.connect(300, on_resume="reboot") + body = request.call_args.kwargs["body"].to_dict() + assert body["timeout"] == 300 + assert body["memory"] is False @pytest.mark.parametrize("value", UNRECOGNIZED) diff --git a/packages/python-sdk/tests/sync/sandbox_sync/test_config_propagation.py b/packages/python-sdk/tests/sync/sandbox_sync/test_config_propagation.py index 6be4312e3b..a5fe9a459c 100644 --- a/packages/python-sdk/tests/sync/sandbox_sync/test_config_propagation.py +++ b/packages/python-sdk/tests/sync/sandbox_sync/test_config_propagation.py @@ -3,16 +3,13 @@ import time from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from typing import Dict, List, Tuple -from unittest.mock import Mock import httpx import pytest from local_api_server import connect_recording_proxy from e2b import Sandbox -from e2b.api import SandboxCreateResponse from e2b.connection_config import ConnectionConfig -import e2b.sandbox_sync.main as sandbox_sync_main BASE_DOMAIN = "base.e2b.dev" BASE_REQUEST_TIMEOUT = 11 @@ -160,39 +157,53 @@ def test_pause_request_timeout_override_wins(fake_api, test_api_key): assert sandbox.pause(request_timeout=5) is True -@pytest.mark.skip_debug() -def test_connect_sets_stable_host_routing_headers(monkeypatch, test_api_key): - mock_connect = Mock( - return_value=SandboxCreateResponse( - sandbox_id="sbx-test", - sandbox_domain="e2b.app", - envd_version="0.4.0", - envd_access_token="tok", - traffic_access_token="traffic", - ) - ) - monkeypatch.setattr(sandbox_sync_main.SandboxApi, "_cls_connect", mock_connect) +class _FakeEnvdHandler(BaseHTTPRequestHandler): + """Answers envd file reads and records each request's headers.""" - monkeypatch.setattr(ConnectionConfig, "_integration", "testing/version") - config = ConnectionConfig( - api_key=test_api_key, - api_headers=BASE_HEADERS, - ) + headers_seen: List[Dict[str, str]] = [] + + def log_message(self, *args): # noqa: A003 - silence the default stderr log + pass + + def do_GET(self): + type(self).headers_seen.append({k.lower(): v for k, v in self.headers.items()}) + body = b"hello" + self.send_response(200) + self.send_header("Content-Type", "text/plain") + self.send_header("Content-Length", str(len(body))) + self.end_headers() + self.wfile.write(body) + + +@pytest.fixture +def fake_envd(): + _FakeEnvdHandler.headers_seen = [] + server = ThreadingHTTPServer(("127.0.0.1", 0), _FakeEnvdHandler) + threading.Thread(target=server.serve_forever, daemon=True).start() + try: + yield f"http://127.0.0.1:{server.server_port}" + finally: + server.shutdown() + server.server_close() + + +@pytest.mark.skip_debug() +def test_connect_sends_stable_host_routing_headers_to_envd( + fake_api, fake_envd, test_api_key +): sandbox = Sandbox.connect( "sbx-test", - **config.get_api_params(), + api_key=test_api_key, + api_url=fake_api(), + sandbox_url=fake_envd, + api_headers=BASE_HEADERS, ) - assert sandbox.envd_api_url == "https://sandbox.e2b.app" - assert "X-Test" not in sandbox.connection_config.sandbox_headers - assert sandbox.connection_config.sandbox_headers["User-Agent"].startswith( - "e2b-python-sdk/" - ) - assert sandbox.connection_config.sandbox_headers["User-Agent"].endswith( - " testing/version" - ) - assert sandbox.connection_config.sandbox_headers["E2b-Sandbox-Id"] == "sbx-test" - assert sandbox.connection_config.sandbox_headers["E2b-Sandbox-Port"] == str( - ConnectionConfig.envd_port - ) - assert sandbox.connection_config.sandbox_headers["X-Access-Token"] == "tok" + assert sandbox.files.read("/hello.txt") == "hello" + + [headers] = _FakeEnvdHandler.headers_seen + assert "x-test" not in headers + assert headers["user-agent"].startswith("e2b-python-sdk/") + assert headers["e2b-sandbox-id"] == "sbx-test" + assert headers["e2b-sandbox-port"] == str(ConnectionConfig.envd_port) + assert headers["x-access-token"] == "tok" diff --git a/packages/python-sdk/tests/test_envd_stream_request_timeout.py b/packages/python-sdk/tests/test_envd_stream_request_timeout.py index 64ddc9f32e..9a130e42e7 100644 --- a/packages/python-sdk/tests/test_envd_stream_request_timeout.py +++ b/packages/python-sdk/tests/test_envd_stream_request_timeout.py @@ -20,10 +20,12 @@ import pytest from connectrpc.code import Code from connectrpc.errors import ConnectError -from envd_frame_server import make_config +from envd_frame_server import frame_recording_server, make_config from packaging.version import Version +from pyqwest import HTTPVersion +from transport_caches import reset_transport_caches -import e2b.sandbox_async.commands.command as command_async +import e2b.api.client_async as api_client_async from e2b.envd.client_async import first_event from e2b.envd.rpc import handle_rpc_exception from e2b.exceptions import TimeoutException @@ -108,23 +110,28 @@ async def call(): async def test_commands_connect_applies_request_timeout(monkeypatch): - class NeverStartingRpc: - def connect(self, req, headers=None, timeout_ms=None): - return connectrpc_style_stream(30) - - # Hand Commands the stub directly; the real factory would register a - # pooled transport in the process-global cache. - monkeypatch.setattr( - command_async, "create_rpc_client", lambda *_args, **_kwargs: NeverStartingRpc() - ) - commands = Commands( - "http://127.0.0.1:1", - make_config(), - Version("0.5.0"), - httpx.AsyncClient(), - ) + # The frame server is plaintext, so force HTTP/2 prior knowledge while + # keeping the SDK's own RPC client factory and transport cache. + build_transport = api_client_async.HTTPTransport - start = time.monotonic() - with pytest.raises(TimeoutException, match="request_timeout"): - await commands.connect(pid=1, request_timeout=0.1) - assert time.monotonic() - start < 5 + def build_http2_transport(**kwargs): + kwargs["http_version"] = HTTPVersion.HTTP2 + return build_transport(**kwargs) + + reset_transport_caches() + monkeypatch.setattr(api_client_async, "HTTPTransport", build_http2_transport) + try: + with frame_recording_server(server_ends_stream=False, respond=False) as server: + commands = Commands( + f"http://127.0.0.1:{server.port}", + make_config(), + Version("0.5.0"), + httpx.AsyncClient(), + ) + + start = time.monotonic() + with pytest.raises(TimeoutException, match="request_timeout"): + await commands.connect(pid=1, request_timeout=0.1) + assert time.monotonic() - start < 5 + finally: + reset_transport_caches() From cb548ce22348089d4ee61f8b9bf7699e2d11eb27 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 13 Nov 2026 21:15:29 +0000 Subject: [PATCH 5/5] test(python-sdk): drop duplicate, tautological and internal-state tests Co-Authored-By: mish@e2b.dev --- .../async/sandbox_async/test_snapshot_api.py | 40 ------------ .../tests/async/sandbox_async/test_timeout.py | 7 --- .../template_async/test_bound_api_params.py | 2 +- .../utils/test_get_all_files_in_path.py | 62 +++++-------------- .../utils/test_normalize_build_arguments.py | 10 --- .../sync/sandbox_sync/test_snapshot_api.py | 40 ------------ .../tests/sync/sandbox_sync/test_timeout.py | 7 --- .../template_sync/test_bound_api_params.py | 2 +- .../tests/test_envd_interceptors.py | 18 ------ .../tests/test_filesystem_models.py | 8 --- .../tests/test_volume_connection_config.py | 6 -- 11 files changed, 18 insertions(+), 184 deletions(-) diff --git a/packages/python-sdk/tests/async/sandbox_async/test_snapshot_api.py b/packages/python-sdk/tests/async/sandbox_async/test_snapshot_api.py index 23534f6832..585f0b0d15 100644 --- a/packages/python-sdk/tests/async/sandbox_async/test_snapshot_api.py +++ b/packages/python-sdk/tests/async/sandbox_async/test_snapshot_api.py @@ -149,46 +149,6 @@ async def test_delete_snapshot(async_sandbox: AsyncSandbox): assert deleted_again is False -@pytest.mark.skip_debug() -@pytest.mark.timeout(180) -async def test_snapshot_preserves_filesystem(async_sandbox: AsyncSandbox): - app_dir = "/home/user/app" - config_path = f"{app_dir}/config.json" - config_content = '{"env": "test"}' - data_path = f"{app_dir}/data.txt" - data_content = "important data" - - await async_sandbox.files.make_dir(app_dir) - await async_sandbox.files.write(config_path, config_content) - await async_sandbox.files.write(data_path, data_content) - - snapshot = await async_sandbox.create_snapshot() - - try: - try: - new_sandbox = await AsyncSandbox.create(snapshot.snapshot_id) - except SandboxException as error: - # Placement can transiently time out while the snapshot is restored. - # Retry only the backend response that explicitly asks the caller to do so. - if "Failed to place sandbox: placement timed out" not in str(error): - raise - new_sandbox = await AsyncSandbox.create(snapshot.snapshot_id) - - try: - dir_exists = await new_sandbox.files.exists(app_dir) - assert dir_exists - - config = await new_sandbox.files.read(config_path) - data = await new_sandbox.files.read(data_path) - - assert config == config_content - assert data == data_content - finally: - await new_sandbox.kill() - finally: - await AsyncSandbox.delete_snapshot(snapshot.snapshot_id) - - @pytest.mark.skip_debug() async def test_create_snapshot_class_method(async_sandbox: AsyncSandbox): snapshot = await AsyncSandbox.create_snapshot(async_sandbox.sandbox_id) diff --git a/packages/python-sdk/tests/async/sandbox_async/test_timeout.py b/packages/python-sdk/tests/async/sandbox_async/test_timeout.py index b36ae72ce3..4eddce87d6 100644 --- a/packages/python-sdk/tests/async/sandbox_async/test_timeout.py +++ b/packages/python-sdk/tests/async/sandbox_async/test_timeout.py @@ -1,5 +1,4 @@ import pytest -from datetime import datetime from time import sleep @@ -24,9 +23,3 @@ async def test_shorten_then_lengthen_timeout(async_sandbox: AsyncSandbox): is_running = await async_sandbox.is_running() assert is_running is True - - -@pytest.mark.skip_debug() -async def test_get_timeout(async_sandbox: AsyncSandbox): - info = await async_sandbox.get_info() - assert isinstance(info.end_at, datetime) diff --git a/packages/python-sdk/tests/async/template_async/test_bound_api_params.py b/packages/python-sdk/tests/async/template_async/test_bound_api_params.py index d92f4f90ea..67aa77b3ee 100644 --- a/packages/python-sdk/tests/async/template_async/test_bound_api_params.py +++ b/packages/python-sdk/tests/async/template_async/test_bound_api_params.py @@ -241,7 +241,7 @@ async def request(*, client, body): @pytest.mark.parametrize( "options, expected_body", [ - ({}, {}), + ({"cpu_count": 2}, {"cpuCount": 2}), ( {"cpu_count": 2, "max_cpu_count": 4}, {"cpuCount": 2, "maxCpuCount": 4}, diff --git a/packages/python-sdk/tests/shared/template/utils/test_get_all_files_in_path.py b/packages/python-sdk/tests/shared/template/utils/test_get_all_files_in_path.py index 4084e20385..b063131f01 100644 --- a/packages/python-sdk/tests/shared/template/utils/test_get_all_files_in_path.py +++ b/packages/python-sdk/tests/shared/template/utils/test_get_all_files_in_path.py @@ -1,11 +1,8 @@ -import builtins -import hashlib import os import sys import tempfile import pytest from e2b.exceptions import TemplateException -from e2b.template import utils as template_utils from e2b.template.utils import ( calculate_files_hash, get_all_files_in_path, @@ -577,53 +574,26 @@ def test_dir(self): yield tmpdir def test_should_hash_file_content_spanning_multiple_read_chunks(self, test_dir): - content = os.urandom(3 * 1024 * 1024 + 123) + content = bytearray(os.urandom(3 * 1024 * 1024 + 123)) file_path = os.path.join(test_dir, "big.bin") - with open(file_path, "wb") as f: - f.write(content) - stats = os.stat(file_path) - - expected = hashlib.sha256() - expected.update(b"COPY big.bin /app") - expected.update(b"big.bin") - expected.update(str(stats.st_mode).encode()) - expected.update(str(stats.st_size).encode()) - expected.update(content) - - assert ( - calculate_files_hash("big.bin", "/app", test_dir, [], False, None) - == expected.hexdigest() - ) - - def test_should_not_read_whole_files_into_memory(self, test_dir, monkeypatch): - with open(os.path.join(test_dir, "big.bin"), "wb") as f: - f.write(os.urandom(2 * 1024 * 1024)) - - read_sizes = [] - real_open = builtins.open - class RecordingFile: - def __init__(self, f): - self._f = f + def write(): + with open(file_path, "wb") as f: + f.write(content) - def __enter__(self): - return self - - def __exit__(self, *exc): - self._f.close() + def files_hash(): + return calculate_files_hash("big.bin", "/app", test_dir, [], False, None) - def read(self, size=-1): - read_sizes.append(size) - return self._f.read(size) + write() + original = files_hash() - monkeypatch.setattr( - template_utils, - "open", - lambda *args, **kwargs: RecordingFile(real_open(*args, **kwargs)), - raising=False, - ) + # Flip one byte in the final, partial chunk; same size and mode. + content[-1] ^= 0xFF + write() + changed = files_hash() - calculate_files_hash("big.bin", "/app", test_dir, [], False, None) + content[-1] ^= 0xFF + write() - assert read_sizes - assert all(0 < size <= 1024 * 1024 for size in read_sizes) + assert changed != original + assert files_hash() == original diff --git a/packages/python-sdk/tests/shared/template/utils/test_normalize_build_arguments.py b/packages/python-sdk/tests/shared/template/utils/test_normalize_build_arguments.py index f6e83c4798..91d5e8d37d 100644 --- a/packages/python-sdk/tests/shared/template/utils/test_normalize_build_arguments.py +++ b/packages/python-sdk/tests/shared/template/utils/test_normalize_build_arguments.py @@ -9,11 +9,6 @@ def test_handles_string_name(): assert result == "my-template:v1.0" -def test_handles_name_without_tag(): - result = normalize_build_arguments(name="my-template") - assert result == "my-template" - - def test_handles_legacy_alias(): result = normalize_build_arguments(alias="my-template") assert result == "my-template" @@ -38,8 +33,3 @@ def test_throws_for_empty_alias(): def test_throws_for_missing_name_and_alias(): with pytest.raises(TemplateException, match="Name must be provided"): normalize_build_arguments() - - -def test_throws_for_none_values(): - with pytest.raises(TemplateException, match="Name must be provided"): - normalize_build_arguments(name=None, alias=None) diff --git a/packages/python-sdk/tests/sync/sandbox_sync/test_snapshot_api.py b/packages/python-sdk/tests/sync/sandbox_sync/test_snapshot_api.py index 45a9b4ce4a..d764e31cea 100644 --- a/packages/python-sdk/tests/sync/sandbox_sync/test_snapshot_api.py +++ b/packages/python-sdk/tests/sync/sandbox_sync/test_snapshot_api.py @@ -143,46 +143,6 @@ def test_delete_snapshot(sandbox: Sandbox): assert deleted_again is False -@pytest.mark.skip_debug() -@pytest.mark.timeout(180) -def test_snapshot_preserves_filesystem(sandbox: Sandbox): - app_dir = "/home/user/app" - config_path = f"{app_dir}/config.json" - config_content = '{"env": "test"}' - data_path = f"{app_dir}/data.txt" - data_content = "important data" - - sandbox.files.make_dir(app_dir) - sandbox.files.write(config_path, config_content) - sandbox.files.write(data_path, data_content) - - snapshot = sandbox.create_snapshot() - - try: - try: - new_sandbox = Sandbox.create(snapshot.snapshot_id) - except SandboxException as error: - # Placement can transiently time out while the snapshot is restored. - # Retry only the backend response that explicitly asks the caller to do so. - if "Failed to place sandbox: placement timed out" not in str(error): - raise - new_sandbox = Sandbox.create(snapshot.snapshot_id) - - try: - dir_exists = new_sandbox.files.exists(app_dir) - assert dir_exists - - config = new_sandbox.files.read(config_path) - data = new_sandbox.files.read(data_path) - - assert config == config_content - assert data == data_content - finally: - new_sandbox.kill() - finally: - Sandbox.delete_snapshot(snapshot.snapshot_id) - - @pytest.mark.skip_debug() def test_create_snapshot_class_method(sandbox: Sandbox): snapshot = Sandbox.create_snapshot(sandbox.sandbox_id) diff --git a/packages/python-sdk/tests/sync/sandbox_sync/test_timeout.py b/packages/python-sdk/tests/sync/sandbox_sync/test_timeout.py index 2e96d83ce1..a6217afc99 100644 --- a/packages/python-sdk/tests/sync/sandbox_sync/test_timeout.py +++ b/packages/python-sdk/tests/sync/sandbox_sync/test_timeout.py @@ -1,5 +1,4 @@ from time import sleep -from datetime import datetime import pytest @@ -22,9 +21,3 @@ def test_shorten_then_lengthen_timeout(sandbox): is_running = sandbox.is_running() assert is_running is True - - -@pytest.mark.skip_debug() -def test_get_timeout(sandbox): - info = sandbox.get_info() - assert isinstance(info.end_at, datetime) diff --git a/packages/python-sdk/tests/sync/template_sync/test_bound_api_params.py b/packages/python-sdk/tests/sync/template_sync/test_bound_api_params.py index 31814cca5a..05f68b6a9f 100644 --- a/packages/python-sdk/tests/sync/template_sync/test_bound_api_params.py +++ b/packages/python-sdk/tests/sync/template_sync/test_bound_api_params.py @@ -216,7 +216,7 @@ def request(*, client, body): @pytest.mark.parametrize( "options, expected_body", [ - ({}, {}), + ({"cpu_count": 2}, {"cpuCount": 2}), ( {"cpu_count": 2, "max_cpu_count": 4}, {"cpuCount": 2, "maxCpuCount": 4}, diff --git a/packages/python-sdk/tests/test_envd_interceptors.py b/packages/python-sdk/tests/test_envd_interceptors.py index 2035917026..4c7762e68b 100644 --- a/packages/python-sdk/tests/test_envd_interceptors.py +++ b/packages/python-sdk/tests/test_envd_interceptors.py @@ -65,24 +65,6 @@ def _full_chain_config() -> ConnectionConfig: return ConnectionConfig(api_key="k", logger=logging.getLogger("test")) -def test_sync_stream_close_reaches_transport_generator(): - closed = [] - - def transport(request, ctx): - try: - for i in range(10): - yield i - finally: - closed.append(True) - - stream = _compose_sync( - build_interceptors(_full_chain_config(), "http://base"), transport - )(None, _ctx()) - assert next(stream) == 0 - stream.close() - assert closed == [True] - - async def test_async_stream_close_reaches_transport_generator(): # Before the interceptors propagated aclose(), the transport generator # was only finalized by the event loop's async-generator GC hook, several diff --git a/packages/python-sdk/tests/test_filesystem_models.py b/packages/python-sdk/tests/test_filesystem_models.py index 9ba1890873..83a728791c 100644 --- a/packages/python-sdk/tests/test_filesystem_models.py +++ b/packages/python-sdk/tests/test_filesystem_models.py @@ -14,7 +14,6 @@ from e2b.sandbox.filesystem.filesystem import ( AsyncWriteEntry, SyncWriteEntry, - ChunkCheck, WriteEntry, check_stream_upload, multipart_body_is_streamed, @@ -278,13 +277,6 @@ def test_file_like_wrappers_are_read_as_files(): assert [len(c) for c in chunks] == [IO_CHUNK_SIZE, 1] -def test_chunk_check_records_the_validation_error(): - check = ChunkCheck() - with pytest.raises(InvalidArgumentException) as raised: - b"".join(to_upload_body(iter([b"ok", "text"]), check=check)) # type: ignore[arg-type] - assert check.error is raised.value - - async def test_async_readers_are_not_file_like(): class AsyncReader: """Like an aiofiles file or aiohttp ``response.content``.""" diff --git a/packages/python-sdk/tests/test_volume_connection_config.py b/packages/python-sdk/tests/test_volume_connection_config.py index e58cc5b399..4c8eabd428 100644 --- a/packages/python-sdk/tests/test_volume_connection_config.py +++ b/packages/python-sdk/tests/test_volume_connection_config.py @@ -50,12 +50,6 @@ def test_volume_api_url_custom_domain_in_args(): assert config.api_url == "https://api.custom.com" -def test_volume_token_defaults_to_none(): - config = VolumeConnectionConfig() - assert config.token is None - assert config.access_token is None - - def test_volume_token_in_args(): config = VolumeConnectionConfig(token="vol-token") assert config.token == "vol-token"