rlm@10: ; Copyright (c) Rich Hickey. All rights reserved. rlm@10: ; The use and distribution terms for this software are covered by the rlm@10: ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) rlm@10: ; which can be found in the file epl-v10.html at the root of this distribution. rlm@10: ; By using this software in any fashion, you are agreeing to be bound by rlm@10: ; the terms of this license. rlm@10: ; You must not remove this notice, or any other, from this software. rlm@10: rlm@10: ;; Author: Shawn Hoover rlm@10: rlm@10: (ns clojure.test-clojure.agents rlm@10: (:use clojure.test)) rlm@10: rlm@10: (deftest handle-all-throwables-during-agent-actions rlm@10: ;; Bug fixed in r1198; previously hung Clojure or didn't report agent errors rlm@10: ;; after OutOfMemoryError, yet wouldn't execute new actions. rlm@10: (let [agt (agent nil)] rlm@10: (send agt (fn [state] (throw (Throwable. "just testing Throwables")))) rlm@10: (try rlm@10: ;; Let the action finish; eat the "agent has errors" error that bubbles up rlm@10: (await-for 100 agt) rlm@10: (catch RuntimeException _)) rlm@10: (is (instance? Throwable (first (agent-errors agt)))) rlm@10: (is (= 1 (count (agent-errors agt)))) rlm@10: rlm@10: ;; And now send an action that should work rlm@10: (clear-agent-errors agt) rlm@10: (is (= nil @agt)) rlm@10: (send agt nil?) rlm@10: (is (true? (await-for 100 agt))) rlm@10: (is (true? @agt)))) rlm@10: rlm@10: (deftest default-modes rlm@10: (is (= :fail (error-mode (agent nil)))) rlm@10: (is (= :continue (error-mode (agent nil :error-handler println))))) rlm@10: rlm@10: (deftest continue-handler rlm@10: (let [err (atom nil) rlm@10: agt (agent 0 :error-mode :continue :error-handler #(reset! err %&))] rlm@10: (send agt /) rlm@10: (is (true? (await-for 100 agt))) rlm@10: (is (= 0 @agt)) rlm@10: (is (nil? (agent-error agt))) rlm@10: (is (= agt (first @err))) rlm@10: (is (true? (instance? ArithmeticException (second @err)))))) rlm@10: rlm@10: (deftest fail-handler rlm@10: (let [err (atom nil) rlm@10: agt (agent 0 :error-mode :fail :error-handler #(reset! err %&))] rlm@10: (send agt /) rlm@10: (Thread/sleep 100) rlm@10: (is (true? (instance? ArithmeticException (agent-error agt)))) rlm@10: (is (= 0 @agt)) rlm@10: (is (= agt (first @err))) rlm@10: (is (true? (instance? ArithmeticException (second @err)))) rlm@10: (is (thrown? RuntimeException (send agt inc))))) rlm@10: rlm@10: (deftest restart-no-clear rlm@10: (let [p (promise) rlm@10: agt (agent 1 :error-mode :fail)] rlm@10: (send agt (fn [v] @p)) rlm@10: (send agt /) rlm@10: (send agt inc) rlm@10: (send agt inc) rlm@10: (deliver p 0) rlm@10: (Thread/sleep 100) rlm@10: (is (= 0 @agt)) rlm@10: (is (= ArithmeticException (class (agent-error agt)))) rlm@10: (restart-agent agt 10) rlm@10: (is (true? (await-for 100 agt))) rlm@10: (is (= 12 @agt)) rlm@10: (is (nil? (agent-error agt))))) rlm@10: rlm@10: (deftest restart-clear rlm@10: (let [p (promise) rlm@10: agt (agent 1 :error-mode :fail)] rlm@10: (send agt (fn [v] @p)) rlm@10: (send agt /) rlm@10: (send agt inc) rlm@10: (send agt inc) rlm@10: (deliver p 0) rlm@10: (Thread/sleep 100) rlm@10: (is (= 0 @agt)) rlm@10: (is (= ArithmeticException (class (agent-error agt)))) rlm@10: (restart-agent agt 10 :clear-actions true) rlm@10: (is (true? (await-for 100 agt))) rlm@10: (is (= 10 @agt)) rlm@10: (is (nil? (agent-error agt))) rlm@10: (send agt inc) rlm@10: (is (true? (await-for 100 agt))) rlm@10: (is (= 11 @agt)) rlm@10: (is (nil? (agent-error agt))))) rlm@10: rlm@10: (deftest invalid-restart rlm@10: (let [p (promise) rlm@10: agt (agent 2 :error-mode :fail :validator even?)] rlm@10: (is (thrown? RuntimeException (restart-agent agt 4))) rlm@10: (send agt (fn [v] @p)) rlm@10: (send agt (partial + 2)) rlm@10: (send agt (partial + 2)) rlm@10: (deliver p 3) rlm@10: (Thread/sleep 100) rlm@10: (is (= 2 @agt)) rlm@10: (is (= IllegalStateException (class (agent-error agt)))) rlm@10: (is (thrown? RuntimeException (restart-agent agt 5))) rlm@10: (restart-agent agt 6) rlm@10: (is (true? (await-for 100 agt))) rlm@10: (is (= 10 @agt)) rlm@10: (is (nil? (agent-error agt))))) rlm@10: rlm@10: ; http://clojure.org/agents rlm@10: rlm@10: ; agent rlm@10: ; deref, @-reader-macro, agent-errors rlm@10: ; send send-off clear-agent-errors rlm@10: ; await await-for rlm@10: ; set-validator get-validator rlm@10: ; add-watch remove-watch rlm@10: ; shutdown-agents rlm@10: