Mercurial > lasercutter
view src/clojure/test_clojure/evaluation.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 source
1 ; Copyright (c) Rich Hickey. All rights reserved.2 ; The use and distribution terms for this software are covered by the3 ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)4 ; which can be found in the file epl-v10.html at the root of this distribution.5 ; By using this software in any fashion, you are agreeing to be bound by6 ; the terms of this license.7 ; You must not remove this notice, or any other, from this software.10 ;; Tests for the Clojure functions documented at the URL:11 ;;12 ;; http://clojure.org/Evaluation13 ;;14 ;; by J. McConnell15 ;; Created 22 October 200817 (ns clojure.test-clojure.evaluation18 (:use clojure.test))20 (import '(java.lang Boolean)21 '(clojure.lang Compiler Compiler$CompilerException))23 (defmacro test-that24 "Provides a useful way for specifying the purpose of tests. If the first-level25 forms are lists that make a call to a clojure.test function, it supplies the26 purpose as the msg argument to those functions. Otherwise, the purpose just27 acts like a comment and the forms are run unchanged."28 [purpose & test-forms]29 (let [tests (map30 #(if (= (:ns (meta (resolve (first %))))31 (the-ns 'clojure.test))32 (concat % (list purpose))33 %)34 test-forms)]35 `(do ~@tests)))37 (deftest Eval38 (is (= (eval '(+ 1 2 3)) (Compiler/eval '(+ 1 2 3))))39 (is (= (eval '(list 1 2 3)) '(1 2 3)))40 (is (= (eval '(list + 1 2 3)) (list clojure.core/+ 1 2 3)))41 (test-that "Non-closure fns are supported as code"42 (is (= (eval (eval '(list + 1 2 3))) 6)))43 (is (= (eval (list '+ 1 2 3)) 6)))45 ; not using Clojure's RT/classForName since a bug in it could hide a bug in46 ; eval's resolution47 (defn class-for-name [name]48 (java.lang.Class/forName name))50 (defmacro in-test-ns [& body]51 `(binding [*ns* *ns*]52 (in-ns 'clojure.test-clojure.evaluation)53 ~@body))55 ;;; Literals tests ;;;57 (defmacro #^{:private true} evaluates-to-itself? [expr]58 `(let [v# ~expr59 q# (quote ~expr)]60 (is (= (eval q#) q#) (str q# " does not evaluate to itself"))))62 (deftest Literals63 ; Strings, numbers, characters, nil and keywords should evaluate to themselves64 (evaluates-to-itself? "test")65 (evaluates-to-itself? "test66 multi-line67 string")68 (evaluates-to-itself? 1)69 (evaluates-to-itself? 1.0)70 (evaluates-to-itself? 1.123456789)71 (evaluates-to-itself? 1/2)72 (evaluates-to-itself? 1M)73 (evaluates-to-itself? 999999999999999999)74 (evaluates-to-itself? \a)75 (evaluates-to-itself? \newline)76 (evaluates-to-itself? nil)77 (evaluates-to-itself? :test)78 ; Boolean literals should evaluate to Boolean.{TRUE|FALSE}79 (is (identical? (eval true) Boolean/TRUE))80 (is (identical? (eval false) Boolean/FALSE)))82 ;;; Symbol resolution tests ;;;84 (def foo "abc")85 (in-ns 'resolution-test)86 (def bar 123)87 (def #^{:private true} baz 456)88 (in-ns 'clojure.test-clojure.evaluation)90 (defn a-match? [re s] (not (nil? (re-matches re s))))92 (defmacro throws-with-msg93 ([re form] `(throws-with-msg ~re ~form Exception))94 ([re form x] `(throws-with-msg95 ~re96 ~form97 ~(if (instance? Exception x) x Exception)98 ~(if (instance? String x) x nil)))99 ([re form class msg]100 `(let [ex# (try101 ~form102 (catch ~class e# e#)103 (catch Exception e#104 (let [cause# (.getCause e#)]105 (if (= ~class (class cause#)) cause# (throw e#)))))]106 (is (a-match? ~re (.toString ex#))107 (or ~msg108 (str "Expected exception that matched " (pr-str ~re)109 ", but got exception with message: \"" ex#))))))111 (deftest SymbolResolution112 (test-that113 "If a symbol is namespace-qualified, the evaluated value is the value114 of the binding of the global var named by the symbol"115 (is (= (eval 'resolution-test/bar) 123)))117 (test-that118 "It is an error if there is no global var named by the symbol"119 (throws-with-msg120 #".*Unable to resolve symbol: bar.*" (eval 'bar)))122 (test-that123 "It is an error if the symbol reference is to a non-public var in a124 different namespace"125 (throws-with-msg126 #".*resolution-test/baz is not public.*"127 (eval 'resolution-test/baz)128 Compiler$CompilerException))130 (test-that131 "If a symbol is package-qualified, its value is the Java class named by the132 symbol"133 (is (= (eval 'java.lang.Math) (class-for-name "java.lang.Math"))))135 (test-that136 "If a symbol is package-qualified, it is an error if there is no Class named137 by the symbol"138 (is (thrown? Compiler$CompilerException (eval 'java.lang.FooBar))))140 (test-that141 "If a symbol is not qualified, the following applies, in this order:143 1. If it names a special form it is considered a special form, and must144 be utilized accordingly.146 2. A lookup is done in the current namespace to see if there is a mapping147 from the symbol to a class. If so, the symbol is considered to name a148 Java class object.150 3. If in a local scope (i.e. in a function definition), a lookup is done151 to see if it names a local binding (e.g. a function argument or152 let-bound name). If so, the value is the value of the local binding.154 4. A lookup is done in the current namespace to see if there is a mapping155 from the symbol to a var. If so, the value is the value of the binding156 of the var referred-to by the symbol.158 5. It is an error."160 ; First161 (doall (for [form '(def if do let quote var fn loop recur throw try162 monitor-enter monitor-exit)]163 (is (thrown? Compiler$CompilerException (eval form)))))164 (let [if "foo"]165 (is (thrown? Compiler$CompilerException (eval 'if)))167 ; Second168 (is (= (eval 'Boolean) (class-for-name "java.lang.Boolean"))))169 (let [Boolean "foo"]170 (is (= (eval 'Boolean) (class-for-name "java.lang.Boolean"))))172 ; Third173 (is (= (eval '(let [foo "bar"] foo)) "bar"))175 ; Fourth176 (in-test-ns (is (= (eval 'foo) "abc")))177 (is (thrown? Compiler$CompilerException (eval 'bar))) ; not in this namespace179 ; Fifth180 (is (thrown? Compiler$CompilerException (eval 'foobar)))))182 ;;; Metadata tests ;;;184 (defstruct struct-with-symbols (with-meta 'k {:a "A"}))186 (deftest Metadata188 (test-that189 "find returns key symbols and their metadata"190 (let [s (struct struct-with-symbols 1)]191 (is (= {:a "A"} (meta (first (find s 'k))))))))193 ;;; Collections tests ;;;194 (def x 1)195 (def y 2)197 (deftest Collections198 (in-test-ns199 (test-that200 "Vectors and Maps yield vectors and (hash) maps whose contents are the201 evaluated values of the objects they contain."202 (is (= (eval '[x y 3]) [1 2 3]))203 (is (= (eval '{:x x :y y :z 3}) {:x 1 :y 2 :z 3}))204 (is (instance? clojure.lang.IPersistentMap (eval '{:x x :y y})))))206 (in-test-ns207 (test-that208 "Metadata maps yield maps whose contents are the evaluated values of209 the objects they contain. If a vector or map has metadata, the evaluated210 metadata map will become the metadata of the resulting value."211 (is (= (eval #^{:x x} '[x y]) #^{:x 1} [1 2]))))213 (test-that214 "An empty list () evaluates to an empty list."215 (is (= (eval '()) ()))216 (is (empty? (eval ())))217 (is (= (eval (list)) ())))219 (test-that220 "Non-empty lists are considered calls"221 (is (thrown? Compiler$CompilerException (eval '(1 2 3))))))223 (deftest Macros)225 (deftest Loading)