#![allow(clippy::unwrap_used, clippy::expect_used)]
#![cfg(feature = "preinit")]
use eryx::Sandbox;
use eryx::preinit::pre_initialize;
use std::path::PathBuf;
use std::sync::Arc;
fn get_stdlib_path() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.parent()
.unwrap()
.join("eryx-wasm-runtime/tests/python-stdlib")
}
#[tokio::test]
async fn preinit_basic() {
let stdlib = get_stdlib_path();
let preinit_bytes = pre_initialize(&stdlib, None, &[], &[])
.await
.expect("pre-initialization should succeed");
assert!(!preinit_bytes.is_empty());
assert_eq!(&preinit_bytes[0..4], b"\0asm");
}
#[tokio::test]
async fn preinit_can_execute() {
let stdlib = get_stdlib_path();
let preinit_bytes = pre_initialize(&stdlib, None, &[], &[])
.await
.expect("pre-initialization should succeed");
let sandbox = Sandbox::builder()
.with_wasm_bytes(preinit_bytes)
.with_python_stdlib(&stdlib)
.build()
.expect("sandbox creation should succeed");
let result = sandbox
.execute("print('hello from preinit')")
.await
.expect("execution should succeed");
assert!(result.stdout.contains("hello from preinit"));
}
#[tokio::test]
async fn preinit_arbitrary_imports_work() {
let stdlib = get_stdlib_path();
let preinit_bytes = pre_initialize(&stdlib, None, &[], &[])
.await
.expect("pre-initialization should succeed");
let sandbox = Sandbox::builder()
.with_wasm_bytes(preinit_bytes)
.with_python_stdlib(&stdlib)
.build()
.expect("sandbox creation should succeed");
let result = sandbox
.execute(
r#"
import json
import base64
import hashlib
import re
import collections
# Verify they all work
print(f"json: {json.dumps({'a': 1})}")
print(f"base64: {base64.b64encode(b'test').decode()}")
print(f"hashlib: {hashlib.md5(b'test').hexdigest()[:8]}")
print(f"re: {re.match(r'\d+', '123').group()}")
print(f"collections: {type(collections.OrderedDict()).__name__}")
"#,
)
.await
.expect("imports should work");
assert!(result.stdout.contains(r#"json: {"a": 1}"#));
assert!(result.stdout.contains("base64: dGVzdA==")); assert!(result.stdout.contains("hashlib: 098f6bcd")); assert!(result.stdout.contains("re: 123"));
assert!(result.stdout.contains("collections: OrderedDict"));
}
#[tokio::test]
async fn preinit_multiple_sandboxes() {
let stdlib = get_stdlib_path();
let preinit_bytes = Arc::new(
pre_initialize(&stdlib, None, &[], &[])
.await
.expect("pre-initialization should succeed"),
);
for i in 0..3 {
let sandbox = Sandbox::builder()
.with_wasm_bytes((*preinit_bytes).clone())
.with_python_stdlib(&stdlib)
.build()
.expect("sandbox creation should succeed");
let result = sandbox
.execute(&format!("print('sandbox {i}')"))
.await
.expect("execution should succeed");
assert!(result.stdout.contains(&format!("sandbox {i}")));
}
}
#[tokio::test]
async fn preinit_sandboxes_isolated() {
let stdlib = get_stdlib_path();
let preinit_bytes = pre_initialize(&stdlib, None, &[], &[])
.await
.expect("pre-initialization should succeed");
let sandbox1 = Sandbox::builder()
.with_wasm_bytes(preinit_bytes.clone())
.with_python_stdlib(&stdlib)
.build()
.unwrap();
sandbox1
.execute("secret_value = 'sandbox1_secret'")
.await
.unwrap();
let sandbox2 = Sandbox::builder()
.with_wasm_bytes(preinit_bytes)
.with_python_stdlib(&stdlib)
.build()
.unwrap();
let result = sandbox2
.execute(
r#"
try:
print(f"found: {secret_value}")
except NameError:
print("variable not found - correctly isolated")
"#,
)
.await
.unwrap();
assert!(result.stdout.contains("correctly isolated"));
}
#[tokio::test]
async fn preinit_with_imports() {
let stdlib = get_stdlib_path();
let preinit_bytes = pre_initialize(&stdlib, None, &["json"], &[])
.await
.expect("pre-initialization should succeed");
let sandbox = Sandbox::builder()
.with_wasm_bytes(preinit_bytes)
.with_python_stdlib(&stdlib)
.build()
.expect("sandbox creation should succeed");
let result = sandbox
.execute(
r#"
import sys
if 'json' in sys.modules:
print("json was pre-imported")
else:
print("json not in sys.modules")
# Should still work
import json
print(json.dumps([1, 2, 3]))
"#,
)
.await
.expect("execution should succeed");
assert!(result.stdout.contains("json was pre-imported"));
assert!(result.stdout.contains("[1, 2, 3]"));
}
#[tokio::test]
async fn preinit_imports_work_within_execution() {
let stdlib = get_stdlib_path();
let preinit_bytes = pre_initialize(&stdlib, None, &[], &[])
.await
.expect("pre-initialization should succeed");
let sandbox = Sandbox::builder()
.with_wasm_bytes(preinit_bytes)
.with_python_stdlib(&stdlib)
.build()
.unwrap();
let result = sandbox
.execute(
r#"
import json
import hashlib
print(json.dumps({'works': True}))
print(hashlib.md5(b'test').hexdigest()[:8])
"#,
)
.await
.unwrap();
assert!(result.stdout.contains(r#"{"works": true}"#));
assert!(result.stdout.contains("098f6bcd"));
}
#[tokio::test]
async fn preinit_file_operations_work() {
let stdlib = get_stdlib_path();
let preinit_bytes = pre_initialize(&stdlib, None, &[], &[])
.await
.expect("pre-initialization should succeed");
let sandbox = Sandbox::builder()
.with_wasm_bytes(preinit_bytes)
.with_python_stdlib(&stdlib)
.build()
.unwrap();
let result = sandbox
.execute(
r#"
import os
# List contents of stdlib (should have some .py files)
files = os.listdir('/python-stdlib')
py_files = [f for f in files if f.endswith('.py') or not '.' in f]
print(f"found {len(py_files)} items")
print(f"has_encodings: {'encodings' in files}")
"#,
)
.await
.unwrap();
assert!(result.stdout.contains("has_encodings: True"));
}