101453cd4SAlex Crichton use test_programs::p3::wasi;
201453cd4SAlex Crichton use test_programs::p3::wasi::filesystem::types::{
301453cd4SAlex Crichton     Descriptor, DescriptorFlags, DescriptorType, DirectoryEntry, OpenFlags, PathFlags,
401453cd4SAlex Crichton };
501453cd4SAlex Crichton 
601453cd4SAlex Crichton struct Component;
701453cd4SAlex Crichton 
801453cd4SAlex Crichton test_programs::p3::export!(Component);
901453cd4SAlex Crichton 
1001453cd4SAlex Crichton impl test_programs::p3::exports::wasi::cli::run::Guest for Component {
run() -> Result<(), ()>1101453cd4SAlex Crichton     async fn run() -> Result<(), ()> {
1201453cd4SAlex Crichton         let preopens = wasi::filesystem::preopens::get_directories();
1301453cd4SAlex Crichton         let (dir, _) = &preopens[0];
1401453cd4SAlex Crichton 
1501453cd4SAlex Crichton         test_readdir(dir).await;
1601453cd4SAlex Crichton         test_readdir_lots(dir).await;
1701453cd4SAlex Crichton         Ok(())
1801453cd4SAlex Crichton     }
1901453cd4SAlex Crichton }
2001453cd4SAlex Crichton 
main()2101453cd4SAlex Crichton fn main() {
2201453cd4SAlex Crichton     unreachable!()
2301453cd4SAlex Crichton }
2401453cd4SAlex Crichton 
read_dir(dir: &Descriptor) -> Vec<DirectoryEntry>2501453cd4SAlex Crichton async fn read_dir(dir: &Descriptor) -> Vec<DirectoryEntry> {
26bda02c19SBailey Hayes     let (dirs, result) = dir.read_directory();
2701453cd4SAlex Crichton     let mut dirs = dirs.collect().await;
2801453cd4SAlex Crichton     result.await.unwrap();
2901453cd4SAlex Crichton     dirs.sort_by_key(|d| d.name.clone());
3001453cd4SAlex Crichton     dirs
3101453cd4SAlex Crichton }
3201453cd4SAlex Crichton 
assert_empty_dir(dir: &Descriptor)3301453cd4SAlex Crichton async fn assert_empty_dir(dir: &Descriptor) {
3401453cd4SAlex Crichton     let dirs = read_dir(dir).await;
3501453cd4SAlex Crichton     assert_eq!(dirs.len(), 0);
3601453cd4SAlex Crichton }
3701453cd4SAlex Crichton 
test_readdir(dir: &Descriptor)3801453cd4SAlex Crichton async fn test_readdir(dir: &Descriptor) {
3901453cd4SAlex Crichton     // Check the behavior in an empty directory
4001453cd4SAlex Crichton     assert_empty_dir(dir).await;
4101453cd4SAlex Crichton 
4201453cd4SAlex Crichton     dir.open_at(
4301453cd4SAlex Crichton         PathFlags::empty(),
4401453cd4SAlex Crichton         "file".to_string(),
4501453cd4SAlex Crichton         OpenFlags::CREATE,
4601453cd4SAlex Crichton         DescriptorFlags::READ | DescriptorFlags::WRITE,
4701453cd4SAlex Crichton     )
4801453cd4SAlex Crichton     .await
4901453cd4SAlex Crichton     .unwrap();
5001453cd4SAlex Crichton 
5101453cd4SAlex Crichton     dir.create_directory_at("nested".to_string()).await.unwrap();
5201453cd4SAlex Crichton     let nested = dir
5301453cd4SAlex Crichton         .open_at(
5401453cd4SAlex Crichton             PathFlags::empty(),
5501453cd4SAlex Crichton             "nested".to_string(),
5601453cd4SAlex Crichton             OpenFlags::DIRECTORY,
5701453cd4SAlex Crichton             DescriptorFlags::empty(),
5801453cd4SAlex Crichton         )
5901453cd4SAlex Crichton         .await
6001453cd4SAlex Crichton         .unwrap();
6101453cd4SAlex Crichton 
6201453cd4SAlex Crichton     let entries = read_dir(dir).await;
6301453cd4SAlex Crichton     assert_eq!(entries.len(), 2);
6401453cd4SAlex Crichton     assert_eq!(entries[0].name, "file");
65*5d3627b7SBailey Hayes     assert!(matches!(entries[0].type_, DescriptorType::RegularFile));
6601453cd4SAlex Crichton     assert_eq!(entries[1].name, "nested");
67*5d3627b7SBailey Hayes     assert!(matches!(entries[1].type_, DescriptorType::Directory));
6801453cd4SAlex Crichton 
6901453cd4SAlex Crichton     assert_empty_dir(&nested).await;
7001453cd4SAlex Crichton     drop(nested);
7101453cd4SAlex Crichton 
7201453cd4SAlex Crichton     dir.unlink_file_at("file".to_string()).await.unwrap();
7301453cd4SAlex Crichton     dir.remove_directory_at("nested".to_string()).await.unwrap();
7401453cd4SAlex Crichton }
7501453cd4SAlex Crichton 
test_readdir_lots(dir: &Descriptor)7601453cd4SAlex Crichton async fn test_readdir_lots(dir: &Descriptor) {
7701453cd4SAlex Crichton     for count in 0..1000 {
7801453cd4SAlex Crichton         dir.open_at(
7901453cd4SAlex Crichton             PathFlags::empty(),
8001453cd4SAlex Crichton             format!("file.{count}"),
8101453cd4SAlex Crichton             OpenFlags::CREATE,
8201453cd4SAlex Crichton             DescriptorFlags::READ | DescriptorFlags::WRITE,
8301453cd4SAlex Crichton         )
8401453cd4SAlex Crichton         .await
8501453cd4SAlex Crichton         .expect("failed to create file");
8601453cd4SAlex Crichton     }
8701453cd4SAlex Crichton 
8801453cd4SAlex Crichton     assert_eq!(read_dir(dir).await.len(), 1000);
8901453cd4SAlex Crichton 
9001453cd4SAlex Crichton     for count in 0..1000 {
9101453cd4SAlex Crichton         dir.unlink_file_at(format!("file.{count}"))
9201453cd4SAlex Crichton             .await
9301453cd4SAlex Crichton             .expect("removing a file");
9401453cd4SAlex Crichton     }
9501453cd4SAlex Crichton }
96