diff src/clojure/test_clojure/control.clj @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/clojure/test_clojure/control.clj	Sat Aug 21 06:25:44 2010 -0400
     1.3 @@ -0,0 +1,333 @@
     1.4 +;   Copyright (c) Rich Hickey. All rights reserved.
     1.5 +;   The use and distribution terms for this software are covered by the
     1.6 +;   Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
     1.7 +;   which can be found in the file epl-v10.html at the root of this distribution.
     1.8 +;   By using this software in any fashion, you are agreeing to be bound by
     1.9 +;   the terms of this license.
    1.10 +;   You must not remove this notice, or any other, from this software.
    1.11 +
    1.12 +; Author: Frantisek Sodomka, Mike Hinchey, Stuart Halloway
    1.13 +
    1.14 +;;
    1.15 +;;  Test "flow control" constructs.
    1.16 +;;
    1.17 +
    1.18 +(ns clojure.test-clojure.control
    1.19 +  (:use clojure.test
    1.20 +        [clojure.test-clojure.helpers :only (exception)]))
    1.21 +
    1.22 +;; *** Helper functions ***
    1.23 +
    1.24 +(defn maintains-identity [f]
    1.25 +  (are [x] (= (f x) x)
    1.26 +      nil
    1.27 +      false true
    1.28 +      0 42
    1.29 +      0.0 3.14
    1.30 +      2/3
    1.31 +      0M 1M
    1.32 +      \c
    1.33 +      "" "abc"
    1.34 +      'sym
    1.35 +      :kw
    1.36 +      () '(1 2)
    1.37 +      [] [1 2]
    1.38 +      {} {:a 1 :b 2}
    1.39 +      #{} #{1 2} ))
    1.40 +
    1.41 +
    1.42 +; http://clojure.org/special_forms
    1.43 +; http://clojure.org/macros
    1.44 +
    1.45 +(deftest test-do
    1.46 +  (are [x y] (= x y)
    1.47 +      ; no params => nil
    1.48 +      (do) nil
    1.49 +      
    1.50 +      ; return last
    1.51 +      (do 1) 1
    1.52 +      (do 1 2) 2
    1.53 +      (do 1 2 3 4 5) 5
    1.54 +      
    1.55 +      ; evaluate and return last
    1.56 +      (let [a (atom 0)]
    1.57 +        (do (reset! a (+ @a 1))   ; 1
    1.58 +            (reset! a (+ @a 1))   ; 2
    1.59 +            (reset! a (+ @a 1))   ; 3
    1.60 +            @a))  3 )
    1.61 +
    1.62 +  ; identity (= (do x) x)
    1.63 +  (maintains-identity (fn [_] (do _))) )
    1.64 +
    1.65 +
    1.66 +;; loop/recur
    1.67 +(deftest test-loop
    1.68 +  (are [x y] (= x y)
    1.69 +       1 (loop []
    1.70 +           1)
    1.71 +       3 (loop [a 1]
    1.72 +           (if (< a 3)
    1.73 +             (recur (inc a))
    1.74 +             a))
    1.75 +       [2 4 6] (loop [a []
    1.76 +                      b [1 2 3]]
    1.77 +                 (if (seq b)
    1.78 +                   (recur (conj a (* 2 (first b)))
    1.79 +                          (next b))
    1.80 +                   a))
    1.81 +       [6 4 2] (loop [a ()
    1.82 +                      b [1 2 3]]
    1.83 +                 (if (seq b)
    1.84 +                   (recur (conj a (* 2 (first b)))
    1.85 +                          (next b))
    1.86 +                   a))
    1.87 +       )
    1.88 +  )
    1.89 +
    1.90 +
    1.91 +;; throw, try
    1.92 +
    1.93 +; if: see logic.clj
    1.94 +
    1.95 +(deftest test-when
    1.96 +  (are [x y] (= x y)
    1.97 +       1 (when true 1)
    1.98 +       nil (when true)
    1.99 +       nil (when false)
   1.100 +       nil (when false (exception))
   1.101 +       ))
   1.102 +
   1.103 +(deftest test-when-not
   1.104 +  (are [x y] (= x y)
   1.105 +       1 (when-not false 1)
   1.106 +       nil (when-not true)
   1.107 +       nil (when-not false)
   1.108 +       nil (when-not true (exception))
   1.109 +       ))
   1.110 +
   1.111 +(deftest test-if-not
   1.112 +  (are [x y] (= x y)
   1.113 +       1 (if-not false 1)
   1.114 +       1 (if-not false 1 (exception))
   1.115 +       nil (if-not true 1)
   1.116 +       2 (if-not true 1 2)
   1.117 +       nil (if-not true (exception))
   1.118 +       1 (if-not true (exception) 1)
   1.119 +       ))
   1.120 +
   1.121 +(deftest test-when-let
   1.122 +  (are [x y] (= x y)
   1.123 +       1 (when-let [a 1]
   1.124 +           a)
   1.125 +       2 (when-let [[a b] '(1 2)]
   1.126 +           b)
   1.127 +       nil (when-let [a false]
   1.128 +             (exception))
   1.129 +       ))
   1.130 +
   1.131 +(deftest test-if-let
   1.132 +  (are [x y] (= x y)
   1.133 +       1 (if-let [a 1]
   1.134 +           a)
   1.135 +       2 (if-let [[a b] '(1 2)]
   1.136 +           b)
   1.137 +       nil (if-let [a false]
   1.138 +             (exception))
   1.139 +       1 (if-let [a false]
   1.140 +           a 1)
   1.141 +       1 (if-let [[a b] nil]
   1.142 +             b 1)
   1.143 +       1 (if-let [a false]
   1.144 +           (exception)
   1.145 +           1)
   1.146 +       ))
   1.147 +
   1.148 +(deftest test-when-first
   1.149 +  (are [x y] (= x y)
   1.150 +       1 (when-first [a [1 2]]
   1.151 +           a)
   1.152 +       2 (when-first [[a b] '((1 2) 3)]
   1.153 +           b)
   1.154 +       nil (when-first [a nil]
   1.155 +             (exception))
   1.156 +       ))
   1.157 +
   1.158 +
   1.159 +(deftest test-cond
   1.160 +  (are [x y] (= x y)
   1.161 +      (cond) nil
   1.162 +
   1.163 +      (cond nil true) nil
   1.164 +      (cond false true) nil
   1.165 +      
   1.166 +      (cond true 1 true (exception)) 1
   1.167 +      (cond nil 1 false 2 true 3 true 4) 3
   1.168 +      (cond nil 1 false 2 true 3 true (exception)) 3 )
   1.169 +
   1.170 +  ; false
   1.171 +  (are [x]  (= (cond x :a true :b) :b)
   1.172 +      nil false )
   1.173 +
   1.174 +  ; true
   1.175 +  (are [x]  (= (cond x :a true :b) :a)
   1.176 +      true
   1.177 +      0 42
   1.178 +      0.0 3.14
   1.179 +      2/3
   1.180 +      0M 1M
   1.181 +      \c
   1.182 +      "" "abc"
   1.183 +      'sym
   1.184 +      :kw
   1.185 +      () '(1 2)
   1.186 +      [] [1 2]
   1.187 +      {} {:a 1 :b 2}
   1.188 +      #{} #{1 2} )
   1.189 +
   1.190 +  ; evaluation
   1.191 +  (are [x y] (= x y)
   1.192 +      (cond (> 3 2) (+ 1 2) true :result true (exception)) 3
   1.193 +      (cond (< 3 2) (+ 1 2) true :result true (exception)) :result )
   1.194 +
   1.195 +  ; identity (= (cond true x) x)
   1.196 +  (maintains-identity (fn [_] (cond true _))) )
   1.197 +
   1.198 +
   1.199 +(deftest test-condp
   1.200 +  (are [x] (= :pass x)
   1.201 +       (condp = 1
   1.202 +         1 :pass
   1.203 +         2 :fail)
   1.204 +       (condp = 1
   1.205 +         2 :fail
   1.206 +         1 :pass)
   1.207 +       (condp = 1
   1.208 +         2 :fail
   1.209 +         :pass)
   1.210 +       (condp = 1
   1.211 +         :pass)
   1.212 +       (condp = 1
   1.213 +         2 :fail
   1.214 +         ;; doc of condp says result-expr is returned
   1.215 +         ;; shouldn't it say similar to cond: "evaluates and returns
   1.216 +         ;; the value of the corresponding expr and doesn't evaluate any of the
   1.217 +         ;; other tests or exprs."
   1.218 +         (identity :pass))
   1.219 +       (condp + 1
   1.220 +         1 :>> #(if (= % 2) :pass :fail))
   1.221 +       (condp + 1
   1.222 +         1 :>> #(if (= % 3) :fail :pass))
   1.223 +       )
   1.224 +  (is (thrown? IllegalArgumentException
   1.225 +               (condp = 1)
   1.226 +               ))
   1.227 +  (is (thrown? IllegalArgumentException
   1.228 +               (condp = 1
   1.229 +                 2 :fail)
   1.230 +               ))
   1.231 +  )
   1.232 +
   1.233 +
   1.234 +; [for, doseq (for.clj)]
   1.235 +
   1.236 +(deftest test-dotimes
   1.237 +  ;; dotimes always returns nil
   1.238 +  (is (= nil (dotimes [n 1] n)))
   1.239 +  ;; test using an atom since dotimes is for modifying
   1.240 +  ;; test executes n times
   1.241 +  (is (= 3
   1.242 +         (let [a (atom 0)]
   1.243 +           (dotimes [n 3]
   1.244 +             (swap! a inc))
   1.245 +           @a)
   1.246 +         ))
   1.247 +  ;; test all values of n
   1.248 +  (is (= [0 1 2]
   1.249 +         (let [a (atom [])]
   1.250 +           (dotimes [n 3]
   1.251 +             (swap! a conj n))
   1.252 +           @a)))
   1.253 +  (is (= []
   1.254 +         (let [a (atom [])]
   1.255 +           (dotimes [n 0]
   1.256 +             (swap! a conj n))
   1.257 +           @a)))
   1.258 +  )
   1.259 +
   1.260 +(deftest test-while
   1.261 +  (is (= nil (while nil (throw (Exception. "never")))))
   1.262 +  (is (= [0 nil]
   1.263 +         ;; a will dec to 0
   1.264 +         ;; while always returns nil
   1.265 +         (let [a (atom 3)
   1.266 +               w (while (pos? @a)
   1.267 +                   (swap! a dec))]
   1.268 +           [@a w])))
   1.269 +  (is (thrown? Exception (while true (throw (Exception. "expected to throw")))))
   1.270 +  )
   1.271 +
   1.272 +; locking, monitor-enter, monitor-exit
   1.273 +
   1.274 +; case 
   1.275 +(deftest test-case
   1.276 +  (testing "can match many kinds of things"
   1.277 +    (let [two 2
   1.278 +          test-fn
   1.279 +          #(case %
   1.280 +                 1 :number
   1.281 +                 "foo" :string
   1.282 +                 \a :char
   1.283 +                 pow :symbol
   1.284 +                 :zap :keyword
   1.285 +                 (2 \b "bar") :one-of-many
   1.286 +                 [1 2] :sequential-thing
   1.287 +                 {:a 2} :map
   1.288 +                 {:r 2 :d 2} :droid
   1.289 +                 #{2 3 4 5} :set
   1.290 +                 [1 [[[2]]]] :deeply-nested
   1.291 +                 :default)]
   1.292 +      (are [result input] (= result (test-fn input))
   1.293 +           :number 1
   1.294 +           :string "foo"
   1.295 +           :char \a
   1.296 +           :keyword :zap
   1.297 +           :symbol 'pow
   1.298 +           :one-of-many 2
   1.299 +           :one-of-many \b
   1.300 +           :one-of-many "bar"
   1.301 +           :sequential-thing [1 2]
   1.302 +           :sequential-thing (list 1 2)
   1.303 +           :sequential-thing [1 two]
   1.304 +           :map {:a 2}
   1.305 +           :map {:a two}
   1.306 +           :set #{2 3 4 5}
   1.307 +           :set #{two 3 4 5}
   1.308 +           :default #{2 3 4 5 6}
   1.309 +           :droid {:r 2 :d 2}
   1.310 +           :deeply-nested [1 [[[two]]]]
   1.311 +           :default :anything-not-appearing-above)))
   1.312 +  (testing "throws IllegalArgumentException if no match"
   1.313 +    (is (thrown-with-msg?
   1.314 +          IllegalArgumentException #"No matching clause: 2"
   1.315 +          (case 2 1 :ok))))
   1.316 +  (testing "sorting doesn't matter"
   1.317 +    (let [test-fn
   1.318 +          #(case %
   1.319 +                {:b 2 :a 1} :map
   1.320 +                #{3 2 1} :set
   1.321 +                :default)]
   1.322 +      (are [result input] (= result (test-fn input))
   1.323 +           :map {:a 1 :b 2}
   1.324 +           :map (sorted-map :a 1 :b 2)
   1.325 +           :set #{3 2 1}
   1.326 +           :set (sorted-set 2 1 3))))
   1.327 +  (testing "test constants are *not* evaluated"
   1.328 +    (let [test-fn
   1.329 +          ;; never write code like this...
   1.330 +          #(case %
   1.331 +                 (throw (RuntimeException. "boom")) :piece-of-throw-expr
   1.332 +                 :no-match)]
   1.333 +      (are [result input] (= result (test-fn input))
   1.334 +           :piece-of-throw-expr 'throw
   1.335 +           :piece-of-throw-expr '[RuntimeException. "boom"]
   1.336 +           :no-match nil))))