test: minor cleanup to share @uri
[metropolis.git] / test / test_tokyocabinet_hdb.rb
blobf973b69033a85acc4537e95e8278f14e02ce8e4c
1 # -*- encoding: binary -*-
2 require 'test/unit'
3 require 'tempfile'
4 require 'stringio'
5 require 'tokyocabinet' # FIXME: emits warning with 1.29 gem
6 $-w = true
7 require 'metropolis'
9 class TestTokyocabinetHDB < Test::Unit::TestCase
10   attr_reader :tmp, :o, :uri
12   def setup
13     tmp = Tempfile.new('tchdb')
14     @path_pattern = tmp.path + ".%01x.tch"
15     tmp.close!
16     @uri = "tc://#{@path_pattern}"
17   end
19   def teardown
20     Dir[@path_pattern.sub!(/%\d*x/, '*')].each { |x| File.unlink(x) }
21   end
23   def osetup
24     o = Object.new
25     o.extend Metropolis::TokyoCabinet::HDB
26     assert_nothing_raised do
27       o.setup :path_pattern => @path_pattern
28     end
29     o
30   end
32   def test_create_put_get_delete
33     o = osetup
34     r = o.put('hello', { 'rack.input' => StringIO.new('world') })
35     assert_equal 201, r[0].to_i
36     assert_equal 'text/plain', r[1]['Content-Type']
37     assert_equal '8', r[1]['Content-Length']
38     assert_equal "Created\n", r[2].join('')
40     r = o.put('hellox', { 'rack.input' => StringIO.new('worldx') })
41     assert_equal 201, r[0].to_i
42     assert_equal 'text/plain', r[1]['Content-Type']
43     assert_equal '8', r[1]['Content-Length']
44     assert_equal "Created\n", r[2].join('')
46     r = o.get('hello')
47     assert_equal 200, r[0].to_i
48     assert_equal 'application/octet-stream', r[1]['Content-Type']
49     assert_equal '5', r[1]['Content-Length']
50     assert_equal %w(world), r[2]
52     r = o.head('hello')
53     assert_equal 200, r[0].to_i
54     assert_equal 'application/octet-stream', r[1]['Content-Type']
55     assert_equal '5', r[1]['Content-Length']
56     assert_equal [], r[2]
58     r = o.get('hellox')
59     assert_equal 200, r[0].to_i
60     assert_equal 'application/octet-stream', r[1]['Content-Type']
61     assert_equal '6', r[1]['Content-Length']
62     assert_equal %w(worldx), r[2]
64     r = o.delete('hellox')
65     assert_equal 200, r[0].to_i
66     assert_equal 'text/plain', r[1]['Content-Type']
67     assert_equal '3', r[1]['Content-Length']
68     assert_equal "OK\n", r[2].join('')
70     r = o.delete('hellox')
71     assert_equal 404, r[0].to_i
72     assert_equal 'text/plain', r[1]['Content-Type']
73     assert_equal '10', r[1]['Content-Length']
74     assert_equal "Not Found\n", r[2].join('')
76     r = o.get('hellox')
77     assert_equal 404, r[0].to_i
78     assert_equal 'text/plain', r[1]['Content-Type']
79     assert_equal '10', r[1]['Content-Length']
80     assert_equal "Not Found\n", r[2].join('')
82     r = o.head('hellox')
83     assert_equal 404, r[0].to_i
84     assert_equal 'text/plain', r[1]['Content-Type']
85     assert_equal '10', r[1]['Content-Length']
86     assert_equal "Not Found\n", r[2].join('')
87   end
89   def test_putkeep
90     o = osetup
91     env = {
92       "rack.input" => StringIO.new("hello"),
93       "HTTP_X_TT_PDMODE" => "1"
94     }
95     assert_equal 201, o.put("x", env)[0]
96     env["rack.input"] = StringIO.new("wrong")
97     assert_equal 409, o.put("x", env)[0]
98     assert_equal "hello", o.get("x")[2].join('')
99   end
101   def test_putcat
102     o = osetup
103     env = {
104       "rack.input" => StringIO.new("hello"),
105       "HTTP_X_TT_PDMODE" => "2"
106     }
107     assert_equal 201, o.put("x", env)[0]
108     env["rack.input"] = StringIO.new("MOAR")
109     assert_equal 201, o.put("x", env)[0]
110     assert_equal "helloMOAR", o.get("x")[2].join('')
111   end
113   def test_multiproc
114     nr = 2
115     key = "k"
116     str = "." * (1024 * 1024)
117     nr.times {
118       fork {
119         o = osetup
120         sio = StringIO.new(str)
121         env = { "rack.input" => sio }
122         100.times {
123           o.put(key, env)
124           sio.rewind
125           o.get(key)
126         }
127       }
128     }
129     res = Process.waitall
130     assert_equal nr, res.size
131     res.each { |(pid, status)| assert status.success? }
132   end
134   def test_readonly
135     key = "x"
136     wr = osetup
137     wr.put(key, { "rack.input" => StringIO.new("OK") })
138     o = Object.new
139     o.extend Metropolis::TokyoCabinet::HDB
140     assert_nothing_raised do
141       o.setup :path_pattern => @path_pattern, :read_only => true
142     end
143     %w(PUT DELETE).each do |rm|
144       env = {
145         "rack.input" => StringIO.new("FAIL"),
146         "REQUEST_METHOD" => rm,
147         "PATH_INFO" => "/#{key}"
148       }
149       assert_equal 405, o.call(env)[0]
150     end
151     env = {
152       "REQUEST_METHOD" => "GET",
153       "PATH_INFO" => "/#{key}",
154     }
155     assert_equal 200, o.call(env)[0]
156     assert_equal '2', o.call(env)[1]["Content-Length"]
157     assert_equal 'application/octet-stream', o.call(env)[1]["Content-Type"]
158     assert_equal "OK", o.call(env)[2].join('')
160     env["REQUEST_METHOD"] = "HEAD"
161     assert_equal 200, o.call(env)[0]
162     assert_equal '2', o.call(env)[1]["Content-Length"]
163     assert_equal 'application/octet-stream', o.call(env)[1]["Content-Type"]
164     assert_equal "", o.call(env)[2].join('')
165   end
167   def test_create_toplevel
168     k = "x"
169     nr_bytes = 1024 * 1024 * 20
170     data = "0" * nr_bytes
171     obj = nil
172     assert_nothing_raised { obj = Metropolis.new(:uri => uri) }
174     query = "large=true&apow=3&bnum=65536&compress=deflate"
175     assert_nothing_raised {
176       obj = Metropolis.new(:uri => "#{uri}?#{query}")
177     }
178     optimize_args = obj.instance_variable_get(:@optimize)
179     flags = ::TokyoCabinet::HDB::TLARGE | ::TokyoCabinet::HDB::TDEFLATE
180     assert_equal flags, optimize_args[3]
181     assert_equal 65536, optimize_args[0]
182     assert_nil optimize_args[2]
183     assert_equal 3, optimize_args[1]
184     assert_nothing_raised { obj.get(k) }
185     assert_nothing_raised { obj.put(k,{'rack.input' => StringIO.new(data)}) }
187     obj = Metropolis.new(:uri => "#{uri}?#{query}", :read_only => true)
188     assert_equal data, obj.get(k)[2].join('')
189     obj.close!
191     obj = Metropolis.new(:uri => uri, :read_only => true)
192     assert_equal data, obj.get(k)[2].join('')
193     obj.close!
194     sum = obj.instance_eval {
195       @hdbv.inject(0) { |size, (hdb,path)| size += File.stat(path).size }
196     }
197     assert sum <= nr_bytes, "#{sum} > #{nr_bytes}"
198     obj.close!
199   end