riak-client 0.9.8 → 1.0.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +32 -0
- data/Gemfile +17 -11
- data/Guardfile +14 -0
- data/Rakefile +18 -44
- data/erl_src/riak_kv_test_backend.beam +0 -0
- data/erl_src/riak_kv_test_backend.erl +461 -128
- data/erl_src/riak_search_test_backend.beam +0 -0
- data/erl_src/riak_search_test_backend.erl +175 -0
- data/lib/active_support/cache/riak_store.rb +0 -13
- data/lib/riak.rb +11 -16
- data/lib/riak/bucket.rb +59 -41
- data/lib/riak/cache_store.rb +1 -14
- data/lib/riak/client.rb +145 -73
- data/lib/riak/client/beefcake/messages.rb +36 -31
- data/lib/riak/client/beefcake/object_methods.rb +27 -19
- data/lib/riak/client/beefcake_protobuffs_backend.rb +27 -33
- data/lib/riak/client/excon_backend.rb +0 -13
- data/lib/riak/client/http_backend.rb +95 -60
- data/lib/riak/client/http_backend/configuration.rb +144 -19
- data/lib/riak/client/http_backend/key_streamer.rb +1 -14
- data/lib/riak/client/http_backend/object_methods.rb +16 -16
- data/lib/riak/client/http_backend/request_headers.rb +0 -13
- data/lib/riak/client/http_backend/transport_methods.rb +26 -56
- data/lib/riak/client/net_http_backend.rb +11 -13
- data/lib/riak/client/protobuffs_backend.rb +21 -19
- data/lib/riak/client/pump.rb +1 -15
- data/lib/riak/client/search.rb +85 -0
- data/lib/riak/cluster.rb +151 -0
- data/lib/riak/core_ext.rb +1 -0
- data/lib/riak/core_ext/deep_dup.rb +13 -0
- data/lib/riak/core_ext/json.rb +15 -0
- data/lib/riak/core_ext/stringify_keys.rb +1 -1
- data/lib/riak/core_ext/symbolize_keys.rb +1 -1
- data/lib/riak/encoding.rb +6 -0
- data/lib/riak/failed_request.rb +2 -15
- data/lib/riak/i18n.rb +0 -13
- data/lib/riak/json.rb +19 -8
- data/lib/riak/link.rb +18 -20
- data/lib/riak/locale/en.yml +13 -16
- data/lib/riak/map_reduce.rb +40 -20
- data/lib/riak/map_reduce/filter_builder.rb +14 -18
- data/lib/riak/map_reduce/phase.rb +0 -13
- data/lib/riak/map_reduce_error.rb +0 -13
- data/lib/riak/node.rb +38 -0
- data/lib/riak/node/configuration.rb +286 -0
- data/lib/riak/node/console.rb +139 -0
- data/lib/riak/node/control.rb +207 -0
- data/lib/riak/node/defaults.rb +70 -0
- data/lib/riak/node/generation.rb +99 -0
- data/lib/riak/node/log.rb +34 -0
- data/lib/riak/node/version.rb +37 -0
- data/lib/riak/robject.rb +45 -41
- data/lib/riak/search.rb +2 -161
- data/lib/riak/serializers.rb +74 -0
- data/lib/riak/stamp.rb +77 -0
- data/lib/riak/test_server.rb +56 -220
- data/lib/riak/util/escape.rb +58 -17
- data/lib/riak/util/headers.rb +2 -15
- data/lib/riak/util/multipart.rb +0 -13
- data/lib/riak/util/multipart/stream_parser.rb +0 -13
- data/lib/riak/util/tcp_socket_extensions.rb +1 -14
- data/lib/riak/util/translation.rb +0 -13
- data/lib/riak/version.rb +3 -0
- data/lib/riak/walk_spec.rb +0 -13
- data/riak-client.gemspec +27 -47
- data/spec/fixtures/multipart-with-marked-tombstones.txt +17 -0
- data/spec/fixtures/multipart-with-unmarked-tombstone.txt +16 -0
- data/spec/integration/riak/cache_store_spec.rb +2 -40
- data/spec/integration/riak/cluster_spec.rb +88 -0
- data/spec/integration/riak/http_backends_spec.rb +6 -30
- data/spec/integration/riak/node_spec.rb +184 -0
- data/spec/integration/riak/protobuffs_backends_spec.rb +2 -26
- data/spec/integration/riak/test_server_spec.rb +31 -167
- data/spec/riak/beefcake_protobuffs_backend_spec.rb +5 -4
- data/spec/riak/bucket_spec.rb +26 -36
- data/spec/riak/client_spec.rb +44 -38
- data/spec/riak/escape_spec.rb +56 -30
- data/spec/riak/excon_backend_spec.rb +4 -17
- data/spec/riak/headers_spec.rb +1 -14
- data/spec/riak/http_backend/configuration_spec.rb +211 -34
- data/spec/riak/http_backend/object_methods_spec.rb +52 -18
- data/spec/riak/http_backend/transport_methods_spec.rb +5 -38
- data/spec/riak/http_backend_spec.rb +84 -78
- data/spec/riak/link_spec.rb +19 -18
- data/spec/riak/map_reduce/filter_builder_spec.rb +1 -14
- data/spec/riak/map_reduce/phase_spec.rb +1 -14
- data/spec/riak/map_reduce_spec.rb +141 -43
- data/spec/riak/multipart_spec.rb +1 -14
- data/spec/riak/net_http_backend_spec.rb +2 -15
- data/spec/riak/robject_spec.rb +129 -97
- data/spec/riak/search_spec.rb +45 -62
- data/spec/riak/serializers_spec.rb +93 -0
- data/spec/riak/stamp_spec.rb +54 -0
- data/spec/riak/stream_parser_spec.rb +3 -16
- data/spec/riak/walk_spec_spec.rb +1 -14
- data/spec/spec_helper.rb +22 -27
- data/spec/support/http_backend_implementation_examples.rb +49 -79
- data/spec/support/integration_setup.rb +10 -0
- data/spec/support/mock_server.rb +0 -14
- data/spec/support/mocks.rb +0 -13
- data/spec/support/test_server.rb +30 -0
- data/spec/support/test_server.yml.example +14 -2
- data/spec/support/unified_backend_examples.rb +36 -27
- metadata +100 -31
- data/lib/riak/client/curb_backend.rb +0 -89
- data/spec/riak/curb_backend_spec.rb +0 -76
data/spec/riak/search_spec.rb
CHANGED
@@ -1,23 +1,6 @@
|
|
1
|
-
|
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__)
|
15
|
-
|
16
|
-
describe "Search mixins" do
|
17
|
-
before :all do
|
18
|
-
require 'riak/search'
|
19
|
-
end
|
1
|
+
require 'spec_helper'
|
20
2
|
|
3
|
+
describe "Search features" do
|
21
4
|
describe Riak::Client do
|
22
5
|
before :each do
|
23
6
|
@client = Riak::Client.new
|
@@ -26,72 +9,73 @@ describe "Search mixins" do
|
|
26
9
|
end
|
27
10
|
|
28
11
|
describe "searching" do
|
29
|
-
it "should
|
30
|
-
@http.should_receive(:
|
12
|
+
it "should search the default index" do
|
13
|
+
@http.should_receive(:search).with(nil, "foo", {}).and_return({})
|
31
14
|
@client.search("foo")
|
32
15
|
end
|
33
16
|
|
34
|
-
it "should
|
35
|
-
@http.should_receive(:
|
17
|
+
it "should search the default index with additional options" do
|
18
|
+
@http.should_receive(:search).with(nil, 'foo', 'rows' => 30).and_return({})
|
36
19
|
@client.search("foo", 'rows' => 30)
|
37
20
|
end
|
38
21
|
|
39
|
-
it "should
|
40
|
-
@http.should_receive(:
|
22
|
+
it "should search the specified index" do
|
23
|
+
@http.should_receive(:search).with('search', 'foo', {}).and_return({})
|
41
24
|
@client.search("search", "foo")
|
42
25
|
end
|
43
|
-
|
44
|
-
it "should vivify JSON responses" do
|
45
|
-
@http.should_receive(:get).and_return({:code => 200, :headers => {"content-type"=>["application/json"]}, :body => '{"response":{"docs":["foo"]}}'})
|
46
|
-
@client.search("foo").should == {"response" => {"docs" => ["foo"]}}
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should return non-JSON responses raw" do
|
50
|
-
@http.should_receive(:get).and_return({:code => 200, :headers => {"content-type"=>["text/plain"]}, :body => '{"response":{"docs":["foo"]}}'})
|
51
|
-
@client.search("foo").should == '{"response":{"docs":["foo"]}}'
|
52
|
-
end
|
53
26
|
end
|
54
|
-
describe "indexing documents" do
|
55
|
-
it "should exclude the index from the URL when not specified" do
|
56
|
-
@http.should_receive(:post).with(200, "/solr", "update", anything, anything).and_return({:code => 200, :headers => {'content-type' => ['text/html']}, :body => ""})
|
57
|
-
@client.index({:id => 1, :field => "value"})
|
58
|
-
end
|
59
27
|
|
60
|
-
|
61
|
-
|
62
|
-
|
28
|
+
describe "indexing documents" do
|
29
|
+
it "should update the default index" do
|
30
|
+
doc = {'field' => "value", 'id' => 1}
|
31
|
+
if doc.to_a.first.first == 'field'
|
32
|
+
expect_update_body('<add><doc><field name="field">value</field><field name="id">1</field></doc></add>')
|
33
|
+
else # 1.8.7, I hate you.
|
34
|
+
expect_update_body('<add><doc><field name="id">1</field><field name="field">value</field></doc></add>')
|
35
|
+
end
|
36
|
+
@client.index(doc)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should update the specified index" do
|
40
|
+
doc = {'field' => "value", 'id' => 1}
|
41
|
+
if doc.to_a.first.first == 'field'
|
42
|
+
expect_update_body('<add><doc><field name="field">value</field><field name="id">1</field></doc></add>', 'foo')
|
43
|
+
else # 1.8.7, I hate you.
|
44
|
+
expect_update_body('<add><doc><field name="id">1</field><field name="field">value</field></doc></add>', 'foo')
|
45
|
+
end
|
46
|
+
@client.index("foo", doc)
|
63
47
|
end
|
64
48
|
|
65
49
|
it "should raise an error when documents do not contain an id" do
|
66
|
-
@http.stub!(:
|
50
|
+
@http.stub!(:update_search_index).and_return(true)
|
67
51
|
lambda { @client.index({:field => "value"}) }.should raise_error(ArgumentError)
|
68
52
|
lambda { @client.index({:id => 1, :field => "value"}) }.should_not raise_error(ArgumentError)
|
69
53
|
end
|
70
54
|
|
71
|
-
it "should build a Solr <add> request" do
|
72
|
-
expect_update_body('<add><doc><field name="id">1</field><field name="field">value</field></doc></add>')
|
73
|
-
@client.index({'id' => 1, 'field' => "value"})
|
74
|
-
end
|
75
|
-
|
76
55
|
it "should include multiple documents in the <add> request" do
|
77
|
-
|
78
|
-
|
56
|
+
docs = {'field' => "value", 'id' => 1}, {'foo' => "bar", 'id' => 2}
|
57
|
+
if docs.first.to_a.first.first == 'field'
|
58
|
+
expect_update_body('<add><doc><field name="field">value</field><field name="id">1</field></doc><doc><field name="foo">bar</field><field name="id">2</field></doc></add>')
|
59
|
+
else # 1.8.7, I hate you
|
60
|
+
expect_update_body('<add><doc><field name="id">1</field><field name="field">value</field></doc><doc><field name="id">2</field><field name="foo">bar</field></doc></add>')
|
61
|
+
end
|
62
|
+
@client.index(*docs)
|
79
63
|
end
|
80
64
|
end
|
81
65
|
|
82
66
|
describe "removing documents" do
|
83
|
-
it "should
|
84
|
-
|
67
|
+
it "should remove documents from the default index" do
|
68
|
+
expect_update_body('<delete><id>1</id></delete>')
|
85
69
|
@client.remove({:id => 1})
|
86
70
|
end
|
87
71
|
|
88
|
-
it "should
|
89
|
-
|
72
|
+
it "should remove documents from the specified index" do
|
73
|
+
expect_update_body('<delete><id>1</id></delete>', 'foo')
|
90
74
|
@client.remove("foo", {:id => 1})
|
91
75
|
end
|
92
76
|
|
93
77
|
it "should raise an error when document specifications don't include an id or query" do
|
94
|
-
@http.stub!(:
|
78
|
+
@http.stub!(:update_search_index).and_return({:code => 200})
|
95
79
|
lambda { @client.remove({:foo => "bar"}) }.should raise_error(ArgumentError)
|
96
80
|
lambda { @client.remove({:id => 1}) }.should_not raise_error
|
97
81
|
end
|
@@ -110,8 +94,7 @@ describe "Search mixins" do
|
|
110
94
|
end
|
111
95
|
|
112
96
|
def expect_update_body(body, index=nil)
|
113
|
-
|
114
|
-
@http.should_receive(:post).with(*args).and_return({:code => 200, :headers => {'content-type' => ['text/html']}, :body => ""})
|
97
|
+
@http.should_receive(:update_search_index).with(index, body)
|
115
98
|
end
|
116
99
|
end
|
117
100
|
|
@@ -122,11 +105,11 @@ describe "Search mixins" do
|
|
122
105
|
end
|
123
106
|
|
124
107
|
def load_without_index_hook
|
125
|
-
@bucket.instance_variable_set(:@props, {"precommit" => []})
|
108
|
+
@bucket.instance_variable_set(:@props, {"precommit" => [], "search" => false})
|
126
109
|
end
|
127
110
|
|
128
111
|
def load_with_index_hook
|
129
|
-
@bucket.instance_variable_set(:@props, {"precommit" => [{"mod" => "riak_search_kv_hook", "fun" => "precommit"}]})
|
112
|
+
@bucket.instance_variable_set(:@props, {"precommit" => [{"mod" => "riak_search_kv_hook", "fun" => "precommit"}], "search" => true})
|
130
113
|
end
|
131
114
|
|
132
115
|
it "should detect whether the indexing hook is installed" do
|
@@ -140,7 +123,7 @@ describe "Search mixins" do
|
|
140
123
|
describe "enabling indexing" do
|
141
124
|
it "should add the index hook when not present" do
|
142
125
|
load_without_index_hook
|
143
|
-
@bucket.should_receive(:props=).with({"precommit" => [Riak::Bucket::SEARCH_PRECOMMIT_HOOK]})
|
126
|
+
@bucket.should_receive(:props=).with({"precommit" => [Riak::Bucket::SEARCH_PRECOMMIT_HOOK], "search" => true})
|
144
127
|
@bucket.enable_index!
|
145
128
|
end
|
146
129
|
|
@@ -154,7 +137,7 @@ describe "Search mixins" do
|
|
154
137
|
describe "disabling indexing" do
|
155
138
|
it "should remove the index hook when present" do
|
156
139
|
load_with_index_hook
|
157
|
-
@bucket.should_receive(:props=).with({"precommit" => []})
|
140
|
+
@bucket.should_receive(:props=).with({"precommit" => [], "search" => false})
|
158
141
|
@bucket.disable_index!
|
159
142
|
end
|
160
143
|
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Riak::Serializers do
|
4
|
+
shared_examples_for "a serializer" do |type, deserialized, serialized|
|
5
|
+
context "for #{type}" do
|
6
|
+
it "serializes #{deserialized} to #{serialized}" do
|
7
|
+
described_class.serialize(type, deserialized).should == serialized
|
8
|
+
end
|
9
|
+
|
10
|
+
it "deserializes #{serialized} to #{deserialized}" do
|
11
|
+
described_class.deserialize(type, serialized).should == deserialized
|
12
|
+
end
|
13
|
+
|
14
|
+
it "round trips properly" do
|
15
|
+
str = described_class.serialize(type, deserialized)
|
16
|
+
described_class.deserialize(type, str).should == deserialized
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it_behaves_like "a serializer", "text/plain", "a string", "a string"
|
22
|
+
it_behaves_like "a serializer", "application/json", { "a" => 7 }, %q|{"a":7}|
|
23
|
+
it_behaves_like "a serializer", "application/x-ruby-marshal", { :a => 3 }, Marshal.dump({ :a => 3 })
|
24
|
+
|
25
|
+
described_class::YAML_MIME_TYPES.each do |mime_type|
|
26
|
+
it_behaves_like "a serializer", mime_type, { "a" => 7 }, YAML.dump({ "a" => 7 })
|
27
|
+
end
|
28
|
+
|
29
|
+
%w[ serialize deserialize ].each do |meth|
|
30
|
+
describe ".#{meth}" do
|
31
|
+
it 'raises a NotImplementedError when given an unrecognized content type' do
|
32
|
+
expect {
|
33
|
+
described_class.send(meth, "application/unrecognized", "string")
|
34
|
+
}.to raise_error(NotImplementedError)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "plain text serializer" do
|
40
|
+
it 'calls #to_s to convert the object to a string' do
|
41
|
+
described_class.serialize("text/plain", :a_string).should == "a_string"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "JSON serializer" do
|
46
|
+
it "respects the max nesting option" do
|
47
|
+
# Sadly, this spec will not fail for me when using yajl-ruby
|
48
|
+
# on Ruby 1.9, even when passing the options to #to_json is
|
49
|
+
# not implemented.
|
50
|
+
Riak.json_options = {:max_nesting => 51}
|
51
|
+
h = {}
|
52
|
+
p = h
|
53
|
+
(1..50).each do |i|
|
54
|
+
p['a'] = {}
|
55
|
+
p = p['a']
|
56
|
+
end
|
57
|
+
s = h.to_json(Riak.json_options)
|
58
|
+
expect {
|
59
|
+
described_class.serialize('application/json', h)
|
60
|
+
}.should_not raise_error
|
61
|
+
|
62
|
+
expect {
|
63
|
+
described_class.deserialize('application/json', s)
|
64
|
+
}.should_not raise_error
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "a custom serializer" do
|
69
|
+
let(:custom_serializer) do
|
70
|
+
Object.new.tap do |o|
|
71
|
+
def o.dump(string)
|
72
|
+
"The string is: #{string}"
|
73
|
+
end
|
74
|
+
|
75
|
+
def o.load(string)
|
76
|
+
string.sub!(/^The string is: /, '')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'can be registered' do
|
82
|
+
described_class['application/custom-type-1'] = custom_serializer
|
83
|
+
described_class['application/custom-type-1'].should be(custom_serializer)
|
84
|
+
end
|
85
|
+
|
86
|
+
it_behaves_like "a serializer", "application/custom-type-a", "foo", "The string is: foo" do
|
87
|
+
before(:each) do
|
88
|
+
described_class['application/custom-type-a'] = custom_serializer
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'riak/stamp'
|
3
|
+
|
4
|
+
describe Riak::Stamp do
|
5
|
+
subject { described_class.new(Riak::Client.new) }
|
6
|
+
it "should generate always increasing integer identifiers" do
|
7
|
+
1000.times do
|
8
|
+
one = subject.next
|
9
|
+
two = subject.next
|
10
|
+
[one, two].should be_all {|i| Integer === i }
|
11
|
+
two.should > one
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should delay until the next millisecond when the sequence overflows" do
|
16
|
+
old = subject.instance_variable_get(:@timestamp) + 0
|
17
|
+
subject.instance_variable_set(:@sequence, described_class::SEQUENCE_MASK)
|
18
|
+
count = 0
|
19
|
+
# Simulate the time_gen method returning the same thing multiple times
|
20
|
+
subject.stub(:time_gen) do
|
21
|
+
count += 1
|
22
|
+
if count < 10
|
23
|
+
old
|
24
|
+
else
|
25
|
+
old + 1
|
26
|
+
end
|
27
|
+
end
|
28
|
+
((subject.next >> described_class::TIMESTAMP_SHIFT) & described_class::TIMESTAMP_MASK).should == old + 1
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should raise an exception when the system clock moves backwards" do
|
32
|
+
old = subject.instance_variable_get(:@timestamp)
|
33
|
+
subject.should_receive(:time_gen).and_return(old - 10)
|
34
|
+
expect {
|
35
|
+
subject.next
|
36
|
+
}.to raise_error(Riak::BackwardsClockError)
|
37
|
+
end
|
38
|
+
|
39
|
+
# The client/worker ID should be used for disambiguation, not for
|
40
|
+
# primary ordering. This breaks from the Snowflake model where the
|
41
|
+
# worker ID is in more significant bits.
|
42
|
+
it "should use the client ID as the bottom component of the identifier" do
|
43
|
+
(subject.next & described_class::CLIENT_ID_MASK).should == subject.client.client_id & described_class::CLIENT_ID_MASK
|
44
|
+
end
|
45
|
+
|
46
|
+
context "using a non-integer client ID" do
|
47
|
+
subject { described_class.new(Riak::Client.new(:client_id => "ripple")) }
|
48
|
+
let(:hash) { "ripple".hash }
|
49
|
+
|
50
|
+
it "should use the hash of the client ID as the bottom component of the identifier" do
|
51
|
+
(subject.next & described_class::CLIENT_ID_MASK).should == subject.client.client_id.hash & described_class::CLIENT_ID_MASK
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -1,17 +1,4 @@
|
|
1
|
-
|
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__))
|
1
|
+
require 'spec_helper'
|
15
2
|
|
16
3
|
describe Riak::Util::Multipart::StreamParser do
|
17
4
|
let(:klass) { Riak::Util::Multipart::StreamParser }
|
@@ -45,7 +32,7 @@ describe Riak::Util::Multipart::StreamParser do
|
|
45
32
|
parser = klass.new do |result|
|
46
33
|
block.ping
|
47
34
|
result[:headers]['content-type'].should include("application/json")
|
48
|
-
lambda { JSON.parse(result[:body]) }.should_not raise_error
|
35
|
+
lambda { Riak::JSON.parse(result[:body]) }.should_not raise_error
|
49
36
|
end
|
50
37
|
File.open("spec/fixtures/multipart-mapreduce.txt", "r") do |f|
|
51
38
|
while chunk = f.read(16)
|
@@ -59,7 +46,7 @@ describe Riak::Util::Multipart::StreamParser do
|
|
59
46
|
parser = klass.new do |result|
|
60
47
|
block.ping
|
61
48
|
result[:headers]['content-type'].should include("application/json")
|
62
|
-
lambda { JSON.parse(result[:body]) }.should_not raise_error
|
49
|
+
lambda { Riak::JSON.parse(result[:body]) }.should_not raise_error
|
63
50
|
end
|
64
51
|
parser.accept File.read("spec/fixtures/multipart-mapreduce.txt")
|
65
52
|
end
|
data/spec/riak/walk_spec_spec.rb
CHANGED
@@ -1,17 +1,4 @@
|
|
1
|
-
|
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__))
|
1
|
+
require 'spec_helper'
|
15
2
|
|
16
3
|
describe Riak::WalkSpec do
|
17
4
|
describe "initializing" do
|
data/spec/spec_helper.rb
CHANGED
@@ -1,16 +1,3 @@
|
|
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
1
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
2
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
16
3
|
|
@@ -19,25 +6,33 @@ require 'riak'
|
|
19
6
|
require 'rspec'
|
20
7
|
require 'fakeweb'
|
21
8
|
|
22
|
-
|
23
|
-
|
24
|
-
require 'riak/test_server'
|
25
|
-
config = YAML.load_file("spec/support/test_server.yml")
|
26
|
-
$test_server = Riak::TestServer.new(config.symbolize_keys)
|
27
|
-
$test_server.prepare!
|
28
|
-
$test_server.start
|
29
|
-
at_exit { $test_server.cleanup }
|
30
|
-
rescue => e
|
31
|
-
warn "Can't run Riak::TestServer specs. Specify the location of your Riak installation in spec/support/test_server.yml. See Riak::TestServer docs for more info."
|
32
|
-
warn e.inspect
|
33
|
-
end
|
9
|
+
# Only the tests should really get away with this.
|
10
|
+
Riak.disable_list_keys_warnings = true
|
34
11
|
|
35
|
-
|
12
|
+
%w[integration_setup
|
13
|
+
http_backend_implementation_examples
|
14
|
+
unified_backend_examples
|
15
|
+
mocks
|
16
|
+
mock_server
|
17
|
+
drb_mock_server
|
18
|
+
test_server].each do |file|
|
19
|
+
require File.join("support", file)
|
20
|
+
end
|
36
21
|
|
37
22
|
RSpec.configure do |config|
|
23
|
+
config.debug = true
|
38
24
|
config.mock_with :rspec
|
39
|
-
|
25
|
+
|
26
|
+
config.before(:all, :integration => true) do
|
27
|
+
FakeWeb.allow_net_connect = true
|
28
|
+
end
|
29
|
+
|
30
|
+
config.after(:all, :integration => true) do
|
31
|
+
FakeWeb.allow_net_connect = false
|
32
|
+
end
|
33
|
+
|
40
34
|
config.before(:each) do
|
35
|
+
Riak::RObject.on_conflict_hooks.clear
|
41
36
|
FakeWeb.clean_registry
|
42
37
|
end
|
43
38
|
|
@@ -1,65 +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
1
|
shared_examples_for "HTTP backend" do
|
2
|
+
let(:resource){ @backend.path("/riak/","foo") }
|
3
|
+
|
15
4
|
describe "HEAD requests" do
|
16
5
|
before :each do
|
17
|
-
setup_http_mock(:head,
|
6
|
+
setup_http_mock(:head, resource.to_s, :body => "")
|
18
7
|
end
|
19
8
|
|
20
9
|
it "should return only the headers when the request succeeds" do
|
21
|
-
response = @backend.head(200,
|
10
|
+
response = @backend.head(200, resource)
|
22
11
|
response.should_not have_key(:body)
|
23
12
|
response[:headers].should be_kind_of(Hash)
|
24
13
|
response[:code].should == 200
|
25
14
|
end
|
26
15
|
|
27
16
|
it "should raise a FailedRequest exception when the request fails" do
|
28
|
-
lambda { @backend.head(301,
|
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)
|
17
|
+
lambda { @backend.head(301, resource) }.should raise_error(Riak::FailedRequest)
|
33
18
|
end
|
34
19
|
|
35
20
|
it "should not raise a FailedRequest if one of the expected response codes matches" do
|
36
|
-
lambda { @backend.head([200, 301],
|
21
|
+
lambda { @backend.head([200, 301], resource) }.should_not raise_error(Riak::FailedRequest)
|
37
22
|
end
|
38
23
|
end
|
39
24
|
|
40
25
|
describe "GET requests" do
|
41
26
|
before :each do
|
42
|
-
setup_http_mock(:get,
|
27
|
+
setup_http_mock(:get, resource.to_s, :body => "Success!")
|
43
28
|
end
|
44
29
|
|
45
30
|
it "should return the response body and headers when the request succeeds" do
|
46
|
-
response = @backend.get(200,
|
31
|
+
response = @backend.get(200, resource)
|
47
32
|
response[:body].should == "Success!"
|
48
33
|
response[:headers].should be_kind_of(Hash)
|
49
34
|
response[:code].should == 200
|
50
35
|
end
|
51
36
|
|
52
37
|
it "should raise a FailedRequest exception when the request fails" do
|
53
|
-
lambda { @backend.get(304,
|
38
|
+
lambda { @backend.get(304, resource) }.should raise_error(Riak::FailedRequest)
|
54
39
|
end
|
55
40
|
|
56
41
|
it "should not raise a FailedRequest if one of the expected response codes matches" do
|
57
|
-
lambda { @backend.get([200, 301],
|
42
|
+
lambda { @backend.get([200, 301], resource) }.should_not raise_error(Riak::FailedRequest)
|
58
43
|
end
|
59
|
-
|
44
|
+
|
60
45
|
it "should yield successive chunks of the response to the given block but not return the entire body" do
|
61
46
|
chunks = ""
|
62
|
-
response = @backend.get(200,
|
47
|
+
response = @backend.get(200, resource) do |chunk|
|
63
48
|
chunks << chunk
|
64
49
|
end
|
65
50
|
chunks.should == "Success!"
|
@@ -67,34 +52,30 @@ shared_examples_for "HTTP backend" do
|
|
67
52
|
response[:headers].should be_kind_of(Hash)
|
68
53
|
response[:code].should == 200
|
69
54
|
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
55
|
end
|
75
56
|
|
76
57
|
describe "DELETE requests" do
|
77
58
|
before :each do
|
78
|
-
setup_http_mock(:delete,
|
59
|
+
setup_http_mock(:delete, resource.to_s, :body => "Success!")
|
79
60
|
end
|
80
61
|
|
81
62
|
it "should return the response body and headers when the request succeeds" do
|
82
|
-
response = @backend.delete(200,
|
63
|
+
response = @backend.delete(200, resource)
|
83
64
|
response[:body].should == "Success!"
|
84
65
|
response[:headers].should be_kind_of(Hash)
|
85
66
|
end
|
86
67
|
|
87
68
|
it "should raise a FailedRequest exception when the request fails" do
|
88
|
-
lambda { @backend.delete(304,
|
69
|
+
lambda { @backend.delete(304, resource) }.should raise_error(Riak::FailedRequest)
|
89
70
|
end
|
90
|
-
|
71
|
+
|
91
72
|
it "should not raise a FailedRequest if one of the expected response codes matches" do
|
92
|
-
lambda { @backend.delete([200, 301],
|
73
|
+
lambda { @backend.delete([200, 301], resource) }.should_not raise_error(Riak::FailedRequest)
|
93
74
|
end
|
94
|
-
|
75
|
+
|
95
76
|
it "should yield successive chunks of the response to the given block but not return the entire body" do
|
96
77
|
chunks = ""
|
97
|
-
response = @backend.delete(200,
|
78
|
+
response = @backend.delete(200, resource) do |chunk|
|
98
79
|
chunks << chunk
|
99
80
|
end
|
100
81
|
chunks.should == "Success!"
|
@@ -102,36 +83,32 @@ shared_examples_for "HTTP backend" do
|
|
102
83
|
response[:headers].should be_kind_of(Hash)
|
103
84
|
response[:code].should == 200
|
104
85
|
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
86
|
end
|
110
87
|
|
111
88
|
describe "PUT requests" do
|
112
89
|
before :each do
|
113
|
-
setup_http_mock(:put,
|
90
|
+
setup_http_mock(:put, resource.to_s, :body => "Success!")
|
114
91
|
end
|
115
92
|
|
116
93
|
it "should return the response body, headers, and code when the request succeeds" do
|
117
|
-
response = @backend.put(200,
|
94
|
+
response = @backend.put(200, resource, "This is the body.")
|
118
95
|
response[:body].should == "Success!"
|
119
96
|
response[:headers].should be_kind_of(Hash)
|
120
97
|
response[:code].should == 200
|
121
98
|
end
|
122
99
|
|
123
100
|
it "should raise a FailedRequest exception when the request fails" do
|
124
|
-
lambda { @backend.put(204,
|
101
|
+
lambda { @backend.put(204, resource, "This is the body.") }.should raise_error(Riak::FailedRequest)
|
125
102
|
end
|
126
|
-
|
103
|
+
|
127
104
|
it "should not raise a FailedRequest if one of the expected response codes matches" do
|
128
|
-
lambda { @backend.put([200, 204],
|
105
|
+
lambda { @backend.put([200, 204], resource, "This is the body.") }.should_not raise_error(Riak::FailedRequest)
|
129
106
|
end
|
130
|
-
|
131
|
-
|
107
|
+
|
108
|
+
|
132
109
|
it "should yield successive chunks of the response to the given block but not return the entire body" do
|
133
110
|
chunks = ""
|
134
|
-
response = @backend.put(200,
|
111
|
+
response = @backend.put(200, resource, "This is the body.") do |chunk|
|
135
112
|
chunks << chunk
|
136
113
|
end
|
137
114
|
chunks.should == "Success!"
|
@@ -140,42 +117,39 @@ shared_examples_for "HTTP backend" do
|
|
140
117
|
response[:code].should == 200
|
141
118
|
end
|
142
119
|
|
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
120
|
|
147
121
|
it "should raise an error if no body data is given" do
|
148
|
-
lambda { @backend.put(200,
|
122
|
+
lambda { @backend.put(200, resource) }.should raise_error(ArgumentError)
|
149
123
|
end
|
150
124
|
|
151
|
-
it "should raise an error if the body is not a string" do
|
152
|
-
lambda { @backend.put(200,
|
125
|
+
it "should raise an error if the body is not a string or IO" do
|
126
|
+
lambda { @backend.put(200, resource, 123) }.should raise_error(ArgumentError)
|
153
127
|
end
|
154
128
|
end
|
155
129
|
|
156
130
|
describe "POST requests" do
|
157
131
|
before :each do
|
158
|
-
setup_http_mock(:post,
|
132
|
+
setup_http_mock(:post, resource.to_s, :body => "Success!")
|
159
133
|
end
|
160
134
|
|
161
135
|
it "should return the response body, headers, and code when the request succeeds" do
|
162
|
-
response = @backend.post(200,
|
136
|
+
response = @backend.post(200, resource, "This is the body.")
|
163
137
|
response[:body].should == "Success!"
|
164
138
|
response[:headers].should be_kind_of(Hash)
|
165
139
|
response[:code].should == 200
|
166
140
|
end
|
167
141
|
|
168
142
|
it "should raise a FailedRequest exception when the request fails" do
|
169
|
-
lambda { @backend.post(204,
|
143
|
+
lambda { @backend.post(204, resource, "This is the body.") }.should raise_error(Riak::FailedRequest)
|
170
144
|
end
|
171
145
|
|
172
146
|
it "should not raise a FailedRequest if one of the expected response codes matches" do
|
173
|
-
lambda { @backend.post([200, 204],
|
147
|
+
lambda { @backend.post([200, 204], resource, "This is the body.") }.should_not raise_error(Riak::FailedRequest)
|
174
148
|
end
|
175
149
|
|
176
150
|
it "should yield successive chunks of the response to the given block but not return the entire body" do
|
177
151
|
chunks = ""
|
178
|
-
response = @backend.post(200,
|
152
|
+
response = @backend.post(200, resource, "This is the body.") do |chunk|
|
179
153
|
chunks << chunk
|
180
154
|
end
|
181
155
|
chunks.should == "Success!"
|
@@ -184,16 +158,12 @@ shared_examples_for "HTTP backend" do
|
|
184
158
|
response[:code].should == 200
|
185
159
|
end
|
186
160
|
|
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
161
|
it "should raise an error if no body data is given" do
|
192
|
-
lambda { @backend.post(200,
|
162
|
+
lambda { @backend.post(200, resource) }.should raise_error(ArgumentError)
|
193
163
|
end
|
194
164
|
|
195
|
-
it "should raise an error if the body is not a string" do
|
196
|
-
lambda { @backend.post(200,
|
165
|
+
it "should raise an error if the body is not a string or IO" do
|
166
|
+
lambda { @backend.post(200, resource, 123) }.should raise_error(ArgumentError)
|
197
167
|
end
|
198
168
|
end
|
199
169
|
|
@@ -201,11 +171,11 @@ shared_examples_for "HTTP backend" do
|
|
201
171
|
[204, 205, 304].each do |code|
|
202
172
|
[:get, :post, :put, :delete].each do |method|
|
203
173
|
it "should not return a body on #{method.to_s.upcase} for #{code}" do
|
204
|
-
setup_http_mock(method,
|
174
|
+
setup_http_mock(method, resource.to_s, :status => code)
|
205
175
|
response = if method == :post || method == :put
|
206
|
-
@backend.send(method, code,
|
176
|
+
@backend.send(method, code, resource, "This is the body")
|
207
177
|
else
|
208
|
-
@backend.send(method, code,
|
178
|
+
@backend.send(method, code, resource)
|
209
179
|
end
|
210
180
|
response.should_not have_key(:body)
|
211
181
|
end
|
@@ -218,7 +188,7 @@ shared_examples_for "HTTP backend" do
|
|
218
188
|
@client.http_port = $mock_server.port + 1 unless @client.http_backend == :NetHTTP
|
219
189
|
@client.ssl = true
|
220
190
|
setup_http_mock(:get, @backend.path("/riak/","ssl").to_s, :body => "Success!")
|
221
|
-
response = @backend.get(200,
|
191
|
+
response = @backend.get(200, @backend.path("/riak/","ssl"))
|
222
192
|
response[:code].should == 200
|
223
193
|
end
|
224
194
|
end
|
@@ -229,13 +199,13 @@ shared_examples_for "HTTP backend" do
|
|
229
199
|
if @client.http_backend == :NetHTTP
|
230
200
|
setup_http_mock(:get, "http://ripple:rocks@127.0.0.1:8098/riak/auth", :body => 'Success!')
|
231
201
|
else
|
232
|
-
@_mock_set = "Basic #{Base64::encode64("ripple:rocks").strip}"
|
202
|
+
@_mock_set = "Basic #{Base64::encode64("ripple:rocks").strip}"
|
233
203
|
$mock_server.attach do |env|
|
234
204
|
$mock_server.satisfied = env['HTTP_AUTHORIZATION'] == @_mock_set
|
235
205
|
[200, {}, Array('Success!')]
|
236
206
|
end
|
237
207
|
end
|
238
|
-
response = @backend.get(200, "/riak/", "auth")
|
208
|
+
response = @backend.get(200, @backend.path("/riak/", "auth"))
|
239
209
|
response[:code].should == 200
|
240
210
|
end
|
241
211
|
end
|
@@ -244,9 +214,9 @@ shared_examples_for "HTTP backend" do
|
|
244
214
|
|
245
215
|
def bad_request(method)
|
246
216
|
if method == :post || method == :put
|
247
|
-
@backend.send(method, 200,
|
217
|
+
@backend.send(method, 200, resource, "body")
|
248
218
|
else
|
249
|
-
@backend.send(method, 200,
|
219
|
+
@backend.send(method, 200, resource)
|
250
220
|
end
|
251
221
|
end
|
252
222
|
|
@@ -254,7 +224,7 @@ shared_examples_for "HTTP backend" do
|
|
254
224
|
context method.to_s do
|
255
225
|
|
256
226
|
before(:each) do
|
257
|
-
setup_http_mock(method,
|
227
|
+
setup_http_mock(method, resource.to_s, :body => "Failure!", :status => 400, 'Content-Type' => 'text/plain' )
|
258
228
|
end
|
259
229
|
|
260
230
|
it "raises an HTTPFailedRequest exeption" do
|
@@ -273,7 +243,7 @@ shared_examples_for "HTTP backend" do
|
|
273
243
|
|
274
244
|
end
|
275
245
|
end
|
276
|
-
|
246
|
+
|
277
247
|
end
|
278
|
-
|
248
|
+
|
279
249
|
end
|