3

バックグラウンドプロセスを続行するためにスリープする必要があるertを使用していくつかのテストを設定しようとしています。とを使ってみましsleep-foraccept-process-output。どちらも信頼できません。これが小さな例です。

このテストは5秒間スリープしてから、少なくとも3秒が経過したことを確認します。それを使用sleep-forするとすぐに終了し、失敗します。コメントがない場合shell-commandは、予想される5秒かかり、成功します。ここで何が起こっているのですか?

(ert-deftest timetest ()
  (let ((now (cadr (current-time))))
    ;(shell-command "sleep 5")
    (sleep-for 5)
    (should (< now (- (cadr (current-time)) 3)))))

編集:

前の例をテストしたとき、私の環境には何か奇妙なことがあったに違いありません。このわずかに変更された例には、テストする必要があるようなバックグラウンドプロセスが含まれており、失敗します。インタラクティブとコマンドの両方を使用してテストしました。

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

出力は次のとおりです。

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です:

(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:

心が重いので、別のバージョンを投稿します。

(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ブロックに頼ることができないことは明らかなようです。

4

4 に答える 4

6

sleep-forプロセスが終了すると、それは中断されると思います。

sleep-for2秒後に中断されたため、次のテストは失敗しました。

(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-for4秒後に中断されるため、次のテストに合格します。

(ert-deftest timetest ()
  (let ((now (cadr (current-time))))
    (start-process "sleep" "*sleep*" "sleep" "4") ;; Success
    (sleep-for 5)
    (should (< now (- (cadr (current-time)) 3)))))

だから私はあなたが以下のようにテストを書くことができると思います

(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)))))

編集1

process-connection-typeに設定すると、2番目のテストに合格しますnil。(しかし、私はこの振る舞いを理解できません)

(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)))))

ドキュメントをご覧ください

EDIT2

3回目のテストでは、 2回中断されるsleep-forため、3が必要sleep-forですが、これは壊れやすいです。だから私は以下のようにテストを書きます。sleep-for何度も中断された場合、このテストに合格することができます。そして、の 2番目の要素が回り込む可能性があるため、float-time代わりに使用します。current-timecurrent-time

(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)))))
于 2013-02-06T01:26:23.273 に答える
2

*スクラッチ*にコピーして、そのテストを。で実行しましたert-run-tests-interactively。問題を再現できません。古いバージョンのテストがメモリに残っていますか?

編集:OSX10.8でEmacs24.2.1を使用しています

更新:更新されたコードを実行します。非常に奇妙なことが起こっています。私のランの約1/4が​​成功しています。

更新:@syohexの答えを確認できます:2番目の呼び出しを追加するとうまくいきsleep-forます。

于 2013-02-05T05:33:10.620 に答える
2

このバグは次のEmacs(25.1?24.6 ??)で修正される予定です。2015年6月のこのコミットを参照してください(ただし、実際には試していません)。

修正されるまで、

(call-process "/usr/bin/sleep" nil nil nil "<seconds>")

`sleep-for'の代わりに。これは信頼できます。

バグレポートは、修正が報告された元の(#15990)と重複した(#20935)にあります。

于 2013-12-01T02:18:13.863 に答える
0

https://github.com/rejeep/ert-async.elをご覧ください

次に、次のようなことを行うことができます。

(ert-deftest-async timetest (done)
  (call-async-command done))
于 2015-06-17T09:15:35.420 に答える