import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; import { tap, expect } from '@git.zone/tstest/tapbundle'; import { BaseImageManager, SmartVM } from '../ts/index.js'; import type { TBaseImagePreset, TFirecrackerArch } from '../ts/index.js'; const integrationEnabled = ['1', 'true', 'yes'].includes( (process.env.SMARTVM_RUN_INTEGRATION || '').toLowerCase(), ); function getHostArch(): TFirecrackerArch { return process.arch === 'arm64' ? 'aarch64' : 'x86_64'; } async function assertHostReady(): Promise { if (process.platform !== 'linux') { throw new Error('Firecracker integration tests require Linux'); } await fs.promises.access('/dev/kvm', fs.constants.R_OK | fs.constants.W_OK); } tap.test('SmartVM integration - boots a Firecracker CI base image when explicitly enabled', async () => { if (!integrationEnabled) { console.log('Skipping SmartVM integration test. Set SMARTVM_RUN_INTEGRATION=true to enable it.'); return; } await assertHostReady(); const arch = (process.env.SMARTVM_ARCH as TFirecrackerArch | undefined) || getHostArch(); const preset = (process.env.SMARTVM_BASE_IMAGE_PRESET as TBaseImagePreset | undefined) || 'latest'; const maxStoredBaseImages = process.env.SMARTVM_MAX_STORED_BASE_IMAGES ? Number(process.env.SMARTVM_MAX_STORED_BASE_IMAGES) : undefined; const baseImageManager = new BaseImageManager({ arch, cacheDir: process.env.SMARTVM_BASE_IMAGE_CACHE_DIR, maxStoredBaseImages, hostedManifestUrl: process.env.SMARTVM_BASE_IMAGE_MANIFEST_URL, hostedManifestPath: process.env.SMARTVM_BASE_IMAGE_MANIFEST_PATH, }); const baseImage = await baseImageManager.ensureBaseImage({ preset, manifestUrl: process.env.SMARTVM_BASE_IMAGE_MANIFEST_URL, manifestPath: process.env.SMARTVM_BASE_IMAGE_MANIFEST_PATH, }); const smartvm = new SmartVM({ arch, dataDir: process.env.SMARTVM_INTEGRATION_DATA_DIR || path.join(os.tmpdir(), '.smartvm-integration'), firecrackerVersion: process.env.SMARTVM_FIRECRACKER_VERSION || baseImage.firecrackerVersion, baseImageCacheDir: process.env.SMARTVM_BASE_IMAGE_CACHE_DIR, maxStoredBaseImages, baseImageManifestUrl: process.env.SMARTVM_BASE_IMAGE_MANIFEST_URL, baseImageManifestPath: process.env.SMARTVM_BASE_IMAGE_MANIFEST_PATH, }); const vm = await smartvm.createVM({ id: `smartvm-it-${Date.now()}`, bootSource: { kernelImagePath: baseImage.kernelImagePath, bootArgs: baseImage.bootArgs, }, machineConfig: { vcpuCount: 1, memSizeMib: 256, }, drives: [ { driveId: 'rootfs', pathOnHost: baseImage.rootfsPath, isRootDevice: true, isReadOnly: baseImage.rootfsIsReadOnly, }, ], }); try { await vm.start(); expect(vm.state).toEqual('running'); expect(await vm.getInfo()).toBeTruthy(); } finally { if (vm.state === 'running' || vm.state === 'paused') { await vm.stop(); } await vm.cleanup(); await smartvm.cleanup(); } }); export default tap.start();