riak-client 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/Rakefile +74 -0
  2. data/lib/riak.rb +49 -0
  3. data/lib/riak/bucket.rb +176 -0
  4. data/lib/riak/cache_store.rb +82 -0
  5. data/lib/riak/client.rb +139 -0
  6. data/lib/riak/client/curb_backend.rb +82 -0
  7. data/lib/riak/client/http_backend.rb +209 -0
  8. data/lib/riak/client/net_http_backend.rb +49 -0
  9. data/lib/riak/failed_request.rb +37 -0
  10. data/lib/riak/i18n.rb +20 -0
  11. data/lib/riak/invalid_response.rb +25 -0
  12. data/lib/riak/link.rb +73 -0
  13. data/lib/riak/locale/en.yml +37 -0
  14. data/lib/riak/map_reduce.rb +248 -0
  15. data/lib/riak/map_reduce_error.rb +20 -0
  16. data/lib/riak/robject.rb +267 -0
  17. data/lib/riak/util/escape.rb +12 -0
  18. data/lib/riak/util/fiber1.8.rb +48 -0
  19. data/lib/riak/util/headers.rb +44 -0
  20. data/lib/riak/util/multipart.rb +52 -0
  21. data/lib/riak/util/translation.rb +29 -0
  22. data/lib/riak/walk_spec.rb +117 -0
  23. data/spec/fixtures/cat.jpg +0 -0
  24. data/spec/fixtures/multipart-blank.txt +7 -0
  25. data/spec/fixtures/multipart-with-body.txt +16 -0
  26. data/spec/integration/riak/cache_store_spec.rb +129 -0
  27. data/spec/riak/bucket_spec.rb +247 -0
  28. data/spec/riak/client_spec.rb +174 -0
  29. data/spec/riak/curb_backend_spec.rb +53 -0
  30. data/spec/riak/escape_spec.rb +21 -0
  31. data/spec/riak/headers_spec.rb +34 -0
  32. data/spec/riak/http_backend_spec.rb +131 -0
  33. data/spec/riak/link_spec.rb +82 -0
  34. data/spec/riak/map_reduce_spec.rb +352 -0
  35. data/spec/riak/multipart_spec.rb +36 -0
  36. data/spec/riak/net_http_backend_spec.rb +28 -0
  37. data/spec/riak/object_spec.rb +538 -0
  38. data/spec/riak/walk_spec_spec.rb +208 -0
  39. data/spec/spec_helper.rb +30 -0
  40. data/spec/support/http_backend_implementation_examples.rb +215 -0
  41. data/spec/support/mock_server.rb +61 -0
  42. data/spec/support/mocks.rb +3 -0
  43. metadata +187 -0
