updated tests, lots of errors

This commit is contained in:
Nathan Marz 2016-09-01 20:32:38 -04:00
parent 6549be1be5
commit c80bf573a5
5 changed files with 85 additions and 154 deletions

View file

@ -86,6 +86,17 @@
(defmacro providepath [name apath] (defmacro providepath [name apath]
`(i/providepath* ~name (path ~apath))) `(i/providepath* ~name (path ~apath)))
(defmacro recursive-path [params self-sym path]
(if (empty? params)
`(let [~self-sym (i/local-declarepath)]
(providepath ~self-sym ~path)
~self-sym)
`(i/direct-nav-obj
(fn ~params
(let [~self-sym (i/local-declarepath)]
(providepath ~self-sym ~path)
~self-sym)))))
;; copied from tools.macro to avoid the dependency ;; copied from tools.macro to avoid the dependency
(defn ^:no-doc name-with-attributes (defn ^:no-doc name-with-attributes
"To be used in macro definitions. "To be used in macro definitions.

View file

@ -2,12 +2,10 @@
#?(:cljs #?(:cljs
(:require-macros [com.rpl.specter.macros (:require-macros [com.rpl.specter.macros
:refer :refer
[defnav [defnav]]))
defpathedfn]]))
(:use #?(:clj (:use #?(:clj
[com.rpl.specter.macros :only [com.rpl.specter.macros :only
[defnav [defnav]]))
defpathedfn]]))
(:require [com.rpl.specter.navs :as n] (:require [com.rpl.specter.navs :as n]
[com.rpl.specter :refer [subselect selected?]])) [com.rpl.specter :refer [subselect selected?]]))

View file

