ext/gdbm/testgdbm.rb


DEFINITIONS

This source file includes following functions.


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