couchbase 1.3.4-x64-mingw32

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 (92) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.travis.yml +22 -0
  4. data/.yardopts +5 -0
  5. data/CONTRIBUTING.markdown +75 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +201 -0
  8. data/Makefile +3 -0
  9. data/README.markdown +649 -0
  10. data/RELEASE_NOTES.markdown +796 -0
  11. data/Rakefile +20 -0
  12. data/couchbase.gemspec +49 -0
  13. data/examples/chat-em/Gemfile +7 -0
  14. data/examples/chat-em/README.markdown +45 -0
  15. data/examples/chat-em/server.rb +82 -0
  16. data/examples/chat-goliath-grape/Gemfile +5 -0
  17. data/examples/chat-goliath-grape/README.markdown +50 -0
  18. data/examples/chat-goliath-grape/app.rb +67 -0
  19. data/examples/chat-goliath-grape/config/app.rb +20 -0
  20. data/examples/transcoders/Gemfile +3 -0
  21. data/examples/transcoders/README.markdown +59 -0
  22. data/examples/transcoders/cb-zcat +40 -0
  23. data/examples/transcoders/cb-zcp +45 -0
  24. data/examples/transcoders/gzip_transcoder.rb +49 -0
  25. data/examples/transcoders/options.rb +54 -0
  26. data/ext/couchbase_ext/.gitignore +4 -0
  27. data/ext/couchbase_ext/arguments.c +956 -0
  28. data/ext/couchbase_ext/arithmetic.c +307 -0
  29. data/ext/couchbase_ext/bucket.c +1370 -0
  30. data/ext/couchbase_ext/context.c +65 -0
  31. data/ext/couchbase_ext/couchbase_ext.c +1364 -0
  32. data/ext/couchbase_ext/couchbase_ext.h +644 -0
  33. data/ext/couchbase_ext/delete.c +163 -0
  34. data/ext/couchbase_ext/eventmachine_plugin.c +452 -0
  35. data/ext/couchbase_ext/extconf.rb +168 -0
  36. data/ext/couchbase_ext/get.c +316 -0
  37. data/ext/couchbase_ext/gethrtime.c +129 -0
  38. data/ext/couchbase_ext/http.c +432 -0
  39. data/ext/couchbase_ext/multithread_plugin.c +1090 -0
  40. data/ext/couchbase_ext/observe.c +171 -0
  41. data/ext/couchbase_ext/plugin_common.c +171 -0
  42. data/ext/couchbase_ext/result.c +129 -0
  43. data/ext/couchbase_ext/stats.c +163 -0
  44. data/ext/couchbase_ext/store.c +542 -0
  45. data/ext/couchbase_ext/timer.c +192 -0
  46. data/ext/couchbase_ext/touch.c +186 -0
  47. data/ext/couchbase_ext/unlock.c +176 -0
  48. data/ext/couchbase_ext/utils.c +551 -0
  49. data/ext/couchbase_ext/version.c +142 -0
  50. data/lib/action_dispatch/middleware/session/couchbase_store.rb +38 -0
  51. data/lib/active_support/cache/couchbase_store.rb +430 -0
  52. data/lib/couchbase.rb +155 -0
  53. data/lib/couchbase/bucket.rb +457 -0
  54. data/lib/couchbase/cluster.rb +119 -0
  55. data/lib/couchbase/connection_pool.rb +58 -0
  56. data/lib/couchbase/constants.rb +12 -0
  57. data/lib/couchbase/result.rb +26 -0
  58. data/lib/couchbase/transcoder.rb +120 -0
  59. data/lib/couchbase/utils.rb +62 -0
  60. data/lib/couchbase/version.rb +21 -0
  61. data/lib/couchbase/view.rb +506 -0
  62. data/lib/couchbase/view_row.rb +272 -0
  63. data/lib/ext/multi_json_fix.rb +56 -0
  64. data/lib/rack/session/couchbase.rb +108 -0
  65. data/tasks/benchmark.rake +6 -0
  66. data/tasks/compile.rake +158 -0
  67. data/tasks/test.rake +100 -0
  68. data/tasks/util.rake +21 -0
  69. data/test/profile/.gitignore +1 -0
  70. data/test/profile/Gemfile +6 -0
  71. data/test/profile/benchmark.rb +195 -0
  72. data/test/setup.rb +178 -0
  73. data/test/test_arithmetic.rb +185 -0
  74. data/test/test_async.rb +316 -0
  75. data/test/test_bucket.rb +250 -0
  76. data/test/test_cas.rb +235 -0
  77. data/test/test_couchbase.rb +77 -0
  78. data/test/test_couchbase_connection_pool.rb +77 -0
  79. data/test/test_couchbase_rails_cache_store.rb +361 -0
  80. data/test/test_delete.rb +120 -0
  81. data/test/test_errors.rb +82 -0
  82. data/test/test_eventmachine.rb +70 -0
  83. data/test/test_format.rb +164 -0
  84. data/test/test_get.rb +407 -0
  85. data/test/test_stats.rb +57 -0
  86. data/test/test_store.rb +216 -0
  87. data/test/test_timer.rb +42 -0
  88. data/test/test_touch.rb +97 -0
  89. data/test/test_unlock.rb +119 -0
  90. data/test/test_utils.rb +58 -0
  91. data/test/test_version.rb +52 -0
  92. metadata +336 -0
