Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unit tests for passthroughfs and fuser server api #193

Merged
merged 3 commits into from
Apr 17, 2024
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
10 changes: 7 additions & 3 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ jobs:
if: ${{ matrix.arch == 'amd64' }}
run: |
echo user_allow_other | sudo tee --append /etc/fuse.conf
make test
make smoke-all
CARGO_HOME=${HOME}/.cargo
CARGO_BIN=$(which cargo)
sudo -E CARGO=${CARGO_BIN} make test
sudo -E CARGO=${CARGO_BIN} make smoke-all
sudo chown -R $(id -u):$(id -g) "${HOME}/.cargo"

Macos-CI:
runs-on: macos-latest
Expand All @@ -56,7 +59,8 @@ jobs:
sudo installer -pkg fuse-t-macos-installer-1.0.24.pkg -target /
- uses: actions/checkout@v3
- name: build and check
run: make smoke-macos
run: |
make smoke-macos

deny:
name: Cargo Deny
Expand Down
42 changes: 21 additions & 21 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,42 +21,42 @@ check: build
${CARGO} clippy ${TARGET} --features="fusedev,virtiofs" --no-default-features -- -Dwarnings

test:
cargo test ${TARGET} --features="fusedev" --no-default-features -- --nocapture --skip integration
cargo test ${TARGET} --features="virtiofs" --no-default-features -- --nocapture --skip integration
cargo test ${TARGET} --features="vhost-user-fs" --no-default-features -- --nocapture --skip integration
cargo test ${TARGET} --features="fusedev,virtiofs" --no-default-features -- --nocapture --skip integration
cargo test ${TARGET} --features="fusedev,async-io" --no-default-features -- --nocapture --skip integration
cargo test ${TARGET} --features="virtiofs,async-io" --no-default-features -- --nocapture --skip integration
cargo test ${TARGET} --features="vhost-user-fs,async-io" --no-default-features -- --nocapture --skip integration
cargo test ${TARGET} --features="fusedev,virtiofs,async-io" --no-default-features -- --nocapture --skip integration
cargo test ${TARGET} --features="fusedev,persist" --no-default-features -- --nocapture --skip integration
cargo test ${TARGET} --all-features -- --nocapture --skip integration
${CARGO} test ${TARGET} --features="fusedev" --no-default-features -- --nocapture --skip integration
${CARGO} test ${TARGET} --features="virtiofs" --no-default-features -- --nocapture --skip integration
${CARGO} test ${TARGET} --features="vhost-user-fs" --no-default-features -- --nocapture --skip integration
${CARGO} test ${TARGET} --features="fusedev,virtiofs" --no-default-features -- --nocapture --skip integration
${CARGO} test ${TARGET} --features="fusedev,async-io" --no-default-features -- --nocapture --skip integration
${CARGO} test ${TARGET} --features="virtiofs,async-io" --no-default-features -- --nocapture --skip integration
${CARGO} test ${TARGET} --features="vhost-user-fs,async-io" --no-default-features -- --nocapture --skip integration
${CARGO} test ${TARGET} --features="fusedev,virtiofs,async-io" --no-default-features -- --nocapture --skip integration
${CARGO} test ${TARGET} --features="fusedev,persist" --no-default-features -- --nocapture --skip integration
${CARGO} test ${TARGET} --all-features -- --nocapture --skip integration

smoke:
cargo test ${TARGET} --features="fusedev,persist" -- --nocapture
${CARGO} test ${TARGET} --features="fusedev,persist" -- --nocapture

smoke-all: smoke
cargo test ${TARGET} --features="fusedev,persist" -- --nocapture --ignored
${CARGO} test ${TARGET} --features="fusedev,persist" -- --nocapture --ignored

build-macos:
cargo build --features="fusedev"
cargo build --features="fusedev,fuse-t"
${CARGO} build --features="fusedev"
${CARGO} build --features="fusedev,fuse-t"

