/
gen.cljc
140 lines (117 loc) · 4.68 KB
/
gen.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
; Copyright (c) Alan Thompson. All rights reserved.
; The use and distribution terms for this software are covered by the Eclipse Public License 1.0
; (http://opensource.org/licenses/eclipse-1.0.php) which can be found in the file epl-v10.html at
; the root of this distribution. By using this software in any fashion, you are agreeing to be
; bound by the terms of this license. You must not remove this notice, or any other, from this
; software.
(ns tupelo.gen
"Tupelo - Clojure With A Spoonful of Honey"
(:refer-clojure :exclude [rand-nth constantly])
#?(:clj
(:require
[clojure.string :as str]
[clojure.test.check :as tc]
[clojure.test.check.clojure-test :as tst]
[clojure.test.check.generators :as tcgen]
[clojure.test.check.properties :as prop]
[tupelo.chars :as char]
)))
; #todo: for test.check v2:
; fmap -> map
; #todo need tests & doc
; #todo
; maybe
; [tupelo.test.check :as ttc]
; [tupelo.test.check.properties :as tprop]
; [tupelo.test.check.generators :as tgen]
; (gen/sample gen/int 20) -> (tgen/sample {:quantity 20} gen/int )
; ^^^ ctx is always optional 1st arg
; gen/sample-seq -> tgen/->lazy-seq
; tc/quick-check -> (ttc/quick-check {:num-tests 100} ...)
#?(:clj (do
(defn txt-join
"Wraps the supplied generator using clojure.string/join."
[xgen]
(tcgen/fmap str/join xgen))
(defn txt-join-space
"Wraps the supplied generator using #(clojure.string/join \\space %)."
[xgen]
(tcgen/fmap #(str/join \space %) xgen))
(defn maybe-vec
"Given a string generator, randomly return either the original string or a vector of its chars."
[gen-arg]
(tcgen/one-of [ (tcgen/fmap vec gen-arg)
(tcgen/fmap identity gen-arg) ] ))
(defn rand-nth
"Returns a generator yielding a random element from the supplied collection.
Equivalent to `gen/elements` "
[coll]
(tcgen/elements coll))
(defn constantly
"Returns a generator which always yields the supplied argument w/o.
Equivalent to `gen/return` "
[arg]
(tcgen/return arg))
(defn vector+
"Return a non-empty vector (1 or more items) selected using the supplied generator."
[gen-arg]
(tcgen/not-empty (tcgen/vector gen-arg)))
; returns exactly 1 char
(def char-whitespace-horiz (rand-nth char/whitespace-horiz))
(def char-whitespace-eol (rand-nth char/whitespace-eol))
(def char-whitespace (rand-nth char/whitespace))
(def char-alpha (rand-nth char/alpha))
(def char-alphanumeric (rand-nth char/alphanumeric))
; #todo char-visible, char-visible-no-dquote, char-visible-no-squote,
; returns a string (len = 0 or more)
(def whitespace-horiz (txt-join (tcgen/vector char-whitespace-horiz)))
(def whitespace-eol (txt-join (tcgen/vector char-whitespace-eol)))
(def whitespace (txt-join (tcgen/vector char-whitespace)))
; returns a string (len = 1 or more)
(def whitespace-horiz+ (txt-join (vector+ char-whitespace-horiz)))
(def whitespace-eol+ (txt-join (vector+ char-whitespace-eol)))
(def whitespace+ (txt-join (vector+ char-whitespace)))
; returns a string (len = 0 or more)
(def word-alpha (txt-join (tcgen/vector char-alpha)))
(def word-alphanumeric (txt-join (tcgen/vector char-alphanumeric)))
(def words-alpha (txt-join-space (tcgen/vector word-alpha)))
(def words-alphanumeric (txt-join-space (tcgen/vector word-alphanumeric)))
; returns a string (len = 1 or more)
(def word-alpha+ (txt-join (vector+ char-alpha)))
(def word-alphanumeric+ (txt-join (vector+ char-alphanumeric)))
(def words-alpha+ (txt-join-space (vector+ word-alpha+)))
(def words-alphanumeric+ (txt-join-space (vector+ word-alphanumeric+)))
(def identifier (tcgen/let [first-char char-alpha
other-chars word-alphanumeric]
(str first-char other-chars)))
(def char-eol
"A single EOL char"
(rand-nth char/whitespace-eol))
(def chars-eol+
"One or more EOL chars."
(vector+ char-eol))
))
(comment ; #todo sample usage:
(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require
[tupelo.gen :as tg]
[clojure.test.check.properties :as prop]
))
(dospec 9
(do
(newline)
(spy :sample)
(prop/for-all [w tg/word-alpha+]
(spyx w))))
(dospec 9
(do
(newline)
(spy :emails)
(prop/for-all [w1 tg/word-alpha+
w2 tg/word-alpha+]
(let [email-addr (str w1 \@ w2 ".com")]
(spyx email-addr)
)
)))
)