couchbase 0.9.8 → 1.0.0

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 (51) hide show
  1. data/.gitignore +8 -0
  2. data/.yardopts +5 -0
  3. data/HISTORY.markdown +14 -10
  4. data/README.markdown +293 -98
  5. data/Rakefile +19 -24
  6. data/couchbase.gemspec +25 -7
  7. data/ext/couchbase_ext/couchbase_ext.c +2332 -0
  8. data/ext/couchbase_ext/extconf.rb +102 -0
  9. data/lib/couchbase.rb +20 -30
  10. data/lib/couchbase/bucket.rb +43 -112
  11. data/lib/couchbase/version.rb +3 -2
  12. data/tasks/benchmark.rake +6 -0
  13. data/tasks/compile.rake +52 -0
  14. data/tasks/doc.rake +27 -0
  15. data/tasks/test.rake +94 -0
  16. data/tasks/util.rake +21 -0
  17. data/test/profile/.gitignore +1 -0
  18. data/test/profile/Gemfile +6 -0
  19. data/test/profile/benchmark.rb +195 -0
  20. data/test/setup.rb +107 -18
  21. data/test/test_arithmetic.rb +98 -0
  22. data/test/test_async.rb +211 -0
  23. data/test/test_bucket.rb +126 -23
  24. data/test/test_cas.rb +59 -0
  25. data/test/test_couchbase.rb +22 -3
  26. data/test/test_delete.rb +63 -0
  27. data/test/test_errors.rb +82 -0
  28. data/test/test_flush.rb +49 -0
  29. data/test/test_format.rb +98 -0
  30. data/test/test_get.rb +236 -0
  31. data/test/test_stats.rb +53 -0
  32. data/test/test_store.rb +186 -0
  33. data/test/test_touch.rb +57 -0
  34. data/test/test_version.rb +17 -0
  35. metadata +72 -58
  36. data/lib/couchbase/couchdb.rb +0 -107
  37. data/lib/couchbase/document.rb +0 -71
  38. data/lib/couchbase/http_status.rb +0 -118
  39. data/lib/couchbase/latch.rb +0 -71
  40. data/lib/couchbase/memcached.rb +0 -372
  41. data/lib/couchbase/node.rb +0 -49
  42. data/lib/couchbase/rest_client.rb +0 -124
  43. data/lib/couchbase/view.rb +0 -182
  44. data/test/support/buckets-config.json +0 -843
  45. data/test/support/sample_design_doc.json +0 -9
  46. data/test/test_couchdb.rb +0 -98
  47. data/test/test_document.rb +0 -11
  48. data/test/test_latch.rb +0 -88
  49. data/test/test_memcached.rb +0 -59
  50. data/test/test_rest_client.rb +0 -14
  51. data/test/test_view.rb +0 -98
