rlm@10
|
1 ; Copyright (c) Rich Hickey. All rights reserved.
|
rlm@10
|
2 ; The use and distribution terms for this software are covered by the
|
rlm@10
|
3 ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
rlm@10
|
4 ; which can be found in the file epl-v10.html at the root of this distribution.
|
rlm@10
|
5 ; By using this software in any fashion, you are agreeing to be bound by
|
rlm@10
|
6 ; the terms of this license.
|
rlm@10
|
7 ; You must not remove this notice, or any other, from this software.
|
rlm@10
|
8
|
rlm@10
|
9 ;; Author: Shawn Hoover
|
rlm@10
|
10
|
rlm@10
|
11 (ns clojure.test-clojure.agents
|
rlm@10
|
12 (:use clojure.test))
|
rlm@10
|
13
|
rlm@10
|
14 (deftest handle-all-throwables-during-agent-actions
|
rlm@10
|
15 ;; Bug fixed in r1198; previously hung Clojure or didn't report agent errors
|
rlm@10
|
16 ;; after OutOfMemoryError, yet wouldn't execute new actions.
|
rlm@10
|
17 (let [agt (agent nil)]
|
rlm@10
|
18 (send agt (fn [state] (throw (Throwable. "just testing Throwables"))))
|
rlm@10
|
19 (try
|
rlm@10
|
20 ;; Let the action finish; eat the "agent has errors" error that bubbles up
|
rlm@10
|
21 (await-for 100 agt)
|
rlm@10
|
22 (catch RuntimeException _))
|
rlm@10
|
23 (is (instance? Throwable (first (agent-errors agt))))
|
rlm@10
|
24 (is (= 1 (count (agent-errors agt))))
|
rlm@10
|
25
|
rlm@10
|
26 ;; And now send an action that should work
|
rlm@10
|
27 (clear-agent-errors agt)
|
rlm@10
|
28 (is (= nil @agt))
|
rlm@10
|
29 (send agt nil?)
|
rlm@10
|
30 (is (true? (await-for 100 agt)))
|
rlm@10
|
31 (is (true? @agt))))
|
rlm@10
|
32
|
rlm@10
|
33 (deftest default-modes
|
rlm@10
|
34 (is (= :fail (error-mode (agent nil))))
|
rlm@10
|
35 (is (= :continue (error-mode (agent nil :error-handler println)))))
|
rlm@10
|
36
|
rlm@10
|
37 (deftest continue-handler
|
rlm@10
|
38 (let [err (atom nil)
|
rlm@10
|
39 agt (agent 0 :error-mode :continue :error-handler #(reset! err %&))]
|
rlm@10
|
40 (send agt /)
|
rlm@10
|
41 (is (true? (await-for 100 agt)))
|
rlm@10
|
42 (is (= 0 @agt))
|
rlm@10
|
43 (is (nil? (agent-error agt)))
|
rlm@10
|
44 (is (= agt (first @err)))
|
rlm@10
|
45 (is (true? (instance? ArithmeticException (second @err))))))
|
rlm@10
|
46
|
rlm@10
|
47 (deftest fail-handler
|
rlm@10
|
48 (let [err (atom nil)
|
rlm@10
|
49 agt (agent 0 :error-mode :fail :error-handler #(reset! err %&))]
|
rlm@10
|
50 (send agt /)
|
rlm@10
|
51 (Thread/sleep 100)
|
rlm@10
|
52 (is (true? (instance? ArithmeticException (agent-error agt))))
|
rlm@10
|
53 (is (= 0 @agt))
|
rlm@10
|
54 (is (= agt (first @err)))
|
rlm@10
|
55 (is (true? (instance? ArithmeticException (second @err))))
|
rlm@10
|
56 (is (thrown? RuntimeException (send agt inc)))))
|
rlm@10
|
57
|
rlm@10
|
58 (deftest restart-no-clear
|
rlm@10
|
59 (let [p (promise)
|
rlm@10
|
60 agt (agent 1 :error-mode :fail)]
|
rlm@10
|
61 (send agt (fn [v] @p))
|
rlm@10
|
62 (send agt /)
|
rlm@10
|
63 (send agt inc)
|
rlm@10
|
64 (send agt inc)
|
rlm@10
|
65 (deliver p 0)
|
rlm@10
|
66 (Thread/sleep 100)
|
rlm@10
|
67 (is (= 0 @agt))
|
rlm@10
|
68 (is (= ArithmeticException (class (agent-error agt))))
|
rlm@10
|
69 (restart-agent agt 10)
|
rlm@10
|
70 (is (true? (await-for 100 agt)))
|
rlm@10
|
71 (is (= 12 @agt))
|
rlm@10
|
72 (is (nil? (agent-error agt)))))
|
rlm@10
|
73
|
rlm@10
|
74 (deftest restart-clear
|
rlm@10
|
75 (let [p (promise)
|
rlm@10
|
76 agt (agent 1 :error-mode :fail)]
|
rlm@10
|
77 (send agt (fn [v] @p))
|
rlm@10
|
78 (send agt /)
|
rlm@10
|
79 (send agt inc)
|
rlm@10
|
80 (send agt inc)
|
rlm@10
|
81 (deliver p 0)
|
rlm@10
|
82 (Thread/sleep 100)
|
rlm@10
|
83 (is (= 0 @agt))
|
rlm@10
|
84 (is (= ArithmeticException (class (agent-error agt))))
|
rlm@10
|
85 (restart-agent agt 10 :clear-actions true)
|
rlm@10
|
86 (is (true? (await-for 100 agt)))
|
rlm@10
|
87 (is (= 10 @agt))
|
rlm@10
|
88 (is (nil? (agent-error agt)))
|
rlm@10
|
89 (send agt inc)
|
rlm@10
|
90 (is (true? (await-for 100 agt)))
|
rlm@10
|
91 (is (= 11 @agt))
|
rlm@10
|
92 (is (nil? (agent-error agt)))))
|
rlm@10
|
93
|
rlm@10
|
94 (deftest invalid-restart
|
rlm@10
|
95 (let [p (promise)
|
rlm@10
|
96 agt (agent 2 :error-mode :fail :validator even?)]
|
rlm@10
|
97 (is (thrown? RuntimeException (restart-agent agt 4)))
|
rlm@10
|
98 (send agt (fn [v] @p))
|
rlm@10
|
99 (send agt (partial + 2))
|
rlm@10
|
100 (send agt (partial + 2))
|
rlm@10
|
101 (deliver p 3)
|
rlm@10
|
102 (Thread/sleep 100)
|
rlm@10
|
103 (is (= 2 @agt))
|
rlm@10
|
104 (is (= IllegalStateException (class (agent-error agt))))
|
rlm@10
|
105 (is (thrown? RuntimeException (restart-agent agt 5)))
|
rlm@10
|
106 (restart-agent agt 6)
|
rlm@10
|
107 (is (true? (await-for 100 agt)))
|
rlm@10
|
108 (is (= 10 @agt))
|
rlm@10
|
109 (is (nil? (agent-error agt)))))
|
rlm@10
|
110
|
rlm@10
|
111 ; http://clojure.org/agents
|
rlm@10
|
112
|
rlm@10
|
113 ; agent
|
rlm@10
|
114 ; deref, @-reader-macro, agent-errors
|
rlm@10
|
115 ; send send-off clear-agent-errors
|
rlm@10
|
116 ; await await-for
|
rlm@10
|
117 ; set-validator get-validator
|
rlm@10
|
118 ; add-watch remove-watch
|
rlm@10
|
119 ; shutdown-agents
|
rlm@10
|
120
|