uuidtools 1.0.4 → 1.0.5

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.
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ == UUIDTools 1.0.5
2
+ * improved specs
3
+ * fixed minor bugs
4
+ * better JRuby compatibility
5
+ * uses securerandom library
6
+ * updated rake tasks
1
7
  == UUIDTools 1.0.4
2
8
  * calculates random node id with multicast bit if there is no MAC address
3
9
  * uses RSpec instead of Test::Unit
data/Rakefile CHANGED
@@ -36,7 +36,12 @@ PKG_FILES = FileList[
36
36
  "[A-Z]*", "Rakefile"
37
37
  ].exclude(/database\.yml/).exclude(/[_\.]git$/)
38
38
 
39
- task :default => "spec:verify"
39
+ RCOV_ENABLED = (RUBY_PLATFORM != "java" && RUBY_VERSION =~ /^1\.8/)
40
+ if RCOV_ENABLED
41
+ task :default => "spec:verify"
42
+ else
43
+ task :default => "spec"
44
+ end
40
45
 
41
46
  WINDOWS = (RUBY_PLATFORM =~ /mswin|win32|mingw|bccwin|cygwin/) rescue false
42
47
  SUDO = WINDOWS ? '' : ('sudo' unless ENV['SUDOLESS'])
@@ -0,0 +1,197 @@
1
+ # = Secure random number generator interface.
2
+ #
3
+ # This library is an interface for secure random number generator which is
4
+ # suitable for generating session key in HTTP cookies, etc.
5
+ #
6
+ # It supports following secure random number generators.
7
+ #
8
+ # * openssl
9
+ # * /dev/urandom
10
+ # * Win32
11
+ #
12
+ # == Example
13
+ #
14
+ # # random hexadecimal string.
15
+ # p SecureRandom.hex(10) #=> "52750b30ffbc7de3b362"
16
+ # p SecureRandom.hex(10) #=> "92b15d6c8dc4beb5f559"
17
+ # p SecureRandom.hex(11) #=> "6aca1b5c58e4863e6b81b8"
18
+ # p SecureRandom.hex(12) #=> "94b2fff3e7fd9b9c391a2306"
19
+ # p SecureRandom.hex(13) #=> "39b290146bea6ce975c37cfc23"
20
+ # ...
21
+ #
22
+ # # random base64 string.
23
+ # p SecureRandom.base64(10) #=> "EcmTPZwWRAozdA=="
24
+ # p SecureRandom.base64(10) #=> "9b0nsevdwNuM/w=="
25
+ # p SecureRandom.base64(10) #=> "KO1nIU+p9DKxGg=="
26
+ # p SecureRandom.base64(11) #=> "l7XEiFja+8EKEtY="
27
+ # p SecureRandom.base64(12) #=> "7kJSM/MzBJI+75j8"
28
+ # p SecureRandom.base64(13) #=> "vKLJ0tXBHqQOuIcSIg=="
29
+ # ...
30
+ #
31
+ # # random binary string.
32
+ # p SecureRandom.random_bytes(10) #=> "\016\t{\370g\310pbr\301"
33
+ # p SecureRandom.random_bytes(10) #=> "\323U\030TO\234\357\020\a\337"
34
+ # ...
35
+
36
+ begin
37
+ require 'openssl'
38
+ rescue LoadError
39
+ end
40
+
41
+ module SecureRandom
42
+ # SecureRandom.random_bytes generates a random binary string.
43
+ #
44
+ # The argument n specifies the length of the result string.
45
+ #
46
+ # If n is not specified, 16 is assumed.
47
+ # It may be larger in future.
48
+ #
49
+ # If secure random number generator is not available,
50
+ # NotImplementedError is raised.
51
+ def self.random_bytes(n=nil)
52
+ n ||= 16
53
+
54
+ if defined? OpenSSL::Random
55
+ return OpenSSL::Random.random_bytes(n)
56
+ end
57
+
58
+ if !defined?(@has_urandom) || @has_urandom
59
+ flags = File::RDONLY
60
+ flags |= File::NONBLOCK if defined? File::NONBLOCK
61
+ flags |= File::NOCTTY if defined? File::NOCTTY
62
+ flags |= File::NOFOLLOW if defined? File::NOFOLLOW
63
+ begin
64
+ File.open("/dev/urandom", flags) {|f|
65
+ unless f.stat.chardev?
66
+ raise Errno::ENOENT
67
+ end
68
+ @has_urandom = true
69
+ ret = f.readpartial(n)
70
+ if ret.length != n
71
+ raise NotImplementedError,
72
+ "Unexpected partial read from random device"
73
+ end
74
+ return ret
75
+ }
76
+ rescue Errno::ENOENT
77
+ @has_urandom = false
78
+ end
79
+ end
80
+
81
+ if !defined?(@has_win32)
82
+ begin
83
+ require 'Win32API'
84
+
85
+ crypt_acquire_context = Win32API.new(
86
+ "advapi32", "CryptAcquireContext", 'PPPII', 'L'
87
+ )
88
+ @crypt_gen_random = Win32API.new(
89
+ "advapi32", "CryptGenRandom", 'LIP', 'L'
90
+ )
91
+
92
+ hProvStr = " " * 4
93
+ prov_rsa_full = 1
94
+ crypt_verifycontext = 0xF0000000
95
+
96
+ if crypt_acquire_context.call(
97
+ hProvStr, nil, nil, prov_rsa_full, crypt_verifycontext) == 0
98
+ raise SystemCallError,
99
+ "CryptAcquireContext failed: #{lastWin32ErrorMessage}"
100
+ end
101
+ @hProv, = hProvStr.unpack('L')
102
+
103
+ @has_win32 = true
104
+ rescue LoadError
105
+ @has_win32 = false
106
+ end
107
+ end
108
+ if @has_win32
109
+ bytes = " " * n
110
+ if @crypt_gen_random.call(@hProv, bytes.size, bytes) == 0
111
+ raise SystemCallError,
112
+ "CryptGenRandom failed: #{lastWin32ErrorMessage}"
113
+ end
114
+ return bytes
115
+ end
116
+
117
+ raise NotImplementedError, "No random device"
118
+ end
119
+
120
+ # SecureRandom.hex generates a random hex string.
121
+ #
122
+ # The argument n specifies the length of the random length.
123
+ # The length of the result string is twice of n.
124
+ #
125
+ # If n is not specified, 16 is assumed.
126
+ # It may be larger in future.
127
+ #
128
+ # If secure random number generator is not available,
129
+ # NotImplementedError is raised.
130
+ def self.hex(n=nil)
131
+ random_bytes(n).unpack("H*")[0]
132
+ end
133
+
134
+ # SecureRandom.base64 generates a random base64 string.
135
+ #
136
+ # The argument n specifies the length of the random length.
137
+ # The length of the result string is about 4/3 of n.
138
+ #
139
+ # If n is not specified, 16 is assumed.
140
+ # It may be larger in future.
141
+ #
142
+ # If secure random number generator is not available,
143
+ # NotImplementedError is raised.
144
+ def self.base64(n=nil)
145
+ [random_bytes(n)].pack("m*").delete("\n")
146
+ end
147
+
148
+ # SecureRandom.random_number generates a random number.
149
+ #
150
+ # If an positive integer is given as n,
151
+ # SecureRandom.random_number returns an integer:
152
+ # 0 <= SecureRandom.random_number(n) < n.
153
+ #
154
+ # If 0 is given or an argument is not given,
155
+ # SecureRandom.random_number returns an float:
156
+ # 0.0 <= SecureRandom.random_number() < 1.0.
157
+ def self.random_number(n=0)
158
+ if 0 < n
159
+ hex = n.to_s(16)
160
+ hex = '0' + hex if (hex.length & 1) == 1
161
+ bin = [hex].pack("H*")
162
+ mask = bin[0].ord
163
+ mask |= mask >> 1
164
+ mask |= mask >> 2
165
+ mask |= mask >> 4
166
+ begin
167
+ rnd = SecureRandom.random_bytes(bin.length)
168
+ rnd[0] = (rnd[0].ord & mask).chr
169
+ end until rnd < bin
170
+ rnd.unpack("H*")[0].hex
171
+ else
172
+ # assumption: Float::MANT_DIG <= 64
173
+ i64 = SecureRandom.random_bytes(8).unpack("Q")[0]
174
+ Math.ldexp(i64 >> (64-Float::MANT_DIG), -Float::MANT_DIG)
175
+ end
176
+ end
177
+
178
+ # Following code is based on David Garamond's GUID library for Ruby.
179
+ def self.lastWin32ErrorMessage # :nodoc:
180
+ get_last_error = Win32API.new(
181
+ "kernel32", "GetLastError", '', 'L'
182
+ )
183
+ format_message = Win32API.new(
184
+ "kernel32", "FormatMessageA", 'LPLLPLPPPPPPPP', 'L'
185
+ )
186
+ format_message_ignore_inserts = 0x00000200
187
+ format_message_from_system = 0x00001000
188
+
189
+ code = get_last_error.call
190
+ msg = "\0" * 1024
191
+ len = format_message.call(
192
+ format_message_ignore_inserts + format_message_from_system,
193
+ 0, code, 0, msg, 1024, nil, nil, nil, nil, nil, nil, nil, nil
194
+ )
195
+ msg[0, len].tr("\r", '').chomp
196
+ end
197
+ end
@@ -31,6 +31,12 @@ require 'digest/md5'
31
31
 
