#![forbid(unsafe_op_in_unsafe_fn)]
#![warn(missing_docs, rust_2018_idioms)]
mod config;
mod error;
mod status;
#[cfg(unix)]
mod unix;
#[cfg(not(unix))]
mod unsupported;
pub use config::{MlockConfig, MlockConfigBuilder};
pub use error::MlockError;
pub use status::MlockStatus;
pub fn lock_all() -> Result<MlockStatus, MlockError> {
lock_with_config(MlockConfig::default())
}
pub fn lock_with_config(config: MlockConfig) -> Result<MlockStatus, MlockError> {
#[cfg(unix)]
{
unix::lock_with_config(config)
}
#[cfg(not(unix))]
{
unsupported::lock_with_config(config)
}
}
pub fn unlock_all() -> Result<(), MlockError> {
#[cfg(unix)]
{
unix::unlock_all()
}
#[cfg(not(unix))]
{
Ok(())
}
}
#[must_use]
pub fn is_locked() -> bool {
#[cfg(unix)]
{
unix::is_locked()
}
#[cfg(not(unix))]
{
false
}
}
#[must_use]
pub fn locked_bytes() -> usize {
#[cfg(unix)]
{
unix::locked_bytes()
}
#[cfg(not(unix))]
{
0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = MlockConfig::default();
assert!(config.current());
assert!(config.future());
assert!(config.required());
assert!(!config.onfault());
}
#[test]
fn test_config_builder() {
let config = MlockConfig::builder()
.current(false)
.future(true)
.required(false)
.onfault(true)
.build();
assert!(!config.current());
assert!(config.future());
assert!(!config.required());
assert!(config.onfault());
}
#[test]
fn test_is_locked_returns_bool() {
let _ = is_locked();
}
#[test]
fn test_locked_bytes_returns_usize() {
let _ = locked_bytes();
}
#[test]
fn test_unlock_all_does_not_panic() {
let result = unlock_all();
let _ = result;
}
#[test]
fn test_lock_all_non_fatal() {
let config = MlockConfig::builder().required(false).build();
let result = lock_with_config(config);
assert!(result.is_ok());
let _ = unlock_all();
}
#[test]
fn test_lock_with_config_empty_flags() {
let config = MlockConfig::builder()
.current(false)
.future(false)
.build();
let result = lock_with_config(config);
assert!(result.is_ok());
if let Ok(status) = result {
assert!(status.is_locked());
assert_eq!(status.bytes_locked(), 0);
}
}
#[test]
fn test_mlock_status_methods() {
let locked = MlockStatus::Locked { bytes_locked: 1024 };
assert!(locked.is_locked());
assert!(!locked.is_failed());
assert!(!locked.is_unsupported());
assert_eq!(locked.bytes_locked(), 1024);
assert_eq!(locked.failure_errno(), None);
let failed = MlockStatus::Failed { errno: 1 };
assert!(!failed.is_locked());
assert!(failed.is_failed());
assert!(!failed.is_unsupported());
assert_eq!(failed.bytes_locked(), 0);
assert_eq!(failed.failure_errno(), Some(1));
let unsupported = MlockStatus::Unsupported;
assert!(!unsupported.is_locked());
assert!(!unsupported.is_failed());
assert!(unsupported.is_unsupported());
assert_eq!(unsupported.bytes_locked(), 0);
assert_eq!(unsupported.failure_errno(), None);
}
#[test]
fn test_mlock_status_display() {
let locked = MlockStatus::Locked { bytes_locked: 1024 };
assert!(format!("{locked}").contains("locked"));
let failed = MlockStatus::Failed { errno: 12 };
assert!(format!("{failed}").contains("failed"));
let unsupported = MlockStatus::Unsupported;
assert!(format!("{unsupported}").contains("unsupported"));
}
}