mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 08:53:29 +00:00
Add ktest framework
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
d7cc52c615
commit
b8818bb740
@ -6,7 +6,6 @@ runner = "cargo run --package jinux-runner --"
|
|||||||
kcheck = "check --target x86_64-custom.json -Zbuild-std=core,alloc,compiler_builtins -Zbuild-std-features=compiler-builtins-mem"
|
kcheck = "check --target x86_64-custom.json -Zbuild-std=core,alloc,compiler_builtins -Zbuild-std-features=compiler-builtins-mem"
|
||||||
kbuild = "build --target x86_64-custom.json -Zbuild-std=core,alloc,compiler_builtins -Zbuild-std-features=compiler-builtins-mem"
|
kbuild = "build --target x86_64-custom.json -Zbuild-std=core,alloc,compiler_builtins -Zbuild-std-features=compiler-builtins-mem"
|
||||||
krun = "run --target x86_64-custom.json -Zbuild-std=core,alloc,compiler_builtins -Zbuild-std-features=compiler-builtins-mem"
|
krun = "run --target x86_64-custom.json -Zbuild-std=core,alloc,compiler_builtins -Zbuild-std-features=compiler-builtins-mem"
|
||||||
ktest = "test --target x86_64-custom.json -Zbuild-std=core,alloc,compiler_builtins -Zbuild-std-features=compiler-builtins-mem"
|
|
||||||
kclippy = "clippy --target x86_64-custom.json -Zbuild-std=core,alloc,compiler_builtins -Zbuild-std-features=compiler-builtins-mem"
|
kclippy = "clippy --target x86_64-custom.json -Zbuild-std=core,alloc,compiler_builtins -Zbuild-std-features=compiler-builtins-mem"
|
||||||
component-check = "component check --target x86_64-custom.json -Zbuild-std=core,alloc,compiler_builtins -Zbuild-std-features=compiler-builtins-mem"
|
component-check = "component check --target x86_64-custom.json -Zbuild-std=core,alloc,compiler_builtins -Zbuild-std-features=compiler-builtins-mem"
|
||||||
|
|
||||||
|
1
.github/workflows/cargo_check.yml
vendored
1
.github/workflows/cargo_check.yml
vendored
@ -5,7 +5,6 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- releases/*
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
|
25
.github/workflows/unit_test.yml
vendored
Normal file
25
.github/workflows/unit_test.yml
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
name: Unit test
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 15
|
||||||
|
container: jinuxdev/jinux:0.2.1
|
||||||
|
steps:
|
||||||
|
- run: echo "Running in jinuxdev/jinux:0.2.1"
|
||||||
|
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Ktest Unit Test
|
||||||
|
id: ktest_unit_test
|
||||||
|
run: make run KTEST=all ENABLE_KVM=0 RELEASE_MODE=1
|
||||||
|
|
||||||
|
# TODO: include the unit tests for the crates that supports cargo test.
|
||||||
|
|
||||||
|
# TODO: add component check.
|
34
Cargo.lock
generated
34
Cargo.lock
generated
@ -216,7 +216,7 @@ dependencies = [
|
|||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.28",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -368,7 +368,7 @@ dependencies = [
|
|||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.28",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -475,7 +475,7 @@ checksum = "ba330b70a5341d3bc730b8e205aaee97ddab5d9c448c4f51a7c2d924266fa8f9"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.28",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -567,7 +567,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.28",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -637,6 +637,7 @@ dependencies = [
|
|||||||
"inherit-methods-macro",
|
"inherit-methods-macro",
|
||||||
"int-to-c-enum",
|
"int-to-c-enum",
|
||||||
"intrusive-collections",
|
"intrusive-collections",
|
||||||
|
"ktest",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"multiboot2",
|
"multiboot2",
|
||||||
@ -757,6 +758,7 @@ dependencies = [
|
|||||||
"jinux-util",
|
"jinux-util",
|
||||||
"jinux-virtio",
|
"jinux-virtio",
|
||||||
"keyable-arc",
|
"keyable-arc",
|
||||||
|
"ktest",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"lending-iterator",
|
"lending-iterator",
|
||||||
"libflate",
|
"libflate",
|
||||||
@ -830,6 +832,16 @@ checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd"
|
|||||||
name = "keyable-arc"
|
name = "keyable-arc"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ktest"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rand",
|
||||||
|
"syn 2.0.38",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@ -1061,9 +1073,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.66"
|
version = "1.0.69"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
|
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@ -1090,9 +1102,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.32"
|
version = "1.0.33"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
|
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@ -1278,9 +1290,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.28"
|
version = "2.0.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
|
checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1320,7 +1332,7 @@ checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.28",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
16
Makefile
16
Makefile
@ -8,6 +8,7 @@ ENABLE_KVM ?= 1
|
|||||||
GDB_CLIENT ?= 0
|
GDB_CLIENT ?= 0
|
||||||
GDB_SERVER ?= 0
|
GDB_SERVER ?= 0
|
||||||
INTEL_TDX ?= 0
|
INTEL_TDX ?= 0
|
||||||
|
KTEST ?= none
|
||||||
SKIP_GRUB_MENU ?= 1
|
SKIP_GRUB_MENU ?= 1
|
||||||
RELEASE_MODE ?= 0
|
RELEASE_MODE ?= 0
|
||||||
# End of setting up Make varaiables
|
# End of setting up Make varaiables
|
||||||
@ -22,8 +23,8 @@ KERNEL_CMDLINE += -c exit 0
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
CARGO_KBUILD_ARGS :=
|
CARGO_KBUILD_ARGS :=
|
||||||
|
|
||||||
CARGO_KRUN_ARGS :=
|
CARGO_KRUN_ARGS :=
|
||||||
|
GLOBAL_RUSTC_FLAGS :=
|
||||||
|
|
||||||
ifeq ($(RELEASE_MODE), 1)
|
ifeq ($(RELEASE_MODE), 1)
|
||||||
CARGO_KBUILD_ARGS += --release
|
CARGO_KBUILD_ARGS += --release
|
||||||
@ -60,6 +61,11 @@ CARGO_KBUILD_ARGS += --features intel_tdx
|
|||||||
CARGO_KRUN_ARGS += --features intel_tdx
|
CARGO_KRUN_ARGS += --features intel_tdx
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq ($(KTEST), none)
|
||||||
|
comma := ,
|
||||||
|
GLOBAL_RUSTC_FLAGS += --cfg ktest --cfg ktest=\"$(subst $(comma),\" --cfg ktest=\",$(KTEST))\"
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(SKIP_GRUB_MENU), 1)
|
ifeq ($(SKIP_GRUB_MENU), 1)
|
||||||
CARGO_KRUN_ARGS += --skip-grub-menu
|
CARGO_KRUN_ARGS += --skip-grub-menu
|
||||||
endif
|
endif
|
||||||
@ -82,16 +88,16 @@ setup:
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
@make --no-print-directory -C regression
|
@make --no-print-directory -C regression
|
||||||
@cargo kbuild $(CARGO_KBUILD_ARGS)
|
@RUSTFLAGS="$(GLOBAL_RUSTC_FLAGS)" cargo kbuild $(CARGO_KBUILD_ARGS)
|
||||||
|
|
||||||
tools:
|
tools:
|
||||||
@cd services/libs/comp-sys && cargo install --path cargo-component
|
@cd services/libs/comp-sys && cargo install --path cargo-component
|
||||||
|
|
||||||
run: build
|
run: build
|
||||||
@cargo krun $(CARGO_KRUN_ARGS)
|
@RUSTFLAGS="$(GLOBAL_RUSTC_FLAGS)" cargo krun $(CARGO_KRUN_ARGS)
|
||||||
|
|
||||||
test: build
|
test:
|
||||||
@cargo ktest
|
@python3 ./tools/test/run_tests.py
|
||||||
|
|
||||||
docs:
|
docs:
|
||||||
@cargo doc # Build Rust docs
|
@cargo doc # Build Rust docs
|
||||||
|
13
README.md
13
README.md
@ -56,11 +56,16 @@ make build
|
|||||||
make run
|
make run
|
||||||
```
|
```
|
||||||
|
|
||||||
### Test
|
### Unit Test
|
||||||
|
|
||||||
We can run unit tests and integration tests if building succeeds.
|
We can run unit tests if building succeeds. This is powered by our [ktest](framework/libs/ktest) framework.
|
||||||
```bash
|
```bash
|
||||||
make test
|
make run KTEST=all
|
||||||
|
```
|
||||||
|
|
||||||
|
You could also specify tests in a crate or a subset of tests to run, as long as you defined them well using cfg.
|
||||||
|
```bash
|
||||||
|
make run KTEST=jinux-frame,jinux-std
|
||||||
```
|
```
|
||||||
|
|
||||||
If we want to check access control policy among components, install some standalone tools (e.g., `cargo-component`).
|
If we want to check access control policy among components, install some standalone tools (e.g., `cargo-component`).
|
||||||
@ -73,7 +78,7 @@ Then we can use the tool to check access control policy.
|
|||||||
cargo component-check
|
cargo component-check
|
||||||
```
|
```
|
||||||
|
|
||||||
### Syscall Test
|
### Integration Test
|
||||||
|
|
||||||
This command will build the syscall test binary and automatically run Jinux with the tests using QEMU.
|
This command will build the syscall test binary and automatically run Jinux with the tests using QEMU.
|
||||||
```bash
|
```bash
|
||||||
|
@ -13,6 +13,7 @@ volatile = { version = "0.4.5", features = ["unstable"] }
|
|||||||
buddy_system_allocator = "0.9.0"
|
buddy_system_allocator = "0.9.0"
|
||||||
pod = { git = "https://github.com/jinzhao-dev/pod", rev = "d7dba56" }
|
pod = { git = "https://github.com/jinzhao-dev/pod", rev = "d7dba56" }
|
||||||
align_ext = { path = "../libs/align_ext" }
|
align_ext = { path = "../libs/align_ext" }
|
||||||
|
ktest = { path = "../libs/ktest" }
|
||||||
intrusive-collections = "0.9.5"
|
intrusive-collections = "0.9.5"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
lazy_static = { version = "1.0", features = ["spin_no_std"] }
|
lazy_static = { version = "1.0", features = ["spin_no_std"] }
|
||||||
|
@ -24,24 +24,6 @@ SECTIONS
|
|||||||
.text : AT(ADDR(.text) - KERNEL_VMA) { *(.text .text.*) }
|
.text : AT(ADDR(.text) - KERNEL_VMA) { *(.text .text.*) }
|
||||||
.rodata : AT(ADDR(.rodata) - KERNEL_VMA) { *(.rodata .rodata.*) }
|
.rodata : AT(ADDR(.rodata) - KERNEL_VMA) { *(.rodata .rodata.*) }
|
||||||
|
|
||||||
.data : AT(ADDR(.data) - KERNEL_VMA) { *(.data .data.*) }
|
|
||||||
.bss : AT(ADDR(.bss) - KERNEL_VMA) {
|
|
||||||
__bss = .;
|
|
||||||
*(.bss .bss.*) *(COMMON)
|
|
||||||
__bss_end = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tdata : AT(ADDR(.tdata) - KERNEL_VMA) { *(.tdata .tdata.*) }
|
|
||||||
.tbss : AT(ADDR(.tbss) - KERNEL_VMA) { *(.tbss .tbss.*) }
|
|
||||||
|
|
||||||
.init_array : AT(ADDR(.init_array) - KERNEL_VMA) {
|
|
||||||
__sinit_array = .;
|
|
||||||
*(.init_array .init_array.*)
|
|
||||||
__einit_array = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data.rel.ro : AT(ADDR(.data.rel.ro) - KERNEL_VMA) { *(.data.rel.ro .data.rel.ro.*) }
|
|
||||||
.dynamic : AT(ADDR(.dynamic) - KERNEL_VMA) { *(.dynamic) }
|
|
||||||
.eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - KERNEL_VMA) {
|
.eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - KERNEL_VMA) {
|
||||||
__eh_frame_hdr = .;
|
__eh_frame_hdr = .;
|
||||||
KEEP(*(.eh_frame_hdr))
|
KEEP(*(.eh_frame_hdr))
|
||||||
@ -53,8 +35,37 @@ SECTIONS
|
|||||||
__eh_frame_end = .;
|
__eh_frame_end = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
# The notes section are used to mark the PVH boot entry point, useful for QEMU and Xen
|
.data.rel.ro : AT(ADDR(.data.rel.ro) - KERNEL_VMA) { *(.data.rel.ro .data.rel.ro.*) }
|
||||||
.notes : { *(.notes) }
|
.dynamic : AT(ADDR(.dynamic) - KERNEL_VMA) { *(.dynamic) }
|
||||||
|
|
||||||
|
.init_array : AT(ADDR(.init_array) - KERNEL_VMA) {
|
||||||
|
__sinit_array = .;
|
||||||
|
KEEP(*(SORT(.init_array .init_array.*)))
|
||||||
|
__einit_array = .;
|
||||||
|
}
|
||||||
|
|
||||||
|
.got : AT(ADDR(.got) - KERNEL_VMA) { *(.got .got.*) }
|
||||||
|
.got.plt : AT(ADDR(.got.plt) - KERNEL_VMA) { *(.got.plt .got.plt.*) }
|
||||||
|
|
||||||
|
. = DATA_SEGMENT_RELRO_END(0, .);
|
||||||
|
|
||||||
|
.data : AT(ADDR(.data) - KERNEL_VMA) { *(.data .data.*) }
|
||||||
|
.bss : AT(ADDR(.bss) - KERNEL_VMA) {
|
||||||
|
__bss = .;
|
||||||
|
*(.bss .bss.*) *(COMMON)
|
||||||
|
__bss_end = .;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ktest_array : AT(ADDR(.ktest_array) - KERNEL_VMA) {
|
||||||
|
__ktest_array = .;
|
||||||
|
KEEP(*(SORT(.ktest_array)))
|
||||||
|
__ktest_array_end = .;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tdata : AT(ADDR(.tdata) - KERNEL_VMA) { *(.tdata .tdata.*) }
|
||||||
|
.tbss : AT(ADDR(.tbss) - KERNEL_VMA) { *(.tbss .tbss.*) }
|
||||||
|
|
||||||
|
. = DATA_SEGMENT_END(.);
|
||||||
|
|
||||||
__kernel_end = . - KERNEL_VMA;
|
__kernel_end = . - KERNEL_VMA;
|
||||||
}
|
}
|
@ -124,12 +124,6 @@ fn init_memory_regions(memory_regions: &'static Once<Vec<MemoryRegion>>) {
|
|||||||
memory_regions.call_once(|| regions);
|
memory_regions.call_once(|| regions);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The entry point of kernel code, which should be defined by the package that
|
|
||||||
// uses jinux-frame.
|
|
||||||
extern "Rust" {
|
|
||||||
fn jinux_main() -> !;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The entry point of Rust code called by the Linux 64-bit boot compatible bootloader.
|
/// The entry point of Rust code called by the Linux 64-bit boot compatible bootloader.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "sysv64" fn __linux64_boot(params_ptr: *const boot_params::BootParams) -> ! {
|
unsafe extern "sysv64" fn __linux64_boot(params_ptr: *const boot_params::BootParams) -> ! {
|
||||||
@ -144,5 +138,5 @@ unsafe extern "sysv64" fn __linux64_boot(params_ptr: *const boot_params::BootPar
|
|||||||
init_framebuffer_info,
|
init_framebuffer_info,
|
||||||
init_memory_regions,
|
init_memory_regions,
|
||||||
);
|
);
|
||||||
jinux_main();
|
crate::boot::call_jinux_main();
|
||||||
}
|
}
|
||||||
|
@ -332,12 +332,6 @@ struct MemoryEntry {
|
|||||||
memory_type: MemoryAreaType,
|
memory_type: MemoryAreaType,
|
||||||
}
|
}
|
||||||
|
|
||||||
// The entry point of kernel code, which should be defined by the package that
|
|
||||||
// uses jinux-frame.
|
|
||||||
extern "Rust" {
|
|
||||||
fn jinux_main() -> !;
|
|
||||||
}
|
|
||||||
|
|
||||||
static MB1_INFO: Once<&'static MultibootLegacyInfo> = Once::new();
|
static MB1_INFO: Once<&'static MultibootLegacyInfo> = Once::new();
|
||||||
|
|
||||||
/// The entry point of Rust code called by inline asm.
|
/// The entry point of Rust code called by inline asm.
|
||||||
@ -353,5 +347,5 @@ unsafe extern "sysv64" fn __multiboot_entry(boot_magic: u32, boot_params: u64) -
|
|||||||
init_framebuffer_info,
|
init_framebuffer_info,
|
||||||
init_memory_regions,
|
init_memory_regions,
|
||||||
);
|
);
|
||||||
jinux_main();
|
crate::boot::call_jinux_main();
|
||||||
}
|
}
|
||||||
|
@ -163,12 +163,6 @@ fn init_memory_regions(memory_regions: &'static Once<Vec<MemoryRegion>>) {
|
|||||||
memory_regions.call_once(move || non_overlapping_regions_from(regions.as_ref()));
|
memory_regions.call_once(move || non_overlapping_regions_from(regions.as_ref()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// The entry point of kernel code, which should be defined by the package that
|
|
||||||
// uses jinux-frame.
|
|
||||||
extern "Rust" {
|
|
||||||
fn jinux_main() -> !;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The entry point of Rust code called by inline asm.
|
/// The entry point of Rust code called by inline asm.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "sysv64" fn __multiboot2_entry(boot_magic: u32, boot_params: u64) -> ! {
|
unsafe extern "sysv64" fn __multiboot2_entry(boot_magic: u32, boot_params: u64) -> ! {
|
||||||
@ -184,5 +178,5 @@ unsafe extern "sysv64" fn __multiboot2_entry(boot_magic: u32, boot_params: u64)
|
|||||||
init_framebuffer_info,
|
init_framebuffer_info,
|
||||||
init_memory_regions,
|
init_memory_regions,
|
||||||
);
|
);
|
||||||
jinux_main();
|
crate::boot::call_jinux_main();
|
||||||
}
|
}
|
||||||
|
@ -99,3 +99,24 @@ define_global_static_boot_arguments!(
|
|||||||
pub fn init() {
|
pub fn init() {
|
||||||
call_all_boot_init_callbacks();
|
call_all_boot_init_callbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Call the framework-user defined entrypoint of the actual kernel.
|
||||||
|
///
|
||||||
|
/// Any kernel that uses the jinux-frame crate should define a function named
|
||||||
|
/// `jinux_main` as the entrypoint.
|
||||||
|
pub fn call_jinux_main() -> ! {
|
||||||
|
#[cfg(not(ktest))]
|
||||||
|
unsafe {
|
||||||
|
// The entry point of kernel code, which should be defined by the package that
|
||||||
|
// uses jinux-frame.
|
||||||
|
extern "Rust" {
|
||||||
|
fn jinux_main() -> !;
|
||||||
|
}
|
||||||
|
jinux_main();
|
||||||
|
}
|
||||||
|
#[cfg(ktest)]
|
||||||
|
{
|
||||||
|
crate::init();
|
||||||
|
ktest::do_ktests!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
extern crate ktest;
|
||||||
|
#[macro_use]
|
||||||
extern crate static_assertions;
|
extern crate static_assertions;
|
||||||
|
|
||||||
pub mod arch;
|
pub mod arch;
|
||||||
@ -44,7 +46,7 @@ pub use self::error::Error;
|
|||||||
pub use self::prelude::Result;
|
pub use self::prelude::Result;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use arch::irq::{IrqCallbackHandle, IrqLine};
|
use arch::irq::{IrqCallbackHandle, IrqLine};
|
||||||
use core::{mem, panic::PanicInfo};
|
use core::mem;
|
||||||
#[cfg(feature = "intel_tdx")]
|
#[cfg(feature = "intel_tdx")]
|
||||||
use tdx_guest::init_tdx;
|
use tdx_guest::init_tdx;
|
||||||
use trapframe::TrapFrame;
|
use trapframe::TrapFrame;
|
||||||
@ -108,35 +110,6 @@ pub(crate) const fn zero<T>() -> T {
|
|||||||
unsafe { mem::MaybeUninit::zeroed().assume_init() }
|
unsafe { mem::MaybeUninit::zeroed().assume_init() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Testable {
|
|
||||||
fn run(&self);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Testable for T
|
|
||||||
where
|
|
||||||
T: Fn(),
|
|
||||||
{
|
|
||||||
fn run(&self) {
|
|
||||||
print!("{}...\n", core::any::type_name::<T>());
|
|
||||||
self();
|
|
||||||
println!("[ok]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn test_runner(tests: &[&dyn Testable]) {
|
|
||||||
println!("Running {} tests", tests.len());
|
|
||||||
for test in tests {
|
|
||||||
test.run();
|
|
||||||
}
|
|
||||||
exit_qemu(QemuExitCode::Success);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn test_panic_handler(info: &PanicInfo) -> ! {
|
|
||||||
println!("[failed]");
|
|
||||||
println!("Error: {}", info);
|
|
||||||
exit_qemu(QemuExitCode::Failed);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn panic_handler() {
|
pub fn panic_handler() {
|
||||||
// let mut fp: usize;
|
// let mut fp: usize;
|
||||||
// let stop = unsafe{
|
// let stop = unsafe{
|
||||||
@ -181,3 +154,11 @@ pub fn exit_qemu(exit_code: QemuExitCode) -> ! {
|
|||||||
}
|
}
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[if_cfg_ktest]
|
||||||
|
mod test {
|
||||||
|
#[ktest]
|
||||||
|
fn trivial_assertion() {
|
||||||
|
assert_eq!(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -284,11 +284,11 @@ impl fmt::Debug for AtomicBits {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[if_cfg_ktest]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[ktest]
|
||||||
fn new() {
|
fn new() {
|
||||||
let bits = AtomicBits::new_zeroes(1);
|
let bits = AtomicBits::new_zeroes(1);
|
||||||
assert!(bits.len() == 1);
|
assert!(bits.len() == 1);
|
||||||
@ -303,7 +303,7 @@ mod test {
|
|||||||
assert!(bits.len() == 65);
|
assert!(bits.len() == 65);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[ktest]
|
||||||
fn set_get() {
|
fn set_get() {
|
||||||
let bits = AtomicBits::new_zeroes(128);
|
let bits = AtomicBits::new_zeroes(128);
|
||||||
for i in 0..bits.len() {
|
for i in 0..bits.len() {
|
||||||
@ -328,7 +328,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[ktest]
|
||||||
fn iter_ones() {
|
fn iter_ones() {
|
||||||
let bits = AtomicBits::new_zeroes(1);
|
let bits = AtomicBits::new_zeroes(1);
|
||||||
assert!(bits.iter_ones().count() == 0);
|
assert!(bits.iter_ones().count() == 0);
|
||||||
@ -353,7 +353,7 @@ mod test {
|
|||||||
assert!(bits.iter_ones().count() == 3);
|
assert!(bits.iter_ones().count() == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[ktest]
|
||||||
fn iter_zeroes() {
|
fn iter_zeroes() {
|
||||||
let bits = AtomicBits::new_ones(1);
|
let bits = AtomicBits::new_ones(1);
|
||||||
assert!(bits.iter_zeroes().count() == 0);
|
assert!(bits.iter_zeroes().count() == 0);
|
||||||
@ -380,7 +380,7 @@ mod test {
|
|||||||
assert!(bits.iter_zeroes().count() == 5);
|
assert!(bits.iter_zeroes().count() == 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[ktest]
|
||||||
fn iter() {
|
fn iter() {
|
||||||
let bits = AtomicBits::new_zeroes(7);
|
let bits = AtomicBits::new_zeroes(7);
|
||||||
assert!(bits.iter().all(|bit| bit == false));
|
assert!(bits.iter().all(|bit| bit == false));
|
||||||
|
15
framework/libs/ktest/Cargo.toml
Normal file
15
framework/libs/ktest/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
[package]
|
||||||
|
name = "ktest"
|
||||||
|
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"] }
|
192
framework/libs/ktest/src/lib.rs
Normal file
192
framework/libs/ktest/src/lib.rs
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
//! # The kernel mode testing framework of Jinux.
|
||||||
|
//!
|
||||||
|
//! `ktest` stands for kernel-mode testing framework. Its goal is to provide a
|
||||||
|
//! `cargo test`-like experience for any crates that depends on jinux-frame.
|
||||||
|
//!
|
||||||
|
//! All the tests written in the source tree of the crates will be run using the
|
||||||
|
//! `do_ktests!()` macro immediately after the initialization of jinux-frame.
|
||||||
|
//! Thus you can use any feature provided by the frame including the heap
|
||||||
|
//! allocator, etc.
|
||||||
|
//!
|
||||||
|
//! ## Usage
|
||||||
|
//!
|
||||||
|
//! To write a unit test for any crates, it is recommended to create a new test
|
||||||
|
//! module, e.g.:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use ktest::{ktest, if_cfg_ktest};
|
||||||
|
//! #[if_cfg_ktest]
|
||||||
|
//! mod test {
|
||||||
|
//! #[ktest]
|
||||||
|
//! fn trivial_assertion() {
|
||||||
|
//! assert_eq!(0, 0);
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! And also, any crates using the ktest framework should be linked with jinux-frame
|
||||||
|
//! and import the `ktest` crate:
|
||||||
|
//!
|
||||||
|
//! ```toml
|
||||||
|
//! # Cargo.toml
|
||||||
|
//! [dependencies]
|
||||||
|
//! ktest = { path = "relative/path/to/ktest" }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! By the way, `#[ktest]` attribute along also works, but it hinders test control
|
||||||
|
//! using cfgs since plain attribute marked test will be executed in all test runs
|
||||||
|
//! no matter what cfgs are passed to the compiler. More importantly, using `#[ktest]`
|
||||||
|
//! without cfgs occupies binary real estate since the `.ktest_array` section is not
|
||||||
|
//! explicitly stripped in normal builds.
|
||||||
|
//!
|
||||||
|
//! Rust cfg is used to control the compilation of the test module. In cooperation
|
||||||
|
//! with the `ktest` framework, the Makefile will set the `RUSTFLAGS` environment
|
||||||
|
//! variable to pass the cfgs to all rustc invocations. To run the tests, you need
|
||||||
|
//! to pass a list of cfgs to the Makefile, e.g.:
|
||||||
|
//!
|
||||||
|
//! ```bash
|
||||||
|
//! make run KTEST=jinux-frame,jinux-std,align_ext,tdx-guest
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! It is flexible to specify the cfgs for running the tests. The cfg value is not
|
||||||
|
//! limited to crate names, enabling your imagination to configure running any subsets
|
||||||
|
//! of tests in any crates. And to ease development, `#[if_cfg_ktest]` is expanded to
|
||||||
|
//! a default conditional compilation setting:
|
||||||
|
//! `#[cfg(all(ktest, any(ktest = "all", ktest = #crate_name)))]`
|
||||||
|
//!
|
||||||
|
//! Currently we do not support `#[should_panic]` attribute, and this feature will
|
||||||
|
//! be added in the future.
|
||||||
|
//!
|
||||||
|
//! Doctest is not taken into consideration yet, and the interface is subject to
|
||||||
|
//! change.
|
||||||
|
//!
|
||||||
|
//! ## How it works
|
||||||
|
//!
|
||||||
|
//! The `ktest` framework is implemented using the procedural macro feature of Rust.
|
||||||
|
//! The `ktest` attribute macro will generate a static fn pointer variable linked in
|
||||||
|
//! the `.ktest_array` section. The `do_ktests!()` macro will iterate over all the
|
||||||
|
//! static variables in the section and run the tests.
|
||||||
|
//!
|
||||||
|
|
||||||
|
#![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, Ident, ItemFn, ItemMod};
|
||||||
|
|
||||||
|
/// The conditional compilation attribute macro to control the compilation of test
|
||||||
|
/// modules.
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn if_cfg_ktest(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
// Assuming that the item is a module declearation, otherwise panics.
|
||||||
|
let input = parse_macro_input!(item as ItemMod);
|
||||||
|
|
||||||
|
let crate_name = std::env::var("CARGO_PKG_NAME").unwrap();
|
||||||
|
|
||||||
|
let output = quote! {
|
||||||
|
#[cfg(all(ktest, any(ktest = "all", ktest = #crate_name)))]
|
||||||
|
#input
|
||||||
|
};
|
||||||
|
|
||||||
|
TokenStream::from(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Since Rust does not support unamed structures, we have to generate a
|
||||||
|
// unique name for each test item structure.
|
||||||
|
let ktest_item_struct = Ident::new(
|
||||||
|
&format!("KtestItem{}", &fn_id),
|
||||||
|
proc_macro2::Span::call_site(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let span = proc_macro::Span::call_site();
|
||||||
|
let source = span.source_file();
|
||||||
|
let crate_name = std::env::var("CARGO_PKG_NAME").unwrap();
|
||||||
|
let hint_str = format!(
|
||||||
|
"[{}] {}: {}()",
|
||||||
|
crate_name,
|
||||||
|
source.path().to_str().unwrap(),
|
||||||
|
fn_name
|
||||||
|
);
|
||||||
|
|
||||||
|
let register = quote! {
|
||||||
|
struct #ktest_item_struct {
|
||||||
|
fn_: fn() -> (),
|
||||||
|
hint: &'static str,
|
||||||
|
}
|
||||||
|
#[cfg(ktest)]
|
||||||
|
#[used]
|
||||||
|
#[link_section = ".ktest_array"]
|
||||||
|
static #fn_ktest_item_name: #ktest_item_struct = #ktest_item_struct {
|
||||||
|
fn_: #fn_name,
|
||||||
|
hint: #hint_str,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
let output = quote! {
|
||||||
|
#input
|
||||||
|
|
||||||
|
#register
|
||||||
|
};
|
||||||
|
|
||||||
|
TokenStream::from(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The procedural macro to run all the tests.
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn do_ktests(_item: TokenStream) -> TokenStream {
|
||||||
|
let body = quote! {
|
||||||
|
struct KtestItem {
|
||||||
|
fn_: fn() -> (),
|
||||||
|
hint: &'static str,
|
||||||
|
};
|
||||||
|
extern "C" {
|
||||||
|
fn __ktest_array();
|
||||||
|
fn __ktest_array_end();
|
||||||
|
}
|
||||||
|
let item_size = core::mem::size_of::<KtestItem>() as u64;
|
||||||
|
let l = (__ktest_array_end as u64 - __ktest_array as u64) / item_size;
|
||||||
|
crate::println!("Running {} tests", l);
|
||||||
|
for i in 0..l {
|
||||||
|
unsafe {
|
||||||
|
let address = (__ktest_array as u64 + item_size * i) as *const u64;
|
||||||
|
let item = address as *const KtestItem;
|
||||||
|
crate::print!("{} ...", (*item).hint);
|
||||||
|
((*item).fn_)();
|
||||||
|
}
|
||||||
|
crate::println!(" Ok!");
|
||||||
|
}
|
||||||
|
crate::exit_qemu(crate::QemuExitCode::Success);
|
||||||
|
};
|
||||||
|
|
||||||
|
TokenStream::from(body)
|
||||||
|
}
|
@ -1,11 +1,8 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(custom_test_frameworks)]
|
|
||||||
// The no_mangle macro need to remove the `forbid(unsafe_code)` macro. The bootloader needs the _start function
|
// The no_mangle macro need to remove the `forbid(unsafe_code)` macro. The bootloader needs the _start function
|
||||||
// to be no mangle so that it can jump into the entry point.
|
// to be no mangle so that it can jump into the entry point.
|
||||||
// #![forbid(unsafe_code)]
|
// #![forbid(unsafe_code)]
|
||||||
#![test_runner(jinux_frame::test_runner)]
|
|
||||||
#![reexport_test_harness_main = "test_main"]
|
|
||||||
extern crate jinux_frame;
|
extern crate jinux_frame;
|
||||||
|
|
||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
@ -13,8 +10,6 @@ use jinux_frame::println;
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn jinux_main() -> ! {
|
pub fn jinux_main() -> ! {
|
||||||
#[cfg(test)]
|
|
||||||
test_main();
|
|
||||||
jinux_frame::init();
|
jinux_frame::init();
|
||||||
println!("[kernel] finish init jinux_frame");
|
println!("[kernel] finish init jinux_frame");
|
||||||
component::init_all(component::parse_metadata!()).unwrap();
|
component::init_all(component::parse_metadata!()).unwrap();
|
||||||
@ -22,7 +17,6 @@ pub fn jinux_main() -> ! {
|
|||||||
jinux_std::run_first_process();
|
jinux_std::run_first_process();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(test))]
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(info: &PanicInfo) -> ! {
|
fn panic(info: &PanicInfo) -> ! {
|
||||||
use jinux_frame::{exit_qemu, QemuExitCode};
|
use jinux_frame::{exit_qemu, QemuExitCode};
|
||||||
@ -31,14 +25,3 @@ fn panic(info: &PanicInfo) -> ! {
|
|||||||
jinux_frame::panic_handler();
|
jinux_frame::panic_handler();
|
||||||
exit_qemu(QemuExitCode::Failed);
|
exit_qemu(QemuExitCode::Failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
#[panic_handler]
|
|
||||||
fn panic(info: &PanicInfo) -> ! {
|
|
||||||
jinux_frame::test_panic_handler(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test_case]
|
|
||||||
fn trivial_assertion() {
|
|
||||||
assert_eq!(1, 1);
|
|
||||||
}
|
|
||||||
|
@ -35,9 +35,7 @@ pub(crate) fn init() {
|
|||||||
let page_size = size / PAGE_SIZE;
|
let page_size = size / PAGE_SIZE;
|
||||||
|
|
||||||
let start_paddr = framebuffer.address;
|
let start_paddr = framebuffer.address;
|
||||||
let io_mem =
|
let io_mem = todo!("IoMem is private for components now, should fix it.");
|
||||||
IoMem::new(start_paddr..(start_paddr + jinux_frame::config::PAGE_SIZE * page_size))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut buffer: Vec<u8> = Vec::with_capacity(size);
|
let mut buffer: Vec<u8> = Vec::with_capacity(size);
|
||||||
for _ in 0..size {
|
for _ in 0..size {
|
||||||
|
@ -40,6 +40,7 @@ smoltcp = { version = "0.9.1", default-features = false, features = [
|
|||||||
"socket-raw",
|
"socket-raw",
|
||||||
"socket-dhcpv4",
|
"socket-dhcpv4",
|
||||||
] }
|
] }
|
||||||
|
ktest = { path = "../../../framework/libs/ktest" }
|
||||||
tdx-guest = { path = "../../../framework/libs/tdx-guest", optional = true }
|
tdx-guest = { path = "../../../framework/libs/tdx-guest", optional = true }
|
||||||
|
|
||||||
# parse elf file
|
# parse elf file
|
||||||
|
@ -34,6 +34,8 @@ extern crate alloc;
|
|||||||
extern crate lru;
|
extern crate lru;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate controlled;
|
extern crate controlled;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate ktest;
|
||||||
|
|
||||||
pub mod device;
|
pub mod device;
|
||||||
pub mod driver;
|
pub mod driver;
|
||||||
|
@ -132,7 +132,7 @@ impl<R> VmarChildOptions<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[if_cfg_ktest]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::vm::page_fault_handler::PageFaultHandler;
|
use crate::vm::page_fault_handler::PageFaultHandler;
|
||||||
@ -142,13 +142,13 @@ mod test {
|
|||||||
use jinux_frame::vm::VmIo;
|
use jinux_frame::vm::VmIo;
|
||||||
use jinux_rights::Full;
|
use jinux_rights::Full;
|
||||||
|
|
||||||
#[test]
|
#[ktest]
|
||||||
fn root_vmar() {
|
fn root_vmar() {
|
||||||
let vmar = Vmar::<Full>::new_root();
|
let vmar = Vmar::<Full>::new_root();
|
||||||
assert!(vmar.size() == ROOT_VMAR_HIGHEST_ADDR);
|
assert!(vmar.size() == ROOT_VMAR_HIGHEST_ADDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[ktest]
|
||||||
fn child_vmar() {
|
fn child_vmar() {
|
||||||
let root_vmar = Vmar::<Full>::new_root();
|
let root_vmar = Vmar::<Full>::new_root();
|
||||||
let root_vmar_dup = root_vmar.dup().unwrap();
|
let root_vmar_dup = root_vmar.dup().unwrap();
|
||||||
@ -167,7 +167,7 @@ mod test {
|
|||||||
.is_err());
|
.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[ktest]
|
||||||
fn map_vmo() {
|
fn map_vmo() {
|
||||||
let root_vmar = Vmar::<Full>::new_root();
|
let root_vmar = Vmar::<Full>::new_root();
|
||||||
let vmo = VmoOptions::<Full>::new(PAGE_SIZE).alloc().unwrap().to_dyn();
|
let vmo = VmoOptions::<Full>::new(PAGE_SIZE).alloc().unwrap().to_dyn();
|
||||||
@ -193,7 +193,7 @@ mod test {
|
|||||||
assert!(root_vmar.read_val::<u8>(another_map_offset).unwrap() == 100);
|
assert!(root_vmar.read_val::<u8>(another_map_offset).unwrap() == 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[ktest]
|
||||||
fn handle_page_fault() {
|
fn handle_page_fault() {
|
||||||
const OFFSET: usize = 0x1000_0000;
|
const OFFSET: usize = 0x1000_0000;
|
||||||
let root_vmar = Vmar::<Full>::new_root();
|
let root_vmar = Vmar::<Full>::new_root();
|
||||||
|
@ -516,13 +516,13 @@ impl VmoChildType for VmoSliceChild {}
|
|||||||
pub struct VmoCowChild;
|
pub struct VmoCowChild;
|
||||||
impl VmoChildType for VmoCowChild {}
|
impl VmoChildType for VmoCowChild {}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[if_cfg_ktest]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use jinux_frame::vm::VmIo;
|
use jinux_frame::vm::VmIo;
|
||||||
use jinux_rights::Full;
|
use jinux_rights::Full;
|
||||||
|
|
||||||
#[test]
|
#[ktest]
|
||||||
fn alloc_vmo() {
|
fn alloc_vmo() {
|
||||||
let vmo = VmoOptions::<Full>::new(PAGE_SIZE).alloc().unwrap();
|
let vmo = VmoOptions::<Full>::new(PAGE_SIZE).alloc().unwrap();
|
||||||
assert!(vmo.size() == PAGE_SIZE);
|
assert!(vmo.size() == PAGE_SIZE);
|
||||||
@ -530,7 +530,8 @@ mod test {
|
|||||||
assert!(vmo.read_val::<usize>(0).unwrap() == 0);
|
assert!(vmo.read_val::<usize>(0).unwrap() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[ktest]
|
||||||
|
// FIXME: should_panic doesn't work with ktest, two negative makes a positive...
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
/// FIXME: alloc continuous frames is not supported now
|
/// FIXME: alloc continuous frames is not supported now
|
||||||
fn alloc_continuous_vmo() {
|
fn alloc_continuous_vmo() {
|
||||||
@ -541,7 +542,7 @@ mod test {
|
|||||||
assert!(vmo.size() == 10 * PAGE_SIZE);
|
assert!(vmo.size() == 10 * PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[ktest]
|
||||||
fn write_and_read() {
|
fn write_and_read() {
|
||||||
let vmo = VmoOptions::<Full>::new(PAGE_SIZE).alloc().unwrap();
|
let vmo = VmoOptions::<Full>::new(PAGE_SIZE).alloc().unwrap();
|
||||||
let val = 42u8;
|
let val = 42u8;
|
||||||
@ -555,7 +556,7 @@ mod test {
|
|||||||
assert!(read_val == 0x78563412)
|
assert!(read_val == 0x78563412)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[ktest]
|
||||||
fn slice_child() {
|
fn slice_child() {
|
||||||
let parent = VmoOptions::<Full>::new(2 * PAGE_SIZE).alloc().unwrap();
|
let parent = VmoOptions::<Full>::new(2 * PAGE_SIZE).alloc().unwrap();
|
||||||
let parent_dup = parent.dup().unwrap();
|
let parent_dup = parent.dup().unwrap();
|
||||||
@ -570,7 +571,7 @@ mod test {
|
|||||||
assert!(parent.read_val::<u32>(99).unwrap() == 0x1234);
|
assert!(parent.read_val::<u32>(99).unwrap() == 0x1234);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[ktest]
|
||||||
fn cow_child() {
|
fn cow_child() {
|
||||||
let parent = VmoOptions::<Full>::new(2 * PAGE_SIZE).alloc().unwrap();
|
let parent = VmoOptions::<Full>::new(2 * PAGE_SIZE).alloc().unwrap();
|
||||||
let parent_dup = parent.dup().unwrap();
|
let parent_dup = parent.dup().unwrap();
|
||||||
@ -596,7 +597,7 @@ mod test {
|
|||||||
assert!(cow_child.read_val::<u32>(PAGE_SIZE + 10).unwrap() == 12345);
|
assert!(cow_child.read_val::<u32>(PAGE_SIZE + 10).unwrap() == 12345);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[ktest]
|
||||||
fn resize() {
|
fn resize() {
|
||||||
let vmo = VmoOptions::<Full>::new(PAGE_SIZE)
|
let vmo = VmoOptions::<Full>::new(PAGE_SIZE)
|
||||||
.flags(VmoFlags::RESIZABLE)
|
.flags(VmoFlags::RESIZABLE)
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
#![no_std]
|
|
||||||
#![no_main]
|
|
||||||
#![feature(custom_test_frameworks)]
|
|
||||||
#![test_runner(jinux_frame::test_runner)]
|
|
||||||
#![reexport_test_harness_main = "test_main"]
|
|
||||||
extern crate alloc;
|
|
||||||
use core::panic::PanicInfo;
|
|
||||||
use jinux_frame::println;
|
|
||||||
|
|
||||||
static mut INPUT_VALUE: u8 = 0;
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub fn jinux_main() -> ! {
|
|
||||||
jinux_frame::init();
|
|
||||||
test_main();
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[panic_handler]
|
|
||||||
fn panic(info: &PanicInfo) -> ! {
|
|
||||||
jinux_frame::test_panic_handler(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test_case]
|
|
||||||
fn test_input() {
|
|
||||||
x86_64::instructions::interrupts::enable();
|
|
||||||
println!("please input value into console to pass this test");
|
|
||||||
// FIXME: Where is tty?
|
|
||||||
// jinux_std::driver::tty::register_serial_input_callback(input_callback);
|
|
||||||
unsafe {
|
|
||||||
while INPUT_VALUE == 0 {
|
|
||||||
x86_64::instructions::hlt();
|
|
||||||
}
|
|
||||||
// println!("input value:{}", INPUT_VALUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn input_callback(input: u8) {
|
|
||||||
println!("input value:{}", input);
|
|
||||||
unsafe {
|
|
||||||
INPUT_VALUE = input;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
#![no_std]
|
|
||||||
#![no_main]
|
|
||||||
#![feature(custom_test_frameworks)]
|
|
||||||
#![test_runner(jinux_frame::test_runner)]
|
|
||||||
#![reexport_test_harness_main = "test_main"]
|
|
||||||
extern crate alloc;
|
|
||||||
use core::panic::PanicInfo;
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub fn jinux_main() -> ! {
|
|
||||||
jinux_frame::init();
|
|
||||||
component::init_all(component::parse_metadata!()).unwrap();
|
|
||||||
test_main();
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[panic_handler]
|
|
||||||
fn panic(info: &PanicInfo) -> ! {
|
|
||||||
jinux_frame::test_panic_handler(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test_case]
|
|
||||||
fn test_framebuffer() {
|
|
||||||
for _i in 0..30 {
|
|
||||||
jinux_framebuffer::println!("test_println!");
|
|
||||||
}
|
|
||||||
}
|
|
26
tests/rtc.rs
26
tests/rtc.rs
@ -1,26 +0,0 @@
|
|||||||
#![no_std]
|
|
||||||
#![no_main]
|
|
||||||
#![feature(custom_test_frameworks)]
|
|
||||||
#![test_runner(jinux_frame::test_runner)]
|
|
||||||
#![reexport_test_harness_main = "test_main"]
|
|
||||||
extern crate alloc;
|
|
||||||
use core::panic::PanicInfo;
|
|
||||||
use jinux_frame::println;
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub fn jinux_main() -> ! {
|
|
||||||
jinux_frame::init();
|
|
||||||
component::init_all(component::parse_metadata!()).unwrap();
|
|
||||||
test_main();
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[panic_handler]
|
|
||||||
fn panic(info: &PanicInfo) -> ! {
|
|
||||||
jinux_frame::test_panic_handler(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test_case]
|
|
||||||
fn test_rtc() {
|
|
||||||
println!("real time:{:?}", jinux_time::get_real_time());
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
#![no_std]
|
|
||||||
#![no_main]
|
|
||||||
#![feature(custom_test_frameworks)]
|
|
||||||
#![test_runner(jinux_frame::test_runner)]
|
|
||||||
#![reexport_test_harness_main = "test_main"]
|
|
||||||
use core::panic::PanicInfo;
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub fn jinux_main() -> ! {
|
|
||||||
jinux_frame::init();
|
|
||||||
test_main();
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[panic_handler]
|
|
||||||
fn panic(info: &PanicInfo) -> ! {
|
|
||||||
jinux_frame::test_panic_handler(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test_case]
|
|
||||||
fn test_println() {
|
|
||||||
jinux_frame::println!("test_println output");
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
#![no_std]
|
|
||||||
#![no_main]
|
|
||||||
#![feature(custom_test_frameworks)]
|
|
||||||
#![test_runner(jinux_frame::test_runner)]
|
|
||||||
#![reexport_test_harness_main = "test_main"]
|
|
||||||
use jinux_frame::timer::Timer;
|
|
||||||
extern crate alloc;
|
|
||||||
use alloc::sync::Arc;
|
|
||||||
use core::panic::PanicInfo;
|
|
||||||
use core::time::Duration;
|
|
||||||
use jinux_frame::println;
|
|
||||||
|
|
||||||
static mut TICK: usize = 0;
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub fn jinux_main() -> ! {
|
|
||||||
jinux_frame::init();
|
|
||||||
test_main();
|
|
||||||
loop {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[panic_handler]
|
|
||||||
fn panic(info: &PanicInfo) -> ! {
|
|
||||||
jinux_frame::test_panic_handler(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test_case]
|
|
||||||
fn test_timer() {
|
|
||||||
x86_64::instructions::interrupts::enable();
|
|
||||||
unsafe {
|
|
||||||
let timer = Timer::new(timer_callback).unwrap();
|
|
||||||
timer.set(Duration::from_secs(1));
|
|
||||||
while TICK < 5 {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn timer_callback(timer: Arc<Timer>) {
|
|
||||||
unsafe {
|
|
||||||
TICK += 1;
|
|
||||||
println!("TICK:{}", TICK);
|
|
||||||
timer.set(Duration::from_secs(1));
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,11 +5,13 @@
|
|||||||
|
|
||||||
# Update Cargo style versions (`version = "{version}"`) in file $1
|
# Update Cargo style versions (`version = "{version}"`) in file $1
|
||||||
update_cargo_versions() {
|
update_cargo_versions() {
|
||||||
|
echo "Updating file $1"
|
||||||
sed -i "s/^version = \"[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+\"$/version = \"${new_version}\"/g" $1
|
sed -i "s/^version = \"[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+\"$/version = \"${new_version}\"/g" $1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Update Docker image versions (`jinuxdev/jinux:{version}`) in file $1
|
# Update Docker image versions (`jinuxdev/jinux:{version}`) in file $1
|
||||||
update_image_versions() {
|
update_image_versions() {
|
||||||
|
echo "Updating file $1"
|
||||||
sed -i "s/jinuxdev\/jinux:[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+/jinuxdev\/jinux:${new_version}/g" $1
|
sed -i "s/jinuxdev\/jinux:[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+/jinuxdev\/jinux:${new_version}/g" $1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,8 +39,10 @@ update_image_versions ${JINUX_SRC_DIR}/README.md
|
|||||||
update_image_versions ${SCRIPT_DIR}/docker/README.md
|
update_image_versions ${SCRIPT_DIR}/docker/README.md
|
||||||
|
|
||||||
# Update Docker image versions in workflows
|
# Update Docker image versions in workflows
|
||||||
update_image_versions ${JINUX_SRC_DIR}/.github/workflows/syscall_test.yml
|
WORKFLOWS=$(find "${JINUX_SRC_DIR}/.github/workflows/" -type f -name "*.yml")
|
||||||
update_image_versions ${JINUX_SRC_DIR}/.github/workflows/cargo_check.yml
|
for workflow in $WORKFLOWS; do
|
||||||
|
update_image_versions $workflow
|
||||||
|
done
|
||||||
|
|
||||||
# Create or update VERSION
|
# Create or update VERSION
|
||||||
echo "${new_version}" > ${VERSION_PATH}
|
echo "${new_version}" > ${VERSION_PATH}
|
||||||
|
Reference in New Issue
Block a user