32
32
  require 'uuidtools/version'
33
33
 
34
+ begin
35
+ require 'securerandom'
36
+ rescue LoadError
37
+ require File.join(File.dirname(__FILE__), 'compat', 'securerandom')
38
+ end
39
+
34
40
  #= uuidtools.rb
35
41
  #
36
42
  # UUIDTools was designed to be a simple library for generating any
@@ -47,6 +53,8 @@ require 'uuidtools/version'
47
53
  # UUID.random_create
48
54
  # => #<UUID:0x19013a UUID:984265dc-4200-4f02-ae70-fe4f48964159>
49
55
  class UUID
56
+ include Comparable
57
+
50
58
  @@last_timestamp = nil
51
59
  @@last_node_id = nil
52
60
  @@last_clock_sequence = nil
@@ -78,9 +86,9 @@ class UUID
78
86
  "Expected unsigned 8-bit number for clock_seq_low, " +
79
87
  "got #{clock_seq_low}."
80
88
  end
81
- unless nodes.respond_to? :size
82
- raise ArgumentError,
83
- "Expected nodes to respond to :size."
89
+ unless nodes.kind_of?(Enumerable)
90
+ raise TypeError,
91
+ "Expected Enumerable, got #{nodes.class.name}."
84
92
  end
85
93
  unless nodes.size == 6
