added tests and cljs-specific fixes

This commit is contained in:
Nathan Marz 2016-05-23 14:58:22 -04:00
parent 218cbcb933
commit 4f3990c239
4 changed files with 97 additions and 8 deletions

View file

@ -681,8 +681,7 @@
#+cljs
(defn handle-params [precompiled params-maker possible-params]
(let [params (fast-object-array (count params-maker))]
;;TODO: is there a faster way to do this in cljs?
(doseq [i (range (count params-maker))]
(dotimes [i (count params-maker)]
(aset params i ((get possible-params (get params-maker i)))))
(bind-params* precompiled params 0)
))
@ -729,7 +728,7 @@
))
(instance? SpecialFormUse p)
(if (-> p :code first (= 'fn*))
(if (->> p :code first (contains? #{'fn* 'fn}))
(do
(swap! params-atom conj (:code p))
pred*

View file

@ -333,7 +333,9 @@
(i/fn-invocation? path)
(let [[op & params] path]
(if (special-symbol? op)
;; need special case for 'fn since macroexpand does NOT
;; expand fn when run on cljs code, but it's also not considered a special symbol
(if (or (= 'fn op) (special-symbol? op))
`(com.rpl.specter.impl/->SpecialFormUse ~path (quote ~path))
`(com.rpl.specter.impl/->FnInvocation
~(ic-prepare-path locals-set op)
@ -351,7 +353,7 @@
(fn [e]
(cond (or (set? e)
(map? e) ; in case inline maps are ever extended
(and (i/fn-invocation? e) (= 'fn* (first e))))
(and (i/fn-invocation? e) (contains? #{'fn* 'fn} (first e))))
[e]
(i/fn-invocation? e)
@ -399,7 +401,6 @@
~(mapv (fn [p] `(fn [] ~p)) possible-params)
))
]
;; in order to pass the used locals to the clj handle-params macro
`(let [info# (i/get-path-cache ~cache-id)
^com.rpl.specter.impl.CachedPathInfo info#

View file

@ -3,6 +3,7 @@
[cljs.test :refer [is deftest]]
[cljs.test.check.cljs-test :refer [defspec]]
[com.rpl.specter.cljs-test-helpers :refer [for-all+]]
[com.rpl.specter.test-helpers :refer [ic-test]]
[com.rpl.specter.macros
:refer [paramsfn defprotocolpath defnav extend-protocolpath
nav declarepath providepath select select-one select-one!
@ -10,7 +11,7 @@
(:use
#+clj [clojure.test :only [deftest is]]
#+clj [clojure.test.check.clojure-test :only [defspec]]
#+clj [com.rpl.specter.test-helpers :only [for-all+]]
#+clj [com.rpl.specter.test-helpers :only [for-all+ ic-test]]
#+clj [com.rpl.specter.macros
:only [paramsfn defprotocolpath defnav extend-protocolpath
nav declarepath providepath select select-one select-one!
@ -858,3 +859,67 @@
(= q1 q2)
(= (type q1) (type q2))))))
(def ^:dynamic *APATH* s/keypath)
(deftest inline-caching-test
(ic-test
true
[k]
[s/ALL (s/must k)]
inc
[{:a 1} {:b 2 :c 3} {:a 7 :d -1}]
[[:a] [:b] [:c] [:d] [:e]])
(ic-test
true
[]
[s/ALL #{4 5 11} #(> % 2) (fn [e] (< e 7))]
inc
(range 20)
[])
(ic-test
false
[v]
(if v :a :b)
inc
{:a 1 :b 2}
[[true] [false]])
(ic-test
false
[k]
(*APATH* k)
str
{:a 1 :b 2}
[[:a] [:b] [:c]]
)
(binding [*APATH* s/must]
(ic-test
false
[k]
(*APATH* k)
inc
{:a 1 :b 2}
[[:a] [:b] [:c]]
))
(ic-test
true
[k k2]
[s/ALL (s/selected? (s/must k) #(> % 2)) (s/must k2)]
dec
[{:a 1 :b 2} {:a 10 :b 6} {:c 7 :b 8} {:c 1 :d 9} {:c 3 :d -1}]
[[:a :b] [:b :a] [:c :d] [:b :c]]
)
;; TODO: test exception thrown when can't cache and must-cache-paths!
)
;;TODO:
;; make a macro to help with testing inline caching
;; - put into test-helpers
;; - do must-cache-paths!
;; - take in params vec, path expression, data, transform fn, and sequence of param vecs
;; - verify that functional version gets same result as inline
;; caching version run on the data multiple times (make sure same callsite)
;; - have another test that turns must-cache-paths on and verifies certain paths
;; don't cache (but still run with must-cache-paths off)

View file

@ -1,10 +1,15 @@
(ns com.rpl.specter.test-helpers
(:require [clojure.test.check
[generators :as gen]
[properties :as prop]]))
[properties :as prop]]
[clojure.test]
[cljs.test])
(:use [com.rpl.specter.macros :only [select transform]]
[com.rpl.specter :only [select* transform* must-cache-paths!]]))
;; it seems like gen/bind and gen/return are a monad (hence the names)
;; this is only for clj (cljs version in different file)
(defmacro for-all+ [bindings & body]
(let [parts (partition 2 bindings)
vars (vec (map first parts))
@ -15,3 +20,22 @@
(reverse parts))]
`(prop/for-all [~vars ~genned]
~@body )))
(defmacro ic-test [must-cache? params-decl apath transform-fn data params]
(let [platform (if (contains? &env :locals) :cljs :clj)
is-sym (if (= platform :clj) 'clojure.test/is 'cljs.test/is)]
`(let [icfnsel# (fn [~@params-decl] (select ~apath ~data))
icfntran# (fn [~@params-decl] (transform ~apath ~transform-fn ~data))
regfnsel# (fn [~@params-decl] (select* ~apath ~data))
regfntran# (fn [~@params-decl] (transform* ~apath ~transform-fn ~data))
params# (if (empty? ~params) [[]] ~params)
]
(must-cache-paths! ~must-cache?)
(dotimes [_# 3]
(doseq [ps# params#]
(~is-sym (= (apply icfnsel# ps#) (apply regfnsel# ps#)))
(~is-sym (= (apply icfntran# ps#) (apply regfntran# ps#)))
))
(must-cache-paths! false)
)))