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