首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >QuickCheck堆栈溢出

QuickCheck堆栈溢出
EN

Stack Overflow用户
提问于 2022-06-21 13:23:31
回答 1查看 71关注 0票数 0

我有以下结构:

代码语言:javascript
复制
pub struct Restriction {
    pub min: Option<u64>,
    pub max: Option<u64>,
}

对此,我将Arbitrary定义为:

代码语言:javascript
复制
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())
                }
            }
        }))
    }
}

我还有这个测试用例:

代码语言:javascript
复制
    #[quickcheck]
    fn restriction_silly(x: Restriction) -> bool {
        let y = Restriction {
            min: None,
            max: None,
        };
        x == y
    }

如果没有shrink的自定义实现,则生成的反示例如下:

代码语言:javascript
复制
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会出现测试错误。

我甚至编写了以下测试(它通过了很好的测试),以检查限制是否确实缩小到了空限制:

代码语言:javascript
复制
    #[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实现有什么问题感到很困惑。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-21 15:03:01

收缩实现需要150亿次迭代才能完成。我不知道quickcheck是如何工作的,但是如果它从递归函数调用shrink,难怪会有堆栈溢出。即使它迭代地调用了您的函数,您也需要很长的时间来完成。我建议您尝试一些更快的收敛函数(例如使用x/2而不是x-1):

代码语言:javascript
复制
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())
            }
        }
    }))
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72701596

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档