@@ -0,0 +1,98 @@
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::Unit::TestCase
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(:port => @mock.port)
32
+
33
+ connection.set(test_id, 1)
34
+ val = connection.incr(test_id)
35
+ assert_equal 2, val
36
+ val = connection.get(test_id)
37
+ assert_equal 2, val
38
+
39
+ connection.set(test_id, 7)
40
+ val = connection.decr(test_id)
41
+ assert_equal 6, val
42
+ val = connection.get(test_id)
43
+ assert_equal 6, val
44
+ end
45
+
46
+ def test_it_fails_to_incr_decr_missing_key
47
+ connection = Couchbase.new(:port => @mock.port)
48
+
49
+ assert_raises(Couchbase::Error::NotFound) do
50
+ connection.incr(test_id(:missing))
51
+ end
52
+ assert_raises(Couchbase::Error::NotFound) do
53
+ connection.decr(test_id(:missing))
54
+ end
55
+ end
56
+
57
+ def test_it_creates_missing_key_when_initial_value_specified
58
+ connection = Couchbase.new(:port => @mock.port)
59
+
60
+ val = connection.incr(test_id(:missing), :initial => 5)
61
+ assert_equal 5, val
62
+ val = connection.incr(test_id(:missing), :initial => 5)
63
+ assert_equal 6, val
64
+ val = connection.get(test_id(:missing))
65
+ assert_equal 6, val
66
+ end
67
+
68
+ def test_it_uses_zero_as_default_value_for_missing_keys
69
+ connection = Couchbase.new(:port => @mock.port)
70
+
71
+ val = connection.incr(test_id(:missing), :create => true)
72
+ assert_equal 0, val
73
+ val = connection.incr(test_id(:missing), :create => true)
74
+ assert_equal 1, val
75
+ val = connection.get(test_id(:missing))
76
+ assert_equal 1, val
77
+ end
78
+
79
+ def test_it_allows_custom_ttl
80
+ connection = Couchbase.new(:port => @mock.port)
81
+
82
+ val = connection.incr(test_id(:missing), :create => true, :ttl => 1)
83
+ assert_equal 0, val
84
+ val = connection.incr(test_id(:missing), :create => true)
85
+ assert_equal 1, val
86
+ sleep(1)
87
+ refute connection.get(test_id(:missing))
88
+ end
89
+
90
+ def test_it_allows_custom_delta
91
+ connection = Couchbase.new(:port => @mock.port)
92
+
93
+ connection.set(test_id, 12)
94
+ val = connection.incr(test_id, 10)
95
+ assert_equal 22, val
96
+ end
97
+
98
+ end
@@ -0,0 +1,211 @@
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 TestAsync < MiniTest::Unit::TestCase
21
+
22
+ def setup
23
+ @mock = start_mock
24
+ end
25
+
26
+ def teardown
27
+ stop_mock(@mock)
28
+ end
29
+
30
+ def test_result_object_provides_enough_info
31
+ obj = Couchbase::Result.new
32
+ assert obj.respond_to?(:success?)
33
+ assert obj.respond_to?(:error)
34
+ assert obj.respond_to?(:key)
35
+ assert obj.respond_to?(:value)
36
+ assert obj.respond_to?(:node)
37
+ assert obj.respond_to?(:cas)
38
+ assert obj.respond_to?(:flags)
39
+ end
40
+
41
+ def test_it_requires_block_for_running_loop
42
+ connection = Couchbase.new(:port => @mock.port)
43
+ refute connection.async?
44
+ assert_raises(LocalJumpError) do
45
+ connection.run
46
+ end
47
+ connection.run do |conn|
48
+ assert conn.async?
49
+ end
50
+ end
51
+
52
+ def test_it_resets_async_flag_when_raising_exception_from_callback
53
+ connection = Couchbase.new(:port => @mock.port)
54
+
55
+ assert_raises(RuntimeError) do
56
+ connection.run do |conn|
57
+ conn.set(test_id, "foo") { raise }
58
+ end
59
+ end
60
+ refute connection.async?
61
+ end
62
+
63
+ def test_nested_async_get_set
64
+ connection = Couchbase.new(:port => @mock.port)
65
+ connection.set(test_id, {"bar" => 1})
66
+ connection.set(test_id(:hit), 0)
67
+
68
+ connection.run do |conn|
69
+ conn.get(test_id) do
70
+ conn.get(test_id(:hit)) do |res|
71
+ conn.set(test_id(:hit), res.value + 1)
72
+ end
73
+ end
74
+ end
75
+
76
+ val = connection.get(test_id(:hit))
77
+ assert_equal 1, val
78
+ end
79
+
80
+ def test_nested_async_set_get
81
+ connection = Couchbase.new(:port => @mock.port)
82
+ val = nil
83
+
84
+ connection.run do |conn|
85
+ conn.set(test_id, "foo") do
86
+ conn.get(test_id) do |res|
87
+ val = res.value
88
+ end
89
+ end
90
+ end
91
+
92
+ assert_equal "foo", val
93
+ end
94
+
95
+ def test_nested_async_touch_get
96
+ connection = Couchbase.new(:port => @mock.port)
97
+ connection.set(test_id, "foo")
98
+ success = false
99
+ val = nil
100
+
101
+ connection.run do |conn|
102
+ conn.touch(test_id, :ttl => 1) do |res1|
103
+ success = res1.success?
104
+ conn.get(test_id) do |res2|
105
+ val = res2.value
106
+ end
107
+ end
108
+ end
109
+
110
+ assert success
111
+ assert_equal "foo", val
112
+ sleep(1)
113
+ refute connection.get(test_id)
114
+ end
115
+
116
+ def test_nested_async_delete_get
117
+ connection = Couchbase.new(:port => @mock.port)
118
+ cas = connection.set(test_id, "foo")
119
+ success = false
120
+ val = :unknown
121
+
122
+ connection.run do |conn|
123
+ conn.delete(test_id, :cas => cas) do |res1|
124
+ success = res1.success?
125
+ conn.get(test_id) do |res2|
126
+ val = res2.value
127
+ end
128
+ end
129
+ end
130
+
131
+ assert success
132
+ refute val
133
+ end
134
+
135
+ def test_nested_async_stats_set
136
+ connection = Couchbase.new(:port => @mock.port)
137
+ stats = {}
138
+
139
+ connection.run do |conn|
140
+ conn.stats do |res1|
141
+ id = test_id(res1.node, res1.key)
142
+ stats[id] = false
143
+ conn.set(id, res1.value) do |res2|
144
+ stats[id] = res2.cas
145
+ end
146
+ end
147
+ end
148
+
149
+ stats.keys.each do |key|
150
+ assert stats[key].is_a?(Numeric)
151
+ end
152
+ end
153
+
154
+ def test_nested_async_flush_set
155
+ connection = Couchbase.new(:port => @mock.port)
156
+ cas = connection.set(test_id, "foo")
157
+ res = {}
158
+
159
+ connection.run do |conn|
160
+ conn.flush do |res1|
161
+ assert res1.success?
162
+ id = test_id(res1.node)
163
+ res[id] = false
164
+ conn.set(id, true) do |res2|
165
+ res[id] = res2.cas
166
+ end
167
+ end
168
+ end
169
+
170
+ refute connection.get(test_id)
171
+ res.keys.each do |key|
172
+ assert res[key].is_a?(Numeric)
173
+ assert connection.get(key)
174
+ end
175
+ end
176
+
177
+ def test_nested_async_incr_get
178
+ connection = Couchbase.new(:port => @mock.port)
179
+ cas = connection.set(test_id, 1)
180
+ val = nil
181
+
182
+ connection.run do |conn|
183
+ conn.incr(test_id) do
184
+ conn.get(test_id) do |res|
185
+ val = res.value
186
+ end
187
+ end
188
+ end
189
+
190
+ assert_equal 2, val
191
+ end
192
+
193
+ def test_it_doesnt_accept_callbacks_in_synchronous_mode
194
+ connection = Couchbase.new(:port => @mock.port)
195
+ refute connection.async?
196
+
197
+ assert_raises(ArgumentError) { connection.add(test_id, "foo") {} }
198
+ assert_raises(ArgumentError) { connection.set(test_id, "foo") {} }
199
+ assert_raises(ArgumentError) { connection.replace(test_id, "foo") {} }
200
+ assert_raises(ArgumentError) { connection.get(test_id) {} }
201
+ assert_raises(ArgumentError) { connection.touch(test_id) {} }
202
+ assert_raises(ArgumentError) { connection.incr(test_id) {} }
203
+ assert_raises(ArgumentError) { connection.decr(test_id) {} }
204
+ assert_raises(ArgumentError) { connection.delete(test_id) {} }
205
+ assert_raises(ArgumentError) { connection.append(test_id, "bar") {} }
206
+ assert_raises(ArgumentError) { connection.prepend(test_id, "bar") {} }
207
+ assert_raises(ArgumentError) { connection.flush {} }
208
+ assert_raises(ArgumentError) { connection.stats {} }
209
+ end
210
+
211
+ end
@@ -1,39 +1,142 @@
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
+
1
18
  require File.join(File.dirname(__FILE__), 'setup')
