Class: RushCheck::Gen
- Inherits:
-
Object
- Object
- RushCheck::Gen
- Defined in:
- lib/rushcheck/gen.rb
Overview
Gen provides functions for generating test instances.
Constant Summary collapse
- @@max_create =
10000
Class Method Summary collapse
-
.choose(lo = nil, hi = nil) ⇒ Object
choose is one of primitive generators to create a random Gen object.
-
.create(*cs, &f) ⇒ Object
create is one of primitive generators to create a random Gen object.
-
.create_by_gen(xs, &f) ⇒ Object
create_gen is one of primitive generators to create a random Gen object.
-
.elements(xs) ⇒ Object
elements is one of primitive generators to create a random Gen object.
-
.frequency(xs) ⇒ Object
frequency is one of primitive generators to create a random Gen object.
-
.lift_array(xs) ⇒ Object
lift_array is one of primitive generators to create a randam Gen object.
-
.oneof(gens) ⇒ Object
oneof is /one of/ primitive generators to create a random Gen object.
-
.promote ⇒ Object
promote is the function to create a Gen object which generates a procedure (Proc).
-
.rand ⇒ Object
rand returns a Gen object which generates a random number generator.
-
.sized ⇒ Object
sized is a combinator which the programmer can use to access the size bound.
-
.unit(x) ⇒ Object
unit is a monadic function which equals the return function in the Haskell’s monad.
-
.vector(c, len) ⇒ Object
vector is one of primitive generators to create a Gen object.
Instance Method Summary collapse
-
#bind ⇒ Object
bind is a monadic function such as Haskel’s (>>=).
-
#fmap ⇒ Object
fmap is a categorical function as same in Haskell.
-
#forall ⇒ Object
forall is a function to create a Gen object.
-
#generate(n, rnd) ⇒ Object
generate returns the random instance.
-
#initialize(&f) ⇒ Gen
constructor
to initialize Gen object, it requires a block which takes two variables.
-
#resize(n) ⇒ Object
resize returns another Gen object which resized by the given paramater.
-
#value(n, g) ⇒ Object
value is a method to get the value of the internal procedure.
-
#variant(v) ⇒ Object
variant constructs a generator which transforms the random number seed.
Constructor Details
#initialize(&f) ⇒ Gen
to initialize Gen object, it requires a block which takes two variables. The first argument of block is assumed as an integer, and the second one is assumed as a random generator of RandomGen.
167 168 169 |
# File 'lib/rushcheck/gen.rb', line 167 def initialize(&f) @proc = f end |
Class Method Details
.choose(lo = nil, hi = nil) ⇒ Object
choose is one of primitive generators to create a random Gen object. choose returns a Gen object which generates a random value in the bound. It may useful to implement arbitrary method into your class.
19 20 21 22 23 |
# File 'lib/rushcheck/gen.rb', line 19 def self.choose(lo=nil, hi=nil) rand.fmap do |x| lo.class.random(x, lo, hi).first end end |
.create(*cs, &f) ⇒ Object
create is one of primitive generators to create a random Gen object. create takes at least a class, and any block to generate object. Then create returns a Gen object. It may useful to implement arbitrary method into your class.
59 60 61 |
# File 'lib/rushcheck/gen.rb', line 59 def self.create(*cs, &f) self.create_by_gen(cs.map {|c| c.arbitrary}, &f) end |
.create_by_gen(xs, &f) ⇒ Object
create_gen is one of primitive generators to create a random Gen object. create_gen takes an array of Gen objects, and any block to generate object. Then create_gen returns a Gen object. It may useful to implement arbitrary method into your class.
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 |
# File 'lib/rushcheck/gen.rb', line 29 def self.create_by_gen(xs, &f) self.new do |n, r| r2 = r try = 0 begin if try > @@max_create raise(RuntimeError, "Failed to guards too many in the assertion.") end args = xs.map do |gen| r1, r2 = r2.split gen.value(n, r1) end f.call(*args) rescue Exception => ex case ex when RushCheck::GuardException try += 1 retry else raise(ex, ex.to_s) end end end end |
.elements(xs) ⇒ Object
elements is one of primitive generators to create a random Gen object. elements requires an array and returns a Gen object which generates an object in the array randomly. It may useful to implement arbitrary method into your class.
67 68 69 70 71 |
# File 'lib/rushcheck/gen.rb', line 67 def self.elements(xs) raise(RuntimeError, "given argument is empty") if xs.empty? choose(0, xs.length - 1).fmap {|i| xs[i] } end |
.frequency(xs) ⇒ Object
frequency is one of primitive generators to create a random Gen object. frequency requires an array of pairs and returns a Gen object. The first component of pair should be a positive Integer and the second one should be a Gen object. The integer acts as a weight for choosing random Gen object in the array. For example, frequency([[1, Gen.rand], [2, Integer.arbitrary]]) returns the random generator Gen.rand in 33%, while another random generator of Integer (Integer.arbitrary) in 67%.
81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/rushcheck/gen.rb', line 81 def self.frequency(xs) tot = xs.inject(0) {|r, pair| r + pair.first} raise(RuntimeError, "Illegal frequency:#{xs.inspect}") if tot == 0 choose(0, tot - 1).bind do |n| m = n xs.each do |pair| if m <= pair[0] then break pair[1] else m -= pair[0] end end end end |
.lift_array(xs) ⇒ Object
lift_array is one of primitive generators to create a randam Gen object. lift_array takes an array and a block which has a variable. The block should return a Gen object. lift_array returns a Gen object which generates an array of the result of given block for applying each member of given array.
100 101 102 103 104 105 106 107 108 |
# File 'lib/rushcheck/gen.rb', line 100 def self.lift_array(xs) self.new do |n, r| r2 = r xs.map do |c| r1, r2 = r2.split yield.value(n, r1) end end end |
.oneof(gens) ⇒ Object
oneof is /one of/ primitive generators to create a random Gen object. oneof requires an array of Gen objects, and returns a Gen object which choose a Gen object in the array randomly. It may useful to implement arbitrary method into your class.
114 115 116 |
# File 'lib/rushcheck/gen.rb', line 114 def self.oneof(gens) elements(gens).bind {|x| x} end |
.promote ⇒ Object
promote is the function to create a Gen object which generates a procedure (Proc). promote requires a block which takes one variable and the block should be return a Gen object. promote returns a Gen object which generate a new procedure with the given block. It may useful to implement coarbitrary method into your class.
124 125 126 |
# File 'lib/rushcheck/gen.rb', line 124 def self.promote new {|n, r| Proc.new {|a| yield(a).value(n, r) } } end |
.rand ⇒ Object
rand returns a Gen object which generates a random number generator.
130 131 132 |
# File 'lib/rushcheck/gen.rb', line 130 def self.rand new {|n, r| r} end |
.sized ⇒ Object
sized is a combinator which the programmer can use to access the size bound. It requires a block which takes a variable as an integer for size. The block should be a function which changes the size of random instances.
138 139 140 |
# File 'lib/rushcheck/gen.rb', line 138 def self.sized new {|n, r| yield(n).value(n, r) } end |
.unit(x) ⇒ Object
unit is a monadic function which equals the return function in the Haskell’s monad. It requires one variable and returns a Gen object which generates the given object.
145 146 147 |
# File 'lib/rushcheck/gen.rb', line 145 def self.unit(x) new {|n, r| x} end |
.vector(c, len) ⇒ Object
vector is one of primitive generators to create a Gen object. vector takes two variables, while the first one should be class, and the second one should be length. vector returns a Gen object which generates an array whose components belongs the given class and given length.
154 155 156 157 158 159 160 161 162 |
# File 'lib/rushcheck/gen.rb', line 154 def self.vector(c, len) new do |n, r| r2 = r (1..len).map do r1, r2 = r2.split c.arbitrary.value(n, r1) end end end |
Instance Method Details
#bind ⇒ Object
bind is a monadic function such as Haskel’s (>>=). bind takes a block which has a variable where is the return value of the Gen object. The block should return a Gen object.
174 175 176 177 178 179 |
# File 'lib/rushcheck/gen.rb', line 174 def bind self.class.new do |n, r| r1, r2 = r.split yield(value(n, r1)).value(n, r2) end end |
#fmap ⇒ Object
fmap is a categorical function as same in Haskell. fmap requires a block which takes one variable.
191 192 193 |
# File 'lib/rushcheck/gen.rb', line 191 def fmap bind {|x| self.class.unit(yield(x)) } end |
#forall ⇒ Object
forall is a function to create a Gen object. forall requires a block which takes any variables and returns a Property object. Then forall returns a generator of the property.
199 200 201 202 203 204 205 206 |
# File 'lib/rushcheck/gen.rb', line 199 def forall bind do |*a| yield(*a).property.gen.bind do |res| res.arguments.push(a.to_s) self.class.unit(res) end end end |
#generate(n, rnd) ⇒ Object
generate returns the random instance. generates takes two variables, where the first one should be an integer and the second should be the random number generator such as StdGen.
211 212 213 214 |
# File 'lib/rushcheck/gen.rb', line 211 def generate(n, rnd) s, r = Integer.random(rnd, 0, n) value(s, r) end |
#resize(n) ⇒ Object
resize returns another Gen object which resized by the given paramater. resize takes one variable in Integer.
218 219 220 |
# File 'lib/rushcheck/gen.rb', line 218 def resize(n) self.class.new {|x, r| value(n, r) } end |
#value(n, g) ⇒ Object
value is a method to get the value of the internal procedure. value takes two variables where the first argument is assumed as an integer and the second one is assumed as a random generator of RandomGen.
185 186 187 |
# File 'lib/rushcheck/gen.rb', line 185 def value(n, g) @proc.call(n, g) end |
#variant(v) ⇒ Object
variant constructs a generator which transforms the random number seed. variant takes one variable which should be an Integer. variant is needed to generate random functions.
225 226 227 228 229 230 231 |
# File 'lib/rushcheck/gen.rb', line 225 def variant(v) self.class.new do |n, r| gen = r v.times { gen, dummy = gen.split } value(n, gen) end end |