mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-20 04:56:32 +00:00
Refactor CI and OSDK tests, add OSDK publish workflow
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
eb42383532
commit
6694f08eac
@ -1,4 +1,4 @@
|
|||||||
name: Integration test
|
name: Asterinas CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
@ -7,7 +7,43 @@ on:
|
|||||||
- main
|
- main
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
aster-lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 10
|
||||||
|
container: asterinas/asterinas:0.3.0
|
||||||
|
steps:
|
||||||
|
- run: echo "Running in asterinas/asterinas:0.3.0"
|
||||||
|
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- run: make install_osdk
|
||||||
|
|
||||||
|
- name: Check
|
||||||
|
id: check
|
||||||
|
run: make check
|
||||||
|
|
||||||
|
aster-unit-test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 15
|
||||||
|
container: asterinas/asterinas:0.3.0
|
||||||
|
steps:
|
||||||
|
- run: echo "Running in asterinas/asterinas:0.3.0"
|
||||||
|
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- run: make install_osdk
|
||||||
|
|
||||||
|
- name: Usermode Unit test
|
||||||
|
id: usermode_unit_test
|
||||||
|
run: make test
|
||||||
|
|
||||||
|
- name: Ktest Unit Test
|
||||||
|
id: ktest_unit_test
|
||||||
|
run: make update_initramfs && make ktest
|
||||||
|
|
||||||
|
# TODO: add component check.
|
||||||
|
|
||||||
|
aster-integration-test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
container: asterinas/asterinas:0.3.1
|
container: asterinas/asterinas:0.3.1
|
||||||
@ -49,4 +85,3 @@ jobs:
|
|||||||
- name: Regression Test (MicroVM)
|
- name: Regression Test (MicroVM)
|
||||||
id: regression_test_linux
|
id: regression_test_linux
|
||||||
run: make run AUTO_TEST=regression ENABLE_KVM=0 QEMU_MACHINE=microvm RELEASE_MODE=1
|
run: make run AUTO_TEST=regression ENABLE_KVM=0 QEMU_MACHINE=microvm RELEASE_MODE=1
|
||||||
|
|
2
.github/workflows/docker_build.yml
vendored
2
.github/workflows/docker_build.yml
vendored
@ -6,7 +6,7 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- VERSION
|
- VERSION
|
||||||
branches:
|
branches:
|
||||||
- 'main'
|
- main
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker:
|
docker:
|
||||||
|
8
.github/workflows/osdk_ci.yml
vendored
8
.github/workflows/osdk_ci.yml
vendored
@ -2,6 +2,8 @@ name: OSDK CI
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- osdk/**
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
@ -16,9 +18,9 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Format check
|
- name: Lint
|
||||||
id: fmt_check
|
id: lint
|
||||||
run: cd osdk && cargo check && cargo clippy
|
run: cd osdk && cargo clippy -- -D warnings
|
||||||
|
|
||||||
- name: Unit test
|
- name: Unit test
|
||||||
id: unit_test
|
id: unit_test
|
||||||
|
23
.github/workflows/osdk_publish.yml
vendored
Normal file
23
.github/workflows/osdk_publish.yml
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
name: OSDK Publish
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- osdk/Cargo.toml
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
osdk-publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 10
|
||||||
|
container: asterinas/asterinas:0.3.0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: katyo/publish-crates@v2
|
||||||
|
with:
|
||||||
|
path: './osdk'
|
||||||
|
args: --no-verify
|
||||||
|
registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||||
|
ignore-unpublished-changes: true
|
@ -3,6 +3,8 @@
|
|||||||
A secure, fast, and general-purpose OS kernel written in Rust and compatible with Linux
|
A secure, fast, and general-purpose OS kernel written in Rust and compatible with Linux
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
[](https://github.com/asterinas/asterinas/actions/workflows/aster_ci.yml)
|
||||||
|
|
||||||
English | [中文版](README_CN.md)
|
English | [中文版](README_CN.md)
|
||||||
|
|
||||||
## Introducing Asterinas
|
## Introducing Asterinas
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
一个安全、快速、通用的操作系统内核,使用Rust编写,并与Linux兼容
|
一个安全、快速、通用的操作系统内核,使用Rust编写,并与Linux兼容
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
[](https://github.com/asterinas/asterinas/actions/workflows/aster_ci.yml)
|
||||||
|
|
||||||
[English](README.md) | 中文版
|
[English](README.md) | 中文版
|
||||||
|
|
||||||
## 初见星绽
|
## 初见星绽
|
||||||
|
3
osdk/.gitignore
vendored
3
osdk/.gitignore
vendored
@ -8,6 +8,3 @@ target/
|
|||||||
|
|
||||||
# MSVC Windows builds of rustc generate these, which store debugging information
|
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||||
*.pdb
|
*.pdb
|
||||||
|
|
||||||
# Integration test generated files
|
|
||||||
workspace_*
|
|
6
osdk/Cargo.lock
generated
6
osdk/Cargo.lock
generated
@ -88,9 +88,9 @@ checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bstr"
|
name = "bstr"
|
||||||
version = "1.9.0"
|
version = "1.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc"
|
checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-automata",
|
"regex-automata",
|
||||||
@ -119,7 +119,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cargo-osdk"
|
name = "cargo-osdk"
|
||||||
version = "0.1.5"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
"clap",
|
"clap",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cargo-osdk"
|
name = "cargo-osdk"
|
||||||
version = "0.1.5"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Accelerate OS development with Asterinas OSDK"
|
description = "Accelerate OS development with Asterinas OSDK"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# Accelerate OS development with Asterinas OSDK
|
# Accelerate OS development with Asterinas OSDK
|
||||||
|
|
||||||
[](https://crates.io/crates/cargo-osdk)
|
[](https://crates.io/crates/cargo-osdk)
|
||||||
|
[](https://github.com/asterinas/asterinas/actions/workflows/osdk_ci.yml)
|
||||||
|
|
||||||
### What is it?
|
### What is it?
|
||||||
|
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly-2023-12-01"
|
channel = "stable"
|
||||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
|
4
osdk/src/base_crate/Cargo.toml.template
Normal file
4
osdk/src/base_crate/Cargo.toml.template
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[package]
|
||||||
|
name = "#NAME#"
|
||||||
|
version = "#VERSION#"
|
||||||
|
edition = "2021"
|
@ -4,9 +4,7 @@
|
|||||||
//! It will depend on the kernel crate.
|
//! It will depend on the kernel crate.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use std::{fs, path::Path, process, process::Command, str::FromStr};
|
use std::{fs, path::Path, str::FromStr};
|
||||||
|
|
||||||
use crate::{error::Errno, error_msg};
|
|
||||||
|
|
||||||
pub fn new_base_crate(
|
pub fn new_base_crate(
|
||||||
base_crate_path: impl AsRef<Path>,
|
base_crate_path: impl AsRef<Path>,
|
||||||
@ -17,17 +15,32 @@ pub fn new_base_crate(
|
|||||||
std::fs::remove_dir_all(&base_crate_path).unwrap();
|
std::fs::remove_dir_all(&base_crate_path).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cmd = Command::new("cargo");
|
let dep_crate_version = {
|
||||||
cmd.arg("new").arg("--bin").arg(base_crate_path.as_ref());
|
let cargo_toml = dep_crate_path.as_ref().join("Cargo.toml");
|
||||||
cmd.arg("--vcs").arg("none");
|
let cargo_toml = fs::read_to_string(cargo_toml).unwrap();
|
||||||
|
let cargo_toml: toml::Value = toml::from_str(&cargo_toml).unwrap();
|
||||||
|
let dep_version = cargo_toml
|
||||||
|
.get("package")
|
||||||
|
.unwrap()
|
||||||
|
.as_table()
|
||||||
|
.unwrap()
|
||||||
|
.get("version")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap();
|
||||||
|
dep_version.to_string()
|
||||||
|
};
|
||||||
|
|
||||||
if !cmd.status().unwrap().success() {
|
// Create the directory
|
||||||
error_msg!(
|
fs::create_dir_all(&base_crate_path).unwrap();
|
||||||
"Failed to create base crate at: {:#?}",
|
// Create the src directory
|
||||||
base_crate_path.as_ref()
|
fs::create_dir_all(base_crate_path.as_ref().join("src")).unwrap();
|
||||||
);
|
|
||||||
process::exit(Errno::CreateBaseCrate as _);
|
// Write Cargo.toml
|
||||||
}
|
let cargo_toml = include_str!("Cargo.toml.template");
|
||||||
|
let cargo_toml = cargo_toml.replace("#NAME#", &(dep_crate_name.to_string() + "-osdk-bin"));
|
||||||
|
let cargo_toml = cargo_toml.replace("#VERSION#", &dep_crate_version);
|
||||||
|
fs::write(base_crate_path.as_ref().join("Cargo.toml"), cargo_toml).unwrap();
|
||||||
|
|
||||||
// Set the current directory to the target osdk directory
|
// Set the current directory to the target osdk directory
|
||||||
let original_dir = std::env::current_dir().unwrap();
|
let original_dir = std::env::current_dir().unwrap();
|
||||||
@ -44,7 +57,7 @@ pub fn new_base_crate(
|
|||||||
// Overrite the main.rs file
|
// Overrite the main.rs file
|
||||||
let main_rs = include_str!("main.rs.template");
|
let main_rs = include_str!("main.rs.template");
|
||||||
// Replace all occurence of `#TARGET_NAME#` with the `dep_crate_name`
|
// Replace all occurence of `#TARGET_NAME#` with the `dep_crate_name`
|
||||||
let main_rs = main_rs.replace("#TARGET_NAME#", &dep_crate_name.replace("-", "_"));
|
let main_rs = main_rs.replace("#TARGET_NAME#", &dep_crate_name.replace('-', "_"));
|
||||||
fs::write("src/main.rs", main_rs).unwrap();
|
fs::write("src/main.rs", main_rs).unwrap();
|
||||||
|
|
||||||
// Add dependencies to the Cargo.toml
|
// Add dependencies to the Cargo.toml
|
||||||
@ -54,7 +67,7 @@ pub fn new_base_crate(
|
|||||||
copy_manifest_configurations(base_crate_path);
|
copy_manifest_configurations(base_crate_path);
|
||||||
|
|
||||||
// Get back to the original directory
|
// Get back to the original directory
|
||||||
std::env::set_current_dir(&original_dir).unwrap();
|
std::env::set_current_dir(original_dir).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_manifest_dependency(crate_name: &str, crate_path: impl AsRef<Path>) {
|
fn add_manifest_dependency(crate_name: &str, crate_path: impl AsRef<Path>) {
|
||||||
@ -65,6 +78,14 @@ fn add_manifest_dependency(crate_name: &str, crate_path: impl AsRef<Path>) {
|
|||||||
toml::from_str(&content).unwrap()
|
toml::from_str(&content).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check if "dependencies" key exists, create it if it doesn't
|
||||||
|
if !manifest.contains_key("dependencies") {
|
||||||
|
manifest.insert(
|
||||||
|
"dependencies".to_string(),
|
||||||
|
toml::Value::Table(toml::Table::new()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let dependencies = manifest.get_mut("dependencies").unwrap();
|
let dependencies = manifest.get_mut("dependencies").unwrap();
|
||||||
|
|
||||||
let dep = toml::Table::from_str(&format!(
|
let dep = toml::Table::from_str(&format!(
|
||||||
|
@ -44,7 +44,7 @@ impl Bundle {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn load(path: impl AsRef<Path>) -> Self {
|
pub fn load(path: impl AsRef<Path>) -> Self {
|
||||||
let manifest_file_path = path.as_ref().join("bundle.toml");
|
let manifest_file_path = path.as_ref().join("bundle.toml");
|
||||||
let manifest_file_content = std::fs::read_to_string(&manifest_file_path).unwrap();
|
let manifest_file_content = std::fs::read_to_string(manifest_file_path).unwrap();
|
||||||
let manifest: BundleManifest = toml::from_str(&manifest_file_content).unwrap();
|
let manifest: BundleManifest = toml::from_str(&manifest_file_content).unwrap();
|
||||||
// TODO: check integrity of the loaded bundle.
|
// TODO: check integrity of the loaded bundle.
|
||||||
Self {
|
Self {
|
||||||
@ -142,7 +142,7 @@ impl Bundle {
|
|||||||
}
|
}
|
||||||
let file_name = vm_image.path.file_name().unwrap();
|
let file_name = vm_image.path.file_name().unwrap();
|
||||||
let copied_path = self.path.join(file_name);
|
let copied_path = self.path.join(file_name);
|
||||||
std::fs::copy(&vm_image.path, &copied_path).unwrap();
|
std::fs::copy(&vm_image.path, copied_path).unwrap();
|
||||||
self.manifest.vm_image = Some(AsterVmImage {
|
self.manifest.vm_image = Some(AsterVmImage {
|
||||||
path: file_name.into(),
|
path: file_name.into(),
|
||||||
typ: vm_image.typ.clone(),
|
typ: vm_image.typ.clone(),
|
||||||
@ -158,13 +158,13 @@ impl Bundle {
|
|||||||
}
|
}
|
||||||
let file_name = aster_bin.path.file_name().unwrap();
|
let file_name = aster_bin.path.file_name().unwrap();
|
||||||
let copied_path = self.path.join(file_name);
|
let copied_path = self.path.join(file_name);
|
||||||
std::fs::copy(&aster_bin.path, &copied_path).unwrap();
|
std::fs::copy(&aster_bin.path, copied_path).unwrap();
|
||||||
self.manifest.aster_bin = Some(AsterBin {
|
self.manifest.aster_bin = Some(AsterBin {
|
||||||
path: file_name.into(),
|
path: file_name.into(),
|
||||||
typ: aster_bin.typ.clone(),
|
typ: aster_bin.typ.clone(),
|
||||||
version: aster_bin.version.clone(),
|
version: aster_bin.version.clone(),
|
||||||
sha256sum: aster_bin.sha256sum.clone(),
|
sha256sum: aster_bin.sha256sum.clone(),
|
||||||
stripped: aster_bin.stripped.clone(),
|
stripped: aster_bin.stripped,
|
||||||
});
|
});
|
||||||
self.write_manifest_content();
|
self.write_manifest_content();
|
||||||
}
|
}
|
||||||
@ -172,7 +172,7 @@ impl Bundle {
|
|||||||
fn write_manifest_content(&self) {
|
fn write_manifest_content(&self) {
|
||||||
let manifest_file_content = toml::to_string(&self.manifest).unwrap();
|
let manifest_file_content = toml::to_string(&self.manifest).unwrap();
|
||||||
let manifest_file_path = self.path.join("bundle.toml");
|
let manifest_file_path = self.path.join("bundle.toml");
|
||||||
std::fs::write(&manifest_file_path, manifest_file_content).unwrap();
|
std::fs::write(manifest_file_path, manifest_file_content).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ pub struct TestArgs {
|
|||||||
pub struct CargoArgs {
|
pub struct CargoArgs {
|
||||||
#[arg(
|
#[arg(
|
||||||
long,
|
long,
|
||||||
help = "The Cargo build profile (built-in candidates are 'debug', 'release' and 'dev')",
|
help = "The Cargo build profile (built-in candidates are 'debug', 'release', 'dev' and 'bench')",
|
||||||
default_value = "dev"
|
default_value = "dev"
|
||||||
)]
|
)]
|
||||||
pub profile: String,
|
pub profile: String,
|
||||||
|
@ -49,7 +49,7 @@ pub fn make_install_bzimage(
|
|||||||
setup_install_dir.join("bin").join("linux-bzimage-setup")
|
setup_install_dir.join("bin").join("linux-bzimage-setup")
|
||||||
};
|
};
|
||||||
// Make the `bzImage`-compatible kernel image and place it in the boot directory.
|
// Make the `bzImage`-compatible kernel image and place it in the boot directory.
|
||||||
let install_path = install_dir.as_ref().join(&target_name);
|
let install_path = install_dir.as_ref().join(target_name);
|
||||||
info!("Building bzImage");
|
info!("Building bzImage");
|
||||||
println!("install_path: {:?}", install_path);
|
println!("install_path: {:?}", install_path);
|
||||||
make_bzimage(&install_path, image_type, &aster_elf.path, &setup_bin);
|
make_bzimage(&install_path, image_type, &aster_elf.path, &setup_bin);
|
||||||
|
@ -25,7 +25,7 @@ pub fn create_bootdev_image(
|
|||||||
|
|
||||||
// Clear or make the iso dir.
|
// Clear or make the iso dir.
|
||||||
if iso_root.exists() {
|
if iso_root.exists() {
|
||||||
fs::remove_dir_all(&iso_root).unwrap();
|
fs::remove_dir_all(iso_root).unwrap();
|
||||||
}
|
}
|
||||||
fs::create_dir_all(iso_root.join("boot").join("grub")).unwrap();
|
fs::create_dir_all(iso_root.join("boot").join("grub")).unwrap();
|
||||||
|
|
||||||
@ -41,12 +41,12 @@ pub fn create_bootdev_image(
|
|||||||
// Make the kernel image and place it in the boot directory.
|
// Make the kernel image and place it in the boot directory.
|
||||||
match protocol {
|
match protocol {
|
||||||
BootProtocol::LinuxLegacy32 | BootProtocol::LinuxEfiHandover64 => {
|
BootProtocol::LinuxLegacy32 | BootProtocol::LinuxEfiHandover64 => {
|
||||||
make_install_bzimage(&iso_root.join("boot"), &target_dir, aster_bin, protocol);
|
make_install_bzimage(iso_root.join("boot"), &target_dir, aster_bin, protocol);
|
||||||
}
|
}
|
||||||
BootProtocol::Multiboot | BootProtocol::Multiboot2 => {
|
BootProtocol::Multiboot | BootProtocol::Multiboot2 => {
|
||||||
// Copy the kernel image to the boot directory.
|
// Copy the kernel image to the boot directory.
|
||||||
let target_path = iso_root.join("boot").join(&target_name);
|
let target_path = iso_root.join("boot").join(&target_name);
|
||||||
fs::copy(&aster_bin.path, &target_path).unwrap();
|
fs::copy(&aster_bin.path, target_path).unwrap();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ pub fn create_bootdev_image(
|
|||||||
protocol,
|
protocol,
|
||||||
);
|
);
|
||||||
let grub_cfg_path = iso_root.join("boot").join("grub").join("grub.cfg");
|
let grub_cfg_path = iso_root.join("boot").join("grub").join("grub.cfg");
|
||||||
fs::write(&grub_cfg_path, grub_cfg).unwrap();
|
fs::write(grub_cfg_path, grub_cfg).unwrap();
|
||||||
|
|
||||||
// Make the boot device CDROM image using `grub-mkrescue`.
|
// Make the boot device CDROM image using `grub-mkrescue`.
|
||||||
let iso_path = &target_dir.as_ref().join(target_name.to_string() + ".iso");
|
let iso_path = &target_dir.as_ref().join(target_name.to_string() + ".iso");
|
||||||
@ -109,11 +109,11 @@ fn generate_grub_cfg(
|
|||||||
let grub_cfg = grub_cfg.replace("#KERNEL_COMMAND_LINE#", kcmdline);
|
let grub_cfg = grub_cfg.replace("#KERNEL_COMMAND_LINE#", kcmdline);
|
||||||
// Replace the grub commands according to the protocol selected.
|
// Replace the grub commands according to the protocol selected.
|
||||||
let aster_bin_path_on_device = PathBuf::from("/boot")
|
let aster_bin_path_on_device = PathBuf::from("/boot")
|
||||||
.join(&target_name)
|
.join(target_name)
|
||||||
.into_os_string()
|
.into_os_string()
|
||||||
.into_string()
|
.into_string()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let grub_cfg = match protocol {
|
match protocol {
|
||||||
BootProtocol::Multiboot => grub_cfg
|
BootProtocol::Multiboot => grub_cfg
|
||||||
.replace("#GRUB_CMD_KERNEL#", "multiboot")
|
.replace("#GRUB_CMD_KERNEL#", "multiboot")
|
||||||
.replace("#KERNEL#", &aster_bin_path_on_device)
|
.replace("#KERNEL#", &aster_bin_path_on_device)
|
||||||
@ -147,9 +147,7 @@ fn generate_grub_cfg(
|
|||||||
"".to_owned()
|
"".to_owned()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
};
|
}
|
||||||
|
|
||||||
grub_cfg
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_grub_mkrescue_version(grub_mkrescue: &PathBuf) -> String {
|
fn get_grub_mkrescue_version(grub_mkrescue: &PathBuf) -> String {
|
||||||
|
@ -29,9 +29,9 @@ pub fn execute_build_command(config: &BuildConfig) {
|
|||||||
std::fs::create_dir_all(&osdk_target_directory).unwrap();
|
std::fs::create_dir_all(&osdk_target_directory).unwrap();
|
||||||
}
|
}
|
||||||
let target_info = get_current_crate_info();
|
let target_info = get_current_crate_info();
|
||||||
let bundle_path = osdk_target_directory.join(&target_info.name);
|
let bundle_path = osdk_target_directory.join(target_info.name);
|
||||||
|
|
||||||
let _bundle = create_base_and_build(&bundle_path, &osdk_target_directory, &config);
|
let _bundle = create_base_and_build(bundle_path, &osdk_target_directory, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_base_and_build(
|
pub fn create_base_and_build(
|
||||||
@ -43,12 +43,12 @@ pub fn create_base_and_build(
|
|||||||
new_base_crate(
|
new_base_crate(
|
||||||
&base_crate_path,
|
&base_crate_path,
|
||||||
&get_current_crate_info().name,
|
&get_current_crate_info().name,
|
||||||
&get_current_crate_info().path,
|
get_current_crate_info().path,
|
||||||
);
|
);
|
||||||
let original_dir = std::env::current_dir().unwrap();
|
let original_dir = std::env::current_dir().unwrap();
|
||||||
std::env::set_current_dir(&base_crate_path).unwrap();
|
std::env::set_current_dir(&base_crate_path).unwrap();
|
||||||
let bundle = do_build(&bundle_path, &osdk_target_directory, &config);
|
let bundle = do_build(&bundle_path, &osdk_target_directory, config);
|
||||||
std::env::set_current_dir(&original_dir).unwrap();
|
std::env::set_current_dir(original_dir).unwrap();
|
||||||
bundle
|
bundle
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ pub fn do_build(
|
|||||||
&osdk_target_directory,
|
&osdk_target_directory,
|
||||||
&aster_elf,
|
&aster_elf,
|
||||||
config.manifest.initramfs.as_ref(),
|
config.manifest.initramfs.as_ref(),
|
||||||
&config,
|
config,
|
||||||
);
|
);
|
||||||
bundle.add_vm_image(&bootdev_image);
|
bundle.add_vm_image(&bootdev_image);
|
||||||
}
|
}
|
||||||
@ -105,6 +105,7 @@ fn build_kernel_elf(args: &CargoArgs) -> AsterBin {
|
|||||||
let target_json_path = PathBuf::from_str("x86_64-custom.json").unwrap();
|
let target_json_path = PathBuf::from_str("x86_64-custom.json").unwrap();
|
||||||
|
|
||||||
let mut command = cargo();
|
let mut command = cargo();
|
||||||
|
command.env_remove("RUSTUP_TOOLCHAIN");
|
||||||
command.arg("build").arg("--target").arg(&target_json_path);
|
command.arg("build").arg("--target").arg(&target_json_path);
|
||||||
command.args(COMMON_CARGO_ARGS);
|
command.args(COMMON_CARGO_ARGS);
|
||||||
command.arg("--profile=".to_string() + &args.profile);
|
command.arg("--profile=".to_string() + &args.profile);
|
||||||
@ -114,8 +115,8 @@ fn build_kernel_elf(args: &CargoArgs) -> AsterBin {
|
|||||||
process::exit(Errno::ExecuteCommand as _);
|
process::exit(Errno::ExecuteCommand as _);
|
||||||
}
|
}
|
||||||
|
|
||||||
let aster_bin_path = PathBuf::from(target_directory)
|
let aster_bin_path =
|
||||||
.join(target_json_path.file_stem().unwrap().to_str().unwrap());
|
target_directory.join(target_json_path.file_stem().unwrap().to_str().unwrap());
|
||||||
let aster_bin_path = if args.profile == "dev" {
|
let aster_bin_path = if args.profile == "dev" {
|
||||||
aster_bin_path.join("debug")
|
aster_bin_path.join("debug")
|
||||||
} else {
|
} else {
|
||||||
|
@ -77,7 +77,7 @@ fn create_osdk_manifest(cargo_metadata: &serde_json::Value) {
|
|||||||
// The apt OVMF repo installs to `/usr/share/OVMF`
|
// The apt OVMF repo installs to `/usr/share/OVMF`
|
||||||
fs::write(
|
fs::write(
|
||||||
osdk_manifest_path,
|
osdk_manifest_path,
|
||||||
r#"
|
r#"\
|
||||||
[boot]
|
[boot]
|
||||||
ovmf = "/usr/share/OVMF"
|
ovmf = "/usr/share/OVMF"
|
||||||
[qemu]
|
[qemu]
|
||||||
|
@ -18,10 +18,10 @@ pub fn execute_run_command(config: &RunConfig) {
|
|||||||
|
|
||||||
// TODO: Check if the bundle is already built and compatible with the run configuration.
|
// TODO: Check if the bundle is already built and compatible with the run configuration.
|
||||||
let bundle = create_base_and_build(
|
let bundle = create_base_and_build(
|
||||||
&default_bundle_directory,
|
default_bundle_directory,
|
||||||
&osdk_target_directory,
|
&osdk_target_directory,
|
||||||
&required_build_config,
|
&required_build_config,
|
||||||
);
|
);
|
||||||
|
|
||||||
bundle.run(&config);
|
bundle.run(config);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ pub fn execute_test_command(config: &TestConfig) {
|
|||||||
|
|
||||||
let ktest_test_whitelist = match &config.test_name {
|
let ktest_test_whitelist = match &config.test_name {
|
||||||
Some(name) => format!(r#"Some(&["{}"])"#, name),
|
Some(name) => format!(r#"Some(&["{}"])"#, name),
|
||||||
None => format!(r#"None"#),
|
None => r#"None"#.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut ktest_crate_whitelist = vec![current_crate.name];
|
let mut ktest_crate_whitelist = vec![current_crate.name];
|
||||||
@ -54,12 +54,12 @@ pub static KTEST_CRATE_WHITELIST: Option<&[&str]> = Some(&{:#?});
|
|||||||
// Add `--cfg ktest` to RUSTFLAGS
|
// Add `--cfg ktest` to RUSTFLAGS
|
||||||
std::env::set_var("RUSTFLAGS", "--cfg ktest");
|
std::env::set_var("RUSTFLAGS", "--cfg ktest");
|
||||||
let bundle = do_build(
|
let bundle = do_build(
|
||||||
&default_bundle_directory,
|
default_bundle_directory,
|
||||||
&osdk_target_directory,
|
&osdk_target_directory,
|
||||||
&required_build_config,
|
&required_build_config,
|
||||||
);
|
);
|
||||||
std::env::remove_var("RUSTFLAGS");
|
std::env::remove_var("RUSTFLAGS");
|
||||||
std::env::set_current_dir(&original_dir).unwrap();
|
std::env::set_current_dir(original_dir).unwrap();
|
||||||
|
|
||||||
let required_run_config = RunConfig {
|
let required_run_config = RunConfig {
|
||||||
manifest: required_build_config.manifest.clone(),
|
manifest: required_build_config.manifest.clone(),
|
||||||
|
@ -158,3 +158,16 @@ fn check_cfg(cfg: &str) {
|
|||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
pub static ref SELECT_REGEX: Regex = Regex::new(r#"cfg\(select="(?P<select>\w+)"\)"#).unwrap();
|
pub static ref SELECT_REGEX: Regex = Regex::new(r#"cfg\(select="(?P<select>\w+)"\)"#).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extract_selection() {
|
||||||
|
let text = "cfg(select=\"abc123_\")";
|
||||||
|
let captures = SELECT_REGEX.captures(text).unwrap();
|
||||||
|
let selection = captures.name("select").unwrap().as_str();
|
||||||
|
assert_eq!(selection, "abc123_");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -9,6 +9,9 @@ pub mod boot;
|
|||||||
pub mod manifest;
|
pub mod manifest;
|
||||||
pub mod qemu;
|
pub mod qemu;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test;
|
||||||
|
|
||||||
use std::{fs, path::PathBuf, process};
|
use std::{fs, path::PathBuf, process};
|
||||||
|
|
||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::{IndexMap, IndexSet};
|
||||||
@ -336,39 +339,3 @@ fn split_kcmd_args(kcmd_args: &mut Vec<String>) -> Vec<String> {
|
|||||||
init_args.remove(0);
|
init_args.remove(0);
|
||||||
init_args
|
init_args
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn split_kcmd_args_test() {
|
|
||||||
let mut kcmd_args = ["init=/bin/sh", "--", "sh", "-l"]
|
|
||||||
.iter()
|
|
||||||
.map(ToString::to_string)
|
|
||||||
.collect();
|
|
||||||
let init_args = split_kcmd_args(&mut kcmd_args);
|
|
||||||
let expected_kcmd_args: Vec<_> = ["init=/bin/sh"].iter().map(ToString::to_string).collect();
|
|
||||||
assert_eq!(kcmd_args, expected_kcmd_args);
|
|
||||||
let expecetd_init_args: Vec<_> = ["sh", "-l"].iter().map(ToString::to_string).collect();
|
|
||||||
assert_eq!(init_args, expecetd_init_args);
|
|
||||||
|
|
||||||
let mut kcmd_args = ["init=/bin/sh", "--"]
|
|
||||||
.iter()
|
|
||||||
.map(ToString::to_string)
|
|
||||||
.collect();
|
|
||||||
let init_args = split_kcmd_args(&mut kcmd_args);
|
|
||||||
let expected_kcmd_args: Vec<_> = ["init=/bin/sh"].iter().map(ToString::to_string).collect();
|
|
||||||
assert_eq!(kcmd_args, expected_kcmd_args);
|
|
||||||
let expecetd_init_args: Vec<String> = Vec::new();
|
|
||||||
assert_eq!(init_args, expecetd_init_args);
|
|
||||||
|
|
||||||
let mut kcmd_args = ["init=/bin/sh", "shell=/bin/sh"]
|
|
||||||
.iter()
|
|
||||||
.map(ToString::to_string)
|
|
||||||
.collect();
|
|
||||||
let init_args = split_kcmd_args(&mut kcmd_args);
|
|
||||||
let expected_kcmd_args: Vec<_> = ["init=/bin/sh", "shell=/bin/sh"]
|
|
||||||
.iter()
|
|
||||||
.map(ToString::to_string)
|
|
||||||
.collect();
|
|
||||||
assert_eq!(kcmd_args, expected_kcmd_args);
|
|
||||||
let expecetd_init_args: Vec<String> = Vec::new();
|
|
||||||
assert_eq!(init_args, expecetd_init_args);
|
|
||||||
}
|
|
||||||
|
152
osdk/src/config_manager/test/mod.rs
Normal file
152
osdk/src/config_manager/test/mod.rs
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn split_kcmd_args_test() {
|
||||||
|
let mut kcmd_args = ["init=/bin/sh", "--", "sh", "-l"]
|
||||||
|
.iter()
|
||||||
|
.map(ToString::to_string)
|
||||||
|
.collect();
|
||||||
|
let init_args = split_kcmd_args(&mut kcmd_args);
|
||||||
|
let expected_kcmd_args: Vec<_> = ["init=/bin/sh"].iter().map(ToString::to_string).collect();
|
||||||
|
assert_eq!(kcmd_args, expected_kcmd_args);
|
||||||
|
let expecetd_init_args: Vec<_> = ["sh", "-l"].iter().map(ToString::to_string).collect();
|
||||||
|
assert_eq!(init_args, expecetd_init_args);
|
||||||
|
|
||||||
|
let mut kcmd_args = ["init=/bin/sh", "--"]
|
||||||
|
.iter()
|
||||||
|
.map(ToString::to_string)
|
||||||
|
.collect();
|
||||||
|
let init_args = split_kcmd_args(&mut kcmd_args);
|
||||||
|
let expected_kcmd_args: Vec<_> = ["init=/bin/sh"].iter().map(ToString::to_string).collect();
|
||||||
|
assert_eq!(kcmd_args, expected_kcmd_args);
|
||||||
|
let expecetd_init_args: Vec<String> = Vec::new();
|
||||||
|
assert_eq!(init_args, expecetd_init_args);
|
||||||
|
|
||||||
|
let mut kcmd_args = ["init=/bin/sh", "shell=/bin/sh"]
|
||||||
|
.iter()
|
||||||
|
.map(ToString::to_string)
|
||||||
|
.collect();
|
||||||
|
let init_args = split_kcmd_args(&mut kcmd_args);
|
||||||
|
let expected_kcmd_args: Vec<_> = ["init=/bin/sh", "shell=/bin/sh"]
|
||||||
|
.iter()
|
||||||
|
.map(ToString::to_string)
|
||||||
|
.collect();
|
||||||
|
assert_eq!(kcmd_args, expected_kcmd_args);
|
||||||
|
let expecetd_init_args: Vec<String> = Vec::new();
|
||||||
|
assert_eq!(init_args, expecetd_init_args);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_key_test() {
|
||||||
|
let string1 = "init=/bin/init";
|
||||||
|
let key = get_key(string1, "=").unwrap();
|
||||||
|
assert_eq!(key.as_str(), "init");
|
||||||
|
|
||||||
|
let string2 = "-m 2G";
|
||||||
|
let key = get_key(string2, " ").unwrap();
|
||||||
|
assert_eq!(key.as_str(), "-m");
|
||||||
|
|
||||||
|
let string3 = "-device virtio-keyboard-pci,disable-legacy=on,disable-modern=off";
|
||||||
|
let key = get_key(string3, " ").unwrap();
|
||||||
|
assert_eq!(key.as_str(), "-device");
|
||||||
|
|
||||||
|
let string4 = "-device";
|
||||||
|
assert!(get_key(string4, " ").is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn apply_kv_array_test() {
|
||||||
|
let qemu_args = &[
|
||||||
|
"-enable-kvm",
|
||||||
|
"-m 2G",
|
||||||
|
"-device virtio-blk-pci,bus=pcie.0,addr=0x6,drive=x0,disable-legacy=on,disable-modern=off",
|
||||||
|
"-device virtio-keyboard-pci,disable-legacy=on,disable-modern=off",
|
||||||
|
];
|
||||||
|
|
||||||
|
let args = &["-m 100G", "-device ioh3420,id=pcie.0,chassis=1"];
|
||||||
|
|
||||||
|
let expected = &[
|
||||||
|
"-enable-kvm",
|
||||||
|
"-m 100G",
|
||||||
|
"-device virtio-blk-pci,bus=pcie.0,addr=0x6,drive=x0,disable-legacy=on,disable-modern=off",
|
||||||
|
"-device virtio-keyboard-pci,disable-legacy=on,disable-modern=off",
|
||||||
|
"-device ioh3420,id=pcie.0,chassis=1",
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut array = qemu_args.iter().map(ToString::to_string).collect();
|
||||||
|
let args = args.iter().map(ToString::to_string).collect();
|
||||||
|
apply_kv_array(&mut array, &args, " ", &["-device"]);
|
||||||
|
|
||||||
|
let expected: Vec<_> = expected.iter().map(ToString::to_string).collect();
|
||||||
|
assert_eq!(expected, array);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deserialize_osdk_manifest() {
|
||||||
|
let content = include_str!("OSDK.toml.empty");
|
||||||
|
let osdk_manifest: TomlManifest = toml::from_str(content).unwrap();
|
||||||
|
assert!(osdk_manifest == TomlManifest::default());
|
||||||
|
|
||||||
|
let content = include_str!("OSDK.toml.full");
|
||||||
|
let osdk_manifest: TomlManifest = toml::from_str(content).unwrap();
|
||||||
|
assert!(osdk_manifest.boot.grub_mkrescue.unwrap() == PathBuf::from("/usr/bin/grub-mkrescue"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serialize_osdk_manifest() {
|
||||||
|
let manifest = TomlManifest::default();
|
||||||
|
let contents = toml::to_string(&manifest).unwrap();
|
||||||
|
fs::write("OSDK.toml", contents).unwrap();
|
||||||
|
fs::remove_file("OSDK.toml").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deserialize_conditional_osdk_manifest() {
|
||||||
|
let content = include_str!("OSDK.toml.conditional");
|
||||||
|
let manifest: TomlManifest = toml::from_str(content).unwrap();
|
||||||
|
println!("manifest = {:?}", manifest);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn conditional_manifest() {
|
||||||
|
let toml_manifest: TomlManifest = {
|
||||||
|
let content = include_str!("OSDK.toml.conditional");
|
||||||
|
toml::from_str(content).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(toml_manifest.qemu.cfg.is_some());
|
||||||
|
assert!(toml_manifest
|
||||||
|
.qemu
|
||||||
|
.cfg
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.contains_key(&String::from("cfg(select=\"intel_tdx\")")));
|
||||||
|
assert!(toml_manifest
|
||||||
|
.qemu
|
||||||
|
.cfg
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.contains_key(&String::from("cfg(select=\"iommu\")")));
|
||||||
|
|
||||||
|
// Default selection
|
||||||
|
let selection: Option<&str> = None;
|
||||||
|
let manifest = OsdkManifest::from_toml_manifest(toml_manifest.clone(), selection);
|
||||||
|
assert!(manifest.qemu.args.contains(&String::from(
|
||||||
|
"-device virtio-keyboard-pci,disable-legacy=on,disable-modern=off"
|
||||||
|
)));
|
||||||
|
|
||||||
|
// Iommu
|
||||||
|
let selection: Option<&str> = Some("iommu");
|
||||||
|
let manifest = OsdkManifest::from_toml_manifest(toml_manifest.clone(), selection);
|
||||||
|
assert!(manifest
|
||||||
|
.qemu
|
||||||
|
.args
|
||||||
|
.contains(&String::from("-device ioh3420,id=pcie.0,chassis=1")));
|
||||||
|
|
||||||
|
// Tdx
|
||||||
|
let selection: Option<&str> = Some("intel_tdx");
|
||||||
|
let manifest = OsdkManifest::from_toml_manifest(toml_manifest.clone(), selection);
|
||||||
|
assert!(manifest.qemu.args.is_empty());
|
||||||
|
}
|
@ -10,7 +10,6 @@ pub enum Errno {
|
|||||||
ExecuteCommand = 5,
|
ExecuteCommand = 5,
|
||||||
BuildCrate = 6,
|
BuildCrate = 6,
|
||||||
RunBundle = 7,
|
RunBundle = 7,
|
||||||
CreateBaseCrate = 8,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print error message to console
|
/// Print error message to console
|
||||||
|
@ -14,8 +14,6 @@ mod cli;
|
|||||||
mod commands;
|
mod commands;
|
||||||
mod config_manager;
|
mod config_manager;
|
||||||
mod error;
|
mod error;
|
||||||
#[cfg(test)]
|
|
||||||
mod test;
|
|
||||||
mod utils;
|
mod utils;
|
||||||
mod vm_image;
|
mod vm_image;
|
||||||
|
|
||||||
|
@ -1,153 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
use std::{
|
|
||||||
fs,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
cli::CargoArgs,
|
|
||||||
config_manager::{
|
|
||||||
get_feature_strings,
|
|
||||||
manifest::{OsdkManifest, TomlManifest, SELECT_REGEX},
|
|
||||||
},
|
|
||||||
test::utils::{assert_success, cargo_osdk, create_workspace},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn deserialize_osdk_manifest() {
|
|
||||||
let content = include_str!("OSDK.toml.empty");
|
|
||||||
let osdk_manifest: TomlManifest = toml::from_str(content).unwrap();
|
|
||||||
assert!(osdk_manifest == TomlManifest::default());
|
|
||||||
|
|
||||||
let content = include_str!("OSDK.toml.full");
|
|
||||||
let osdk_manifest: TomlManifest = toml::from_str(content).unwrap();
|
|
||||||
assert!(osdk_manifest.boot.grub_mkrescue.unwrap() == PathBuf::from("/usr/bin/grub-mkrescue"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn serialize_osdk_manifest() {
|
|
||||||
let manifest = TomlManifest::default();
|
|
||||||
let contents = toml::to_string(&manifest).unwrap();
|
|
||||||
fs::write("OSDK.toml", contents).unwrap();
|
|
||||||
fs::remove_file("OSDK.toml").unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn deserialize_conditional_osdk_manifest() {
|
|
||||||
let content = include_str!("OSDK.toml.conditional");
|
|
||||||
let manifest: TomlManifest = toml::from_str(content).unwrap();
|
|
||||||
println!("manifest = {:?}", manifest);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn load_manifest() {
|
|
||||||
let workspace = "workspace_foo";
|
|
||||||
let kernel_name: &str = "foo_os";
|
|
||||||
create_workspace(workspace, &[kernel_name]);
|
|
||||||
create_osdk_kernel(kernel_name, workspace);
|
|
||||||
let cargo_args = CargoArgs::default();
|
|
||||||
cargo_osdk_build(PathBuf::from(workspace).join(kernel_name), &cargo_args);
|
|
||||||
fs::remove_dir_all(workspace).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn load_manifest_conditional() {
|
|
||||||
let workspace = "workspace_bar";
|
|
||||||
let kernel_name: &str = "bar_os";
|
|
||||||
create_workspace(workspace, &[kernel_name]);
|
|
||||||
create_osdk_kernel_with_features(kernel_name, &["intel_tdx", "iommu"], workspace);
|
|
||||||
let contents = include_str!("OSDK.toml.conditional");
|
|
||||||
let path = PathBuf::from(workspace).join("OSDK.toml");
|
|
||||||
fs::write(path, contents).unwrap();
|
|
||||||
|
|
||||||
let cargo_args = CargoArgs {
|
|
||||||
profile: "release".to_string(),
|
|
||||||
features: vec![String::from("iommu")],
|
|
||||||
};
|
|
||||||
cargo_osdk_build(PathBuf::from(workspace).join(kernel_name), &cargo_args);
|
|
||||||
|
|
||||||
fs::remove_dir_all(workspace).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_osdk_kernel(name: &str, current_dir: &str) {
|
|
||||||
let output = cargo_osdk(&["new", "--kernel", name])
|
|
||||||
.current_dir(current_dir)
|
|
||||||
.output()
|
|
||||||
.unwrap();
|
|
||||||
assert_success(&output);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_osdk_kernel_with_features(name: &str, features: &[&str], current_dir: &str) {
|
|
||||||
create_osdk_kernel(name, current_dir);
|
|
||||||
let manifest_path = PathBuf::from(current_dir).join(name).join("Cargo.toml");
|
|
||||||
let contents = fs::read_to_string(&manifest_path).unwrap();
|
|
||||||
let mut manifest: toml::Table = toml::from_str(&contents).unwrap();
|
|
||||||
|
|
||||||
let mut features_table = toml::Table::new();
|
|
||||||
for feature in features {
|
|
||||||
features_table.insert(feature.to_string(), toml::Value::Array(Vec::new()));
|
|
||||||
}
|
|
||||||
manifest.insert("features".to_string(), toml::Value::Table(features_table));
|
|
||||||
|
|
||||||
fs::write(&manifest_path, manifest.to_string()).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cargo_osdk_build<P: AsRef<Path>>(current_dir: P, cargo_args: &CargoArgs) {
|
|
||||||
let args = get_feature_strings(cargo_args);
|
|
||||||
let mut command = cargo_osdk(&["build"]);
|
|
||||||
command.args(args);
|
|
||||||
command.current_dir(current_dir);
|
|
||||||
let output = command.output().unwrap();
|
|
||||||
assert_success(&output);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn conditional_manifest() {
|
|
||||||
let toml_manifest: TomlManifest = {
|
|
||||||
let content = include_str!("OSDK.toml.conditional");
|
|
||||||
toml::from_str(content).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
assert!(toml_manifest.qemu.cfg.is_some());
|
|
||||||
assert!(toml_manifest
|
|
||||||
.qemu
|
|
||||||
.cfg
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.contains_key(&String::from("cfg(select=\"intel_tdx\")")));
|
|
||||||
assert!(toml_manifest
|
|
||||||
.qemu
|
|
||||||
.cfg
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.contains_key(&String::from("cfg(select=\"iommu\")")));
|
|
||||||
|
|
||||||
// Default selection
|
|
||||||
let selection: Option<&str> = None;
|
|
||||||
let manifest = OsdkManifest::from_toml_manifest(toml_manifest.clone(), selection);
|
|
||||||
assert!(manifest.qemu.args.contains(&String::from(
|
|
||||||
"-device virtio-keyboard-pci,disable-legacy=on,disable-modern=off"
|
|
||||||
)));
|
|
||||||
|
|
||||||
// Iommu
|
|
||||||
let selection: Option<&str> = Some("iommu");
|
|
||||||
let manifest = OsdkManifest::from_toml_manifest(toml_manifest.clone(), selection);
|
|
||||||
assert!(manifest
|
|
||||||
.qemu
|
|
||||||
.args
|
|
||||||
.contains(&String::from("-device ioh3420,id=pcie.0,chassis=1")));
|
|
||||||
|
|
||||||
// Tdx
|
|
||||||
let selection: Option<&str> = Some("intel_tdx");
|
|
||||||
let manifest = OsdkManifest::from_toml_manifest(toml_manifest.clone(), selection);
|
|
||||||
assert!(manifest.qemu.args.is_empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn extract_selection() {
|
|
||||||
let text = "cfg(select=\"abc123_\")";
|
|
||||||
let captures = SELECT_REGEX.captures(text).unwrap();
|
|
||||||
let selection = captures.name("select").unwrap().as_str();
|
|
||||||
assert_eq!(selection, "abc123_");
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
use crate::config_manager::{apply_kv_array, get_key};
|
|
||||||
mod manifest;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn get_key_test() {
|
|
||||||
let string1 = "init=/bin/init";
|
|
||||||
let key = get_key(string1, "=").unwrap();
|
|
||||||
assert_eq!(key.as_str(), "init");
|
|
||||||
|
|
||||||
let string2 = "-m 2G";
|
|
||||||
let key = get_key(string2, " ").unwrap();
|
|
||||||
assert_eq!(key.as_str(), "-m");
|
|
||||||
|
|
||||||
let string3 = "-device virtio-keyboard-pci,disable-legacy=on,disable-modern=off";
|
|
||||||
let key = get_key(string3, " ").unwrap();
|
|
||||||
assert_eq!(key.as_str(), "-device");
|
|
||||||
|
|
||||||
let string4 = "-device";
|
|
||||||
assert!(get_key(string4, " ").is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn apply_kv_array_test() {
|
|
||||||
let qemu_args = &[
|
|
||||||
"-enable-kvm",
|
|
||||||
"-m 2G",
|
|
||||||
"-device virtio-blk-pci,bus=pcie.0,addr=0x6,drive=x0,disable-legacy=on,disable-modern=off",
|
|
||||||
"-device virtio-keyboard-pci,disable-legacy=on,disable-modern=off",
|
|
||||||
];
|
|
||||||
|
|
||||||
let args = &["-m 100G", "-device ioh3420,id=pcie.0,chassis=1"];
|
|
||||||
|
|
||||||
let expected = &[
|
|
||||||
"-enable-kvm",
|
|
||||||
"-m 100G",
|
|
||||||
"-device virtio-blk-pci,bus=pcie.0,addr=0x6,drive=x0,disable-legacy=on,disable-modern=off",
|
|
||||||
"-device virtio-keyboard-pci,disable-legacy=on,disable-modern=off",
|
|
||||||
"-device ioh3420,id=pcie.0,chassis=1",
|
|
||||||
];
|
|
||||||
|
|
||||||
let mut array = qemu_args.iter().map(ToString::to_string).collect();
|
|
||||||
let args = args.iter().map(ToString::to_string).collect();
|
|
||||||
apply_kv_array(&mut array, &args, " ", &["-device"]);
|
|
||||||
|
|
||||||
let expected: Vec<_> = expected.iter().map(ToString::to_string).collect();
|
|
||||||
assert_eq!(expected, array);
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
//! The crate unit test module
|
|
||||||
|
|
||||||
mod cli;
|
|
||||||
mod commands;
|
|
||||||
mod config_manager;
|
|
||||||
mod utils;
|
|
@ -83,13 +83,13 @@ pub fn get_current_crate_info() -> CrateInfo {
|
|||||||
let default_member = default_members[0]
|
let default_member = default_members[0]
|
||||||
.as_str()
|
.as_str()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.split(" ")
|
.split(' ')
|
||||||
.collect::<Vec<&str>>();
|
.collect::<Vec<&str>>();
|
||||||
let name = default_member[0].to_string();
|
let name = default_member[0].to_string();
|
||||||
let version = default_member[1].to_string();
|
let version = default_member[1].to_string();
|
||||||
let path = default_member[2]
|
let path = default_member[2]
|
||||||
.trim_start_matches("(path+file://")
|
.trim_start_matches("(path+file://")
|
||||||
.trim_end_matches(")")
|
.trim_end_matches(')')
|
||||||
.to_string();
|
.to_string();
|
||||||
CrateInfo {
|
CrateInfo {
|
||||||
name,
|
name,
|
||||||
|
10
osdk/tests/bin.rs
Normal file
10
osdk/tests/bin.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
//! This module contains tests that invokes the `osdk` binary and checks the output.
|
||||||
|
//! Please be sure the the `osdk` binary is built and available in the `target/debug`
|
||||||
|
//! directory before running these tests.
|
||||||
|
|
||||||
|
mod cli;
|
||||||
|
mod commands;
|
||||||
|
mod integration;
|
||||||
|
mod util;
|
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use super::utils::*;
|
use crate::util::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cli_help_message() {
|
fn cli_help_message() {
|
@ -1,15 +1,18 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use std::fs::remove_dir_all;
|
use std::{fs::remove_dir_all, path::Path};
|
||||||
|
|
||||||
use crate::test::utils::*;
|
use crate::util::*;
|
||||||
|
|
||||||
const KERNEL_NAME: &str = "myos";
|
const KERNEL_NAME: &str = "myos";
|
||||||
const LIB_NAME: &str = "my_module";
|
const LIB_NAME: &str = "my_module";
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_kernel_in_workspace() {
|
fn create_kernel_in_workspace() {
|
||||||
const WORKSPACE_NAME: &str = "kernel_workspace";
|
const WORKSPACE_NAME: &str = "/tmp/kernel_workspace";
|
||||||
|
if Path::new(WORKSPACE_NAME).exists() {
|
||||||
|
remove_dir_all(WORKSPACE_NAME).unwrap();
|
||||||
|
}
|
||||||
create_workspace(WORKSPACE_NAME, &[KERNEL_NAME]);
|
create_workspace(WORKSPACE_NAME, &[KERNEL_NAME]);
|
||||||
let mut cargo_osdk = cargo_osdk(["new", "--kernel", KERNEL_NAME]);
|
let mut cargo_osdk = cargo_osdk(["new", "--kernel", KERNEL_NAME]);
|
||||||
cargo_osdk.current_dir(WORKSPACE_NAME);
|
cargo_osdk.current_dir(WORKSPACE_NAME);
|
||||||
@ -20,7 +23,10 @@ fn create_kernel_in_workspace() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_lib_in_workspace() {
|
fn create_lib_in_workspace() {
|
||||||
const WORKSPACE_NAME: &str = "lib_workspace";
|
const WORKSPACE_NAME: &str = "/tmp/lib_workspace";
|
||||||
|
if Path::new(WORKSPACE_NAME).exists() {
|
||||||
|
remove_dir_all(WORKSPACE_NAME).unwrap();
|
||||||
|
}
|
||||||
create_workspace(WORKSPACE_NAME, &[LIB_NAME]);
|
create_workspace(WORKSPACE_NAME, &[LIB_NAME]);
|
||||||
let mut cargo_osdk = cargo_osdk(["new", LIB_NAME]);
|
let mut cargo_osdk = cargo_osdk(["new", LIB_NAME]);
|
||||||
cargo_osdk.current_dir(WORKSPACE_NAME);
|
cargo_osdk.current_dir(WORKSPACE_NAME);
|
||||||
@ -31,7 +37,11 @@ fn create_lib_in_workspace() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_two_crates_in_workspace() {
|
fn create_two_crates_in_workspace() {
|
||||||
const WORKSPACE_NAME: &str = "my_workspace";
|
const WORKSPACE_NAME: &str = "/tmp/my_workspace";
|
||||||
|
if Path::new(WORKSPACE_NAME).exists() {
|
||||||
|
remove_dir_all(WORKSPACE_NAME).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
create_workspace(WORKSPACE_NAME, &[LIB_NAME]);
|
create_workspace(WORKSPACE_NAME, &[LIB_NAME]);
|
||||||
// Create lib crate
|
// Create lib crate
|
||||||
let mut command = cargo_osdk(["new", LIB_NAME]);
|
let mut command = cargo_osdk(["new", LIB_NAME]);
|
16
osdk/tests/integration/OSDK.toml.conditional
Normal file
16
osdk/tests/integration/OSDK.toml.conditional
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
[qemu]
|
||||||
|
args = [
|
||||||
|
"-device virtio-keyboard-pci,disable-legacy=on,disable-modern=off",
|
||||||
|
"-device virtio-net-pci,netdev=net01,disable-legacy=on,disable-modern=off",
|
||||||
|
"-device virtio-serial-pci,disable-legacy=on,disable-modern=off"
|
||||||
|
]
|
||||||
|
|
||||||
|
[qemu.'cfg(select="intel_tdx")']
|
||||||
|
|
||||||
|
[qemu.'cfg(select="iommu")']
|
||||||
|
args = [
|
||||||
|
"-device virtio-blk-pci,bus=pcie.0,addr=0x6,drive=x0,disable-legacy=on,disable-modern=off,iommu_platform=on,ats=on",
|
||||||
|
"-device virtio-keyboard-pci,disable-legacy=on,disable-modern=off,iommu_platform=on,ats=on",
|
||||||
|
"-device intel-iommu,intremap=on,device-iotlb=on",
|
||||||
|
"-device ioh3420,id=pcie.0,chassis=1",
|
||||||
|
]
|
76
osdk/tests/integration/mod.rs
Normal file
76
osdk/tests/integration/mod.rs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
fs,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::util::{assert_success, cargo_osdk, create_workspace};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn build_with_default_manifest() {
|
||||||
|
let workspace = "/tmp/workspace_foo";
|
||||||
|
if Path::new(workspace).exists() {
|
||||||
|
fs::remove_dir_all(workspace).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let kernel_name: &str = "foo_os";
|
||||||
|
create_workspace(workspace, &[kernel_name]);
|
||||||
|
create_osdk_kernel(kernel_name, workspace);
|
||||||
|
cargo_osdk_build(PathBuf::from(workspace).join(kernel_name), &[]);
|
||||||
|
|
||||||
|
fs::remove_dir_all(workspace).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn build_with_conditional_manifest() {
|
||||||
|
let workspace = "/tmp/workspace_bar";
|
||||||
|
if Path::new(workspace).exists() {
|
||||||
|
fs::remove_dir_all(workspace).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let kernel_name: &str = "bar_os";
|
||||||
|
create_workspace(workspace, &[kernel_name]);
|
||||||
|
create_osdk_kernel_with_features(kernel_name, &["intel_tdx", "iommu"], workspace);
|
||||||
|
let contents = include_str!("OSDK.toml.conditional");
|
||||||
|
let path = PathBuf::from(workspace).join("OSDK.toml");
|
||||||
|
fs::write(path, contents).unwrap();
|
||||||
|
|
||||||
|
cargo_osdk_build(
|
||||||
|
PathBuf::from(workspace).join(kernel_name),
|
||||||
|
&["--profile", "release", "--features", "iommu"],
|
||||||
|
);
|
||||||
|
|
||||||
|
fs::remove_dir_all(workspace).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_osdk_kernel(name: &str, current_dir: &str) {
|
||||||
|
let output = cargo_osdk(&["new", "--kernel", name])
|
||||||
|
.current_dir(current_dir)
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
assert_success(&output);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_osdk_kernel_with_features(name: &str, features: &[&str], current_dir: &str) {
|
||||||
|
create_osdk_kernel(name, current_dir);
|
||||||
|
let manifest_path = PathBuf::from(current_dir).join(name).join("Cargo.toml");
|
||||||
|
let contents = fs::read_to_string(&manifest_path).unwrap();
|
||||||
|
let mut manifest: toml::Table = toml::from_str(&contents).unwrap();
|
||||||
|
|
||||||
|
let mut features_table = toml::Table::new();
|
||||||
|
for feature in features {
|
||||||
|
features_table.insert(feature.to_string(), toml::Value::Array(Vec::new()));
|
||||||
|
}
|
||||||
|
manifest.insert("features".to_string(), toml::Value::Table(features_table));
|
||||||
|
|
||||||
|
fs::write(&manifest_path, manifest.to_string()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cargo_osdk_build<P: AsRef<Path>>(current_dir: P, args: &[&str]) {
|
||||||
|
let mut command = cargo_osdk(&["build"]);
|
||||||
|
command.args(args);
|
||||||
|
command.current_dir(current_dir);
|
||||||
|
let output = command.output().unwrap();
|
||||||
|
assert_success(&output);
|
||||||
|
}
|
@ -33,6 +33,7 @@ pub fn assert_stdout_contains_msg(output: &Output, msg: &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_workspace(workspace_name: &str, members: &[&str]) {
|
pub fn create_workspace(workspace_name: &str, members: &[&str]) {
|
||||||
|
// Create Cargo.toml
|
||||||
let mut table = toml::Table::new();
|
let mut table = toml::Table::new();
|
||||||
let workspace_table = {
|
let workspace_table = {
|
||||||
let mut table = toml::Table::new();
|
let mut table = toml::Table::new();
|
||||||
@ -58,8 +59,14 @@ pub fn create_workspace(workspace_name: &str, members: &[&str]) {
|
|||||||
let content = table.to_string();
|
let content = table.to_string();
|
||||||
fs::write(manefest_path, content).unwrap();
|
fs::write(manefest_path, content).unwrap();
|
||||||
|
|
||||||
|
// Create OSDK.toml
|
||||||
let osdk_manifest_path = PathBuf::from(workspace_name).join("OSDK.toml");
|
let osdk_manifest_path = PathBuf::from(workspace_name).join("OSDK.toml");
|
||||||
fs::write(osdk_manifest_path, "").unwrap();
|
fs::write(osdk_manifest_path, "").unwrap();
|
||||||
|
|
||||||
|
// Create rust-toolchain.toml which is synced with the Asterinas' toolchain
|
||||||
|
let rust_toolchain_path = PathBuf::from(workspace_name).join("rust-toolchain.toml");
|
||||||
|
let content = include_str!("../../../rust-toolchain.toml");
|
||||||
|
fs::write(rust_toolchain_path, content).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_member_to_workspace(workspace: impl AsRef<Path>, new_member: &str) {
|
pub fn add_member_to_workspace(workspace: impl AsRef<Path>, new_member: &str) {
|
Reference in New Issue
Block a user