extern crate libc;
extern crate loopdev;
extern crate tempfile;
#[macro_use]
extern crate lazy_static;
extern crate serde;
extern crate serde_json;
use loopdev::{LoopControl, LoopDevice};
use std::path::PathBuf;
mod util;
use util::{attach_file, create_backing_file, detach_all, list_device, setup};
#[test]
fn get_next_free_device() {
let num_devices_at_start = list_device(None).len();
let _lock = setup();
let lc = LoopControl::open().expect("should be able to open the LoopControl device");
let ld0 = lc
.next_free()
.expect("should not error finding the next free loopback device");
assert_eq!(
ld0.path(),
Some(PathBuf::from(&format!(
"/dev/loop{}",
num_devices_at_start
))),
"should find the first loopback device"
);
}
#[test]
fn attach_a_backing_file_default() {
attach_a_backing_file(0, 0, 128 * 1024 * 1024);
}
#[test]
fn attach_a_backing_file_with_offset() {
attach_a_backing_file(128 * 1024, 0, 128 * 1024 * 1024);
}
#[test]
fn attach_a_backing_file_with_sizelimit() {
attach_a_backing_file(0, 128 * 1024, 128 * 1024 * 1024);
}
#[test]
fn attach_a_backing_file_with_offset_sizelimit() {
attach_a_backing_file(128 * 1024, 128 * 1024, 128 * 1024 * 1024);
}
#[test]
fn attach_a_backing_file_with_offset_overflow() {
attach_a_backing_file(128 * 1024 * 1024 * 2, 0, 128 * 1024 * 1024);
}
#[test]
fn attach_a_backing_file_with_sizelimit_overflow() {
attach_a_backing_file(0, 128 * 1024 * 1024 * 2, 128 * 1024 * 1024);
}
fn attach_a_backing_file(offset: u64, sizelimit: u64, file_size: i64) {
let _lock = setup();
let (devices, ld0_path, file_path) = {
let lc = LoopControl::open().expect("should be able to open the LoopControl device");
let file = create_backing_file(file_size);
let file_path = file.to_path_buf();
let ld0 = lc
.next_free()
.expect("should not error finding the next free loopback device");
ld0.with()
.offset(offset)
.size_limit(sizelimit)
.attach(&file)
.expect("should not error attaching the backing file to the loopdev");
let devices = list_device(Some(ld0.path().unwrap().to_str().unwrap()));
file.close().expect("should delete the temp backing file");
(devices, ld0.path().unwrap(), file_path)
};
assert_eq!(
devices.len(),
1,
"there should be only one loopback mounted device"
);
assert_eq!(
devices[0].name.as_str(),
ld0_path.to_str().unwrap(),
"the attached devices name should match the input name"
);
assert_eq!(
devices[0].back_file.clone().unwrap().as_str(),
file_path.to_str().unwrap(),
"the backing file should match the given file"
);
assert_eq!(
devices[0].offset,
Some(offset),
"the offset should match the requested offset"
);
assert_eq!(
devices[0].size_limit,
Some(sizelimit),
"the sizelimit should match the requested sizelimit"
);
detach_all();
}
#[test]
fn detach_a_backing_file_default() {
detach_a_backing_file(0, 0, 128 * 1024 * 1024);
}
#[test]
fn detach_a_backing_file_with_offset() {
detach_a_backing_file(128 * 1024, 0, 128 * 1024 * 1024);
}
#[test]
fn detach_a_backing_file_with_sizelimit() {
detach_a_backing_file(0, 128 * 1024, 128 * 1024 * 1024);
}
#[test]
fn detach_a_backing_file_with_offset_sizelimit() {
detach_a_backing_file(128 * 1024, 128 * 1024, 128 * 1024 * 1024);
}
#[test]
fn detach_a_backing_file_with_offset_overflow() {
detach_a_backing_file(128 * 1024 * 1024 * 2, 0, 128 * 1024 * 1024);
}
#[test]
fn detach_a_backing_file_with_sizelimit_overflow() {
detach_a_backing_file(0, 128 * 1024 * 1024 * 2, 128 * 1024 * 1024);
}
fn detach_a_backing_file(offset: u64, sizelimit: u64, file_size: i64) {
let num_devices_at_start = list_device(None).len();
let _lock = setup();
{
let file = create_backing_file(file_size);
attach_file(
"/dev/loop3",
file.to_path_buf().to_str().unwrap(),
offset,
sizelimit,
);
let ld0 = LoopDevice::open("/dev/loop3")
.expect("should be able to open the created loopback device");
ld0.detach()
.expect("should not error detaching the backing file from the loopdev");
file.close().expect("should delete the temp backing file");
};
std::thread::sleep(std::time::Duration::from_millis(100));
assert_eq!(
list_device(None).len(),
num_devices_at_start,
"there should be no loopback devices mounted"
);
detach_all();
}