couchbase-jruby-client 0.1.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +203 -0
- data/README.md +347 -0
- data/Rakefile +10 -0
- data/couchbase-jruby-client.gemspec +30 -0
- data/lib/couchbase/async/callback.rb +19 -0
- data/lib/couchbase/async/queue.rb +26 -0
- data/lib/couchbase/async.rb +139 -0
- data/lib/couchbase/bucket.rb +663 -0
- data/lib/couchbase/cluster.rb +105 -0
- data/lib/couchbase/constants.rb +12 -0
- data/lib/couchbase/error.rb +28 -0
- data/lib/couchbase/jruby/couchbase_client.rb +22 -0
- data/lib/couchbase/jruby/future.rb +8 -0
- data/lib/couchbase/operations/arithmetic.rb +301 -0
- data/lib/couchbase/operations/delete.rb +104 -0
- data/lib/couchbase/operations/get.rb +298 -0
- data/lib/couchbase/operations/stats.rb +16 -0
- data/lib/couchbase/operations/store.rb +468 -0
- data/lib/couchbase/operations/touch.rb +123 -0
- data/lib/couchbase/operations/utils.rb +49 -0
- data/lib/couchbase/operations.rb +23 -0
- data/lib/couchbase/result.rb +43 -0
- data/lib/couchbase/transcoder.rb +83 -0
- data/lib/couchbase/utils.rb +62 -0
- data/lib/couchbase/version.rb +3 -0
- data/lib/couchbase/view.rb +506 -0
- data/lib/couchbase/view_row.rb +272 -0
- data/lib/couchbase.rb +177 -0
- data/lib/jars/commons-codec-1.5.jar +0 -0
- data/lib/jars/couchbase-client-1.2.0-javadoc.jar +0 -0
- data/lib/jars/couchbase-client-1.2.0-sources.jar +0 -0
- data/lib/jars/couchbase-client-1.2.0.jar +0 -0
- data/lib/jars/httpcore-4.1.1.jar +0 -0
- data/lib/jars/httpcore-nio-4.1.1.jar +0 -0
- data/lib/jars/jettison-1.1.jar +0 -0
- data/lib/jars/netty-3.5.5.Final.jar +0 -0
- data/lib/jars/spymemcached-2.10.0-javadoc.jar +0 -0
- data/lib/jars/spymemcached-2.10.0-sources.jar +0 -0
- data/lib/jars/spymemcached-2.10.0.jar +0 -0
- data/test/profile/.gitignore +1 -0
- data/test/profile/Gemfile +6 -0
- data/test/profile/benchmark.rb +195 -0
- data/test/setup.rb +201 -0
- data/test/test_arithmetic.rb +177 -0
- data/test/test_async.rb +324 -0
- data/test/test_bucket.rb +213 -0
- data/test/test_cas.rb +78 -0
- data/test/test_couchbase.rb +29 -0
- data/test/test_couchbase_rails_cache_store.rb +341 -0
- data/test/test_delete.rb +125 -0
- data/test/test_errors.rb +82 -0
- data/test/test_format.rb +161 -0
- data/test/test_get.rb +417 -0
- data/test/test_stats.rb +57 -0
- data/test/test_store.rb +216 -0
- data/test/test_timer.rb +42 -0
- data/test/test_touch.rb +97 -0
- data/test/test_unlock.rb +119 -0
- data/test/test_utils.rb +58 -0
- data/test/test_version.rb +52 -0
- metadata +226 -0
data/test/setup.rb
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
# Author:: Couchbase <info@couchbase.com>
|
2
|
+
# Copyright:: 2011, 2012 Couchbase, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
gem 'minitest'
|
19
|
+
require 'minitest/autorun'
|
20
|
+
require 'couchbase'
|
21
|
+
|
22
|
+
require 'socket'
|
23
|
+
require 'open-uri'
|
24
|
+
|
25
|
+
# Surpress connection logging
|
26
|
+
# java_import java.lang.System
|
27
|
+
# java_import java.util.logging.Logger
|
28
|
+
# java_import java.util.logging.Level
|
29
|
+
|
30
|
+
# properties = System.getProperties
|
31
|
+
# properties.put("net.spy.log.LoggerImpl", "net.spy.memcached.compat.log.Log4JLogger")
|
32
|
+
# System.setProperties(properties)
|
33
|
+
|
34
|
+
# Logger.getLogger('net.spy.memcached').setLevel(Level::SEVERE)
|
35
|
+
# Logger.getLogger('com.couchbase.client').setLevel(Level::SEVERE)
|
36
|
+
# Logger.getLogger('com.couchbase.client.vbucket').setLevel(Level::SEVERE)
|
37
|
+
|
38
|
+
# $stderr = StringIO.new
|
39
|
+
|
40
|
+
Minitest.after_run { Couchbase.disconnect }
|
41
|
+
|
42
|
+
class CouchbaseServer
|
43
|
+
attr_accessor :host, :port, :num_nodes, :buckets_spec
|
44
|
+
|
45
|
+
def real?
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize(params = {})
|
50
|
+
@host, @port = ['localhost', 8091] #ENV['COUCHBASE_SERVER'].split(':')
|
51
|
+
@port = @port.to_i
|
52
|
+
|
53
|
+
if @host.nil? || @host.empty? || @port == 0
|
54
|
+
raise ArgumentError, "Check COUCHBASE_SERVER variable. It should be hostname:port"
|
55
|
+
end
|
56
|
+
|
57
|
+
@config = MultiJson.load(open("http://#{@host}:#{@port}/pools/default"))
|
58
|
+
@num_nodes = @config["nodes"].size
|
59
|
+
@buckets_spec = params[:buckets_spec] || "default:" # "default:,protected:secret,cache::memcache"
|
60
|
+
end
|
61
|
+
|
62
|
+
def start
|
63
|
+
# flush all buckets
|
64
|
+
@buckets_spec.split(',') do |bucket|
|
65
|
+
name, password, _ = bucket.split(':')
|
66
|
+
connection = Couchbase.new(:hostname => @host,
|
67
|
+
:port => @port,
|
68
|
+
:username => name,
|
69
|
+
:bucket => name,
|
70
|
+
:password => password)
|
71
|
+
begin
|
72
|
+
connection.flush
|
73
|
+
rescue Couchbase::Error::NotSupported
|
74
|
+
# on recent server flush is disabled
|
75
|
+
ensure
|
76
|
+
connection.disconnect
|
77
|
+
end
|
78
|
+
end if ENV['COUCHBASE_FLUSH_BUCKETS']
|
79
|
+
end
|
80
|
+
|
81
|
+
def stop
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class CouchbaseMock
|
86
|
+
Monitor = Struct.new(:pid, :client, :socket, :port)
|
87
|
+
|
88
|
+
attr_accessor :host, :port, :buckets_spec, :num_nodes, :num_vbuckets
|
89
|
+
|
90
|
+
def real?
|
91
|
+
false
|
92
|
+
end
|
93
|
+
|
94
|
+
def initialize(params = {})
|
95
|
+
@host = "127.0.0.1"
|
96
|
+
@port = 0
|
97
|
+
@num_nodes = 10
|
98
|
+
@num_vbuckets = 4096
|
99
|
+
@buckets_spec = "default:" # "default:,protected:secret,cache::memcache"
|
100
|
+
params.each do |key, value|
|
101
|
+
send("#{key}=", value)
|
102
|
+
end
|
103
|
+
yield self if block_given?
|
104
|
+
if @num_vbuckets < 1 || (@num_vbuckets & (@num_vbuckets - 1) != 0)
|
105
|
+
raise ArgumentError, "Number of vbuckets should be a power of two and greater than zero"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def start
|
110
|
+
@monitor = Monitor.new
|
111
|
+
@monitor.socket = TCPServer.new(nil, 0)
|
112
|
+
@monitor.socket.listen(10)
|
113
|
+
_, @monitor.port, _, _ = @monitor.socket.addr
|
114
|
+
trap("CLD") do
|
115
|
+
puts "CouchbaseMock.jar died unexpectedly during startup"
|
116
|
+
exit(1)
|
117
|
+
end
|
118
|
+
@monitor.pid = fork
|
119
|
+
if @monitor.pid.nil?
|
120
|
+
rc = exec(command_line("--harakiri-monitor=:#{@monitor.port}"))
|
121
|
+
else
|
122
|
+
trap("CLD", "SIG_DFL")
|
123
|
+
@monitor.client, _ = @monitor.socket.accept
|
124
|
+
@port = @monitor.client.recv(100).to_i
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def stop
|
129
|
+
@monitor.client.close
|
130
|
+
@monitor.socket.close
|
131
|
+
Process.kill("TERM", @monitor.pid)
|
132
|
+
Process.wait(@monitor.pid)
|
133
|
+
end
|
134
|
+
|
135
|
+
def failover_node(index, bucket = "default")
|
136
|
+
@monitor.client.send("failover,#{index},#{bucket}", 0)
|
137
|
+
end
|
138
|
+
|
139
|
+
def respawn_node(index, bucket = "default")
|
140
|
+
@monitor.client.send("respawn,#{index},#{bucket}", 0)
|
141
|
+
end
|
142
|
+
|
143
|
+
protected
|
144
|
+
|
145
|
+
def command_line(extra = nil)
|
146
|
+
cmd = "java -jar #{File.dirname(__FILE__)}/CouchbaseMock.jar"
|
147
|
+
cmd << " --host #{@host}" if @host
|
148
|
+
cmd << " --port #{@port}" if @port
|
149
|
+
cmd << " --nodes #{@num_nodes}" if @num_nodes
|
150
|
+
cmd << " --vbuckets #{@num_vbuckets}" if @num_vbuckets
|
151
|
+
cmd << " --buckets #{@buckets_spec}" if @buckets_spec
|
152
|
+
cmd << " #{extra}"
|
153
|
+
cmd
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
class MiniTest::Test
|
158
|
+
|
159
|
+
def start_mock(params = {})
|
160
|
+
mock = nil
|
161
|
+
if true # ENV['COUCHBASE_SERVER']
|
162
|
+
mock = CouchbaseServer.new(params)
|
163
|
+
if (params[:port] && mock.port != params[:port]) ||
|
164
|
+
(params[:host] && mock.host != params[:host]) ||
|
165
|
+
mock.buckets_spec != "default:"
|
166
|
+
skip("Unable to configure real cluster. Requested config is: #{params.inspect}")
|
167
|
+
end
|
168
|
+
else
|
169
|
+
mock = CouchbaseMock.new(params)
|
170
|
+
end
|
171
|
+
mock.start
|
172
|
+
mock
|
173
|
+
end
|
174
|
+
|
175
|
+
def stop_mock(mock)
|
176
|
+
assert(mock)
|
177
|
+
mock.stop
|
178
|
+
end
|
179
|
+
|
180
|
+
def with_mock(params = {})
|
181
|
+
return
|
182
|
+
mock = nil
|
183
|
+
if block_given?
|
184
|
+
mock = start_mock(params)
|
185
|
+
yield mock
|
186
|
+
end
|
187
|
+
ensure
|
188
|
+
stop_mock(mock) if mock
|
189
|
+
end
|
190
|
+
|
191
|
+
def uniq_id(*suffixes)
|
192
|
+
test_id = [caller.first[/.*[` ](.*)'/, 1], suffixes].compact.join("_")
|
193
|
+
@ids ||= {}
|
194
|
+
@ids[test_id] ||= Time.now.to_f
|
195
|
+
[test_id, @ids[test_id]].join("_")
|
196
|
+
end
|
197
|
+
|
198
|
+
def after_teardown
|
199
|
+
GC.start
|
200
|
+
end
|
201
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
# Author:: Couchbase <info@couchbase.com>
|
2
|
+
# Copyright:: 2011, 2012 Couchbase, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require File.join(File.dirname(__FILE__), 'setup')
|
19
|
+
|
20
|
+
class TestArithmetic < MiniTest::Test
|
21
|
+
|
22
|
+
def setup
|
23
|
+
@mock = start_mock
|
24
|
+
end
|
25
|
+
|
26
|
+
def teardown
|
27
|
+
stop_mock(@mock)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_trivial_incr_decr
|
31
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
32
|
+
|
33
|
+
connection.set(uniq_id, 1)
|
34
|
+
val = connection.incr(uniq_id)
|
35
|
+
assert_equal 2, val
|
36
|
+
val = connection.get(uniq_id)
|
37
|
+
assert_equal 2, val
|
38
|
+
|
39
|
+
connection.set(uniq_id, 7)
|
40
|
+
val = connection.decr(uniq_id)
|
41
|
+
assert_equal 6, val
|
42
|
+
val = connection.get(uniq_id)
|
43
|
+
assert_equal 6, val
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_it_fails_to_incr_decr_missing_key
|
47
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
48
|
+
|
49
|
+
assert_raises(Couchbase::Error::NotFound) do
|
50
|
+
connection.incr(uniq_id(:missing))
|
51
|
+
end
|
52
|
+
assert_raises(Couchbase::Error::NotFound) do
|
53
|
+
connection.decr(uniq_id(:missing))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_it_allows_to_make_increments_less_verbose_by_forcing_create_by_default
|
58
|
+
connection = Couchbase.connect(:hostname => @mock.host, :port => @mock.port,
|
59
|
+
:default_arithmetic_init => true)
|
60
|
+
assert_raises(Couchbase::Error::NotFound) do
|
61
|
+
connection.get(uniq_id)
|
62
|
+
end
|
63
|
+
assert_equal 0, connection.incr(uniq_id), "return value"
|
64
|
+
assert_equal 0, connection.get(uniq_id), "via get command"
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_it_allows_to_setup_initial_value_during_connection
|
68
|
+
connection = Couchbase.connect(:hostname => @mock.host, :port => @mock.port,
|
69
|
+
:default_arithmetic_init => 10)
|
70
|
+
assert_raises(Couchbase::Error::NotFound) do
|
71
|
+
connection.get(uniq_id)
|
72
|
+
end
|
73
|
+
|
74
|
+
assert_equal 10, connection.incr(uniq_id), "return value"
|
75
|
+
assert_equal 10, connection.get(uniq_id), "via get command"
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_it_allows_to_change_default_initial_value_after_connection
|
79
|
+
connection = Couchbase.connect(:hostname => @mock.host, :port => @mock.port)
|
80
|
+
|
81
|
+
assert_equal 0, connection.default_arithmetic_init
|
82
|
+
assert_raises(Couchbase::Error::NotFound) do
|
83
|
+
connection.incr(uniq_id)
|
84
|
+
end
|
85
|
+
|
86
|
+
connection.default_arithmetic_init = 10
|
87
|
+
assert_equal 10, connection.default_arithmetic_init
|
88
|
+
assert_raises(Couchbase::Error::NotFound) do
|
89
|
+
connection.get(uniq_id)
|
90
|
+
end
|
91
|
+
assert_equal 10, connection.incr(uniq_id), "return value"
|
92
|
+
assert_equal 10, connection.get(uniq_id), "via get command"
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_it_creates_missing_key_when_initial_value_specified
|
96
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
97
|
+
|
98
|
+
val = connection.incr(uniq_id(:missing), :initial => 5)
|
99
|
+
assert_equal 5, val
|
100
|
+
val = connection.incr(uniq_id(:missing), :initial => 5)
|
101
|
+
assert_equal 6, val
|
102
|
+
val = connection.get(uniq_id(:missing))
|
103
|
+
assert_equal 6, val
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_it_uses_zero_as_default_value_for_missing_keys
|
107
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
108
|
+
|
109
|
+
val = connection.incr(uniq_id(:missing), :create => true)
|
110
|
+
assert_equal 0, val
|
111
|
+
val = connection.incr(uniq_id(:missing), :create => true)
|
112
|
+
assert_equal 1, val
|
113
|
+
val = connection.get(uniq_id(:missing))
|
114
|
+
assert_equal 1, val
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_it_allows_custom_ttl
|
118
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
119
|
+
|
120
|
+
val = connection.incr(uniq_id(:missing), :create => true, :ttl => 1)
|
121
|
+
assert_equal 0, val
|
122
|
+
val = connection.incr(uniq_id(:missing), :create => true)
|
123
|
+
assert_equal 1, val
|
124
|
+
sleep(2)
|
125
|
+
assert_raises(Couchbase::Error::NotFound) do
|
126
|
+
connection.get(uniq_id(:missing))
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_decrement_with_absolute_ttl
|
131
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
132
|
+
# absolute TTL: one second from now
|
133
|
+
exp = Time.now.to_i + 1
|
134
|
+
val = connection.decr(uniq_id, 12, :initial => 0, :ttl => exp)
|
135
|
+
assert_equal 0, val
|
136
|
+
assert_equal 0, connection.get(uniq_id)
|
137
|
+
sleep(2)
|
138
|
+
assert_raises(Couchbase::Error::NotFound) do
|
139
|
+
refute connection.get(uniq_id)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_it_allows_custom_delta
|
144
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
145
|
+
|
146
|
+
connection.set(uniq_id, 12)
|
147
|
+
val = connection.incr(uniq_id, 10)
|
148
|
+
assert_equal 22, val
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_it_allows_to_specify_delta_in_options
|
152
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
153
|
+
|
154
|
+
connection.set(uniq_id, 12)
|
155
|
+
options = {:delta => 10}
|
156
|
+
val = connection.incr(uniq_id, options)
|
157
|
+
assert_equal 22, val
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_multi_incr
|
161
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
162
|
+
connection.set(uniq_id(:foo) => 1, uniq_id(:bar) => 1)
|
163
|
+
|
164
|
+
assert_equal [2, 2], connection.incr(uniq_id(:foo), uniq_id(:bar)).values.sort
|
165
|
+
assert_equal [12, 12], connection.incr(uniq_id(:foo), uniq_id(:bar), :delta => 10).values.sort
|
166
|
+
assert_equal [14, 15], connection.incr(uniq_id(:foo) => 2, uniq_id(:bar) => 3).values.sort
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_multi_decr
|
170
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
171
|
+
connection.set(uniq_id(:foo) => 14, uniq_id(:bar) => 15)
|
172
|
+
|
173
|
+
assert_equal [12, 12], connection.decr(uniq_id(:foo) => 2, uniq_id(:bar) => 3).values.sort
|
174
|
+
assert_equal [2, 2], connection.decr(uniq_id(:foo), uniq_id(:bar), :delta => 10).values.sort
|
175
|
+
assert_equal [1, 1], connection.decr(uniq_id(:foo), uniq_id(:bar)).values.sort
|
176
|
+
end
|
177
|
+
end
|
data/test/test_async.rb
ADDED
@@ -0,0 +1,324 @@
|
|
1
|
+
# Author:: Couchbase <info@couchbase.com>
|
2
|
+
# Copyright:: 2011, 2012 Couchbase, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require File.join(File.dirname(__FILE__), 'setup')
|
19
|
+
|
20
|
+
class TestAsync < MiniTest::Test
|
21
|
+
|
22
|
+
def setup
|
23
|
+
@mock = start_mock
|
24
|
+
end
|
25
|
+
|
26
|
+
def teardown
|
27
|
+
stop_mock(@mock)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_result_object_provides_enough_info
|
31
|
+
obj = Couchbase::Result.new
|
32
|
+
assert obj.respond_to?(:success?)
|
33
|
+
assert obj.respond_to?(:error)
|
34
|
+
assert obj.respond_to?(:key)
|
35
|
+
assert obj.respond_to?(:value)
|
36
|
+
assert obj.respond_to?(:node)
|
37
|
+
assert obj.respond_to?(:cas)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_it_requires_block_for_running_loop
|
41
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
42
|
+
refute connection.async?
|
43
|
+
assert_raises(LocalJumpError) do
|
44
|
+
connection.run
|
45
|
+
end
|
46
|
+
connection.run do |conn|
|
47
|
+
assert conn.async?
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_it_resets_async_flag_when_raising_exception_from_callback
|
52
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
53
|
+
|
54
|
+
assert_raises(RuntimeError) do
|
55
|
+
connection.run do |conn|
|
56
|
+
conn.set(uniq_id, "foo") { raise }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
refute connection.async?
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_nested_async_get_set
|
63
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
64
|
+
connection.set(uniq_id, {"bar" => 1})
|
65
|
+
connection.set(uniq_id(:hit), 0)
|
66
|
+
|
67
|
+
connection.run do |conn|
|
68
|
+
conn.get(uniq_id) do
|
69
|
+
conn.get(uniq_id(:hit)) do |res|
|
70
|
+
conn.set(uniq_id(:hit), res.value + 1)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
val = connection.get(uniq_id(:hit))
|
76
|
+
assert_equal 1, val
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_nested_async_set_get
|
80
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
81
|
+
val = nil
|
82
|
+
|
83
|
+
connection.run do |conn|
|
84
|
+
conn.set(uniq_id, "foo") do
|
85
|
+
conn.get(uniq_id) do |res|
|
86
|
+
val = res.value
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
assert_equal "foo", val
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_nested_async_touch_get
|
95
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
96
|
+
connection.set(uniq_id, "foo")
|
97
|
+
success = false
|
98
|
+
val = nil
|
99
|
+
|
100
|
+
connection.run do |conn|
|
101
|
+
conn.touch(uniq_id, :ttl => 1) do |res1|
|
102
|
+
success = res1.success?
|
103
|
+
conn.get(uniq_id) do |res2|
|
104
|
+
val = res2.value
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
assert success
|
110
|
+
assert_equal "foo", val
|
111
|
+
sleep(2)
|
112
|
+
assert_raises(Couchbase::Error::NotFound) do
|
113
|
+
connection.get(uniq_id)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_nested_async_delete_get
|
118
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
119
|
+
cas = connection.set(uniq_id, "foo")
|
120
|
+
success = false
|
121
|
+
val = :unknown
|
122
|
+
|
123
|
+
connection.run do |conn|
|
124
|
+
conn.delete(uniq_id, :cas => cas) do |res1|
|
125
|
+
success = res1.success?
|
126
|
+
conn.get(uniq_id, :quiet => true) do |res2|
|
127
|
+
val = res2.value
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
assert success
|
133
|
+
refute val
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_nested_async_stats_set
|
137
|
+
skip
|
138
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
139
|
+
stats = {}
|
140
|
+
|
141
|
+
connection.run do |conn|
|
142
|
+
conn.stats do |res1|
|
143
|
+
id = uniq_id(res1.node, res1.key)
|
144
|
+
stats[id] = false
|
145
|
+
conn.set(id, res1.value) do |res2|
|
146
|
+
stats[id] = res2.cas
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
stats.keys.each do |key|
|
152
|
+
assert stats[key].is_a?(Numeric)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_nested_async_flush_set
|
157
|
+
skip
|
158
|
+
if @mock.real?
|
159
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
160
|
+
cas = connection.set(uniq_id, "foo")
|
161
|
+
res = {}
|
162
|
+
|
163
|
+
connection.run do |conn|
|
164
|
+
conn.flush do |res1|
|
165
|
+
assert res1.success?, "Expected: successful status code.\nActual: #{res1.error.inspect}"
|
166
|
+
id = uniq_id(res1.node)
|
167
|
+
res[id] = false
|
168
|
+
conn.set(id, true) do |res2|
|
169
|
+
res[id] = res2.cas
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
assert_raises(Couchbase::Error::NotFound) do
|
175
|
+
connection.get(uniq_id)
|
176
|
+
end
|
177
|
+
res.keys.each do |key|
|
178
|
+
assert res[key].is_a?(Numeric)
|
179
|
+
assert connection.get(key)
|
180
|
+
end
|
181
|
+
else
|
182
|
+
skip("REST FLUSH isn't implemented in CouchbaseMock.jar yet")
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_nested_async_incr_get
|
187
|
+
skip
|
188
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
189
|
+
cas = connection.set(uniq_id, 1)
|
190
|
+
val = nil
|
191
|
+
|
192
|
+
connection.run do |conn|
|
193
|
+
conn.incr(uniq_id) do
|
194
|
+
conn.get(uniq_id) do |res|
|
195
|
+
val = res.value
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
assert_equal 2, val
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_it_doesnt_accept_callbacks_in_synchronous_mode
|
204
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
205
|
+
refute connection.async?
|
206
|
+
|
207
|
+
assert_raises(ArgumentError) { connection.add(uniq_id, "foo") {} }
|
208
|
+
assert_raises(ArgumentError) { connection.set(uniq_id, "foo") {} }
|
209
|
+
assert_raises(ArgumentError) { connection.replace(uniq_id, "foo") {} }
|
210
|
+
assert_raises(ArgumentError) { connection.get(uniq_id) {} }
|
211
|
+
assert_raises(ArgumentError) { connection.touch(uniq_id) {} }
|
212
|
+
assert_raises(ArgumentError) { connection.incr(uniq_id) {} }
|
213
|
+
assert_raises(ArgumentError) { connection.decr(uniq_id) {} }
|
214
|
+
assert_raises(ArgumentError) { connection.delete(uniq_id) {} }
|
215
|
+
assert_raises(ArgumentError) { connection.append(uniq_id, "bar") {} }
|
216
|
+
assert_raises(ArgumentError) { connection.prepend(uniq_id, "bar") {} }
|
217
|
+
assert_raises(ArgumentError) { connection.flush {} }
|
218
|
+
assert_raises(ArgumentError) { connection.stats {} }
|
219
|
+
end
|
220
|
+
|
221
|
+
def test_it_disallow_nested_run
|
222
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
223
|
+
assert_raises(Couchbase::Error::Invalid) do
|
224
|
+
connection.run do
|
225
|
+
connection.run do
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_it_extends_timeout_in_async_mode_if_needed
|
232
|
+
skip
|
233
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
234
|
+
connection.set(uniq_id, "foo")
|
235
|
+
|
236
|
+
connection.timeout = 100_000 # 100_000 us
|
237
|
+
connection.run do
|
238
|
+
connection.get(uniq_id) do |ret|
|
239
|
+
assert ret.success?
|
240
|
+
assert_equal "foo", ret.value
|
241
|
+
end
|
242
|
+
sleep(1.5) # 1_500_000 us
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def test_send_threshold
|
247
|
+
skip
|
248
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
249
|
+
|
250
|
+
sent = false
|
251
|
+
connection.run(:send_threshold => 100) do # 100 bytes
|
252
|
+
connection.set(uniq_id, "foo" * 100) {|r| sent = true}
|
253
|
+
assert sent
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def test_asynchronous_connection
|
258
|
+
skip
|
259
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port, :async => true)
|
260
|
+
refute connection.connected?, "new asynchronous connection must be disconnected"
|
261
|
+
connection.on_connect do |res|
|
262
|
+
assert res.success?, "on_connect called with error #{res.error.inspect}"
|
263
|
+
assert_same connection, res.bucket
|
264
|
+
end
|
265
|
+
connection.run {}
|
266
|
+
assert connection.connected?, "it should be connected after first run"
|
267
|
+
end
|
268
|
+
|
269
|
+
def test_it_calls_callback_immediately_if_connected_sync
|
270
|
+
skip
|
271
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
|
272
|
+
assert connection.connected?, "connection wasn't established in sync mode"
|
273
|
+
called = false
|
274
|
+
connection.on_connect do |res|
|
275
|
+
assert res.success?, "on_connect called with error #{res.error.inspect}"
|
276
|
+
called = true
|
277
|
+
end
|
278
|
+
assert called, "the callback hasn't been called on set"
|
279
|
+
called = false
|
280
|
+
connection.on_connect do |res|
|
281
|
+
assert res.success?, "on_connect called with error #{res.error.inspect}"
|
282
|
+
called = true
|
283
|
+
end
|
284
|
+
refute called, "the callback must not be called on subsequent sets"
|
285
|
+
end
|
286
|
+
|
287
|
+
def test_it_calls_callback_immediately_if_connected_async
|
288
|
+
skip
|
289
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port, :async => true)
|
290
|
+
refute connection.connected?, "new asynchronous connection must be disconnected"
|
291
|
+
called = false
|
292
|
+
connection.run {}
|
293
|
+
assert connection.connected?, "the connection must be established"
|
294
|
+
connection.run do
|
295
|
+
connection.on_connect do |res|
|
296
|
+
assert res.success?, "on_connect called with error #{res.error.inspect}"
|
297
|
+
called = true
|
298
|
+
end
|
299
|
+
end
|
300
|
+
assert called, "the callback hasn't been called on set"
|
301
|
+
called = false
|
302
|
+
connection.run do
|
303
|
+
connection.on_connect do |res|
|
304
|
+
assert res.success?, "on_connect called with error #{res.error.inspect}"
|
305
|
+
called = true
|
306
|
+
end
|
307
|
+
end
|
308
|
+
refute called, "the callback must not be called on subsequent sets"
|
309
|
+
end
|
310
|
+
|
311
|
+
def test_it_returns_error_if_user_start_work_on_disconnected_instance_outside_on_connect_callback
|
312
|
+
skip
|
313
|
+
connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port, :async => true)
|
314
|
+
refute connection.connected?, "new asynchronous connection must be disconnected"
|
315
|
+
error = nil
|
316
|
+
connection.on_error do |ex|
|
317
|
+
error = ex
|
318
|
+
end
|
319
|
+
connection.run do |c|
|
320
|
+
c.set("foo", "bar")
|
321
|
+
end
|
322
|
+
assert_instance_of(Couchbase::Error::Connect, error)
|
323
|
+
end
|
324
|
+
end
|