Skip to content

Instantly share code, notes, and snippets.

@tdantas
Forked from nikolavojicic/bulkspace.clj
Created November 29, 2023 09:59
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 tdantas/3977a5c4ac19a1f38855171e948a5dde to your computer and use it in GitHub Desktop.
Save tdantas/3977a5c4ac19a1f38855171e948a5dde to your computer and use it in GitHub Desktop.
Various Clojure specs + generators
;; String containing bulk space(s)
(s/def ::bulk-space-string
(s/with-gen
(s/and string? #(re-find #"\t|\n|\r| +" %))
#(gen/fmap
str/join
(gen/vector
(gen/one-of
[(gen/string)
(gen/return "\t")
(gen/return "\n")
(gen/return "\r")
(gen/return (str/join (repeat (rand-int 20) " ")))])))))
;; Email
(defn email?
[s]
(re-matches #"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$" s))
(defn gen-email
[]
(gen/fmap
(fn [[name host tld]]
(str name "@" host "." tld))
(gen/tuple
(gen/not-empty (gen/string-alphanumeric))
(gen/not-empty (gen/string-alphanumeric))
(gen/fmap
#(apply str %)
(gen/vector (gen/char-alpha) 2 63)))))
(s/def ::email
(s/with-gen
(s/and string? util/email?)
gen-email))
;; java.time.LocalDateTime
(defn gen-local-date-time
([]
(gen-local-date-time
(Date. Integer/MAX_VALUE)
(Date.)))
([start end]
(gen/fmap
#(-> ^Date % .toInstant
(.atZone (ZoneId/systemDefault))
.toLocalDateTime)
(s/gen (s/inst-in start end)))))
(s/def ::local-date-time
(s/spec
#(instance? LocalDateTime %)
:gen gen-local-date-time))
;; java.time.LocalDate
(defn gen-local-date
([]
(gen-local-date
(Date. Integer/MAX_VALUE)
(Date.)))
([start end]
(gen/fmap
#(-> ^Date % .toInstant
(.atZone (ZoneId/systemDefault))
.toLocalDate)
(s/gen (s/inst-in start end)))))
(s/def ::local-date
(s/spec
#(instance? LocalDate %)
:gen gen-local-date))
;; java.time.LocalTime
(defn gen-local-time
[]
(gen/fmap
(fn [[hh mm ss]]
(LocalTime/of hh mm ss))
(gen/tuple (gen/choose 0 23)
(gen/choose 0 59)
(gen/choose 0 59))))
(s/def ::local-time
(s/spec
#(instance? LocalTime %)
:gen gen-local-time))
(defn numeric?
[s]
(boolean
(try (Double/parseDouble s)
(catch Throwable __))))
(defn gen-numeric-string
([]
(let [min (gen/generate (gen/choose 0 10))
max (gen/generate (gen/choose min 100))]
(gen-numeric-string min max)))
([size]
(gen-numeric-string size size))
([min max]
(gen/fmap
str/join
(gen/vector (gen/choose 0 9) min max))))
(s/def ::numeric-string
(s/with-gen
(s/and string? seq numeric?)
gen-numeric-string))
(s/def ::percent-int
(s/and nat-int?
#(>= % 0)
#(<= % 10000)))
;; BigDecimal percent, > 0M <= 100M, scale 2
(defn gen-percent
[]
(gen/fmap
#(-> (BigDecimal/valueOf ^double %)
(.setScale 2 BigDecimal/ROUND_HALF_EVEN))
(s/gen (s/double-in :min 0.01 :max 100.00))))
(s/def ::percent
(s/with-gen
(s/and decimal?
#(= (.scale ^BigDecimal %) 2)
#(pos? (compare % 0.00M))
#(neg? (compare % 100.01M)))
gen-percent))
(s/def ::pos-int
(s/and nat-int? pos?
#(<= % Integer/MAX_VALUE)))
(s/def ::pos-long
(s/and nat-int? pos?))
(defn trimmed?
[s]
(= (str/trim s) s))
(s/def ::trimmed-not-empty-string
(s/and string? seq trimmed?))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment