junklet 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZDBjY2JlZjYxYjAyMjI4NTc0NTBlZDkwZTRjNzdmMjMyZmQwNGMyMQ==
4
+ Zjc3YzlmNzVjYTc3YmZhNTIwZjZlNTE4Y2I1ZTQ2YWM0ZmNmODk3ZQ==
5
5
  data.tar.gz: !binary |-
6
- MmRjOTE4OGRiYTA4ODkyYzE3ZTAzNTQ3Y2VjOGYzZDkwZjc0NTY4MA==
6
+ NTI1YTRjZWJkMmFiMmI3ZWNhOGM2NTBhNDRkZmNjYWZiMzJjNGM4ZQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NGY2OTMwZGM3NDc5MWI5MzFjYmY2ZTFiZTdjM2VjOTFiMjJiYWVjMjk3N2Fk
10
- OWE1MDU2YTc5OWI1M2ZmMjM2YThiMzNiZGMyYTg1MGJkNzNlOTU1NDVjMWEw
11
- N2NjMjNjYzE5ZTQyYWNkMGZiNmFkODFhZjkxYzAyNzk4YTNjZmE=
9
+ OGM0ZDRjYTkxYjdhNTdlNzA5YTM3MjU5MGEyZDk3ZWQwYTQ0YjU5NjczMGE2
10
+ ZGU0NmIxNjk4ZDc1Yzg5NDAxOTU2NTM4NmJlNTE3NjIwMmM4NWZhMDM2MTNk
11
+ OTFmN2FiNjAwMThiYTBlNTFkYTM3M2I4NjE5NDQzMDZiZjIxZjk=
12
12
  data.tar.gz: !binary |-
