Skip to content

Instantly share code, notes, and snippets.

@jimrthy
Last active February 28, 2018 05:32
Show Gist options
  • Save jimrthy/21851c52a8cd6b04a31ed08b1d0a7f04 to your computer and use it in GitHub Desktop.
Save jimrthy/21851c52a8cd6b04a31ed08b1d0a7f04 to your computer and use it in GitHub Desktop.
clojure.spec gen oddities
(ns indirect-spec-gen
(:require [clojure.spec.alpha :as s]
[clojure.spec.gen.alpha :as gen]
[clojure.test :refer (deftest is)]))
(def extension-length 16)
;; Need a byte array with 16 members
(s/def ::extension (s/and bytes?
#(= (count %) extension-length)))
;; Need to track one for the client, another for the server
(s/def ::srvr-xtn ::extension)
(s/def ::clnt-xtn ::extension)
;; Haven't seen this fail yet
(deftest transitive
(let [test-runs 40
success-count
(reduce (fn [n m]
(try
(let [samples (gen/sample (s/gen (s/keys :req [::srvr-xtn
::clnt-xtn])
;; This second parameter to s/gen lets me override the generators.
;; I think this is the key to the sometimes nature of my problem.
{::srvr-xtn #(gen/fmap byte-array (gen/vector (gen/choose -128 127) extension-length))
::clnt-xtn #(gen/fmap byte-array (gen/vector (gen/choose -128 127) extension-length))}))]
(is samples)
(inc n))
(catch Exception ex
(println ex "on sample" m)
n)))
0
(range test-runs))]
(println success-count "successes out of" test-runs)))
(defn manual-check
[]
(gen/sample (s/gen (s/keys :req [::srvr-xtn
::clnt-xtn])
{::srvr-xtn #(gen/fmap byte-array (gen/vector (gen/choose -128 127) extension-length))
::clnt-xtn #(gen/fmap byte-array (gen/vector (gen/choose -128 127) extension-length))})))
;; Calling this in this manner or from the REPL fails pretty much every time
(manual-check)
;; Repeatedly calling manual-check from inside a test passes
(deftest transitive-indirect
(let [test-runs 40
success-count
(reduce (fn [n m]
(try
(let [samples (manual-check)]
(is samples)
(inc n))
(catch Exception ex
(println ex "on sample" m)
n)))
0
(range test-runs))]
(println success-count "successes out of" test-runs)))
;; Generating the "base" spec seems to always work
(deftest direct
(let [samples (gen/sample (s/gen ::extension
{::extension #(gen/fmap byte-array (gen/vector (gen/choose -128 127) extension-length))}))]
(is samples)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment