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,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
@@ -0,0 +1,125 @@
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 TestStore < 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_delete
31
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
32
+ connection.set(uniq_id, "bar")
33
+ assert connection.delete(uniq_id)
34
+ assert_raises(Couchbase::Error::NotFound) do
35
+ connection.delete(uniq_id)
36
+ end
37
+ end
38
+
39
+ def test_delete_missing
40
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
41
+ assert_raises(Couchbase::Error::NotFound) do
42
+ connection.delete(uniq_id(:missing))
43
+ end
44
+ refute connection.delete(uniq_id(:missing), :quiet => true)
45
+ refute connection.quiet?
46
+ connection.quiet = true
47
+ refute connection.delete(uniq_id(:missing))
48
+ end
49
+
50
+ def test_delete_with_cas
51
+ skip
52
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
53
+ cas = connection.set(uniq_id, "bar")
54
+ missing_cas = cas - 1
55
+ assert_raises(Couchbase::Error::KeyExists) do
56
+ connection.delete(uniq_id, :cas => missing_cas)
57
+ end
58
+ assert connection.delete(uniq_id, :cas => cas)
59
+ end
60
+
61
+ def test_allow_fixnum_as_cas_parameter
62
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
63
+ cas = connection.set(uniq_id, "bar")
64
+ assert connection.delete(uniq_id, cas)
65
+ end
66
+
67
+ def test_delete_with_prefix
68
+ skip
69
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port, :key_prefix => "prefix:")
70
+ connection.set(uniq_id(:foo), "bar")
71
+ assert connection.delete(uniq_id(:foo))
72
+ assert_raises(Couchbase::Error::NotFound) do
73
+ connection.get(uniq_id(:foo))
74
+ end
75
+ end
76
+
77
+ def test_simple_multi_delete
78
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port, :quiet => true)
79
+ connection.set(uniq_id(1) => "bar", uniq_id(2) => "foo")
80
+ res = connection.delete(uniq_id(1), uniq_id(2))
81
+ assert res.is_a?(Hash)
82
+ assert res[uniq_id(1)]
83
+ assert res[uniq_id(2)]
84
+ end
85
+
86
+ def test_simple_multi_delete_missing
87
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port, :quiet => true)
88
+ connection.set(uniq_id(1) => "bar", uniq_id(2) => "foo")
89
+ res = connection.delete(uniq_id(1), uniq_id(:missing), :quiet => true)
90
+ assert res.is_a?(Hash)
91
+ assert res[uniq_id(1)]
92
+ refute res[uniq_id(:missing)]
93
+ end
94
+
95
+ def test_multi_delete_with_cas_check
96
+ skip
97
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port, :quiet => true)
98
+ cas = connection.set(uniq_id(1) => "bar", uniq_id(2) => "foo")
99
+ res = connection.delete(uniq_id(1) => cas[uniq_id(1)], uniq_id(2) => cas[uniq_id(2)])
100
+ assert res.is_a?(Hash)
101
+ assert res[uniq_id(1)]
102
+ assert res[uniq_id(2)]
103
+ end
104
+
105
+ def test_multi_delete_missing_with_cas_check
106
+ skip
107
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port, :quiet => true)
108
+ cas = connection.set(uniq_id(1) => "bar", uniq_id(2) => "foo")
109
+ res = connection.delete(uniq_id(1) => cas[uniq_id(1)], uniq_id(:missing) => cas[uniq_id(2)])
110
+ assert res.is_a?(Hash)
111
+ assert res[uniq_id(1)]
112
+ refute res[uniq_id(:missing)]
113
+ end
114
+
115
+ def test_multi_delete_with_cas_check_mismatch
116
+ skip
117
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port, :quiet => true)
118
+ cas = connection.set(uniq_id(1) => "bar", uniq_id(2) => "foo")
119
+
120
+ assert_raises(Couchbase::Error::KeyExists) do
121
+ connection.delete(uniq_id(1) => cas[uniq_id(1)] + 1,
122
+ uniq_id(2) => cas[uniq_id(2)])
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,72 @@
1
+ # Author:: Mike Evans <mike@urlgonomics.com>
2
+ # Copyright:: 2013 Urlgonomics LLC.
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 TestDesignDocs < MiniTest::Test
21
+
22
+ def setup
23
+ @mock = start_mock
24
+ @cb = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
25
+ end
26
+
27
+ def teardown
28
+ stop_mock(@mock)
29
+ @cb.disconnect
30
+ end
31
+
32
+ def test_save_design_doc
33
+ assert @cb.save_design_doc(design_doc)
34
+ end
35
+
36
+ def test_save_design_doc_with_bad_data
37
+ assert_raises ArgumentError do
38
+ @cb.save_design_doc(123)
39
+ end
40
+ end
41
+
42
+ def test_delete_design_doc
43
+ @cb.save_design_doc(design_doc)
44
+ assert @cb.delete_design_doc('blog')
45
+ end
46
+
47
+ def test_design_doc_access
48
+ @cb.save_design_doc(design_doc)
49
+ assert @cb.design_docs['blog']
50
+ end
51
+
52
+ def test_design_doc_missing_access
53
+ refute @cb.design_docs['missing']
54
+ end
55
+
56
+ def design_doc
57
+ {
58
+ '_id' => '_design/blog',
59
+ 'language' => 'javascript',
60
+ 'views' => {
61
+ 'recent_posts' => {
62
+ 'map' => <<-JS
63
+ function (doc, meta) {
64
+ emit(doc.name);
65
+ }
66
+ JS
67
+ }
68
+ }
69
+ }
70
+ end
71
+
72
+ end
@@ -0,0 +1,82 @@
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 'digest/md5'
20
+
21
+ class TestErrors < MiniTest::Test
22
+
23
+ def setup
24
+ @mock = start_mock
25
+ end
26
+
27
+ def teardown
28
+ stop_mock(@mock)
29
+ end
30
+
31
+ def genkey(item)
32
+ tuple = [item["author"], item["message"]]
33
+ Digest::MD5.hexdigest(tuple.join('-'))
34
+ end
35
+
36
+ def test_graceful_add_with_collision
37
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port)
38
+ msg1 = {"author" => "foo", "message" => "hi all", "time" => "2012-01-12 11:29:09"}
39
+ key1 = uniq_id(genkey(msg1))
40
+ msg2 = {"author" => "foo", "message" => "hi all", "time" => "2012-01-12 11:29:30"}
41
+ key2 = uniq_id(genkey(msg2))
42
+
43
+ connection.add(key1, msg1)
44
+ begin
45
+ connection.add(key2, msg2)
46
+ rescue Couchbase::Error::KeyExists => ex
47
+ # using info from exception
48
+ # it could be done with cas operation, but we can save one request
49
+ # here (in real world cas operation will be more consistent because it
50
+ # fetch fresh version from the cluster)
51
+ #
52
+ # connection.cas(key2) do |msg|
53
+ # msg.merge("time" => [msg["time"], msg2["time"]])
54
+ # end
55
+ msg2 = msg1.merge("time" => [msg1["time"], msg2["time"]])
56
+ connection.set(key2, msg2, :cas => ex.cas)
57
+ end
58
+
59
+ msg3 = {"author" => "foo", "message" => "hi all",
60
+ "time" => ["2012-01-12 11:29:09", "2012-01-12 11:29:30"]}
61
+ key3 = uniq_id(genkey(msg3))
62
+ assert_equal msg3, connection.get(key3)
63
+
64
+ connection.run do |conn|
65
+ msg4 = {"author" => "foo", "message" => "hi all", "time" => "2012-01-12 11:45:34"}
66
+ key4 = uniq_id(genkey(msg4))
67
+
68
+ connection.add(key4, msg4) do |ret|
69
+ assert_equal :add, ret.operation
70
+ assert_equal key4, ret.key
71
+ msg4 = msg3.merge("time" => msg3["time"] + [msg4["time"]])
72
+ connection.set(ret.key, msg4, :cas => ret.cas)
73
+ end
74
+ end
75
+
76
+ msg5 = {"author" => "foo", "message" => "hi all",
77
+ "time" => ["2012-01-12 11:29:09", "2012-01-12 11:29:30", "2012-01-12 11:45:34"]}
78
+ key5 = uniq_id(genkey(msg5))
79
+ assert_equal msg5, connection.get(key5)
80
+ end
81
+
82
+ end