Testing 无限循环的clojure检验

Testing 无限循环的clojure检验,testing,clojure,Testing,Clojure,我想编写一个测试(使用clojure.test)来验证某些示例代码是否不会导致无限循环。如果我正在测试的代码有缺陷,并且确实导致了无限循环,那么我希望测试工具报告失败——而不是永远停止循环。(我假设一种无限循环不会溢出堆栈。) 有什么办法吗?这相当于解决,这是不可能的。当然,在一般情况下你不能这样做,如果你想解决一个更简单的问题,比如“这个函数是否在最多五秒钟内完成执行?”那么你可以相对轻松地完成。例如,请参见clojure自身中的a: (defn sample [& args] 0

我想编写一个测试(使用
clojure.test
)来验证某些示例代码是否不会导致无限循环。如果我正在测试的代码有缺陷,并且确实导致了无限循环,那么我希望测试工具报告失败——而不是永远停止循环。(我假设一种无限循环不会溢出堆栈。)


有什么办法吗?

这相当于解决,这是不可能的。

当然,在一般情况下你不能这样做,如果你想解决一个更简单的问题,比如“这个函数是否在最多五秒钟内完成执行?”那么你可以相对轻松地完成。例如,请参见clojure自身中的a:

(defn sample [& args]
  0)

(deftest test-vars-apply-lazily
  (is (= 0 (deref (future (apply sample (range)))
                  1000 :timeout)))
  (is (= 0 (deref (future (apply #'sample (range)))
                  1000 :timeout))))

创建一个做你想做的事情的未来,然后在超时的情况下取消该未来。

此外,如果已知你的循环将相同的数据传递给下一次迭代,以获得相同的输入数据(在某种程度上是纯的),那么你可能可以确定,如果在不同的Itation上遇到相同的循环参数,那么循环可能是无限的(这意味着它在某个地方循环了自己)。例如(相当愚蠢的一个):

所以当你第二次遇到
(=i10)
时,你知道它是无限的

也许您可以创建一些宏,仅用于测试目的,它将跟踪循环的参数并找到重复的参数,如以下答案所示:


在一般情况下[对于无限内存等假设],您(可证明,comp sci 101数学不可能)无法用任何语言实现这一点。我可以设想一个在某些特殊情况下有效的答案——即重新编译代码以查找蹦床或循环/重复调用,并将当前状态与之前观察到的每个状态进行比较,如果以前见过某个状态,则终止该操作——但一个永不重复给定状态两次的无限循环并不难实现……现在,如果你只是想做一个断言,比如“这应该总是在不到N毫秒的挂钟时间内完成”(或者CPU时间或你拥有的时间),那就容易多了。感谢你理解了问题的精神。这个答案并没有阻止
(apply sample(range))
在后台运行,消耗资源<代码>期货取消可以停止期货。你将如何将终止未来整合到这个答案中?@Teodor
future cancel
可以在某些时候取消某些期货。但只有当该线程上发生的操作执行某些操作时,JVM才有机会发出停止的信号:通常这是I/O。即使使用
future cancel
,也无法停止此问题中的操作,一般来说,我建议不要依赖于
未来取消
来确保程序的正确性。谢谢您的解释。作为参考,
future cancel
在一个从1开始计数的函数上工作,每个
println
之间有一个
(线程/睡眠1000)
1秒的等待时间。是的,因为
线程/睡眠
显然是我命名的操作之一:它会导致线程暂时放弃控制,并要求线程计划线程同时被取消的可能性。在编写单元测试时,我们定义了预期的行为。你是对的,如果我想定义一个预期的行为,“这个代码最终会返回一个值,即使它需要10亿年”,我必须解决停止问题。我并不认为这是对这个问题的合理解释,但你是对的,我没有指定代码应该在合理的时间内返回一个值。您已经给出了一个没有人会问的问题的正确答案(在堆栈溢出时),这样的答案和注释说明了QA格式的工作情况。不,事先查明申请是否会终止是不可能的。但是,出于实际目的,我们可以使用超时来获得答案。两人都投赞成票!
(loop [i 20]
  (if (zero? i)
    (recur 10)
    (recur (dec i))))