ext/dbm/testdbm.rb


DEFINITIONS

This source file includes following functions.


   1  require 'runit/testcase'
   2  require 'runit/cui/testrunner'
   3  
   4  if $".grep(/\bdbm.so\b/).empty?
   5    begin
   6      require './dbm'
   7    rescue LoadError
   8      require 'dbm'
   9    end
  10  end
  11  
  12  def uname_s
  13    require 'rbconfig'
  14    case Config::CONFIG['host_os']
  15    when 'cygwin'
  16      require 'Win32API'
  17      uname = Win32API.new 'cygwin1', 'uname', 'P', 'I'
  18      utsname = ' ' * 100
  19      raise 'cannot get system name' if uname.call(utsname) == -1
  20  
  21      utsname.unpack('A20' * 5)[0]
  22    else
  23      Config::CONFIG['host_os']
  24    end
  25  end
  26  
  27  SYSTEM = uname_s
  28  
  29  class TestDBM < RUNIT::TestCase
  30    def setup
  31      @path = "tmptest_dbm_"
  32      assert_instance_of(DBM, @dbm = DBM.new(@path))
  33  
  34      # prepare to make readonly DBM file
  35      DBM.open("tmptest_dbm_rdonly", 0400) {|dbm|
  36        dbm['foo'] = 'FOO'
  37      }
  38      assert_instance_of(DBM, @dbm_rdonly = DBM.new("tmptest_dbm_rdonly", nil))
  39    end
  40    def teardown
  41      assert_nil(@dbm.close)
  42      assert_nil(@dbm_rdonly.close)
  43      GC.start
  44      File.delete *Dir.glob("tmptest_dbm*").to_a
  45      p Dir.glob("tmptest_dbm*") if $DEBUG
  46    end
  47  
  48    def check_size(expect, dbm=@dbm)
  49      assert_equals(expect, dbm.size)
  50      n = 0
  51      dbm.each { n+=1 }
  52      assert_equals(expect, n)
  53      if expect == 0
  54        assert_equals(true, dbm.empty?)
  55      else
  56        assert_equals(false, dbm.empty?)
  57      end
  58    end
  59  
  60    def test_version
  61      STDERR.print DBM::VERSION
  62    end
  63  
  64    def test_s_new_has_no_block
  65      # DBM.new ignore the block
  66      foo = true
  67      assert_instance_of(DBM, dbm = DBM.new("tmptest_dbm") { foo = false })
  68      assert_equals(foo, true)
  69      assert_nil(dbm.close)
  70    end
  71    def test_s_open_no_create
  72      assert_nil(dbm = DBM.open("tmptest_dbm", nil))
  73    ensure
  74      dbm.close if dbm
  75    end
  76    def test_s_open_with_block
  77      assert_equals(DBM.open("tmptest_dbm") { :foo }, :foo)
  78    end
  79    def test_s_open_lock
  80      fork() {
  81        assert_instance_of(DBM, dbm = DBM.open("tmptest_dbm", 0644))
  82        sleep 2
  83      }
  84      begin
  85        sleep 1
  86        assert_exception(Errno::EWOULDBLOCK) {
  87          begin
  88            assert_instance_of(DBM, dbm2 = DBM.open("tmptest_dbm", 0644))
  89          rescue Errno::EAGAIN, Errno::EACCES, Errno::EINVAL
  90            raise Errno::EWOULDBLOCK
  91          end
  92        }
  93      ensure
  94        Process.wait
  95      end
  96    end
  97  
  98  =begin
  99    # Is it guaranteed on many OS?
 100    def test_s_open_lock_one_process
 101      # locking on one process
 102      assert_instance_of(DBM, dbm  = DBM.open("tmptest_dbm", 0644))
 103      assert_exception(Errno::EWOULDBLOCK) {
 104        begin
 105          DBM.open("tmptest_dbm", 0644)
 106        rescue Errno::EAGAIN
 107          raise Errno::EWOULDBLOCK
 108        end
 109      }
 110    end
 111  =end
 112  
 113    def test_s_open_nolock
 114      # dbm 1.8.0 specific
 115      if not defined? DBM::NOLOCK
 116        return
 117      end
 118  
 119      fork() {
 120        assert_instance_of(DBM, dbm  = DBM.open("tmptest_dbm", 0644,
 121                                                  DBM::NOLOCK))
 122        sleep 2
 123      }
 124      sleep 1
 125      begin
 126        dbm2 = nil
 127        assert_no_exception(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) {
 128          assert_instance_of(DBM, dbm2 = DBM.open("tmptest_dbm", 0644))
 129        }
 130      ensure
 131        Process.wait
 132        dbm2.close if dbm2
 133      end
 134  
 135      p Dir.glob("tmptest_dbm*") if $DEBUG
 136  
 137      fork() {
 138        assert_instance_of(DBM, dbm  = DBM.open("tmptest_dbm", 0644))
 139        sleep 2
 140      }
 141      begin
 142        sleep 1
 143        dbm2 = nil
 144        assert_no_exception(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) {
 145          # this test is failed on Cygwin98 (???)
 146          assert_instance_of(DBM, dbm2 = DBM.open("tmptest_dbm", 0644,
 147                                                     DBM::NOLOCK))
 148        }
 149      ensure
 150        Process.wait
 151        dbm2.close if dbm2
 152      end
 153    end
 154  
 155    def test_s_open_error
 156      assert_instance_of(DBM, dbm = DBM.open("tmptest_dbm", 0))
 157      assert_exception(Errno::EACCES) {
 158        DBM.open("tmptest_dbm", 0)
 159      }
 160      dbm.close
 161    end
 162  
 163    def test_close
 164      assert_instance_of(DBM, dbm = DBM.open("tmptest_dbm"))
 165      assert_nil(dbm.close)
 166  
 167      # closed DBM file
 168      assert_exception(DBMError) { dbm.close }
 169    end
 170  
 171    def test_aref
 172      assert_equals('bar', @dbm['foo'] = 'bar')
 173      assert_equals('bar', @dbm['foo'])
 174  
 175      assert_nil(@dbm['bar'])
 176    end
 177  
 178    def test_fetch
 179      assert_equals('bar', @dbm['foo']='bar')
 180      assert_equals('bar', @dbm.fetch('foo'))
 181  
 182      # key not found
 183      assert_exception(IndexError) {
 184        @dbm.fetch('bar')
 185      }
 186  
 187      # test for `ifnone' arg
 188      assert_equals('baz', @dbm.fetch('bar', 'baz'))
 189  
 190      # test for `ifnone' block
 191      assert_equals('foobar', @dbm.fetch('bar') {|key| 'foo' + key })
 192    end
 193  
 194    def test_aset
 195      num = 0
 196      2.times {|i|
 197        assert_equals('foo', @dbm['foo'] = 'foo')
 198        assert_equals('foo', @dbm['foo'])
 199        assert_equals('bar', @dbm['foo'] = 'bar')
 200        assert_equals('bar', @dbm['foo'])
 201  
 202        num += 1 if i == 0
 203        assert_equals(num, @dbm.size)
 204  
 205        # assign nil
 206        assert_equals('', @dbm['bar'] = '')
 207        assert_equals('', @dbm['bar'])
 208  
 209        num += 1 if i == 0
 210        assert_equals(num, @dbm.size)
 211  
 212        # empty string
 213        assert_equals('', @dbm[''] = '')
 214        assert_equals('', @dbm[''])
 215  
 216        num += 1 if i == 0
 217        assert_equals(num, @dbm.size)
 218  
 219        # Fixnum
 220        assert_equals('200', @dbm['100'] = '200')
 221        assert_equals('200', @dbm['100'])
 222  
 223        num += 1 if i == 0
 224        assert_equals(num, @dbm.size)
 225  
 226        # Big key and value
 227        assert_equals('y' * 100, @dbm['x' * 100] = 'y' * 100)
 228        assert_equals('y' * 100, @dbm['x' * 100])
 229  
 230        num += 1 if i == 0
 231        assert_equals(num, @dbm.size)
 232      }
 233    end
 234  
 235    def test_index
 236      assert_equals('bar', @dbm['foo'] = 'bar')
 237      assert_equals('foo', @dbm.index('bar'))
 238      assert_nil(@dbm['bar'])
 239    end
 240  
 241    def test_indexes
 242      keys = %w(foo bar baz)
 243      values = %w(FOO BAR BAZ)
 244      @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
 245      assert_equals(values.reverse, @dbm.indexes(*keys.reverse))
 246    end
 247  
 248    def test_select
 249      keys = %w(foo bar baz)
 250      values = %w(FOO BAR BAZ)
 251      @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
 252      assert_equals(values.reverse, @dbm.select(*keys.reverse))
 253    end
 254  
 255    def test_select_with_block
 256      keys = %w(foo bar baz)
 257      values = %w(FOO BAR BAZ)
 258      @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
 259      ret = @dbm.select {|k,v|
 260        assert_equals(k.upcase, v)
 261        k != "bar"
 262      }
 263      assert_equals([['baz', 'BAZ'], ['foo', 'FOO']],
 264                    ret.sort)
 265    end
 266  
 267    def test_length
 268      num = 10
 269      assert_equals(0, @dbm.size)
 270      num.times {|i|
 271        i = i.to_s
 272        @dbm[i] = i
 273      }
 274      assert_equals(num, @dbm.size)
 275  
 276      @dbm.shift
 277  
 278      assert_equals(num - 1, @dbm.size)
 279    end
 280  
 281    def test_empty?
 282      assert_equals(true, @dbm.empty?)
 283      @dbm['foo'] = 'FOO'
 284      assert_equals(false, @dbm.empty?)
 285    end
 286  
 287    def test_each_pair
 288      n = 0
 289      @dbm.each_pair { n += 1 }
 290      assert_equals(0, n)
 291  
 292      keys = %w(foo bar baz)
 293      values = %w(FOO BAR BAZ)
 294  
 295      @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
 296  
 297      n = 0
 298      ret = @dbm.each_pair {|key, val|
 299        assert_not_nil(i = keys.index(key))
 300        assert_equals(val, values[i])
 301  
 302        n += 1
 303      }
 304      assert_equals(keys.size, n)
 305      assert_equals(@dbm, ret)
 306    end
 307  
 308    def test_each_value
 309      n = 0
 310      @dbm.each_value { n += 1 }
 311      assert_equals(0, n)
 312  
 313      keys = %w(foo bar baz)
 314      values = %w(FOO BAR BAZ)
 315  
 316      @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
 317  
 318      n = 0
 319      ret = @dbm.each_value {|val|
 320        assert_not_nil(key = @dbm.index(val))
 321        assert_not_nil(i = keys.index(key))
 322        assert_equals(val, values[i])
 323  
 324        n += 1
 325      }
 326      assert_equals(keys.size, n)
 327      assert_equals(@dbm, ret)
 328    end
 329  
 330    def test_each_key
 331      n = 0
 332      @dbm.each_key { n += 1 }
 333      assert_equals(0, n)
 334  
 335      keys = %w(foo bar baz)
 336      values = %w(FOO BAR BAZ)
 337  
 338      @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
 339  
 340      n = 0
 341      ret = @dbm.each_key {|key|
 342        assert_not_nil(i = keys.index(key))
 343        assert_equals(@dbm[key], values[i])
 344  
 345        n += 1
 346      }
 347      assert_equals(keys.size, n)
 348      assert_equals(@dbm, ret)
 349    end
 350  
 351    def test_keys
 352      assert_equals([], @dbm.keys)
 353  
 354      keys = %w(foo bar baz)
 355      values = %w(FOO BAR BAZ)
 356  
 357      @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
 358  
 359      assert_equals(keys.sort, @dbm.keys.sort)
 360      assert_equals(values.sort, @dbm.values.sort)
 361    end
 362  
 363    def test_values
 364      test_keys
 365    end
 366  
 367    def test_shift
 368      assert_nil(@dbm.shift)
 369      assert_equals(0, @dbm.size)
 370  
 371      keys = %w(foo bar baz)
 372      values = %w(FOO BAR BAZ)
 373  
 374      @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
 375  
 376      ret_keys = []
 377      ret_values = []
 378      while ret = @dbm.shift
 379        ret_keys.push ret[0]
 380        ret_values.push ret[1]
 381  
 382        assert_equals(keys.size - ret_keys.size, @dbm.size)
 383      end
 384  
 385      assert_equals(keys.sort, ret_keys.sort)
 386      assert_equals(values.sort, ret_values.sort)
 387    end
 388  
 389    def test_delete
 390      keys = %w(foo bar baz)
 391      values = %w(FOO BAR BAZ)
 392      key = keys[1]
 393  
 394      assert_nil(@dbm.delete(key))
 395      assert_equals(0, @dbm.size)
 396  
 397      @dbm[keys[0]], @dbm[keys[1]], @dbm[keys[2]] = values
 398  
 399      assert_equals('BAR', @dbm.delete(key))
 400      assert_nil(@dbm[key])
 401      assert_equals(2, @dbm.size)
 402  
 403      assert_nil(@dbm.delete(key))
 404  
 405      if /^CYGWIN_9/ !~ SYSTEM
 406        assert_exception(DBMError) {
 407          @dbm_rdonly.delete("foo")
 408        }
 409  
 410        assert_nil(@dbm_rdonly.delete("bar"))
 411      end
 412    end
 413    def test_delete_with_block
 414      key = 'no called block'
 415      @dbm[key] = 'foo'
 416      assert_equals('foo', @dbm.delete(key) {|k| k.replace 'called block'})
 417      assert_equals('no called block', key)
 418      assert_equals(0, @dbm.size)
 419  
 420      key = 'no called block'
 421      assert_equals(:blockval,
 422                    @dbm.delete(key) {|k| k.replace 'called block'; :blockval})
 423      assert_equals('called block', key)
 424      assert_equals(0, @dbm.size)
 425    end
 426  
 427    def test_delete_if
 428      v = "0"
 429      100.times {@dbm[v] = v; v = v.next}
 430  
 431      ret = @dbm.delete_if {|key, val| key.to_i < 50}
 432      assert_equals(@dbm, ret)
 433      check_size(50, @dbm)
 434  
 435      ret = @dbm.delete_if {|key, val| key.to_i >= 50}
 436      assert_equals(@dbm, ret)
 437      check_size(0, @dbm)
 438  
 439      # break
 440      v = "0"
 441      100.times {@dbm[v] = v; v = v.next}
 442      check_size(100, @dbm)
 443      n = 0;
 444      @dbm.delete_if {|key, val|
 445        break if n > 50
 446        n+=1
 447        true
 448      }
 449      assert_equals(51, n)
 450      check_size(49, @dbm)
 451  
 452      @dbm.clear
 453  
 454      # raise
 455      v = "0"
 456      100.times {@dbm[v] = v; v = v.next}
 457      check_size(100, @dbm)
 458      n = 0;
 459      begin
 460        @dbm.delete_if {|key, val|
 461          raise "runtime error" if n > 50
 462          n+=1
 463          true
 464        }
 465      rescue
 466      end
 467      assert_equals(51, n)
 468      check_size(49, @dbm)
 469    end
 470  
 471    def test_reject
 472      v = "0"
 473      100.times {@dbm[v] = v; v = v.next}
 474  
 475      hash = @dbm.reject {|key, val| key.to_i < 50}
 476      assert_instance_of(Hash, hash)
 477      assert_equals(100, @dbm.size)
 478  
 479      assert_equals(50, hash.size)
 480      hash.each_pair {|key,val|
 481        assert_equals(false, key.to_i < 50)
 482        assert_equals(key, val)
 483      }
 484  
 485      hash = @dbm.reject {|key, val| key.to_i < 100}
 486      assert_instance_of(Hash, hash)
 487      assert_equals(true, hash.empty?)
 488    end
 489  
 490    def test_clear
 491      v = "1"
 492      100.times {v = v.next; @dbm[v] = v}
 493  
 494      assert_equals(@dbm, @dbm.clear)
 495  
 496      # validate DBM#size
 497      i = 0
 498      @dbm.each { i += 1 }
 499      assert_equals(@dbm.size, i)
 500      assert_equals(0, i)
 501    end
 502  
 503    def test_invert
 504      v = "0"
 505      100.times {@dbm[v] = v; v = v.next}
 506  
 507      hash = @dbm.invert
 508      assert_instance_of(Hash, hash)
 509      assert_equals(100, hash.size)
 510      hash.each_pair {|key, val|
 511        assert_equals(key.to_i, val.to_i)
 512      }
 513    end
 514  
 515    def test_update
 516      hash = {}
 517      v = "0"
 518      100.times {v = v.next; hash[v] = v}
 519  
 520      @dbm["101"] = "101"
 521      @dbm.update hash
 522      assert_equals(101, @dbm.size)
 523      @dbm.each_pair {|key, val|
 524        assert_equals(key.to_i, val.to_i)
 525      }
 526    end
 527  
 528    def test_replace
 529      hash = {}
 530      v = "0"
 531      100.times {v = v.next; hash[v] = v}
 532  
 533      @dbm["101"] = "101"
 534      @dbm.replace hash
 535      assert_equals(100, @dbm.size)
 536      @dbm.each_pair {|key, val|
 537        assert_equals(key.to_i, val.to_i)
 538      }
 539    end
 540  
 541    def test_haskey?
 542      assert_equals('bar', @dbm['foo']='bar')
 543      assert_equals(true,  @dbm.has_key?('foo'))
 544      assert_equals(false, @dbm.has_key?('bar'))
 545    end
 546  
 547    def test_has_value?
 548      assert_equals('bar', @dbm['foo']='bar')
 549      assert_equals(true,  @dbm.has_value?('bar'))
 550      assert_equals(false, @dbm.has_value?('foo'))
 551    end
 552  
 553    def test_to_a
 554      v = "0"
 555      100.times {v = v.next; @dbm[v] = v}
 556  
 557      ary = @dbm.to_a
 558      assert_instance_of(Array, ary)
 559      assert_equals(100, ary.size)
 560      ary.each {|key,val|
 561        assert_equals(key.to_i, val.to_i)
 562      }
 563    end
 564  
 565    def test_to_hash
 566      v = "0"
 567      100.times {v = v.next; @dbm[v] = v}
 568  
 569      hash = @dbm.to_hash
 570      assert_instance_of(Hash, hash)
 571      assert_equals(100, hash.size)
 572      hash.each {|key,val|
 573        assert_equals(key.to_i, val.to_i)
 574      }
 575    end
 576  end
 577  
 578  if $0 == __FILE__
 579    if ARGV.size == 0
 580      suite = RUNIT::TestSuite.new
 581      suite.add_test(TestDBM.suite)
 582    else
 583      suite = RUNIT::TestSuite.new
 584      ARGV.each do |testmethod|
 585        suite.add_test(TestDBM.new(testmethod))
 586      end
 587    end
 588  
 589    RUNIT::CUI::TestRunner.run(suite)
 590  end