/**
* Unit tests for Sandbox Factory
*
* Tests the factory functions for creating sandbox instances
* with configurable isolation modes.
*/
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import {
setDefaultSandboxMode,
getDefaultSandboxMode,
getAvailableSandboxModes,
createSandbox,
createSandboxPool,
getSandboxModeInfo,
type SandboxMode,
} from "../sandbox-factory.js";
import { CodeModeSandbox, SandboxPool } from "../sandbox.js";
import { WorkerSandbox, WorkerSandboxPool } from "../worker-sandbox.js";
// Mock the logger
vi.mock("../../utils/logger.js", () => ({
logger: {
debug: vi.fn(),
info: vi.fn(),
warn: vi.fn(),
error: vi.fn(),
},
}));
describe("Sandbox Factory", () => {
// Store original default mode to restore after tests
let originalMode: SandboxMode;
beforeEach(() => {
originalMode = getDefaultSandboxMode();
});
afterEach(() => {
// Restore original mode
setDefaultSandboxMode(originalMode);
});
describe("setDefaultSandboxMode / getDefaultSandboxMode", () => {
it("should default to vm mode", () => {
setDefaultSandboxMode("vm");
expect(getDefaultSandboxMode()).toBe("vm");
});
it("should switch to worker mode", () => {
setDefaultSandboxMode("worker");
expect(getDefaultSandboxMode()).toBe("worker");
});
it("should switch back to vm mode", () => {
setDefaultSandboxMode("worker");
setDefaultSandboxMode("vm");
expect(getDefaultSandboxMode()).toBe("vm");
});
});
describe("getAvailableSandboxModes", () => {
it("should return array with vm and worker modes", () => {
const modes = getAvailableSandboxModes();
expect(modes).toContain("vm");
expect(modes).toContain("worker");
});
it("should return exactly two modes", () => {
const modes = getAvailableSandboxModes();
expect(modes.length).toBe(2);
});
});
describe("createSandbox", () => {
it("should create CodeModeSandbox when mode is vm", () => {
const sandbox = createSandbox("vm");
expect(sandbox).toBeInstanceOf(CodeModeSandbox);
});
it("should create WorkerSandbox when mode is worker", () => {
const sandbox = createSandbox("worker");
expect(sandbox).toBeInstanceOf(WorkerSandbox);
});
it("should use default mode when not specified", () => {
setDefaultSandboxMode("vm");
const sandbox = createSandbox();
expect(sandbox).toBeInstanceOf(CodeModeSandbox);
});
it("should use worker as default when set", () => {
setDefaultSandboxMode("worker");
const sandbox = createSandbox();
expect(sandbox).toBeInstanceOf(WorkerSandbox);
});
it("should pass options to vm sandbox", () => {
const sandbox = createSandbox("vm", { timeoutMs: 5000 });
expect(sandbox).toBeInstanceOf(CodeModeSandbox);
// Sandbox should be functional
expect(sandbox.isHealthy()).toBe(true);
});
it("should pass options to worker sandbox", () => {
const sandbox = createSandbox("worker", { timeoutMs: 5000 });
expect(sandbox).toBeInstanceOf(WorkerSandbox);
expect(sandbox.isHealthy()).toBe(true);
});
});
describe("createSandboxPool", () => {
it("should create SandboxPool when mode is vm", () => {
const pool = createSandboxPool("vm");
expect(pool).toBeInstanceOf(SandboxPool);
pool.dispose();
});
it("should create WorkerSandboxPool when mode is worker", () => {
const pool = createSandboxPool("worker");
expect(pool).toBeInstanceOf(WorkerSandboxPool);
pool.dispose();
});
it("should use default mode when not specified", () => {
setDefaultSandboxMode("vm");
const pool = createSandboxPool();
expect(pool).toBeInstanceOf(SandboxPool);
pool.dispose();
});
it("should pass pool options to vm pool", () => {
const pool = createSandboxPool("vm", { maxInstances: 5 });
expect(pool).toBeInstanceOf(SandboxPool);
pool.initialize();
const stats = pool.getStats();
expect(stats.max).toBe(5);
pool.dispose();
});
it("should pass pool options to worker pool", () => {
const pool = createSandboxPool("worker", { maxInstances: 3 });
expect(pool).toBeInstanceOf(WorkerSandboxPool);
pool.initialize();
const stats = pool.getStats();
expect(stats.max).toBe(3);
pool.dispose();
});
it("should pass sandbox options to pool", () => {
const pool = createSandboxPool("vm", undefined, { timeoutMs: 10000 });
expect(pool).toBeInstanceOf(SandboxPool);
pool.dispose();
});
});
describe("getSandboxModeInfo", () => {
describe("vm mode info", () => {
it("should return correct name for vm mode", () => {
const info = getSandboxModeInfo("vm");
expect(info.name).toBe("VM Context");
});
it("should describe vm isolation", () => {
const info = getSandboxModeInfo("vm");
expect(info.isolation).toContain("Script isolation");
});
it("should describe vm performance", () => {
const info = getSandboxModeInfo("vm");
expect(info.performance).toContain("Low overhead");
});
it("should describe vm security", () => {
const info = getSandboxModeInfo("vm");
expect(info.security).toContain("Standard");
});
it("should describe vm requirements", () => {
const info = getSandboxModeInfo("vm");
expect(info.requirements).toContain("vm module");
});
});
describe("worker mode info", () => {
it("should return correct name for worker mode", () => {
const info = getSandboxModeInfo("worker");
expect(info.name).toBe("Worker Thread");
});
it("should describe worker isolation", () => {
const info = getSandboxModeInfo("worker");
expect(info.isolation).toContain("Separate V8 instance");
});
it("should describe worker performance", () => {
const info = getSandboxModeInfo("worker");
expect(info.performance).toContain("Higher overhead");
});
it("should describe worker security", () => {
const info = getSandboxModeInfo("worker");
expect(info.security).toContain("Enhanced");
});
it("should describe worker requirements", () => {
const info = getSandboxModeInfo("worker");
expect(info.requirements).toContain("worker_threads");
});
});
});
});