2
19
 
3
20
  class TestBucket < MiniTest::Unit::TestCase
4
- def setup
5
- config_fixture = json_fixture('buckets-config.json')
6
- Couchbase::Bucket.any_instance.stubs(:http_get).returns(config_fixture)
7
- Couchbase::Bucket.class_eval do
8
- alias :listen_for_config_changes_orig :listen_for_config_changes
9
- define_method :listen_for_config_changes do
10
- setup(config_fixture.first)
21
+
22
+ def test_it_substitute_default_parts_to_url
23
+ with_mock(:port => 8091, :buckets_spec => 'default,foo') do
24
+ connections = [
25
+ Couchbase.new,
26
+ Couchbase.new('http://localhost'),
27
+ Couchbase.new('http://localhost:8091'),
28
+ Couchbase.new('http://localhost:8091/pools/default'),
29
+ Couchbase.new(:hostname => 'localhost'),
30
+ Couchbase.new(:hostname => 'localhost', :port => 8091)
31
+ ]
32
+ connections.each do |connection|
33
+ assert_equal 'localhost', connection.hostname
34
+ assert_equal 8091, connection.port
35
+ assert_equal "localhost:8091", connection.authority
36
+ assert_equal 'default', connection.bucket
37
+ assert_equal 'http://localhost:8091/pools/default/buckets/default/', connection.url
38
+ end
39
+
40
+ connections = [
41
+ Couchbase.new('http://localhost:8091/pools/default/buckets/foo'),
42
+ Couchbase.new(:bucket => 'foo'),
43
+ Couchbase.new('http://localhost:8091/pools/default/buckets/default', :bucket => 'foo')
44
+ ]
45
+ connections.each do |connection|
46
+ assert_equal 'foo', connection.bucket
47
+ assert_equal 'http://localhost:8091/pools/default/buckets/foo/', connection.url
11
48
  end
