rushcheck 0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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