couchbase-jruby-client 0.1.1

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.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.jrubyrc +722 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +203 -0
  7. data/README.md +349 -0
  8. data/Rakefile +10 -0
  9. data/couchbase-jruby-client.gemspec +31 -0
  10. data/lib/couchbase/async/callback.rb +19 -0
  11. data/lib/couchbase/async/queue.rb +26 -0
  12. data/lib/couchbase/async.rb +140 -0
  13. data/lib/couchbase/bucket.rb +556 -0
  14. data/lib/couchbase/cluster.rb +105 -0
  15. data/lib/couchbase/constants.rb +12 -0
  16. data/lib/couchbase/design_doc.rb +61 -0
  17. data/lib/couchbase/error.rb +43 -0
  18. data/lib/couchbase/jruby/couchbase_client.rb +22 -0
  19. data/lib/couchbase/jruby/future.rb +8 -0
  20. data/lib/couchbase/operations/arithmetic.rb +301 -0
  21. data/lib/couchbase/operations/delete.rb +104 -0
  22. data/lib/couchbase/operations/design_docs.rb +99 -0
  23. data/lib/couchbase/operations/get.rb +282 -0
  24. data/lib/couchbase/operations/stats.rb +26 -0
  25. data/lib/couchbase/operations/store.rb +461 -0
  26. data/lib/couchbase/operations/touch.rb +136 -0
  27. data/lib/couchbase/operations/unlock.rb +192 -0
  28. data/lib/couchbase/operations/utils.rb +44 -0
  29. data/lib/couchbase/operations.rb +27 -0
  30. data/lib/couchbase/query.rb +73 -0
  31. data/lib/couchbase/result.rb +43 -0
  32. data/lib/couchbase/transcoder.rb +77 -0
  33. data/lib/couchbase/utils.rb +62 -0
  34. data/lib/couchbase/version.rb +3 -0
  35. data/lib/couchbase/view.rb +367 -0
  36. data/lib/couchbase/view_row.rb +193 -0
  37. data/lib/couchbase.rb +157 -0
  38. data/lib/jars/commons-codec-1.5.jar +0 -0
  39. data/lib/jars/couchbase-client-1.2.0-javadoc.jar +0 -0
  40. data/lib/jars/couchbase-client-1.2.0-sources.jar +0 -0
  41. data/lib/jars/couchbase-client-1.2.0.jar +0 -0
  42. data/lib/jars/httpcore-4.1.1.jar +0 -0
  43. data/lib/jars/httpcore-nio-4.1.1.jar +0 -0
  44. data/lib/jars/jettison-1.1.jar +0 -0
  45. data/lib/jars/netty-3.5.5.Final.jar +0 -0
  46. data/lib/jars/spymemcached-2.10.0-javadoc.jar +0 -0
  47. data/lib/jars/spymemcached-2.10.0-sources.jar +0 -0
  48. data/lib/jars/spymemcached-2.10.0.jar +0 -0
  49. data/test/profile/.gitignore +1 -0
  50. data/test/profile/.jrubyrc +722 -0
  51. data/test/profile/Gemfile +6 -0
  52. data/test/profile/benchmark.rb +168 -0
  53. data/test/profile/profile.rb +59 -0
  54. data/test/setup.rb +203 -0
  55. data/test/test_arithmetic.rb +177 -0
  56. data/test/test_async.rb +324 -0
  57. data/test/test_bucket.rb +213 -0
  58. data/test/test_cas.rb +79 -0
  59. data/test/test_couchbase.rb +29 -0
  60. data/test/test_couchbase_rails_cache_store.rb +341 -0
  61. data/test/test_delete.rb +125 -0
  62. data/test/test_design_docs.rb +72 -0
  63. data/test/test_errors.rb +82 -0
  64. data/test/test_format.rb +161 -0
  65. data/test/test_get.rb +417 -0
  66. data/test/test_query.rb +23 -0
  67. data/test/test_stats.rb +57 -0
  68. data/test/test_store.rb +213 -0
  69. data/test/test_timer.rb +43 -0
  70. data/test/test_touch.rb +97 -0
  71. data/test/test_unlock.rb +121 -0
  72. data/test/test_utils.rb +58 -0
  73. data/test/test_version.rb +53 -0
  74. data/test/test_view.rb +94 -0
  75. metadata +255 -0
