Skip to content

Commit 4cbc9d1

Browse files
committed
Code coverage report
1 parent 39d68e2 commit 4cbc9d1

9 files changed

Lines changed: 183 additions & 12 deletions

File tree

.github/workflows/rust.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ jobs:
3131
pushd $t
3232
cargo fmt --check
3333
cargo clippy -- -D warnings
34-
cargo test --no-fail-fast --all-features
3534
popd
3635
done
3736
@@ -52,14 +51,18 @@ jobs:
5251
- name: Install rust
5352
uses: actions-rust-lang/setup-rust-toolchain@v1
5453
with:
55-
components: rustfmt, clippy
54+
toolchain: nightly
55+
components: llvm-tools
5656
target: wasm32-unknown-unknown, x86_64-unknown-uefi
5757
cache-workspaces: |
5858
pixie-server
5959
pixie-shared
6060
pixie-uefi
6161
pixie-web
6262
63+
- name: Install rustfilt
64+
run: cargo install rustfilt
65+
6366
- name: Install trunk
6467
uses: jetli/trunk-action@v0.5.0
6568

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ buildroot/pixie.tar.gz
55
pixie-web/dist
66
.*.swp
77
pixie-shared/Cargo.lock
8+
/prof-out

pixie-uefi/Cargo.lock

Lines changed: 54 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pixie-uefi/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ path = "src/main.rs"
99
test = false
1010
bench = false
1111

12+
[features]
13+
coverage = ["dep:minicov"]
14+
1215
[dependencies]
1316
anstyle = { version = "1.0.11", default-features = false }
1417
blake3 = { version = "1.8.2", default-features = false, features = ["prefer_intrinsics", "no_avx512", "pure"] }
@@ -18,6 +21,7 @@ gpt_disk_io = "0.16.2"
1821
log = "0.4.27"
1922
lz4_flex = { version = "0.11.5", default-features = false }
2023
managed = { version = "0.8.0", default-features = false, features = ["alloc"] }
24+
minicov = { version = "0.3.7", optional = true }
2125
postcard = { version = "1.1.3", default-features = false, features = ["alloc"] }
2226
rand = { version = "0.8.5", default-features = false }
2327
rand_xoshiro = { version = "0.6.0", default-features = false }

pixie-uefi/src/export_cov.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use crate::os::{disk::Disk, UefiOS};
2+
3+
pub async fn export(os: UefiOS) {
4+
let mut disk = Disk::open_with_size(os, 500 << 20);
5+
6+
let mut coverage = vec![];
7+
// SAFETY: we never create threads anyway.
8+
unsafe { minicov::capture_coverage(&mut coverage).unwrap() };
9+
disk.write_(0, &coverage).unwrap();
10+
}

pixie-uefi/src/main.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ mod reboot_to_os;
2828
mod register;
2929
mod store;
3030

31+
#[cfg(feature = "coverage")]
32+
mod export_cov;
33+
3134
const MIN_MEMORY: u64 = 500 << 20;
3235

