Write generalized spec generation macro
This add `gen-spec` which provides a fairly general macro for creating `test.check` specifications for vector instructions. It takes a string used to generate specification names, a function used to check the state after running the function under test, and a list of keywords indicating types for arguments generated by `test.check` and passed to the check function. Keywords like `:integer` and `:string` are associated with "simple" generators such as `gen/small-integer` and `gen/string`. The keyword `:vector` is used to generate a vector of items whose type is specified by the `generator` argument to `generator-for-arg-type`. This allows us to loop over all of the supported vector item types in the macro and generate a separate specification for each type. We moved the `value-type` argument for the `check` functions to the front to simplify passing in the value type arguments, which can vary in number.
This commit is contained in:
parent
b41c35582a
commit
d30f7c195e
@ -190,7 +190,7 @@
|
||||
The order of concatenation is that the top of the stack will be
|
||||
_second_ in the concatenation, i.e., its elements will come _after_
|
||||
the elements in the vector one below it in the stack."
|
||||
[first-vect second-vect value-type]
|
||||
[value-type first-vect second-vect]
|
||||
(let [stack-type (keyword (str "vector_" value-type))
|
||||
start-state (state/push-to-stack
|
||||
(state/push-to-stack state/empty-state
|
||||
@ -210,7 +210,7 @@
|
||||
second-vect# (gen/vector ~generator)]
|
||||
(check-concat first-vect# second-vect# ~value-type))))))
|
||||
|
||||
(concat-spec)
|
||||
; (concat-spec)
|
||||
|
||||
;;; vector/_subvec
|
||||
|
||||
@ -229,7 +229,7 @@
|
||||
the given values on the integer stack.
|
||||
It then runs the vector/_subvec instruction, and confirms that the
|
||||
result (on the :vector_<value-type> stack) is the expected value."
|
||||
[vect start stop value-type]
|
||||
[value-type vect start stop]
|
||||
(let [stack-type (keyword (str "vector_" value-type))
|
||||
start-state (state/push-to-stack
|
||||
(state/push-to-stack
|
||||
@ -254,4 +254,37 @@
|
||||
stop# gen/small-integer]
|
||||
(check-subvec vect# start# stop# ~value-type))))))
|
||||
|
||||
(subvec-spec)
|
||||
; (subvec-spec)
|
||||
|
||||
(defn generator-for-arg-type
|
||||
[arg-type generator]
|
||||
(case arg-type
|
||||
:boolean 'gen/boolean
|
||||
:integer 'gen/small-integer
|
||||
:float 'gen/double
|
||||
:string 'gen/string
|
||||
; This is for "generic" vectors where the element is provided by
|
||||
; the `generator` argument.
|
||||
:vector `(gen/vector ~generator)
|
||||
:vector_boolean '(gen/vector gen/boolean)
|
||||
:vector_integer '(gen/vector gen/small-integer)
|
||||
:vector_float '(gen/vector gen/double)
|
||||
:vector_string '(gen/vector gen/string)
|
||||
))
|
||||
|
||||
(defmacro gen-specs
|
||||
[spec-name check-fn & arg-types]
|
||||
(let [symbol-names (repeatedly (count arg-types) gensym)]
|
||||
`(do ~@(for [[generator value-type] gen-type-pairs
|
||||
:let [name (symbol (str spec-name "-spec-" value-type))]]
|
||||
`(defspec ~name
|
||||
(prop/for-all
|
||||
[~@(mapcat
|
||||
(fn [symbol-name arg-type]
|
||||
[symbol-name (generator-for-arg-type arg-type generator)])
|
||||
symbol-names
|
||||
arg-types) ]
|
||||
(~check-fn ~value-type ~@symbol-names)))))))
|
||||
|
||||
(gen-specs "concat" check-concat :vector :vector)
|
||||
(gen-specs "subvec" check-subvec :vector :integer :integer)
|
||||
|
Loading…
x
Reference in New Issue
Block a user