1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
// Take a look at the license at the top of the repository in the LICENSE file.
#[cfg(all(feature = "system", feature = "disk"))]
fn should_skip() -> bool {
if !sysinfo::IS_SUPPORTED_SYSTEM {
return true;
}
// If we don't have any physical core present, it's very likely that we're inside a VM...
sysinfo::System::physical_core_count().unwrap_or_default() == 0
}
#[test]
#[cfg(all(feature = "system", feature = "disk"))]
#[ignore = "not supported in debian build environments"]
fn test_disks() {
if should_skip() {
return;
}
let mut disks = sysinfo::Disks::new();
assert!(disks.list().is_empty());
disks.refresh(false);
assert!(!disks.list().is_empty());
}
#[test]
#[cfg(all(feature = "system", feature = "disk"))]
#[ignore = "not supported in debian build environments"]
fn test_disk_refresh_kind() {
use itertools::Itertools;
use sysinfo::{DiskKind, DiskRefreshKind, Disks};
if should_skip() {
return;
}
for fs in [
DiskRefreshKind::with_kind,
DiskRefreshKind::without_kind,
DiskRefreshKind::with_storage,
DiskRefreshKind::without_storage,
DiskRefreshKind::with_io_usage,
DiskRefreshKind::without_io_usage,
]
.iter()
.powerset()
{
let mut refreshes = DiskRefreshKind::nothing();
for f in fs {
refreshes = f(refreshes);
}
let assertions = |name: &'static str, disks: &Disks| {
if refreshes.kind() {
// This would ideally assert that *all* are refreshed, but we settle for a weaker
// assertion because failures can't be distinguished from "not refreshed" values.
#[cfg(not(any(target_os = "freebsd", target_os = "windows")))]
assert!(
disks
.iter()
.any(|disk| disk.kind() != DiskKind::Unknown(-1)),
"{name}: disk.kind should be refreshed"
);
} else {
assert!(
disks
.iter()
.all(|disk| disk.kind() == DiskKind::Unknown(-1)),
"{name}: disk.kind should not be refreshed"
);
}
if refreshes.storage() {
// These would ideally assert that *all* are refreshed, but we settle for a weaker
// assertion because failures can't be distinguished from "not refreshed" values.
assert!(
disks
.iter()
.any(|disk| disk.available_space() != Default::default()),
"{name}: disk.available_space should be refreshed"
);
assert!(
disks
.iter()
.any(|disk| disk.total_space() != Default::default()),
"{name}: disk.total_space should be refreshed"
);
// We can't assert anything about booleans, since false is indistinguishable from
// not-refreshed
} else {
assert!(
disks
.iter()
.all(|disk| disk.available_space() == Default::default()),
"{name}: disk.available_space should not be refreshed"
);
assert!(
disks
.iter()
.all(|disk| disk.total_space() == Default::default()),
"{name}: disk.total_space should not be refreshed"
);
}
if refreshes.io_usage() {
// This would ideally assert that *all* are refreshed, but we settle for a weaker
// assertion because failures can't be distinguished from "not refreshed" values.
assert!(
disks.iter().any(|disk| disk.usage() != Default::default()),
"{name}: disk.usage should be refreshed"
);
} else {
assert!(
disks.iter().all(|disk| disk.usage() == Default::default()),
"{name}: disk.usage should not be refreshed"
);
}
};
// load and refresh with the desired details should work
let disks = Disks::new_with_refreshed_list_specifics(refreshes);
assertions("full", &disks);
// load with minimal `DiskRefreshKind`, then refresh for added detail should also work!
let mut disks = Disks::new_with_refreshed_list_specifics(DiskRefreshKind::nothing());
disks.refresh_specifics(false, refreshes);
assertions("incremental", &disks);
}
}
#[test]
#[cfg(all(feature = "system", feature = "disk"))]
#[ignore = "not supported in debian build environments"]
fn test_disks_usage() {
use std::fs::{File, remove_file};
use std::io::Write;
use std::path::{Path, PathBuf};
use std::thread::sleep;
use sysinfo::Disks;
if should_skip() {
return;
}
// The test always fails in CI on Linux. For some unknown reason, /proc/diskstats just doesn't
// update, regardless of how long we wait. Until the root cause is discovered, skip the test
// in CI.
if cfg!(target_os = "linux") && std::env::var("CI").is_ok() {
return;
}
let mut disks = Disks::new_with_refreshed_list();
let path = match std::env::var("CARGO_TARGET_DIR") {
Ok(p) => Path::new(&p).join("data.tmp"),
_ => PathBuf::from("target/data.tmp"),
};
let mut file = File::create(&path).expect("failed to create temporary file");
// Write 10mb worth of data to the temp file.
let data = vec![1u8; 10 * 1024 * 1024];
file.write_all(&data).unwrap();
// The sync_all call is important to ensure all the data is persisted to disk. Without
// the call, this test is flaky.
file.sync_all().unwrap();
// Wait a bit just in case
sleep(std::time::Duration::from_millis(500));
disks.refresh(false);
// Depending on the OS and how disks are configured, the disk usage may be the exact same
// across multiple disks. To account for this, collect the disk usages and dedup.
let mut disk_usages = disks.list().iter().map(|d| d.usage()).collect::<Vec<_>>();
disk_usages.dedup();
let mut written_bytes = 0;
for disk_usage in disk_usages {
written_bytes += disk_usage.written_bytes;
}
let _ = remove_file(path);
// written_bytes should have increased by about 10mb, but this is not fully reliable in CI Linux. For now,
// just verify the number is non-zero.
assert!(written_bytes > 0);
}
|