ripple 0.5.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.
- data/.document +5 -0
- data/.gitignore +26 -0
- data/LICENSE +13 -0
- data/README.textile +126 -0
- data/RELEASE_NOTES.textile +24 -0
- data/Rakefile +61 -0
- data/VERSION +1 -0
- data/lib/riak.rb +45 -0
- data/lib/riak/bucket.rb +105 -0
- data/lib/riak/client.rb +138 -0
- data/lib/riak/client/curb_backend.rb +63 -0
- data/lib/riak/client/http_backend.rb +209 -0
- data/lib/riak/client/net_http_backend.rb +49 -0
- data/lib/riak/failed_request.rb +37 -0
- data/lib/riak/i18n.rb +15 -0
- data/lib/riak/invalid_response.rb +25 -0
- data/lib/riak/link.rb +54 -0
- data/lib/riak/locale/en.yml +37 -0
- data/lib/riak/map_reduce.rb +240 -0
- data/lib/riak/map_reduce_error.rb +20 -0
- data/lib/riak/robject.rb +234 -0
- data/lib/riak/util/headers.rb +44 -0
- data/lib/riak/util/multipart.rb +52 -0
- data/lib/riak/util/translation.rb +29 -0
- data/lib/riak/walk_spec.rb +113 -0
- data/lib/ripple.rb +48 -0
- data/lib/ripple/core_ext/casting.rb +96 -0
- data/lib/ripple/document.rb +60 -0
- data/lib/ripple/document/attribute_methods.rb +111 -0
- data/lib/ripple/document/attribute_methods/dirty.rb +52 -0
- data/lib/ripple/document/attribute_methods/query.rb +49 -0
- data/lib/ripple/document/attribute_methods/read.rb +38 -0
- data/lib/ripple/document/attribute_methods/write.rb +36 -0
- data/lib/ripple/document/bucket_access.rb +38 -0
- data/lib/ripple/document/finders.rb +84 -0
- data/lib/ripple/document/persistence.rb +93 -0
- data/lib/ripple/document/persistence/callbacks.rb +48 -0
- data/lib/ripple/document/properties.rb +85 -0
- data/lib/ripple/document/validations.rb +44 -0
- data/lib/ripple/embedded_document.rb +38 -0
- data/lib/ripple/embedded_document/persistence.rb +46 -0
- data/lib/ripple/i18n.rb +15 -0
- data/lib/ripple/locale/en.yml +16 -0
- data/lib/ripple/property_type_mismatch.rb +23 -0
- data/lib/ripple/translation.rb +24 -0
- data/ripple.gemspec +159 -0
- data/spec/fixtures/cat.jpg +0 -0
- data/spec/fixtures/multipart-blank.txt +7 -0
- data/spec/fixtures/multipart-with-body.txt +16 -0
- data/spec/riak/bucket_spec.rb +141 -0
- data/spec/riak/client_spec.rb +169 -0
- data/spec/riak/curb_backend_spec.rb +50 -0
- data/spec/riak/headers_spec.rb +34 -0
- data/spec/riak/http_backend_spec.rb +136 -0
- data/spec/riak/link_spec.rb +50 -0
- data/spec/riak/map_reduce_spec.rb +347 -0
- data/spec/riak/multipart_spec.rb +36 -0
- data/spec/riak/net_http_backend_spec.rb +28 -0
- data/spec/riak/object_spec.rb +444 -0
- data/spec/riak/walk_spec_spec.rb +208 -0
- data/spec/ripple/attribute_methods_spec.rb +149 -0
- data/spec/ripple/bucket_access_spec.rb +48 -0
- data/spec/ripple/callbacks_spec.rb +86 -0
- data/spec/ripple/document_spec.rb +35 -0
- data/spec/ripple/embedded_document_spec.rb +52 -0
- data/spec/ripple/finders_spec.rb +146 -0
- data/spec/ripple/persistence_spec.rb +89 -0
- data/spec/ripple/properties_spec.rb +195 -0
- data/spec/ripple/ripple_spec.rb +43 -0
- data/spec/ripple/validations_spec.rb +64 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/http_backend_implementation_examples.rb +215 -0
- data/spec/support/mock_server.rb +58 -0
- metadata +221 -0
Binary file
|
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
--5EiMOjuGavQ2IbXAqsJPLLfJNlA
|
3
|
+
Content-Type: multipart/mixed; boundary=7extjTzvYIKVMVHowUiTn0LfvSs
|
4
|
+
|
5
|
+
--7extjTzvYIKVMVHowUiTn0LfvSs
|
6
|
+
X-Riak-Vclock: a85hYGBgyWDKBVHMr9s3ZzAlMuaxMtyZcPAIH1RYyObHDqiwxIZjcOG1M98chAq3bUQIz7SSFQEKM4FUbwMKZwEA
|
7
|
+
Location: /raw/foo/baz
|
8
|
+
Content-Type: text/plain
|
9
|
+
Link: </raw/foo>; rel="up"
|
10
|
+
Etag: 6JdI51eFrvv5lDwY6un7a2
|
11
|
+
Last-Modified: Sat, 16 Jan 2010 22:13:44 GMT
|
12
|
+
|
13
|
+
SCP sloooow....
|
14
|
+
--7extjTzvYIKVMVHowUiTn0LfvSs--
|
15
|
+
|
16
|
+
--5EiMOjuGavQ2IbXAqsJPLLfJNlA--
|
@@ -0,0 +1,141 @@
|
|
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::Bucket do
|
17
|
+
before :each do
|
18
|
+
@client = Riak::Client.new
|
19
|
+
@bucket = Riak::Bucket.new(@client, "foo")
|
20
|
+
end
|
21
|
+
|
22
|
+
def do_load(overrides={})
|
23
|
+
@bucket.load({
|
24
|
+
:body => '{"props":{"name":"foo","allow_mult":false,"big_vclock":50,"chash_keyfun":{"mod":"riak_util","fun":"chash_std_keyfun"},"linkfun":{"mod":"jiak_object","fun":"mapreduce_linkfun"},"n_val":3,"old_vclock":86400,"small_vclock":10,"young_vclock":20},"keys":["bar"]}',
|
25
|
+
:headers => {
|
26
|
+
"vary" => ["Accept-Encoding"],
|
27
|
+
"server" => ["MochiWeb/1.1 WebMachine/1.5.1 (hack the charles gibson)"],
|
28
|
+
"link" => ['</raw/foo/bar>; riaktag="contained"'],
|
29
|
+
"date" => ["Tue, 12 Jan 2010 15:30:43 GMT"],
|
30
|
+
"content-type" => ["application/json"],
|
31
|
+
"content-length" => ["257"]
|
32
|
+
}
|
33
|
+
}.merge(overrides))
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
describe "when initializing" do
|
38
|
+
it "should require a client and a name" do
|
39
|
+
lambda { Riak::Bucket.new }.should raise_error
|
40
|
+
lambda { Riak::Bucket.new(@client) }.should raise_error
|
41
|
+
lambda { Riak::Bucket.new("foo") }.should raise_error
|
42
|
+
lambda { Riak::Bucket.new("foo", @client) }.should raise_error
|
43
|
+
lambda { Riak::Bucket.new(@client, "foo") }.should_not raise_error
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should set the client and name attributes" do
|
47
|
+
bucket = Riak::Bucket.new(@client, "foo")
|
48
|
+
bucket.client.should == @client
|
49
|
+
bucket.name.should == "foo"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "when loading data from an HTTP response" do
|
54
|
+
it "should load the bucket properties from the response body" do
|
55
|
+
do_load
|
56
|
+
@bucket.props.should == {"name"=>"foo","allow_mult" => false,"big_vclock" => 50,"chash_keyfun" => {"mod" =>"riak_util","fun"=>"chash_std_keyfun"},"linkfun"=>{"mod"=>"jiak_object","fun"=>"mapreduce_linkfun"},"n_val"=>3,"old_vclock"=>86400,"small_vclock"=>10,"young_vclock"=>20}
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should load the keys from the response body" do
|
60
|
+
do_load
|
61
|
+
@bucket.keys.should == ["bar"]
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should raise an error for a response that is not JSON" do
|
65
|
+
lambda do
|
66
|
+
do_load(:headers => {"content-type" => ["text/plain"]})
|
67
|
+
end.should raise_error(Riak::InvalidResponse)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should unescape key names" do
|
71
|
+
do_load(:body => '{"keys":["foo", "bar%20baz"]}')
|
72
|
+
@bucket.keys.should == ["foo", "bar baz"]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "accessing keys" do
|
77
|
+
before :each do
|
78
|
+
@http = mock("HTTPBackend")
|
79
|
+
@client.stub!(:http).and_return(@http)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should load the keys if not present" do
|
83
|
+
@http.should_receive(:get).with(200, "/raw/", "foo", {:props => false}, {}).and_return({:headers => {"content-type" => ["application/json"]}, :body => '{"keys":["bar"]}'})
|
84
|
+
@bucket.keys.should == ["bar"]
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should allow reloading of the keys" do
|
88
|
+
@http.should_receive(:get).with(200, "/raw/","foo", {:props => false}, {}).and_return({:headers => {"content-type" => ["application/json"]}, :body => '{"keys":["bar"]}'})
|
89
|
+
do_load # Ensures they're already loaded
|
90
|
+
@bucket.keys(:reload => true).should == ["bar"]
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should allow streaming keys through block" do
|
94
|
+
# pending "Needs support in the raw_http_resource"
|
95
|
+
@http.should_receive(:get).with(200, "/raw/","foo", {:props => false}, {}).and_yield("{}").and_yield('{"keys":[]}').and_yield('{"keys":["bar"]}').and_yield('{"keys":["baz"]}')
|
96
|
+
all_keys = []
|
97
|
+
@bucket.keys do |list|
|
98
|
+
all_keys.concat(list)
|
99
|
+
end
|
100
|
+
all_keys.should == ["bar", "baz"]
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should unescape key names" do
|
104
|
+
@http.should_receive(:get).with(200, "/raw/","foo", {:props => false}, {}).and_return({:headers => {"content-type" => ["application/json"]}, :body => '{"keys":["bar%20baz"]}'})
|
105
|
+
@bucket.keys.should == ["bar baz"]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "setting the bucket properties" do
|
110
|
+
before :each do
|
111
|
+
@http = mock("HTTPBackend")
|
112
|
+
@client.stub!(:http).and_return(@http)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should PUT the new properties to the bucket" do
|
116
|
+
@http.should_receive(:put).with(204, "/raw/","foo", '{"props":{"name":"foo"}}', {"Content-Type" => "application/json"}).and_return({:body => "", :headers => {}})
|
117
|
+
@bucket.props = { :name => "foo" }
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should raise an error if an invalid property is given" do
|
121
|
+
lambda { @bucket.props = "blah" }.should raise_error(ArgumentError)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "fetching an object" do
|
126
|
+
before :each do
|
127
|
+
@http = mock("HTTPBackend")
|
128
|
+
@client.stub!(:http).and_return(@http)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should load the object from the server as a Riak::RObject" do
|
132
|
+
@http.should_receive(:get).with(200, "/raw/","foo", "db", {}, {}).and_return({:headers => {"content-type" => ["application/json"]}, :body => '{"name":"Riak","company":"Basho"}'})
|
133
|
+
@bucket.get("db").should be_kind_of(Riak::RObject)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should use the given query parameters (for R value, etc)" do
|
137
|
+
@http.should_receive(:get).with(200, "/raw/","foo", "db", {:r => 2}, {}).and_return({:headers => {"content-type" => ["application/json"]}, :body => '{"name":"Riak","company":"Basho"}'})
|
138
|
+
@bucket.get("db", :r => 2).should be_kind_of(Riak::RObject)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,169 @@
|
|
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::Client do
|
17
|
+
describe "when initializing" do
|
18
|
+
it "should default to the local interface on port 8098" do
|
19
|
+
client = Riak::Client.new
|
20
|
+
client.host.should == "127.0.0.1"
|
21
|
+
client.port.should == 8098
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should accept a host" do
|
25
|
+
client = Riak::Client.new :host => "riak.basho.com"
|
26
|
+
client.host.should == "riak.basho.com"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should accept a port" do
|
30
|
+
client = Riak::Client.new :port => 9000
|
31
|
+
client.port.should == 9000
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should accept a client ID" do
|
35
|
+
client = Riak::Client.new :client_id => "AAAAAA=="
|
36
|
+
client.client_id.should == "AAAAAA=="
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should turn an integer client ID into a base64-encoded string" do
|
40
|
+
client = Riak::Client.new :client_id => 1
|
41
|
+
client.client_id.should == "AAAAAQ=="
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should create a client ID if not specified" do
|
45
|
+
Riak::Client.new.client_id.should be_kind_of(String)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should accept a path prefix" do
|
49
|
+
client = Riak::Client.new(:prefix => "/jiak/")
|
50
|
+
client.prefix.should == "/jiak/"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should default the prefix to /raw/ if not specified" do
|
54
|
+
Riak::Client.new.prefix.should == "/raw/"
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should accept a mapreduce path" do
|
58
|
+
client = Riak::Client.new(:mapred => "/mr")
|
59
|
+
client.mapred.should == "/mr"
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should default the mapreduce path to /mapred if not specified" do
|
63
|
+
Riak::Client.new.mapred.should == "/mapred"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "reconfiguring" do
|
68
|
+
before :each do
|
69
|
+
@client = Riak::Client.new
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "setting the host" do
|
73
|
+
it "should allow setting the host" do
|
74
|
+
@client.should respond_to(:host=)
|
75
|
+
@client.host = "riak.basho.com"
|
76
|
+
@client.host.should == "riak.basho.com"
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should require the host to be an IP or hostname" do
|
80
|
+
[238472384972, ""].each do |invalid|
|
81
|
+
lambda { @client.host = invalid }.should raise_error(ArgumentError)
|
82
|
+
end
|
83
|
+
["127.0.0.1", "10.0.100.5", "localhost", "otherhost.local", "riak.basho.com"].each do |valid|
|
84
|
+
lambda { @client.host = valid }.should_not raise_error
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "setting the port" do
|
90
|
+
it "should allow setting the port" do
|
91
|
+
@client.should respond_to(:port=)
|
92
|
+
@client.port = 9000
|
93
|
+
@client.port.should == 9000
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should require the port to be a valid number" do
|
97
|
+
[-1,65536,"foo"].each do |invalid|
|
98
|
+
lambda { @client.port = invalid }.should raise_error(ArgumentError)
|
99
|
+
end
|
100
|
+
[0,1,65535,8098].each do |valid|
|
101
|
+
lambda { @client.port = valid }.should_not raise_error
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should allow setting the prefix (although we prefer the raw interface)" do
|
107
|
+
@client.should respond_to(:prefix=)
|
108
|
+
@client.prefix = "/another-prefix"
|
109
|
+
@client.prefix.should == "/another-prefix"
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "setting the client id" do
|
113
|
+
it "should accept a string unmodified" do
|
114
|
+
@client.client_id = "foo"
|
115
|
+
@client.client_id.should == "foo"
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should base64-encode an integer" do
|
119
|
+
@client.client_id = 1
|
120
|
+
@client.client_id.should == "AAAAAQ=="
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should reject an integer equal to the maximum client id" do
|
124
|
+
lambda { @client.client_id = Riak::Client::MAX_CLIENT_ID }.should raise_error(ArgumentError)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should reject an integer larger than the maximum client id" do
|
128
|
+
lambda { @client.client_id = Riak::Client::MAX_CLIENT_ID + 1 }.should raise_error(ArgumentError)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "choosing an HTTP backend" do
|
134
|
+
before :each do
|
135
|
+
@client = Riak::Client.new
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should choose the Curb backend if Curb is available" do
|
139
|
+
@client.should_receive(:require).with('curb').and_return(true)
|
140
|
+
@client.http.should be_instance_of(Riak::Client::CurbBackend)
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should choose the Net::HTTP backend if Curb is unavailable" do
|
144
|
+
@client.should_receive(:require).with('curb').and_raise(LoadError)
|
145
|
+
@client.should_receive(:warn).and_return(true)
|
146
|
+
@client.http.should be_instance_of(Riak::Client::NetHTTPBackend)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "retrieving a bucket" do
|
151
|
+
before :each do
|
152
|
+
@client = Riak::Client.new
|
153
|
+
@http = mock(Riak::Client::HTTPBackend)
|
154
|
+
@client.stub!(:http).and_return(@http)
|
155
|
+
@payload = {:headers => {"content-type" => ["application/json"]}, :body => "{}"}
|
156
|
+
@http.stub!(:get).and_return(@payload)
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should send a GET request to the bucket name and return a Riak::Bucket" do
|
160
|
+
@http.should_receive(:get).with(200, "/raw/", "foo", {}, {}).and_return(@payload)
|
161
|
+
@client.bucket("foo").should be_kind_of(Riak::Bucket)
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should allow requesting bucket properties without the keys" do
|
165
|
+
@http.should_receive(:get).with(200, "/raw/", "foo", {:keys => false}, {}).and_return(@payload)
|
166
|
+
@client.bucket("foo", :keys => false)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,50 @@
|
|
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
|
+
begin
|
17
|
+
require 'curb'
|
18
|
+
rescue LoadError
|
19
|
+
warn "Skipping CurbBackend specs, curb library not found."
|
20
|
+
else
|
21
|
+
describe Riak::Client::CurbBackend do
|
22
|
+
def setup_http_mock(method, uri, options={})
|
23
|
+
method = method.to_s.upcase
|
24
|
+
uri = URI.parse(uri)
|
25
|
+
path = uri.path || "/"
|
26
|
+
query = uri.query || ""
|
27
|
+
status = options[:status] ? Array(options[:status]).first.to_i : 200
|
28
|
+
body = options[:body] || []
|
29
|
+
headers = options[:headers] || {}
|
30
|
+
headers['Content-Type'] ||= "text/plain"
|
31
|
+
$server.attach do |env|
|
32
|
+
env["REQUEST_METHOD"].should == method
|
33
|
+
env["PATH_INFO"].should == path
|
34
|
+
env["QUERY_STRING"].should == query
|
35
|
+
[status, headers, Array(body)]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
before :each do
|
40
|
+
@client = Riak::Client.new(:port => 4000) # Point to our mock
|
41
|
+
@backend = Riak::Client::CurbBackend.new(@client)
|
42
|
+
end
|
43
|
+
|
44
|
+
it_should_behave_like "HTTP backend"
|
45
|
+
|
46
|
+
after :each do
|
47
|
+
$server.detach
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,34 @@
|
|
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::Util::Headers do
|
17
|
+
it "should include the Net::HTTPHeader module" do
|
18
|
+
Riak::Util::Headers.included_modules.should include(Net::HTTPHeader)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should be initially empty" do
|
22
|
+
Riak::Util::Headers.new.to_hash.should == {}
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should parse a header line into the key and value" do
|
26
|
+
Riak::Util::Headers.parse("Content-Type: text/plain\n").should == ["Content-Type", "text/plain"]
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should parse a header line and add it to the collection" do
|
30
|
+
h = Riak::Util::Headers.new
|
31
|
+
h.parse("Content-Type: text/plain\n")
|
32
|
+
h.to_hash.should == {"content-type" => ["text/plain"]}
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,136 @@
|
|
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::Client::HTTPBackend do
|
17
|
+
before :each do
|
18
|
+
@client = Riak::Client.new
|
19
|
+
@backend = Riak::Client::HTTPBackend.new(@client)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should take the Riak::Client when creating" do
|
23
|
+
lambda { Riak::Client::HTTPBackend.new(nil) }.should raise_error(ArgumentError)
|
24
|
+
lambda { Riak::Client::HTTPBackend.new(@client) }.should_not raise_error
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should make the client accessible" do
|
28
|
+
@backend.client.should == @client
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should generate default headers for requests based on the client settings" do
|
32
|
+
@client.client_id = "testing"
|
33
|
+
@backend.default_headers.should == {"X-Riak-ClientId" => "testing", "Accept" => "multipart/mixed, application/json;q=0.7, */*;q=0.5"}
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should generate a root URI based on the client settings" do
|
37
|
+
@backend.root_uri.should be_kind_of(URI)
|
38
|
+
@backend.root_uri.to_s.should == "http://127.0.0.1:8098"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should compute a URI from a relative resource path" do
|
42
|
+
@backend.path("baz").should be_kind_of(URI)
|
43
|
+
@backend.path("foo").to_s.should == "http://127.0.0.1:8098/foo"
|
44
|
+
@backend.path("foo", "bar").to_s.should == "http://127.0.0.1:8098/foo/bar"
|
45
|
+
@backend.path("/foo/bar").to_s.should == "http://127.0.0.1:8098/foo/bar"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should escape appropriate characters in a relative resource path" do
|
49
|
+
@backend.path("foo bar").to_s.should == "http://127.0.0.1:8098/foo%20bar"
|
50
|
+
@backend.path("foo", "bar", {"param" => "a string"}).to_s.should == "http://127.0.0.1:8098/foo/bar?param=a+string"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should compute a URI from a relative resource path with a hash of query parameters" do
|
54
|
+
@backend.path("baz", :r => 2).to_s.should == "http://127.0.0.1:8098/baz?r=2"
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should raise an error if a resource path is too short" do
|
58
|
+
lambda { @backend.verify_path!(["/raw/"]) }.should raise_error(ArgumentError)
|
59
|
+
lambda { @backend.verify_path!(["/raw/", "foo"]) }.should_not raise_error
|
60
|
+
lambda { @backend.verify_path!(["/mapred"]) }.should_not raise_error
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "verify_path_and_body!" do
|
64
|
+
it "should separate the path and body from given arguments" do
|
65
|
+
uri, data = @backend.verify_path_and_body!(["/raw/", "foo", "This is the body."])
|
66
|
+
uri.should == ["/raw/", "foo"]
|
67
|
+
data.should == "This is the body."
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should raise an error if the body is not a string or IO" do
|
71
|
+
lambda { @backend.verify_path_and_body!(["/raw/", "foo", nil]) }.should raise_error(ArgumentError)
|
72
|
+
lambda { @backend.verify_path_and_body!(["/raw/", "foo", File.open("spec/fixtures/cat.jpg")]) }.should_not raise_error(ArgumentError)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should raise an error if a body is not given" do
|
76
|
+
lambda { @backend.verify_path_and_body!(["/raw/", "foo"])}.should raise_error(ArgumentError)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should raise an error if a path is not given" do
|
80
|
+
lambda { @backend.verify_path_and_body!(["/raw/"])}.should raise_error(ArgumentError)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "detecting valid response codes" do
|
85
|
+
it "should accept strings or integers for either argument" do
|
86
|
+
@backend.should be_valid_response("300", "300")
|
87
|
+
@backend.should be_valid_response(300, "300")
|
88
|
+
@backend.should be_valid_response("300", 300)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should accept an array of strings or integers for the expected code" do
|
92
|
+
@backend.should be_valid_response([200,304], "200")
|
93
|
+
@backend.should be_valid_response(["200",304], "200")
|
94
|
+
@backend.should be_valid_response([200,"304"], "200")
|
95
|
+
@backend.should be_valid_response(["200","304"], "200")
|
96
|
+
@backend.should be_valid_response([200,304], 200)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should be false when none of the response codes match" do
|
100
|
+
@backend.should_not be_valid_response(200, 404)
|
101
|
+
@backend.should_not be_valid_response(["200","304"], 404)
|
102
|
+
@backend.should_not be_valid_response([200,304], 404)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "detecting whether a body should be returned" do
|
107
|
+
it "should be false when the method is :head" do
|
108
|
+
@backend.should_not be_return_body(:head, 200, false)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should be false when the response code is 204, 205, or 304" do
|
112
|
+
@backend.should_not be_return_body(:get, 204, false)
|
113
|
+
@backend.should_not be_return_body(:get, 205, false)
|
114
|
+
@backend.should_not be_return_body(:get, 304, false)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should be false when a streaming block was passed" do
|
118
|
+
@backend.should_not be_return_body(:get, 200, true)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should be true when the method is not head, a code other than 204, 205, or 304 was given, and there was no streaming block" do
|
122
|
+
[:get, :put, :post, :delete].each do |method|
|
123
|
+
[100,101,200,201,202,203,206,300,301,302,303,305,307,400,401,
|
124
|
+
402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,
|
125
|
+
500,501,502,503,504,505].each do |code|
|
126
|
+
@backend.should be_return_body(method, code, false)
|
127
|
+
@backend.should be_return_body(method, code.to_s, false)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should force subclasses to implement the perform method" do
|
134
|
+
lambda { @backend.send(:perform, :get, "/foo", {}, 200) }.should raise_error(NotImplementedError)
|
135
|
+
end
|
136
|
+
end
|