|
| 1 | +//! |
| 2 | +//! The macro in this file takes 3 arguments: |
| 3 | +//! 1. The name of the function to generate |
| 4 | +//! 2. The return type of the function |
| 5 | +//! 3. A brace-enclosed, comma-separated list of module |
| 6 | +//! names |
| 7 | +//! |
| 8 | +//! Each module in (3) should match the basename of a file in `tests/messages` but with dashes |
| 9 | +//! replaced by underscores to make it a valid Rust identifier. When the generated function is |
| 10 | +//! called with a filename that matches one of these modules, it will call the `expected()` |
| 11 | +//! function of that module, which should return an object of the return type specified in the |
| 12 | +//! macro, which will be returned as Some(expected()). If the generated function is called with a |
| 13 | +//! filename that does not match any module, it will return `None`. |
| 14 | +//! |
| 15 | +//! # Example # |
| 16 | +//! |
| 17 | +//! ## Macro call ## |
| 18 | +//! |
| 19 | +//! ```ignore |
| 20 | +//! use ssh_agent_lib::proto::Request; |
| 21 | +//! |
| 22 | +//! make_expected_fn!(get_expected_request, Request, { |
| 23 | +//! req_hello |
| 24 | +//! }); |
| 25 | +//! ``` |
| 26 | +//! |
| 27 | +//! ## Usage of generated function in test code ## |
| 28 | +//! |
| 29 | +//! ```ignore |
| 30 | +//! let test_data_path = PathBuf::from("test/messages/req-hello.bin"); |
| 31 | +//! let expected = path::to::get_expected_request(&test_data_path); |
| 32 | +//! assert_eq!(expected, ...); |
| 33 | +//! ``` |
| 34 | +//! |
| 35 | +//! ## `path/to/req_hello.rs` ## |
| 36 | +//! |
| 37 | +//! ```ignore |
| 38 | +//! pub fn expected() -> Request { |
| 39 | +//! ... |
| 40 | +//! } |
| 41 | +//! ``` |
| 42 | +
|
| 43 | +macro_rules! make_expected_fn { |
| 44 | + ($fn_name:ident -> $ty:ty, { $($case:ident),+ } ) => { |
| 45 | + $( mod $case; )+ |
| 46 | + |
| 47 | + pub fn $fn_name(path: impl ::core::convert::AsRef<::std::path::Path>) -> ::core::option::Option<$ty> { |
| 48 | + let cases: &[(&str, &dyn ::core::ops::Fn() -> $ty)] = &[ |
| 49 | + $( (::core::stringify!($case), &self::$case::expected,) ),+ |
| 50 | + ]; |
| 51 | + |
| 52 | + let path_case_name = path |
| 53 | + .as_ref() |
| 54 | + .file_stem() |
| 55 | + .expect("test path has no filename") |
| 56 | + .to_str() |
| 57 | + .expect("test filename not UTF-8") |
| 58 | + .replace("-", "_"); |
| 59 | + |
| 60 | + cases |
| 61 | + .into_iter() |
| 62 | + .find(|(c, _)| c == &path_case_name) |
| 63 | + .map(|(_, f)| f()) |
| 64 | + } |
| 65 | + }; |
| 66 | +} |
0 commit comments