mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-28 00:58:59 +00:00
339 lines
10 KiB
Rust
339 lines
10 KiB
Rust
#[cfg(target_os = "linux")]
|
|
mod linux;
|
|
#[cfg(all(unix, not(target_os = "linux")))]
|
|
mod unix;
|
|
#[cfg(target_os = "windows")]
|
|
mod windows;
|
|
|
|
#[cfg(target_os = "linux")]
|
|
pub use linux::{get_drive_stats, get_info, same_disk};
|
|
// pub use linux::same_disk;
|
|
|
|
#[cfg(all(unix, not(target_os = "linux")))]
|
|
pub use unix::{get_drive_stats, get_info, same_disk};
|
|
#[cfg(target_os = "windows")]
|
|
pub use windows::{get_drive_stats, get_info, same_disk};
|
|
|
|
#[derive(Debug, Default, PartialEq)]
|
|
pub struct IOStats {
|
|
pub read_ios: u64,
|
|
pub read_merges: u64,
|
|
pub read_sectors: u64,
|
|
pub read_ticks: u64,
|
|
pub write_ios: u64,
|
|
pub write_merges: u64,
|
|
pub write_sectors: u64,
|
|
pub write_ticks: u64,
|
|
pub current_ios: u64,
|
|
pub total_ticks: u64,
|
|
pub req_ticks: u64,
|
|
pub discard_ios: u64,
|
|
pub discard_merges: u64,
|
|
pub discard_sectors: u64,
|
|
pub discard_ticks: u64,
|
|
pub flush_ios: u64,
|
|
pub flush_ticks: u64,
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use std::path::PathBuf;
|
|
|
|
#[test]
|
|
fn test_get_info_valid_path() {
|
|
let temp_dir = tempfile::tempdir().unwrap();
|
|
let info = get_info(temp_dir.path()).unwrap();
|
|
|
|
println!("Disk Info: {:?}", info);
|
|
|
|
assert!(info.total > 0);
|
|
assert!(info.free > 0);
|
|
assert!(info.used > 0);
|
|
assert!(info.files > 0);
|
|
assert!(info.ffree > 0);
|
|
assert!(!info.fstype.is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn test_get_info_invalid_path() {
|
|
let invalid_path = PathBuf::from("/invalid/path");
|
|
let result = get_info(&invalid_path);
|
|
|
|
assert!(result.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_same_disk_same_path() {
|
|
let temp_dir = tempfile::tempdir().unwrap();
|
|
let path = temp_dir.path().to_str().unwrap();
|
|
|
|
let result = same_disk(path, path).unwrap();
|
|
assert!(result);
|
|
}
|
|
|
|
#[test]
|
|
fn test_same_disk_different_paths() {
|
|
let temp_dir1 = tempfile::tempdir().unwrap();
|
|
let temp_dir2 = tempfile::tempdir().unwrap();
|
|
|
|
let path1 = temp_dir1.path().to_str().unwrap();
|
|
let path2 = temp_dir2.path().to_str().unwrap();
|
|
|
|
let result = same_disk(path1, path2).unwrap();
|
|
// Note: On many systems, temporary directories are on the same disk
|
|
// This test mainly verifies the function works without error
|
|
// The actual result depends on the system configuration
|
|
println!("Same disk result for temp dirs: {}", result);
|
|
|
|
// Just verify the function executes successfully
|
|
assert!(result == true || result == false);
|
|
}
|
|
|
|
#[test]
|
|
fn test_get_drive_stats_default() {
|
|
let stats = get_drive_stats(0, 0).unwrap();
|
|
assert_eq!(stats, IOStats::default());
|
|
}
|
|
|
|
#[test]
|
|
fn test_iostats_default_values() {
|
|
// Test that IOStats default values are all zero
|
|
let stats = IOStats::default();
|
|
|
|
assert_eq!(stats.read_ios, 0);
|
|
assert_eq!(stats.read_merges, 0);
|
|
assert_eq!(stats.read_sectors, 0);
|
|
assert_eq!(stats.read_ticks, 0);
|
|
assert_eq!(stats.write_ios, 0);
|
|
assert_eq!(stats.write_merges, 0);
|
|
assert_eq!(stats.write_sectors, 0);
|
|
assert_eq!(stats.write_ticks, 0);
|
|
assert_eq!(stats.current_ios, 0);
|
|
assert_eq!(stats.total_ticks, 0);
|
|
assert_eq!(stats.req_ticks, 0);
|
|
assert_eq!(stats.discard_ios, 0);
|
|
assert_eq!(stats.discard_merges, 0);
|
|
assert_eq!(stats.discard_sectors, 0);
|
|
assert_eq!(stats.discard_ticks, 0);
|
|
assert_eq!(stats.flush_ios, 0);
|
|
assert_eq!(stats.flush_ticks, 0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_iostats_equality() {
|
|
// Test IOStats equality comparison
|
|
let stats1 = IOStats::default();
|
|
let stats2 = IOStats::default();
|
|
assert_eq!(stats1, stats2);
|
|
|
|
let stats3 = IOStats {
|
|
read_ios: 100,
|
|
write_ios: 50,
|
|
..Default::default()
|
|
};
|
|
let stats4 = IOStats {
|
|
read_ios: 100,
|
|
write_ios: 50,
|
|
..Default::default()
|
|
};
|
|
assert_eq!(stats3, stats4);
|
|
|
|
// Test inequality
|
|
assert_ne!(stats1, stats3);
|
|
}
|
|
|
|
#[test]
|
|
fn test_iostats_debug_format() {
|
|
// Test Debug trait implementation
|
|
let stats = IOStats {
|
|
read_ios: 123,
|
|
write_ios: 456,
|
|
total_ticks: 789,
|
|
..Default::default()
|
|
};
|
|
|
|
let debug_str = format!("{:?}", stats);
|
|
assert!(debug_str.contains("read_ios: 123"));
|
|
assert!(debug_str.contains("write_ios: 456"));
|
|
assert!(debug_str.contains("total_ticks: 789"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_iostats_partial_eq() {
|
|
// Test PartialEq trait implementation with various field combinations
|
|
let base_stats = IOStats {
|
|
read_ios: 10,
|
|
write_ios: 20,
|
|
read_sectors: 100,
|
|
write_sectors: 200,
|
|
..Default::default()
|
|
};
|
|
|
|
let same_stats = IOStats {
|
|
read_ios: 10,
|
|
write_ios: 20,
|
|
read_sectors: 100,
|
|
write_sectors: 200,
|
|
..Default::default()
|
|
};
|
|
|
|
let different_read = IOStats {
|
|
read_ios: 11, // Different
|
|
write_ios: 20,
|
|
read_sectors: 100,
|
|
write_sectors: 200,
|
|
..Default::default()
|
|
};
|
|
|
|
assert_eq!(base_stats, same_stats);
|
|
assert_ne!(base_stats, different_read);
|
|
}
|
|
|
|
#[test]
|
|
fn test_get_info_path_edge_cases() {
|
|
// Test with root directory (should work on most systems)
|
|
#[cfg(unix)]
|
|
{
|
|
let result = get_info(std::path::Path::new("/"));
|
|
assert!(result.is_ok(), "Root directory should be accessible");
|
|
|
|
if let Ok(info) = result {
|
|
assert!(info.total > 0, "Root filesystem should have non-zero total space");
|
|
assert!(!info.fstype.is_empty(), "Root filesystem should have a type");
|
|
}
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
{
|
|
let result = get_info(std::path::Path::new("C:\\"));
|
|
// On Windows, C:\ might not always exist, so we don't assert success
|
|
if let Ok(info) = result {
|
|
assert!(info.total > 0);
|
|
assert!(!info.fstype.is_empty());
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_get_info_nonexistent_path() {
|
|
// Test with various types of invalid paths
|
|
let invalid_paths = [
|
|
"/this/path/definitely/does/not/exist/anywhere",
|
|
"/dev/null/invalid", // /dev/null is a file, not a directory
|
|
"", // Empty path
|
|
];
|
|
|
|
for invalid_path in &invalid_paths {
|
|
let result = get_info(std::path::Path::new(invalid_path));
|
|
assert!(result.is_err(), "Invalid path should return error: {}", invalid_path);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_same_disk_edge_cases() {
|
|
// Test with same path (should always be true)
|
|
let temp_dir = tempfile::tempdir().unwrap();
|
|
let path_str = temp_dir.path().to_str().unwrap();
|
|
|
|
let result = same_disk(path_str, path_str);
|
|
assert!(result.is_ok());
|
|
assert!(result.unwrap(), "Same path should be on same disk");
|
|
|
|
// Test with parent and child directories (should be on same disk)
|
|
let child_dir = temp_dir.path().join("child");
|
|
std::fs::create_dir(&child_dir).unwrap();
|
|
let child_path = child_dir.to_str().unwrap();
|
|
|
|
let result = same_disk(path_str, child_path);
|
|
assert!(result.is_ok());
|
|
assert!(result.unwrap(), "Parent and child should be on same disk");
|
|
}
|
|
|
|
#[test]
|
|
fn test_same_disk_invalid_paths() {
|
|
// Test with invalid paths
|
|
let temp_dir = tempfile::tempdir().unwrap();
|
|
let valid_path = temp_dir.path().to_str().unwrap();
|
|
let invalid_path = "/this/path/does/not/exist";
|
|
|
|
let result1 = same_disk(valid_path, invalid_path);
|
|
assert!(result1.is_err(), "Should fail with one invalid path");
|
|
|
|
let result2 = same_disk(invalid_path, valid_path);
|
|
assert!(result2.is_err(), "Should fail with one invalid path");
|
|
|
|
let result3 = same_disk(invalid_path, invalid_path);
|
|
assert!(result3.is_err(), "Should fail with both invalid paths");
|
|
}
|
|
|
|
#[test]
|
|
fn test_iostats_field_ranges() {
|
|
// Test that IOStats can handle large values
|
|
let large_stats = IOStats {
|
|
read_ios: u64::MAX,
|
|
write_ios: u64::MAX,
|
|
read_sectors: u64::MAX,
|
|
write_sectors: u64::MAX,
|
|
total_ticks: u64::MAX,
|
|
..Default::default()
|
|
};
|
|
|
|
// Should be able to create and compare
|
|
let another_large = IOStats {
|
|
read_ios: u64::MAX,
|
|
write_ios: u64::MAX,
|
|
read_sectors: u64::MAX,
|
|
write_sectors: u64::MAX,
|
|
total_ticks: u64::MAX,
|
|
..Default::default()
|
|
};
|
|
|
|
assert_eq!(large_stats, another_large);
|
|
}
|
|
|
|
#[test]
|
|
fn test_get_drive_stats_error_handling() {
|
|
// Test with potentially invalid major/minor numbers
|
|
// Note: This might succeed on some systems, so we just ensure it doesn't panic
|
|
let result1 = get_drive_stats(999, 999);
|
|
// Don't assert success/failure as it's platform-dependent
|
|
let _ = result1;
|
|
|
|
let result2 = get_drive_stats(u32::MAX, u32::MAX);
|
|
let _ = result2;
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
#[test]
|
|
fn test_unix_specific_paths() {
|
|
// Test Unix-specific paths
|
|
let unix_paths = ["/tmp", "/var", "/usr"];
|
|
|
|
for path in &unix_paths {
|
|
if std::path::Path::new(path).exists() {
|
|
let result = get_info(std::path::Path::new(path));
|
|
if result.is_ok() {
|
|
let info = result.unwrap();
|
|
assert!(info.total > 0, "Path {} should have non-zero total space", path);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_iostats_clone_and_copy() {
|
|
// Test that IOStats implements Clone (if it does)
|
|
let original = IOStats {
|
|
read_ios: 42,
|
|
write_ios: 84,
|
|
..Default::default()
|
|
};
|
|
|
|
// Test Debug formatting with non-default values
|
|
let debug_output = format!("{:?}", original);
|
|
assert!(debug_output.contains("42"));
|
|
assert!(debug_output.contains("84"));
|
|
}
|
|
}
|