1 module unit_threaded.ut.randomized.gen;
2 
3 
4 import unit_threaded.randomized.gen;
5 
6 static if (__VERSION__ >= 2096)
7     import std.math: close = isClose;
8 else
9     import std.math: close = approxEqual;
10 
11 
12 /*
13 Regarding `version(OldWindows)` blocks below: It is unclear what conditions
14 made Windows behave differently. Nowadays, with dmd v2.094 on Windows 10 in
15 November 2020, there is no difference between Windows and Posix.
16 */
17 
18 @safe pure unittest {
19     import unit_threaded.asserts: assertEqual;
20     import std.random: Random;
21 
22     auto rnd = Random(1337);
23     Gen!int gen;
24     assertEqual(gen.gen(rnd), 0);
25     assertEqual(gen.gen(rnd), 1);
26     assertEqual(gen.gen(rnd), int.min);
27     assertEqual(gen.gen(rnd), int.max);
28     assertEqual(gen.gen(rnd), 1125387415); //1st non front-loaded value
29 }
30 
31 @safe unittest {
32     // not pure because of floating point flags
33     import unit_threaded.asserts: assertEqual;
34     import std.conv: to;
35     import std.random: Random;
36 
37     auto rnd = Random(1337);
38     Gen!float gen;
39     assertEqual(gen.gen(rnd), 0);
40     assertEqual(gen.gen(rnd), float.epsilon);
41     assertEqual(gen.gen(rnd), float.min_normal);
42     assert(close(gen.gen(rnd), 6.022E23), gen.value.to!string);
43     assert(close(gen.gen(rnd), 1.57791E23), gen.value.to!string);
44 }
45 
46 
47 @safe unittest {
48     // not pure because of floating point flags
49     import unit_threaded.asserts: assertEqual;
50     import std.conv: to;
51     import std.random: Random;
52 
53     auto rnd = Random(1337);
54     Gen!(float, 0, 5) gen;
55     assertEqual(gen.gen(rnd), 0);
56     assertEqual(gen.gen(rnd), float.epsilon);
57     assertEqual(gen.gen(rnd), float.min_normal);
58     assertEqual(gen.gen(rnd), 5);
59     assert(close(gen.gen(rnd), 1.31012), gen.value.to!string);
60 }
61 
62 @safe unittest {
63     import std.meta : AliasSeq, aliasSeqOf;
64     import std.range : iota;
65     import std.array : empty;
66     import std.random: Random;
67     import unit_threaded.asserts;
68 
69     foreach (index, T; AliasSeq!(string, wstring, dstring)) {
70         auto r = Random(1337);
71         Gen!T a;
72         T expected = "";
73         assertEqual(a.gen(r), expected);
74         expected = "a";
75         assertEqual(a.gen(r), expected);
76         expected = "é";
77         assertEqual(a.gen(r), expected);
78         assert(a.gen(r).length > 1);
79     }
80 }
81 
82 // FIXME: fails in this mode
83 version(unitThreadedLight) {}
84 else {
85     @safe unittest {
86         import unit_threaded.asserts;
87         import std.random: Random;
88 
89         auto rnd = Random(1337);
90         GenASCIIString!() gen;
91         assertEqual(gen.gen(rnd), "");
92         assertEqual(gen.gen(rnd), "a");
93         version(OldWindows) // See comment above.
94             assertEqual(gen.gen(rnd), "yt4>%PnZwJ*Nv3L5:9I#N_ZK");
95         else
96             assertEqual(gen.gen(rnd), "i<pDqp7-LV;W`d)w/}VXi}TR=8CO|m");
97     }
98 }
99 
100 @("Gen!int[] generates random arrays of int")
101 @safe unittest {
102     import unit_threaded.asserts: assertEqual;
103     import std.random: Random;
104 
105     auto rnd = Random(1337);
106     auto gen = Gen!(int[], 1, 10)();
107 
108     // first the front-loaded values
109     assertEqual(gen.gen(rnd), []);
110     version(OldWindows) // See comment above.
111         assertEqual(gen.gen(rnd), [0, 1]);
112     else
113         assertEqual(gen.gen(rnd), [0, 1, -2147483648, 2147483647, 681542492, 913057000, 1194544295, -1962453543, 1972751015]);
114 }
115 
116 @("Gen!ubyte[] generates random arrays of ubyte")
117 @safe unittest {
118     import unit_threaded.asserts: assertEqual;
119     import std.random: Random;
120 
121     auto rnd = Random(1337);
122     auto gen = Gen!(ubyte[], 1, 10)();
123     assertEqual(gen.gen(rnd), []);
124 }
125 
126 
127 @("Gen!double[] generates random arrays of double")
128 @safe unittest {
129     import unit_threaded.asserts: assertEqual;
130     import std.random: Random;
131 
132     auto rnd = Random(1337);
133     auto gen = Gen!(double[], 1, 10)();
134 
135     // first the front-loaded values
136     assertEqual(gen.gen(rnd), []);
137     // then the pseudo-random ones
138     version(OldWindows) // See comment above.
139         assertEqual(gen.gen(rnd).length, 2);
140     else
141         assertEqual(gen.gen(rnd).length, 9);
142 }
143 
144 @("Gen!string[] generates random arrays of string")
145 @safe unittest {
146     import unit_threaded.asserts: assertEqual;
147     import std.random: Random;
148 
149     auto rnd = Random(1337);
150     auto gen = Gen!(string[])();
151 
152     assertEqual(gen.gen(rnd), []);
153     auto strings = gen.gen(rnd);
154     assert(strings.length > 1);
155     assertEqual(strings[1], "a");
156 }
157 
158 @("Gen!string[][] generates random arrays of string")
159 @safe unittest {
160     import unit_threaded.asserts: assertEqual;
161     import std.random: Random;
162 
163     auto rnd = Random(1337);
164     auto gen = Gen!(string[][])();
165 
166     assertEqual(gen.gen(rnd), []);
167     // takes too long
168     // auto strings = gen.gen(rnd);
169     // assert(strings.length > 1);
170 }
171 
172 @("Gen!bool generates random booleans")
173 @safe unittest {
174     import unit_threaded.asserts: assertEqual;
175     import std.random: Random;
176 
177     auto rnd = Random(1337);
178     auto gen = Gen!bool();
179 
180     assertEqual(gen.gen(rnd), true);
181     assertEqual(gen.gen(rnd), true);
182     assertEqual(gen.gen(rnd), false);
183     assertEqual(gen.gen(rnd), false);
184 }
185 
186 @("Gen char, wchar, dchar")
187 @safe unittest {
188     import unit_threaded.asserts: assertEqual;
189     import std.random: Random;
190 
191     {
192         auto rnd = Random(1337);
193         Gen!char gen;
194         assertEqual(cast(int)gen.gen(rnd), 151);
195     }
196     {
197         auto rnd = Random(1337);
198         Gen!wchar gen;
199         assertEqual(cast(int)gen.gen(rnd), 3223);
200     }
201     {
202         auto rnd = Random(1337);
203         Gen!dchar gen;
204         assertEqual(cast(int)gen.gen(rnd), 3223);
205     }
206 }
207 
208 @("struct")
209 @safe unittest {
210     import unit_threaded.asserts: assertEqual;
211     import std.random: Random;
212 
213     struct Foo {
214         int i;
215         string s;
216     }
217 
218     auto rnd = Random(1337);
219     Gen!Foo gen;
220     assertEqual(gen.gen(rnd), Foo(0, ""));
221     assertEqual(gen.gen(rnd), Foo(1, "a"));
222     assertEqual(gen.gen(rnd), Foo(int.min, "é"));
223 }
224 
225 @("class")
226 @safe unittest {
227     import unit_threaded.asserts: assertEqual;
228     import std.random: Random;
229 
230     static class Foo {
231         this() {}
232         this(int i, string s) { this.i = i; this.s = s; }
233         override string toString() @safe const pure nothrow {
234             import std.conv;
235             return text(`Foo(`, i, `, "`, s, `")`);
236         }
237         override bool opEquals(Object _rhs) @safe const pure nothrow {
238             auto rhs = cast(Foo)_rhs;
239             return i == rhs.i && s == rhs.s;
240         }
241         int i;
242         string s;
243     }
244 
245     auto rnd = Random(1337);
246     Gen!Foo gen;
247     assertEqual(gen.gen(rnd), new Foo(0, ""));
248     assertEqual(gen.gen(rnd), new Foo(1, "a"));
249     assertEqual(gen.gen(rnd), new Foo(int.min, "é"));
250 }