check-macos: build-macos
cargo fmt -- --check
cargo clippy --features="fusedev" -- -Dwarnings
cargo test --features="fusedev" -- --nocapture --skip integration
cargo clippy --features="fusedev,fuse-t" -- -Dwarnings
cargo test --features="fusedev,fuse-t" -- --nocapture --skip integration
${CARGO} fmt -- --check
${CARGO} clippy --features="fusedev" -- -Dwarnings
${CARGO} test --features="fusedev" -- --nocapture --skip integration
${CARGO} clippy --features="fusedev,fuse-t" -- -Dwarnings
${CARGO} test --features="fusedev,fuse-t" -- --nocapture --skip integration

smoke-macos: check-macos
cargo test --features="fusedev,fuse-t" -- --nocapture
${CARGO} test --features="fusedev,fuse-t" -- --nocapture

docker-smoke:
docker run --env RUST_BACKTRACE=1 --rm --privileged --volume ${current_dir}:/fuse-rs rust:1.68 sh -c "rustup component add clippy rustfmt; cd /fuse-rs; make smoke-all"

testoverlay:
cd tests/testoverlay && cargo build
cd tests/testoverlay && ${CARGO} build

# Setup xfstests env and run.
xfstests:
Expand Down
40 changes: 40 additions & 0 deletions src/api/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ impl<'a, F: FileSystem, S: BitmapSlice> SrvContext<'a, F, S> {
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "fusedev")]
use crate::transport::FuseBuf;

#[test]
fn test_extract_cstrs() {
Expand Down Expand Up @@ -249,4 +251,42 @@ mod tests {
ServerUtil::extract_two_cstrs(&[0x1u8, 0x2u8, 0x0]).unwrap_err();
ServerUtil::extract_two_cstrs(&[0x1u8, 0x2u8]).unwrap_err();
}

#[cfg(feature = "fusedev")]
#[test]
fn test_get_message_body() {
let mut read_buf = [0u8; 4096];

let mut r = Reader::<()>::from_fuse_buffer(FuseBuf::new(&mut read_buf)).unwrap();
let in_header = InHeader {
len: 0x1000,
..Default::default()
};
let buf = ServerUtil::get_message_body(&mut r, &in_header, 0).unwrap();
assert_eq!(buf.len(), 0x1000 - size_of::<InHeader>());

let mut r = Reader::<()>::from_fuse_buffer(FuseBuf::new(&mut read_buf)).unwrap();
let in_header = InHeader {
len: 0x1000,
..Default::default()
};
let buf = ServerUtil::get_message_body(&mut r, &in_header, 0x100).unwrap();
assert_eq!(buf.len(), 0x1000 - size_of::<InHeader>() - 0x100);

let mut r = Reader::<()>::from_fuse_buffer(FuseBuf::new(&mut read_buf)).unwrap();
let in_header = InHeader {
len: 0x1000,
..Default::default()
};
// shoutld fail because of invalid sub header size
assert!(ServerUtil::get_message_body(&mut r, &in_header, 0x1000).is_err());

let mut r = Reader::<()>::from_fuse_buffer(FuseBuf::new(&mut read_buf)).unwrap();
let in_header = InHeader {
len: 0x1000,
..Default::default()
};
// shoutld fail because of invalid sub header size
assert!(ServerUtil::get_message_body(&mut r, &in_header, 0x1001).is_err());
}
}
149 changes: 149 additions & 0 deletions src/api/server/sync_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1401,3 +1401,152 @@ fn add_dirent<S: BitmapSlice>(
Ok(total_len)
}
}

