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.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +203 -0
  6. data/README.md +347 -0
  7. data/Rakefile +10 -0
  8. data/couchbase-jruby-client.gemspec +30 -0
  9. data/lib/couchbase/async/callback.rb +19 -0
  10. data/lib/couchbase/async/queue.rb +26 -0
  11. data/lib/couchbase/async.rb +139 -0
  12. data/lib/couchbase/bucket.rb +663 -0
  13. data/lib/couchbase/cluster.rb +105 -0
  14. data/lib/couchbase/constants.rb +12 -0
  15. data/lib/couchbase/error.rb +28 -0
  16. data/lib/couchbase/jruby/couchbase_client.rb +22 -0
  17. data/lib/couchbase/jruby/future.rb +8 -0
  18. data/lib/couchbase/operations/arithmetic.rb +301 -0
  19. data/lib/couchbase/operations/delete.rb +104 -0
  20. data/lib/couchbase/operations/get.rb +298 -0
  21. data/lib/couchbase/operations/stats.rb +16 -0
  22. data/lib/couchbase/operations/store.rb +468 -0
  23. data/lib/couchbase/operations/touch.rb +123 -0
  24. data/lib/couchbase/operations/utils.rb +49 -0
  25. data/lib/couchbase/operations.rb +23 -0
  26. data/lib/couchbase/result.rb +43 -0
  27. data/lib/couchbase/transcoder.rb +83 -0
  28. data/lib/couchbase/utils.rb +62 -0
  29. data/lib/couchbase/version.rb +3 -0
  30. data/lib/couchbase/view.rb +506 -0
  31. data/lib/couchbase/view_row.rb +272 -0
  32. data/lib/couchbase.rb +177 -0
  33. data/lib/jars/commons-codec-1.5.jar +0 -0
  34. data/lib/jars/couchbase-client-1.2.0-javadoc.jar +0 -0
  35. data/lib/jars/couchbase-client-1.2.0-sources.jar +0 -0
  36. data/lib/jars/couchbase-client-1.2.0.jar +0 -0
  37. data/lib/jars/httpcore-4.1.1.jar +0 -0
  38. data/lib/jars/httpcore-nio-4.1.1.jar +0 -0
  39. data/lib/jars/jettison-1.1.jar +0 -0
  40. data/lib/jars/netty-3.5.5.Final.jar +0 -0
  41. data/lib/jars/spymemcached-2.10.0-javadoc.jar +0 -0
  42. data/lib/jars/spymemcached-2.10.0-sources.jar +0 -0
  43. data/lib/jars/spymemcached-2.10.0.jar +0 -0
  44. data/test/profile/.gitignore +1 -0
  45. data/test/profile/Gemfile +6 -0
  46. data/test/profile/benchmark.rb +195 -0
  47. data/test/setup.rb +201 -0
  48. data/test/test_arithmetic.rb +177 -0
  49. data/test/test_async.rb +324 -0
  50. data/test/test_bucket.rb +213 -0
  51. data/test/test_cas.rb +78 -0
  52. data/test/test_couchbase.rb +29 -0
  53. data/test/test_couchbase_rails_cache_store.rb +341 -0
  54. data/test/test_delete.rb +125 -0
  55. data/test/test_errors.rb +82 -0
  56. data/test/test_format.rb +161 -0
  57. data/test/test_get.rb +417 -0
  58. data/test/test_stats.rb +57 -0
  59. data/test/test_store.rb +216 -0
  60. data/test/test_timer.rb +42 -0
  61. data/test/test_touch.rb +97 -0
  62. data/test/test_unlock.rb +119 -0
  63. data/test/test_utils.rb +58 -0
  64. data/test/test_version.rb +52 -0
  65. metadata +226 -0
