I am using Clojure spec to spec a simple data structure:
{:max 10
:data [[3 8 1]
[9 0 1]]}
The :data
value is a vector of equal-size vectors of integers in the interval from zero to the :max
value inclusive. I expressed this with spec as follows:
(s/def ::max pos-int?)
(s/def ::row (s/coll-of nat-int? :kind vector?, :min-count 1))
(s/def ::data (s/and (s/coll-of ::row :kind vector?, :min-count 1)
#(apply = (map count %))))
(s/def ::image (s/and (s/keys :req-un [::max ::data])
(fn [{:keys [max data]}]
(every? #(<= 0 % max) (flatten data)))))
Automatic generators work fine for the first three specs, but not for ::image
. (s/exercise ::image)
always fails after 100 tries.
I tried to create a custom generator for ::image
but did not manage. I don’t see how I could express the constraints which cross the layers of the nested structure (key :max
constrains values in a vector somewhere else).
Is it possible to create a Clojure spec/test.check generator that generates ::image
s?