#[cfg(test)]
mod tests {

#[cfg(all(feature = "fusedev", target_os = "linux"))]
mod tests_fusedev {
use super::super::*;
use crate::passthrough::{Config, PassthroughFs};
use crate::transport::FuseBuf;

use std::fs::File;
use std::os::unix::io::AsRawFd;
use vmm_sys_util::tempfile::TempFile;

fn prepare_srvcontext<'a>(
read_buf: &'a mut [u8],
write_buf: &'a mut [u8],
) -> (SrvContext<'a, PassthroughFs>, File) {
let file = TempFile::new().unwrap().into_file();
let reader = Reader::<()>::from_fuse_buffer(FuseBuf::new(read_buf)).unwrap();
let writer = FuseDevWriter::<()>::new(file.as_raw_fd(), write_buf).unwrap();
let in_header = InHeader::default();
(
SrvContext::<PassthroughFs>::new(in_header, reader, writer.into()),
file,
)
}

#[test]
fn test_server_init() {
let fs = PassthroughFs::<()>::new(Config::default()).unwrap();
let server = Server::new(fs);

let mut read_buf = [
0x8u8, 0x0, 0x0, 0x0, // major = 0x0008
0x0u8, 0x0, 0x0, 0x0, // minor = 0x0008
0x0, 0x0, 0x0, 0x0, // max_readahead = 0x0000
0x0, 0x0, 0x0, 0x0, // flags = 0x0000
];
let mut write_buf = [0u8; 4096];
let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf);

let res = server.init(ctx).unwrap();
assert_eq!(res, 80);

let mut read_buf1 = [
0x7u8, 0x0, 0x0, 0x0, // major = 0x0007
0x0u8, 0x0, 0x0, 0x0, // minor = 0x0000
0x0, 0x0, 0x0, 0x0, // max_readahead = 0x0000
0x0, 0x0, 0x0, 0x0, // flags = 0x0000
];
let mut write_buf1 = [0u8; 4096];
let (ctx1, _file) = prepare_srvcontext(&mut read_buf1, &mut write_buf1);

let res = server.init(ctx1).unwrap();
assert_eq!(res, 24);
}

#[test]
fn test_server_write() {
let fs = PassthroughFs::<()>::new(Config::default()).unwrap();
let server = Server::new(fs);

let mut read_buf = [0u8; 4096];
let mut write_buf = [0u8; 4096];
let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf);

let res = server.write(ctx).unwrap();
assert_eq!(res, 16);
}

#[test]
fn test_server_read() {
let fs = PassthroughFs::<()>::new(Config::default()).unwrap();
let server = Server::new(fs);

let mut read_buf = [0u8; 4096];
let mut write_buf = [0u8; 4096];
let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf);

let res = server.read(ctx).unwrap();
assert_eq!(res, 16);
}

#[test]
fn test_server_readdir() {
let fs = PassthroughFs::<()>::new(Config::default()).unwrap();
let server = Server::new(fs);

let mut read_buf = [0u8; 4096];
let mut write_buf = [0u8; 4096];
let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf);

let res = server.do_readdir(ctx, true).unwrap();
assert_eq!(res, 16);
}

#[test]
fn test_server_ioctl() {
let fs = PassthroughFs::<()>::new(Config::default()).unwrap();
let server = Server::new(fs);

let mut read_buf = [0u8; 4096];
let mut write_buf = [0u8; 4096];
let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf);

let res = server.ioctl(ctx).unwrap();
assert!(res > 0);

// construct IoctlIn with invalid in_size
let mut read_buf_fail = [
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, //fh = 0
0x0, 0x0, 0x0, 0x0, //flags = 0
0x0, 0x0, 0x0, 0x0, //cmd = 0
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, //arg = 0
0x7u8, 0x3u8, 0x0, 0x0, //in_size = 0x307
0x0, 0x0, 0x0, 0x0, //out_size = 0
];
let mut write_buf_fail = [0u8; 48];
let (ctx_fail, _file) = prepare_srvcontext(&mut read_buf_fail, &mut write_buf_fail);
let res = server.ioctl(ctx_fail).unwrap();
assert!(res > 0);
}

#[test]
fn test_server_batch_forget() {
let fs = PassthroughFs::<()>::new(Config::default()).unwrap();
let server = Server::new(fs);

let mut read_buf = [0u8; 4096];
let mut write_buf = [0u8; 4096];
let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf);
// forget should return 0 anyway
assert_eq!(server.batch_forget(ctx).unwrap(), 0);
}

#[test]
fn test_server_forget() {
let fs = PassthroughFs::<()>::new(Config::default()).unwrap();
let server = Server::new(fs);

let mut read_buf = [0x1u8, 0x2u8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0];
let mut write_buf = [0u8; 4096];
let (ctx, _file) = prepare_srvcontext(&mut read_buf, &mut write_buf);

assert_eq!(server.forget(ctx).unwrap(), 0);
}
}
}
Loading
Loading