86
94
  raise ArgumentError,
@@ -111,7 +119,7 @@ class UUID
111
119
  # Parses a UUID from a string.
112
120
  def self.parse(uuid_string)
113
121
  unless uuid_string.kind_of? String
114
- raise ArgumentError,
122
+ raise TypeError,
115
123
  "Expected String, got #{uuid_string.class.name} instead."
116
124
  end
117
125
  uuid_components = uuid_string.downcase.scan(
@@ -134,7 +142,7 @@ class UUID
134
142
  # Parses a UUID from a raw byte string.
135
143
  def self.parse_raw(raw_string)
136
144
  unless raw_string.kind_of? String
137
- raise ArgumentError,
145
+ raise TypeError,
138
146
  "Expected String, got #{raw_string.class.name} instead."
139
147
  end
140
148
  integer = self.convert_byte_string_to_int(raw_string)
@@ -154,7 +162,7 @@ class UUID
154
162
 
155
163
  # Creates a UUID from a random value.
156
164
  def self.random_create()
157
- new_uuid = self.parse_raw(self.random_bits)
165
+ new_uuid = self.parse_raw(SecureRandom.random_bytes(16))
158
166
  new_uuid.time_hi_and_version &= 0x0FFF
159
167
  new_uuid.time_hi_and_version |= (4 << 12)
160
168
  new_uuid.clock_seq_hi_and_reserved &= 0x3F
@@ -183,14 +191,9 @@ class UUID
183
191
  octet.to_i(16)
184
192
  end
185
193
  else
186
- nodes = self.random_bits(48).split("").map do |chr|
187
- if chr.respond_to?(:ord)
188
- # Ruby 1.9
189
- chr.ord
190
- else
191
- # Ruby 1.8
192
- chr.sum(8)
193
- end
194
+ nodes = SecureRandom.random_bytes(6).split("").map do |chr|
195
+ # Ruby 1.9 / Ruby 1.8
196
+ chr.respond_to?(:ord) ? chr.ord : chr.sum(8)
194
197
  end
195
198
  nodes[0] |= 0b00000001
196
199
  end
@@ -199,11 +202,15 @@ class UUID
199
202
  end
200
203
  clock_sequence = @@last_clock_sequence
201
204
  if clock_sequence.nil?
202
- clock_sequence = self.convert_byte_string_to_int(self.random_bits)
205
+ clock_sequence = self.convert_byte_string_to_int(
206
+ SecureRandom.random_bytes(16)
207
+ )
203
208
  end
204
209
  if @@last_node_id != nil && @@last_node_id != node_id
205
210
  # The node id has changed. Change the clock id.
206
- clock_sequence = self.convert_byte_string_to_int(self.random_bits)
211
+ clock_sequence = self.convert_byte_string_to_int(
212
+ SecureRandom.random_bytes(16)
213
+ )
207
214
  elsif @@last_timestamp != nil &&
208
215
  gmt_timestamp_100_nanoseconds <= @@last_timestamp
209
216
  clock_sequence = clock_sequence + 1
@@ -353,7 +360,7 @@ class UUID
353
360
 
354
361
  # Returns the hex digest of the UUID object.
355
362
  def hexdigest
356
- return self.to_i.to_s(16)
363
+ return self.to_i.to_s(16).rjust(32, "0")
357
364
  end
358
365
 
359
366
  # Returns the raw bytes that represent this UUID.
@@ -394,7 +401,7 @@ class UUID
394
401
 
395
402
  # Returns true if this UUID is exactly equal to the other UUID.
396
403
  def eql?(other)
397
- return (self <=> other) == 0
404
+ return self == other
398
405
  end
399
406
 
400
407
  # Returns the MAC address of the current computer's network card.
@@ -406,7 +413,7 @@ class UUID
406
413
  if os_platform =~ /win/ && !(os_platform =~ /darwin/)
407
414
  script_in_path = true
408
415
  else
409
- script_in_path = !(`which ifconfig`.strip =~ /no .+ in/)
416
+ script_in_path = Kernel.system("which ifconfig 2>&1 > /dev/null")
410
417
  end
411
418
  if os_platform =~ /solaris/
412
419
  begin
@@ -526,7 +533,9 @@ class UUID
526
533
  @@mac_address = new_mac_address
527
534
  end
528
535
 
529
- protected
536
+ # The following methods are not part of the public API,
537
+ # and generally should not be called directly.
538
+
530
539
  # Creates a new UUID from a SHA1 or MD5 hash
531
540
  def self.create_from_hash(hash_class, namespace, name) #:nodoc:
532
541
  if hash_class == Digest::MD5
@@ -551,29 +560,6 @@ protected
551
560
  return new_uuid
552
561
  end
553
562
 
554
- # N bits of unpredictable data.
555
- def self.random_bits(size=128) #:nodoc:
556
- if 128 % 16 != 0
557
- raise ArgumentError, "Value must be divisible by 16."
558
- end
559
- if !defined?(@random_device) || @random_device == nil
560
- begin
561
- @random_device = nil
562
- if File.exists? "/dev/urandom"
563
- @random_device = File.open "/dev/urandom", "r"
564
- elsif File.exists? "/dev/random"
565
- @random_device = File.open "/dev/random", "r"
566
- end
567
- rescue Exception
568
- end
569
- end
570
- begin
571
- return @random_device.read(size / 8) if @random_device != nil
572
- rescue Exception
573
- end
574
- return (1..(size / 16)).to_a.map { rand(0x10000) }.pack("n#{size / 16}")
575
- end
576
-
577
563
  def self.convert_int_to_byte_string(integer, size) #:nodoc:
578
564
  byte_string = ""
579
565
  for i in 0..(size - 1)
@@ -586,13 +572,9 @@ protected
586
572
  integer = 0
587
573
  size = byte_string.size
588
574
  for i in 0..(size - 1)
589
- if byte_string[i].respond_to?(:ord)
590
- # Ruby 1.9
591
- integer += (byte_string[i].ord << (((size - 1) - i) * 8))
592
- else
593
- # Ruby 1.8
594
- integer += (byte_string[i] << (((size - 1) - i) * 8))
595
- end
575
+ ordinal = (byte_string[i].respond_to?(:ord) ?
576
+ byte_string[i].ord : byte_string[i])
577
+ integer += (ordinal << (((size - 1) - i) * 8))
596
578
  end
597
579
  return integer
598
580
  end
@@ -602,3 +584,9 @@ UUID_DNS_NAMESPACE = UUID.parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
602
584
  UUID_URL_NAMESPACE = UUID.parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
603
585
  UUID_OID_NAMESPACE = UUID.parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
604
586
  UUID_X500_NAMESPACE = UUID.parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
587
+
588
+ at_exit do
589
+ if UUID.instance_variable_get("@random_device") != nil
590
+ UUID.instance_variable_get("@random_device").close rescue nil
591
+ end
592
+ end
@@ -21,12 +21,15 @@
21
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  #++
23
23
 
24
- class UUID
25
- module VERSION #:nodoc:
26
- MAJOR = 1
27
- MINOR = 0
28
- TINY = 4
24
+ # Used to prevent the class/module from being loaded more than once
25
+ unless defined? UUID::VERSION
26
+ class UUID
27
+ module VERSION #:nodoc:
28
+ MAJOR = 1
29
+ MINOR = 0
30
+ TINY = 5
29
31
 
30
- STRING = [MAJOR, MINOR, TINY].join('.')
32
+ STRING = [MAJOR, MINOR, TINY].join('.')
33
+ end
31
34
  end
32
35
  end
@@ -0,0 +1,17 @@
1
+ require File.join(File.dirname(__FILE__), "../spec_helper.rb")
2
+
3
+ describe UUID, "when using utility methods" do
4
+ it "should correctly obtain random bits" do
5
+ bits = []
6
+ 1000.times do
7
+ bits << SecureRandom.random_bytes(16)
8
+ end
9
+ # Check to make sure that none of the 10,000 strings were duplicates
10
+ (bits.map {|x| x.to_s}).uniq.size.should == bits.size
11
+ end
12
+
13
+ it "should return the correct number of random bits" do
14
+ SecureRandom.random_bytes(16).size.should == 16
15
+ SecureRandom.random_bytes(6).size.should == 6
16
+ end
17
+ end
@@ -14,6 +14,7 @@ describe UUID, "when generating" do
14
14
  end
15
15
 
16
16
  it "should correctly generate timestamp variant UUIDs" do
17
+ UUID.timestamp_create.should_not be_random_node_id
17
18
  UUID.timestamp_create.to_s.should_not == UUID.timestamp_create.to_s
18
19
  current_time = Time.now
19
20
  UUID.timestamp_create(current_time).to_s.should_not ==
@@ -22,16 +23,98 @@ describe UUID, "when generating" do
22
23
  1000.times do
23
24
  uuids << UUID.timestamp_create
24
25
  end
25
- # Check to make sure that none of the 10,000 UUIDs were duplicates
26
+ # Check to make sure that none of the 1,000 UUIDs were duplicates
26
27
  (uuids.map {|x| x.to_s}).uniq.size.should == uuids.size
27
28
  end
28
29
 
30
+ it "should correctly generate UUIDs without a MAC address" do
31
+ mac_address = UUID.mac_address
32
+ UUID.mac_address = nil
33
+ UUID.timestamp_create.should be_random_node_id
34
+ UUID.mac_address = mac_address
35
+ end
36
+
29
37
  it "should correctly generate random number variant UUIDs" do
30
38
  uuids = []
31
39
  1000.times do
32
40
  uuids << UUID.random_create
33
41
  end
34
- # Check to make sure that none of the 10,000 UUIDs were duplicates
42
+ # Check to make sure that none of the 1,000 UUIDs were duplicates
35
43
  (uuids.map {|x| x.to_s}).uniq.size.should == uuids.size
36
44
  end
45
+
46
+ it "should throw an exception if a segment has an invalid value" do
47
+ (lambda do
48
+ UUID.new(-1, 0, 0, 0, 0, [0, 0, 0, 0, 0, 0])
49
+ end).should raise_error(ArgumentError)
50
+ (lambda do
51
+ UUID.new(4294967296, 0, 0, 0, 0, [0, 0, 0, 0, 0, 0])
52
+ end).should raise_error(ArgumentError)
53
+ end
54
+
55
+ it "should throw an exception if a segment has an invalid value" do
56
+ (lambda do
57
+ UUID.new(0, -1, 0, 0, 0, [0, 0, 0, 0, 0, 0])
58
+ end).should raise_error(ArgumentError)
59
+ (lambda do
60
+ UUID.new(0, 65536, 0, 0, 0, [0, 0, 0, 0, 0, 0])
61
+ end).should raise_error(ArgumentError)
62
+ end
63
+
64
+ it "should throw an exception if a segment has an invalid value" do
65
+ (lambda do
66
+ UUID.new(0, 0, -1, 0, 0, [0, 0, 0, 0, 0, 0])
67
+ end).should raise_error(ArgumentError)
68
+ (lambda do
69
+ UUID.new(0, 0, 65536, 0, 0, [0, 0, 0, 0, 0, 0])
70
+ end).should raise_error(ArgumentError)
71
+ end
72
+
73
+ it "should throw an exception if a segment has an invalid value" do
74
+ (lambda do
75
+ UUID.new(0, 0, 0, -1, 0, [0, 0, 0, 0, 0, 0])
76
+ end).should raise_error(ArgumentError)
77
+ (lambda do
78
+ UUID.new(0, 0, 0, 256, 0, [0, 0, 0, 0, 0, 0])
79
+ end).should raise_error(ArgumentError)
80
+ end
81
+
82
+ it "should throw an exception if a segment has an invalid value" do
83
+ (lambda do
84
+ UUID.new(0, 0, 0, 0, -1, [0, 0, 0, 0, 0, 0])
85
+ end).should raise_error(ArgumentError)
86
+ (lambda do
87
+ UUID.new(0, 0, 0, 0, 256, [0, 0, 0, 0, 0, 0])
88
+ end).should raise_error(ArgumentError)
89
+ end
90
+
91
+ it "should throw an exception if nodes are not a collection" do
92
+ (lambda do
93
+ UUID.new(0, 0, 0, 0, 0, :bogus)
94
+ end).should raise_error(TypeError)
95
+ end
96
+
97
+ it "should throw an exception if nodes are the wrong size" do
98
+ (lambda do
99
+ UUID.new(0, 0, 0, 0, 0, [0, 0, 0, 0, 0])
100
+ end).should raise_error(ArgumentError)
101
+ end
102
+
103
+ it "should throw an exception if any nodes have invalid values" do
104
+ (lambda do
105
+ UUID.new(0, 0, 0, 0, 0, [0, 0, 0, 0, 0, 256])
106
+ end).should raise_error(ArgumentError)
107
+ end
108
+
109
+ it "should throw an exception if parsing anything but a String" do
110
+ (lambda do
111
+ UUID.parse(:bogus)
112
+ end).should raise_error(TypeError)
113
+ end
114
+
115
+ it "should throw an exception if raw parsing anything but a String" do
116
+ (lambda do
117
+ UUID.parse_raw(:bogus)
118
+ end).should raise_error(TypeError)
119
+ end
37
120
  end
@@ -33,4 +33,74 @@ describe UUID, "when parsing" do
33
33
  UUID.timestamp_create.should be_random_node_id
34
34
  UUID.mac_address = old_mac_address
35
35
  end
36
+
37
+ it "should correctly identify the nil UUID" do
38
+ UUID.new(0, 0, 0, 0, 0, [0, 0, 0, 0, 0, 0]).should be_nil_uuid
39
+ end
40
+
41
+ it "should correctly identify timestamp version UUIDs as valid" do
42
+ UUID.timestamp_create.should be_valid
43
+ end
44
+
45
+ it "should correctly identify random number version UUIDs as valid" do
46
+ UUID.random_create.should be_valid
47
+ end
48
+
49
+ it "should correctly identify SHA1 hash version UUIDs as valid" do
50
+ UUID.sha1_create(
51
+ UUID_URL_NAMESPACE, 'http://sporkmonger.com'
52
+ ).should be_valid
53
+ end
54
+
55
+ it "should correctly identify MD5 hash version UUIDs as valid" do
56
+ UUID.md5_create(
57
+ UUID_URL_NAMESPACE, 'http://sporkmonger.com'
58
+ ).should be_valid
59
+ end
60
+
61
+ it "should not identify the nil UUID as valid" do
62
+ UUID.new(0, 0, 0, 0, 0, [0, 0, 0, 0, 0, 0]).should_not be_valid
63
+ end
64
+
65
+ it "should allow for sorting of UUID arrays" do
66
+ uuids = []
67
+ 1000.times do
68
+ uuids << UUID.timestamp_create
69
+ end
70
+ uuids.sort!
71
+ uuids.first.should < uuids.last
72
+ uuids.last.should > uuids.first
73
+ end
74
+
75
+ it "should allow for comparison of UUIDs" do
76
+ UUID.new(0, 0, 0, 0, 0, [0, 0, 0, 0, 0, 0]).should <
77
+ UUID.new(0, 0, 0, 0, 0, [0, 0, 0, 0, 0, 1])
78
+ UUID.new(0, 0, 0, 0, 0, [0, 0, 0, 0, 0, 1]).should >
79
+ UUID.new(0, 0, 0, 0, 0, [0, 0, 0, 0, 0, 0])
80
+ UUID.new(0, 0, 0, 0, 0, [0, 0, 0, 0, 0, 0]).should ==
81
+ UUID.new(0, 0, 0, 0, 0, [0, 0, 0, 0, 0, 0])
82
+ end
83
+
84
+ it "should produce the correct hexdigest for a UUID" do
85
+ UUID.new(0, 0, 0, 0, 0, [0, 0, 0, 0, 0, 0]).hexdigest.should ==
86
+ "00000000000000000000000000000000"
87
+ UUID.new(1, 0, 0, 0, 0, [0, 0, 0, 0, 0, 0]).hexdigest.should ==
88
+ "00000001000000000000000000000000"
89
+ UUID.timestamp_create.hexdigest.size.should == 32
90
+ end
91
+
92
+ it "should produce a sane hash value for a UUID" do
93
+ UUID.new(0, 0, 0, 0, 0, [0, 0, 0, 0, 0, 0]).hash.should == 0
94
+ end
95
+
96
+ it "should produce the correct URI for a UUID" do
97
+ UUID.new(0, 0, 0, 0, 0, [0, 0, 0, 0, 0, 0]).to_uri.should ==
98
+ "urn:uuid:00000000-0000-0000-0000-000000000000"
99
+ end
100
+
101
+ it "should correctly test UUID equality" do
102
+ UUID.new(0, 0, 0, 0, 0, [0, 0, 0, 0, 0, 0]).should be_eql(
103
+ UUID.new(0, 0, 0, 0, 0, [0, 0, 0, 0, 0, 0])
104
+ )
105
+ end
36
106
  end
@@ -2,6 +2,11 @@ require "rake/gempackagetask"
2
2
 
3
3
  namespace :gem do
4
4
  GEM_SPEC = Gem::Specification.new do |s|
5
+ unless s.respond_to?(:add_development_dependency)
6
+ puts "The gem spec requires a newer version of RubyGems."
7
+ exit(1)
8
+ end
9
+
5
10
  s.name = PKG_NAME
6
11
  s.version = PKG_VERSION
7
12
  s.summary = PKG_SUMMARY
@@ -13,8 +18,9 @@ namespace :gem do
13
18
  s.extra_rdoc_files = %w( README )
14
19
  s.rdoc_options.concat ["--main", "README"]
15
20
 
16
- s.add_dependency("rake", ">= 0.7.3")
17
- s.add_dependency("rspec", ">= 1.0.8")
21
+ s.add_development_dependency("rake", ">= 0.8.3")
22
+ s.add_development_dependency("rspec", ">= 1.1.11")
23
+ s.add_development_dependency("launchy", ">= 0.3.2")
18
24
 
19
25
  s.require_path = "lib"
20
26
 
@@ -1,9 +1,8 @@
1
- require 'rubyforge'
2
- require 'rake/contrib/sshpublisher'
3
-
4
1
  namespace :gem do
5
2
  desc 'Package and upload to RubyForge'
6
3
  task :release => ["gem:package"] do |t|
4
+ require 'rubyforge'
5
+
7
6
  v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
8
7
  abort "Versions don't match #{v} vs #{PROJ.version}" if v != PKG_VERSION
9
8
  pkg = "pkg/#{GEM_SPEC.full_name}"
@@ -28,6 +27,9 @@ end
28
27
  namespace :doc do
29
28
  desc "Publish RDoc to RubyForge"
30
29
  task :release => ["doc:rdoc"] do
30
+ require "rake/contrib/sshpublisher"
31
+ require "yaml"
32
+
31
33
  config = YAML.load(
32
34
  File.read(File.expand_path('~/.rubyforge/user-config.yml'))
33
35
  )
@@ -41,6 +43,9 @@ end
41
43
  namespace :spec do
42
44
  desc "Publish specdoc to RubyForge"
43
45
  task :release => ["spec:specdoc"] do
46
+ require "rake/contrib/sshpublisher"
47
+ require "yaml"
48
+
44
49
  config = YAML.load(
45
50
  File.read(File.expand_path('~/.rubyforge/user-config.yml'))
46
51
  )
@@ -53,6 +58,9 @@ namespace :spec do
53
58
  namespace :rcov do
54
59
  desc "Publish coverage report to RubyForge"
55
60
  task :release => ["spec:rcov"] do
61
+ require "rake/contrib/sshpublisher"
62
+ require "yaml"
63
+
56
64
  config = YAML.load(
57
65
  File.read(File.expand_path('~/.rubyforge/user-config.yml'))
58
66
  )
@@ -67,6 +75,9 @@ end
67
75
  namespace :website do
68
76
  desc "Publish website to RubyForge"
69
77
  task :release => ["doc:release", "spec:release", "spec:rcov:release"] do
78
+ require "rake/contrib/sshpublisher"
79
+ require "yaml"
80
+
70
81
  config = YAML.load(
71
82
  File.read(File.expand_path('~/.rubyforge/user-config.yml'))
72
83
  )
@@ -4,20 +4,33 @@ namespace :spec do
4
4
  Spec::Rake::SpecTask.new(:rcov) do |t|
5
5
  t.spec_files = FileList['spec/**/*_spec.rb']
6
6
  t.spec_opts = ['--color', '--format', 'specdoc']
7
- t.rcov = true
7
+ if RCOV_ENABLED
8
+ t.rcov = true
9
+ else
10
+ t.rcov = false
11
+ end
8
12
  t.rcov_opts = [
9
13
  '--exclude', 'spec',
10
14
  '--exclude', '1\\.8\\/gems',
11
- '--exclude', '1\\.9\\/gems'
15
+ '--exclude', '1\\.9\\/gems',
16
+ '--exclude', 'addressable\\/idna\\.rb', # unicode tables too big
12
17
  ]
13
18
  end
14
19
 
15
- RCov::VerifyTask.new(:verify) do |t|
16
- t.threshold = 100.0
17
- t.index_html = 'coverage/index.html'
20
+ Spec::Rake::SpecTask.new(:normal) do |t|
21
+ t.spec_files = FileList['spec/**/*_spec.rb']
22
+ t.spec_opts = ['--color', '--format', 'specdoc']
23
+ t.rcov = false
18
24
  end
19
25
 
20
- task :verify => :rcov
26
+ if RCOV_ENABLED
27
+ RCov::VerifyTask.new(:verify) do |t|
28
+ t.threshold = 100.0
29
+ t.index_html = 'coverage/index.html'
30
+ end
31
+
32
+ task :verify => :rcov
33
+ end
21
34
 
22
35
  desc "Generate HTML Specdocs for all specs"
23
36
  Spec::Rake::SpecTask.new(:specdoc) do |t|
@@ -34,56 +47,18 @@ namespace :spec do
34
47
  namespace :rcov do
35
48
  desc "Browse the code coverage report."
36
49
  task :browse => "spec:rcov" do
37
- Rake.browse("coverage/index.html")
50
+ require "launchy"
51
+ Launchy::Browser.run("coverage/index.html")
38
52
  end
39
53
  end
40
54
  end
41
55
 
42
- desc "Alias to spec:verify"
43
- task "spec" => "spec:verify"
56
+ if RCOV_ENABLED
57
+ desc "Alias to spec:verify"
58
+ task "spec" => "spec:verify"
59
+ else
60
+ desc "Alias to spec:normal"
61
+ task "spec" => "spec:normal"
62
+ end
44
63
 
45
64
  task "clobber" => ["spec:clobber_rcov"]
46
-
47
- module Rake
48
- def self.browse(filepath)
49
- if RUBY_PLATFORM =~ /mswin/
50
- system(filepath)
51
- else
52
- try_browsers = lambda do
53
- result = true
54
- if !(`which firefox 2>&1` =~ /no firefox/)
55
- system("firefox #{filepath}")
56
- elsif !(`which mozilla 2>&1` =~ /no mozilla/)
57
- system("mozilla #{filepath}")
58
- elsif !(`which netscape 2>&1` =~ /no netscape/)
59
- system("netscape #{filepath}")
60
- elsif !(`which links 2>&1` =~ /no links/)
61
- system("links #{filepath}")
62
- elsif !(`which lynx 2>&1` =~ /no lynx/)
63
- system("lynx #{filepath}")
64
- else
65
- result = false
66
- end
67
- result
68
- end
69
- opened = false
70
- if RUBY_PLATFORM =~ /darwin/
71
- opened = true
72
- system("open #{filepath}")
73
- elsif !(`which gnome-open 2>&1` =~ /no gnome-open/)
74
- success =
75
- !(`gnome-open #{filepath} 2>&1` =~ /There is no default action/)
76
- if !success
77
- opened = try_browsers.call()
78
- else
79
- opened = true
80
- end
81
- else
82
- opened = try_browsers.call()
83
- end
84
- if !opened
85
- puts "Don't know how to browse to location."
86
- end
87
- end
88
- end
89
- end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uuidtools
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bob Aman
@@ -9,28 +9,38 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-09-29 00:00:00 -04:00
12
+ date: 2008-12-01 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
17
- type: :runtime
17
+ type: :development
18
18
  version_requirement:
19
19
  version_requirements: !ruby/object:Gem::Requirement
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 0.7.3
23
+ version: 0.8.3
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- type: :runtime
27
+ type: :development
28
28
  version_requirement:
29
29
  version_requirements: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 1.0.8
33
+ version: 1.1.11
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: launchy
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 0.3.2
34
44
  version:
35
45
  description: A simple universally unique ID generation library.
36
46
  email: bob@sporkmonger.com
@@ -41,6 +51,8 @@ extensions: []
41
51
  extra_rdoc_files:
42
52
  - README
43
53
  files:
54
+ - lib/compat
55
+ - lib/compat/securerandom.rb
44
56
  - lib/uuidtools
45
57
  - lib/uuidtools/version.rb
46
58
  - lib/uuidtools.rb
@@ -48,6 +60,7 @@ files:
48
60
  - spec/spec_helper.rb
49
61
  - spec/uuidtools
50
62
  - spec/uuidtools/mac_address_spec.rb
63
+ - spec/uuidtools/utility_spec.rb
51
64
  - spec/uuidtools/uuid_creation_spec.rb
52
65
  - spec/uuidtools/uuid_parsing_spec.rb
53
66
  - tasks/benchmark.rake
@@ -86,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
99
  requirements: []
87
100
 
88
101
  rubyforge_project: uuidtools
89
- rubygems_version: 1.2.0
102
+ rubygems_version: 1.3.1
90
103
  signing_key:
91
104
  specification_version: 2
92
105
  summary: UUID generator