首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Elisp:在ert中运行测试时睡眠不会阻塞

Elisp:在ert中运行测试时睡眠不会阻塞
EN

Stack Overflow用户
提问于 2013-02-05 08:13:03
回答 4查看 735关注 0票数 3

我正在尝试使用ert设置一些测试,这些测试需要休眠才能使后台进程继续进行。我尝试过使用sleep-foraccept-process-output。两者都不可靠。这里有一个小例子。

此测试仅休眠5秒,然后检查是否至少已过3秒。使用sleep-for,它会立即结束,但会失败。如果shell-command未被注释,则花费预期的5秒并成功!这里发生什么事情?

代码语言:javascript
复制
(ert-deftest timetest ()
  (let ((now (cadr (current-time))))
    ;(shell-command "sleep 5")
    (sleep-for 5)
    (should (< now (- (cadr (current-time)) 3)))))

编辑:

当我测试前面的示例时,我的环境中一定有一些奇怪的东西。这个稍微修改过的示例包含一个后台进程,与我需要测试的进程类似,但失败了。我以交互方式和使用命令对其进行了测试:

代码语言:javascript
复制
emacs --batch -l example.el -f ert-run-tests-batch-and-exit
代码语言:javascript
复制
(ert-deftest timetest ()
  (let ((now (cadr (current-time))))
    (start-process "echo" "*echo*" "echo" "hello world")
    (sleep-for 5)
    (should (< now (- (cadr (current-time)) 3)))))

输出为:

代码语言:javascript
复制
Test timetest condition:
    (ert-test-failed
     ((should
       (< now
          (- ... 3)))
      :form
      (< 55177 55174)
      :value nil))
   FAILED  1/1  timetest

Ran 1 tests, 0 results as expected, 1 unexpected (2013-02-05 09:57:29+0000)

1 unexpected results:
   FAILED  timetest

EDIT2:

新版本似乎表明进程输出足以中断sleep-for

代码语言:javascript
复制
(ert-deftest timetest ()
  (let ((now (cadr (current-time))))
    (start-process "yes" "*yes*" "yes")
    (sleep-for 1) ;; This sleep-for may be interrupted by process *output*
    (sleep-for 5) ;; This sleep-for is also interrupted
    (should (< now (- (cadr (current-time)) 3)))))

EDIT3:

怀着沉重的心情,我发布了另一个版本:

代码语言:javascript
复制
(ert-deftest timetest ()
  (let ((now (cadr (current-time)))
        (process-connection-type nil))
    (start-process "tmp" "*tmp*" "bash" "-c" "sleep 1; echo hi")
    (sleep-for 5)
    (should (< now (- (cadr (current-time)) 3)))))

似乎很明显,不能依赖sleep-for来阻止。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-02-06 09:26:23

我认为当进程退出时,sleep-for会中断。

后续测试失败,2秒后sleep-for中断

代码语言:javascript
复制
(ert-deftest timetest ()
  (let ((now (cadr (current-time))))
    (start-process "sleep" "*sleep*" "sleep" "2") ;; Fail
    (sleep-for 5)
    (should (< now (- (cadr (current-time)) 3)))))

但是下面的测试通过了,因为sleep-for在4秒后就中断了。

代码语言:javascript
复制
(ert-deftest timetest ()
  (let ((now (cadr (current-time))))
    (start-process "sleep" "*sleep*" "sleep" "4") ;; Success
    (sleep-for 5)
    (should (< now (- (cadr (current-time)) 3)))))

所以我认为你可以像下面这样写测试

代码语言:javascript
复制
(ert-deftest timetest ()
  (let ((now (cadr (current-time))))
    (start-process "echo" "*echo*" "echo" "hello world")
    (sleep-for 1) ;; This sleep-for may be interrupted by process exited
    (sleep-for 5) ;; This sleep-for can sleep 5 seconds
    (should (< now (- (cadr (current-time)) 3)))))

EDIT1

process-connection-type设置为nil即可通过第二个测试。(但我不能理解这种行为)

代码语言:javascript
复制
(ert-deftest timetest ()
  (let ((now (cadr (current-time)))
        (process-connection-type nil))
    (start-process "yes" "*yes*" "yes")
    (sleep-for 5)
    (should (< now (- (cadr (current-time)) 3)))))

请参阅document

EDIT2

在第三个测试中,我们需要3个sleep-for,因为sleep-for被中断了2次,但这是脆弱的。因此,我编写了如下测试。如果sleep-for中断次数相同,则可以通过此测试。我使用float-time而不是current-time,因为current-time的第二个元素可能会换行。

代码语言:javascript
复制
(ert-deftest timetest ()
  (let ((now (float-time))
        (process-connection-type nil))
    (start-process "tmp" "*tmp*" "bash" "-c" "sleep 1; echo hi")
    (while (< (- (float-time) now) 5)
      (sleep-for 1))
    (should (< now (- (float-time) 3)))))
票数 6
EN

Stack Overflow用户

发布于 2013-02-05 13:33:11

我只是复制到*scratch*中,并使用ert-run-tests-interactively运行该测试。我不能复制你的问题。你是否有一个旧版本的测试在内存中徘徊?

编辑:我在OS X 10.8上使用Emacs 24.2.1

更新:运行更新后的代码。发生了一些非常奇怪的事情。我大约有1/4的跑步是成功的。

更新:我可以验证@syohex的答案:添加第二个调用sleep-for对我有效。

票数 2
EN

Stack Overflow用户

发布于 2013-12-01 10:18:14

此错误将在下一个Emacs (25.1? 24.6??)中修复。请参阅2015年6月的this commit。(不过,我还没有真正尝试过。)

在它得到修复之前,使用

代码语言:javascript
复制
(call-process "/usr/bin/sleep" nil nil nil "<seconds>")

而不是“睡眠”。这是可靠的。

在报告修复的original (#15990)和duplicate (#20935)中可以找到错误报告。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14698081

复制
相关文章

相似问题

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