@@ -0,0 +1,168 @@
1
+ # Useful environment variables:
2
+ #
3
+ # LOOPS (50000)
4
+ # how many time run exercises
5
+ #
6
+ # HOST (127.0.0.1)
7
+ # the host where cluster is running. benchmark will use default ports to
8
+ # connect to it (11211 and 8091)
9
+ #
10
+ # STACK_DEPTH (0)
11
+ # the depth of stack where exercises are run. the benchmark will
12
+ # recursively go to given depth before run
13
+ #
14
+ # TEST ('')
15
+ # use to run specific test (possible values are: set, get, get-multi,
16
+ # append, prepend, delete, get-missing, append-missing, prepend-missing,
17
+ # set-large, get-large)
18
+ #
19
+ # CLIENT ('')
20
+ # use to run with specific client (possible values are: couchbase, dalli,
21
+ # memcached, memcached:buffer)
22
+ #
23
+ # DEBUG ('')
24
+ # show exceptions
25
+ #
26
+
27
+ require 'rubygems'
28
+ require 'bundler/setup'
29
+
30
+ $LOAD_PATH << File.join(File.dirname(__FILE__), "..", "..", "lib")
31
+ require 'couchbase'
32
+ require 'benchmark/ips'
33
+
34
+ puts `uname -a`
35
+ puts File.readlines('/proc/cpuinfo').sort.uniq.grep(/model name|cpu cores/) rescue nil
36
+ puts RUBY_DESCRIPTION
37
+
38
+ class Bench
39
+
40
+ def initialize
41
+
42
+ puts "PID is #{Process.pid}"
43
+
44
+ @value = { 'im' => [ 'testing', 'stuff' ] }
45
+
46
+ puts "Raw value size is: #{@value.size} bytes"
47
+
48
+ @keys = [
49
+ @k1 = "Short",
50
+ @k2 = "Sym1-2-3::45" * 8,
51
+ @k3 = "Long" * 40,
52
+ @k4 = "Medium" * 8,
53
+ @k5 = "Medium2" * 8,
54
+ @k6 = "Long3" * 40]
55
+
56
+ @cb = Couchbase.new
57
+
58
+ # Ensure it is JITed
59
+ 2_000.times do
60
+ @cb.set(@k1, 'a')
61
+ @cb.get(@k1)
62
+ end
63
+ end
64
+
65
+ def run
66
+ Benchmark.ips do |x|
67
+ x.report('jruby set') do
68
+ @cb.set @k1, @value
69
+ @cb.set @k2, @value
70
+ @cb.set @k3, @value
71
+ end
72
+
73
+ x.report('java set') do
74
+ @cb.client.set(@k1, MultiJson.dump(@value)).get
75
+ @cb.client.set(@k2, MultiJson.dump(@value)).get
76
+ @cb.client.set(@k3, MultiJson.dump(@value)).get
77
+ end
78
+
79
+ x.report('jruby get') do
80
+ @cb.get @k1
81
+ @cb.get @k2
82
+ @cb.get @k3
83
+ end
84
+
85
+ x.report('java get') do
86
+ MultiJson.load @cb.client.get(@k1)
87
+ MultiJson.load @cb.client.get(@k2)
88
+ MultiJson.load @cb.client.get(@k3)
89
+ end
90
+
91
+ x.report('jruby delete') do
92
+ @cb.set @k1, ''
93
+ @cb.set @k2, ''
94
+ @cb.set @k3, ''
95
+ @cb.delete(@k1)
96
+ @cb.delete(@k2)
97
+ @cb.delete(@k3)
98
+ end
99
+
100
+ x.report('java delete') do
101
+ @cb.set @k1, ''
102
+ @cb.set @k2, ''
103
+ @cb.set @k3, ''
104
+ @cb.client.delete @k1
105
+ @cb.client.delete @k2
106
+ @cb.client.delete @k3
107
+ end
108
+
109
+ x.report('jruby get missing') do
110
+ @cb.get(@k1, quiet: true)
111
+ @cb.get(@k2, quiet: true)
112
+ @cb.get(@k3, quiet: true)
113
+ end
114
+
115
+ x.report('java get missing') do
116
+ @cb.client.get @k1
117
+ @cb.client.get @k2
118
+ @cb.client.get @k3
119
+ end
120
+
121
+ x.report('jruby async set') do
122
+ @cb.run do
123
+ 100.times do
124
+ @cb.set @k1, @value
125
+ @cb.set @k2, @value
126
+ @cb.set @k3, @value
127
+ end
128
+ end
129
+ end
130
+
131
+ x.report('java async set') do
132
+ futures = []
133
+ 100.times do
134
+ futures << @cb.client.set(@k1, MultiJson.dump(@value))
135
+ futures << @cb.client.set(@k2, MultiJson.dump(@value))
136
+ futures << @cb.client.set(@k3, MultiJson.dump(@value))
137
+ end
138
+ futures.each(&:get)
139
+ end
140
+
141
+ x.report('jruby async get') do
142
+ @cb.run do
143
+ 100.times do
144
+ @cb.get @k1
145
+ @cb.get @k2
146
+ @cb.get @k3
147
+ end
148
+ end
149
+ end
150
+
151
+ x.report('java async get') do
152
+ futures = []
153
+ 100.times do
154
+ futures << @cb.client.asyncGet(@k1)
155
+ futures << @cb.client.asyncGet(@k2)
156
+ futures << @cb.client.asyncGet(@k3)
157
+ end
158
+ futures.each(&:get)
159
+ end
160
+
161
+ end
162
+
163
+ @cb.disconnect
164
+ end
165
+
166
+ end
167
+
168
+ Bench.new.run
@@ -0,0 +1,59 @@
1
+
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
+
5
+ $LOAD_PATH << File.join(File.dirname(__FILE__), "..", "..", "lib")
6
+ require 'couchbase'
7
+ require 'jruby/profiler'
8
+
9
+ puts `uname -a`
10
+ puts File.readlines('/proc/cpuinfo').sort.uniq.grep(/model name|cpu cores/) rescue nil
11
+ puts RUBY_DESCRIPTION
12
+
13
+ class Profile
14
+
15
+ def initialize
16
+
17
+ puts "PID is #{Process.pid}"
18
+
19
+ @value = { 'im' => [ 'testing', 'stuff' ] }
20
+
21
+ puts "Raw value size is: #{@value.size} bytes"
22
+
23
+ @keys = [
24
+ @k1 = "Short",
25
+ @k2 = "Sym1-2-3::45" * 8,
26
+ @k3 = "Long" * 40,
27
+ @k4 = "Medium" * 8,
28
+ @k5 = "Medium2" * 8,
29
+ @k6 = "Long3" * 40]
30
+
31
+ @cb = Couchbase.new
32
+
33
+
34
+ end
35
+
36
+ def run
37
+ profile_data = JRuby::Profiler.profile do
38
+ 2_000.times do
39
+ @cb.set(@k1, @value)
40
+ @cb.set(@k2, @value)
41
+ @cb.set(@k3, @value)
42
+ end
43
+
44
+ 2_000.times do
45
+ @cb.get(@k1)
46
+ @cb.get(@k2)
47
+ @cb.get(@k3)
48
+ end
49
+ end
50
+
51
+ profile_printer = JRuby::Profiler::GraphProfilePrinter.new(profile_data)
52
+ profile_printer.printProfile(STDOUT)
53
+
54
+ @cb.disconnect
55
+ end
56
+
57
+ end
58
+
59
+ Profile.new.run
data/test/setup.rb ADDED
@@ -0,0 +1,203 @@
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
+ require 'pry'
26
+
27
+ # Surpress connection logging
28
+ # java_import java.lang.System
29
+ # java_import java.util.logging.Logger
30
+ # java_import java.util.logging.Level
31
+
32
+ # properties = System.getProperties
33
+ # properties.put("net.spy.log.LoggerImpl", "net.spy.memcached.compat.log.Log4JLogger")
34
+ # System.setProperties(properties)
35
+
36
+ # Logger.getLogger('net.spy.memcached').setLevel(Level::SEVERE)
37
+ # Logger.getLogger('com.couchbase.client').setLevel(Level::SEVERE)
38
+ # Logger.getLogger('com.couchbase.client.vbucket').setLevel(Level::SEVERE)
39
+
40
+ # $stderr = StringIO.new
41
+
42
+ Minitest.after_run { Couchbase.disconnect }
43
+
44
+ class CouchbaseServer
45
+ attr_accessor :host, :port, :num_nodes, :buckets_spec
46
+
47
+ def real?
48
+ true
49
+ end
50
+
51
+ def initialize(params = {})
52
+ @host, @port = ['localhost', 8091] #ENV['COUCHBASE_SERVER'].split(':')
53
+ @port = @port.to_i
54
+
55
+ if @host.nil? || @host.empty? || @port == 0
56
+ raise ArgumentError, "Check COUCHBASE_SERVER variable. It should be hostname:port"
57
+ end
58
+
59
+ @config = MultiJson.load(open("http://#{@host}:#{@port}/pools/default"))
60
+ @num_nodes = @config["nodes"].size
61
+ @buckets_spec = params[:buckets_spec] || "default:" # "default:,protected:secret,cache::memcache"
62
+ end
63
+
64
+ def start
65
+ # flush all buckets
66
+ @buckets_spec.split(',') do |bucket|
67
+ name, password, _ = bucket.split(':')
68
+ connection = Couchbase.new(:hostname => @host,
69
+ :port => @port,
70
+ :username => name,
71
+ :bucket => name,
72
+ :password => password)
73
+ begin
74
+ connection.flush
75
+ rescue Couchbase::Error::NotSupported
76
+ # on recent server flush is disabled
77
+ ensure
78
+ connection.disconnect
79
+ end
80
+ end if ENV['COUCHBASE_FLUSH_BUCKETS']
81
+ end
82
+
83
+ def stop
84
+ end
85
+ end
86
+
87
+ class CouchbaseMock
88
+ Monitor = Struct.new(:pid, :client, :socket, :port)
89
+
90
+ attr_accessor :host, :port, :buckets_spec, :num_nodes, :num_vbuckets
91
+
92
+ def real?
93
+ false
94
+ end
95
+
96
+ def initialize(params = {})
97
+ @host = "127.0.0.1"
98
+ @port = 0
99
+ @num_nodes = 10
100
+ @num_vbuckets = 4096
101
+ @buckets_spec = "default:" # "default:,protected:secret,cache::memcache"
102
+ params.each do |key, value|
103
+ send("#{key}=", value)
104
+ end
105
+ yield self if block_given?
106
+ if @num_vbuckets < 1 || (@num_vbuckets & (@num_vbuckets - 1) != 0)
107
+ raise ArgumentError, "Number of vbuckets should be a power of two and greater than zero"
108
+ end
109
+ end
110
+
111
+ def start
112
+ @monitor = Monitor.new
113
+ @monitor.socket = TCPServer.new(nil, 0)
114
+ @monitor.socket.listen(10)
115
+ _, @monitor.port, _, _ = @monitor.socket.addr
116
+ trap("CLD") do
117
+ puts "CouchbaseMock.jar died unexpectedly during startup"
118
+ exit(1)
119
+ end
120
+ @monitor.pid = fork
121
+ if @monitor.pid.nil?
122
+ rc = exec(command_line("--harakiri-monitor=:#{@monitor.port}"))
123
+ else
124
+ trap("CLD", "SIG_DFL")
125
+ @monitor.client, _ = @monitor.socket.accept
126
+ @port = @monitor.client.recv(100).to_i
127
+ end
128
+ end
129
+
130
+ def stop
131
+ @monitor.client.close
132
+ @monitor.socket.close
133
+ Process.kill("TERM", @monitor.pid)
134
+ Process.wait(@monitor.pid)
135
+ end
136
+
137
+ def failover_node(index, bucket = "default")
138
+ @monitor.client.send("failover,#{index},#{bucket}", 0)
139
+ end
140
+
141
+ def respawn_node(index, bucket = "default")
142
+ @monitor.client.send("respawn,#{index},#{bucket}", 0)
143
+ end
144
+
145
+ protected
146
+
147
+ def command_line(extra = nil)
148
+ cmd = "java -jar #{File.dirname(__FILE__)}/CouchbaseMock.jar"
149
+ cmd << " --host #{@host}" if @host
150
+ cmd << " --port #{@port}" if @port
151
+ cmd << " --nodes #{@num_nodes}" if @num_nodes
152
+ cmd << " --vbuckets #{@num_vbuckets}" if @num_vbuckets
153
+ cmd << " --buckets #{@buckets_spec}" if @buckets_spec
154
+ cmd << " #{extra}"
155
+ cmd
156
+ end
157
+ end
158
+
159
+ class MiniTest::Test
160
+
161
+ def start_mock(params = {})
162
+ mock = nil
163
+ if true # ENV['COUCHBASE_SERVER']
164
+ mock = CouchbaseServer.new(params)
165
+ if (params[:port] && mock.port != params[:port]) ||
166
+ (params[:host] && mock.host != params[:host]) ||
167
+ mock.buckets_spec != "default:"
168
+ skip("Unable to configure real cluster. Requested config is: #{params.inspect}")
169
+ end
170
+ else
171
+ mock = CouchbaseMock.new(params)
172
+ end
173
+ mock.start
174
+ mock
175
+ end
176
+
177
+ def stop_mock(mock)
178
+ assert(mock)
179
+ mock.stop
180
+ end
181
+
182
+ def with_mock(params = {})
183
+ return
184
+ mock = nil
185
+ if block_given?
186
+ mock = start_mock(params)
187
+ yield mock
188
+ end
189
+ ensure
190
+ stop_mock(mock) if mock
191
+ end
192
+
193
+ def uniq_id(*suffixes)
194
+ test_id = [caller.first[/.*[` ](.*)'/, 1], suffixes].compact.join("_")
195
+ @ids ||= {}
196
+ @ids[test_id] ||= Time.now.to_f
197
+ [test_id, @ids[test_id]].join("_")
198
+ end
199
+
200
+ def after_teardown
201
+ GC.start
202
+ end
203
+ 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(3)
138
+ assert_raises(Couchbase::Error::NotFound) do
139
+ 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