couchbase 0.9.8 → 1.0.0

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