rushcheck 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. data/COPYING +515 -0
  2. data/INSTALL +14 -0
  3. data/LICENSE +5 -0
  4. data/README +49 -0
  5. data/Rakefile +39 -0
  6. data/copying.txt +23 -0
  7. data/data/rushcheck/doc/policy.txt +520 -0
  8. data/data/rushcheck/doc/rushcheck.txt +612 -0
  9. data/data/rushcheck/examples/printf.rb +22 -0
  10. data/data/rushcheck/examples/proc.rb +33 -0
  11. data/data/rushcheck/examples/roguetile.rb +153 -0
  12. data/data/rushcheck/examples/sample.rb +52 -0
  13. data/data/rushcheck/rdoc/classes/Arbitrary.html +148 -0
  14. data/data/rushcheck/rdoc/classes/Arbitrary.src/M000075.html +18 -0
  15. data/data/rushcheck/rdoc/classes/Assertion.html +183 -0
  16. data/data/rushcheck/rdoc/classes/Assertion.src/M000015.html +20 -0
  17. data/data/rushcheck/rdoc/classes/Assertion.src/M000016.html +45 -0
  18. data/data/rushcheck/rdoc/classes/Coarbitrary.html +135 -0
  19. data/data/rushcheck/rdoc/classes/Coarbitrary.src/M000095.html +18 -0
  20. data/data/rushcheck/rdoc/classes/FalseClass.html +177 -0
  21. data/data/rushcheck/rdoc/classes/FalseClass.src/M000018.html +18 -0
  22. data/data/rushcheck/rdoc/classes/FalseClass.src/M000019.html +18 -0
  23. data/data/rushcheck/rdoc/classes/FalseClass.src/M000020.html +18 -0
  24. data/data/rushcheck/rdoc/classes/Float.html +191 -0
  25. data/data/rushcheck/rdoc/classes/Float.src/M000047.html +21 -0
  26. data/data/rushcheck/rdoc/classes/Float.src/M000048.html +18 -0
  27. data/data/rushcheck/rdoc/classes/Float.src/M000049.html +22 -0
  28. data/data/rushcheck/rdoc/classes/Float.src/M000050.html +20 -0
  29. data/data/rushcheck/rdoc/classes/Gen.html +515 -0
  30. data/data/rushcheck/rdoc/classes/Gen.src/M000026.html +18 -0
  31. data/data/rushcheck/rdoc/classes/Gen.src/M000027.html +20 -0
  32. data/data/rushcheck/rdoc/classes/Gen.src/M000028.html +28 -0
  33. data/data/rushcheck/rdoc/classes/Gen.src/M000029.html +24 -0
  34. data/data/rushcheck/rdoc/classes/Gen.src/M000030.html +18 -0
  35. data/data/rushcheck/rdoc/classes/Gen.src/M000031.html +18 -0
  36. data/data/rushcheck/rdoc/classes/Gen.src/M000032.html +18 -0
  37. data/data/rushcheck/rdoc/classes/Gen.src/M000033.html +18 -0
  38. data/data/rushcheck/rdoc/classes/Gen.src/M000034.html +18 -0
  39. data/data/rushcheck/rdoc/classes/Gen.src/M000035.html +24 -0
  40. data/data/rushcheck/rdoc/classes/Gen.src/M000036.html +18 -0
  41. data/data/rushcheck/rdoc/classes/Gen.src/M000037.html +21 -0
  42. data/data/rushcheck/rdoc/classes/Gen.src/M000038.html +18 -0
  43. data/data/rushcheck/rdoc/classes/Gen.src/M000039.html +18 -0
  44. data/data/rushcheck/rdoc/classes/Gen.src/M000040.html +23 -0
  45. data/data/rushcheck/rdoc/classes/Gen.src/M000041.html +19 -0
  46. data/data/rushcheck/rdoc/classes/Gen.src/M000042.html +18 -0
  47. data/data/rushcheck/rdoc/classes/Gen.src/M000043.html +24 -0
  48. data/data/rushcheck/rdoc/classes/Guard.html +159 -0
  49. data/data/rushcheck/rdoc/classes/Guard.src/M000024.html +27 -0
  50. data/data/rushcheck/rdoc/classes/Guard.src/M000025.html +18 -0
  51. data/data/rushcheck/rdoc/classes/HsRandom.html +201 -0
  52. data/data/rushcheck/rdoc/classes/HsRandom.src/M000081.html +22 -0
  53. data/data/rushcheck/rdoc/classes/HsRandom.src/M000082.html +32 -0
  54. data/data/rushcheck/rdoc/classes/HsRandom.src/M000083.html +18 -0
  55. data/data/rushcheck/rdoc/classes/Integer.html +212 -0
  56. data/data/rushcheck/rdoc/classes/Integer.src/M000006.html +18 -0
  57. data/data/rushcheck/rdoc/classes/Integer.src/M000007.html +18 -0
  58. data/data/rushcheck/rdoc/classes/Integer.src/M000008.html +21 -0
  59. data/data/rushcheck/rdoc/classes/Integer.src/M000009.html +19 -0
  60. data/data/rushcheck/rdoc/classes/NilClass.html +177 -0
  61. data/data/rushcheck/rdoc/classes/NilClass.src/M000059.html +18 -0
  62. data/data/rushcheck/rdoc/classes/NilClass.src/M000060.html +18 -0
  63. data/data/rushcheck/rdoc/classes/NilClass.src/M000061.html +18 -0
  64. data/data/rushcheck/rdoc/classes/Property.html +174 -0
  65. data/data/rushcheck/rdoc/classes/Property.src/M000070.html +26 -0
  66. data/data/rushcheck/rdoc/classes/Property.src/M000071.html +18 -0
  67. data/data/rushcheck/rdoc/classes/RandomArray.html +184 -0
  68. data/data/rushcheck/rdoc/classes/RandomArray.src/M000021.html +18 -0
  69. data/data/rushcheck/rdoc/classes/RandomArray.src/M000022.html +35 -0
  70. data/data/rushcheck/rdoc/classes/RandomArray.src/M000023.html +22 -0
  71. data/data/rushcheck/rdoc/classes/RandomBool.html +146 -0
  72. data/data/rushcheck/rdoc/classes/RandomBool.src/M000079.html +18 -0
  73. data/data/rushcheck/rdoc/classes/RandomBool.src/M000080.html +19 -0
  74. data/data/rushcheck/rdoc/classes/RandomGen.html +196 -0
  75. data/data/rushcheck/rdoc/classes/RandomGen.src/M000076.html +18 -0
  76. data/data/rushcheck/rdoc/classes/RandomGen.src/M000077.html +18 -0
  77. data/data/rushcheck/rdoc/classes/RandomGen.src/M000078.html +18 -0
  78. data/data/rushcheck/rdoc/classes/RandomHash.html +197 -0
  79. data/data/rushcheck/rdoc/classes/RandomHash.src/M000044.html +18 -0
  80. data/data/rushcheck/rdoc/classes/RandomHash.src/M000045.html +26 -0
  81. data/data/rushcheck/rdoc/classes/RandomHash.src/M000046.html +22 -0
  82. data/data/rushcheck/rdoc/classes/RandomProc.html +192 -0
  83. data/data/rushcheck/rdoc/classes/RandomProc.src/M000055.html +18 -0
  84. data/data/rushcheck/rdoc/classes/RandomProc.src/M000056.html +30 -0
  85. data/data/rushcheck/rdoc/classes/RandomProc.src/M000057.html +26 -0
  86. data/data/rushcheck/rdoc/classes/RandomProc.src/M000058.html +20 -0
  87. data/data/rushcheck/rdoc/classes/Result.html +214 -0
  88. data/data/rushcheck/rdoc/classes/Result.src/M000051.html +18 -0
  89. data/data/rushcheck/rdoc/classes/Result.src/M000052.html +18 -0
  90. data/data/rushcheck/rdoc/classes/Result.src/M000053.html +18 -0
  91. data/data/rushcheck/rdoc/classes/RushCheckConfig.html +240 -0
  92. data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000001.html +23 -0
  93. data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000002.html +22 -0
  94. data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000003.html +18 -0
  95. data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000004.html +38 -0
  96. data/data/rushcheck/rdoc/classes/RushCheckConfig.src/M000005.html +55 -0
  97. data/data/rushcheck/rdoc/classes/RushCheckGuard.html +118 -0
  98. data/data/rushcheck/rdoc/classes/SpecialString.html +151 -0
  99. data/data/rushcheck/rdoc/classes/SpecialString.src/M000017.html +37 -0
  100. data/data/rushcheck/rdoc/classes/StdGen.html +252 -0
  101. data/data/rushcheck/rdoc/classes/StdGen.src/M000010.html +23 -0
  102. data/data/rushcheck/rdoc/classes/StdGen.src/M000011.html +21 -0
  103. data/data/rushcheck/rdoc/classes/StdGen.src/M000012.html +21 -0
  104. data/data/rushcheck/rdoc/classes/StdGen.src/M000013.html +18 -0
  105. data/data/rushcheck/rdoc/classes/StdGen.src/M000014.html +18 -0
  106. data/data/rushcheck/rdoc/classes/String.html +191 -0
  107. data/data/rushcheck/rdoc/classes/String.src/M000066.html +24 -0
  108. data/data/rushcheck/rdoc/classes/String.src/M000067.html +18 -0
  109. data/data/rushcheck/rdoc/classes/String.src/M000068.html +25 -0
  110. data/data/rushcheck/rdoc/classes/String.src/M000069.html +22 -0
  111. data/data/rushcheck/rdoc/classes/Testable.html +281 -0
  112. data/data/rushcheck/rdoc/classes/Testable.src/M000084.html +18 -0
  113. data/data/rushcheck/rdoc/classes/Testable.src/M000085.html +18 -0
  114. data/data/rushcheck/rdoc/classes/Testable.src/M000088.html +18 -0
  115. data/data/rushcheck/rdoc/classes/Testable.src/M000089.html +18 -0
  116. data/data/rushcheck/rdoc/classes/Testable.src/M000090.html +18 -0
  117. data/data/rushcheck/rdoc/classes/Testable.src/M000092.html +18 -0
  118. data/data/rushcheck/rdoc/classes/Testable.src/M000094.html +18 -0
  119. data/data/rushcheck/rdoc/classes/TheStdGen.html +200 -0
  120. data/data/rushcheck/rdoc/classes/TheStdGen.src/M000062.html +18 -0
  121. data/data/rushcheck/rdoc/classes/TheStdGen.src/M000063.html +20 -0
  122. data/data/rushcheck/rdoc/classes/TheStdGen.src/M000064.html +21 -0
  123. data/data/rushcheck/rdoc/classes/TheStdGen.src/M000065.html +18 -0
  124. data/data/rushcheck/rdoc/classes/TrueClass.html +177 -0
  125. data/data/rushcheck/rdoc/classes/TrueClass.src/M000072.html +18 -0
  126. data/data/rushcheck/rdoc/classes/TrueClass.src/M000073.html +18 -0
  127. data/data/rushcheck/rdoc/classes/TrueClass.src/M000074.html +18 -0
  128. data/data/rushcheck/rdoc/created.rid +1 -0
  129. data/data/rushcheck/rdoc/files/rushcheck/arbitrary_rb.html +114 -0
  130. data/data/rushcheck/rdoc/files/rushcheck/array_rb.html +117 -0
  131. data/data/rushcheck/rdoc/files/rushcheck/assertion_rb.html +120 -0
  132. data/data/rushcheck/rdoc/files/rushcheck/bool_rb.html +120 -0
  133. data/data/rushcheck/rdoc/files/rushcheck/config_rb.html +109 -0
  134. data/data/rushcheck/rdoc/files/rushcheck/float_rb.html +118 -0
  135. data/data/rushcheck/rdoc/files/rushcheck/gen_rb.html +111 -0
  136. data/data/rushcheck/rdoc/files/rushcheck/guard_rb.html +108 -0
  137. data/data/rushcheck/rdoc/files/rushcheck/hash_rb.html +117 -0
  138. data/data/rushcheck/rdoc/files/rushcheck/integer_rb.html +118 -0
  139. data/data/rushcheck/rdoc/files/rushcheck/proc_rb.html +118 -0
  140. data/data/rushcheck/rdoc/files/rushcheck/property_rb.html +119 -0
  141. data/data/rushcheck/rdoc/files/rushcheck/random_rb.html +126 -0
  142. data/data/rushcheck/rdoc/files/rushcheck/result_rb.html +118 -0
  143. data/data/rushcheck/rdoc/files/rushcheck/rushcheck_rb.html +123 -0
  144. data/data/rushcheck/rdoc/files/rushcheck/string_rb.html +121 -0
  145. data/data/rushcheck/rdoc/files/rushcheck/testable_rb.html +117 -0
  146. data/data/rushcheck/rdoc/fr_class_index.html +51 -0
  147. data/data/rushcheck/rdoc/fr_file_index.html +43 -0
  148. data/data/rushcheck/rdoc/fr_method_index.html +121 -0
  149. data/data/rushcheck/rdoc/index.html +24 -0
  150. data/data/rushcheck/rdoc/rdoc-style.css +208 -0
  151. data/lib/rushcheck/arbitrary.rb +28 -0
  152. data/lib/rushcheck/array.rb +49 -0
  153. data/lib/rushcheck/assertion.rb +67 -0
  154. data/lib/rushcheck/bool.rb +90 -0
  155. data/lib/rushcheck/config.rb +98 -0
  156. data/lib/rushcheck/float.rb +43 -0
  157. data/lib/rushcheck/gen.rb +189 -0
  158. data/lib/rushcheck/guard.rb +27 -0
  159. data/lib/rushcheck/hash.rb +45 -0
  160. data/lib/rushcheck/integer.rb +43 -0
  161. data/lib/rushcheck/proc.rb +53 -0
  162. data/lib/rushcheck/property.rb +29 -0
  163. data/lib/rushcheck/random.rb +215 -0
  164. data/lib/rushcheck/result.rb +26 -0
  165. data/lib/rushcheck/rushcheck.rb +17 -0
  166. data/lib/rushcheck/string.rb +100 -0
  167. data/lib/rushcheck/testable.rb +41 -0
  168. metadata +238 -0
