From 5849320d3a5cccebd540365b49e34cc944632199 Mon Sep 17 00:00:00 2001 From: Peter Taoussanis Date: Tue, 1 Dec 2015 13:07:38 +0700 Subject: [PATCH] Drop Expectations, migrate to clojure.test, update test.check stuff --- project.clj | 6 +- test/taoensso/nippy/tests/main.clj | 285 ++++++++++++++++------------- 2 files changed, 158 insertions(+), 133 deletions(-) diff --git a/project.clj b/project.clj index ee71d7b..dc2bf72 100644 --- a/project.clj +++ b/project.clj @@ -28,8 +28,7 @@ :1.7 {:dependencies [[org.clojure/clojure "1.7.0"]]} :1.8 {:dependencies [[org.clojure/clojure "1.8.0-RC2"]]} :test {:jvm-opts ["-Xms1024m" "-Xmx2048m"] - :dependencies [[expectations "2.1.4"] - [org.clojure/test.check "0.9.0"] + :dependencies [[org.clojure/test.check "0.9.0"] [org.clojure/data.fressian "0.2.1"] [org.xerial.snappy/snappy-java "1.1.2"]]} :dev [:1.7 :test @@ -45,8 +44,7 @@ :source-uri "https://github.com/ptaoussanis/nippy/blob/master/{filepath}#L{line}"} :aliases - {"test-all" ["with-profile" "+1.5:+1.6:+1.7:+1.8" "expectations"] - "test-auto" ["with-profile" "+test" "autoexpect"] + {"test-all" ["with-profile" "+1.5:+1.6:+1.7:+1.8" "test"] "deploy-lib" ["do" "deploy" "clojars," "install"] "start-dev" ["with-profile" "+server-jvm" "repl" ":headless"]} diff --git a/test/taoensso/nippy/tests/main.clj b/test/taoensso/nippy/tests/main.clj index a43c2cf..906d174 100644 --- a/test/taoensso/nippy/tests/main.clj +++ b/test/taoensso/nippy/tests/main.clj @@ -1,174 +1,201 @@ (ns taoensso.nippy.tests.main - (:require [clojure.test.check :as check] - [clojure.test.check.generators :as check-gen] - [clojure.test.check.properties :as check-props] - [expectations :as test :refer :all] - [taoensso.nippy :as nippy :refer (freeze thaw)] - [taoensso.nippy.benchmarks :as benchmarks])) + (:require + [clojure.test :as test :refer (is are deftest run-tests)] + [clojure.test.check :as tc] + [clojure.test.check.generators :as tc-gens] + [clojure.test.check.properties :as tc-props] + [taoensso.encore :as enc :refer ()] + [taoensso.nippy :as nippy :refer (freeze thaw)] + [taoensso.nippy.benchmarks :as benchmarks])) -(comment (test/run-tests '[taoensso.nippy.tests.main])) +(comment (test/run-tests)) (def test-data nippy/stress-data-comparable) -(defn- before-run {:expectations-options :before-run} []) -(defn- after-run {:expectations-options :after-run} []) +(def tc-num-tests 120) +(def tc-gens + "Like `tc-gens/any` but removes NaN (which breaks equality tests)" + (tc-gens/recursive-gen tc-gens/container-type #_simple-type + (tc-gens/one-of + [tc-gens/int tc-gens/large-integer #_tc-gens/double + (tc-gens/double* {:NaN? false}) + tc-gens/char tc-gens/string tc-gens/ratio tc-gens/boolean tc-gens/keyword + tc-gens/keyword-ns tc-gens/symbol tc-gens/symbol-ns tc-gens/uuid]))) + +(comment (tc-gens/sample tc-gens 10)) ;;;; Core -(expect (do (println (str "Clojure version: " *clojure-version*)) true)) +(deftest _core + (is (do (println (str "Clojure version: " *clojure-version*)) true)) + (is (= test-data ((comp thaw freeze) test-data))) + (is (= test-data ((comp #(thaw % {:no-header? true + :compressor nippy/lz4-compressor + :encryptor nil}) + #(freeze % {:no-header? true})) + test-data))) -(expect test-data ((comp thaw freeze) test-data)) -(expect test-data ((comp #(thaw % {:no-header? true - :compressor nippy/lz4-compressor - :encryptor nil}) - #(freeze % {:no-header? true})) - test-data)) -(expect test-data ((comp #(thaw % {:password [:salted "p"]}) - #(freeze % {:password [:salted "p"]})) - test-data)) -(expect test-data ((comp #(thaw % {:compressor nippy/lzma2-compressor}) - #(freeze % {:compressor nippy/lzma2-compressor})) - test-data)) -(expect test-data ((comp #(thaw % {:compressor nippy/lzma2-compressor - :password [:salted "p"]}) - #(freeze % {:compressor nippy/lzma2-compressor - :password [:salted "p"]})) - test-data)) -(expect test-data ((comp #(thaw % {:compressor nippy/lz4-compressor}) - #(freeze % {:compressor nippy/lz4hc-compressor})) - test-data)) + (is (= test-data ((comp #(thaw % {:password [:salted "p"]}) + #(freeze % {:password [:salted "p"]})) + test-data))) -(expect ; Try roundtrip anything that simple-check can dream up - (:result (check/quick-check 80 ; Time is n-non-linear - (check-props/for-all [val check-gen/any] - (= val (thaw (freeze val))))))) + (is (= test-data ((comp #(thaw % {:compressor nippy/lzma2-compressor}) + #(freeze % {:compressor nippy/lzma2-compressor})) + test-data))) -(expect Exception (thaw (freeze test-data {:password "malformed"}))) -(expect Exception (thaw (freeze test-data {:password [:salted "p"]}) - {;; Necessary to prevent against JVM segfault due to - ;; https://goo.gl/t0OUIo: - :v1-compatibility? false})) -(expect Exception (thaw (freeze test-data {:password [:salted "p"]}) - {:v1-compatibility? false ; Ref. https://goo.gl/t0OUIo - :compressor nil})) + (is (= test-data ((comp #(thaw % {:compressor nippy/lzma2-compressor + :password [:salted "p"]}) + #(freeze % {:compressor nippy/lzma2-compressor + :password [:salted "p"]})) + test-data))) -(expect ; Snappy lib compatibility (for legacy versions of Nippy) - (let [^bytes raw-ba (freeze test-data {:compressor nil}) - ^bytes xerial-ba (org.xerial.snappy.Snappy/compress raw-ba) - ^bytes iq80-ba (org.iq80.snappy.Snappy/compress raw-ba)] - (= (thaw raw-ba) - (thaw (org.xerial.snappy.Snappy/uncompress xerial-ba)) - (thaw (org.xerial.snappy.Snappy/uncompress iq80-ba)) - (thaw (org.iq80.snappy.Snappy/uncompress iq80-ba 0 (alength iq80-ba))) - (thaw (org.iq80.snappy.Snappy/uncompress xerial-ba 0 (alength xerial-ba)))))) + (is (= test-data ((comp #(thaw % {:compressor nippy/lz4-compressor}) + #(freeze % {:compressor nippy/lz4hc-compressor})) + test-data))) + + (is ; Try roundtrip anything that simple-check can dream up + (:result (tc/quick-check tc-num-tests + (tc-props/for-all [val tc-gens] + (= val (thaw (freeze val))))))) + + (is (thrown? Exception (thaw (freeze test-data {:password "malformed"})))) + (is (thrown? Exception (thaw (freeze test-data {:password [:salted "p"]}) + {;; Necessary to prevent against JVM segfault due to + ;; https://goo.gl/t0OUIo: + :v1-compatibility? false}))) + (is (thrown? Exception (thaw (freeze test-data {:password [:salted "p"]}) + {:v1-compatibility? false ; Ref. https://goo.gl/t0OUIo + :compressor nil}))) + + (is ; Snappy lib compatibility (for legacy versions of Nippy) + (let [^bytes raw-ba (freeze test-data {:compressor nil}) + ^bytes xerial-ba (org.xerial.snappy.Snappy/compress raw-ba) + ^bytes iq80-ba (org.iq80.snappy.Snappy/compress raw-ba)] + (= (thaw raw-ba) + (thaw (org.xerial.snappy.Snappy/uncompress xerial-ba)) + (thaw (org.xerial.snappy.Snappy/uncompress iq80-ba)) + (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]) -(expect Exception (do (nippy/extend-freeze MyType 1 [x s] (.writeUTF s (:data x))) - (thaw (freeze (->MyType "val"))))) -(expect (do (nippy/extend-thaw 1 [s] (->MyType (.readUTF s))) - (let [type (->MyType "val")] (= type (thaw (freeze type)))))) +(deftype MyType [data]) +(defrecord MyRec [data]) -;;; Extend to custom Record -(defrecord MyRec [data]) -(expect (do (nippy/extend-freeze MyRec 2 [x s] (.writeUTF s (str "foo-" (:data x)))) - (nippy/extend-thaw 2 [s] (->MyRec (.readUTF s))) - (= (->MyRec "foo-val") (thaw (freeze (->MyRec "val")))))) +(deftest _types + ;;; Extend to custom Type + (is (thrown? Exception ; No thaw extension yet + (do (nippy/swap-custom-readers! (constantly {})) + (nippy/extend-freeze MyType 1 [x s] (.writeUTF s (.data x))) + (thaw (freeze (->MyType "val")))))) + (is (do (nippy/extend-thaw 1 [s] (->MyType (.readUTF s))) + (let [mt (->MyType "val")] (= (.data ^MyType mt) + (.data ^MyType (thaw (freeze mt))))))) -;;; Keyword (prefixed) extensions -(expect - (do (nippy/extend-freeze MyType :nippy-tests/MyType [x s] (.writeUTF s (:data x))) - (nippy/extend-thaw :nippy-tests/MyType [s] (->MyType (.readUTF s))) - (let [type (->MyType "val")] (= type (thaw (freeze type)))))) + ;;; Extend to custom Record + (is (do (nippy/extend-freeze MyRec 2 [x s] (.writeUTF s (str "foo-" (:data x)))) + (nippy/extend-thaw 2 [s] (->MyRec (.readUTF s))) + (= (->MyRec "foo-val") (thaw (freeze (->MyRec "val")))))) + + ;;; Keyword (prefixed) extensions + (is + (do (nippy/extend-freeze MyRec :nippy-tests/MyRec [x s] (.writeUTF s (:data x))) + (nippy/extend-thaw :nippy-tests/MyRec [s] (->MyRec (.readUTF s))) + (let [mr (->MyRec "val")] (= mr (thaw (freeze mr))))))) ;;;; Stable binary representation of vals -(expect (seq (freeze test-data)) - (seq (freeze test-data))) ; f(x)=f(y) | x=y +(deftest _stable-bin -;; As above, but try multiple times to catch possible protocol interface races: -(expect #(every? true? %) + (is (= (seq (freeze test-data)) + (seq (freeze test-data)))) ; f(x)=f(y) | x=y + + ;; As above, but try multiple times to catch possible protocol interface races: + (is (every? true? (repeatedly 1000 (fn [] (= (seq (freeze test-data)) - (seq (freeze test-data)))))) + (seq (freeze test-data))))))) -;; NB abandoning - no way to do this reliably w/o appropriate contracts from -;; (seq ): -;; -;; (expect (seq (-> test-data freeze)) ; f(x)=f(f-1(f(x))) -;; (seq (-> test-data freeze thaw freeze))) -;; -;; As above, but with repeated refreeze to catch possible protocol interface races: -;; (expect (= (seq (freeze test-data)) -;; (seq (reduce (fn [frozen _] (freeze (thaw frozen))) -;; (freeze test-data) (range 1000))))) + ;; NB abandoning - no way to do this reliably w/o appropriate contracts from + ;; (seq ): + ;; + ;; (is (= (seq (-> test-data freeze)) + ;; (seq (-> test-data freeze thaw freeze)))) ; f(x)=f(f-1(f(x))) + ;; + ;; As above, but with repeated refreeze to catch possible protocol interface races: + ;; (is (= (seq (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 - (check/quick-check (or n 1) - (check-props/for-all [val check-gen/any #_check-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)) + (tc/quick-check (or n 1) + (tc-props/for-all [val tc-gens] + (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))) + (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 - (check-gen/sample check-gen/any 10) + (tc-gens/sample tc-gens 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 80)) +(deftest _gc-prop-bijection + (is (:result (qc-prop-bijection tc-num-tests)))) ;;;; Thread safety ;; Not sure why, but record equality test fails in futures: (def test-data-threaded (dissoc nippy/stress-data-comparable :stress-record)) -(expect - (let [futures - (mapv - (fn [_] - (future - (= (thaw (freeze test-data-threaded)) test-data-threaded))) - (range 50))] - (every? deref futures))) +(deftest _thread-safe + (is + (let [futures + (mapv + (fn [_] + (future + (= (thaw (freeze test-data-threaded)) test-data-threaded))) + (range 50))] + (every? deref futures))) -(expect - (let [futures - (mapv - (fn [_] - (future - (= (thaw (freeze test-data-threaded {:password [:salted "password"]}) - {:password [:salted "password"]}) - test-data-threaded))) - (range 50))] - (every? deref futures))) + (is + (let [futures + (mapv + (fn [_] + (future + (= (thaw (freeze test-data-threaded {:password [:salted "password"]}) + {:password [:salted "password"]}) + test-data-threaded))) + (range 50))] + (every? deref futures))) -(expect - (let [futures - (mapv - (fn [_] - (future - (= (thaw (freeze test-data-threaded {:password [:cached "password"]}) - {:password [:cached "password"]}) - test-data-threaded))) - (range 50))] - (every? deref futures))) + (is + (let [futures + (mapv + (fn [_] + (future + (= (thaw (freeze test-data-threaded {:password [:cached "password"]}) + {:password [:cached "password"]}) + test-data-threaded))) + (range 50))] + (every? deref futures)))) ;;;; Benchmarks -(expect (benchmarks/bench {})) ; Also tests :cached passwords +(deftest _benchmarks + (is (benchmarks/bench {})) ; Also tests :cached passwords + )