Skip to content
Draft
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
13 changes: 10 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,21 @@ clean:

clean-all: clean clean-sysroot

test-prefix/lib64/libkrun.pc: $(LIBRARY_RELEASE_$(OS))
test-prefix/$(LIBDIR_$(OS))/libkrun.pc: $(LIBRARY_RELEASE_$(OS))
mkdir -p test-prefix
PREFIX="$$(realpath test-prefix)" make install

test-prefix: test-prefix/lib64/libkrun.pc
test-prefix: test-prefix/$(LIBDIR_$(OS))/libkrun.pc

TEST ?= all
TEST_FLAGS ?=

# Library path variable differs by OS
LIBPATH_VAR_Linux = LD_LIBRARY_PATH
LIBPATH_VAR_Darwin = DYLD_LIBRARY_PATH
# Extra library paths needed for tests (libkrunfw, llvm)
EXTRA_LIBPATH_Linux =
EXTRA_LIBPATH_Darwin = /opt/homebrew/opt/libkrunfw/lib:/opt/homebrew/opt/llvm/lib

test: test-prefix
cd tests; RUST_LOG=trace LD_LIBRARY_PATH="$$(realpath ../test-prefix/lib64/)" PKG_CONFIG_PATH="$$(realpath ../test-prefix/lib64/pkgconfig/)" ./run.sh test --test-case "$(TEST)" $(TEST_FLAGS)
cd tests; RUST_LOG=trace $(LIBPATH_VAR_$(OS))="$$(realpath ../test-prefix/$(LIBDIR_$(OS))/):$(EXTRA_LIBPATH_$(OS)):$${$(LIBPATH_VAR_$(OS))}" PKG_CONFIG_PATH="$$(realpath ../test-prefix/$(LIBDIR_$(OS))/pkgconfig/)" ./run.sh test --test-case "$(TEST)" $(TEST_FLAGS)
41 changes: 39 additions & 2 deletions tests/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,46 @@
# End-to-end tests
The testing framework here allows you to write code to configure libkrun (using the public API) and run some specific code in the guest.
The testing framework here allows you to write code to configure libkrun (using the public API) and run some specific code in the guest.

## Running the tests:
The tests can be ran using `make test` (from the main libkrun directory).
You can also run `./run.sh` inside the `test` directory. When using the `./run.sh` script you probably want specify the `PKG_CONFIG_PATH` enviroment variable, otherwise you will be testing the system wide installation of libkrun.
You can also run `./run.sh` inside the `test` directory. When using the `./run.sh` script you probably want specify the `PKG_CONFIG_PATH` enviroment variable, otherwise you will be testing the system wide installation of libkrun.

## Running on macOS

### Prerequisites

1. Install required build tools:
```bash
brew install lld xz
rustup target add aarch64-unknown-linux-musl
```

2. Install libkrunfw (required for non-EFI builds). Either via homebrew:
```bash
brew install libkrunfw
```

Or build from source:
```bash
curl -LO https://github.com/containers/libkrunfw/releases/download/v5.2.0/libkrunfw-prebuilt-aarch64.tgz
tar -xzf libkrunfw-prebuilt-aarch64.tgz
cd libkrunfw
make
sudo make install
```

If installed from source, add `/usr/local/lib` to your library path:
```bash
export DYLD_LIBRARY_PATH="/usr/local/lib:${DYLD_LIBRARY_PATH}"
```

The test harness automatically handles the library path for homebrew installations.

### Running tests

```bash
make test
```

## Adding tests
To add a test you need to add a new rust module in the `test_cases` directory, implement the required host and guest side methods (see existing tests) and register the test in the `test_cases/src/lib.rs` to be ran.
2 changes: 1 addition & 1 deletion tests/guest-agent/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fn run_guest_agent(test_name: &str) -> anyhow::Result<()> {
.into_iter()
.find(|t| t.name() == test_name)
.context("No such test!")?;
let TestCase { test, name: _ } = test_case;
let TestCase { test, .. } = test_case;
test.in_guest();
Ok(())
}
Expand Down
46 changes: 42 additions & 4 deletions tests/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,53 @@

set -e

OS=$(uname -s)
ARCH=$(uname -m)

# Run the unit tests first (this tests the testing framework itself not libkrun)
cargo test -p test_cases --features guest

GUEST_TARGET_ARCH="$(uname -m)-unknown-linux-musl"
# Determine guest target architecture
# macOS uses arm64 but Rust uses aarch64
if [ "$ARCH" = "arm64" ]; then
RUST_ARCH="aarch64"
else
RUST_ARCH="$ARCH"
fi
GUEST_TARGET="${RUST_ARCH}-unknown-linux-musl"

# On macOS, we need to cross-compile for Linux musl
if [ "$OS" = "Darwin" ]; then
SYSROOT="../linux-sysroot"
if [ ! -d "$SYSROOT" ]; then
echo "ERROR: Linux sysroot not found at $SYSROOT"
echo "Run 'make' in the libkrun root directory first to create it."
exit 1
fi

cargo build --target=$GUEST_TARGET_ARCH -p guest-agent
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER="clang"
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUSTFLAGS="-C link-arg=-target -C link-arg=aarch64-linux-gnu -C link-arg=-fuse-ld=lld -C link-arg=--sysroot=$SYSROOT -C link-arg=-static"
echo "Cross-compiling guest-agent for $GUEST_TARGET..."
fi

cargo build --target=$GUEST_TARGET -p guest-agent
cargo build -p runner

export KRUN_TEST_GUEST_AGENT_PATH="target/$GUEST_TARGET_ARCH/debug/guest-agent"
# On macOS, the runner needs entitlements to use Hypervisor.framework
if [ "$OS" = "Darwin" ]; then
codesign --entitlements /dev/stdin --force -s - target/debug/runner <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.hypervisor</key>
<true/>
</dict>
</plist>
EOF
fi

export KRUN_TEST_GUEST_AGENT_PATH="target/$GUEST_TARGET/debug/guest-agent"

# Build runner args: pass through all arguments
RUNNER_ARGS="$*"
Expand All @@ -24,7 +62,7 @@ if [ -n "${KRUN_TEST_BASE_DIR}" ]; then
RUNNER_ARGS="${RUNNER_ARGS} --base-dir ${KRUN_TEST_BASE_DIR}"
fi

if [ -z "${KRUN_NO_UNSHARE}" ] && which unshare 2>&1 >/dev/null; then
if [ "$OS" != "Darwin" ] && [ -z "${KRUN_NO_UNSHARE}" ] && which unshare 2>&1 >/dev/null; then
unshare --user --map-root-user --net -- /bin/sh -c "ifconfig lo 127.0.0.1 && exec target/debug/runner ${RUNNER_ARGS}"
else
echo "WARNING: Running tests without a network namespace."
Expand Down
Loading
Loading