@ -1,10 +1,11 @@
(ns com.rpl.specter.zipper (ns com.rpl.specter.zipper
#?(:cljs (:require-macros #?(:cljs (:require-macros
[com.rpl.specter.macros [com.rpl.specter.macros
:refer [defnav nav declarepath providepath]])) :refer [defnav nav declarepath providepath recursive-path]]))
#?(:clj #?(:clj
(:use (:use
[com.rpl.specter.macros :only [defnav nav declarepath providepath]])) [com.rpl.specter.macros :only [defnav nav declarepath providepath
recursive-path]]))
(:require [com.rpl.specter :as s] (:require [com.rpl.specter :as s]
[clojure.zip :as zip])) [clojure.zip :as zip]))
@ -116,15 +117,15 @@
(zip/remove inserted)))) (zip/remove inserted))))
(declarepath ^{:doc "Navigate the zipper to the first element (def ^{:doc "Navigate the zipper to the first element
in the structure matching predfn. A linear scan in the structure matching predfn. A linear scan
is done using NEXT to find the element."} is done using NEXT to find the element."}
find-first [predfn]) find-first
(recursive-path [predfn] p
(providepath find-first (s/if-path [NODE (s/pred predfn)]
(s/if-path [NODE s/pred]
s/STAY s/STAY
[NEXT (s/params-reset find-first)])) [NEXT p])))
(declarepath ^{:doc "Navigate to every element reachable using calls (declarepath ^{:doc "Navigate to every element reachable using calls

View file

@ -5,21 +5,21 @@
[com.rpl.specter.cljs-test-helpers :refer [for-all+]] [com.rpl.specter.cljs-test-helpers :refer [for-all+]]
[com.rpl.specter.test-helpers :refer [ic-test]] [com.rpl.specter.test-helpers :refer [ic-test]]
[com.rpl.specter.macros [com.rpl.specter.macros
:refer [paramsfn defprotocolpath defnav extend-protocolpath :refer [defprotocolpath defnav extend-protocolpath
nav declarepath providepath select select-one select-one! nav declarepath providepath select select-one select-one!
select-first transform setval replace-in defnavconstructor select-first transform setval replace-in
select-any selected-any? collected? traverse select-any selected-any? collected? traverse
multi-transform path]])) multi-transform path dynamicnav recursive-path]]))
(:use (:use
#?(:clj [clojure.test :only [deftest is]]) #?(:clj [clojure.test :only [deftest is]])
#?(:clj [clojure.test.check.clojure-test :only [defspec]]) #?(:clj [clojure.test.check.clojure-test :only [defspec]])
#?(:clj [com.rpl.specter.test-helpers :only [for-all+ ic-test]]) #?(:clj [com.rpl.specter.test-helpers :only [for-all+ ic-test]])
#?(:clj [com.rpl.specter.macros #?(:clj [com.rpl.specter.macros
:only [paramsfn defprotocolpath defnav extend-protocolpath :only [defprotocolpath defnav extend-protocolpath
nav declarepath providepath select select-one select-one! nav declarepath providepath select select-one select-one!
select-first transform setval replace-in defnavconstructor select-first transform setval replace-in
select-any selected-any? collected? traverse select-any selected-any? collected? traverse
multi-transform path]])) multi-transform path dynamicnav recursive-path]]))
@ -476,44 +476,12 @@
(gen-map-with-keys gen/keyword gen/int k2) (gen-map-with-keys gen/keyword gen/int k2)
k1)) k1))
pred (gen/elements [inc dec])] pred (gen/elements [inc dec])]
(let [p (s/comp-paths s/keypath s/keypath)] (let [p (dynamicnav [a b] (path (s/keypath a) (s/keypath b)))]
(and (and
(= (s/compiled-select (p k1 k2) m1) (select [k1 k2] m1)) (= (s/compiled-select (p k1 k2) m1) (select [k1 k2] m1))
(= (s/compiled-transform (p k1 k2) pred m1) (transform [k1 k2] pred m1)))))) (= (s/compiled-transform (p k1 k2) pred m1) (transform [k1 k2] pred m1))))))
(defspec various-orders-comp-test
(for-all+
[k1 (limit-size 3 gen/keyword)
k2 (limit-size 3 gen/keyword)
k3 (limit-size 3 gen/keyword)
m1 (limit-size 5
(gen-map-with-keys
gen/keyword
(gen-map-with-keys
gen/keyword
(gen-map-with-keys
gen/keyword
gen/int
k3)
k2)
k1))
pred (gen/elements [inc dec])]
(let [paths [((s/comp-paths s/keypath s/keypath k3) k1 k2)
(s/comp-paths k1 k2 k3)
((s/comp-paths s/keypath k2 s/keypath) k1 k3)
((s/comp-paths k1 s/keypath k3) k2)
(s/comp-paths k1 (s/keypath k2) k3)
((s/comp-paths (s/keypath k1) s/keypath (s/keypath k3)) k2)
((s/comp-paths s/keypath (s/keypath k2) s/keypath) k1 k3)]]
(and
(apply = (for [p paths] (s/compiled-select p m1)))
(apply = (for [p paths] (s/compiled-transform p pred m1)))))))
(defspec filterer-param-test (defspec filterer-param-test
(for-all+ (for-all+
[k gen/keyword [k gen/keyword
@ -529,18 +497,24 @@
pred (gen/elements [odd? even?]) pred (gen/elements [odd? even?])
updater (gen/elements [inc dec])] updater (gen/elements [inc dec])]
(and (and
(= (s/compiled-select ((s/filterer s/keypath pred) k) v) (= (select (s/filterer (s/keypath k) pred) v)
(s/compiled-select (s/filterer k pred) v)) (select (s/filterer k pred) v))
(= (s/compiled-transform ((s/comp-paths (s/filterer s/keypath pred) s/ALL k2) k) (= (transform [(s/filterer (s/keypath k) pred) s/ALL k2]
updater updater
v) v)
(s/compiled-transform (s/comp-paths (s/filterer k pred) s/ALL k2) (transform [(s/filterer k pred) s/ALL k2]
updater updater
v))))) v)))))
(deftest nested-param-paths (deftest nested-param-paths
(let [p (s/filterer s/keypath (s/selected? s/ALL s/keypath (s/filterer s/keypath even?) s/ALL)) (let [p (fn [a b c]
(path
(s/filterer (s/keypath a)
(s/selected? s/ALL
(s/keypath b)
(s/filterer (s/keypath c) even?)
s/ALL))))
p2 (p :a :b :c) p2 (p :a :b :c)
p3 (s/filterer :a (s/selected? s/ALL :b (s/filterer :c even?) s/ALL)) p3 (s/filterer :a (s/selected? s/ALL :b (s/filterer :c even?) s/ALL))
data [{:a [{:b [{:c 4 :d 5}]}]} data [{:a [{:b [{:c 4 :d 5}]}]}
@ -574,9 +548,9 @@
gen/int gen/int
k)))] k)))]
(and (and
(= (s/compiled-select ((s/subselect s/ALL s/keypath) k) v) (= (s/compiled-select (s/subselect s/ALL (s/keypath k)) v)
[(map k v)]) [(map k v)])
(let [v2 (s/compiled-transform ((s/comp-paths (s/subselect s/ALL s/keypath)) k) (let [v2 (s/compiled-transform (s/comp-paths (s/subselect s/ALL (s/keypath k)))
reverse reverse
v)] v)]
(and (= (map k v) (reverse (map k v2))) (and (= (map k v) (reverse (map k v2)))
@ -601,11 +575,11 @@
pred2 (gen/elements [odd? even?]) pred2 (gen/elements [odd? even?])
updater (gen/elements [inc dec])] updater (gen/elements [inc dec])]
(let [paths [((s/multi-path [s/keypath pred1] [s/keypath pred2] k3) k1 k2) (let [paths [(path (s/multi-path [(s/keypath k1) pred1 [(s/keypath k2) pred2 k3]]))
((s/multi-path [k1 pred1] [s/keypath pred2] s/keypath) k2 k3) (path (s/multi-path [k1 pred1] [(s/keypath k2) pred2 (s/keypath k3)]))
((s/multi-path [s/keypath pred1] [s/keypath pred2] s/keypath) k1 k2 k3) (path (s/multi-path [(s/keypath k1) pred1 [(s/keypath k2) pred2 (s/keypath k3)]]))
(s/multi-path [k1 pred1] [k2 pred2] k3) (s/multi-path [k1 pred1] [k2 pred2] k3)
((s/multi-path [k1 pred1] [s/keypath pred2] k3) k2)]] (path (s/multi-path [k1 pred1] [(s/keypath k2) pred2 k3]))]]
(and (and
(apply = (apply =
@ -617,18 +591,6 @@
(transform p updater m))))))) (transform p updater m)))))))
(defspec paramsfn-test
(for-all+
[v (gen/vector (gen/elements (range 10)))
val (gen/elements (range 10))
op (gen/elements [inc dec])
comparator (gen/elements [= > <])]
(let [cpath (s/comp-paths s/ALL (paramsfn [p] [v] (comparator v p)))]
(= (transform (cpath val) op v)
(transform [s/ALL #(comparator % val)] op v)))))
(defspec subset-test (defspec subset-test
(for-all+ (for-all+
[s1 (gen/vector (limit-size 5 gen/keyword)) [s1 (gen/vector (limit-size 5 gen/keyword))
@ -711,14 +673,12 @@
[:bb [:aa 34 [:abc 10 [:ccc 9 8 [:abc 9 1]]]] [:abc 1 [:abc 3]]])))) [:bb [:aa 34 [:abc 10 [:ccc 9 8 [:abc 9 1]]]] [:abc 1 [:abc 3]]]))))
(def map-key-walker
(declarepath map-key-walker [akey]) (recursive-path [akey] p
(providepath map-key-walker
[s/ALL [s/ALL
(s/if-path [s/FIRST (paramsfn [akey] [curr] (= curr akey))] (s/if-path [s/FIRST #(= % akey)]
s/LAST s/LAST
[s/LAST (s/params-reset map-key-walker)])]) [s/LAST p])]))
(deftest recursive-params-path-test (deftest recursive-params-path-test
(is (= #{1 2 3} (set (select (map-key-walker :aaa) (is (= #{1 2 3} (set (select (map-key-walker :aaa)
@ -731,7 +691,7 @@
(deftest recursive-params-composable-path-test (deftest recursive-params-composable-path-test
(let [p (s/comp-paths s/keypath map-key-walker)] (let [p (fn [k k2] (path (s/keypath k) (map-key-walker k2)))]
(is (= [1] (select (p 1 :a) [{:a 3} {:a 1} {:a 2}]))))) (is (= [1] (select (p 1 :a) [{:a 3} {:a 1} {:a 2}])))))
@ -740,13 +700,13 @@
(is (= {3 21 4 31} (transform [s/ALL s/ALL] inc {2 20 3 30})))) (is (= {3 21 4 31} (transform [s/ALL s/ALL] inc {2 20 3 30}))))
(declarepath NestedHigherOrderWalker [k])
(providepath NestedHigherOrderWalker (def NestedHigherOrderWalker
(recursive-path [k] p
(s/if-path vector? (s/if-path vector?
(s/if-path [s/FIRST (paramsfn [k] [e] (= k e))] (s/if-path [s/FIRST #(= % k)]
(s/continue-then-stay s/ALL (s/params-reset NestedHigherOrderWalker)) (s/continue-then-stay s/ALL p)
[s/ALL (s/params-reset NestedHigherOrderWalker)]))) [s/ALL p]))))
(deftest nested-higher-order-walker-test (deftest nested-higher-order-walker-test
@ -758,13 +718,13 @@
#?(:clj #?(:clj
(deftest large-params-test (deftest large-params-test
(let [path (apply s/comp-paths (repeat 25 s/keypath)) (let [path (apply com.rpl.specter.impl/comp-navs (for [i (range 25)] (s/keypath i)))
m (reduce m (reduce
(fn [m k] (fn [m k]
{k m}) {k m})
:a :a
(reverse (range 25)))] (reverse (range 25)))]
(is (= :a (select-one (apply path (range 25)) m)))))) (is (= :a (select-one path m))))))
;;TODO: there's a bug in clojurescript that won't allow ;;TODO: there's a bug in clojurescript that won't allow
;; non function implementations of IFn to have more than 20 arguments ;; non function implementations of IFn to have more than 20 arguments
@ -799,8 +759,8 @@
(defrecord LabeledUser [account]) (defrecord LabeledUser [account])
(defrecord LabeledFamily [accounts]) (defrecord LabeledFamily [accounts])
(extend-protocolpath LabeledAccountPath (extend-protocolpath LabeledAccountPath
LabeledUser [:account s/keypath] LabeledUser [:account (s/keypath label)]
LabeledFamily [:accounts s/keypath s/ALL]))) LabeledFamily [:accounts (s/keypath label) s/ALL])))
#?(:clj #?(:clj
@ -878,16 +838,13 @@
(= q1 q2) (= q1 q2)
(= (type q1) (type q2)))))) (= (type q1) (type q2))))))
(defnavconstructor double-str-keypath (defn ^:direct-nav double-str-keypath [s1 s2]
[p s/keypath] (path (s/keypath (str s1 s2))))
[s1 s2]
(p (str s1 s2)))
(defnavconstructor some-keypath (defn ^:direct-nav some-keypath
[p s/keypath] ([] (s/keypath "a"))
([] (p "a")) ([k1] (s/keypath (str k1 "!")))
([k1] (p (str k1 "!"))) ([k & args] (s/keypath "bbb")))
([k & args] (p "bbb")))
(deftest nav-constructor-test (deftest nav-constructor-test
;; this also tests that the eval done by clj platform during inline ;; this also tests that the eval done by clj platform during inline
@ -903,35 +860,30 @@
(deftest inline-caching-test (deftest inline-caching-test
(ic-test (ic-test
true
[k] [k]
[s/ALL (s/must k)] [s/ALL (s/must k)]
inc inc
[{:a 1} {:b 2 :c 3} {:a 7 :d -1}] [{:a 1} {:b 2 :c 3} {:a 7 :d -1}]
[[:a] [:b] [:c] [:d] [:e]]) [[:a] [:b] [:c] [:d] [:e]])
(ic-test (ic-test
true
[] []
[s/ALL #{4 5 11} #(> % 2) (fn [e] (< e 7))] [s/ALL #{4 5 11} #(> % 2) (fn [e] (< e 7))]
inc inc
(range 20) (range 20)
[]) [])
(ic-test (ic-test
false
[v] [v]
(if v :a :b) (if v :a :b)
inc inc
{:a 1 :b 2} {:a 1 :b 2}
[[true] [false]]) [[true] [false]])
(ic-test (ic-test
true
[v] [v]
[s/ALL (double-str-keypath v (inc v))] [s/ALL (double-str-keypath v (inc v))]
str str
[{"12" :a "1011" :b} {"1011" :c}] [{"12" :a "1011" :b} {"1011" :c}]
[[1] [10]]) [[1] [10]])
(ic-test (ic-test
false
[k] [k]
(*APATH* k) (*APATH* k)
str str
@ -940,7 +892,6 @@
(binding [*APATH* s/must] (binding [*APATH* s/must]
(ic-test (ic-test
false
[k] [k]
(*APATH* k) (*APATH* k)
inc inc
@ -948,7 +899,6 @@
[[:a] [:b] [:c]])) [[:a] [:b] [:c]]))
(ic-test (ic-test
true
[k k2] [k k2]
[s/ALL (s/selected? (s/must k) #(> % 2)) (s/must k2)] [s/ALL (s/selected? (s/must k) #(> % 2)) (s/must k2)]
dec dec
@ -956,7 +906,6 @@
[[:a :b] [:b :a] [:c :d] [:b :c]]) [[:a :b] [:b :a] [:c :d] [:b :c]])
(ic-test (ic-test
true
[] []
[(s/transformed s/STAY inc)] [(s/transformed s/STAY inc)]
inc inc
@ -964,30 +913,17 @@
[]) [])
(s/must-cache-paths!) ;; verifying that these don't throw errors
(is (thrown? #?(:clj Exception :cljs js/Error) (is (= 1 (select-any (if true :a :b) {:a 1})))
(select (if true :a :b) nil))) (is (= 3 (select-any (*APATH* :a) {:a 3})))
(is (= 2 (select-any [:a (identity even?)] {:a 2})))
(is (thrown? #?(:clj Exception :cljs js/Error) (is (= [10 11] (select-one! [(s/putval 10) (s/transformed s/STAY #(inc %))] 10)))
(select (*APATH* :a) nil)))
(is (thrown? #?(:clj Exception :cljs js/Error) (is (= 2 (let [p :a] (select-one! [p even?] {:a 2}))))
(select [:a (identity even?)] {:a 2})))
;; this tests a bug that existed before ^:staticparam annotation (is (= [{:a 2}] (let [p :a] (select [s/ALL (s/selected? p even?)] [{:a 2}])))))
;; for pathedfns
(is (thrown? #?(:clj Exception :cljs js/Error)
(select [(s/putval 10) (s/transformed s/STAY #(inc %))] 10)))
(let [p :a]
(is (thrown? #?(:clj Exception :cljs js/Error)
(select [p even?] {:a 2}))))
(let [p :a]
(is (thrown? #?(:clj Exception :cljs js/Error)
(select [s/ALL (s/selected? p even?)] [{:a 2}]))))
(s/must-cache-paths! false))
(deftest nested-inline-caching-test (deftest nested-inline-caching-test
@ -1024,8 +960,7 @@
;; there was a bug where the transform-fn was being factored by inline caching ;; verifies that late binding of dynamic parameters works correctly
;; this verifies that it doesn't do inline caching
(deftest transformed-inline-caching (deftest transformed-inline-caching
(dotimes [i 10] (dotimes [i 10]
(is (= [(inc i)] (select (s/transformed s/STAY #(+ % i)) 1))))) (is (= [(inc i)] (select (s/transformed s/STAY #(+ % i)) 1)))))
@ -1271,12 +1206,11 @@
(= (reduce + i (traverse [s/ALL p] v)) (= (reduce + i (traverse [s/ALL p] v))
(reduce + i (filter p v)))))) (reduce + i (filter p v))))))
(def KeyAccumWalker
(declarepath KeyAccumWalker [k]) (recursive-path [k] p
(providepath KeyAccumWalker (s/if-path (s/must k)
(s/if-path s/STAY
s/must s/STAY [s/ALL (s/collect-one s/FIRST) s/LAST p])))
[s/ALL (s/collect-one s/FIRST) s/LAST (s/params-reset KeyAccumWalker)]))
(deftest recursive-if-path-select-vals-test (deftest recursive-if-path-select-vals-test
@ -1338,13 +1272,4 @@
[even? (s/terminal-val 100)] [even? (s/terminal-val 100)]
[#(= 100 %) (s/terminal inc)] [#(= 100 %) (s/terminal inc)]
[#(= 101 %) (s/terminal inc)]) [#(= 101 %) (s/terminal inc)])
1)))) 1))))
(deftest inline-lean-path
;; use executors from ALL because it's a lean navigator
(let [e (.-executors s/ALL)]
(is (identical? e (.-executors (path :a (s/view inc)))))
(is (identical? e (.-executors (path (s/keypath :a) (s/srange 2 7)))))
(is (identical? e (.-executors (path :a (s/selected? (s/view inc) (s/selected? (s/srange 2 7)))))))))

View file

@ -5,7 +5,7 @@
[clojure.test]) [clojure.test])
(:use [com.rpl.specter.macros :only [select transform]] (:use [com.rpl.specter.macros :only [select transform]]
[com.rpl.specter :only [select* transform* must-cache-paths!]])) [com.rpl.specter :only [select* transform*]]))
;; it seems like gen/bind and gen/return are a monad (hence the names) ;; it seems like gen/bind and gen/return are a monad (hence the names)
@ -22,7 +22,7 @@
~@body))) ~@body)))
(defmacro ic-test [must-cache? params-decl apath transform-fn data params] (defmacro ic-test [params-decl apath transform-fn data params]
(let [platform (if (contains? &env :locals) :cljs :clj) (let [platform (if (contains? &env :locals) :cljs :clj)
is-sym (if (= platform :clj) 'clojure.test/is 'cljs.test/is)] is-sym (if (= platform :clj) 'clojure.test/is 'cljs.test/is)]
`(let [icfnsel# (fn [~@params-decl] (select ~apath ~data)) `(let [icfnsel# (fn [~@params-decl] (select ~apath ~data))
@ -30,11 +30,7 @@
regfnsel# (fn [~@params-decl] (select* ~apath ~data)) regfnsel# (fn [~@params-decl] (select* ~apath ~data))
regfntran# (fn [~@params-decl] (transform* ~apath ~transform-fn ~data)) regfntran# (fn [~@params-decl] (transform* ~apath ~transform-fn ~data))
params# (if (empty? ~params) [[]] ~params)] params# (if (empty? ~params) [[]] ~params)]
(must-cache-paths! ~must-cache?)
(dotimes [_# 3] (dotimes [_# 3]
(doseq [ps# params#] (doseq [ps# params#]
(~is-sym (= (apply icfnsel# ps#) (apply regfnsel# ps#))) (~is-sym (= (apply icfnsel# ps#) (apply regfnsel# ps#)))
(~is-sym (= (apply icfntran# ps#) (apply regfntran# ps#))))) (~is-sym (= (apply icfntran# ps#) (apply regfntran# ps#))))))))
(must-cache-paths! false))))