lazy-uuid 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ module LazyUuid
2
+ VERSION = '0.5.0'
3
+ end
@@ -0,0 +1,43 @@
1
+ require 'securerandom'
2
+ require 'lazy-uuid/uuid'
3
+
4
+ FactoryGirl.define do
5
+ factory :uuid_str, class: String do
6
+ trait :no_dashes do
7
+ after(:build) do |uuid_str|
8
+ uuid_str.delete!('-')
9
+ end
10
+ end
11
+
12
+ initialize_with { SecureRandom.uuid }
13
+ end
14
+
15
+ factory :uuid_value, class: String do
16
+ transient do
17
+ association :source, :factory => :uuid_str, :strategy => :build
18
+ end
19
+
20
+ initialize_with { source.delete('-').scan(/../).map(&:hex).pack('C*') }
21
+ end
22
+
23
+ factory :uuid, class: Uuid do
24
+ transient do
25
+ source nil
26
+ end
27
+
28
+ initialize_with do
29
+ case source
30
+ when nil
31
+ Uuid.generate
32
+ when Uuid
33
+ Uuid.new(source.value)
34
+ else
35
+ if source.length == 16
36
+ Uuid.new(source)
37
+ else
38
+ Uuid.new(build(:uuid_value, :source => source))
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,85 @@
1
+ if RUBY_PLATFORM != 'java'
2
+ # Code Climate test coverage.
3
+ begin
4
+ require 'codeclimate-test-reporter'
5
+ CodeClimate::TestReporter.start
6
+ rescue
7
+ # Continue without Code Climate test coverage.
8
+ end
9
+ end
10
+
11
+ require 'rspec'
12
+ require 'factory_girl'
13
+
14
+ RSpec.configure do |config|
15
+ # rspec-expectations config goes here. You can use an alternate
16
+ # assertion/expectation library such as wrong or the stdlib/minitest
17
+ # assertions if you prefer.
18
+ config.expect_with :rspec do |expectations|
19
+ # This option will default to `true` in RSpec 4. It makes the `description`
20
+ # and `failure_message` of custom matchers include text for helper methods
21
+ # defined using `chain`, e.g.:
22
+ # be_bigger_than(2).and_smaller_than(4).description
23
+ # # => "be bigger than 2 and smaller than 4"
24
+ # ...rather than:
25
+ # # => "be bigger than 2"
26
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
27
+ end
28
+
29
+ # rspec-mocks config goes here. You can use an alternate test double
30
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
31
+ config.mock_with :rspec do |mocks|
32
+ # Prevents you from mocking or stubbing a method that does not exist on
33
+ # a real object. This is generally recommended, and will default to
34
+ # `true` in RSpec 4.
35
+ mocks.verify_partial_doubles = true
36
+ end
37
+
38
+ # Allows RSpec to persist some state between runs in order to support
39
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
40
+ # you configure your source control system to ignore this file.
41
+ config.example_status_persistence_file_path = 'spec/examples.txt'
42
+
43
+ # Limits the available syntax to the non-monkey patched syntax that is
44
+ # recommended. For more details, see:
45
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
46
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
47
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
48
+ config.disable_monkey_patching!
49
+
50
+ # This setting enables warnings. It's recommended, but in some cases may
51
+ # be too noisy due to issues in dependencies.
52
+ config.warnings = true
53
+
54
+ # Many RSpec users commonly either run the entire suite or an individual
55
+ # file, and it's useful to allow more verbose output when running an
56
+ # individual spec file.
57
+ if config.files_to_run.one?
58
+ # Use the documentation formatter for detailed output,
59
+ # unless a formatter has already been configured
60
+ # (e.g. via a command-line flag).
61
+ config.default_formatter = 'doc'
62
+ end
63
+
64
+ # Run specs in random order to surface order dependencies. If you find an
65
+ # order dependency and want to debug it, you can fix the order by providing
66
+ # the seed, which is printed after each run.
67
+ # --seed 1234
68
+ config.order = :random
69
+
70
+ # Seed global randomization in this process using the `--seed` CLI option.
71
+ # Setting this allows you to use `--seed` to deterministically reproduce
72
+ # test failures related to randomization by passing the same `--seed` value
73
+ # as the one that triggered the failure.
74
+ Kernel.srand config.seed
75
+
76
+ # Include FactoryGirl for building test objects.
77
+ config.include FactoryGirl::Syntax::Methods
78
+ end
79
+
80
+ # Include the library.
81
+ require_relative '../lib/lazy-uuid'
82
+
83
+ # Include factories.
84
+ FactoryGirl.definition_file_paths << File.join(File.dirname(__FILE__), 'factories')
85
+ FactoryGirl.find_definitions
@@ -0,0 +1,457 @@
1
+ require_relative 'spec_helper'
2
+
3
+ RSpec::Matchers.define :be_a_valid_uuid_string do
4
+ match do |actual|
5
+ !!/^\A[0-9a-f]{8}(-?)[0-9a-f]{4}\1[1-5][0-9a-f]{3}\1[89ab][0-9a-f]{3}\1[0-9a-f]{12}\z$/i.match(actual)
6
+ end
7
+
8
+ description do
9
+ 'be a valid UUID string'
10
+ end
11
+
12
+ failure_message do |actual|
13
+ "expected that #{actual} would be a valid UUID string"
14
+ end
15
+
16
+ failure_message_when_negated do |actual|
17
+ "expected that #{actual} would not be a valid UUID string"
18
+ end
19
+ end
20
+
21
+ RSpec.describe Uuid do
22
+
23
+ describe '::DEFAULT' do
24
+ subject { Uuid::DEFAULT }
25
+
26
+ it 'is all zeroes' do
27
+ is_expected.to eq("\x0" * 16)
28
+ end
29
+
30
+ it 'is frozen' do
31
+ is_expected.to be_frozen
32
+ end
33
+ end
34
+
35
+ describe '#initialize' do
36
+ context 'with a valid value' do
37
+ let(:uuid_value) { build(:uuid_value) }
38
+ subject(:uuid) { described_class.new(uuid_value) }
39
+
40
+ describe 'the value' do
41
+ subject { uuid.value }
42
+
43
+ it 'is stored' do
44
+ is_expected.to eq uuid_value
45
+ end
46
+ end
47
+ end
48
+
49
+ context 'with an invalid value' do
50
+ let(:uuid_value) { 'foobar' }
51
+
52
+ it 'throws an ArgumentError' do
53
+ expect { subject }.to raise_error(ArgumentError)
54
+ end
55
+ end
56
+ end
57
+
58
+ describe '.generate' do
59
+ subject(:uuid) { described_class.generate }
60
+
61
+ describe 'the value' do
62
+ subject { uuid.value }
63
+
64
+ # The UUID standards don't allow generated UUID to be all zeroes.
65
+ it 'is not DEFAULT' do
66
+ is_expected.to_not eq("\x0" * 16)
67
+ end
68
+
69
+ # The chances of two randomly generated UUIDs being identical is virtually impossible.
70
+ it 'is random' do
71
+ other = build(:uuid)
72
+ is_expected.to_not eq other
73
+ end
74
+ end
75
+
76
+ describe 'the string' do
77
+ subject { uuid.to_s }
78
+
79
+ it 'is valid' do
80
+ is_expected.to be_a_valid_uuid_string
81
+ end
82
+ end
83
+ end
84
+
85
+ describe '.parse' do
86
+ subject { described_class.parse(uuid_str) }
87
+
88
+ context 'with a valid argument' do
89
+ context 'with dashes' do
90
+ let(:uuid_str) { build(:uuid_str) }
91
+
92
+ it 'parses correctly' do
93
+ is_expected.to eq uuid_str
94
+ end
95
+ end
96
+
97
+ context 'without dashes' do
98
+ let(:uuid_str) { build(:uuid_str, :no_dashes) }
99
+
100
+ it 'parses correctly' do
101
+ is_expected.to eq uuid_str
102
+ end
103
+ end
104
+ end
105
+
106
+ context 'with a malformed string' do
107
+ let(:uuid_str) { 'foobar' }
108
+
109
+ it 'returns nil' do
110
+ is_expected.to be_nil
111
+ end
112
+ end
113
+
114
+ context 'with an invalid argument' do
115
+ let(:uuid_str) { 5 }
116
+
117
+ it 'raises an ArgumentError' do
118
+ expect { subject }.to raise_error(ArgumentError)
119
+ end
120
+ end
121
+
122
+ context 'with newlines' do
123
+ let(:uuid_str) { "\n" + build(:uuid_str) + "\n" }
124
+
125
+ it 'returns nil' do
126
+ is_expected.to be_nil
127
+ end
128
+ end
129
+ end
130
+
131
+ describe '#value' do
132
+ let(:uuid) { build(:uuid) }
133
+ subject(:value) { uuid.value }
134
+
135
+ it 'is a string' do
136
+ is_expected.to be_a String
137
+ end
138
+
139
+ it 'is frozen' do
140
+ is_expected.to be_frozen
141
+ end
142
+
143
+ it 'is 16 bytes' do
144
+ expect(value.length).to be 16
145
+ end
146
+ end
147
+
148
+ describe '#eql?' do
149
+ let(:uuid) { build(:uuid) }
150
+ subject { uuid.eql?(other) }
151
+
152
+ context 'with two identical UUIDs' do
153
+ let(:other) { build(:uuid, :source => uuid) }
154
+
155
+ it 'returns true' do
156
+ is_expected.to eq true
157
+ end
158
+ end
159
+
160
+ context 'with two different UUIDs' do
161
+ let(:other) { build(:uuid) }
162
+
163
+ it 'returns false' do
164
+ is_expected.to eq false
165
+ end
166
+ end
167
+
168
+ context 'without a UUID' do
169
+ let(:other) { 'foobar' }
170
+
171
+ it 'returns false' do
172
+ is_expected.to eq false
173
+ end
174
+ end
175
+ end
176
+
177
+ describe '#==' do
178
+ let(:uuid) { build(:uuid) }
179
+ subject { uuid == other }
180
+
181
+ context 'with equal UUIDs' do
182
+ let(:other) { build(:uuid, :source => uuid) }
183
+
184
+ it 'is true' do
185
+ is_expected.to be true
186
+ end
187
+ end
188
+
189
+ context 'with the same instance' do
190
+ let(:other) { uuid }
191
+
192
+ it 'is true' do
193
+ is_expected.to be true
194
+ end
195
+ end
196
+
197
+ context 'with unequal UUIDs' do
198
+ let(:other) { build(:uuid) }
199
+
200
+ it 'is false' do
201
+ is_expected.to be false
202
+ end
203
+ end
204
+
205
+ context 'with nil' do
206
+ let(:other) { nil }
207
+
208
+ it 'is false' do
209
+ is_expected.to be false
210
+ end
211
+ end
212
+
213
+ context 'with a malformed string' do
214
+ let(:other) { 'foobar' }
215
+
216
+ it 'is false' do
217
+ is_expected.to be false
218
+ end
219
+ end
220
+
221
+ context 'with a non-string' do
222
+ let(:other) { 5 }
223
+
224
+ it 'is false' do
225
+ is_expected.to be false
226
+ end
227
+ end
228
+
229
+ context 'with identical value' do
230
+ let(:other) { uuid.value }
231
+
232
+ it 'is true' do
233
+ is_expected.to be true
234
+ end
235
+ end
236
+
237
+ context 'with identical string' do
238
+ let(:other) { uuid.to_s }
239
+
240
+ it 'is true' do
241
+ is_expected.to be true
242
+ end
243
+ end
244
+ end
245
+
246
+ describe '#<=>' do
247
+ let(:lesser) { 'de305d54-75b4-431b-adb2-eb6b9e546014' }
248
+ let(:greater) { 'de305d54-75b4-431b-adb2-eb6b9e546020' }
249
+ subject { first <=> second }
250
+
251
+ context 'with an equal UUID' do
252
+ let(:first) { build(:uuid) }
253
+ let(:second) { build(:uuid, :source => first) }
254
+
255
+ it 'is 0' do
256
+ is_expected.to eq 0
257
+ end
258
+ end
259
+
260
+ context 'with the same instance' do
261
+ let(:first) { build(:uuid) }
262
+ let(:second) { first }
263
+
264
+ it 'is 0' do
265
+ is_expected.to eq 0
266
+ end
267
+ end
268
+
269
+ context 'with a lesser UUID' do
270
+ let(:first) { build(:uuid, :source => greater) }
271
+ let(:second) { build(:uuid, :source => lesser) }
272
+
273
+ it 'is 1' do
274
+ is_expected.to eq 1
275
+ end
276
+ end
277
+
278
+ context 'with a greater UUID' do
279
+ let(:first) { build(:uuid, :source => lesser) }
280
+ let(:second) { build(:uuid, :source => greater) }
281
+
282
+ it 'is -1' do
283
+ is_expected.to eq(-1)
284
+ end
285
+ end
286
+
287
+ context 'with nil' do
288
+ let(:first) { build(:uuid) }
289
+ let(:second) { nil }
290
+
291
+ it 'is nil' do
292
+ is_expected.to be_nil
293
+ end
294
+ end
295
+
296
+ context 'with a number' do
297
+ let(:first) { build(:uuid) }
298
+ let(:second) { 500 }
299
+
300
+ it 'is nil' do
301
+ is_expected.to be_nil
302
+ end
303
+ end
304
+
305
+ context 'with an identical value' do
306
+ let(:first) { build(:uuid) }
307
+ let(:second) { first.value }
308
+
309
+ it 'is 0' do
310
+ is_expected.to eq 0
311
+ end
312
+ end
313
+
314
+ context 'with a lesser value' do
315
+ let(:first) { build(:uuid, :source => greater) }
316
+ let(:second) { build(:uuid_value, :source => lesser) }
317
+
318
+ it 'is 1' do
319
+ is_expected.to eq 1
320
+ end
321
+ end
322
+
323
+ context 'with a greater value' do
324
+ let(:first) { build(:uuid, :source => lesser) }
325
+ let(:second) { build(:uuid_value, :source => greater) }
326
+
327
+ it 'is -1' do
328
+ is_expected.to eq(-1)
329
+ end
330
+ end
331
+
332
+ context 'with an equal string' do
333
+ let(:first) { build(:uuid) }
334
+ let(:second) { first.to_s }
335
+
336
+ it 'is 0' do
337
+ is_expected.to eq 0
338
+ end
339
+ end
340
+
341
+ context 'with a lesser string' do
342
+ let(:first) { build(:uuid, :source => greater) }
343
+ let(:second) { lesser }
344
+
345
+ it 'is 1' do
346
+ is_expected.to eq 1
347
+ end
348
+ end
349
+
350
+ context 'with a greater string' do
351
+ let(:first) { build(:uuid, :source => lesser) }
352
+ let(:second) { greater }
353
+
354
+ it 'is -1' do
355
+ is_expected.to eq(-1)
356
+ end
357
+ end
358
+
359
+ context 'with an invalid string' do
360
+ let(:first) { build(:uuid) }
361
+ let(:second) { 'foobar' }
362
+
363
+ it 'is nil' do
364
+ is_expected.to be_nil
365
+ end
366
+ end
367
+ end
368
+
369
+ describe '#hash' do
370
+ let(:uuid) { build(:uuid) }
371
+ subject { uuid.hash }
372
+
373
+ it 'is a Fixnum' do
374
+ is_expected.to be_a Fixnum
375
+ end
376
+
377
+ context 'with identical UUIDs' do
378
+ let(:first) { build(:uuid) }
379
+ let(:second) { build(:uuid, :source => first) }
380
+
381
+ it 'returns identical values' do
382
+ expect(first.hash).to eq(second.hash)
383
+ end
384
+ end
385
+
386
+ context 'with different UUIDs' do
387
+ let(:first) { build(:uuid) }
388
+ let(:second) { build(:uuid) }
389
+
390
+ it 'returns different values' do
391
+ expect(first.hash).to_not eq(second.hash)
392
+ end
393
+ end
394
+ end
395
+
396
+ describe '#to_s' do
397
+ let(:uuid_str) { build(:uuid_str) }
398
+ let(:uuid) { build(:uuid, :source => uuid_str) }
399
+ subject { uuid.to_s }
400
+
401
+ it 'is a String' do
402
+ is_expected.to be_a String
403
+ end
404
+
405
+ it 'is a valid UUID string' do
406
+ is_expected.to be_a_valid_uuid_string
407
+ end
408
+
409
+ it 'equals the initial value' do
410
+ is_expected.to eq uuid_str
411
+ end
412
+
413
+ it 'contains dashes' do
414
+ is_expected.to include '-'
415
+ end
416
+
417
+ context 'with bytes less than 16' do
418
+ let(:uuid_str) { '05305d54-7502-431b-adb2-eb6b9e546000' }
419
+ let(:uuid) { build(:uuid, :source => uuid_str) }
420
+
421
+ it 'pads with zeroes' do
422
+ is_expected.to eq uuid_str
423
+ end
424
+ end
425
+
426
+ context 'with dashes set to false' do
427
+ let(:uuid_str) { build(:uuid_str, :no_dashes) }
428
+ subject { uuid.to_s(false) }
429
+
430
+ it 'is a String' do
431
+ is_expected.to be_a String
432
+ end
433
+
434
+ it 'is a valid UUID string' do
435
+ is_expected.to be_a_valid_uuid_string
436
+ end
437
+
438
+ it 'equals the initial value' do
439
+ is_expected.to eq uuid_str
440
+ end
441
+
442
+ it 'does not contain dashes' do
443
+ is_expected.not_to include '-'
444
+ end
445
+
446
+ context 'with bytes less than 16' do
447
+ let(:uuid_str) { '05305d547502431badb2eb6b9e546000' }
448
+ let(:uuid) { build(:uuid, :source => uuid_str) }
449
+
450
+ it 'pads with zeroes' do
451
+ is_expected.to eq uuid_str
452
+ end
453
+ end
454
+ end
455
+ end
456
+
457
+ end