use std::thread; use std::fs::{copy, remove_file}; use std::path::Path; use std::time::Duration; use pi_async_rt::rt::{AsyncRuntime, multi_thread::MultiTaskRuntimeBuilder, startup_global_time_loop}; use pi_store::devices::{BlockDevice, BlockLocation, DeviceStatus, simple_device::{Binary, SimpleDevice}}; use pi_blocks_allocator::device::{BuddyBlocksDeviceBuilder, BuddyBlocksDevice}; #[test] fn test_buddy_blocks_device() { env_logger::init(); let _handle = startup_global_time_loop(100); let builder = MultiTaskRuntimeBuilder::default(); let rt = builder.build(); let rt_copy = rt.clone(); rt.spawn(async move { //清理测试环境 let _r = remove_file("./buddy_blocks/000.dat"); let _r = remove_file("./buddy_blocks/000.dat.0"); let _r = remove_file("./buddy_blocks/000.dat.1"); let mut builder = BuddyBlocksDeviceBuilder::new("./buddy_blocks"); let device = builder .build(rt_copy.clone()) .await .unwrap(); assert!(device.is_full_free()); assert!(device.is_freed(&BlockLocation::empty())); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8); assert_eq!(device.avail_size().unwrap(), device.capacity().unwrap()); assert_eq!(device.used_size(), 0); assert_eq!(device.block_unit_len(), 4096); assert_eq!(device.max_block_size(), 4096 * 4096 * 8); assert_eq!(device.get_url().unwrap().to_string().as_str(), "file:///E:/rust/pi_mastser/crate%20master/pi_store/buddy_blocks/"); assert_eq!(device.get_status() as u8, 1); //测试分配 let mut blocks = Vec::with_capacity(10); for size in vec![1, 4096, 4097, 8192, 8193, 10000, 20000, 65536, 65537, 4096 * 4096 * 8, 4096 * 4096 * 8 + 1] { let block = device.alloc_block(size).await; match size { 1 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 1)); assert_eq!(device.used_size(), 1 * 4096); }, 4096 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 2)); assert_eq!(device.used_size(), 2 * 4096); }, 4097 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 4)); assert_eq!(device.used_size(), 4 * 4096); }, 8192 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 6)); assert_eq!(device.used_size(), 6 * 4096); }, 8193 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 10)); assert_eq!(device.used_size(), 10 * 4096); }, 10000 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 14)); assert_eq!(device.used_size(), 14 * 4096); }, 20000 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 22)); assert_eq!(device.used_size(), 22 * 4096); }, 65536 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 38)); assert_eq!(device.used_size(), 38 * 4096); }, 65537 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 70)); assert_eq!(device.used_size(), 70 * 4096); }, 134217728 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 70)); assert_eq!(device.used_size(), 134504448); }, 134217729 => { assert!(block.is_empty()); assert!(device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 70)); assert_eq!(device.used_size(), 134504448); }, _ => unimplemented!(), } blocks.push(block); } //测试读写 for (index, block) in blocks.iter().enumerate() { if !device.is_freed(&block) { let r = device .write(block, &format!("This is {:?}", index).into_bytes()) .await; assert!(r.is_ok()); } } for (index, block) in blocks.iter().enumerate() { if !device.is_freed(&block) { let r = device .read(block) .await; assert!(r.is_ok()); assert_eq!(String::from_utf8_lossy(&r.unwrap()[..9]).to_string(), format!("This is {:?}", index)); println!("read {:?} ok", index); } } //测试释放前复制块文件 rt_copy.timeout(6000).await; let from = "./buddy_blocks/000.dat"; let to = "./buddy_blocks/000.dat.0"; let r = copy(from, to); assert!(r.is_ok()); //测试释放 for (index, block) in blocks.into_iter().enumerate() { if !device.is_freed(&block) { println!("free block: {:?}", block); let r = device.free_block(&block).await; assert!(r); assert!(device.is_freed(&block)); match index { 0 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 69)); assert_eq!(device.used_size(), 134504448 - 1 * 4096); }, 1 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 68)); assert_eq!(device.used_size(), 134504448 - 2 * 4096); }, 2 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 66)); assert_eq!(device.used_size(), 134504448 - 4 * 4096); }, 3 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 64)); assert_eq!(device.used_size(), 134504448 - 6 * 4096); }, 4 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 60)); assert_eq!(device.used_size(), 134504448 - 10 * 4096); }, 5 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 56)); assert_eq!(device.used_size(), 134504448 - 14 * 4096); }, 6 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 48)); assert_eq!(device.used_size(), 134504448 - 22 * 4096); }, 7 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 32)); assert_eq!(device.used_size(), 134504448 - 38 * 4096); }, 8 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 0)); assert_eq!(device.used_size(), 134504448 - 70 * 4096); }, 9 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.used_size(), 134504448 - 70 * 4096 - 4096 * 4096 * 8); }, _ => unimplemented!(), } } } println!("======================="); //再测试分配 let mut blocks = Vec::with_capacity(10); for size in vec![1, 4096, 4097, 8192, 8193, 10000, 20000, 65536, 65537, 4096 * 4096 * 8, 4096 * 4096 * 8 + 1] { let block = device.alloc_block(size).await; match size { 1 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 1)); assert_eq!(device.used_size(), 1 * 4096); }, 4096 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 2)); assert_eq!(device.used_size(), 2 * 4096); }, 4097 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 4)); assert_eq!(device.used_size(), 4 * 4096); }, 8192 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 6)); assert_eq!(device.used_size(), 6 * 4096); }, 8193 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 10)); assert_eq!(device.used_size(), 10 * 4096); }, 10000 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 14)); assert_eq!(device.used_size(), 14 * 4096); }, 20000 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 22)); assert_eq!(device.used_size(), 22 * 4096); }, 65536 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 38)); assert_eq!(device.used_size(), 38 * 4096); }, 65537 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 * 2 - 70)); assert_eq!(device.used_size(), 70 * 4096); }, 134217728 => { assert!(!block.is_empty()); assert!(!device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 70)); assert_eq!(device.used_size(), 134504448); }, 134217729 => { assert!(block.is_empty()); assert!(device.is_freed(&block)); assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 70)); assert_eq!(device.used_size(), 134504448); }, _ => unimplemented!(), } blocks.push(block); } //再测试读写 for (index, block) in blocks.iter().enumerate() { if !device.is_freed(&block) { let r = device .write(block, &format!("This is {:?}", index).into_bytes()) .await; assert!(r.is_ok()); } } for (index, block) in blocks.iter().enumerate() { if !device.is_freed(&block) { let r = device .read(block) .await; assert!(r.is_ok()); assert_eq!(String::from_utf8_lossy(&r.unwrap()[..9]).to_string(), format!("This is {:?}", index)); println!("read {:?} ok", index); } } //再测试释放前复制块文件 rt_copy.timeout(6000).await; let from = "./buddy_blocks/000.dat"; let to = "./buddy_blocks/000.dat.1"; let r = copy(from, to); assert!(r.is_ok()); //再测试释放 for (index, block) in blocks.into_iter().enumerate() { if !device.is_freed(&block) { println!("free block: {:?}", block); let r = device.free_block(&block).await; assert!(r); assert!(device.is_freed(&block)); match index { 0 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 69)); assert_eq!(device.used_size(), 134504448 - 1 * 4096); }, 1 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 68)); assert_eq!(device.used_size(), 134504448 - 2 * 4096); }, 2 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 66)); assert_eq!(device.used_size(), 134504448 - 4 * 4096); }, 3 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 64)); assert_eq!(device.used_size(), 134504448 - 6 * 4096); }, 4 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 60)); assert_eq!(device.used_size(), 134504448 - 10 * 4096); }, 5 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 56)); assert_eq!(device.used_size(), 134504448 - 14 * 4096); }, 6 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 48)); assert_eq!(device.used_size(), 134504448 - 22 * 4096); }, 7 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 32)); assert_eq!(device.used_size(), 134504448 - 38 * 4096); }, 8 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * (4096 * 8 - 0)); assert_eq!(device.used_size(), 134504448 - 70 * 4096); }, 9 => { assert_eq!(device.capacity().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.avail_size().unwrap(), 4096 * 4096 * 8 * 2); assert_eq!(device.used_size(), 134504448 - 70 * 4096 - 4096 * 4096 * 8); }, _ => unimplemented!(), } } } }); thread::sleep(Duration::from_millis(1000000000)); } #[test] fn test_load_buddy_blocks_device_after_crashed() { env_logger::init(); let _handle = startup_global_time_loop(100); let builder = MultiTaskRuntimeBuilder::default(); let rt = builder.build(); let rt_copy = rt.clone(); rt.spawn(async move { let mut builder = BuddyBlocksDeviceBuilder::new("./buddy_blocks1"); builder = builder.set_collect_interval(Duration::from_millis(1000000000)); let device = builder .build(rt_copy.clone()) .await .unwrap(); assert_eq!(device.max_block_size(), 4096 * 4096 * 8); assert_eq!(device.get_url().unwrap().to_string().as_str(), "file:///E:/rust/pi_mastser/crate%20master/pi_store/buddy_blocks1/"); assert_eq!(device.get_status() as u8, 1); let metadata = device.get_metadata().await; println!("device metadata: {:#?}", metadata); //测试分配 let mut blocks = Vec::with_capacity(10); for size in vec![1, 4096, 4097, 8192, 8193, 10000, 20000, 65536, 65537, 4096 * 4096 * 8, 4096 * 4096 * 8 + 1] { let block = device.alloc_block(size).await; blocks.push(block); } //测试读写 for (index, block) in blocks.iter().enumerate() { if !device.is_freed(&block) { let r = device .write(block, &format!("This is {:?}", index).into_bytes()) .await; assert!(r.is_ok()); } } for (index, block) in blocks.iter().enumerate() { if !device.is_freed(&block) { let r = device .read(block) .await; assert!(r.is_ok()); assert_eq!(String::from_utf8_lossy(&r.unwrap()[..9]).to_string(), format!("This is {:?}", index)); println!("read {:?} ok", index); } } //关闭进程前提交脏块组和脏块索引 let r = device.mamually_commit_block_groups().await; assert!(r.is_ok()); let r = device.mamually_commit_block_indexes().await; assert!(r.is_ok()); let metadata = device.get_metadata().await; println!("device metadata: {:#?}", metadata); std::process::exit(0); }); thread::sleep(Duration::from_millis(1000000000)); } #[test] fn test_simple_device() { let builder = MultiTaskRuntimeBuilder::default(); let rt = builder.build(); let rt_copy = rt.clone(); rt.spawn(async move { match SimpleDevice::open(rt_copy, "./device/0.simple", None).await { Err(e) => panic!("Open simple device failed, reason: {:?}", e), Ok(device) => { println!("!!!!!!device: {:?}", device.get_status()); let location = device.alloc_block(50).await; println!("!!!!!!location: {:?}", location); match device.write(&location, &Binary::new("Hello Simple device".to_string().into_bytes())).await { Err(e) => panic!("Write block failed, reason: {:?}", e), Ok(len) => { println!("!!!!!!write ok, len: {}", len); } } match device.read(&location).await { Err(e) => panic!("Read block failed, reason: {:?}", e), Ok(block) => { println!("read writed data: {:?}", String::from_utf8_lossy(block.as_ref())) } } }, } }); thread::sleep(Duration::from_millis(1000000000)); } // 先执行一次test_simple_device,再执行 #[test] fn test_simple_device_collect() { let builder = MultiTaskRuntimeBuilder::default(); let rt = builder.build(); let rt_copy = rt.clone(); rt.spawn(async move { match SimpleDevice::open(rt_copy, "./device/0.simple", None).await { Err(e) => panic!("Open simple device failed, reason: {:?}", e), Ok(device) => { println!("!!!!!!device: {:?}", device.get_status()); match device.collect_alloced_blocks(&[BlockLocation::from(1)]).await { Err(e) => println!("Collect alloced failed, reason: {:?}", e), Ok(size) => { println!("collect alloced ok, size: {}", size); } } let location = device.alloc_block(50).await; println!("!!!!!!location: {:?}", location); match device.write(&location, &Binary::new("Hello Simple device".to_string().into_bytes())).await { Err(e) => panic!("Write block failed, reason: {:?}", e), Ok(len) => { println!("!!!!!!write ok, len: {}", len); } } match device.read(&location).await { Err(e) => panic!("Read block failed, reason: {:?}", e), Ok(block) => { println!("read writed data: {:?}", String::from_utf8_lossy(block.as_ref())) } } }, } }); thread::sleep(Duration::from_millis(1000000000)); }