couchbase 1.3.4-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
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