|
| 1 | +use std::collections::HashSet; |
| 2 | +use std::fs::{DirEntry, File}; |
| 3 | +use std::path::PathBuf; |
| 4 | +use std::sync::LazyLock; |
| 5 | + |
| 6 | +use apollo_infra_utils::compile_time_cargo_manifest_dir; |
| 7 | + |
| 8 | +static CAIRO_FILE_LIST_PATH: LazyLock<PathBuf> = LazyLock::new(|| { |
| 9 | + PathBuf::from(compile_time_cargo_manifest_dir!()).join("src/cairo_files_list.json") |
| 10 | +}); |
| 11 | +static CAIRO_FILE_LIST: LazyLock<Vec<String>> = LazyLock::new(|| { |
| 12 | + serde_json::from_reader( |
| 13 | + File::open(&*CAIRO_FILE_LIST_PATH) |
| 14 | + .unwrap_or_else(|error| panic!("Failed to open {CAIRO_FILE_LIST_PATH:?}: {error:?}.")), |
| 15 | + ) |
| 16 | + .unwrap_or_else(|error| panic!("Failed to deserialize {CAIRO_FILE_LIST_PATH:?}: {error:?}.")) |
| 17 | +}); |
| 18 | + |
| 19 | +/// Utility function for `get_cairo_file_list`. |
| 20 | +fn get_cairo_file_list_recursive(entry: DirEntry) -> Vec<String> { |
| 21 | + let file_type = entry.file_type().unwrap(); |
| 22 | + if file_type.is_dir() { |
| 23 | + std::fs::read_dir(entry.path()) |
| 24 | + .unwrap() |
| 25 | + .flat_map(|entry| get_cairo_file_list_recursive(entry.unwrap())) |
| 26 | + .collect() |
| 27 | + } else { |
| 28 | + assert!(file_type.is_file()); |
| 29 | + if entry.path().extension().unwrap_or_default() == "cairo" { |
| 30 | + Vec::from_iter(std::iter::once(entry.path().to_str().unwrap().to_string())) |
| 31 | + } else { |
| 32 | + Vec::new() |
| 33 | + } |
| 34 | + } |
| 35 | +} |
| 36 | + |
| 37 | +/// Find all files with a .cairo extension in the `src` directory. |
| 38 | +fn get_cairo_file_set() -> HashSet<String> { |
| 39 | + let base_path = PathBuf::from(compile_time_cargo_manifest_dir!()).join("src"); |
| 40 | + let base_path_string = base_path.to_str().unwrap(); |
| 41 | + std::fs::read_dir(base_path_string) |
| 42 | + .unwrap() |
| 43 | + .flat_map(|entry| get_cairo_file_list_recursive(entry.unwrap())) |
| 44 | + .map(|path| { |
| 45 | + assert!(path.starts_with(&base_path_string)); |
| 46 | + path.strip_prefix(&base_path_string) |
| 47 | + .unwrap() |
| 48 | + .strip_prefix("/cairo/") |
| 49 | + .unwrap() |
| 50 | + .to_string() |
| 51 | + }) |
| 52 | + .collect() |
| 53 | +} |
| 54 | + |
| 55 | +/// Tests that the list of Cairo files in the `src` directory matches the actual set of cairo files |
| 56 | +/// in the crate. |
| 57 | +/// To fix this test, run the following command: |
| 58 | +/// ```bash |
| 59 | +/// FIX_OS_FILE_LIST=1 cargo test -p apollo_starknet_os_program test_cairo_file_list |
| 60 | +/// ``` |
| 61 | +#[test] |
| 62 | +fn test_cairo_file_list() { |
| 63 | + let actual_files = get_cairo_file_set(); |
| 64 | + let expected_files: HashSet<String> = HashSet::from_iter(CAIRO_FILE_LIST.iter().cloned()); |
| 65 | + if std::env::var("FIX_OS_FILE_LIST").is_ok() { |
| 66 | + let mut actual_files_vec = Vec::from_iter(actual_files.iter()); |
| 67 | + actual_files_vec.sort(); |
| 68 | + std::fs::write( |
| 69 | + CAIRO_FILE_LIST_PATH.as_path(), |
| 70 | + serde_json::to_string_pretty(&actual_files_vec).unwrap(), |
| 71 | + ) |
| 72 | + .expect("Failed to write the cairo file list."); |
| 73 | + } else { |
| 74 | + assert_eq!(actual_files, expected_files); |
| 75 | + } |
| 76 | +} |
0 commit comments