~ubuntu-branches/ubuntu/quantal/ruby1.9.1/quantal

« back to all changes in this revision

Viewing changes to test/test_securerandom.rb

  • Committer: Bazaar Package Importer
  • Author(s): Lucas Nussbaum
  • Date: 2011-09-24 19:16:17 UTC
  • mfrom: (1.1.8 upstream) (13.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20110924191617-o1qz4rcmqjot8zuy
Tags: 1.9.3~rc1-1
* New upstream release: 1.9.3 RC1.
  + Includes load.c fixes. Closes: #639959.
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
require 'test/unit'
 
2
require 'securerandom'
 
3
require 'tempfile'
 
4
 
 
5
# This testcase does NOT aim to test cryptographically strongness and randomness.
 
6
class TestSecureRandom < Test::Unit::TestCase
 
7
  def setup
 
8
    @it = SecureRandom
 
9
  end
 
10
 
 
11
  def test_s_random_bytes
 
12
    assert_equal(16, @it.random_bytes.size)
 
13
    assert_equal(Encoding::ASCII_8BIT, @it.random_bytes.encoding)
 
14
    65.times do |idx|
 
15
      assert_equal(idx, @it.random_bytes(idx).size)
 
16
    end
 
17
  end
 
18
 
 
19
# This test took 2 minutes on my machine.
 
20
# And 65536 times loop could not be enough for forcing PID recycle.
 
21
if false
 
22
  def test_s_random_bytes_is_fork_safe
 
23
    begin
 
24
      require 'openssl'
 
25
    rescue LoadError
 
26
      return
 
27
    end
 
28
    SecureRandom.random_bytes(8)
 
29
    pid, v1 = forking_random_bytes
 
30
    assert(check_forking_random_bytes(pid, v1), 'Process ID not recycled?')
 
31
  end
 
32
 
 
33
  def forking_random_bytes
 
34
    r, w = IO.pipe
 
35
    pid = fork {
 
36
      r.close
 
37
      w.write SecureRandom.random_bytes(8)
 
38
      w.close
 
39
    }
 
40
    w.close
 
41
    v = r.read(8)
 
42
    r.close
 
43
    Process.waitpid2(pid)
 
44
    [pid, v]
 
45
  end
 
46
 
 
47
  def check_forking_random_bytes(target_pid, target)
 
48
    65536.times do
 
49
      pid = fork {
 
50
        if $$ == target_pid
 
51
          v2 = SecureRandom.random_bytes(8)
 
52
          if v2 == target
 
53
            exit(1)
 
54
          else
 
55
            exit(2)
 
56
          end
 
57
        end
 
58
        exit(3)
 
59
      }
 
60
      pid, status = Process.waitpid2(pid)
 
61
      case status.exitstatus
 
62
      when 1
 
63
        raise 'returned same sequence for same PID'
 
64
      when 2
 
65
        return true
 
66
      end
 
67
    end
 
68
    false # not recycled?
 
69
  end
 
70
end
 
71
 
 
72
  def test_s_random_bytes_without_openssl
 
73
    begin
 
74
      require 'openssl'
 
75
    rescue LoadError
 
76
      return
 
77
    end
 
78
    begin
 
79
      load_path = $LOAD_PATH.dup
 
80
      loaded_features = $LOADED_FEATURES.dup
 
81
      openssl = Object.instance_eval { remove_const(:OpenSSL) }
 
82
 
 
83
      remove_feature('securerandom.rb')
 
84
      remove_feature('openssl.rb')
 
85
      Dir.mktmpdir do |dir|
 
86
        open(File.join(dir, 'openssl.rb'), 'w') { |f|
 
87
          f << 'raise LoadError'
 
88
        }
 
89
        $LOAD_PATH.unshift(dir)
 
90
        require 'securerandom'
 
91
        test_s_random_bytes
 
92
      end
 
93
    ensure
 
94
      $LOADED_FEATURES.replace(loaded_features)
 
95
      $LOAD_PATH.replace(load_path)
 
96
      Object.const_set(:OpenSSL, openssl)
 
97
    end
 
98
  end
 
99
 
 
100
  def test_s_hex
 
101
    assert_equal(16 * 2, @it.hex.size)
 
102
    33.times do |idx|
 
103
      assert_equal(idx * 2, @it.hex(idx).size)
 
104
      assert_equal(idx, @it.hex(idx).gsub(/(..)/) { [$1].pack('H*') }.size)
 
105
    end
 
106
  end
 
107
 
 
108
  def test_s_base64
 
109
    assert_equal(16, @it.base64.unpack('m*')[0].size)
 
110
    17.times do |idx|
 
111
      assert_equal(idx, @it.base64(idx).unpack('m*')[0].size)
 
112
    end
 
113
  end
 
114
 
 
115
  def test_s_urlsafe_base64
 
116
    safe = /[\n+\/]/
 
117
    65.times do |idx|
 
118
      assert_not_match(safe, @it.urlsafe_base64(idx))
 
119
    end
 
120
    # base64 can include unsafe byte
 
121
    10001.times do |idx|
 
122
      return if safe =~ @it.base64(idx)
 
123
    end
 
124
    flunk
 
125
  end
 
126
 
 
127
  def test_s_random_number_float
 
128
    101.times do
 
129
      v = @it.random_number
 
130
      assert(0.0 <= v && v < 1.0)
 
131
    end
 
132
  end
 
133
 
 
134
  def test_s_random_number_float_by_zero
 
135
    101.times do
 
136
      v = @it.random_number(0)
 
137
      assert(0.0 <= v && v < 1.0)
 
138
    end
 
139
  end
 
140
 
 
141
  def test_s_random_number_int
 
142
    101.times do |idx|
 
143
      next if idx.zero?
 
144
      v = @it.random_number(idx)
 
145
      assert(0 <= v && v < idx)
 
146
    end
 
147
  end
 
148
 
 
149
  def test_uuid
 
150
    uuid = @it.uuid
 
151
    assert_equal(36, uuid.size)
 
152
    uuid.unpack('a8xa4xa4xa4xa12').each do |e|
 
153
      assert_match(/^[0-9a-f]+$/, e)
 
154
    end
 
155
  end
 
156
 
 
157
  def protect
 
158
    begin
 
159
      yield
 
160
    rescue NotImplementedError
 
161
      # ignore
 
162
    end
 
163
  end
 
164
 
 
165
  def remove_feature(basename)
 
166
    $LOADED_FEATURES.delete_if { |path|
 
167
      if File.basename(path) == basename
 
168
        $LOAD_PATH.any? { |dir|
 
169
          File.exists?(File.join(dir, basename))
 
170
        }
 
171
      end
 
172
    }
 
173
  end
 
174
 
 
175
end