diff src/clojure/test_clojure/serialization.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/serialization.clj	Sat Aug 21 06:25:44 2010 -0400
     1.3 @@ -0,0 +1,158 @@
     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: Chas Emerick
    1.13 +;;         cemerick@snowtide.com
    1.14 +
    1.15 +(ns clojure.test-clojure.serialization
    1.16 +  (:use clojure.test)
    1.17 +  (:import (java.io ObjectOutputStream ObjectInputStream
    1.18 +             ByteArrayOutputStream ByteArrayInputStream)))
    1.19 +
    1.20 +(defn- serialize
    1.21 +  "Serializes a single object, returning a byte array."
    1.22 +  [v]
    1.23 +  (with-open [bout (ByteArrayOutputStream.)
    1.24 +              oos (ObjectOutputStream. bout)]
    1.25 +    (.writeObject oos v)
    1.26 +    (.flush oos)
    1.27 +    (.toByteArray bout)))
    1.28 +
    1.29 +(defn- deserialize
    1.30 +  "Deserializes and returns a single object from the given byte array."
    1.31 +  [bytes]
    1.32 +  (with-open [ois (-> bytes ByteArrayInputStream. ObjectInputStream.)]
    1.33 +    (.readObject ois)))
    1.34 +
    1.35 +(defrecord SerializationRecord [a b c])
    1.36 +(defstruct SerializationStruct :a :b :c)
    1.37 +
    1.38 +(defn- build-via-transient
    1.39 +  [coll]
    1.40 +  (persistent!
    1.41 +    (reduce conj! (transient coll) (map vec (partition 2 (range 1000))))))
    1.42 +
    1.43 +(defn- roundtrip
    1.44 +  [v]
    1.45 +  (let [rt (-> v serialize deserialize)
    1.46 +        rt-seq (-> v seq serialize deserialize)]
    1.47 +    (and (= v rt)
    1.48 +      (= (seq v) (seq rt))
    1.49 +      (= (seq v) rt-seq))))
    1.50 +
    1.51 +(deftest sequable-serialization
    1.52 +  (are [val] (roundtrip val)
    1.53 +    ; lists and related
    1.54 +    (list)
    1.55 +    (apply list (range 10))
    1.56 +    (cons 0 nil)
    1.57 +    (clojure.lang.Cons. 0 nil)
    1.58 +
    1.59 +    ; vectors
    1.60 +    []
    1.61 +    (into [] (range 10))
    1.62 +    (into [] (range 25))
    1.63 +    (into [] (range 100))
    1.64 +    (into [] (range 500))
    1.65 +    (into [] (range 1000))
    1.66 +
    1.67 +    ; maps
    1.68 +    {}
    1.69 +    {:a 5 :b 0}
    1.70 +    (apply array-map (range 100))
    1.71 +    (apply hash-map (range 100))
    1.72 +
    1.73 +    ; sets
    1.74 +    #{}
    1.75 +    #{'a 'b 'c}
    1.76 +    (set (range 10))
    1.77 +    (set (range 25))
    1.78 +    (set (range 100))
    1.79 +    (set (range 500))
    1.80 +    (set (range 1000))
    1.81 +    (sorted-set)
    1.82 +    (sorted-set 'a 'b 'c)
    1.83 +    (apply sorted-set (reverse (range 10)))
    1.84 +    (apply sorted-set (reverse (range 25)))
    1.85 +    (apply sorted-set (reverse (range 100)))
    1.86 +    (apply sorted-set (reverse (range 500)))
    1.87 +    (apply sorted-set (reverse (range 1000)))
    1.88 +
    1.89 +    ; queues
    1.90 +    clojure.lang.PersistentQueue/EMPTY
    1.91 +    (into clojure.lang.PersistentQueue/EMPTY (range 50))
    1.92 +
    1.93 +    ; lazy seqs
    1.94 +    (lazy-seq nil)
    1.95 +    (lazy-seq (range 50))
    1.96 +
    1.97 +    ; transient / persistent! round-trip
    1.98 +    (build-via-transient [])
    1.99 +    (build-via-transient {})
   1.100 +    (build-via-transient #{})
   1.101 +    
   1.102 +    ; array-seqs
   1.103 +    (seq (make-array Object 10))
   1.104 +    (seq (make-array Boolean/TYPE 10))
   1.105 +    (seq (make-array Byte/TYPE 10))
   1.106 +    (seq (make-array Character/TYPE 10))
   1.107 +    (seq (make-array Double/TYPE 10))
   1.108 +    (seq (make-array Float/TYPE 10))
   1.109 +    (seq (make-array Integer/TYPE 10))
   1.110 +    (seq (make-array Long/TYPE 10))
   1.111 +
   1.112 +    ; "records"
   1.113 +    (SerializationRecord. 0 :foo (range 20))
   1.114 +    (struct SerializationStruct 0 :foo (range 20))
   1.115 +
   1.116 +    ; misc seqs
   1.117 +    (seq "s11n")
   1.118 +    (range 50)
   1.119 +    (rseq (apply sorted-set (reverse (range 100))))))
   1.120 +
   1.121 +(deftest misc-serialization
   1.122 +  (are [v] (= v (-> v serialize deserialize))
   1.123 +    25/3
   1.124 +    :keyword
   1.125 +    ::namespaced-keyword
   1.126 +    'symbol))
   1.127 +
   1.128 +(deftest interned-serializations
   1.129 +  (are [v] (identical? v (-> v serialize deserialize))
   1.130 +    clojure.lang.RT/DEFAULT_COMPARATOR
   1.131 +    
   1.132 +    ; namespaces just get deserialized back into the same-named ns in the present runtime
   1.133 +    ; (they're referred to by defrecord instances)
   1.134 +    *ns*))
   1.135 +
   1.136 +(deftest function-serialization
   1.137 +  (let [capture 5]
   1.138 +    (are [f] (= capture ((-> f serialize deserialize)))
   1.139 +      (constantly 5)
   1.140 +      (fn [] 5)
   1.141 +      #(do 5)
   1.142 +      (constantly capture)
   1.143 +      (fn [] capture)
   1.144 +      #(do capture))))
   1.145 +
   1.146 +(deftest check-unserializable-objects
   1.147 +  (are [t] (thrown? java.io.NotSerializableException (serialize t))
   1.148 +    ;; transients
   1.149 +    (transient [])
   1.150 +    (transient {})
   1.151 +    (transient #{})
   1.152 +
   1.153 +    ;; reference types
   1.154 +    (atom nil)
   1.155 +    (ref nil)
   1.156 +    (agent nil)
   1.157 +    #'+
   1.158 +
   1.159 +    ;; stateful seqs
   1.160 +    (enumeration-seq (java.util.Collections/enumeration (range 50)))
   1.161 +    (iterator-seq (.iterator (range 50)))))
   1.162 \ No newline at end of file