Skip to content

Instantly share code, notes, and snippets.

@jcf
Created April 1, 2015 18:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jcf/7a91c9473b57b1834704 to your computer and use it in GitHub Desktop.
Save jcf/7a91c9473b57b1834704 to your computer and use it in GitHub Desktop.
Generate deterministic type-4 UUIDs with Clojure's test.check
(require '[clojure.string :as str])
(require '[clojure.test.check.generators :as gen])
(def gen-hex-char
(gen/elements (concat (map char (range (int \a) (int \f)))
(range 0 9))))
(defn gen-hex-string [len]
(gen/fmap str/join (gen/vector gen-hex-char len len)))
(def gen-uuid
(->> (gen/tuple (gen-hex-string 8)
(gen/return "-")
(gen-hex-string 4)
(gen/return "-4")
(gen-hex-string 3)
(gen/return "-a")
(gen-hex-string 3)
(gen/return "-")
(gen-hex-string 12))
(gen/fmap str/join)
(gen/fmap (fn [xs] (java.util.UUID/fromString (apply str xs))))))
@eraserhd
Copy link

I found it easier to do this:

(gen/fmap (fn [[a b]] (UUID. a b)) (gen/resize Long/MAX_VALUE (gen/tuple gen/int gen/int)))

@jcf
Copy link
Author

jcf commented Jun 29, 2015

I like the use of least and most significant bytes; that's definitely an improvement over messing around with strings. I need to make a few tweaks to the "easier" version to avoid producing irregular UUIDs:

(def eraserhd-uuid
  (gen/fmap (fn [[a b]] (UUID. a b))
            (gen/resize Long/MAX_VALUE (gen/tuple gen/int gen/int))))

(map #(.version ^java.util.UUID %) (gen/sample eraserhd-uuid))
(9 11 14 13 11 14 6 8 14 12)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment