use crate::{Config, Result};
pub mod fs;
pub mod threading;
pub mod time;
#[derive(Debug)]
pub struct Platform {
fs: fs::FileSystem,
time: time::TimeProvider,
threading: threading::ThreadingProvider,
config: Config,
}
impl Platform {
pub async fn new(config: &Config) -> Result<Self> {
Ok(Self {
fs: fs::FileSystem::new().await?,
time: time::TimeProvider::new(),
threading: threading::ThreadingProvider::new(),
config: config.clone(),
})
}
pub fn fs(&self) -> &fs::FileSystem {
&self.fs
}
pub fn time(&self) -> &time::TimeProvider {
&self.time
}
pub fn threading(&self) -> &threading::ThreadingProvider {
&self.threading
}
pub fn config(&self) -> &Config {
&self.config
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::Path;
use tempfile::TempDir;
#[tokio::test]
async fn test_platform_creation() {
let config = Config::default();
let platform = Platform::new(&config).await.unwrap();
assert!(platform.fs().exists(Path::new(".")).await.unwrap());
}
#[tokio::test]
async fn test_file_system() {
let config = Config::default();
let platform = Platform::new(&config).await.unwrap();
let fs = platform.fs();
let temp_dir = TempDir::new().unwrap();
let test_file = temp_dir.path().join("test.txt");
let content = b"Hello, World!";
fs.write_file(&test_file, content).await.unwrap();
assert!(fs.exists(&test_file).await.unwrap());
let read_content = fs.read_file(&test_file).await.unwrap();
assert_eq!(read_content, content);
let size = fs.file_size(&test_file).await.unwrap();
assert_eq!(size, content.len() as u64);
fs.remove_file(&test_file).await.unwrap();
assert!(!fs.exists(&test_file).await.unwrap());
}
#[test]
fn test_time_provider() {
let time = time::TimeProvider::new();
let now_micros = time.now_micros();
let now_millis = time.now_millis();
let now_secs = time.now_secs();
assert!(now_micros > 0);
assert!(now_millis > 0);
assert!(now_secs > 0);
let micros_to_millis = now_micros / 1000;
let millis_to_secs = now_millis / 1000;
let tolerance_ms: u64 = 5;
let tolerance_sec: u64 = 1;
assert!(
micros_to_millis >= now_millis.saturating_sub(tolerance_ms),
"micros_to_millis ({}) should be within {}ms of now_millis ({})",
micros_to_millis,
tolerance_ms,
now_millis
);
assert!(
millis_to_secs >= now_secs.saturating_sub(tolerance_sec),
"millis_to_secs ({}) should be within {}s of now_secs ({})",
millis_to_secs,
tolerance_sec,
now_secs
);
}
#[tokio::test]
async fn test_threading_provider() {
let threading = threading::ThreadingProvider::new();
let result = threading.execute_cpu_task(|| 42).await.unwrap();
assert_eq!(result, 42);
let result = threading
.execute_io_task(|| "hello".to_string())
.await
.unwrap();
assert_eq!(result, "hello");
}
}