Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions js/tests/reconnect.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { expect } from 'vitest'

import { Sandbox } from '../src'
import { sandboxTest } from './setup'
import { isDebug, sandboxTest } from './setup'

sandboxTest('reconnect', async ({ sandbox }) => {
sandboxTest.skipIf(isDebug)('reconnect', async ({ sandbox }) => {
sandbox = await Sandbox.connect(sandbox.sandboxId)

const result = await sandbox.runCode('x =1; x')
Expand Down
88 changes: 47 additions & 41 deletions js/tests/systemd.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect } from 'vitest'
import { sandboxTest, wait } from './setup'
import { isDebug, sandboxTest, wait } from './setup'

async function waitForHealth(sandbox: any, maxRetries = 10, intervalMs = 100) {
for (let i = 0; i < maxRetries; i++) {
Expand All @@ -18,50 +18,56 @@ async function waitForHealth(sandbox: any, maxRetries = 10, intervalMs = 100) {
return false
}

sandboxTest('restart after jupyter kill', async ({ sandbox }) => {
// Verify health is up initially
const initialHealth = await waitForHealth(sandbox)
expect(initialHealth).toBe(true)
sandboxTest.skipIf(isDebug)(
'restart after jupyter kill',
async ({ sandbox }) => {
// Verify health is up initially
const initialHealth = await waitForHealth(sandbox)
expect(initialHealth).toBe(true)

// Kill the jupyter process as root
// The command handle may get killed too (since killing jupyter cascades to code-interpreter),
// so we catch the error.
try {
await sandbox.commands.run("kill -9 $(pgrep -f 'jupyter server')", {
user: 'root',
})
} catch {
// Expected — the kill cascade may terminate the command handle
}
// Kill the jupyter process as root
// The command handle may get killed too (since killing jupyter cascades to code-interpreter),
// so we catch the error.
try {
await sandbox.commands.run("kill -9 $(pgrep -f 'jupyter server')", {
user: 'root',
})
} catch {
// Expected — the kill cascade may terminate the command handle
}

// Wait for systemd to restart both services
const recovered = await waitForHealth(sandbox, 60, 500)
expect(recovered).toBe(true)
// Wait for systemd to restart both services
const recovered = await waitForHealth(sandbox, 60, 500)
expect(recovered).toBe(true)

// Verify code execution works after recovery
const result = await sandbox.runCode('x = 1; x')
expect(result.text).toEqual('1')
})
// Verify code execution works after recovery
const result = await sandbox.runCode('x = 1; x')
expect(result.text).toEqual('1')
}
)

sandboxTest('restart after code-interpreter kill', async ({ sandbox }) => {
// Verify health is up initially
const initialHealth = await waitForHealth(sandbox)
expect(initialHealth).toBe(true)
sandboxTest.skipIf(isDebug)(
'restart after code-interpreter kill',
async ({ sandbox }) => {
// Verify health is up initially
const initialHealth = await waitForHealth(sandbox)
expect(initialHealth).toBe(true)

// Kill the code-interpreter process as root
try {
await sandbox.commands.run("kill -9 $(pgrep -f 'uvicorn main:app')", {
user: 'root',
})
} catch {
// Expected — killing code-interpreter may terminate the command handle
}
// Kill the code-interpreter process as root
try {
await sandbox.commands.run("kill -9 $(pgrep -f 'uvicorn main:app')", {
user: 'root',
})
} catch {
// Expected — killing code-interpreter may terminate the command handle
}

// Wait for systemd to restart it and health to come back
const recovered = await waitForHealth(sandbox, 60, 500)
expect(recovered).toBe(true)
// Wait for systemd to restart it and health to come back
const recovered = await waitForHealth(sandbox, 60, 500)
expect(recovered).toBe(true)

// Verify code execution works after recovery
const result = await sandbox.runCode('x = 1; x')
expect(result.text).toEqual('1')
})
// Verify code execution works after recovery
const result = await sandbox.runCode('x = 1; x')
expect(result.text).toEqual('1')
}
)
3 changes: 3 additions & 0 deletions python/tests/async/test_async_reconnect.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import pytest

from e2b_code_interpreter.code_interpreter_async import AsyncSandbox


@pytest.mark.skip_debug
async def test_reconnect(async_sandbox: AsyncSandbox):
sandbox_id = async_sandbox.sandbox_id

Expand Down
4 changes: 4 additions & 0 deletions python/tests/async/test_async_systemd.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import asyncio

import pytest

from e2b_code_interpreter.code_interpreter_async import AsyncSandbox


Expand All @@ -17,6 +19,7 @@ async def wait_for_health(sandbox: AsyncSandbox, max_retries=10, interval_ms=100
return False


@pytest.mark.skip_debug
async def test_restart_after_jupyter_kill(async_sandbox: AsyncSandbox):
# Verify health is up initially
assert await wait_for_health(async_sandbox)
Expand All @@ -39,6 +42,7 @@ async def test_restart_after_jupyter_kill(async_sandbox: AsyncSandbox):
assert result.text == "1"


@pytest.mark.skip_debug
async def test_restart_after_code_interpreter_kill(async_sandbox: AsyncSandbox):
# Verify health is up initially
assert await wait_for_health(async_sandbox)
Expand Down
3 changes: 3 additions & 0 deletions python/tests/sync/test_reconnect.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import pytest

from e2b_code_interpreter.code_interpreter_sync import Sandbox


@pytest.mark.skip_debug
def test_reconnect(sandbox: Sandbox):
sandbox_id = sandbox.sandbox_id

Expand Down
4 changes: 4 additions & 0 deletions python/tests/sync/test_systemd.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import time

import pytest

from e2b_code_interpreter.code_interpreter_sync import Sandbox


Expand All @@ -17,6 +19,7 @@ def wait_for_health(sandbox: Sandbox, max_retries=10, interval_ms=100):
return False


@pytest.mark.skip_debug
def test_restart_after_jupyter_kill(sandbox: Sandbox):
# Verify health is up initially
assert wait_for_health(sandbox)
Expand All @@ -37,6 +40,7 @@ def test_restart_after_jupyter_kill(sandbox: Sandbox):
assert result.text == "1"


@pytest.mark.skip_debug
def test_restart_after_code_interpreter_kill(sandbox: Sandbox):
# Verify health is up initially
assert wait_for_health(sandbox)
Expand Down
2 changes: 1 addition & 1 deletion template/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def make_template(
template = template.set_user("user").set_workdir("/home/user")

if is_docker:
start_cmd = "sudo /root/.jupyter/start-up.sh"
start_cmd = "sudo --preserve-env=E2B_LOCAL /root/.jupyter/start-up.sh"
else:
start_cmd = "sudo systemctl start jupyter"

Expand Down
Loading