rantly 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79dd7dec8dc33c88121e8f18e937c066730f92d190e34657742245d5d2ad39ce
4
- data.tar.gz: 0d0a1435d25e7ad2d1948d45040a6524b79425011289331484b35b0387d7d750
3
+ metadata.gz: 13f1bd6f943416c68aff13d50f505ff92485c1613c4c01b52d8cbc78eb027b66
4
+ data.tar.gz: af1de15faf3be9d3984c1343eb59b65081d0d8c12916c07434e0353ee37a4204
5
5
  SHA512:
6
- metadata.gz: 7f652b90718f7d9f32c1e88995d85371cd87af8d247b7def676a171b58f170cb08d0d29f54cb68259a7f4f42c64299d7c1b8f1741095c9dc174e4208904535b0
7
- data.tar.gz: 54a9a7f6c94741379d58268fb56a0fb47e8787868e5f8610904a2c551d65041e6042470a3a3514acd0a585a2e75859b26f73605b0a55e5352f0a913a83b4742c
6
+ metadata.gz: 2f24ffc2cb269a377fb0b5c0e40897ba417ef991d5e219c0a0423458b8b5e760102ba1f32c157190f982419da8f8e6a32e628e1012a0d070d36045609e0a7255
7
+ data.tar.gz: bb6c3265fbfcd2a0d339dbdf87d6f38afb9e71c5f4f58531c92ce99d784ad5e66405f0a26b6caf6aed9a7cc86bebe6b4194273c389073041b7890abb79f51c03
@@ -4,10 +4,13 @@ cache: bundler
4
4
  after_success:
5
5
  - coveralls
6
6
  rvm:
7
- - 2.0.0
8
- - 2.1.9
9
- - 2.2.6
10
- - 2.3.3
11
7
  - 2.4.0
12
- - jruby-1.7.26
13
- - jruby-9.1.7.0
8
+ - 2.5.1
9
+ - ruby-head
10
+ - jruby-9.2.0.0
11
+ - jruby-head
12
+
13
+ matrix:
14
+ allow_failures:
15
+ - rvm: jruby-head
16
+ - rvm: ruby-head
@@ -3,6 +3,38 @@ All notable changes to rantly will be documented in this file. The curated log b
3
3
 