3336
async fn server_discover(os: UefiOS) -> Result<SocketAddrV4> {
@@ -63,6 +66,9 @@ async fn server_discover(os: UefiOS) -> Result<SocketAddrV4> {
6366
}
6467

6568
async fn shutdown(os: UefiOS) -> ! {
69+
#[cfg(feature = "coverage")]
70+
export_cov::export(os).await;
71+
6672
log::info!("Shutting down...");
6773
os.sleep_us(1_000_000).await;
6874
os.shutdown()

pixie-uefi/src/os/disk.rs

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,46 @@ pub struct Disk {
5050
// available; support having more than one disk.
5151
impl Disk {
5252
pub fn new(os: UefiOS) -> Disk {
53-
let handle = uefi::boot::find_handles::<DiskIo>()
53+
let (_size, handle) = uefi::boot::find_handles::<DiskIo>()
5454
.unwrap()
5555
.into_iter()
56-
.find(|handle| {
57-
let op = open_disk(*handle);
58-
if let Ok((_, block)) = op {
59-
if block.media().is_media_present() {
60-
return true;
61-
}
56+
.filter_map(|handle| {
57+
let op = open_disk(handle);
58+
let Ok((_, block)) = op else {
59+
return None;
60+
};
61+
let m = block.media();
62+
if !m.is_media_present() {
63+
return None;
6264
}
63-
false
65+
let size = (m.last_block() as u128 + 1) * (m.block_size() as u128);
66+
Some((size, handle))
6467
})
68+
.max_by_key(|(size, _)| *size)
69+
.expect("Disk not found");
70+
71+
let (disk, block) = open_disk(handle).unwrap();
72+
Disk { disk, block, os }
73+
}
74+
75+
#[cfg(feature = "coverage")]
76+
pub fn open_with_size(os: UefiOS, base_size: i64) -> Disk {
77+
let (_size, handle) = uefi::boot::find_handles::<DiskIo>()
78+
.unwrap()
79+
.into_iter()
80+
.filter_map(|handle| {
81+
let op = open_disk(handle);
82+
let Ok((_, block)) = op else {
83+
return None;
84+
};
85+
let m = block.media();
86+
if !m.is_media_present() {
87+
return None;
88+
}
89+
let size = (m.last_block() as i64 + 1) * (m.block_size() as i64);
90+
Some(((size - base_size).abs(), handle))
91+
})
92+
.min_by_key(|(size, _)| *size)
6593
.expect("Disk not found");
6694

6795
let (disk, block) = open_disk(handle).unwrap();
@@ -83,6 +111,13 @@ impl Disk {
83111
.read_disk(self.block.media().media_id(), offset, buf)?)
84112
}
85113

114+
#[cfg(feature = "coverage")]
115+
pub fn write_(&mut self, offset: u64, buf: &[u8]) -> Result<()> {
116+
Ok(self
117+
.disk
118+
.write_disk(self.block.media().media_id(), offset, buf)?)
119+
}
120+
86121
pub async fn write(&mut self, offset: u64, buf: &[u8]) -> Result<()> {
87122
self.os.schedule().await;
88123
Ok(self

run_test.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,16 @@ if ! ip link show br-pixie; then
4343
ip addr add 10.0.0.1/8 brd 10.255.255.255 dev br-pixie
4444
fi
4545

46-
RUST_BACKTRACE=short RUST_LOG=debug RUST_LOG_STYLE=always ./pixie-server/target/debug/pixie-server -s $TEMPDIR/storage &
46+
RUST_BACKTRACE=short RUST_LOG=debug RUST_LOG_STYLE=always LLVM_PROFILE_FILE=prof-out/pixie-server-%m-%p.profraw ./pixie-server/target/debug/pixie-server -s $TEMPDIR/storage &
4747

4848
run_qemu() {
4949
OVMF=/usr/share/OVMF/OVMF_CODE_4M.fd
5050
if ! [ -e $OVMF ]
5151
then
5252
OVMF=/usr/share/edk2/x64/OVMF_CODE.4m.fd
5353
fi
54+
FILE=prof-out/pixie-uefi-$RANDOM.profraw
55+
truncate -s 500M $FILE
5456
qemu-system-x86_64 \
5557
-nographic \
5658
-chardev stdio,id=char0,logfile=$1,signal=off \
@@ -61,6 +63,7 @@ run_qemu() {
6163
-m 1G \
6264
-drive if=pflash,format=raw,file=$OVMF \
6365
-drive file=$TEMPDIR/disk.img,if=none,id=nvm,format=raw \
66+
-drive file=$FILE,format=raw \
6467
-device nvme,serial=deadbeef,drive=nvm \
6568
-nic bridge,mac=52:54:00:12:34:56,br=br-pixie,model=virtio-net-pci
6669
}

test.sh

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,62 @@ set -xe
44
SELFDIR="$(realpath "$(dirname "$0")")"
55
cd "$SELFDIR"
66

7-
./setup.sh
7+
STORAGE_DIR="${SELFDIR}/storage"
8+
9+
rm -rf prof-out
10+
mkdir -p prof-out
11+
12+
SYSROOT=$(rustc +nightly --print sysroot)
13+
LLVM_TOOLS_DIR="$SYSROOT/lib/rustlib/$(rustc +nightly -Vv | grep host | awk '{print $2}')/bin"
14+
LLVM_COV="$LLVM_TOOLS_DIR/llvm-cov"
15+
LLVM_PROFDATA="$LLVM_TOOLS_DIR/llvm-profdata"
16+
17+
pushd pixie-shared
18+
RUSTFLAGS='-C instrument-coverage' LLVM_PROFILE_FILE=../prof-out/pixie-shared-test-%m-%p.profraw cargo +nightly test --no-fail-fast --all-features
19+
popd
20+
21+
pushd pixie-uefi
22+
RUSTFLAGS='-Cinstrument-coverage -Zno-profiler-runtime' cargo +nightly build -F coverage
23+
popd
24+
25+
pushd pixie-web
26+
trunk build
27+
popd
28+
29+
pushd pixie-server
30+
RUSTFLAGS='-C instrument-coverage' cargo +nightly build
31+
popd
32+
33+
mkdir -p "${STORAGE_DIR}/tftpboot" "${STORAGE_DIR}/images" "${STORAGE_DIR}/chunks" "${STORAGE_DIR}/admin"
34+
cp "pixie-uefi/target/x86_64-unknown-uefi/debug/pixie-uefi.efi" "${STORAGE_DIR}/tftpboot/"
35+
cp -r pixie-web/dist/* "${STORAGE_DIR}/admin/"
36+
37+
[ -f "${STORAGE_DIR}/config.yaml" ] || cp pixie-server/example.config.yaml "${STORAGE_DIR}/config.yaml"
838

939
trap '' SIGTERM
1040
sudo ./run_test.sh ${SELFDIR}/storage
41+
42+
TEST_OBJECTS=$( \
43+
for file in \
44+
$( \
45+
RUSTFLAGS="-C instrument-coverage" \
46+
cargo +nightly test --manifest-path pixie-shared/Cargo.toml --no-fail-fast --all-features --no-run --message-format=json \
47+
| jq -r "select(.profile.test == true) | .filenames[]" \
48+
| grep -v dSYM - \
49+
); \
50+
do \
51+
printf "%s %s " -object $file; \
52+
done \
53+
)
54+
55+
"$LLVM_PROFDATA" merge -sparse prof-out/*.profraw -o prof-out/pixie.profdata
56+
"$LLVM_COV" show \
57+
-instr-profile=prof-out/pixie.profdata \
58+
-object pixie-server/target/debug/pixie-server \
59+
-object pixie-uefi/target/x86_64-unknown-uefi/debug/pixie-uefi.efi \
60+
$TEST_OBJECTS \
61+
-Xdemangler=rustfilt \
62+
--ignore-filename-regex='/.cargo' \
63+
--ignore-filename-regex='/.rustup' \
64+
--format html \
65+
-o prof-out/html

0 commit comments

Comments
 (0)