uuidtools 1.0.4 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
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