bench!
:
- 插入
#[bench]
测试代码,无需再手动引入test::Bencher
,让单元测试里的函数名与被测试的函数 同名 。(最重要的目的是,我想让测试函数与被测试函数同名) - 两种测试样式:封装成
assert_eq!
型;传入辅助测试函数(里面可测试多个断言)和被测试函数型。 - 为了避免同时使用两种测试样式造成同名冲突(或者与测试模块下其他函数重名),可选添加函数名前缀。
例子:
#[cfg(test)]
mod bench {
fn string_from(s: &str) -> String { String::from(s) }
bench!(string_from(""); target = ""; prefix = __); // 如果没有前缀,会与 string_from 重名冲突
bench!(String::from(""); target = ""; prefix = __); // 如果没有前缀,会与 from 重名冲突
fn assert<F>(f: F)
where F: Fn(&'static str) -> String {
assert_eq!(f(""), "");
}
bench!(assert string_from; prefix = ___); // 如果没有前缀,会与 string_from 重名冲突
bench!(assert String::from); // 取 from 函数名
}
test _macros::bench::___string_from ... ok
test _macros::bench::__from ... ok
test _macros::bench::__string_from ... ok
test _macros::bench::from ... ok
vec_pos!
:
- 目的:打印数组和索引名称与位置。
- 索引名称与位置参数有两种样式:传入外部定义的变量名;传入
未定义的变量名 = 位置
。 - 同一个位置多个索引名称时,只打印第一个传入的名称。
- 索引名称长度超过打印的数组元素长度时,截断名称。
- 索引位置不必有序。
例子:
#[test]
fn pos() {
let v = vec![1, 2, 3];
assert_eq!(vec_pos!(v; i = 1, j = 2, k = 0), ["[1 2 3]", " 0 1 2 ", " k i j "]);
assert_eq!(vec_pos!(v; i = 1, j = 1, k = 0), ["[1 2 3]", " 0 1 ", " k i "]);
let n = 1;
assert_eq!(vec_pos!(v; n), ["[1 2 3]", " 1 ", " n "]);
assert_eq!(vec_pos!(v; i = n, j = 1, k = 0), ["[1 2 3]", " 0 1 ", " k i "]);
let v = vec!["hello", "world", "!"];
assert_eq!(vec_pos!(v; i = 1, j_trunc = 2, k = 0), ["[\"hello\" \"world\" \"!\"]",
" 0 1 2 ",
" k i j_tr"]);
let v = vec![1.2, 0., -8.5];
assert_eq!(vec_pos!(v; i = 1, j = 2, k = 0), ["[1.2 0.0 -8.5]",
" 0 1 2 ",
" k i j "]);
}
定义的代码:
#[macro_export]
macro_rules! bench {
() => {};
($func:ident($($args:expr),*); target = $target:expr $(; prefix = $prefix:ident)?) => {
paste::paste! {
#[bench]
fn [<$($prefix)? $func>](b: &mut test::Bencher) {
b.iter(|| { assert_eq!($func($($args),*), $target); })
}
}
};
($solution:tt:: $func:ident($($args:expr),*); target = $target:expr $(; prefix = $prefix:ident)?) => {
// ($solution:tt:: $func:ident($($args:expr),*); $(target = )? $target:expr) => {
paste::paste! {
#[bench]
fn [<$($prefix)? $func>](b: &mut test::Bencher) {
b.iter(|| { assert_eq!($solution::$func($($args),*), $target); })
}
}
};
($assert:ident $func:ident $(; prefix = $prefix:ident)?) => {
paste::paste! {
#[bench]
fn [<$($prefix)? $func>](b: &mut test::Bencher) { b.iter(|| { $assert($func); }) }
}
};
($assert:ident $solution:tt:: $func:ident $(; prefix = $prefix:ident)?) => {
paste::paste! {
#[bench]
fn [<$($prefix)? $func>](b: &mut test::Bencher) { b.iter(|| { $assert($solution::$func); }) }
}
};
}
#[macro_export]
macro_rules! vec_pos {
() => {};
($vec:expr; $($name:ident = $pos:expr),*) => {
$crate::_macros::vec_pos(format!("{:?}", $vec), vec![$(stringify!($name)),*], vec![$($pos),*])
};
($vec:expr; $($pos:expr),*) => {
$crate::_macros::vec_pos(format!("{:?}", $vec), vec![$(stringify!($pos)),*], vec![$($pos),*])
};
}
pub fn vec_pos(v_str: String, names: Vec<&str>, pos: Vec<usize>) -> [String; 3] {
// 排序、去重
let mut names_pos = names.into_iter().zip(pos).collect::<Vec<_>>();
names_pos.sort_by_key(|(_a, b)| *b);
names_pos.dedup_by_key(|(_a, b)| *b);
let (names, pos): (Vec<_>, Vec<_>) = names_pos.into_iter().unzip();
let [mut v_res, mut pos_res, mut name_res]: [String; 3] = Default::default();
let mut name;
for (i, v) in v_str.split(',').enumerate() {
v_res = format!("{}{}", v_res, v);
if let Ok(p) = pos.binary_search(&i) {
pos_res = format!("{} {}{}", pos_res, i, " ".repeat(v.len() - i.to_string().len() - 1));
name = names[p];
name_res = if v.len() - 1 < name.len() {
format!("{} {}", name_res, &name[..v.len() - 1])
} else {
format!("{} {}{}", name_res, name, " ".repeat(v.len() - name.len() - 1))
};
} else {
pos_res = format!("{}{}", pos_res, " ".repeat(v.len()),);
name_res = format!("{}{}", name_res, " ".repeat(v.len()));
}
}
println!("{}\n{}\n{}", v_res, pos_res, name_res);
[v_res, pos_res, name_res]
}
Ext Link: https://gitee.com/ZIP97/leetcode/blob/master/src/_macros.rs
1
共 0 条评论, 1 页
评论区
写评论还没有评论