4
4
  This project adheres to [Semantic Versioning](http://semver.org/).
5
5
 
6
+ ## [Master](https://github.com/rantly-rb/rantly/compare/2.0.0...master) (unreleased)
7
+
8
+ ### New features
9
+
10
+ ### Bug fixes
11
+
12
+ ### Changes
13
+
14
+
15
+ ## [2.0.0](https://github.com/rantly-rb/rantly/compare/1.2.0...2.0.0) - 2019-01-08
16
+
17
+ ### New features
18
+ - Add support for float ranges to `range` generator
19
+ - [Issue #60](https://github.com/rantly-rb/rantly/issues/60)
20
+ - thanks [Trevor Brown][Trevor Brown]
21
+
22
+ ### Bug fixes
23
+ - `range` generator returns `nil` for invalid ranges
24
+ - [Issue #60](https://github.com/rantly-rb/rantly/issues/60)
25
+ - thanks [Ana María Martínez Gómez][Ana María Martínez Gómez]
26
+ - `choose` generator returns `nil` when no values are given
27
+ - thanks [Ana María Martínez Gómez][Ana María Martínez Gómez]
28
+
29
+ ### Changes
30
+ - Only support for Ruby >= 2.4 and JRuby >= 9.2
31
+ - [Issue #42](https://github.com/rantly-rb/rantly/issues/42) and [issue #37](https://github.com/rantly-rb/rantly/issues/37)
32
+ - Do not render all shrinking levels, only the failing case and the minimal failed data.
33
+ - thanks [Ana María Martínez Gómez][Ana María Martínez Gómez]
34
+ - Improve failure/success messages
35
+ - thanks [Ana María Martínez Gómez][Ana María Martínez Gómez]
36
+
37
+
6
38
  ## [1.2.0](https://github.com/abargnesi/rantly/compare/1.1.0...1.2.0) - 2018-08-29
7
39
  ### New features
8
40
  - Allow to generate floats using Gaussian distribution
@@ -59,3 +91,4 @@ This project adheres to [Semantic Versioning](http://semver.org/).
59
91
  [Oleksii Fedorov]: https://github.com/waterlink
60
92
  [Ana María Martínez Gómez]: https://github.com/Ana06
61
93
  [Víctor Gallego]: https://github.com/vicgalle
94
+ [Trevor Brown]: https://github.com/Stratus3D
data/Gemfile CHANGED
@@ -1,8 +1,10 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  group :development, :test do
4
- gem 'rake', '~> 12.0.0'
4
+ gem 'coveralls', '>= 0', require: false
5
5
  gem 'minitest', '~> 5.10.0'
6
+ gem 'rake', '~> 12.0.0'
6
7
  gem 'simplecov', '>= 0'
7
- gem 'coveralls', '>= 0', :require => false
8
+
9
+ gem 'rubocop'
8
10
  end
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  [![Gem version](https://badge.fury.io/rb/rantly.svg)](https://badge.fury.io/rb/rantly)
2
2
  [![Build Status](https://travis-ci.org/rantly-rb/rantly.svg?branch=master)](https://travis-ci.org/rantly-rb/rantly)
3
+ [![Coverage Status](https://coveralls.io/repos/github/rantly-rb/rantly/badge.svg?branch=master)](https://coveralls.io/github/rantly-rb/rantly?branch=master)
3
4
 
4
5
  # Imperative Random Data Generator and Quickcheck
5
6
 
@@ -9,13 +10,19 @@ Rantly is basically a recursive descent interpreter, each of its method returns
9
10
 
10
11
  Its implementation has no alien mathematics inside. Completely side-effect-free-free.
11
12
 
13
+ ![img](/logo/Rantly.png)
14
+
12
15
 
13
16
  # Install
14
17
 
18
+ Rantly requires Ruby 2.4 or higher. To install Rantly add it to your Gemfile or run:
19
+
15
20
  ```ruby
16
21
  $ gem install rantly
17
22
  ```
18
23
 
24
+ You can try it in the console by running:
25
+
19
26
  ```ruby
20
27
  $ irb -rrantly
21
28
  > Rantly { [integer,float] } # same as Rantly.value { integer }
@@ -401,8 +408,10 @@ Normal arrays or hashes are not shrinked.
401
408
 
402
409
  Thanks to [all contributors](https://github.com/rantly-rb/rantly/graphs/contributors). :cupid: New contributors are welcome! :wink:
403
410
 
411
+ [Logotype](/logo) designed by: [@Richardbmx](https://github.com/richardbmx)
412
+
404
413
 
405
414
  # License
406
415
 
407
- Code published under MIT License, Copyright (c) 2009 Howard Yeh. See [LICENSE](https://github.com/abargnesi/rantly/LICENSE).
416
+ Code published under MIT License, Copyright (c) 2009 Howard Yeh. See [LICENSE](/LICENSE).
408
417
 
data/Rakefile CHANGED
@@ -1,22 +1,35 @@
1
1
  require 'rake'
2
2
 
3
+ task default: %i[test rubocop]
4
+
3
5
  require 'rake/testtask'
6
+
4
7
  Rake::TestTask.new(:test) do |test|
5
8
  test.libs << 'lib' << 'test'
6
9
  test.pattern = 'test/**/*_test.rb'
7
10
  test.verbose = true
8
11
  end
9
12
 
10
- task :default => :test
13
+ require 'rubocop/rake_task'
14
+
15
+ desc 'Run RuboCop'
16
+ RuboCop::RakeTask.new(:rubocop) do |task|
17
+ task.options = ['--display-cop-names']
18
+ end
19
+
20
+ RuboCop::RakeTask.new('rubocop:auto_gen_config') do |task|
21
+ task.options = ['--display-cop-names', '--auto-gen-config', '--auto-gen-only-exclude']
22
+ end
11
23
 
12
24
  require 'rdoc/task'
25
+
13
26
  Rake::RDocTask.new do |rdoc|
14
27
  require 'yaml'
15
28
  if File.exist?('VERSION.yml')
16
29
  config = YAML.load(File.read('VERSION.yml'))
17
30
  version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
18
31
  else
19
- version = ""
32
+ version = ''
20
33
  end
21
34
 
22
35
  rdoc.rdoc_dir = 'rdoc'
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  :build:
3
- :major: 1
4
- :minor: 2
3
+ :major: 2
4
+ :minor: 0
5
5
  :patch: 0
@@ -1,14 +1,14 @@
1
- $:.unshift(File.dirname(__FILE__)) unless
2
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__)) unless
2
+ $LOAD_PATH.include?(File.dirname(__FILE__)) || $LOAD_PATH.include?(__dir__)
3
3
 
4
4
  class Rantly
5
5
  end
6
6
 
7
7
  require 'rantly/generator'
8
8
 
9
- def Rantly(n=1,&block)
9
+ def Rantly(n = 1, &block)
10
10
  if n > 1
11
- Rantly.map(n,&block)
11
+ Rantly.map(n, &block)
12
12
  else
13
13
  Rantly.value(&block)
14
14
  end
@@ -1,6 +1,6 @@
1
1
  module Rantly::Data
2
2
  def email
3
- "#{string(:alnum)}@#{string(:alnum)}.#{sized(3){string(:alpha)}}".downcase
3
+ "#{string(:alnum)}@#{string(:alnum)}.#{sized(3) { string(:alpha) }}".downcase
4
4
  end
5
5
 
6
6
  def password
@@ -1,5 +1,4 @@
1
1
  class Rantly
2
-
3
2
  class << self
4
3
  attr_writer :default_size
5
4
  def singleton
@@ -11,20 +10,20 @@ class Rantly
11
10
  @default_size || 6
12
11
  end
13
12
 
14
- def each(n,limit=10,&block)
15
- gen.each(n,limit,&block)
13
+ def each(n, limit = 10, &block)
14
+ gen.each(n, limit, &block)
16
15
  end
17
16
 
18
- def map(n,limit=10,&block)
19
- gen.map(n,limit,&block)
17
+ def map(n, limit = 10, &block)
18
+ gen.map(n, limit, &block)
20
19
  end
21
20
 
22
- def value(limit=10,&block)
23
- gen.value(limit,&block)
21
+ def value(limit = 10, &block)
22
+ gen.value(limit, &block)
24
23
  end
25
24
 
26
25
  def gen
27
- self.singleton
26
+ singleton
28
27
  end
29
28
  end
30
29
 
@@ -32,7 +31,7 @@ class Rantly
32
31
  end
33
32
 
34
33
  class TooManyTries < RuntimeError
35
- def initialize(limit,nfailed)
34
+ def initialize(limit, nfailed)
36
35
  @limit = limit
37
36
  @nfailed = nfailed
38
37
  end
@@ -41,38 +40,37 @@ class Rantly
41
40
  @nfailed
42
41
  end
43
42
 
44
- def to_s
45
- "Exceed gen limit #{@limit}: #{@nfailed} failed guards"
46
- end
43
+ attr_reader :limit
47
44
  end
48
45
 
49
46
  # limit attempts to 10 times of how many things we want to generate
50
- def each(n,limit=10,&block)
51
- generate(n,limit,block)
47
+ def each(n, limit = 10, &block)
48
+ generate(n, limit, block)
52
49
  end
53
50
 
54
- def map(n,limit=10,&block)
51
+ def map(n, limit = 10, &block)
55
52
  acc = []
56
- generate(n,limit,block) do |val|
53
+ generate(n, limit, block) do |val|
57
54
  acc << val
58
55
  end
59
56
  acc
60
57
  end
61
58
 
62
- def value(limit=10,&block)
63
- generate(1,limit,block) do |val|
59
+ def value(limit = 10, &block)
60
+ generate(1, limit, block) do |val|
64
61
  return val
65
62
  end
66
63
  end
67
64
 
68
- def generate(n,limit_arg,gen_block,&handler)
65
+ def generate(n, limit_arg, gen_block, &handler)
69
66
  limit = n * limit_arg
70
67
  nfailed = 0
71
68
  nsuccess = 0
72
69
  while nsuccess < n
73
- raise TooManyTries.new(limit_arg*n,nfailed) if limit < 0
70
+ raise TooManyTries.new(limit_arg * n, nfailed) if limit.zero?
71
+
74
72
  begin
75
- val = self.instance_eval(&gen_block)
73
+ val = instance_eval(&gen_block)
76
74
  rescue GuardFailure
77
75
  nfailed += 1
78
76
  limit -= 1
@@ -80,7 +78,7 @@ class Rantly
80
78
  end
81
79
  nsuccess += 1
82
80
  limit -= 1
83
- handler.call(val) if handler
81
+ yield(val) if handler
84
82
  end
85
83
  end
86
84
 
@@ -100,87 +98,89 @@ class Rantly
100
98
  end
101
99
 
102
100
  def guard(test)
103
- unless test
104
- raise GuardFailure.new
105
- else
106
- true
107
- end
101
+ return true if test
102
+
103
+ raise GuardFailure
108
104
  end
109
105
 
110
106
  def size
111
107
  @size || Rantly.default_size
112
108
  end
113
109
 
114
- def sized(n,&block)
115
- raise "size needs to be greater than zero" if n < 0
110
+ def sized(n, &block)
111
+ raise 'size needs to be greater than zero' if n.negative?
112
+
116
113
  old_size = @size
117
114
  @size = n
118
- r = self.instance_eval(&block)
115
+ r = instance_eval(&block)
119
116
  @size = old_size
120
- return r
117
+ r
121
118
  end
122
119
 
123
120
  # wanna avoid going into Bignum when calling range with these.
124
121
  INTEGER_MAX = (2**(0.size * 8 - 2) - 1) / 2
125
- INTEGER_MIN = -(INTEGER_MAX)
126
- def integer(limit=nil)
122
+ INTEGER_MIN = -INTEGER_MAX
123
+ def integer(limit = nil)
127
124
  case limit
128
125
  when Range
129
126
  hi = limit.end
130
127
  lo = limit.begin
131
128
  when Integer
132
- raise "n should be greater than zero" if limit < 0
133
- hi, lo = limit, -limit
129
+ raise 'n should be greater than zero' if limit.negative?
130
+
131
+ hi = limit
132
+ lo = -limit
134
133
  else
135
- hi, lo = INTEGER_MAX, INTEGER_MIN
134
+ hi = INTEGER_MAX
135
+ lo = INTEGER_MIN
136
136
  end
137
- range(lo,hi)
137
+ range(lo, hi)
138
138
  end
139
139
 
140
140
  def positive_integer
141
141
  range(0)
142
142
  end
143
143
 
144
- def float(distribution=nil, params={})
144
+ def float(distribution = nil, params = {})
145
145
  case distribution
146
146
  when :normal
147
147
  params[:center] ||= 0
148
148
  params[:scale] ||= 1
149
- raise "The distribution scale should be greater than zero" unless params[:scale] > 0
149
+ raise 'The distribution scale should be greater than zero' if params[:scale].negative?
150
+
150
151
  # Sum of 6 draws from a uniform distribution give as a draw of a normal
151
152
  # distribution centered in 3 (central limit theorem).
152
- ([rand, rand, rand, rand, rand, rand].reduce(0, :+) - 3) * params[:scale] + params[:center]
153
+ ([rand, rand, rand, rand, rand, rand].sum - 3) * params[:scale] + params[:center]
153
154
  else
154
155
  rand
155
156
  end
156
157
  end
157
158
 
158
- def range(lo=nil,hi=nil)
159
- lo ||= INTEGER_MIN
160
- hi ||= INTEGER_MAX
161
- rand(hi+1-lo) + lo
159
+ def range(lo = INTEGER_MIN, hi = INTEGER_MAX)
160
+ rand(lo..hi)
162
161
  end
163
162
 
164
- def call(gen,*args)
163
+ def call(gen, *args)
165
164
  case gen
166
165
  when Symbol
167
- return self.send(gen,*args)
166
+ send(gen, *args)
168
167
  when Array
169
- raise "empty array" if gen.empty?
170
- return self.send(gen[0],*gen[1..-1])
168
+ raise 'empty array' if gen.empty?
169
+
170
+ send(gen[0], *gen[1..-1])
171
171
  when Proc
172
- return self.instance_eval(&gen)
172
+ instance_eval(&gen)
173
173
  else
174
174
  raise "don't know how to call type: #{gen}"
175
175
  end
176
176
  end
177
177
 
178
178
  def branch(*gens)
179
- self.call(choose(*gens))
179
+ call(choose(*gens))
180
180
  end
181
181
 
182
182
  def choose(*vals)
183
- vals[range(0,vals.length-1)]
183
+ vals[range(0, vals.length - 1)] if vals.length.positive?
184
184
  end
185
185
 
186
186
  def literal(value)
@@ -188,52 +188,50 @@ class Rantly
188
188
  end
189
189
 
190
190
  def boolean
191
- range(0,1) == 0 ? true : false
191
+ range(0, 1).zero?
192
192
  end
193
193
 
194
194
  def freq(*pairs)
195
195
  pairs = pairs.map do |pair|
196
196
  case pair
197
197
  when Symbol, String, Proc
198
- [1,pair]
198
+ [1, pair]
199
199
  when Array
200
- unless pair.first.is_a?(Integer)
201
- [1] + pair
202
- else
200
+ if pair.first.is_a?(Integer)
203
201
  pair
202
+ else
203
+ [1] + pair
204
204
  end
205
205
  end
206
206
  end
207
- total = pairs.inject(0) { |sum,p| sum + p.first }
208
- raise(RuntimeError, "Illegal frequency:#{pairs.inspect}") if total == 0
209
- pos = range(1,total)
207
+ total = pairs.inject(0) { |sum, p| sum + p.first }
208
+ raise("Illegal frequency:#{pairs.inspect}") if total.zero?
209
+
210
+ pos = range(1, total)
210
211
  pairs.each do |p|
211
212
  weight, gen, *args = p
212
- if pos <= p[0]
213
- return self.call(gen,*args)
214
- else
215
- pos -= weight
216
- end
213
+ return call(gen, *args) if pos <= p[0]
214
+
215
+ pos -= weight
217
216
  end
218
217
  end
219
218
 
220
- def array(n=self.size,&block)
221
- n.times.map { self.instance_eval(&block) }
219
+ def array(n = size, &block)
220
+ n.times.map { instance_eval(&block) }
222
221
  end
223
222
 
224
- def dict(n=self.size,&block)
223
+ def dict(n = size, &block)
225
224
  h = {}
226
225
  each(n) do
227
- k,v = instance_eval(&block)
228
- h[k] = v if guard(!h.has_key?(k))
226
+ k, v = instance_eval(&block)
227
+ h[k] = v if guard(!h.key?(k))
229
228
  end
230
229
  h
231
230
  end
232
231
 
233
232
  module Chars
234
-
235
233
  class << self
236
- ASCII = (0..127).to_a.each_with_object("") { |i, obj| obj << i }
234
+ ASCII = (0..127).to_a.each_with_object('') { |i, obj| obj << i }
237
235
 
238
236
  def of(regexp)
239
237
  ASCII.scan(regexp).to_a.map! { |char| char[0].ord }
@@ -254,41 +252,35 @@ class Rantly
254
252
  XDIGIT = Chars.of(/[[:xdigit:]]/)
255
253
  ASCII = Chars.of(/./)
256
254
 
257
-
258
255
  CLASSES = {
259
- :alnum => ALNUM,
260
- :alpha => ALPHA,
261
- :blank => BLANK,
262
- :cntrl => CNTRL,
263
- :digit => DIGIT,
264
- :graph => GRAPH,
265
- :lower => LOWER,
266
- :print => PRINT,
267
- :punct => PUNCT,
268
- :space => SPACE,
269
- :upper => UPPER,
270
- :xdigit => XDIGIT,
271
- :ascii => ASCII,
272
- }
273
-
256
+ alnum: ALNUM,
257
+ alpha: ALPHA,
258
+ blank: BLANK,
259
+ cntrl: CNTRL,
260
+ digit: DIGIT,
261
+ graph: GRAPH,
262
+ lower: LOWER,
263
+ print: PRINT,
264
+ punct: PUNCT,
265
+ space: SPACE,
266
+ upper: UPPER,
267
+ xdigit: XDIGIT,
268
+ ascii: ASCII
269
+ }.freeze
274
270
  end
275
271
 
276
- def string(char_class=:print)
272
+ def string(char_class = :print)
277
273
  chars = case char_class
278
274
  when Regexp
279
275
  Chars.of(char_class)
280
276
  when Symbol
281
277
  Chars::CLASSES[char_class]
282
278
  end
283
- raise "bad arg" unless chars
279
+ raise 'bad arg' unless chars
284
280
 
285
- char_strings = chars.map { |c| c.chr }
281
+ char_strings = chars.map(&:chr)
286
282
  str = Array.new(size)
287
- current_index = 0
288
- while current_index < size
289
- str[current_index] = char_strings.sample
290
- current_index += 1
291
- end
283
+ size.times { |i| str[i] = char_strings.sample }
292
284
  str.join
293
285
  end
294
286
  end