@@ -0,0 +1,208 @@
1
+ # Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ require File.expand_path("../spec_helper", File.dirname(__FILE__))
15
+
16
+ describe Riak::WalkSpec do
17
+ describe "initializing" do
18
+ describe "with a hash" do
19
+ it "should be empty by default" do
20
+ spec = Riak::WalkSpec.new({})
21
+ spec.bucket.should == "_"
22
+ spec.tag.should == "_"
23
+ spec.keep.should be_false
24
+ end
25
+
26
+ it "should extract the bucket" do
27
+ spec = Riak::WalkSpec.new({:bucket => "foo"})
28
+ spec.bucket.should == "foo"
29
+ spec.tag.should == "_"
30
+ spec.keep.should be_false
31
+ end
32
+
33
+ it "should extract the tag" do
34
+ spec = Riak::WalkSpec.new({:tag => "foo"})
35
+ spec.bucket.should == "_"
36
+ spec.tag.should == "foo"
37
+ spec.keep.should be_false
38
+ end
39
+
40
+ it "should extract the keep" do
41
+ spec = Riak::WalkSpec.new({:keep => true})
42
+ spec.bucket.should == "_"
43
+ spec.tag.should == "_"
44
+ spec.keep.should be_true
45
+ end
46
+ end
47
+
48
+ describe "with three arguments for bucket, tag, and keep" do
49
+ it "should assign the bucket, tag, and keep" do
50
+ spec = Riak::WalkSpec.new("foo", "next", false)
51
+ spec.bucket.should == "foo"
52
+ spec.tag.should == "next"
53
+ spec.keep.should be_false
54
+ end
55
+
56
+ it "should make the bucket '_' when false or nil" do
57
+ spec = Riak::WalkSpec.new(nil, "next", false)
58
+ spec.bucket.should == "_"
59
+ spec = Riak::WalkSpec.new(false, "next", false)
60
+ spec.bucket.should == "_"
61
+ end
62
+
63
+ it "should make the tag '_' when false or nil" do
64
+ spec = Riak::WalkSpec.new("foo", nil, false)
65
+ spec.tag.should == "_"
66
+ spec = Riak::WalkSpec.new("foo", false, false)
67
+ spec.tag.should == "_"
68
+ end
69
+
70
+ it "should make the keep false when false or nil" do
71
+ spec = Riak::WalkSpec.new(nil, nil, nil)
72
+ spec.keep.should be_false
73
+ spec = Riak::WalkSpec.new(nil, nil, false)
74
+ spec.keep.should be_false
75
+ end
76
+ end
77
+
78
+ it "should raise an ArgumentError for invalid arguments" do
79
+ lambda { Riak::WalkSpec.new }.should raise_error(ArgumentError)
80
+ lambda { Riak::WalkSpec.new("foo") }.should raise_error(ArgumentError)
81
+ lambda { Riak::WalkSpec.new("foo","bar") }.should raise_error(ArgumentError)
82
+ end
83
+ end
84
+
85
+ describe "converting to a string" do
86
+ before :each do
87
+ @spec = Riak::WalkSpec.new({})
88
+ end
89
+
90
+ it "should be the empty spec by default" do
91
+ @spec.to_s.should == "_,_,_"
92
+ end
93
+
94
+ it "should include the bucket when set" do
95
+ @spec.bucket = "foo"
96
+ @spec.to_s.should == "foo,_,_"
97
+ end
98
+
99
+ it "should include the tag when set" do
100
+ @spec.tag = "next"
101
+ @spec.to_s.should == "_,next,_"
102
+ end
103
+
104
+ it "should include the keep when true" do
105
+ @spec.keep = true
106
+ @spec.to_s.should == "_,_,1"
107
+ end
108
+ end
109
+
110
+ describe "creating from a list of parameters" do
111
+ it "should detect hashes and WalkSpecs interleaved with other parameters" do
112
+ specs = Riak::WalkSpec.normalize(nil,"next",nil,{:bucket => "foo"},Riak::WalkSpec.new({:tag => "child", :keep => true}))
113
+ specs.should have(3).items
114
+ specs.should be_all {|s| s.kind_of?(Riak::WalkSpec) }
115
+ specs.join("/").should == "_,next,_/foo,_,_/_,child,1"
116
+ end
117
+ end
118
+
119
+ describe "matching other objects with ===" do
120
+ before :each do
121
+ @spec = Riak::WalkSpec.new({})
122
+ end
123
+
124
+ it "should not match objects that aren't links or walk specs" do
125
+ @spec.should_not === "foo"
126
+ end
127
+
128
+ describe "matching links" do
129
+ before :each do
130
+ @link = Riak::Link.new("/riak/foo/bar", "next")
131
+ end
132
+
133
+ it "should match a link when the bucket and tag are not specified" do
134
+ @spec.should === @link
135
+ end
136
+
137
+ it "should match a link when the bucket is the same" do
138
+ @spec.bucket = "foo"
139
+ @spec.should === @link
140
+ end
141
+
142
+ it "should not match a link when the bucket is different" do
143
+ @spec.bucket = "bar"
144
+ @spec.should_not === @link
145
+ end
146
+
147
+ it "should match a link when the tag is the same" do
148
+ @spec.tag = "next"
149
+ @spec.should === @link
150
+ end
151
+
152
+ it "should not match a link when the tag is different" do
153
+ @spec.tag = "previous"
154
+ @spec.should_not === @link
155
+ end
156
+
157
+ it "should match a link when the bucket and tag are the same" do
158
+ @spec.bucket = "foo"
159
+ @spec.should === @link
160
+ end
161
+ end
162
+
163
+ describe "matching walk specs" do
164
+ before :each do
165
+ @other = Riak::WalkSpec.new({})
166
+ end
167
+
168
+ it "should match a walk spec that is equivalent" do
169
+ @spec.should === @other
170
+ end
171
+
172
+ it "should not match a walk spec that has a different keep value" do
173
+ @other.keep = true
174
+ @spec.should_not === @other
175
+ end
176
+
177
+ it "should match a walk spec with a more specific bucket" do
178
+ @other.bucket = "foo"
179
+ @spec.should === @other
180
+ end
181
+
182
+ it "should match a walk spec with the same bucket" do
183
+ @other.bucket = "foo"; @spec.bucket = "foo"
184
+ @spec.should === @other
185
+ end
186
+
187
+ it "should not match a walk spec with a different bucket" do
188
+ @other.bucket = "foo"; @spec.bucket = "bar"
189
+ @spec.should_not === @other
190
+ end
191
+
192
+ it "should match a walk spec with a more specific tag" do
193
+ @other.tag = "next"
194
+ @spec.should === @other
195
+ end
196
+
197
+ it "should match a walk spec with the same tag" do
198
+ @other.tag = "next"; @spec.tag = "next"
199
+ @spec.should === @other
200
+ end
201
+
202
+ it "should not match a walk spec with a different tag" do
203
+ @other.tag = "next"; @spec.tag = "previous"
204
+ @spec.should_not === @other
205
+ end
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,30 @@
1
+ # Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
16
+
17
+ require 'rubygems' # Use the gems path only for the spec suite
18
+ require 'riak'
19
+ require 'rspec/autorun'
20
+ require 'fakeweb'
21
+
22
+ Dir[File.join(File.dirname(__FILE__), "support", "*.rb")].each {|f| require f }
23
+
24
+ Rspec.configure do |config|
25
+ config.mock_with :rspec
26
+
27
+ config.before(:each) do
28
+ FakeWeb.clean_registry
29
+ end
30
+ end
@@ -0,0 +1,215 @@
1
+ # Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ shared_examples_for "HTTP backend" do
15
+ describe "HEAD requests" do
16
+ before :each do
17
+ setup_http_mock(:head, @backend.path("/riak/","foo").to_s, :body => "")
18
+ end
19
+
20
+ it "should return only the headers when the request succeeds" do
21
+ response = @backend.head(200, "/riak/","foo")
22
+ response.should_not have_key(:body)
23
+ response[:headers].should be_kind_of(Hash)
24
+ response[:code].should == 200
25
+ end
26
+
27
+ it "should raise a FailedRequest exception when the request fails" do
28
+ lambda { @backend.head(301, "/riak/", "foo") }.should raise_error(Riak::FailedRequest)
29
+ end
30
+
31
+ it "should raise an error if an invalid resource path is given" do
32
+ lambda { @backend.head(200, "/riak/") }.should raise_error(ArgumentError)
33
+ end
34
+
35
+ it "should not raise a FailedRequest if one of the expected response codes matches" do
36
+ lambda { @backend.head([200, 301], "/riak/", "foo") }.should_not raise_error(Riak::FailedRequest)
37
+ end
38
+ end
39
+
40
+ describe "GET requests" do
41
+ before :each do
42
+ setup_http_mock(:get, @backend.path("/riak/","foo").to_s, :body => "Success!")
43
+ end
44
+
45
+ it "should return the response body and headers when the request succeeds" do
46
+ response = @backend.get(200, "/riak/","foo")
47
+ response[:body].should == "Success!"
48
+ response[:headers].should be_kind_of(Hash)
49
+ response[:code].should == 200
50
+ end
51
+
52
+ it "should raise a FailedRequest exception when the request fails" do
53
+ lambda { @backend.get(304, "/riak/","foo") }.should raise_error(Riak::FailedRequest)
54
+ end
55
+
56
+ it "should not raise a FailedRequest if one of the expected response codes matches" do
57
+ lambda { @backend.get([200, 301], "/riak/","foo") }.should_not raise_error(Riak::FailedRequest)
58
+ end
59
+
60
+ it "should yield successive chunks of the response to the given block but not return the entire body" do
61
+ chunks = ""
62
+ response = @backend.get(200, "/riak/","foo") do |chunk|
63
+ chunks << chunk
64
+ end
65
+ chunks.should == "Success!"
66
+ response.should_not have_key(:body)
67
+ response[:headers].should be_kind_of(Hash)
68
+ response[:code].should == 200
69
+ end
70
+
71
+ it "should raise an error if an invalid resource path is given" do
72
+ lambda { @backend.get(200, "/riak/") }.should raise_error(ArgumentError)
73
+ end
74
+ end
75
+
76
+ describe "DELETE requests" do
77
+ before :each do
78
+ setup_http_mock(:delete, @backend.path("/riak/","foo").to_s, :body => "Success!")
79
+ end
80
+
81
+ it "should return the response body and headers when the request succeeds" do
82
+ response = @backend.delete(200, "/riak/","foo")
83
+ response[:body].should == "Success!"
84
+ response[:headers].should be_kind_of(Hash)
85
+ end
86
+
87
+ it "should raise a FailedRequest exception when the request fails" do
88
+ lambda { @backend.delete(304, "/riak/","foo") }.should raise_error(Riak::FailedRequest)
89
+ end
90
+
91
+ it "should not raise a FailedRequest if one of the expected response codes matches" do
92
+ lambda { @backend.delete([200, 301], "/riak/","foo") }.should_not raise_error(Riak::FailedRequest)
93
+ end
94
+
95
+ it "should yield successive chunks of the response to the given block but not return the entire body" do
96
+ chunks = ""
97
+ response = @backend.delete(200, "/riak/","foo") do |chunk|
98
+ chunks << chunk
99
+ end
100
+ chunks.should == "Success!"
101
+ response.should_not have_key(:body)
102
+ response[:headers].should be_kind_of(Hash)
103
+ response[:code].should == 200
104
+ end
105
+
106
+ it "should raise an error if an invalid resource path is given" do
107
+ lambda { @backend.delete(200, "/riak/") }.should raise_error(ArgumentError)
108
+ end
109
+ end
110
+
111
+ describe "PUT requests" do
112
+ before :each do
113
+ setup_http_mock(:put, @backend.path("/riak/","foo").to_s, :body => "Success!")
114
+ end
115
+
116
+ it "should return the response body, headers, and code when the request succeeds" do
117
+ response = @backend.put(200, "/riak/","foo", "This is the body.")
118
+ response[:body].should == "Success!"
119
+ response[:headers].should be_kind_of(Hash)
120
+ response[:code].should == 200
121
+ end
122
+
123
+ it "should raise a FailedRequest exception when the request fails" do
124
+ lambda { @backend.put(204, "/riak/","foo", "This is the body.") }.should raise_error(Riak::FailedRequest)
125
+ end
126
+
127
+ it "should not raise a FailedRequest if one of the expected response codes matches" do
128
+ lambda { @backend.put([200, 204], "/riak/","foo", "This is the body.") }.should_not raise_error(Riak::FailedRequest)
129
+ end
130
+
131
+
132
+ it "should yield successive chunks of the response to the given block but not return the entire body" do
133
+ chunks = ""
134
+ response = @backend.put(200, "/riak/","foo", "This is the body.") do |chunk|
135
+ chunks << chunk
136
+ end
137
+ chunks.should == "Success!"
138
+ response.should_not have_key(:body)
139
+ response[:headers].should be_kind_of(Hash)
140
+ response[:code].should == 200
141
+ end
142
+
143
+ it "should raise an error if an invalid resource path is given" do
144
+ lambda { @backend.put(200, "/riak/") }.should raise_error(ArgumentError)
145
+ end
146
+
147
+ it "should raise an error if no body data is given" do
148
+ lambda { @backend.put(200, "/riak/","foo") }.should raise_error(ArgumentError)
149
+ end
150
+
151
+ it "should raise an error if the body is not a string" do
152
+ lambda { @backend.put(200, "/riak/","foo", 123) }.should raise_error(ArgumentError)
153
+ end
154
+ end
155
+
156
+ describe "POST requests" do
157
+ before :each do
158
+ setup_http_mock(:post, @backend.path("/riak/","foo").to_s, :body => "Success!")
159
+ end
160
+
161
+ it "should return the response body, headers, and code when the request succeeds" do
162
+ response = @backend.post(200, "/riak/","foo", "This is the body.")
163
+ response[:body].should == "Success!"
164
+ response[:headers].should be_kind_of(Hash)
165
+ response[:code].should == 200
166
+ end
167
+
168
+ it "should raise a FailedRequest exception when the request fails" do
169
+ lambda { @backend.post(204, "/riak/", "foo", "This is the body.") }.should raise_error(Riak::FailedRequest)
170
+ end
171
+
172
+ it "should not raise a FailedRequest if one of the expected response codes matches" do
173
+ lambda { @backend.post([200, 204], "/riak/", "foo", "This is the body.") }.should_not raise_error(Riak::FailedRequest)
174
+ end
175
+
176
+ it "should yield successive chunks of the response to the given block but not return the entire body" do
177
+ chunks = ""
178
+ response = @backend.post(200, "/riak/", "foo", "This is the body.") do |chunk|
179
+ chunks << chunk
180
+ end
181
+ chunks.should == "Success!"
182
+ response.should_not have_key(:body)
183
+ response[:headers].should be_kind_of(Hash)
184
+ response[:code].should == 200
185
+ end
186
+
187
+ it "should raise an error if an invalid resource path is given" do
188
+ lambda { @backend.post(200, "/riak/") }.should raise_error(ArgumentError)
189
+ end
190
+
191
+ it "should raise an error if no body data is given" do
192
+ lambda { @backend.post(200, "/riak/", "foo") }.should raise_error(ArgumentError)
193
+ end
194
+
195
+ it "should raise an error if the body is not a string" do
196
+ lambda { @backend.post(200, "/riak/", "foo", 123) }.should raise_error(ArgumentError)
197
+ end
198
+ end
199
+
200
+ describe "Responses with no body" do
201
+ [204, 205, 304].each do |code|
202
+ [:get, :post, :put, :delete].each do |method|
203
+ it "should not return a body on #{method.to_s.upcase} for #{code}" do
204
+ setup_http_mock(method, @backend.path("/riak/","foo").to_s, :status => code)
205
+ response = if method == :post || method == :put
206
+ @backend.send(method, code,"/riak/","foo", "This is the body")
207
+ else
208
+ @backend.send(method, code, "/riak/", "foo")
209
+ end
210
+ response.should_not have_key(:body)
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end