Add tests for transients, fix transient navigators based on test failures

This commit is contained in:
Alex Engelberg 2016-06-05 21:38:14 -07:00
parent 067ce9edee
commit cb0dc261cf
3 changed files with 64 additions and 14 deletions

View file

@ -466,6 +466,14 @@
(defn vec-count [v]
(count v))
#+clj
(defn transient-vec-count [^clojure.lang.ITransientVector v]
(.count v))
#+cljs
(defn transient-vec-count [v]
(count v))
(extend-protocol UpdateExtremes
#+clj clojure.lang.PersistentVector #+cljs cljs.core/PersistentVector
(update-first [v afn]
@ -505,6 +513,9 @@
#+clj clojure.lang.IPersistentVector #+cljs cljs.core/PersistentVector
(fast-empty? [v]
(= 0 (vec-count v)))
#+clj clojure.lang.ITransientVector #+cljs cljs.core/TransientVector
(fast-empty? [v]
(= 0 (transient-vec-count v)))
#+clj Object #+cljs default
(fast-empty? [s]
(empty? s))
@ -762,21 +773,11 @@
(extend-protocol p/Navigator
TransientEndNavigator
(select* [this structure next-fn]
[])
(next-fn []))
(transform* [this structure next-fn]
(let [res (next-fn [])]
(reduce conj! structure res))))
(deftype TransientLastNavigator [])
(extend-protocol p/Navigator
TransientLastNavigator
(select* [this structure next-fn]
(next-fn (nth structure (dec (count structure)))))
(transform* [this structure next-fn]
(let [i (dec (count structure))]
(assoc! structure i (next-fn (nth structure i))))))
#+clj
(defn transient-all-select
[structure next-fn]

View file

@ -25,13 +25,30 @@
"Navigates to an empty (persistent) vector at the end of a transient vector."
(i/comp-paths* [(i/->TransientEndNavigator)]))
(defn- t-get-first
[tv]
(nth tv 0))
(defn- t-get-last
[tv]
(nth tv (dec (i/transient-vec-count tv))))
(defn- t-update-first
[tv next-fn]
(assoc! tv 0 (next-fn (nth tv 0))))
(defn- t-update-last
[tv next-fn]
(let [i (dec (i/transient-vec-count tv))]
(assoc! tv i (next-fn (nth tv i)))))
(def FIRST!
"Navigates to the first element of a transient vector."
(keypath! 0))
(i/->PosNavigator t-get-first t-update-first))
(def LAST!
"Navigates to the last element of a transient vector."
(i/comp-paths* [(i/->TransientLastNavigator)]))
(i/->PosNavigator t-get-last t-update-last))
(defn- select-keys-from-transient-map
"Selects keys from transient map, because built-in select-keys uses
@ -54,7 +71,7 @@
submap!
[m-keys]
(select* [this structure next-fn]
(select-keys-from-transient-map structure m-keys))
(next-fn (select-keys-from-transient-map structure m-keys)))
(transform* [this structure next-fn]
(let [selected (select-keys-from-transient-map structure m-keys)
res (next-fn selected)]

View file

@ -25,6 +25,7 @@
#+cljs [cljs.test.check.generators :as gen]
#+cljs [cljs.test.check.properties :as prop :include-macros true]
[com.rpl.specter :as s]
[com.rpl.specter.transient :as t]
[clojure.set :as set]))
;;TODO:
@ -1036,3 +1037,34 @@
(is (= 2 (key e)))
(is (= 4 (val e)))
))
(defspec transient-vector-test
(for-all+
[v (gen/vector (limit-size 5 gen/int))]
(every? identity
(for [[path transient-path f]
[[s/FIRST t/FIRST! (fnil inc 0)] ;; fnil in case vector is empty
[s/LAST t/LAST! (fnil inc 0)]
[(s/keypath 0) (t/keypath! 0) (fnil inc 0)]
[s/END t/END! #(conj % 1 2 3)]]]
(and (= (s/transform* path f v)
(persistent! (s/transform* transient-path f (transient v))))
(= (s/select* path v)
(s/select* transient-path (transient v))))))))
(defspec transient-map-test
(for-all+
[m (gen/not-empty (gen/map gen/keyword gen/int))
new-key gen/keyword]
(let [existing-key (first (keys m))]
(every? identity
(for [[path transient-path f]
[[(s/keypath existing-key) (t/keypath! existing-key) inc]
[(s/keypath new-key) (t/keypath! new-key) (constantly 3)]
[(s/submap [existing-key new-key])
(t/submap! [existing-key new-key])
(constantly {new-key 1234})]]]
(and (= (s/transform* path f m)
(persistent! (s/transform* transient-path f (transient m))))
(= (s/select* path m)
(s/select* transient-path (transient m)))))))))