1 module unit_threaded.randomized.random; 2 3 4 /** This type will generate a $(D Gen!T) for all passed $(D T...). 5 Every call to $(D genValues) will call $(D gen) of all $(D Gen) structs 6 present in $(D values). The member $(D values) can be passed to every 7 function accepting $(D T...). 8 */ 9 struct RndValueGen(T...) 10 { 11 import std.meta : staticMap; 12 import std.random: Random; 13 14 /* $(D Values) is a collection of $(D Gen) types created through 15 $(D ParameterToGen) of passed $(T ...). 16 */ 17 static if(is(typeof(T[0]) == string[])) { 18 alias generators = T[1 .. $]; 19 string[] parameterNames = T[0]; 20 } else { 21 alias generators = T; 22 string[T.length] parameterNames; 23 } 24 25 alias Values = staticMap!(ParameterToGen, generators); 26 27 /// Ditto 28 Values values; 29 30 /* The constructor accepting the required random number generator. 31 Params: 32 rnd = The required random number generator. 33 */ 34 this(Random* rnd) 35 { 36 this.rnd = rnd; 37 } 38 39 this(ref Random rnd) { 40 this.rnd = &rnd; 41 } 42 43 /* The random number generator used to generate new value for all 44 $(D values). 45 */ 46 Random* rnd; 47 48 /** A call to this member function will call $(D gen) on all items in 49 $(D values) passing $(D the provided) random number generator 50 */ 51 void genValues() scope 52 in(rnd !is null) 53 do 54 { 55 foreach (ref it; this.values) 56 { 57 it.gen(*this.rnd); 58 } 59 } 60 61 void toString(scope void delegate(const(char)[]) sink) 62 { 63 import std.format : formattedWrite; 64 65 foreach (idx, ref it; values) 66 { 67 formattedWrite(sink, "'%s' = %s ", parameterNames[idx], it); 68 } 69 } 70 } 71 72 @("176") 73 @safe unittest { 74 import std.random: Random; 75 const seed = 0x1337; 76 scope random = Random(seed); 77 scope gen = RndValueGen!(int[])(&random); 78 gen.genValues; 79 } 80 81 82 /** A template that turns a $(D T) into a $(D Gen!T) unless $(D T) is 83 already a $(D Gen) or no $(D Gen) for given $(D T) is available. 84 */ 85 template ParameterToGen(T) 86 { 87 import unit_threaded.randomized.gen: isGen, Gen; 88 static if (isGen!T) 89 alias ParameterToGen = T; 90 else static if (is(T : GenASCIIString!(S), S...)) 91 alias ParameterToGen = T; 92 else { 93 static assert(__traits(compiles, Gen!T), 94 "ParameterToGen does not handle " ~ T.stringof); 95 alias ParameterToGen = Gen!T; 96 } 97 }