12
49
  end
50
+
51
+ with_mock do |mock| # pick first free port
52
+ connections = [
53
+ Couchbase.new("http://localhost:#{mock.port}"),
54
+ Couchbase.new(:port => mock.port),
55
+ Couchbase.new('http://localhost:8091', :port => mock.port)
56
+ ]
57
+ connections.each do |connection|
58
+ assert_equal mock.port, connection.port
59
+ assert_equal "localhost:#{mock.port}", connection.authority
60
+ assert_equal "http://localhost:#{mock.port}/pools/default/buckets/default/", connection.url
61
+ end
62
+ end
63
+
64
+ with_mock(:host => '127.0.0.1') do |mock|
65
+ connections = [
66
+ Couchbase.new("http://127.0.0.1:#{mock.port}"),
67
+ Couchbase.new(:hostname => '127.0.0.1', :port => mock.port),
68
+ Couchbase.new('http://localhost:8091', :hostname => '127.0.0.1', :port => mock.port)
69
+ ]
70
+ connections.each do |connection|
71
+ assert_equal '127.0.0.1', connection.hostname
72
+ assert_equal "127.0.0.1:#{mock.port}", connection.authority
73
+ assert_equal "http://127.0.0.1:#{mock.port}/pools/default/buckets/default/", connection.url
74
+ end
75
+ end
76
+ end
77
+
78
+ def test_it_raises_network_error_if_server_not_found
79
+ refute(`netstat -tnl` =~ /12345/)
80
+ assert_raises Couchbase::Error::Network do
81
+ Couchbase.new(:port => 12345)
82
+ end
13
83
  end
14
84
 
15
- def teardown
16
- Couchbase::Bucket.class_eval do
17
- alias :listen_for_config_changes :listen_for_config_changes_orig
85
+ def test_it_raises_argument_error_for_illegal_url
86
+ illegal = [
87
+ "ftp://localhost:8091/",
88
+ "http:/localhost:8091/",
89
+ ""
90
+ ]
91
+ illegal.each do |url|
92
+ assert_raises ArgumentError do
93
+ Couchbase.new(url)
94
+ end
18
95
  end
19
96
  end
20
97
 
21
- def test_it_should_defaults_to_default_bucket_in_production_mode
22
- bucket = Couchbase.new('http://localhost:8091/pools/default')
23
- assert_equal 'default', bucket.name
24
- assert_equal :production, bucket.environment
98
+ def test_it_able_to_connect_to_protected_buckets
99
+ with_mock(:buckets_spec => 'protected:secret') do |mock|
100
+ connection = Couchbase.new(: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
25
108
  end
26
109
 
27
- def test_it_should_initialize_itself_from_config
28
- bucket = Couchbase.new('http://localhost:8091/pools/default')
29
- assert_equal 'http://localhost:8091/pools/default/buckets/default', bucket.uri.to_s
30
- assert_equal 'membase', bucket.type
31
- assert_equal 1, bucket.nodes.size
32
- assert_equal 256, bucket.vbuckets.size
110
+ def test_it_raises_error_with_wrong_credentials
111
+ with_mock(:buckets_spec => 'protected:secret') do |mock|
112
+ assert_raises Couchbase::Error::Libcouchbase do
113
+ Couchbase.new(:port => mock.port,
114
+ :bucket => 'protected',
115
+ :username => 'wrong',
116
+ :password => 'secret')
117
+ end
118
+ assert_raises Couchbase::Error::Libcouchbase do
119
+ Couchbase.new(:port => mock.port,
120
+ :bucket => 'protected',
121
+ :username => 'protected',
122
+ :password => 'wrong')
123
+ end
124
+ end
33
125
  end
34
126
 
35
- def test_initialization_low_level_drivers
36
- bucket = Couchbase.new('http://localhost:8091/pools/default', :format => :plain)
37
- assert_equal :plain, bucket.default_format
127
+ def test_it_allows_change_quiet_flag
128
+ with_mock do |mock|
129
+ connection = Couchbase.new(:port => mock.port)
130
+ assert connection.quiet?
131
+
132
+ connection = Couchbase.new(:port => mock.port, :quiet => true)
133
+ assert connection.quiet?
134
+
135
+ connection.quiet = nil
136
+ assert_equal false, connection.quiet?
137
+
138
+ connection.quiet = :foo
139
+ assert_equal true, connection.quiet?
140
+ end
38
141
  end
39
142
  end