3

マルチスレッドアプリをテストするための優れた戦略を誰かが思いついたのかどうか知りたいです。

私はmidjeを使ってたくさんのテストを行っていますが、これは関数のテストに最適です...しかし、マルチスレッドコードをテストする方法がよくわかりません。

  (fact "the state is modified by a thread call"
    (Thread/sleep 100)
    (check-state-eq *state* nil)
    (Thread/sleep 100)
    (modify-state-thread-call *state* :updated-value)
    (Thread/sleep 100)
    (check-state-eq *state* :updated-value))

コンパイル時間のために、状態が時間内に更新されなかったためにテストが失敗することがあります。そのため、より長くスリープする必要があります。理想的には、次のようなものを書く方法が必要です。

  (fact "the state is modified by a thread call"
    (modify-state-thread-call *state* :updated-value) 
     =leads-to=> (check-state-eq *state* :updated-value))

眠りから離れます。それを行うための戦略はありますか?

4

2 に答える 2

5

この例がclojure参照型の1つである場合*state*、add-watchを使用して、そのオブジェクトへのすべての変更を通知する関数を追加できます:http: //clojuredocs.org/clojure_core/clojure.core/add-watch

私が提案するかもしれないアプローチは、条件が満たされたときに約束を果たすために時計を使用することです。

(let [check-promise (promise)]
  (add-watch *state* :check-for-updated-value
    (fn [rkey refr _oldval newval]
       (when (some-check newval)
          (remove-watch refr rkey)
          (deliver check-promise true))))
  (modify-state-thread-call *state* :updated-value)
  (deref check-promise 1000 false))

*state*これは、1000ms以内に満たす値をとる場合はすぐにtrueを返しsome-check、条件が満たされない場合は1000ms後にfalseを返します。

于 2012-12-05T06:24:42.173 に答える
1

Crateの応答に基づいて、次のwait関数を作成しました。

(defn return-val [p ms ret]
  (cond (nil? ms) (deref p)
        :else (deref p ms ret)))

(defn wait
  ([f rf] (wait f rf nil nil))
  ([f rf ms] (wait f rf ms nil))
  ([f rf ms ret]
     (let [p (promise)
           pk (hash-keyword p)
           d-fn (fn [_ rf _ _]
                  (remove-watch rf pk)
                  (deliver p rf))]
       (add-watch rf pk d-fn)
       (f rf)
       (return-val p ms ret))))

その使用法は次のとおりです。

(defn threaded-inc [rf]
  (future
    (Thread/sleep 100)
    (dosync (alter rf inc)))
  rf)

(def arf (ref 0))
(deref (threaded-inc arf)) ;=> 0

(dosync (ref-set arf 0))
(deref (wait threaded-inc arf)) ;=> 1
于 2013-04-16T23:41:27.843 に答える