@@ -0,0 +1,250 @@
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
+ # with_mock(:host => 'localhost', :port => 8091, :buckets_spec => 'default,foo') do |mock|
24
+ # connections = [
25
+ # Couchbase.new,
26
+ # Couchbase.new("http://#{mock.host}:8091"),
27
+ # Couchbase.new("http://#{mock.host}:8091/pools/default"),
28
+ # Couchbase.new(:hostname => mock.host),
29
+ # Couchbase.new(:hostname => mock.host, :port => 8091)
30
+ # ]
31
+ # connections.each do |connection|
32
+ # assert_equal mock.host, connection.hostname
33
+ # assert_equal 8091, connection.port
34
+ # assert_equal "#{mock.host}:8091", connection.authority
35
+ # assert_equal 'default', connection.bucket
36
+ # assert_equal "http://#{mock.host}:8091/pools/default/buckets/default/", connection.url
37
+ # end
38
+
39
+ # connections = [
40
+ # Couchbase.new("http://#{mock.host}:8091/pools/default/buckets/foo"),
41
+ # Couchbase.new(:bucket => 'foo'),
42
+ # Couchbase.new("http://#{mock.host}:8091/pools/default/buckets/default", :bucket => 'foo')
43
+ # ]
44
+ # connections.each do |connection|
45
+ # assert_equal 'foo', connection.bucket
46
+ # assert_equal "http://#{mock.host}:8091/pools/default/buckets/foo/", connection.url
47
+ # end
48
+ # end
49
+
50
+ with_mock(:host => 'localhost') do |mock| # pick first free port
51
+ connections = [
52
+ Couchbase.new("http://#{mock.host}:#{mock.port}"),
53
+ Couchbase.new(:port => mock.port),
54
+ Couchbase.new("http://#{mock.host}:8091", :port => mock.port)
55
+ ]
56
+ connections.each do |connection|
57
+ assert_equal mock.port, connection.port
58
+ assert_equal "#{mock.host}:#{mock.port}", connection.authority
59
+ assert_equal "http://#{mock.host}:#{mock.port}/pools/default/buckets/default/", connection.url
60
+ end
61
+ end
62
+
63
+ with_mock(:host => '127.0.0.1') do |mock|
64
+ connections = [
65
+ Couchbase.new("http://#{mock.host}:#{mock.port}"),
66
+ Couchbase.new(:hostname => mock.host, :port => mock.port),
67
+ Couchbase.new('http://example.com:8091', :hostname => mock.host, :port => mock.port)
68
+ ]
69
+ connections.each do |connection|
70
+ assert_equal mock.host, connection.hostname
71
+ assert_equal "#{mock.host}:#{mock.port}", connection.authority
72
+ assert_equal "http://#{mock.host}:#{mock.port}/pools/default/buckets/default/", connection.url
73
+ end
74
+ end
75
+ end
76
+
77
+ def test_it_raises_network_error_if_server_not_found
78
+ refute(`netstat -tnl` =~ /12345/)
79
+ assert_raises Couchbase::Error::Connect do
80
+ Couchbase.new(:port => 12345)
81
+ end
82
+ end
83
+
84
+ def test_it_raises_argument_error_for_illegal_url
85
+ illegal = [
86
+ "ftp://localhost:8091/",
87
+ "http:/localhost:8091/",
88
+ ""
89
+ ]
90
+ illegal.each do |url|
91
+ assert_raises ArgumentError do
92
+ Couchbase.new(url)
93
+ end
94
+ end
95
+ end
96
+
97
+ def test_it_able_to_connect_to_protected_buckets
98
+ with_mock(:buckets_spec => 'protected:secret') do |mock|
99
+ connection = Couchbase.new(:hostname => mock.host,
100
+ :port => mock.port,
101
+ :bucket => 'protected',
102
+ :username => 'protected',
103
+ :password => 'secret')
104
+ assert_equal "protected", connection.bucket
105
+ assert_equal "protected", connection.username
106
+ assert_equal "secret", connection.password
107
+ end
108
+ end
109
+
110
+ def test_it_allows_to_specify_credentials_in_url
111
+ with_mock(:buckets_spec => 'protected:secret') do |mock|
112
+ connection = Couchbase.new("http://protected:secret@#{mock.host}:#{mock.port}/pools/default/buckets/protected/")
113
+ assert_equal "protected", connection.bucket
114
+ assert_equal "protected", connection.username
115
+ assert_equal "secret", connection.password
116
+ end
117
+ end
118
+
119
+ def test_it_raises_error_with_wrong_credentials
120
+ with_mock do |mock|
121
+ assert_raises Couchbase::Error::Auth do
122
+ Couchbase.new(:hostname => mock.host,
123
+ :port => mock.port,
124
+ :bucket => 'default',
125
+ :password => 'wrong_password')
126
+ end
127
+ assert_raises Couchbase::Error::InvalidUsername do
128
+ Couchbase.new(:hostname => mock.host,
129
+ :port => mock.port,
130
+ :bucket => 'default',
131
+ :username => 'wrong.username',
132
+ :password => 'wrong_password')
133
+ end
134
+ end
135
+ end
136
+
137
+ def test_it_unable_to_connect_to_protected_buckets_with_wrong_credentials
138
+ with_mock(:buckets_spec => 'protected:secret') do |mock|
139
+ assert_raises Couchbase::Error::InvalidUsername do
140
+ Couchbase.new(:hostname => mock.host,
141
+ :port => mock.port,
142
+ :bucket => 'protected',
143
+ :username => 'wrong',
144
+ :password => 'secret')
145
+ end
146
+ assert_raises Couchbase::Error::Auth do
147
+ Couchbase.new(:hostname => mock.host,
148
+ :port => mock.port,
149
+ :bucket => 'protected',
150
+ :username => 'protected',
151
+ :password => 'wrong')
152
+ end
153
+ end
154
+ end
155
+
156
+ def test_it_allows_change_quiet_flag
157
+ with_mock do |mock|
158
+ connection = Couchbase.new(:hostname => mock.host,
159
+ :port => mock.port)
160
+ refute connection.quiet?
161
+
162
+ connection = Couchbase.new(:hostname => mock.host,
163
+ :port => mock.port,
164
+ :quiet => true)
165
+ assert connection.quiet?
166
+
167
+ connection.quiet = nil
168
+ assert_equal false, connection.quiet?
169
+
170
+ connection.quiet = :foo
171
+ assert_equal true, connection.quiet?
172
+ end
173
+ end
174
+
175
+ def test_it_is_connected
176
+ with_mock do |mock|
177
+ connection = Couchbase.new(:hostname => mock.host,
178
+ :port => mock.port)
179
+ assert connection.connected?
180
+ end
181
+ end
182
+
183
+ def test_it_is_possible_to_disconnect_instance
184
+ with_mock do |mock|
185
+ connection = Couchbase.new(:hostname => mock.host,
186
+ :port => mock.port)
187
+ connection.disconnect
188
+ refute connection.connected?
189
+ end
190
+ end
191
+
192
+ def test_it_raises_error_on_double_disconnect
193
+ with_mock do |mock|
194
+ connection = Couchbase.new(:hostname => mock.host,
195
+ :port => mock.port)
196
+ connection.disconnect
197
+ assert_raises Couchbase::Error::Connect do
198
+ connection.disconnect
199
+ end
200
+ end
201
+ end
202
+
203
+ def test_it_allows_to_reconnect_the_instance
204
+ with_mock do |mock|
205
+ connection = Couchbase.new(:hostname => mock.host,
206
+ :port => mock.port)
207
+ connection.disconnect
208
+ refute connection.connected?
209
+ connection.reconnect
210
+ assert connection.connected?
211
+ assert connection.set(uniq_id, "foo")
212
+ end
213
+ end
214
+
215
+ def test_it_allows_to_change_configuration_during_reconnect
216
+ with_mock(:buckets_spec => 'protected:secret') do |mock|
217
+ connection = Couchbase.new(:hostname => mock.host,
218
+ :port => mock.port,
219
+ :bucket => 'protected',
220
+ :username => 'protected',
221
+ :password => 'secret')
222
+ connection.disconnect
223
+ assert_raises Couchbase::Error::Auth do
224
+ connection.reconnect(:password => 'incorrect')
225
+ end
226
+ refute connection.connected?
227
+
228
+ connection.reconnect(:password => 'secret')
229
+ assert connection.connected?
230
+ end
231
+ end
232
+
233
+ def test_it_uses_bucket_name_as_username_if_username_is_empty
234
+ with_mock(:buckets_spec => 'protected:secret') do |mock|
235
+ connection = Couchbase.new(:hostname => mock.host,
236
+ :port => mock.port,
237
+ :bucket => 'protected',
238
+ :password => 'secret')
239
+ assert connection.connected?
240
+ end
241
+ end
242
+
243
+ def test_it_doesnt_try_to_destroy_handle_in_case_of_lcb_create_failure
244
+ assert_raises(Couchbase::Error::InvalidHostFormat) do
245
+ Couchbase.connect(:hostname => "foobar:baz")
246
+ end
247
+ GC.start # make sure it won't touch handle in finalizer
248
+ end
249
+
250
+ end
data/test/test_cas.rb ADDED
@@ -0,0 +1,235 @@
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_collision
44
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
45
+ :default_format => :document)
46
+ connection.set(uniq_id, {"bar" => 1})
47
+ assert_raises(Couchbase::Error::KeyExists) do
48
+ connection.cas(uniq_id) do |val|
49
+ # Simulate collision with a separate writer. This will
50
+ # change the CAS value to be different than what #cas just loaded.
51
+ connection.set(uniq_id, {"bar" => 2})
52
+
53
+ # Complete the modification we desire, which should fail when set.
54
+ val["baz"] = 3
55
+ val
56
+ end
57
+ end
58
+ end
59
+
60
+ def test_compare_and_swap_retry
61
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
62
+ :default_format => :document)
63
+ connection.set(uniq_id, {"bar" => 1})
64
+ calls = 0
65
+ connection.cas(uniq_id, :retry => 1) do |val|
66
+ calls += 1
67
+ if calls == 1
68
+ # Simulate collision with a separate writer. This will
69
+ # change the CAS value to be different than what #cas just loaded.
70
+ # Only do this the first time this block is executed.
71
+ connection.set(uniq_id, {"bar" => 2})
72
+ end
73
+
74
+ # Complete the modification we desire, which should fail when set.
75
+ val["baz"] = 3
76
+ val
77
+ end
78
+ assert_equal 2, calls
79
+ val = connection.get(uniq_id)
80
+ expected = {"bar" => 2, "baz" => 3}
81
+ assert_equal expected, val
82
+ end
83
+
84
+ def test_compare_and_swap_too_many_retries
85
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
86
+ :default_format => :document)
87
+ connection.set(uniq_id, {"bar" => 0})
88
+ calls = 0
89
+ assert_raises(Couchbase::Error::KeyExists) do
90
+ connection.cas(uniq_id, :retry => 10) do |val|
91
+ calls += 1
92
+
93
+ # Simulate collision with a separate writer. This will
94
+ # change the CAS value to be different than what #cas just loaded.
95
+ # Do it every time so we just keep retrying and failing.
96
+ connection.set(uniq_id, {"bar" => calls})
97
+
98
+ # Complete the modification we desire, which should fail when set.
99
+ val["baz"] = 3
100
+ val
101
+ end
102
+ end
103
+ assert_equal 11, calls
104
+ end
105
+
106
+ def test_compare_and_swap_async
107
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
108
+ :default_format => :document)
109
+ connection.set(uniq_id, {"bar" => 1})
110
+ calls = 0
111
+ connection.run do |conn|
112
+ conn.cas(uniq_id) do |ret|
113
+ calls += 1
114
+ case ret.operation
115
+ when :get
116
+ new_val = ret.value
117
+ new_val["baz"] = 2
118
+ new_val
119
+ when :set
120
+ assert ret.success?
121
+ else
122
+ flunk "Unexpected operation: #{ret.operation.inspect}"
123
+ end
124
+ end
125
+ end
126
+ assert_equal 2, calls
127
+ val = connection.get(uniq_id)
128
+ expected = {"bar" => 1, "baz" => 2}
129
+ assert_equal expected, val
130
+ end
131
+
132
+ def test_compare_and_swap_async_collision
133
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
134
+ :default_format => :document)
135
+ connection.set(uniq_id, {"bar" => 1})
136
+ calls = 0
137
+ connection.run do |conn|
138
+ conn.cas(uniq_id) do |ret|
139
+ calls += 1
140
+ case ret.operation
141
+ when :get
142
+ new_val = ret.value
143
+
144
+ # Simulate collision with a separate writer. This will
145
+ # change the CAS value to be different than what #cas just loaded.
146
+ connection.set(uniq_id, {"bar" => 2})
147
+
148
+
149
+ # Complete the modification we desire, which should fail when set.
150
+ new_val["baz"] = 3
151
+ new_val
152
+ when :set
153
+ assert ret.error.is_a? Couchbase::Error::KeyExists
154
+ else
155
+ flunk "Unexpected operation: #{ret.operation.inspect}"
156
+ end
157
+ end
158
+ end
159
+ assert_equal 2, calls
160
+ end
161
+
162
+ def test_compare_and_swap_async_retry
163
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
164
+ :default_format => :document)
165
+ connection.set(uniq_id, {"bar" => 1})
166
+ calls = 0
167
+ connection.run do |conn|
168
+ conn.cas(uniq_id, :retry => 1) do |ret|
169
+ calls += 1
170
+ case ret.operation
171
+ when :get
172
+ new_val = ret.value
173
+
174
+ if calls == 1
175
+ # Simulate collision with a separate writer. This will
176
+ # change the CAS value to be different than what #cas just loaded.
177
+ # Only do this the first time this block is executed.
178
+ connection.set(uniq_id, {"bar" => 2})
179
+ end
180
+
181
+ # Complete the modification we desire, which should fail when set.
182
+ new_val["baz"] = 3
183
+ new_val
184
+ when :set
185
+ assert ret.success?
186
+ else
187
+ flunk "Unexpected operation: #{ret.operation.inspect}"
188
+ end
189
+ end
190
+ end
191
+ assert_equal 3, calls
192
+ val = connection.get(uniq_id)
193
+ expected = {"bar" => 2, "baz" => 3}
194
+ assert_equal expected, val
195
+ end
196
+
197
+ def test_compare_and_swap_async_too_many_retries
198
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
199
+ :default_format => :document)
200
+ connection.set(uniq_id, {"bar" => 0})
201
+ calls = 0
202
+ connection.run do |conn|
203
+ conn.cas(uniq_id, :retry => 10) do |ret|
204
+ calls += 1
205
+ case ret.operation
206
+ when :get
207
+ new_val = ret.value
208
+
209
+ # Simulate collision with a separate writer. This will
210
+ # change the CAS value to be different than what #cas just loaded.
211
+ # Do it every time so we just keep retrying and failing.
212
+ connection.set(uniq_id, {"bar" => calls})
213
+
214
+ # Complete the modification we desire, which should fail when set.
215
+ new_val["baz"] = 3
216
+ new_val
217
+ when :set
218
+ assert ret.error.is_a? Couchbase::Error::KeyExists
219
+ else
220
+ flunk "Unexpected operation: #{ret.operation.inspect}"
221
+ end
222
+ end
223
+ end
224
+ assert_equal 12, calls
225
+ end
226
+
227
+ def test_flags_replication
228
+ connection = Couchbase.new(:hostname => @mock.host, :port => @mock.port,
229
+ :default_format => :document)
230
+ connection.set(uniq_id, "bar", :flags => 0x100)
231
+ connection.cas(uniq_id) { "baz" }
232
+ _, flags, _ = connection.get(uniq_id, :extended => true)
233
+ assert_equal 0x100, flags
234
+ end
235
+ end