我有以下结构:
pub struct Restriction {
pub min: Option<u64>,
pub max: Option<u64>,
}对此,我将Arbitrary定义为:
impl Arbitrary for Restriction {
fn arbitrary(g: &mut Gen) -> Self {
let x = Option::<u64>::arbitrary(g);
let y = Option::<u64>::arbitrary(g);
let (min, max) = match (x, y) {
(Some(x_), Some(y_)) if x > y => (Some(y_), Some(x_)),
vals => vals,
};
Restriction { min, max }
}
fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
Box::new(unfold(self.clone(), |r| {
let next_min = match r.min {
None => None,
Some(0) => Some(None),
Some(x) => Some(Some(x - 1)),
};
let next_max = match r.max {
None => None,
Some(0) => Some(None),
Some(x) => Some(Some(x - 1)),
};
match (next_min, next_max) {
(None, None) => None,
(None, Some(max)) => {
r.max = max;
Some(r.clone())
}
(Some(min), None) => {
r.min = min;
Some(r.clone())
}
(Some(min), Some(max)) => {
r.min = min;
r.max = max;
Some(r.clone())
}
}
}))
}
}我还有这个测试用例:
#[quickcheck]
fn restriction_silly(x: Restriction) -> bool {
let y = Restriction {
min: None,
max: None,
};
x == y
}如果没有shrink的自定义实现,则生成的反示例如下:
Restriction { min: Some(15789104099073884865), max: Some(16586241492943163879) }从直觉上可以看出,一个更好的反例可以是Restriction { min: Some(1), max: None },我甚至会接受Restriction { min: Some(1), max: Some(1) }。
不幸的是,在使用我的自定义shrink实现时,fatal runtime error: stack overflow会出现测试错误。
我甚至编写了以下测试(它通过了很好的测试),以检查限制是否确实缩小到了空限制:
#[test]
fn restriction_shrink_to_empty() -> Result<(), std::io::Error> {
let r = Restriction {
min: Some(3),
max: Some(7),
};
assert_eq!(r.shrink().last(), Some(Restriction::EMPTY));
Ok(())
}因此,我现在对我的shrink实现有什么问题感到很困惑。
发布于 2022-06-21 15:03:01
收缩实现需要150亿次迭代才能完成。我不知道quickcheck是如何工作的,但是如果它从递归函数调用shrink,难怪会有堆栈溢出。即使它迭代地调用了您的函数,您也需要很长的时间来完成。我建议您尝试一些更快的收敛函数(例如使用x/2而不是x-1):
fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
Box::new(unfold(self.clone(), |r| {
let next_min = match r.min {
None => None,
Some(0) => Some(None),
Some(x) => Some(Some(x / 2)),
};
let next_max = match r.max {
None => None,
Some(0) => Some(None),
Some(x) => Some(Some(x / 2)),
};
match (next_min, next_max) {
(None, None) => None,
(None, Some(max)) => {
r.max = max;
Some(r.clone())
}
(Some(min), None) => {
r.min = min;
Some(r.clone())
}
(Some(min), Some(max)) => {
r.min = min;
r.max = max;
Some(r.clone())
}
}
}))
}https://stackoverflow.com/questions/72701596
复制相似问题