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 +8 -8
- data/Gemfile.lock +1 -1
- data/README.md +43 -0
- data/lib/junklet/version.rb +1 -1
- data/lib/junklet.rb +83 -8
- data/spec/lib/junklet_spec.rb +73 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
Zjc3YzlmNzVjYTc3YmZhNTIwZjZlNTE4Y2I1ZTQ2YWM0ZmNmODk3ZQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NTI1YTRjZWJkMmFiMmI3ZWNhOGM2NTBhNDRkZmNjYWZiMzJjNGM4ZQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
OGM0ZDRjYTkxYjdhNTdlNzA5YTM3MjU5MGEyZDk3ZWQwYTQ0YjU5NjczMGE2
|
10
|
+
ZGU0NmIxNjk4ZDc1Yzg5NDAxOTU2NTM4NmJlNTE3NjIwMmM4NWZhMDM2MTNk
|
11
|
+
OTFmN2FiNjAwMThiYTBlNTFkYTM3M2I4NjE5NDQzMDZiZjIxZjk=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
OWIxNDM5ZGUyOWRhODg1YmM5NDFiMWZhMjNjNGY0MTRlZGQ1ZDNmY2JhNGJh
|
14
|
+
Nzk5MzVlZTk4NDJhYWIwM2E0ZDUyNmI1NzEyZGQ2NGIyYjM0M2VhOWM5YTAx
|
15
|
+
MmJiNTg0MGY3ZDY2NGNlNjJlYTU4NmViMmM2OWY5ZmNjZjlhYmU=
|
data/Gemfile.lock
CHANGED
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
|
data/lib/junklet/version.rb
CHANGED
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(
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
data/spec/lib/junklet_spec.rb
CHANGED
@@ -71,12 +71,80 @@ describe Junklet do
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
context "with type:
|
75
|
-
let(:
|
76
|
-
it "returns
|
77
|
-
expect
|
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.
|
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-
|
11
|
+
date: 2015-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|