Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/basic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ jobs:
nix-channel --update
nix build -f default.nix testn.container
docker load < ./result
docker build --tag ghcr.io/githedgehog/testn/n-vm:v0.0.8 .
docker build --tag ghcr.io/githedgehog/testn/n-vm:v0.0.9 .
docker run --privileged --rm busybox:latest sh -c "echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages && cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages"
cargo test --package=scratch
docker push ghcr.io/githedgehog/testn/n-vm:v0.0.8
cargo test --package=n-vm
docker push ghcr.io/githedgehog/testn/n-vm:v0.0.9

- name: "Setup tmate session for debug"
if: ${{ failure() && github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
Expand Down
16 changes: 3 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ members = [
"n-it",
"n-vm",
"n-vm-macros",
"scratch",
]

[workspace.dependencies]
Expand Down
2 changes: 1 addition & 1 deletion n-it/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "n-it"
version = "0.0.8"
version = "0.0.9"
edition = "2024"
license = "Apache-2.0"
publish = false
Expand Down
4 changes: 2 additions & 2 deletions n-it/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ impl InitSystem {
if let Some(pid) = child.id() {
debug!("main process spawned with PID: {pid}");
} else {
fatal!("unable to determine main processs id");
fatal!("unable to determine main PID");
}
(console, child)
}
Expand Down Expand Up @@ -304,7 +304,7 @@ impl InitSystem {
.await
{
Ok(_) => {
// normaly I would use unreachable!() here, but in this case
// normally I would use unreachable!() here, but in this case
// it is better to use fatal!() to help ensure that stdio is flushed.
fatal!("unreachable code?");
}
Expand Down
2 changes: 1 addition & 1 deletion n-vm-macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "n-vm-macros"
version = "0.0.8"
version = "0.0.9"
edition = "2024"
license = "Apache-2.0"
publish = false
Expand Down
2 changes: 1 addition & 1 deletion n-vm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "n-vm"
version = "0.0.8"
version = "0.0.9"
edition = "2024"
license = "Apache-2.0"
publish = false
Expand Down
95 changes: 3 additions & 92 deletions n-vm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ pub async fn run_in_vm<F: FnOnce()>(_: F) -> VmTestOutput {
..Default::default()
}),
pvpanic: Some(true),
landlock_enable: Some(false),
landlock_enable: Some(true),
landlock_rules: Some(vec![LandlockConfig {
path: "/vm".into(),
access: "rw".into(),
Expand Down Expand Up @@ -567,7 +567,7 @@ pub fn run_test_in_vm<F: FnOnce()>(_test_fn: F) -> ContainerState {
entrypoint: None,
cmd: Some(args),
// TODO: this needs to be dynamic somehow. Not sure how to do that yet.
image: Some("ghcr.io/githedgehog/testn/n-vm:v0.0.8".into()),
image: Some("ghcr.io/githedgehog/testn/n-vm:v0.0.9".into()),
network_disabled: Some(true),
env: Some([
"IN_TEST_CONTAINER=YES".into(),
Expand Down Expand Up @@ -615,7 +615,7 @@ pub fn run_test_in_vm<F: FnOnce()>(_test_fn: F) -> ContainerState {
].into()),
tmpfs: Some({
let mut map = std::collections::HashMap::new();
map.insert("/vm".into(), format!("nodev,noexec,nosuid,mode=0300,uid={uid},gid={gid}"));
map.insert("/vm".into(), format!("nodev,noexec,nosuid,uid={uid},gid={gid}"));
map
}),
privileged: Some(false),
Expand Down Expand Up @@ -676,92 +676,3 @@ pub fn run_test_in_vm<F: FnOnce()>(_test_fn: F) -> ContainerState {
exit
})
}

#[cfg(test)]
mod test {
use std::sync::atomic::{AtomicUsize, Ordering};

#[test]
fn science_time() {
println!("science time");
}

#[test]
fn more_science_time() {
println!("more_science time");
}

#[test]
fn container_biscuit() {
mod __user_defined {
pub(super) const SHOULD_PANIC: bool = false;
#[inline(always)]
pub(super) fn container_biscuit() {
println!("stdout");
eprintln!("stderr");
println!("hello from container biscuit");
panic!("oh no!")
}
}
match std::env::var("IN_VM") {
Ok(var) if var == "YES" => {
__user_defined::container_biscuit();
return;
}
_ => {
if let Ok(val) = std::env::var("IN_TEST_CONTAINER")
&& val == "YES"
{
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_io()
.enable_time()
.thread_name_fn(|| {
static ATOMIC_ID: AtomicUsize = AtomicUsize::new(0);
let id = ATOMIC_ID.fetch_add(1, Ordering::SeqCst);
format!("hypervisor-{}", id)
})
.build()
.unwrap();
let _guard = runtime.enter();
runtime.block_on(async {
tracing_subscriber::fmt()
.with_max_level(tracing::Level::INFO)
.with_thread_names(true)
.without_time()
.with_test_writer()
.with_line_number(true)
.with_target(true)
.with_file(true)
.init();
let _init_span = tracing::span!(tracing::Level::INFO, "hypervisor");
let _guard = _init_span.enter();
let output = super::run_in_vm(container_biscuit).await;
eprintln!("{output}");
assert!(output.success);
});
return;
}
}
}
eprintln!("•─────⋅☾☾☾☾BEGIN NESTED TEST ENVIRONMENT☽☽☽☽⋅─────•");
let container_state = super::run_test_in_vm(container_biscuit);
eprintln!("•─────⋅☾☾☾☾END NESTED TEST ENVIRONMENT☽☽☽☽⋅─────•");
if __user_defined::SHOULD_PANIC {
if let Some(code) = container_state.exit_code {
if code != 0 {
eprintln!("test container was expected to panic");
} else {
panic!("test container failed as required");
}
} else {
eprintln!("test container did not return an exit code");
}
} else if let Some(code) = container_state.exit_code {
if code != 0 {
panic!("test container exited with code {code}");
}
} else {
panic!("test container not return an exit code");
}
}
}
48 changes: 48 additions & 0 deletions n-vm/tests/integration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use n_vm::in_vm;

#[test]
#[in_vm]
fn test_which_runs_in_vm() {
assert_eq!(2 + 2, 4);
}

#[should_panic]
#[test]
#[allow(unreachable_code)]
#[in_vm]
fn test_which_runs_in_vm_control() {
assert_eq!(2 + 2, 4);
panic!("deliberate panic");
}

#[test]
fn test_which_does_not_run_in_vm() {
assert_eq!(2 + 2, 4);
}

#[cfg(false)] // deactivated until needed as control
#[should_panic]
#[test]
fn test_which_does_not_run_in_vm_control() {
assert_eq!(2 + 2, 4);
panic!("deliberate panic");
}

#[test]
#[in_vm]
fn root_filesystem_in_vm_is_read_only() {
let error = std::fs::File::create_new("/some.file").unwrap_err();
assert_eq!(error.kind(), std::io::ErrorKind::ReadOnlyFilesystem);
}

#[test]
#[in_vm]
fn run_filesystem_in_vm_is_read_write() {
std::fs::File::create_new("/run/some.file").unwrap();
}

#[test]
#[in_vm]
fn tmp_filesystem_in_vm_is_read_write() {
std::fs::File::create_new("/tmp/some.file").unwrap();
}
15 changes: 0 additions & 15 deletions scratch/Cargo.toml

This file was deleted.

34 changes: 0 additions & 34 deletions scratch/src/main.rs

This file was deleted.

1 change: 1 addition & 0 deletions shell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
# for dev
bash
docker-client
rust-analyzer-unwrapped
rustup
]);
runScript = ''bash'';
Expand Down