mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	 b0e40509c3
			
		
	
	
		b0e40509c3
		
	
	
	
	
		
			
			* pack.c (pack_unpack): set encoding of the 'H','h','B' and 'B' modifiers to US-ASCII. * test/ruby/test_pack.rb: tests for the above. [ruby-core:47653][Bug #7050] * test/test_securerandom.rb: tests for SecureRandom.hex from tenderlove. [ruby-core:46792][Bug #6799] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37269 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			185 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			185 lines
		
	
	
	
		
			4 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| require 'test/unit'
 | |
| require 'securerandom'
 | |
| require 'tempfile'
 | |
| 
 | |
| # This testcase does NOT aim to test cryptographically strongness and randomness.
 | |
| class TestSecureRandom < Test::Unit::TestCase
 | |
|   def setup
 | |
|     @it = SecureRandom
 | |
|   end
 | |
| 
 | |
|   def test_s_random_bytes
 | |
|     assert_equal(16, @it.random_bytes.size)
 | |
|     assert_equal(Encoding::ASCII_8BIT, @it.random_bytes.encoding)
 | |
|     65.times do |idx|
 | |
|       assert_equal(idx, @it.random_bytes(idx).size)
 | |
|     end
 | |
|   end
 | |
| 
 | |
| # This test took 2 minutes on my machine.
 | |
| # And 65536 times loop could not be enough for forcing PID recycle.
 | |
| if false
 | |
|   def test_s_random_bytes_is_fork_safe
 | |
|     begin
 | |
|       require 'openssl'
 | |
|     rescue LoadError
 | |
|       return
 | |
|     end
 | |
|     SecureRandom.random_bytes(8)
 | |
|     pid, v1 = forking_random_bytes
 | |
|     assert(check_forking_random_bytes(pid, v1), 'Process ID not recycled?')
 | |
|   end
 | |
| 
 | |
|   def forking_random_bytes
 | |
|     r, w = IO.pipe
 | |
|     pid = fork {
 | |
|       r.close
 | |
|       w.write SecureRandom.random_bytes(8)
 | |
|       w.close
 | |
|     }
 | |
|     w.close
 | |
|     v = r.read(8)
 | |
|     r.close
 | |
|     Process.waitpid2(pid)
 | |
|     [pid, v]
 | |
|   end
 | |
| 
 | |
|   def check_forking_random_bytes(target_pid, target)
 | |
|     65536.times do
 | |
|       pid = fork {
 | |
|         if $$ == target_pid
 | |
|           v2 = SecureRandom.random_bytes(8)
 | |
|           if v2 == target
 | |
|             exit(1)
 | |
|           else
 | |
|             exit(2)
 | |
|           end
 | |
|         end
 | |
|         exit(3)
 | |
|       }
 | |
|       pid, status = Process.waitpid2(pid)
 | |
|       case status.exitstatus
 | |
|       when 1
 | |
|         raise 'returned same sequence for same PID'
 | |
|       when 2
 | |
|         return true
 | |
|       end
 | |
|     end
 | |
|     false # not recycled?
 | |
|   end
 | |
| end
 | |
| 
 | |
|   def test_s_random_bytes_without_openssl
 | |
|     begin
 | |
|       require 'openssl'
 | |
|     rescue LoadError
 | |
|       return
 | |
|     end
 | |
|     begin
 | |
|       load_path = $LOAD_PATH.dup
 | |
|       loaded_features = $LOADED_FEATURES.dup
 | |
|       openssl = Object.instance_eval { remove_const(:OpenSSL) }
 | |
| 
 | |
|       remove_feature('securerandom.rb')
 | |
|       remove_feature('openssl.rb')
 | |
|       Dir.mktmpdir do |dir|
 | |
|         open(File.join(dir, 'openssl.rb'), 'w') { |f|
 | |
|           f << 'raise LoadError'
 | |
|         }
 | |
|         $LOAD_PATH.unshift(dir)
 | |
|         v = $VERBOSE
 | |
|         begin
 | |
|           $VERBOSE = false
 | |
|           require 'securerandom'
 | |
|         ensure
 | |
|           $VERBOSE = v
 | |
|         end
 | |
|         test_s_random_bytes
 | |
|       end
 | |
|     ensure
 | |
|       $LOADED_FEATURES.replace(loaded_features)
 | |
|       $LOAD_PATH.replace(load_path)
 | |
|       Object.const_set(:OpenSSL, openssl)
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def test_s_hex
 | |
|     assert_equal(16 * 2, @it.hex.size)
 | |
|     33.times do |idx|
 | |
|       assert_equal(idx * 2, @it.hex(idx).size)
 | |
|       assert_equal(idx, @it.hex(idx).gsub(/(..)/) { [$1].pack('H*') }.size)
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def test_hex_encoding
 | |
|     assert_equal(Encoding::US_ASCII, @it.hex.encoding)
 | |
|   end
 | |
| 
 | |
|   def test_s_base64
 | |
|     assert_equal(16, @it.base64.unpack('m*')[0].size)
 | |
|     17.times do |idx|
 | |
|       assert_equal(idx, @it.base64(idx).unpack('m*')[0].size)
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def test_s_urlsafe_base64
 | |
|     safe = /[\n+\/]/
 | |
|     65.times do |idx|
 | |
|       assert_not_match(safe, @it.urlsafe_base64(idx))
 | |
|     end
 | |
|     # base64 can include unsafe byte
 | |
|     10001.times do |idx|
 | |
|       return if safe =~ @it.base64(idx)
 | |
|     end
 | |
|     flunk
 | |
|   end
 | |
| 
 | |
|   def test_s_random_number_float
 | |
|     101.times do
 | |
|       v = @it.random_number
 | |
|       assert(0.0 <= v && v < 1.0)
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def test_s_random_number_float_by_zero
 | |
|     101.times do
 | |
|       v = @it.random_number(0)
 | |
|       assert(0.0 <= v && v < 1.0)
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def test_s_random_number_int
 | |
|     101.times do |idx|
 | |
|       next if idx.zero?
 | |
|       v = @it.random_number(idx)
 | |
|       assert(0 <= v && v < idx)
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def test_uuid
 | |
|     uuid = @it.uuid
 | |
|     assert_equal(36, uuid.size)
 | |
|     uuid.unpack('a8xa4xa4xa4xa12').each do |e|
 | |
|       assert_match(/^[0-9a-f]+$/, e)
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def protect
 | |
|     begin
 | |
|       yield
 | |
|     rescue NotImplementedError
 | |
|       # ignore
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def remove_feature(basename)
 | |
|     $LOADED_FEATURES.delete_if { |path|
 | |
|       if File.basename(path) == basename
 | |
|         $LOAD_PATH.any? { |dir|
 | |
|           File.exists?(File.join(dir, basename))
 | |
|         }
 | |
|       end
 | |
|     }
 | |
|   end
 | |
| 
 | |
| end
 |