@@ -0,0 +1,98 @@
1
+ # = Config.rb
2
+ # This file is implemented for the class RushCheckConfig.
3
+
4
+ # RushCheckConfig is a class which has configurations of tests.
5
+ # This class is needed for several test functions.
6
+ class RushCheckConfig
7
+
8
+ attr_reader :max_test, :max_fail, :size, :every
9
+
10
+ def self.quick
11
+ new(100, 1000,
12
+ Proc.new{|x| x / 2 + 3},
13
+ Proc.new do |n, args|
14
+ s = n.to_s
15
+ s + ("\b" * s.length)
16
+ end)
17
+ end
18
+
19
+ def self.verbose
20
+ new(100, 1000,
21
+ Proc.new{|x| x / 2 + 3},
22
+ Proc.new do |n, args|
23
+ n.to_s + ":\n" + args.join("\n") + "\n"
24
+ end)
25
+ end
26
+
27
+ def initialize(max_test, max_fail, size, every)
28
+ @max_test, @max_fail, @size, @every = max_test, max_fail, size, every
29
+ end
30
+
31
+ # print results of tests.
32
+ def done(mesg, ntest, stamps)
33
+ print mesg + ' ' + ntest.to_s + ' tests'
34
+
35
+ bag = stamps.compact.find_all {|x| ! x.empty?}.sort.
36
+ inject(Hash.new) do |r, m|
37
+ r[m] = r[m].nil? ? 1 : r[m] + 1
38
+ r
39
+ end.sort_by {|k, v| v}.reverse.map do |pair|
40
+ percentage = ((100 * pair[1]) / ntest).to_s + '%'
41
+ ([percentage] + pair[0]).join(', ')
42
+ end
43
+
44
+ mes = case bag.length
45
+ when 0
46
+ ".\n"
47
+ when 1
48
+ '(' + bag[0] + ").\n"
49
+ else
50
+ ".\n" + bag.join(".\n") + ".\n"
51
+ end
52
+
53
+ print mes
54
+ end
55
+
56
+ # execute tests
57
+ def tests(gen, rnd, nt=1, nf=0, stamps=[])
58
+ ntest, nfail = nt, nf
59
+ while true
60
+ if ntest > max_test
61
+ done('OK, passed', max_test, stamps)
62
+ tests_result = true
63
+ break
64
+ end
65
+ if nfail > max_fail
66
+ done('Arguments exhausted after ', ntest, stamps)
67
+ tests_result = nil
68
+ break
69
+ end
70
+
71
+ rnd_l, rnd_r = rnd.split
72
+ result = gen.generate(size.call(ntest), rnd_r)
73
+ message = every.call(ntest, result.arguments)
74
+ print message # don't puts
75
+
76
+ case result.ok
77
+ when nil
78
+ nfail += 1
79
+ redo
80
+ when true
81
+ stamps.push(result.stamp)
82
+ ntest += 1
83
+ redo
84
+ when false
85
+ error = "Falsifiable, after " + ntest.to_s + " tests:\n" +
86
+ result.arguments.join("\n")
87
+ puts error
88
+ tests_result = false
89
+ break
90
+ else
91
+ raise(RuntimeError, "RushCheck: illegal result")
92
+ end
93
+ end
94
+
95
+ tests_result
96
+ end
97
+
98
+ end
@@ -0,0 +1,43 @@
1
+ # = float.rb
2
+ # an extension to Float class for RushCheck
3
+
4
+ require 'rushcheck/arbitrary'
5
+ require 'rushcheck/integer'
6
+ require 'rushcheck/random'
7
+
8
+ class Float
9
+
10
+ extend Arbitrary
11
+ extend HsRandom
12
+
13
+ include Coarbitrary
14
+
15
+ @@min_bound = 0.0
16
+ @@max_bound = 1.0
17
+
18
+ def self.arbitrary
19
+ Gen.new do |n, r|
20
+ a, b, c = (1..3).map { Integer.arbitrary.value(n, r) }
21
+ a + (b / (c.abs + 1))
22
+ end
23
+ end
24
+
25
+ def self.bound
26
+ [@@min_bound, @@max_bound]
27
+ end
28
+
29
+ def self.random_range(gen, lo=@@min_bound, hi=@@max_bound)
30
+ x, g = Integer.random(gen)
31
+ a, b = Integer.bound
32
+ r = (lo+hi/2).to_f + ((hi - lo).to_f / (b - a) * x)
33
+
34
+ [r, g]
35
+ end
36
+
37
+ def coarbitrary(g)
38
+ h = truncate
39
+ t = (self * (10 ** ((self - h).to_s.length - 2))).truncate
40
+ h.coarbitrary(t.coarbitrary(g))
41
+ end
42
+
43
+ end
@@ -0,0 +1,189 @@
1
+ # = Gen.rb
2
+ # This file is implemented the type class Gen in Haskell's QuickCheck.
3
+ # Almost all implementations are similar to Haskell's one.
4
+ # Therefore check also the Haskell implementation.
5
+
6
+ # Gen provides functions for generating test instances.
7
+ class Gen
8
+
9
+ # choose is one of primitive generators to create a random Gen object.
10
+ # choose returns a Gen object which generates a random value in the
11
+ # bound. It may useful to implement arbitrary method into your class.
12
+ def self.choose(lo=nil, hi=nil)
13
+ rand.fmap {|x| lo.class.random(x, lo, hi)[0] }
14
+ end
15
+
16
+ # elements is one of primitive generators to create a random Gen
17
+ # object. elements requires an array and returns a Gen object which
18
+ # generates an object in the array randomly. It may useful to
19
+ # implement arbitrary method into your class.
20
+ def self.elements(xs)
21
+ raise(RuntimeError, "given argument is empty") if xs.empty?
22
+
23
+ choose(0, xs.length - 1).fmap {|i| xs[i] }
24
+ end
25
+
26
+ # frequency is one of primitive generators to create a random Gen
27
+ # object. frequency requires an array of pairs and returns a Gen
28
+ # object. The first component of pair should be a positive Integer
29
+ # and the second one should be a Gen object. The integer acts as a
30
+ # weight for choosing random Gen object in the array. For example,
31
+ # frequency([[1, Gen.rand], [2, Integer.arbitrary]]) returns the
32
+ # random generator Gen.rand in 33%, while another random generator
33
+ # of Integer (Integer.arbitrary) in 67%.
34
+ def self.frequency(xs)
35
+ tot = xs.inject(0) {|r, pair| r + pair[0]}
36
+ raise(RuntimeError, "Illegal frequency:#{xs.inspect}") if tot == 0
37
+ choose(0, tot - 1).bind do |n|
38
+ m = n
39
+ xs.each do |pair|
40
+ if m <= pair[0]
41
+ then break pair[1]
42
+ else m -= pair[0]
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ # lift_array is one of primitive generators to create a randam Gen
49
+ # object. lift_array takes an array and a block which has a
50
+ # variable. The block should return a Gen object. lift_array returns
51
+ # a Gen object which generates an array of the result of given block
52
+ # for applying each member of given array.
53
+ def self.lift_array(ary)
54
+ Gen.new do |n, r|
55
+ r2 = r
56
+ ary.map do |c|
57
+ r1, r2 = r.split
58
+ yield.value(n, r1)
59
+ end
60
+ end
61
+ end
62
+
63
+ # oneof is /one of/ primitive generators to create a random Gen object.
64
+ # oneof requires an array of Gen objects, and returns a Gen object
65
+ # which choose a Gen object in the array randomly.
66
+ # It may useful to implement arbitrary method into your class.
67
+ def self.oneof(gens)
68
+ elements(gens).bind {|x| x}
69
+ end
70
+
71
+ # promote is the function to create a Gen object which generates a
72
+ # procedure (Proc). promote requires a block which takes one
73
+ # variable and the block should be return a Gen object.
74
+ # promote returns a Gen object which generate a new procedure
75
+ # with the given block.
76
+ # It may useful to implement coarbitrary method into your class.
77
+ def self.promote
78
+ new {|n, r| Proc.new {|a| yield(a).value(n, r) } }
79
+ end
80
+
81
+ # rand returns a Gen object which generates a random number
82
+ # generator.
83
+ def self.rand
84
+ new {|n, r| r}
85
+ end
86
+
87
+ # sized is a combinator which the programmer can use to access the
88
+ # size bound. It requires a block which takes a variable as an
89
+ # integer for size. The block should be a function which changes the
90
+ # size of random instances.
91
+ def self.sized
92
+ new {|n, r| yield(n).value(n, r) }
93
+ end
94
+
95
+ # unit is a monadic function which equals the return function in
96
+ # the Haskell's monad. It requires one variable and returns a Gen
97
+ # object which generates the given object.
98
+ def self.unit(x)
99
+ new {|n, r| x}
100
+ end
101
+
102
+ # vector is one of primitive generators to create a Gen object.
103
+ # vector takes two variables, while the first one should be class,
104
+ # and the second one should be length. vector returns a Gen object
105
+ # which generates an array whose components belongs the given class
106
+ # and given length.
107
+ def self.vector(c, len)
108
+ new do |n, r|
109
+ r2 = r
110
+ (1..len).map do
111
+ r1, r2 = r2.split
112
+ c.arbitrary.value(n, r1)
113
+ end
114
+ end
115
+ end
116
+
117
+ # to initialize Gen object, it requires a block which takes two
118
+ # variables. The first argument of block is assumed as an integer,
119
+ # and the second one is assumed as a random generator of RandomGen.
120
+ def initialize(&f)
121
+ @proc = f
122
+ end
123
+
124
+ # bind is a monadic function such as Haskel's (>>=).
125
+ # bind takes a block which has two variables where the first one
126
+ # is assumed as an integer, and the second one is assumed as a
127
+ # random generator of RandomGen.
128
+ def bind
129
+ self.class.new do |n, r|
130
+ r1, r2 = r.split
131
+ yield(value(n, r1)).value(n, r2)
132
+ end
133
+ end
134
+
135
+ # value is a method to get the value of the internal procedure.
136
+ # value takes two variables where the first argument is assumed as
137
+ # an integer and the second one is assumed as a random generator of
138
+ # RandomGen.
139
+ def value(n, g)
140
+ @proc.call(n, g)
141
+ end
142
+
143
+ # fmap is a categorical function as same in Haskell.
144
+ # fmap requires a block which takes one variable.
145
+ def fmap
146
+ bind {|x| Gen.unit(yield(x)) }
147
+ end
148
+
149
+ # forall is a function to create a Gen object.
150
+ # forall requires a block which takes any variables
151
+ # and returns a Property object. Then forall returns
152
+ # a generator of the property.
153
+ def forall
154
+ bind do |*a|
155
+ yield(*a).property.bind do |res|
156
+ res.arguments.push(a.to_s)
157
+ Gen.unit(res)
158
+ end
159
+ end
160
+ end
161
+
162
+ # generate returns the random instance. generates takes two
163
+ # variables, where the first one should be an integer and the second
164
+ # should be the random number generator such as StdGen.
165
+ def generate(n, rnd)
166
+ s, r = Integer.random(rnd, 0, n)
167
+ value(s, r)
168
+ end
169
+
170
+ # resize returns another Gen object which resized by the given
171
+ # paramater. resize takes one variable in Integer.
172
+ def resize(n)
173
+ self.class.new {|x, r| value(n, r) }
174
+ end
175
+
176
+ # variant constructs a generator which transforms the random number
177
+ # seed. variant takes one variable which should be an
178
+ # Integer. variant is needed to generate rundom functions.
179
+ def variant(v)
180
+ self.class.new do |n, r|
181
+ g = (1..v).inject(r) do |gen, i|
182
+ gen, dummy = gen.split
183
+ gen
184
+ end
185
+ value(n, g)
186
+ end
187
+ end
188
+
189
+ end
@@ -0,0 +1,27 @@
1
+ # = guard.rb
2
+ # This provides class Guard
3
+
4
+ class RushCheckGuard < StandardError; end
5
+
6
+ # class Guard is used for RushCheck internally and many user
7
+ # don't care about this class.
8
+ class Guard
9
+
10
+ def guard_raise(c)
11
+ begin
12
+ yield
13
+ rescue Exception => ex
14
+ case ex
15
+ when c
16
+ raise RushCheckGuard
17
+ else
18
+ raise ex
19
+ end
20
+ end
21
+ end
22
+
23
+ def guard
24
+ raise RushCheckGuard unless yield
25
+ end
26
+
27
+ end
@@ -0,0 +1,45 @@
1
+ # = hash.rb
2
+ # a random generator of Hash
3
+ require 'rushcheck/arbitrary'
4
+ require 'rushcheck/gen'
5
+ require 'rushcheck/testable'
6
+
7
+ # RandomHash is a subclass of Hash which provides a random generator
8
+ # of hash. Programmer can make a subclass of RandomHash to make user
9
+ # defined random generator of Hash.
10
+ class RandomHash < Hash
11
+
12
+ extend Arbitrary
13
+ include Coarbitrary
14
+
15
+ # class method set_pattern takes a hash object of
16
+ # random pattern. For example, the following pattern
17
+ # pat = { 'key1' => Integer, 'key2' => String }
18
+ # means that an arbitrary hash is randomly generated
19
+ # which has two keys (say 'key1' and 'key2') and
20
+ # has indicated random object as its values.
21
+ def self.set_pattern(pat)
22
+ @@pat = pat
23
+ end
24
+
25
+ def self.arbitrary
26
+ Gen.new do |n, r|
27
+ h = {}
28
+ r2 = r
29
+ @@pat.keys.each do |k|
30
+ r1, r2 = r2.split
31
+ h[k] = @@pat[k].arbitrary.value(n, r1)
32
+ end
33
+ h
34
+ end
35
+ end
36
+
37
+ def coarbitrary(g)
38
+ r = g.variant(0)
39
+ values.each do |c|
40
+ r = c.coarbitrary(r.variant(1))
41
+ end
42
+ r
43
+ end
44
+
45
+ end
@@ -0,0 +1,43 @@
1
+ # = integer.rb
2
+ # an extension to Integer class for RushCheck
3
+ #
4
+
5
+ require 'rushcheck/arbitrary'
6
+ require 'rushcheck/gen'
7
+ require 'rushcheck/random'
8
+
9
+ # ruby's Integer class is extended to use RushCheck library.
10
+ # See also HsRandom, Arbitrary and Coarbitrary.
11
+ class Integer
12
+ extend HsRandom
13
+ extend Arbitrary
14
+ include Coarbitrary
15
+
16
+ @@max_bound = 2**30 - 1
17
+ @@min_bound = -(2**30)
18
+
19
+ # this method is needed to include HsRandom.
20
+ def self.bound
21
+ [@@min_bound, @@max_bound]
22
+ end
23
+
24
+ # this method is needed to use Arbitrary.
25
+ def self.arbitrary
26
+ Gen.sized {|n| Gen.choose(-n, n) }
27
+ end
28
+
29
+ # this method is needed to include HsRandom.
30
+ def self.random_range(gen, lo=@@min_bound, hi=@@max_bound)
31
+ raise(RuntimeError, "illegal arguments:#{lo}, #{hi}") if hi - lo + 1 == 0
32
+ v, g = gen.gen_next
33
+
34
+ [(v % (hi - lo + 1)) + lo, g]
35
+ end
36
+
37
+ # this method is needed to use Coarbitrary.
38
+ def coarbitrary(g)
39
+ m = (self >= 0) ? 2 * self : (-2) * self + 1
40
+ g.variant(m)
41
+ end
42
+
43
+ end
@@ -0,0 +1,53 @@
1
+ # = proc.rb
2
+ # The file provides a random generator of procedure.
3
+ # See also examples/proc.rb
4
+
5
+ require 'rushcheck/arbitrary'
6
+ require 'rushcheck/gen'
7
+ require 'rushcheck/testable'
8
+
9
+ class RandomProc < Proc
10
+
11
+ extend Arbitrary
12
+ include Coarbitrary
13
+ include Testable
14
+
15
+ def self.set_pattern(inputs, outputs)
16
+ @@inputs, @@outputs = inputs, outputs
17
+ end
18
+
19
+ def self.arbitrary
20
+ Gen.new do |n, r|
21
+ Proc.new do |*args|
22
+ gens = if args.empty?
23
+ then @@outputs.map {|c| c.arbitrary }
24
+ else args.map do |v|
25
+ @@outputs.map do |c|
26
+ v.coarbitrary(c.arbitrary)
27
+ end
28
+ end.flatten
29
+ end
30
+ Gen.oneof(gens).value(n, r)
31
+ end
32
+ end
33
+ end
34
+
35
+ def coarbitrary(g)
36
+ Gen.new do |n, r|
37
+ r2 = r
38
+ args = @@inputs.map do |c|
39
+ r1, r2 = r2.split
40
+ c.arbitrary.value(n, r1)
41
+ end
42
+
43
+ call(*args).coarbitrary(g)
44
+ end
45
+ end
46
+
47
+ def property
48
+ Gen.lift_array(@@inputs) {|c| c.arbitrary }.forall do |*args|
49
+ call(*args)
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,29 @@
1
+ # = property.rb
2
+ # This file defines properties of testcase
3
+ # class Property is used for RushCheck internally
4
+ require 'rushcheck/gen'
5
+ require 'rushcheck/result'
6
+ require 'rushcheck/testable'
7
+
8
+ class Property
9
+
10
+ include Testable
11
+
12
+ attr_reader :gen
13
+ def initialize(obj=nil, stamp=[], arguments=[])
14
+ case obj
15
+ when nil, true, false
16
+ result = Result.new(obj, stamp, arguments)
17
+ @gen = Gen.unit(result)
18
+ when Gen
19
+ @gen = obj
20
+ else
21
+ raise(RuntimeError, "illegal arguments")
22
+ end
23
+ end
24
+
25
+ def property
26
+ self
27
+ end
28
+
29
+ end