about summary refs log tree commit
path: root/test/test_tokyocabinet_hdb.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_tokyocabinet_hdb.rb')
-rw-r--r--test/test_tokyocabinet_hdb.rb200
1 files changed, 200 insertions, 0 deletions
diff --git a/test/test_tokyocabinet_hdb.rb b/test/test_tokyocabinet_hdb.rb
new file mode 100644
index 0000000..31a77d7
--- /dev/null
+++ b/test/test_tokyocabinet_hdb.rb
@@ -0,0 +1,200 @@
+# -*- encoding: binary -*-
+require 'test/unit'
+require 'tempfile'
+require 'stringio'
+require 'tokyocabinet' # FIXME: emits warning with 1.29 gem
+$-w = true
+require 'metropolis'
+
+class TestTokyocabinetHDB < Test::Unit::TestCase
+  attr_reader :tmp, :o
+
+  def setup
+    tmp = Tempfile.new('tchdb')
+    @path_pattern = tmp.path + ".%01x.tch"
+    tmp.close!
+  end
+
+  def teardown
+    Dir[@path_pattern.sub!(/%\d*x/, '*')].each { |x| File.unlink(x) }
+  end
+
+  def osetup
+    o = Object.new
+    o.extend Metropolis::TokyoCabinet::HDB
+    assert_nothing_raised do
+      o.setup :path_pattern => @path_pattern
+    end
+    o
+  end
+
+  def test_create_put_get_delete
+    o = osetup
+    r = o.put('hello', { 'rack.input' => StringIO.new('world') })
+    assert_equal 201, r[0].to_i
+    assert_equal 'text/plain', r[1]['Content-Type']
+    assert_equal '8', r[1]['Content-Length']
+    assert_equal "Created\n", r[2].join('')
+
+    r = o.put('hellox', { 'rack.input' => StringIO.new('worldx') })
+    assert_equal 201, r[0].to_i
+    assert_equal 'text/plain', r[1]['Content-Type']
+    assert_equal '8', r[1]['Content-Length']
+    assert_equal "Created\n", r[2].join('')
+
+    r = o.get('hello')
+    assert_equal 200, r[0].to_i
+    assert_equal 'application/octet-stream', r[1]['Content-Type']
+    assert_equal '5', r[1]['Content-Length']
+    assert_equal %w(world), r[2]
+
+    r = o.head('hello')
+    assert_equal 200, r[0].to_i
+    assert_equal 'application/octet-stream', r[1]['Content-Type']
+    assert_equal '5', r[1]['Content-Length']
+    assert_equal [], r[2]
+
+    r = o.get('hellox')
+    assert_equal 200, r[0].to_i
+    assert_equal 'application/octet-stream', r[1]['Content-Type']
+    assert_equal '6', r[1]['Content-Length']
+    assert_equal %w(worldx), r[2]
+
+    r = o.delete('hellox')
+    assert_equal 200, r[0].to_i
+    assert_equal 'text/plain', r[1]['Content-Type']
+    assert_equal '3', r[1]['Content-Length']
+    assert_equal "OK\n", r[2].join('')
+
+    r = o.delete('hellox')
+    assert_equal 404, r[0].to_i
+    assert_equal 'text/plain', r[1]['Content-Type']
+    assert_equal '10', r[1]['Content-Length']
+    assert_equal "Not Found\n", r[2].join('')
+
+    r = o.get('hellox')
+    assert_equal 404, r[0].to_i
+    assert_equal 'text/plain', r[1]['Content-Type']
+    assert_equal '10', r[1]['Content-Length']
+    assert_equal "Not Found\n", r[2].join('')
+
+    r = o.head('hellox')
+    assert_equal 404, r[0].to_i
+    assert_equal 'text/plain', r[1]['Content-Type']
+    assert_equal '10', r[1]['Content-Length']
+    assert_equal "Not Found\n", r[2].join('')
+  end
+
+  def test_putkeep
+    o = osetup
+    env = {
+      "rack.input" => StringIO.new("hello"),
+      "HTTP_X_TT_PDMODE" => "1"
+    }
+    assert_equal 201, o.put("x", env)[0]
+    env["rack.input"] = StringIO.new("wrong")
+    assert_equal 409, o.put("x", env)[0]
+    assert_equal "hello", o.get("x")[2].join('')
+  end
+
+  def test_putcat
+    o = osetup
+    env = {
+      "rack.input" => StringIO.new("hello"),
+      "HTTP_X_TT_PDMODE" => "2"
+    }
+    assert_equal 201, o.put("x", env)[0]
+    env["rack.input"] = StringIO.new("MOAR")
+    assert_equal 201, o.put("x", env)[0]
+    assert_equal "helloMOAR", o.get("x")[2].join('')
+  end
+
+  def test_multiproc
+    nr = 2
+    key = "k"
+    str = "." * (1024 * 1024)
+    nr.times {
+      fork {
+        o = osetup
+        sio = StringIO.new(str)
+        env = { "rack.input" => sio }
+        100.times {
+          o.put(key, env)
+          sio.rewind
+          o.get(key)
+        }
+      }
+    }
+    res = Process.waitall
+    assert_equal nr, res.size
+    res.each { |(pid, status)| assert status.success? }
+  end
+
+  def test_readonly
+    key = "x"
+    wr = osetup
+    wr.put(key, { "rack.input" => StringIO.new("OK") })
+    o = Object.new
+    o.extend Metropolis::TokyoCabinet::HDB
+    assert_nothing_raised do
+      o.setup :path_pattern => @path_pattern, :read_only => true
+    end
+    %w(PUT DELETE).each do |rm|
+      env = {
+        "rack.input" => StringIO.new("FAIL"),
+        "REQUEST_METHOD" => rm,
+        "PATH_INFO" => "/#{key}"
+      }
+      assert_equal 405, o.call(env)[0]
+    end
+    env = {
+      "REQUEST_METHOD" => "GET",
+      "PATH_INFO" => "/#{key}",
+    }
+    assert_equal 200, o.call(env)[0]
+    assert_equal '2', o.call(env)[1]["Content-Length"]
+    assert_equal 'application/octet-stream', o.call(env)[1]["Content-Type"]
+    assert_equal "OK", o.call(env)[2].join('')
+
+    env["REQUEST_METHOD"] = "HEAD"
+    assert_equal 200, o.call(env)[0]
+    assert_equal '2', o.call(env)[1]["Content-Length"]
+    assert_equal 'application/octet-stream', o.call(env)[1]["Content-Type"]
+    assert_equal "", o.call(env)[2].join('')
+  end
+
+  def test_create_toplevel
+    k = "x"
+    nr_bytes = 1024 * 1024 * 20
+    data = "0" * nr_bytes
+    uri = "tc://#{@path_pattern}"
+    obj = nil
+    assert_nothing_raised { obj = Metropolis.new(:uri => uri) }
+
+    query = "large=true&apow=3&bnum=65536&compress=deflate"
+    assert_nothing_raised {
+      obj = Metropolis.new(:uri => "#{uri}?#{query}")
+    }
+    optimize_args = obj.instance_variable_get(:@optimize)
+    flags = ::TokyoCabinet::HDB::TLARGE | ::TokyoCabinet::HDB::TDEFLATE
+    assert_equal flags, optimize_args[3]
+    assert_equal 65536, optimize_args[0]
+    assert_nil optimize_args[2]
+    assert_equal 3, optimize_args[1]
+    assert_nothing_raised { obj.get(k) }
+    assert_nothing_raised { obj.put(k,{'rack.input' => StringIO.new(data)}) }
+
+    obj = Metropolis.new(:uri => "#{uri}?#{query}", :read_only => true)
+    assert_equal data, obj.get(k)[2].join('')
+    obj.close!
+
+    obj = Metropolis.new(:uri => uri, :read_only => true)
+    assert_equal data, obj.get(k)[2].join('')
+    obj.close!
+    sum = obj.instance_eval {
+      @hdbv.inject(0) { |size, (hdb,path)| size += File.stat(path).size }
+    }
+    assert sum <= nr_bytes, "#{sum} > #{nr_bytes}"
+    obj.close!
+  end
+end