Skip to content

Commit

Permalink
Add bigfile and openfile flag testcases
Browse files Browse the repository at this point in the history
  • Loading branch information
diqiu50 committed Jan 14, 2025
1 parent 016aec2 commit 07b38b2
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 39 deletions.
3 changes: 3 additions & 0 deletions clients/filesystem-fuse/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ doc-test:
unit-test: doc-test
cargo test --no-fail-fast --lib --all-features --workspace

test-it:
cargo test --test fuse_test

test-fuse-it:
@bash ./tests/bin/run_fuse_testers.sh test

Expand Down
4 changes: 2 additions & 2 deletions clients/filesystem-fuse/src/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ pub trait FileWriter: Sync + Send {
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use libc::{O_APPEND, O_CREAT, O_RDONLY};
use libc::{O_CREAT, O_RDONLY, O_RDWR};
use std::collections::HashMap;
use std::path::Component;

Expand Down Expand Up @@ -548,7 +548,7 @@ pub(crate) mod tests {
async fn test_create_file(&mut self, root_file_id: u64, name: &OsStr) -> FileHandle {
let file = self
.fs
.create_file(root_file_id, name, (O_CREAT | O_APPEND) as u32)
.create_file(root_file_id, name, (O_CREAT | O_RDWR) as u32)
.await;
assert!(file.is_ok());
let file = file.unwrap();
Expand Down
36 changes: 19 additions & 17 deletions clients/filesystem-fuse/src/memory_filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl PathFileSystem for MemoryFileSystem {
Ok(results)
}

async fn open_file(&self, path: &Path, _flags: OpenFileFlags) -> Result<OpenedFile> {
async fn open_file(&self, path: &Path, flags: OpenFileFlags) -> Result<OpenedFile> {
let file_stat = self.stat(path).await?;
let mut opened_file = OpenedFile::new(file_stat);
match opened_file.file_stat.kind {
Expand All @@ -105,8 +105,18 @@ impl PathFileSystem for MemoryFileSystem {
.unwrap()
.data
.clone();
opened_file.reader = Some(Box::new(MemoryFileReader { data: data.clone() }));
opened_file.writer = Some(Box::new(MemoryFileWriter { data: data }));
if flags.is_read() {

opened_file.reader = Some(Box::new(MemoryFileReader { data: data.clone() }));
}
if flags.is_write() || flags.is_append() {
opened_file.writer = Some(Box::new(MemoryFileWriter { data: data.clone() }));
}

if flags.is_truncate() {
let mut data = data.lock().unwrap();
data.clear();
}
Ok(opened_file)
}
_ => Err(Errno::from(libc::EBADF)),
Expand All @@ -117,27 +127,19 @@ impl PathFileSystem for MemoryFileSystem {
self.open_file(path, flags).await
}

async fn create_file(&self, path: &Path, _flags: OpenFileFlags) -> Result<OpenedFile> {
let mut file_map = self.file_map.write().unwrap();
if file_map.contains_key(path) {
async fn create_file(&self, path: &Path, flags: OpenFileFlags) -> Result<OpenedFile> {
if self.file_map.read().unwrap().contains_key(path) && flags.is_exclusive() {
return Err(Errno::from(libc::EEXIST));
}

let mut opened_file = OpenedFile::new(FileStat::new_file_filestat_with_path(path, 0));

let data = Arc::new(Mutex::new(Vec::new()));
file_map.insert(
opened_file.file_stat.path.clone(),
self.file_map.write().unwrap().insert(
path.to_path_buf(),
MemoryFile {
kind: RegularFile,
data: data.clone(),
data: Arc::new(Mutex::new(Vec::new())),
},
);

opened_file.reader = Some(Box::new(MemoryFileReader { data: data.clone() }));
opened_file.writer = Some(Box::new(MemoryFileWriter { data: data }));

Ok(opened_file)
self.open_file(path, flags).await
}

async fn create_dir(&self, path: &Path) -> Result<FileStat> {
Expand Down
6 changes: 5 additions & 1 deletion clients/filesystem-fuse/src/open_dal_filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,11 @@ impl PathFileSystem for OpenDalFileSystem {
.map_err(opendal_error_to_errno)?;
file.reader = Some(Box::new(FileReaderImpl { reader }));
}
if flags.is_write() || flags.is_create() || flags.is_append() || flags.is_truncate() {
if !flags.is_create() && flags.is_append() {
return Err(Errno::from(libc::EBADF));
}

if flags.is_write() || flags.is_truncate() {
let writer = self
.op
.writer_with(&file_name)
Expand Down
154 changes: 135 additions & 19 deletions clients/filesystem-fuse/tests/fuse_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ use gvfs_fuse::config::AppConfig;
use gvfs_fuse::RUN_TEST_WITH_FUSE;
use gvfs_fuse::{gvfs_mount, gvfs_unmount, test_enable_with};
use log::{error, info};
use std::fs::File;
use std::fs::{File, OpenOptions};
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::Path;
use std::sync::Arc;
use std::thread::sleep;
Expand Down Expand Up @@ -89,11 +90,6 @@ impl Drop for FuseTest {
fn test_fuse_with_memory_fs() {
tracing_subscriber::fmt().init();

panic::set_hook(Box::new(|info| {
error!("A panic occurred: {:?}", info);
process::exit(1);
}));

let mount_point = "target/gvfs";
let _ = fs::create_dir_all(mount_point);

Expand All @@ -104,26 +100,31 @@ fn test_fuse_with_memory_fs() {
};

test.setup();
test_fuse_filesystem(mount_point);

let test_dir = Path::new(&test.mount_point).join("test_dir");
run_tests(&test_dir);
}

fn run_tests(test_dir: &Path) {
fs::create_dir_all(test_dir).expect("Failed to create test dir");
test_fuse_filesystem(test_dir);
test_big_file(test_dir);
test_open_file_flag(test_dir);
}

#[test]
fn fuse_it_test_fuse() {
test_enable_with!(RUN_TEST_WITH_FUSE);
let mount_point = Path::new("target/gvfs");
let test_dir = mount_point.join("test_dir");

test_fuse_filesystem("target/gvfs/gvfs_test");
run_tests(&test_dir);
}

fn test_fuse_filesystem(mount_point: &str) {
fn test_fuse_filesystem(test_path: &Path) {
info!("Test startup");
let base_path = Path::new(mount_point);

if !file_exists(base_path) {
fs::create_dir_all(base_path).expect("Failed to create test dir");
}

//test create file
let test_file = base_path.join("test_create");
let test_file = test_path.join("test_create");
let file = File::create(&test_file).expect("Failed to create file");
assert!(file.metadata().is_ok(), "Failed to get file metadata");
assert!(file_exists(&test_file));
Expand All @@ -140,16 +141,16 @@ fn test_fuse_filesystem(mount_point: &str) {
assert!(!file_exists(&test_file));

//test create directory
let test_dir = base_path.join("test_dir");
let test_dir = test_path.join("test_dir");
fs::create_dir(&test_dir).expect("Failed to create directory");

//test create file in directory
let test_file = base_path.join("test_dir/test_file");
let test_file = test_path.join("test_dir/test_file");
let file = File::create(&test_file).expect("Failed to create file");
assert!(file.metadata().is_ok(), "Failed to get file metadata");

//test write file in directory
let test_file = base_path.join("test_dir/test_read");
let test_file = test_path.join("test_dir/test_read");
fs::write(&test_file, "read test").expect("Failed to write file");

//test read file in directory
Expand All @@ -167,6 +168,121 @@ fn test_fuse_filesystem(mount_point: &str) {
info!("Success test");
}

#[allow(clippy::needless_range_loop)]
fn test_big_file(test_dir: &Path) {
if !file_exists(test_dir) {
fs::create_dir_all(test_dir).expect("Failed to create test dir");
}

let test_file = test_dir.join("test_big_file");
let mut file = File::create(&test_file).expect("Failed to create file");
assert!(file.metadata().is_ok(), "Failed to get file metadata");
assert!(file_exists(&test_file));

let round_size: usize = 1024 * 1024;
let round: u8 = 10;

for i in 0..round {
let mut content = vec![0; round_size];
for j in 0..round_size {
content[j] = (i as usize + j) as u8;
}

file.write_all(&content).expect("Failed to write file");
}
file.flush().expect("Failed to flush file");

file = File::open(&test_file).expect("Failed to open file");
for i in 0..round {
let mut buffer = vec![0; round_size];
file.read_exact(&mut buffer).unwrap();

for j in 0..round_size {
assert_eq!(buffer[j], (i as usize + j) as u8, "File content mismatch");
}
}

fs::remove_file(&test_file).expect("Failed to delete file");
assert!(!file_exists(&test_file));
}

fn test_open_file_flag(test_dir: &Path) {
// test open file with read and write create flag
let file_path = test_dir.join("test_open_file");
let mut file = OpenOptions::new()
.write(true)
.read(true)
.create(true)
.open(&file_path)
.expect("Failed to open file");
// test file offset is 0
let offset = file.stream_position().expect("Failed to seek file");
assert_eq!(offset, 0, "File offset mismatch");

// test write can be done
let write_content = "write content";
file.write_all(write_content.as_bytes())
.expect("Failed to write file");
let mut content = vec![0; write_content.len()];

// test read can be done
file.seek(SeekFrom::Start(0)).expect("Failed to seek file");
file.read_exact(&mut content).expect("Failed to read file");
assert_eq!(content, write_content.as_bytes(), "File content mismatch");

// test open file with read flag
let mut file = OpenOptions::new()
.read(true)
.open(&file_path)
.expect("Failed to open file");
// test reaad can be done
let mut content = vec![0; write_content.len()];
file.read_exact(&mut content).expect("Failed to read file");
assert_eq!(content, write_content.as_bytes(), "File content mismatch");

// test write can be have error
let result = file.write_all(write_content.as_bytes());
if let Err(e) = result {
assert_eq!(e.to_string(), "Bad file descriptor (os error 9)");
}

// test open file with truncate file
// test file size is not 0
let old_file_size = file.metadata().expect("Failed to get file metadata").len();
assert_eq!(old_file_size, write_content.len() as u64);

let mut file = OpenOptions::new()
.write(true)
.truncate(true)
.open(&file_path)
.expect("Failed to open file");
// validate file size is 0
let file_size = file.metadata().expect("Failed to get file metadata").len();
assert_eq!(file_size, 0, "File size mismatch");
// validate file offset is 0
let offset = file.stream_position().expect("Failed to seek file");
assert_eq!(offset, 0, "File offset mismatch");

file.write_all(write_content.as_bytes())
.expect("Failed to write file");

// test open file with append flag
let mut file = OpenOptions::new()
.append(true)
.open(&file_path)
.expect("Failed to open file");
// test append
file.write_all(write_content.as_bytes())
.expect("Failed to write file");
let file_len = file.metadata().expect("Failed to get file metadata").len();
// validate file size is 2 * write_content.len()
assert_eq!(
file_len,
2 * write_content.len() as u64,
"File size mismatch"
);
}

fn file_exists<P: AsRef<Path>>(path: P) -> bool {
fs::metadata(path).is_ok()
}

0 comments on commit 07b38b2

Please sign in to comment.