13
- YjRkMGJhNjdhNzBmMzI4N2U3ZjgwZTVhNjdmODdjNmQxYzg0ZWM1NzBkMzYz
14
- NTljODE1NjM4Y2I2YTc0NjEzMjc3MmM3Zjg3M2I1N2NiZDZjODcyZDBjMWM5
15
- ODI3MGI1NjQ5ZmQ5MDYyNTM0ODFmY2M4ODdkMWI2MWM0Y2QwZTE=
13
+ OWIxNDM5ZGUyOWRhODg1YmM5NDFiMWZhMjNjNGY0MTRlZGQ1ZDNmY2JhNGJh
14
+ Nzk5MzVlZTk4NDJhYWIwM2E0ZDUyNmI1NzEyZGQ2NGIyYjM0M2VhOWM5YTAx
15
+ MmJiNTg0MGY3ZDY2NGNlNjJlYTU4NmViMmM2OWY5ZmNjZjlhYmU=
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- junklet (1.0.0)
4
+ junklet (1.0.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -119,6 +119,49 @@ This will have the same effect as calling `let` on the named fields
119
119
  and setting the fieldname and a 32-byte hex string (a uuid with
120
120
  hyphens removed) to be the memoized value.
121
121
 
122
+
123
+
124
+ # Finer Control / Custom Types
125
+
126
+ The `junk` method now has MUCH finer-grained control, though this
127
+ hasn't been pushed up to junklet yet.
128
+
129
+
130
+ `junk <type> [options]`
131
+
132
+ ```ruby
133
+ junk(:int) # returns a random, positive ruby Fixnum between 0 and
134
+ # 2**62-1.
135
+ junk(:int, min: 5, max: 9) # returns a number from 5 to 9
136
+ junk(:int, max: 1) # returns 0 or 1
137
+
138
+ junk(:bool) # returns true or false
139
+
140
+ junk([:a, :b, :c]) # samples from the Array
141
+ junk(('A'..'Z')) # samples from the range.
142
+
143
+ # Memory warning: calls to_a on range first, so if you want a number
144
+ # from 100000 to 999999, favor junk(:int, min: 100000, max: 999999)
145
+ # instead.
146
+
147
+ junk ->{ your_own_random_thing_here }
148
+
149
+ # Also note that all types also take an `exclude` option, which can be
150
+ # a value, an array, or a proc. These all return even numbers:
151
+
152
+ junk :int, min: 2, max: 4, exclude: 3
153
+ junk :int, min: 2, max: 10, exclude: [3,5,7,9]
154
+ junk :int, min: 2, max: 100, exclude: ->(x) { x % 2 == 1 }
155
+
156
+ # And remember that junk is at the same level of precedence as let, so
157
+ # the following ALSO return even numbers:
158
+
159
+ let(:three) { 3 }
160
+ let(:evens) { junk :int, min: 2, max: 4, exclude: three }
161
+ let(:two_or_four) { junk :int, min: 2, max: 4, exclude: ->(x){ !evens.include?(x) }
162
+
163
+ ```
164
+
122
165
  # TODO
123
166
 
124
167
  * Formats - The original motivation for Junklet is to encapsulate the
@@ -1,3 +1,3 @@
1
1
  module Junklet
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.2"
3
3
  end
data/lib/junklet.rb CHANGED
@@ -5,12 +5,17 @@ module RSpec
5
5
  module MemoizedHelpers
6
6
  module ClassMethods
7
7
  def junklet(*args)
8
+ # TODO: figure out how to use this to wrap junk in junklet,
9
+ # so that junklet can basically have all the same options as
10
+ # junk does. E.g. junklet :ddid, :pcn, :group, type: :int,
11
+ # min: 100000, max: 999999, etc, and you'd get back 3
12
+ # junklets of 6-digit numbers.
8
13
  opts = args.size > 1 && !args.last.is_a?(Symbol) && args.pop || {}
9
14
 
10
15
  names = args.map(&:to_s)
11
16
 
12
17
  if opts.key?(:separator)
13
- names = names.map {|name| name.gsub(/_/, opts[:separator]) }
18
+ names = names.map {|name| name.gsub(/_/, opts[:separator])}
14
19
  end
15
20
 
16
21
  args.zip(names).each do |arg, name|
@@ -19,14 +24,84 @@ module RSpec
19
24
  end
20
25
  end
21
26
 
22
- def junk(size=32, options={})
23
- if :integer == options[:type]
24
- # TODO: We can actual know how many hex digits we need in
25
- # advance because of te ratio of the logs. We should totally
26
- # work that out sometime. The ratio is like 1.2 something. For
27
- # now, blah, just make it work.
28
- SecureRandom.hex.to_i(16).to_s[0..size]
27
+ def junk(*args)
28
+ # TODO: It's long past time to extract this....
29
+
30
+ # args.first can be
31
+ # - an integer indicating the size of the hex string to return
32
+ # - a symbol denoting the base type, e.g. :int
33
+ # - an array to sample from
34
+ # - a range or Enumerable to sample from. WARNING: will call
35
+ # .to_a on it first, which might be expensive
36
+ # - a generator Proc which, when called, will generate the
37
+ # value to use.
38
+ #
39
+ # args.rest is a hash of options:
40
+ # - sequence: Proc or Array of values to choose from.
41
+ # - exclude: value, array of values, or proc to exclude. If a
42
+ # Proc is given, it takes the value generated and returns
43
+ # true if the value should be excluded.
44
+ #
45
+ # - for int:
46
+ # - min: minimum number to return. Default: 0
47
+ # - max: upper limit of range
48
+ # - exclude: number, array of numbers, or proc to
49
+ # exclude. If Proc is provided, tests the number against
50
+ # the Proc an excludes it if the Proc returns true. This
51
+ # is implemented except for the proc.
52
+
53
+ # FIXME: Raise Argument error unless *args.size is 0-2
54
+ # FIXME: If arg 1 is a hash, it's the options hash, raise
55
+ # ArgumentError unless args.size == 1
56
+ # FIXME: If arg 2 present, Raise Argument error unless it's a
57
+ # hash.
58
+ # FIXME: Figure out what our valid options are and parse them;
59
+ # raise errors if present.
60
+
61
+ classes = [Symbol, Array, Enumerable, Proc]
62
+ if args.size > 0 && classes.any? {|klass| args.first.is_a?(klass) }
63
+ type = args.shift
64
+ opts = args.last || {}
65
+ excluder = if opts[:exclude]
66
+ if opts[:exclude].is_a?(Proc)
67
+ opts[:exclude]
68
+ else
69
+ ->(x) { Array(opts[:exclude]).include?(x) }
70
+ end
71
+ else
72
+ ->(x) { false }
73
+ end
74
+
75
+ # TODO: Refactor me. Seriously, this is a functional
76
+ # programming version of the strategy pattern. Wouldn't it
77
+ # be neat if we had some kind of object-oriented language
78
+ # available here?
79
+ case type
80
+ when :int
81
+ # Fun fact: you can get back an arbitrarily large number
82
+ # by specifying a max value >= 2**62 so that Ruby promotes
83
+ # it to a BigNum.
84
+ min = opts[:min] || 0
85
+ max = (opts[:max] || 2**62-2) + 1
86
+ min,max = max,min if min>max
87
+
88
+ generator = -> { rand(max-min) + min }
89
+ when :bool
90
+ generator = -> { [true, false].sample }
91
+ when Array, Enumerable
92
+ generator = -> { type.to_a.sample }
93
+ when Proc
94
+ generator = type
95
+ else
96
+ raise "Unrecognized junk type: '#{type}'"
97
+ end
98
+
99
+ begin
100
+ val = generator.call
101
+ end while excluder.call(val)
102
+ val
29
103
  else
104
+ size = args.first.is_a?(Numeric) ? args.first : 32
30
105
  # hex returns size*2 digits, because it returns a 0..255 byte
31
106
  # as a hex pair. But when we want junt, we want *bytes* of
32
107
  # junk. Get (size+1)/2 chars, which will be correct for even
@@ -71,12 +71,80 @@ describe Junklet do
71
71
  end
72
72
  end
73
73
 
74
- context "with type: :decimal" do
75
- let(:junk_integer) { junk 15, type: :integer }
76
- it "returns the request number of decimal digits" do
77
- expect { (widget_id).to be_a Integer }
78
- expect { (widget_id.to_s.size).to eq(15) }
74
+ context "with type: array" do
75
+ let(:junk_ray) { junk [:a, :b, :c] }
76
+ it "returns a random element of the array" do
77
+ expect([:a, :b, :c]).to include(junk_ray)
79
78
  end
79
+
80
+ context "with excludes" do
81
+ let(:junk_ray) { junk [:a, :b, :c], exclude: [:a, :b] }
82
+ specify { expect(junk_ray).to eq(:c) }
83
+ end
84
+ end
85
+
86
+ context "with type: Proc" do
87
+ let(:junk_proc) { junk(->{ rand(3) }) }
88
+ specify { expect([0,1,2]).to include(junk_proc) }
89
+
90
+ context "with excludes" do
91
+ let(:junk_proc) { junk(->{ rand(3) }, exclude: [0,2]) }
92
+ specify { expect(junk_proc).to eq(1) }
93
+ end
94
+ end
95
+
96
+ context "with type: enumerable" do
97
+ let(:junk_list) { junk (0..3) }
98
+ it "returns a random element of the array" do
99
+ expect([0,1,2,3]).to include(junk_list)
100
+ end
101
+ end
102
+
103
+ context "with type: :int" do
104
+ let(:junk_integer) { junk :int }
105
+ it "returns a random positive Fixnum" do
106
+ expect { (junk_integer).to be_a Fixnum }
107
+ end
108
+
109
+ context "with min and max values" do
110
+ let(:coin) { junk :int, min: 0, max: 1 }
111
+ specify { expect([0,1]).to include(coin) }
112
+ end
113
+
114
+ context "with exclude proc" do
115
+ let(:junk_evens) { junk :int, min: 0, max: 10, exclude: ->(x) { x % 2 == 1 } }
116
+ specify { expect(junk_evens % 2).to eq(0) }
117
+ end
118
+ end
119
+
120
+ context "with type: :bool" do
121
+ let(:junk_bool) { junk :bool }
122
+ specify { expect([true, false]).to include(junk_bool) }
123
+
124
+ context "with excludes" do
125
+ let(:junk_bool) { junk :bool, exclude: true }
126
+ specify { expect(junk_bool).to eq(false) }
127
+ end
128
+ end
129
+
130
+ # begin
131
+ # $caught_bad_junklet_error = false
132
+ # junklet :cheesy_bad_junklet, cheese: true
133
+ # rescue INVALID_JUNKLET_ERROR => e
134
+ # raise "junklet got invalid option" unless e.message == "junklet options must be one of #{VALID_JUNKLET_ARGS.map(&:inspect) * ', '}"
135
+ # $caught_bad_junklet_error = true
136
+ # else
137
+ # raise "junklet got an invalid argument but didn't catch it" unless $caught_bad_junklet_error
138
+ # end
139
+
140
+ context "with exclude: val" do
141
+ let(:heads) { 0 }
142
+ let(:tails) { 1 }
143
+ let(:coin_heads) { junk :int, max: 1, exclude: tails }
144
+ let(:coin_tails) { junk :int, max: 1, exclude: heads }
145
+
146
+ specify { expect(coin_heads).to eq(heads) }
147
+ specify { expect(coin_tails).to eq(tails) }
80
148
  end
81
149
  end
82
150
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: junklet
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dave Brady
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-10 00:00:00.000000000 Z
11
+ date: 2015-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler