diff --git a/project.clj b/project.clj index 34f107f..c0845a9 100644 --- a/project.clj +++ b/project.clj @@ -11,7 +11,10 @@ :1.5 {:dependencies [[org.clojure/clojure "1.5.1"]]} :1.6 {:dependencies [[org.clojure/clojure "1.6.0-alpha3"]]} :dev {:dependencies []} - :test {:dependencies [[expectations "1.4.56"] + :test {:jvm-opts ["-Xms1024m" ; Initial heap size + "-Xmx2048m" ; Max heap size + ] + :dependencies [[expectations "1.4.56"] [org.xerial.snappy/snappy-java "1.1.1-M1"] [reiddraper/simple-check "0.5.3"] [org.clojure/data.fressian "0.2.0"]]} diff --git a/test/taoensso/nippy/tests/main.clj b/test/taoensso/nippy/tests/main.clj index 629190f..a033981 100644 --- a/test/taoensso/nippy/tests/main.clj +++ b/test/taoensso/nippy/tests/main.clj @@ -1,5 +1,8 @@ (ns taoensso.nippy.tests.main - (:require [expectations :as test :refer :all] + (:require [simple-check (core :as sc) + (generators :as sc-gen) + (properties :as sc-prop)] + [expectations :as test :refer :all] [taoensso.nippy :as nippy :refer (freeze thaw)] [taoensso.nippy.compression :as compression] [taoensso.nippy.benchmarks :as benchmarks])) @@ -8,6 +11,8 @@ (defn- before-run {:expectations-options :before-run} []) (defn- after-run {:expectations-options :after-run} []) +;;;; Core + (expect test-data ((comp thaw freeze) test-data)) (expect test-data ((comp thaw #(freeze % {:legacy-mode true})) test-data)) (expect test-data ((comp #(thaw % {:password [:salted "p"]}) @@ -37,6 +42,7 @@ (thaw (org.iq80.snappy.Snappy/uncompress iq80-ba 0 (alength iq80-ba))) (thaw (org.iq80.snappy.Snappy/uncompress xerial-ba 0 (alength xerial-ba)))))) +;;;; Custom types & records ;;; Extend to custom Type (defrecord MyType [data]) @@ -51,4 +57,57 @@ (nippy/extend-thaw 2 [s] (->MyRec (.readUTF s))) (= (->MyRec "fast-val") (thaw (freeze (->MyRec "val")))))) +;;;; Stable binary representation of vals ; EXPERIMENTAL + +(expect (seq (nippy/freeze test-data)) + (seq (nippy/freeze test-data))) ; f(x)=f(y) | x=y + +;;; As above, but try multiple times (catch protocol interface races): +(expect #(every? true? %) + (repeatedly 1000 (fn [] (= (seq (nippy/freeze test-data)) + (seq (nippy/freeze test-data)))))) + +(expect (seq (-> test-data nippy/freeze)) ; f(x)=f(f-1(f(x))) + (seq (-> test-data nippy/freeze nippy/thaw nippy/freeze))) + +;;; As above, but with repeated refreeze (catch protocol interface races): +(expect (= (seq (nippy/freeze test-data)) + (seq (reduce (fn [frozen _] (freeze (thaw frozen))) + (freeze test-data) (range 1000))))) + +;;; + +(defn qc-prop-bijection [& [n]] + (let [bin->val (atom {}) + val->bin (atom {})] + (merge + (sc/quick-check (or n 1) + (sc-prop/for-all [val sc-gen/any #_sc-gen/any-printable] + (let [;; Nb need `seq` for Clojure hash equality: + bin (hash (seq (freeze val)))] + (and + (if (contains? val->bin val) + (= (get val->bin val) bin) ; x=y => f(x)=f(y) by clj= + (do (swap! val->bin assoc val bin) + true)) + + (if (contains? bin->val bin) + (= (get bin->val bin) val) ; f(x)=f(y) => x=y by clj= + (do (swap! bin->val assoc bin val) + true)))))) + #_ {:bin->val @bin->val + :val->bin @val->bin} + nil))) + +(comment + (sc-gen/sample sc-gen/any 10) + (:result (qc-prop-bijection 80)) + (let [{:keys [result bin->val val->bin]} (qc-prop-bijection 10)] + [result (vals bin->val)])) + +;; (expect #(:result %) (qc-prop-bijection 120)) ; Time seems to be n-non-linear +(expect #(:result %) (qc-prop-bijection 80)) + +;;;; Benchmarks + (expect (benchmarks/bench {})) ; Also tests :cached passwords