Files
smartvm/test/test.integration.node.ts
T

92 lines
3.0 KiB
TypeScript

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<void> {
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();