@@ -0,0 +1,213 @@
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 TestBucket < MiniTest::Test
21
+
22
+ def test_it_substitute_default_parts_to_url
23
+
24
+ with_mock(:host => 'localhost') do |mock| # pick first free port
25
+ connections = [
26
+ Couchbase.new("http://#{mock.host}:#{mock.port}"),
27
+ Couchbase.new(:port => mock.port),
28
+ Couchbase.new("http://#{mock.host}:8091", :port => mock.port)
29
+ ]
30
+ connections.each do |connection|
31
+ assert_equal mock.port, connection.port
32
+ assert_equal "#{mock.host}:#{mock.port}", connection.authority
33
+ assert_equal "http://#{mock.host}:#{mock.port}/pools/default/buckets/default/", connection.url
34
+ end
35
+ end
36
+
37
+ with_mock(:host => '127.0.0.1') do |mock|
38
+ connections = [
39
+ Couchbase.new("http://#{mock.host}:#{mock.port}"),
40
+ Couchbase.new(:hostname => mock.host, :port => mock.port),
41
+ Couchbase.new('http://example.com:8091', :hostname => mock.host, :port => mock.port)
42
+ ]
43
+ connections.each do |connection|
44
+ assert_equal mock.host, connection.hostname
45
+ assert_equal "#{mock.host}:#{mock.port}", connection.authority
46
+ assert_equal "http://#{mock.host}:#{mock.port}/pools/default/buckets/default/", connection.url
47
+ end
48
+ end
49
+ end
50
+
51
+ def test_it_raises_network_error_if_server_not_found
52
+ skip 'Exception not being trapped correctly'
53
+ refute(`netstat -tnl` =~ /12345/)
54
+ assert_raises Couchbase::Error::Connect do
55
+ Couchbase.new(:port => 12345)
56
+ end
57
+ end
58
+
59
+ def test_it_raises_argument_error_for_illegal_url
60
+ illegal = [
61
+ "ftp://localhost:8091/",
62
+ "http:/localhost:8091/",
63
+ ""
64
+ ]
65
+ illegal.each do |url|
66
+ assert_raises ArgumentError do
67
+ Couchbase.new(url)
68
+ end
69
+ end
70
+ end
71
+
72
+ def test_it_able_to_connect_to_protected_buckets
73
+ with_mock(:buckets_spec => 'protected:secret') do |mock|
74
+ connection = Couchbase.new(:hostname => mock.host,
75
+ :port => mock.port,
76
+ :bucket => 'protected',
77
+ :username => 'protected',
78
+ :password => 'secret')
79
+ assert_equal "protected", connection.bucket
80
+ assert_equal "protected", connection.username
81
+ assert_equal "secret", connection.password
82
+ end
83
+ end
84
+
85
+ def test_it_allows_to_specify_credentials_in_url
86
+ with_mock(:buckets_spec => 'protected:secret') do |mock|
87
+ connection = Couchbase.new("http://protected:secret@#{mock.host}:#{mock.port}/pools/default/buckets/protected/")
88
+ assert_equal "protected", connection.bucket
89
+ assert_equal "protected", connection.username
90
+ assert_equal "secret", connection.password
91
+ end
92
+ end
93
+
94
+ def test_it_raises_error_with_wrong_credentials
95
+ with_mock do |mock|
96
+ assert_raises Couchbase::Error::Auth do
97
+ Couchbase.new(:hostname => mock.host,
98
+ :port => mock.port,
99
+ :bucket => 'default',
100
+ :username => 'wrong.username',
101
+ :password => 'wrong_password')
102
+ end
103
+ end
104
+ end
105
+
106
+ def test_it_unable_to_connect_to_protected_buckets_with_wrong_credentials
107
+ with_mock(:buckets_spec => 'protected:secret') do |mock|
108
+ assert_raises Couchbase::Error::Auth do
109
+ Couchbase.new(:hostname => mock.host,
110
+ :port => mock.port,
111
+ :bucket => 'protected',
112
+ :username => 'wrong',
113
+ :password => 'secret')
114
+ end
115
+ assert_raises Couchbase::Error::Auth do
116
+ Couchbase.new(:hostname => mock.host,
117
+ :port => mock.port,
118
+ :bucket => 'protected',
119
+ :username => 'protected',
120
+ :password => 'wrong')
121
+ end
122
+ end
123
+ end
124
+
125
+ def test_it_allows_change_quiet_flag
126
+ with_mock do |mock|
127
+ connection = Couchbase.new(:hostname => mock.host,
128
+ :port => mock.port)
129
+
130
+ refute connection.quiet?
131
+
132
+ connection = Couchbase.new(:hostname => mock.host,
133
+ :port => mock.port,
134
+ :quiet => true)
135
+ assert connection.quiet?
136
+
137
+ connection.quiet = nil
138
+ assert_equal false, connection.quiet?
139
+
140
+ connection.quiet = :foo
141
+ assert_equal true, connection.quiet?
142
+ end
143
+ end
144
+
145
+ def test_it_is_connected
146
+ with_mock do |mock|
147
+ connection = Couchbase.new(:hostname => mock.host,
148
+ :port => mock.port)
149
+ assert connection.connected?
150
+ end
151
+ end
152
+
153
+ def test_it_is_possible_to_disconnect_instance
154
+ with_mock do |mock|
155
+ connection = Couchbase.new(:hostname => mock.host,
156
+ :port => mock.port)
157
+ connection.disconnect
158
+ refute connection.connected?
159
+ end
160
+ end
161
+
162
+ def test_it_raises_error_on_double_disconnect
163
+ with_mock do |mock|
164
+ connection = Couchbase.new(:hostname => mock.host,
165
+ :port => mock.port)
166
+ connection.disconnect
167
+ assert_raises Couchbase::Error::Connect do
168
+ connection.disconnect
169
+ end
170
+ end
171
+ end
172
+
173
+ def test_it_allows_to_reconnect_the_instance
174
+ with_mock do |mock|
175
+ connection = Couchbase.new(:hostname => mock.host,
176
+ :port => mock.port)
177
+ connection.disconnect
178
+ refute connection.connected?
179
+ connection.reconnect
180
+ assert connection.connected?
181
+ assert connection.set(uniq_id, "foo")
182
+ end
183
+ end
184
+
185
+ def test_it_allows_to_change_configuration_during_reconnect
186
+ with_mock(:buckets_spec => 'protected:secret') do |mock|
187
+ connection = Couchbase.new(:hostname => mock.host,
188
+ :port => mock.port,
189
+ :bucket => 'protected',
190
+ :username => 'protected',
191
+ :password => 'secret')
192
+ connection.disconnect
193
+ assert_raises Couchbase::Error::Auth do
194
+ connection.reconnect(:password => 'incorrect')
195
+ end
196
+ refute connection.connected?
197
+
198
+ connection.reconnect(:password => 'secret')
199
+ assert connection.connected?
200
+ end
201
+ end
202
+
203
+ def test_it_uses_bucket_name_as_username_if_username_is_empty
204
+ with_mock(:buckets_spec => 'protected:secret') do |mock|
205
+ connection = Couchbase.new(:hostname => mock.host,
206
+ :port => mock.port,
207
+ :bucket => 'protected',
208
+ :password => 'secret')
209
+ assert connection.connected?
210
+ end
211
+ end
212
+
213
+ end
data/test/test_cas.rb ADDED
@@ -0,0 +1,78 @@
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 TestCas < 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_compare_and_swap
31
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
32
+ :default_format => :document)
33
+ connection.set(uniq_id, {"bar" => 1})
34
+ connection.cas(uniq_id) do |val|
35
+ val["baz"] = 2
36
+ val
37
+ end
38
+ val = connection.get(uniq_id)
39
+ expected = {"bar" => 1, "baz" => 2}
40
+ assert_equal expected, val
41
+ end
42
+
43
+ def test_compare_and_swap_async
44
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
45
+ :default_format => :document)
46
+ connection.set(uniq_id, {"bar" => 1})
47
+ calls = 0
48
+ connection.run do |conn|
49
+ conn.cas(uniq_id) do |ret|
50
+ calls += 1
51
+ case ret.operation
52
+ when :get
53
+ new_val = ret.value
54
+ new_val["baz"] = 2
55
+ new_val
56
+ when :set
57
+ assert ret.success?
58
+ else
59
+ flunk "Unexpected operation: #{ret.operation.inspect}"
60
+ end
61
+ end
62
+ end
63
+ assert_equal 2, calls
64
+ val = connection.get(uniq_id)
65
+ expected = {"bar" => 1, "baz" => 2}
66
+ assert_equal expected, val
67
+ end
68
+
69
+ def test_flags_replication
70
+ skip
71
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
72
+ :default_format => :document)
73
+ connection.set(uniq_id, "bar", :flags => 0x100)
74
+ connection.cas(uniq_id) { "baz" }
75
+ _, flags, _ = connection.get(uniq_id, :extended => true)
76
+ assert_equal 0x100, flags
77
+ end
78
+ end
@@ -0,0 +1,29 @@
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
+ require 'minitest/mock'
20
+
21
+ class TestCouchbase < MiniTest::Test
22
+
23
+ def test_that_it_create_instance_of_bucket
24
+ with_mock do |mock|
25
+ assert_instance_of Couchbase::Bucket, Couchbase.new("http://#{mock.host}:#{mock.port}")
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,341 @@
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
+ # require 'active_support/cache/couchbase_store'
20
+ # require 'active_support/notifications'
21
+ # require 'ostruct'
22
+
23
+ # class TestCouchbaseRailsCacheStore < MiniTest::Test
24
+
25
+ # def setup
26
+ # @mock = start_mock
27
+ # @foo = OpenStruct.new :payload => "foo"
28
+ # @foobar = OpenStruct.new :payload => "foobar"
29
+ # end
30
+
31
+ # def teardown
32
+ # stop_mock(@mock)
33
+ # end
34
+
35
+ # def store
36
+ # @store ||= ActiveSupport::Cache::CouchbaseStore.new(:hostname => @mock.host,
37
+ # :port => @mock.port)
38
+ # end
39
+
40
+ # def pool_store
41
+ # @pool_store ||= ActiveSupport::Cache::CouchbaseStore.new(:hostname => @mock.host,
42
+ # :port => @mock.port,
43
+ # :connection_pool => 5)
44
+ # end
45
+
46
+ # def test_it_supported_methods
47
+ # supported_methods = store.public_methods(false).map(&:to_sym)
48
+ # assert supported_methods.include?(:fetch)
49
+ # assert supported_methods.include?(:write)
50
+ # assert supported_methods.include?(:read)
51
+ # assert supported_methods.include?(:read_multi)
52
+ # assert supported_methods.include?(:increment)
53
+ # assert supported_methods.include?(:decrement)
54
+ # assert supported_methods.include?(:exists?)
55
+ # assert supported_methods.include?(:delete)
56
+ # assert supported_methods.include?(:stats)
57
+ # refute supported_methods.include?(:clear)
58
+ # assert_raises(NotImplementedError) do
59
+ # store.clear
60
+ # end
61
+ # refute supported_methods.include?(:cleanup)
62
+ # assert_raises(NotImplementedError) do
63
+ # store.cleanup
64
+ # end
65
+ # end
66
+
67
+ # def test_it_writes_and_reads_the_data
68
+ # store.write uniq_id, @foobar
69
+ # assert_equal @foobar, store.read(uniq_id)
70
+ # end
71
+
72
+ # def test_it_writes_the_data_with_expiration_time
73
+ # store.write(uniq_id, @foobar, :expires_in => 1.second)
74
+ # assert_equal @foobar, store.read(uniq_id)
75
+ # sleep 2
76
+ # refute store.read(uniq_id)
77
+ # end
78
+
79
+ # def test_it_doest_write_data_if_unless_exist_option_is_true
80
+ # store.write uniq_id, @foo
81
+ # [:unless_exist, :unless_exists].each do |unless_exists|
82
+ # store.write uniq_id, @foobar, unless_exists => true
83
+ # assert_equal @foo, store.read(uniq_id)
84
+ # end
85
+ # end
86
+
87
+ # def test_it_reads_raw_data
88
+ # store.write uniq_id, @foo
89
+ # expected = case RUBY_VERSION
90
+ # when /^2\.0/
91
+ # "\x04\bU:\x0FOpenStruct{\x06:\fpayloadI\"\bfoo\x06:\x06ET"
92
+ # when /^1\.9/
93
+ # "\x04\bU:\x0FOpenStruct{\x06:\fpayloadI\"\bfoo\x06:\x06EF"
94
+ # else
95
+ # "\004\bU:\017OpenStruct{\006:\fpayload\"\bfoo"
96
+ # end
97
+ # assert_equal expected, store.read(uniq_id, :raw => true)
98
+ # end
99
+
100
+ # def test_it_writes_raw_data
101
+ # store.write uniq_id, @foobar, :raw => true
102
+ # assert_equal '#<OpenStruct payload="foobar">', store.read(uniq_id, :raw => true)
103
+ # end
104
+
105
+ # def test_it_deletes_data
106
+ # store.write uniq_id, @foo
107
+ # store.delete uniq_id
108
+ # refute store.read(uniq_id)
109
+ # end
110
+
111
+ # def test_it_verifies_existence_of_an_object_in_the_store
112
+ # store.write uniq_id, @foo
113
+ # assert store.exist?(uniq_id)
114
+ # refute store.exist?(uniq_id(:missing))
115
+ # end
116
+
117
+ # def test_it_initializes_key_on_first_increment_with_zero
118
+ # store.increment(uniq_id)
119
+ # assert_equal 0, store.read(uniq_id)
120
+ # assert_equal "0", store.read(uniq_id, :raw => true)
121
+ # end
122
+
123
+ # def test_it_initializes_key_on_first_decrement_with_zero
124
+ # store.decrement(uniq_id)
125
+ # assert_equal 0, store.read(uniq_id)
126
+ # assert_equal "0", store.read(uniq_id, :raw => true)
127
+ # end
128
+
129
+ # def test_it_initializes_key_with_given_value_on_increment
130
+ # store.increment(uniq_id, 1, :initial => 5)
131
+ # assert_equal 5, store.read(uniq_id)
132
+ # assert_equal "5", store.read(uniq_id, :raw => true)
133
+ # end
134
+
135
+ # def test_it_initializes_key_with_given_value_on_decrement
136
+ # store.decrement(uniq_id, 1, :initial => 5)
137
+ # assert_equal 5, store.read(uniq_id)
138
+ # assert_equal "5", store.read(uniq_id, :raw => true)
139
+ # end
140
+
141
+ # def test_it_increments_a_key
142
+ # 3.times { store.increment uniq_id }
143
+ # assert_equal 2, store.read(uniq_id)
144
+ # assert_equal "2", store.read(uniq_id, :raw => true)
145
+ # end
146
+
147
+ # def test_it_decrements_a_key
148
+ # 4.times { store.increment uniq_id }
149
+ # 2.times { store.decrement uniq_id }
150
+ # assert_equal 1, store.read(uniq_id)
151
+ # assert_equal "1", store.read(uniq_id, :raw => true)
152
+ # end
153
+
154
+ # def test_it_increments_a_raw_key
155
+ # assert store.write(uniq_id, 1, :raw => true)
156
+ # store.increment(uniq_id, 2)
157
+ # assert_equal 3, store.read(uniq_id, :raw => true).to_i
158
+ # end
159
+
160
+ # def test_it_decrements_a_raw_key
161
+ # assert store.write(uniq_id, 3, :raw => true)
162
+ # store.decrement(uniq_id, 2)
163
+ # assert_equal 1, store.read(uniq_id, :raw => true).to_i
164
+ # end
165
+
166
+ # def test_it_increments_a_key_by_given_value
167
+ # store.write(uniq_id, 0, :raw => true)
168
+ # store.increment uniq_id, 3
169
+ # assert_equal 3, store.read(uniq_id, :raw => true).to_i
170
+ # end
171
+
172
+ # def test_it_decrements_a_key_by_given_value
173
+ # store.write(uniq_id, 0, :raw => true)
174
+ # 3.times { store.increment uniq_id }
175
+ # store.decrement uniq_id, 2
176
+ # assert_equal 1, store.read(uniq_id, :raw => true).to_i
177
+ # end
178
+
179
+ # def test_it_provides_store_stats
180
+ # refute store.stats.empty?
181
+ # end
182
+
183
+ # def test_it_fetches_data
184
+ # assert store.write(uniq_id, @foo)
185
+ # assert_equal @foo, store.fetch(uniq_id)
186
+ # refute store.fetch("rub-a-dub")
187
+ # store.fetch("rub-a-dub") { "Flora de Cana" }
188
+ # assert_equal "Flora de Cana", store.fetch("rub-a-dub")
189
+ # store.fetch(uniq_id, :force => true) # force cache miss
190
+ # store.fetch(uniq_id, :force => true, :expires_in => 1.second) { @foobar }
191
+ # assert_equal @foobar, store.fetch(uniq_id)
192
+ # sleep 2
193
+ # refute store.fetch(uniq_id)
194
+ # end
195
+
196
+ # def test_it_reads_multiple_keys
197
+ # assert store.write(uniq_id(1), @foo)
198
+ # assert store.write(uniq_id(2), "foo")
199
+ # result = store.read_multi uniq_id(1), uniq_id(2)
200
+ # assert_equal @foo, result[uniq_id(1)]
201
+ # assert_equal "foo", result[uniq_id(2)]
202
+ # end
203
+
204
+ # def test_it_reads_multiple_keys_and_returns_only_the_matched_ones
205
+ # assert store.write(uniq_id, @foo)
206
+ # result = store.read_multi uniq_id, uniq_id(:missing)
207
+ # assert result[uniq_id]
208
+ # refute result[uniq_id(:missing)]
209
+ # end
210
+
211
+ # def test_it_notifies_on_fetch
212
+ # collect_notifications do
213
+ # store.fetch(uniq_id) { "foo" }
214
+ # end
215
+
216
+ # read, generate, write = @events
217
+
218
+ # assert_equal 'cache_read.active_support', read.name
219
+ # assert_equal({:key => uniq_id, :super_operation => :fetch}, read.payload)
220
+
221
+ # assert_equal 'cache_generate.active_support', generate.name
222
+ # assert_equal({:key => uniq_id}, generate.payload)
223
+
224
+ # assert_equal 'cache_write.active_support', write.name
225
+ # assert_equal({:key => uniq_id}, write.payload)
226
+ # end
227
+
228
+ # def test_it_notifies_on_read
229
+ # collect_notifications do
230
+ # store.read uniq_id
231
+ # end
232
+
233
+ # read = @events.first
234
+ # assert_equal 'cache_read.active_support', read.name
235
+ # assert_equal({:key => uniq_id, :hit => false}, read.payload)
236
+ # end
237
+
238
+ # def test_it_notifies_on_write
239
+ # collect_notifications do
240
+ # store.write uniq_id, "foo"
241
+ # end
242
+
243
+ # write = @events.first
244
+ # assert_equal 'cache_write.active_support', write.name
245
+ # assert_equal({:key => uniq_id}, write.payload)
246
+ # end
247
+
248
+ # def test_it_notifies_on_delete
249
+ # collect_notifications do
250
+ # store.delete uniq_id
251
+ # end
252
+
253
+ # delete = @events.first
254
+ # assert_equal 'cache_delete.active_support', delete.name
255
+ # assert_equal({:key => uniq_id}, delete.payload)
256
+ # end
257
+
258
+ # def test_it_notifies_on_exist?
259
+ # collect_notifications do
260
+ # store.exist? uniq_id
261
+ # end
262
+
263
+ # exist = @events.first
264
+ # assert_equal 'cache_exists?.active_support', exist.name
265
+ # assert_equal({:key => uniq_id}, exist.payload)
266
+ # end
267
+
268
+ # def test_it_notifies_on_increment
269
+ # collect_notifications do
270
+ # store.increment uniq_id
271
+ # end
272
+
273
+ # increment = @events.first
274
+ # assert_equal 'cache_increment.active_support', increment.name
275
+ # assert_equal({:key => uniq_id, :amount => 1, :create => true}, increment.payload)
276
+ # end
277
+
278
+ # def test_it_notifies_on_decrement
279
+ # collect_notifications do
280
+ # store.decrement uniq_id
281
+ # end
282
+
283
+ # decrement = @events.first
284
+ # assert_equal 'cache_decrement.active_support', decrement.name
285
+ # assert_equal({:key => uniq_id, :amount => 1, :create => true}, decrement.payload)
286
+ # end
287
+
288
+ # # Inspiration: https://github.com/mperham/dalli/blob/master/test/test_dalli.rb#L416
289
+ # def test_it_is_threadsafe
290
+ # workers = []
291
+
292
+ # # Have a bunch of threads perform a bunch of operations at the same time.
293
+ # # Verify the result of each operation to ensure the request and response
294
+ # # are not intermingled between threads.
295
+ # 10.times do
296
+ # workers << Thread.new do
297
+ # 100.times do
298
+ # store.write('a', 9)
299
+ # store.write('b', 11)
300
+ # assert_equal 9, store.read('a')
301
+ # assert_equal({ 'a' => 9, 'b' => 11 }, store.read_multi('a', 'b'))
302
+ # assert_equal 11, store.read('b')
303
+ # assert_equal %w(a b), store.read_multi('a', 'b', 'c').keys.sort
304
+ # end
305
+ # end
306
+ # end
307
+
308
+ # workers.each { |w| w.join }
309
+ # end
310
+
311
+ # def test_it_can_use_connection_pool_for_thread_safety
312
+ # workers = []
313
+
314
+ # 10.times do
315
+ # workers << Thread.new do
316
+ # 100.times do
317
+ # pool_store.write('a', 9)
318
+ # pool_store.write('b', 11)
319
+ # assert_equal 9, pool_store.read('a')
320
+ # assert_equal({ 'a' => 9, 'b' => 11 }, pool_store.read_multi('a', 'b'))
321
+ # assert_equal 11, pool_store.read('b')
322
+ # assert_equal %w(a b), pool_store.read_multi('a', 'b', 'c').keys.sort
323
+ # end
324
+ # end
325
+ # end
326
+
327
+ # workers.each { |w| w.join }
328
+ # end
329
+
330
+ # private
331
+
332
+ # def collect_notifications
333
+ # @events = [ ]
334
+ # ActiveSupport::Cache::CouchbaseStore.instrument = true
335
+ # ActiveSupport::Notifications.subscribe(/^cache_(.*)\.active_support$/) do |*args|
336
+ # @events << ActiveSupport::Notifications::Event.new(*args)
337
+ # end
338
+ # yield
339
+ # ActiveSupport::Cache::CouchbaseStore.instrument = false
340
+ # end
341
+ # end