mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-20 13:06:33 +00:00
Fix the OSDK CI failure
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
fe7251c413
commit
3de8a9330a
15
Cargo.lock
generated
15
Cargo.lock
generated
@ -139,7 +139,6 @@ dependencies = [
|
||||
"bitvec",
|
||||
"component",
|
||||
"int-to-c-enum",
|
||||
"ktest",
|
||||
"log",
|
||||
"ostd",
|
||||
"pod",
|
||||
@ -180,7 +179,6 @@ dependencies = [
|
||||
"int-to-c-enum",
|
||||
"intrusive-collections",
|
||||
"keyable-arc",
|
||||
"ktest",
|
||||
"lazy_static",
|
||||
"lending-iterator",
|
||||
"libflate",
|
||||
@ -240,7 +238,6 @@ dependencies = [
|
||||
"aster-rights",
|
||||
"aster-rights-proc",
|
||||
"inherit-methods-macro",
|
||||
"ktest",
|
||||
"ostd",
|
||||
"pod",
|
||||
"typeflags-util",
|
||||
@ -797,20 +794,9 @@ version = "0.1.0"
|
||||
name = "ktest"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ktest-proc-macro",
|
||||
"owo-colors",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ktest-proc-macro"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rand",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
@ -1131,6 +1117,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rand",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
|
@ -9,7 +9,6 @@ members = [
|
||||
"ostd/libs/linux-bzimage/boot-params",
|
||||
"ostd/libs/linux-bzimage/setup",
|
||||
"ostd/libs/ktest",
|
||||
"ostd/libs/ktest-proc-macro",
|
||||
"kernel",
|
||||
"kernel/aster-nix",
|
||||
"kernel/comps/block",
|
||||
|
3
Makefile
3
Makefile
@ -86,12 +86,11 @@ export
|
||||
# or tested without OSDK.
|
||||
NON_OSDK_CRATES := \
|
||||
ostd/libs/align_ext \
|
||||
ostd/libs/ostd-macros \
|
||||
ostd/libs/id-alloc \
|
||||
ostd/libs/linux-bzimage/builder \
|
||||
ostd/libs/linux-bzimage/boot-params \
|
||||
ostd/libs/ktest \
|
||||
ostd/libs/ktest-proc-macro \
|
||||
ostd/libs/ostd-macros \
|
||||
kernel/libs/cpio-decoder \
|
||||
kernel/libs/int-to-c-enum \
|
||||
kernel/libs/int-to-c-enum/derive \
|
||||
|
@ -84,10 +84,6 @@ The dependency version may change over time.
|
||||
[dependencies.ostd]
|
||||
git = "https://github.com/asterinas/asterinas"
|
||||
branch = "main"
|
||||
|
||||
[dependencies.ktest]
|
||||
git = "https://github.com/asterinas/asterinas"
|
||||
branch = "main"
|
||||
```
|
||||
|
||||
OSDK will also exclude the directory
|
||||
|
@ -42,7 +42,6 @@ smoltcp = { version = "0.9.1", default-features = false, features = [
|
||||
"socket-raw",
|
||||
"socket-dhcpv4",
|
||||
] }
|
||||
ktest = { path = "../../ostd/libs/ktest" }
|
||||
tdx-guest = { version = "0.1.0", optional = true }
|
||||
|
||||
# parse elf file
|
||||
|
@ -21,7 +21,10 @@ mod test {
|
||||
bio::{BioEnqueueError, BioStatus, BioType, SubmittedBio},
|
||||
BlockDevice,
|
||||
};
|
||||
use ostd::mm::{FrameAllocOptions, Segment, VmIo};
|
||||
use ostd::{
|
||||
mm::{FrameAllocOptions, Segment, VmIo},
|
||||
prelude::*,
|
||||
};
|
||||
use rand::{rngs::SmallRng, RngCore, SeedableRng};
|
||||
|
||||
use crate::{
|
||||
|
@ -541,6 +541,8 @@ impl<T> AsRef<Error> for (Error, T) {
|
||||
mod test {
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use ostd::prelude::*;
|
||||
|
||||
use crate::fs::utils::Channel;
|
||||
|
||||
#[ktest]
|
||||
|
@ -41,9 +41,6 @@ extern crate alloc;
|
||||
extern crate lru;
|
||||
#[macro_use]
|
||||
extern crate controlled;
|
||||
#[cfg(ktest)]
|
||||
#[macro_use]
|
||||
extern crate ktest;
|
||||
#[macro_use]
|
||||
extern crate getset;
|
||||
|
||||
|
@ -652,6 +652,8 @@ pub fn current() -> Arc<Process> {
|
||||
#[cfg(ktest)]
|
||||
mod test {
|
||||
|
||||
use ostd::prelude::*;
|
||||
|
||||
use super::*;
|
||||
|
||||
fn new_process(parent: Option<Arc<Process>>) -> Arc<Process> {
|
||||
|
@ -264,7 +264,7 @@ impl Condvar {
|
||||
|
||||
#[cfg(ktest)]
|
||||
mod test {
|
||||
use ostd::sync::Mutex;
|
||||
use ostd::{prelude::*, sync::Mutex};
|
||||
|
||||
use super::*;
|
||||
use crate::thread::{
|
||||
|
@ -189,7 +189,7 @@ fn taskless_softirq_handler(
|
||||
mod test {
|
||||
use core::sync::atomic::AtomicUsize;
|
||||
|
||||
use ostd::trap::enable_local;
|
||||
use ostd::{prelude::*, trap::enable_local};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
@ -136,7 +136,7 @@ impl<R> VmarChildOptions<R> {
|
||||
#[cfg(ktest)]
|
||||
mod test {
|
||||
use aster_rights::Full;
|
||||
use ostd::mm::VmIo;
|
||||
use ostd::{mm::VmIo, prelude::*};
|
||||
|
||||
use super::*;
|
||||
use crate::vm::{
|
||||
|
@ -477,7 +477,7 @@ impl VmoChildType for VmoCowChild {}
|
||||
#[cfg(ktest)]
|
||||
mod test {
|
||||
use aster_rights::Full;
|
||||
use ostd::mm::VmIo;
|
||||
use ostd::{mm::VmIo, prelude::*};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
@ -13,7 +13,6 @@ bitflags = "1.3"
|
||||
bitvec = { version = "1.0.1", default-features = false, features = ["alloc"]}
|
||||
component = { path = "../../libs/comp-sys/component" }
|
||||
int-to-c-enum = { path = "../../libs/int-to-c-enum" }
|
||||
ktest = { path = "../../../ostd/libs/ktest" }
|
||||
log = "0.4"
|
||||
ostd = { path = "../../../ostd" }
|
||||
pod = { git = "https://github.com/asterinas/pod", rev = "d7dba56" }
|
||||
|
@ -9,7 +9,6 @@ use alloc::{
|
||||
use core::ops::Range;
|
||||
|
||||
use bitvec::{array::BitArray, prelude::Lsb0};
|
||||
use ktest::ktest;
|
||||
use ostd::{
|
||||
mm::{
|
||||
Daddr, DmaDirection, DmaStream, FrameAllocOptions, HasDaddr, VmReader, VmWriter, PAGE_SIZE,
|
||||
@ -288,6 +287,8 @@ impl Drop for DmaSegment {
|
||||
mod test {
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use ostd::prelude::*;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[ktest]
|
||||
|
@ -12,6 +12,5 @@ typeflags-util = { path = "../typeflags-util" }
|
||||
aster-rights-proc = { path = "../aster-rights-proc" }
|
||||
aster-rights = { path = "../aster-rights" }
|
||||
inherit-methods-macro = { git = "https://github.com/asterinas/inherit-methods-macro", rev = "98f7e3e" }
|
||||
ktest = { path = "../../../ostd/libs/ktest" }
|
||||
|
||||
[features]
|
||||
|
@ -127,9 +127,10 @@ impl Mul<u32> for Coeff {
|
||||
|
||||
#[cfg(ktest)]
|
||||
mod test {
|
||||
use ktest::ktest;
|
||||
use ostd::prelude::*;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[ktest]
|
||||
fn calculation() {
|
||||
let coeff = Coeff::new(23456, 56789, 1_000_000_000);
|
||||
|
@ -1,12 +1,10 @@
|
||||
#![no_std]
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
#[cfg_attr(ktest, macro_use)]
|
||||
extern crate ktest;
|
||||
extern crate ostd;
|
||||
|
||||
#[cfg(ktest)]
|
||||
mod tests {
|
||||
use ostd::prelude::*;
|
||||
|
||||
#[ktest]
|
||||
fn it_works() {
|
||||
let memory_regions = ostd::boot::memory_regions();
|
||||
|
@ -42,8 +42,6 @@ fn add_manifest_dependencies(cargo_metadata: &serde_json::Value, crate_name: &st
|
||||
|
||||
let ostd_dep = toml::Table::from_str(&aster_crate_dep("ostd")).unwrap();
|
||||
dependencies.as_table_mut().unwrap().extend(ostd_dep);
|
||||
let ktest_dep = toml::Table::from_str(&aster_crate_dep("ktest")).unwrap();
|
||||
dependencies.as_table_mut().unwrap().extend(ktest_dep);
|
||||
|
||||
let content = toml::to_string(&manifest).unwrap();
|
||||
fs::write(mainfest_path, content).unwrap();
|
||||
|
@ -18,16 +18,19 @@ fn create_kernel_in_workspace() {
|
||||
}
|
||||
create_workspace(WORKSPACE_NAME, &[KERNEL_NAME]);
|
||||
let kernel_path = PathBuf::from(WORKSPACE_NAME).join(KERNEL_NAME);
|
||||
let manifest_path = kernel_path.join("Cargo.toml");
|
||||
|
||||
let mut cmd = cargo_osdk(["new", "--kernel", KERNEL_NAME]);
|
||||
cmd.current_dir(WORKSPACE_NAME);
|
||||
let output = cmd.output().unwrap();
|
||||
depends_on_local_ostd(&manifest_path);
|
||||
assert_success(&output);
|
||||
remove_dir_all(&kernel_path).unwrap();
|
||||
|
||||
let mut cmd = cargo_osdk(["new", "-t", "kernel", KERNEL_NAME]);
|
||||
cmd.current_dir(WORKSPACE_NAME);
|
||||
let output = cmd.output().unwrap();
|
||||
depends_on_local_ostd(&manifest_path);
|
||||
assert_success(&output);
|
||||
remove_dir_all(&kernel_path).unwrap();
|
||||
|
||||
|
@ -21,6 +21,8 @@ mod workspace {
|
||||
cargo_osdk_new
|
||||
.ok()
|
||||
.expect("Failed to create kernel project");
|
||||
let manifest_path = os_dir.join("Cargo.toml");
|
||||
depends_on_local_ostd(manifest_path);
|
||||
}
|
||||
|
||||
fn prepare_workspace(workspace: &str) {
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use std::{fs, path::PathBuf};
|
||||
|
||||
use crate::util::cargo_osdk;
|
||||
use crate::util::{cargo_osdk, depends_on_local_ostd};
|
||||
|
||||
#[test]
|
||||
fn create_a_kernel_project() {
|
||||
@ -23,6 +23,8 @@ fn create_a_kernel_project() {
|
||||
assert!(kernel_path.join("Cargo.toml").is_file());
|
||||
assert!(kernel_path.join("rust-toolchain.toml").is_file());
|
||||
|
||||
depends_on_local_ostd(kernel_path.join("Cargo.toml"));
|
||||
|
||||
fs::remove_dir_all(&kernel_path).unwrap();
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use std::{fs, path::PathBuf};
|
||||
|
||||
use crate::util::cargo_osdk;
|
||||
use crate::util::{cargo_osdk, depends_on_local_ostd};
|
||||
|
||||
#[test]
|
||||
fn create_and_run_kernel() {
|
||||
@ -19,6 +19,10 @@ fn create_and_run_kernel() {
|
||||
command.current_dir(work_dir);
|
||||
command.ok().unwrap();
|
||||
|
||||
// Makes the kernel depend on local OSTD
|
||||
let manifest_path = os_dir.join("Cargo.toml");
|
||||
depends_on_local_ostd(&manifest_path);
|
||||
|
||||
let mut command = cargo_osdk(&["build"]);
|
||||
command.current_dir(&os_dir);
|
||||
command.ok().unwrap();
|
||||
@ -48,6 +52,9 @@ fn create_and_test_library() {
|
||||
command.current_dir(work_dir);
|
||||
command.ok().unwrap();
|
||||
|
||||
let manifest_path = module_dir.join("Cargo.toml");
|
||||
depends_on_local_ostd(manifest_path);
|
||||
|
||||
let mut command = cargo_osdk(&["test"]);
|
||||
command.current_dir(&module_dir);
|
||||
command.ok().unwrap();
|
||||
|
@ -7,7 +7,7 @@ use std::{
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use crate::util::cargo_osdk;
|
||||
use crate::util::{cargo_osdk, depends_on_local_ostd};
|
||||
|
||||
#[test]
|
||||
fn work_in_workspace() {
|
||||
@ -46,9 +46,14 @@ fn work_in_workspace() {
|
||||
.unwrap();
|
||||
module_src_file.flush().unwrap();
|
||||
|
||||
// Make module depends on local ostd
|
||||
let module_manifest_path = workspace_dir.join(module).join("Cargo.toml");
|
||||
depends_on_local_ostd(module_manifest_path);
|
||||
|
||||
// Add dependency to myos/Cargo.toml
|
||||
let kernel_manifest_path = workspace_dir.join(kernel).join("Cargo.toml");
|
||||
assert!(kernel_manifest_path.is_file());
|
||||
depends_on_local_ostd(&kernel_manifest_path);
|
||||
let mut kernel_manifest_file = OpenOptions::new()
|
||||
.append(true)
|
||||
.open(&kernel_manifest_path)
|
||||
|
@ -10,6 +10,7 @@ use std::{
|
||||
};
|
||||
|
||||
use assert_cmd::Command;
|
||||
use toml::{Table, Value};
|
||||
|
||||
pub fn cargo_osdk<T: AsRef<OsStr>, I: IntoIterator<Item = T>>(args: I) -> Command {
|
||||
let mut command = Command::cargo_bin("cargo-osdk").unwrap();
|
||||
@ -85,3 +86,35 @@ pub fn add_member_to_workspace(workspace: impl AsRef<Path>, new_member: &str) {
|
||||
let new_content = workspace_manifest.to_string();
|
||||
fs::write(&path, new_content).unwrap();
|
||||
}
|
||||
|
||||
/// Makes crates created by `cargo ostd new` depends on ostd locally,
|
||||
/// instead of ostd from local branch.
|
||||
///
|
||||
/// Each crate created by `cargo ostd new` should add this patch.
|
||||
pub fn depends_on_local_ostd(manifest_path: impl AsRef<Path>) {
|
||||
let crate_dir = env!("CARGO_MANIFEST_DIR");
|
||||
let ostd_dir = PathBuf::from(crate_dir)
|
||||
.join("..")
|
||||
.join("ostd")
|
||||
.canonicalize()
|
||||
.unwrap()
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
|
||||
// FIXME: It may be more elegant to add `patch` section instead of replacing dependency.
|
||||
// But adding `patch` section does not work in my local test, which is confusing.
|
||||
|
||||
let manifest_content = fs::read_to_string(&manifest_path).unwrap();
|
||||
let mut manifest: Table = toml::from_str(&manifest_content).unwrap();
|
||||
let dep = manifest
|
||||
.get_mut("dependencies")
|
||||
.map(Value::as_table_mut)
|
||||
.flatten()
|
||||
.unwrap();
|
||||
|
||||
let mut table = Table::new();
|
||||
table.insert("path".to_string(), Value::String(ostd_dir));
|
||||
dep.insert("ostd".to_string(), Value::Table(table));
|
||||
|
||||
fs::write(manifest_path, manifest.to_string().as_bytes()).unwrap();
|
||||
}
|
||||
|
@ -1,15 +0,0 @@
|
||||
[package]
|
||||
name = "ktest-proc-macro"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0.69"
|
||||
quote = "1.0.33"
|
||||
rand = "0.8.5"
|
||||
syn = { version = "2.0.29", features = ["full"] }
|
@ -1,113 +0,0 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#![feature(proc_macro_span)]
|
||||
|
||||
extern crate proc_macro2;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use rand::{distributions::Alphanumeric, Rng};
|
||||
use syn::{parse_macro_input, Expr, Ident, ItemFn};
|
||||
|
||||
/// The test attribute macro to mark a test function.
|
||||
#[proc_macro_attribute]
|
||||
pub fn ktest(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
// Assuming that the item has type `fn() -> ()`, otherwise panics.
|
||||
let input = parse_macro_input!(item as ItemFn);
|
||||
assert!(
|
||||
input.sig.inputs.is_empty(),
|
||||
"ktest function should have no arguments"
|
||||
);
|
||||
assert!(
|
||||
matches!(input.sig.output, syn::ReturnType::Default),
|
||||
"ktest function should return `()`"
|
||||
);
|
||||
|
||||
// Generate a random identifier to avoid name conflicts.
|
||||
let fn_id: String = rand::thread_rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
.take(8)
|
||||
.map(char::from)
|
||||
.collect();
|
||||
|
||||
let fn_name = &input.sig.ident;
|
||||
let fn_ktest_item_name = Ident::new(
|
||||
&format!("{}_ktest_item_{}", &input.sig.ident, &fn_id),
|
||||
proc_macro2::Span::call_site(),
|
||||
);
|
||||
|
||||
let is_should_panic_attr = |attr: &&syn::Attribute| {
|
||||
attr.path()
|
||||
.segments
|
||||
.iter()
|
||||
.any(|segment| segment.ident == "should_panic")
|
||||
};
|
||||
let mut attr_iter = input.attrs.iter();
|
||||
let should_panic = attr_iter.find(is_should_panic_attr);
|
||||
let (should_panic, expectation) = match should_panic {
|
||||
Some(attr) => {
|
||||
assert!(
|
||||
!attr_iter.any(|attr: &syn::Attribute| is_should_panic_attr(&attr)),
|
||||
"multiple `should_panic` attributes"
|
||||
);
|
||||
match &attr.meta {
|
||||
syn::Meta::List(l) => {
|
||||
let arg_err_message = "`should_panic` attribute should only have zero or one `expected` argument, with the format of `expected = \"<panic message>\"`";
|
||||
let expected_assign =
|
||||
syn::parse2::<syn::ExprAssign>(l.tokens.clone()).expect(arg_err_message);
|
||||
let Expr::Lit(s) = *expected_assign.right else {
|
||||
panic!("{}", arg_err_message);
|
||||
};
|
||||
let syn::Lit::Str(expectation) = s.lit else {
|
||||
panic!("{}", arg_err_message);
|
||||
};
|
||||
(true, Some(expectation))
|
||||
}
|
||||
_ => (true, None),
|
||||
}
|
||||
}
|
||||
None => (false, None),
|
||||
};
|
||||
let expectation_tokens = if let Some(s) = expectation {
|
||||
quote! {
|
||||
Some(#s)
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let package_name = std::env::var("CARGO_PKG_NAME").unwrap();
|
||||
let span = proc_macro::Span::call_site();
|
||||
let source = span.source_file().path();
|
||||
let source = source.to_str().unwrap();
|
||||
let line = span.line();
|
||||
let col = span.column();
|
||||
|
||||
let register_ktest_item = quote! {
|
||||
#[cfg(ktest)]
|
||||
#[used]
|
||||
#[link_section = ".ktest_array"]
|
||||
static #fn_ktest_item_name: ktest::KtestItem = ktest::KtestItem::new(
|
||||
#fn_name,
|
||||
(#should_panic, #expectation_tokens),
|
||||
ktest::KtestItemInfo {
|
||||
module_path: module_path!(),
|
||||
fn_name: stringify!(#fn_name),
|
||||
package: #package_name,
|
||||
source: #source,
|
||||
line: #line,
|
||||
col: #col,
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
let output = quote! {
|
||||
#input
|
||||
|
||||
#register_ktest_item
|
||||
};
|
||||
|
||||
TokenStream::from(output)
|
||||
}
|
@ -7,4 +7,3 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
owo-colors = "3.5.0"
|
||||
ktest-proc-macro = { path = "../ktest-proc-macro" }
|
||||
|
@ -22,9 +22,10 @@
|
||||
//! module, e.g.:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use ktest::ktest;
|
||||
//! #[cfg(ktest)]
|
||||
//! mod test {
|
||||
//! use ostd::prelude::*;
|
||||
//!
|
||||
//! #[ktest]
|
||||
//! fn trivial_assertion() {
|
||||
//! assert_eq!(0, 0);
|
||||
@ -42,13 +43,12 @@
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! And also, any crates using the ktest framework should be linked with ostd
|
||||
//! and import the `ktest` crate:
|
||||
//! Any crates using the ktest framework should be linked with ostd.
|
||||
//!
|
||||
//! ```toml
|
||||
//! # Cargo.toml
|
||||
//! [dependencies]
|
||||
//! ktest = { path = "relative/path/to/ktest" }
|
||||
//! ostd = { path = "relative/path/to/ostd" }
|
||||
//! ```
|
||||
//!
|
||||
//! By the way, `#[ktest]` attribute along also works, but it hinders test control
|
||||
@ -97,8 +97,6 @@ pub mod tree;
|
||||
extern crate alloc;
|
||||
use alloc::{boxed::Box, string::String};
|
||||
|
||||
pub use ktest_proc_macro::ktest;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PanicInfo {
|
||||
pub message: String,
|
||||
|
@ -11,4 +11,5 @@ proc-macro = true
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0.78"
|
||||
quote = "1.0.35"
|
||||
rand = "0.8.5"
|
||||
syn = { version = "2.0.48", features = ["full"] }
|
||||
|
@ -1,8 +1,11 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#![feature(proc_macro_span)]
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, ItemFn};
|
||||
use rand::{distributions::Alphanumeric, Rng};
|
||||
use syn::{parse_macro_input, Expr, Ident, ItemFn};
|
||||
|
||||
/// This macro is used to mark the kernel entry point.
|
||||
///
|
||||
@ -33,3 +36,152 @@ pub fn main(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// The test attribute macro to mark a test function.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// For crates other than ostd,
|
||||
/// this macro can be used in the following form.
|
||||
///
|
||||
/// ```norun
|
||||
/// use ostd::prelude::*;
|
||||
///
|
||||
/// #[ktest]
|
||||
/// fn test_fn() {
|
||||
/// assert_eq!(1 + 1, 2);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// For ostd crate itself,
|
||||
/// this macro can be used in the form
|
||||
///
|
||||
/// ```norun
|
||||
/// use crate::prelude::*;
|
||||
///
|
||||
/// #[ktest]
|
||||
/// fn test_fn() {
|
||||
/// assert_eq!(1 + 1, 2);
|
||||
/// }
|
||||
/// ```
|
||||
#[proc_macro_attribute]
|
||||
pub fn ktest(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
// Assuming that the item has type `fn() -> ()`, otherwise panics.
|
||||
let input = parse_macro_input!(item as ItemFn);
|
||||
assert!(
|
||||
input.sig.inputs.is_empty(),
|
||||
"ostd::test function should have no arguments"
|
||||
);
|
||||
assert!(
|
||||
matches!(input.sig.output, syn::ReturnType::Default),
|
||||
"ostd::test function should return `()`"
|
||||
);
|
||||
|
||||
// Generate a random identifier to avoid name conflicts.
|
||||
let fn_id: String = rand::thread_rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
.take(8)
|
||||
.map(char::from)
|
||||
.collect();
|
||||
|
||||
let fn_name = &input.sig.ident;
|
||||
let fn_ktest_item_name = Ident::new(
|
||||
&format!("{}_ktest_item_{}", &input.sig.ident, &fn_id),
|
||||
proc_macro2::Span::call_site(),
|
||||
);
|
||||
|
||||
let is_should_panic_attr = |attr: &&syn::Attribute| {
|
||||
attr.path()
|
||||
.segments
|
||||
.iter()
|
||||
.any(|segment| segment.ident == "should_panic")
|
||||
};
|
||||
let mut attr_iter = input.attrs.iter();
|
||||
let should_panic = attr_iter.find(is_should_panic_attr);
|
||||
let (should_panic, expectation) = match should_panic {
|
||||
Some(attr) => {
|
||||
assert!(
|
||||
!attr_iter.any(|attr: &syn::Attribute| is_should_panic_attr(&attr)),
|
||||
"multiple `should_panic` attributes"
|
||||
);
|
||||
match &attr.meta {
|
||||
syn::Meta::List(l) => {
|
||||
let arg_err_message = "`should_panic` attribute should only have zero or one `expected` argument, with the format of `expected = \"<panic message>\"`";
|
||||
let expected_assign =
|
||||
syn::parse2::<syn::ExprAssign>(l.tokens.clone()).expect(arg_err_message);
|
||||
let Expr::Lit(s) = *expected_assign.right else {
|
||||
panic!("{}", arg_err_message);
|
||||
};
|
||||
let syn::Lit::Str(expectation) = s.lit else {
|
||||
panic!("{}", arg_err_message);
|
||||
};
|
||||
(true, Some(expectation))
|
||||
}
|
||||
_ => (true, None),
|
||||
}
|
||||
}
|
||||
None => (false, None),
|
||||
};
|
||||
let expectation_tokens = if let Some(s) = expectation {
|
||||
quote! {
|
||||
Some(#s)
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let package_name = std::env::var("CARGO_PKG_NAME").unwrap();
|
||||
let span = proc_macro::Span::call_site();
|
||||
let source = span.source_file().path();
|
||||
let source = source.to_str().unwrap();
|
||||
let line = span.line();
|
||||
let col = span.column();
|
||||
|
||||
let register_ktest_item = if package_name.as_str() == "ostd" {
|
||||
quote! {
|
||||
#[cfg(ktest)]
|
||||
#[used]
|
||||
#[link_section = ".ktest_array"]
|
||||
static #fn_ktest_item_name: ktest::KtestItem = ktest::KtestItem::new(
|
||||
#fn_name,
|
||||
(#should_panic, #expectation_tokens),
|
||||
ktest::KtestItemInfo {
|
||||
module_path: module_path!(),
|
||||
fn_name: stringify!(#fn_name),
|
||||
package: #package_name,
|
||||
source: #source,
|
||||
line: #line,
|
||||
col: #col,
|
||||
},
|
||||
);
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
#[cfg(ktest)]
|
||||
#[used]
|
||||
#[link_section = ".ktest_array"]
|
||||
static #fn_ktest_item_name: ostd::ktest::KtestItem = ostd::ktest::KtestItem::new(
|
||||
#fn_name,
|
||||
(#should_panic, #expectation_tokens),
|
||||
ostd::ktest::KtestItemInfo {
|
||||
module_path: module_path!(),
|
||||
fn_name: stringify!(#fn_name),
|
||||
package: #package_name,
|
||||
source: #source,
|
||||
line: #line,
|
||||
col: #col,
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
let output = quote! {
|
||||
#input
|
||||
|
||||
#register_ktest_item
|
||||
};
|
||||
|
||||
TokenStream::from(output)
|
||||
}
|
||||
|
@ -22,9 +22,6 @@
|
||||
#![warn(missing_docs)]
|
||||
|
||||
extern crate alloc;
|
||||
#[cfg(ktest)]
|
||||
#[macro_use]
|
||||
extern crate ktest;
|
||||
extern crate static_assertions;
|
||||
|
||||
pub mod arch;
|
||||
@ -109,6 +106,8 @@ fn invoke_ffi_init_funcs() {
|
||||
/// Simple unit tests for the ktest framework.
|
||||
#[cfg(ktest)]
|
||||
mod test {
|
||||
use crate::prelude::*;
|
||||
|
||||
#[ktest]
|
||||
fn trivial_assertion() {
|
||||
assert_eq!(0, 0);
|
||||
@ -126,3 +125,9 @@ mod test {
|
||||
panic!("expected panic message");
|
||||
}
|
||||
}
|
||||
|
||||
/// The module re-exports everything from the ktest crate
|
||||
#[cfg(ktest)]
|
||||
pub mod ktest {
|
||||
pub use ktest::*;
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ mod test {
|
||||
use alloc::vec;
|
||||
|
||||
use super::*;
|
||||
use crate::mm::FrameAllocOptions;
|
||||
use crate::{mm::FrameAllocOptions, prelude::*};
|
||||
|
||||
#[ktest]
|
||||
fn map_with_coherent_device() {
|
||||
|
@ -310,7 +310,7 @@ mod test {
|
||||
use alloc::vec;
|
||||
|
||||
use super::*;
|
||||
use crate::mm::FrameAllocOptions;
|
||||
use crate::{mm::FrameAllocOptions, prelude::*};
|
||||
|
||||
#[ktest]
|
||||
fn streaming_map() {
|
||||
|
@ -161,6 +161,9 @@ impl<E: PageTableEntryTrait, C: PagingConstsTrait> Drop for BootPageTable<E, C>
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ktest)]
|
||||
use crate::prelude::*;
|
||||
|
||||
#[cfg(ktest)]
|
||||
#[ktest]
|
||||
fn test_boot_pt_map_protect() {
|
||||
|
@ -3,10 +3,13 @@
|
||||
use core::mem::ManuallyDrop;
|
||||
|
||||
use super::*;
|
||||
use crate::mm::{
|
||||
kspace::LINEAR_MAPPING_BASE_VADDR,
|
||||
page::{allocator, meta::FrameMeta},
|
||||
page_prop::{CachePolicy, PageFlags},
|
||||
use crate::{
|
||||
mm::{
|
||||
kspace::LINEAR_MAPPING_BASE_VADDR,
|
||||
page::{allocator, meta::FrameMeta},
|
||||
page_prop::{CachePolicy, PageFlags},
|
||||
},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
const PAGE_SIZE: usize = 4096;
|
||||
|
@ -10,6 +10,9 @@ pub type Result<T> = core::result::Result<T, crate::error::Error>;
|
||||
pub(crate) use alloc::{boxed::Box, sync::Arc, vec::Vec};
|
||||
pub(crate) use core::any::Any;
|
||||
|
||||
#[cfg(ktest)]
|
||||
pub use ostd_macros::ktest;
|
||||
|
||||
pub use crate::{
|
||||
early_print as print, early_println as println,
|
||||
mm::{Paddr, Vaddr},
|
||||
|
@ -293,6 +293,7 @@ impl fmt::Debug for AtomicBits {
|
||||
#[cfg(ktest)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[ktest]
|
||||
fn new() {
|
||||
|
@ -298,7 +298,7 @@ impl Waker {
|
||||
#[cfg(ktest)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::task::TaskOptions;
|
||||
use crate::{prelude::*, task::TaskOptions};
|
||||
|
||||
fn queue_wake<F>(wake: F)
|
||||
where
|
||||
|
@ -332,6 +332,8 @@ impl TaskOptions {
|
||||
|
||||
#[cfg(ktest)]
|
||||
mod test {
|
||||
use crate::prelude::*;
|
||||
|
||||
#[ktest]
|
||||
fn create_task() {
|
||||
let task = || {
|
||||
|
Reference in New Issue
Block a user