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.
Files changed (106) hide show
  1. data/.gitignore +32 -0
  2. data/Gemfile +17 -11
  3. data/Guardfile +14 -0
  4. data/Rakefile +18 -44
  5. data/erl_src/riak_kv_test_backend.beam +0 -0
  6. data/erl_src/riak_kv_test_backend.erl +461 -128
  7. data/erl_src/riak_search_test_backend.beam +0 -0
  8. data/erl_src/riak_search_test_backend.erl +175 -0
  9. data/lib/active_support/cache/riak_store.rb +0 -13
  10. data/lib/riak.rb +11 -16
  11. data/lib/riak/bucket.rb +59 -41
  12. data/lib/riak/cache_store.rb +1 -14
  13. data/lib/riak/client.rb +145 -73
  14. data/lib/riak/client/beefcake/messages.rb +36 -31
  15. data/lib/riak/client/beefcake/object_methods.rb +27 -19
  16. data/lib/riak/client/beefcake_protobuffs_backend.rb +27 -33
  17. data/lib/riak/client/excon_backend.rb +0 -13
  18. data/lib/riak/client/http_backend.rb +95 -60
  19. data/lib/riak/client/http_backend/configuration.rb +144 -19
  20. data/lib/riak/client/http_backend/key_streamer.rb +1 -14
  21. data/lib/riak/client/http_backend/object_methods.rb +16 -16
  22. data/lib/riak/client/http_backend/request_headers.rb +0 -13
  23. data/lib/riak/client/http_backend/transport_methods.rb +26 -56
  24. data/lib/riak/client/net_http_backend.rb +11 -13
  25. data/lib/riak/client/protobuffs_backend.rb +21 -19
  26. data/lib/riak/client/pump.rb +1 -15
  27. data/lib/riak/client/search.rb +85 -0
  28. data/lib/riak/cluster.rb +151 -0
  29. data/lib/riak/core_ext.rb +1 -0
  30. data/lib/riak/core_ext/deep_dup.rb +13 -0
  31. data/lib/riak/core_ext/json.rb +15 -0
  32. data/lib/riak/core_ext/stringify_keys.rb +1 -1
  33. data/lib/riak/core_ext/symbolize_keys.rb +1 -1
  34. data/lib/riak/encoding.rb +6 -0
  35. data/lib/riak/failed_request.rb +2 -15
  36. data/lib/riak/i18n.rb +0 -13
  37. data/lib/riak/json.rb +19 -8
  38. data/lib/riak/link.rb +18 -20
  39. data/lib/riak/locale/en.yml +13 -16
  40. data/lib/riak/map_reduce.rb +40 -20
  41. data/lib/riak/map_reduce/filter_builder.rb +14 -18
  42. data/lib/riak/map_reduce/phase.rb +0 -13
  43. data/lib/riak/map_reduce_error.rb +0 -13
  44. data/lib/riak/node.rb +38 -0
  45. data/lib/riak/node/configuration.rb +286 -0
  46. data/lib/riak/node/console.rb +139 -0
  47. data/lib/riak/node/control.rb +207 -0
  48. data/lib/riak/node/defaults.rb +70 -0
  49. data/lib/riak/node/generation.rb +99 -0
  50. data/lib/riak/node/log.rb +34 -0
  51. data/lib/riak/node/version.rb +37 -0
  52. data/lib/riak/robject.rb +45 -41
  53. data/lib/riak/search.rb +2 -161
  54. data/lib/riak/serializers.rb +74 -0
  55. data/lib/riak/stamp.rb +77 -0
  56. data/lib/riak/test_server.rb +56 -220
  57. data/lib/riak/util/escape.rb +58 -17
  58. data/lib/riak/util/headers.rb +2 -15
  59. data/lib/riak/util/multipart.rb +0 -13
  60. data/lib/riak/util/multipart/stream_parser.rb +0 -13
  61. data/lib/riak/util/tcp_socket_extensions.rb +1 -14
  62. data/lib/riak/util/translation.rb +0 -13
  63. data/lib/riak/version.rb +3 -0
  64. data/lib/riak/walk_spec.rb +0 -13
  65. data/riak-client.gemspec +27 -47
  66. data/spec/fixtures/multipart-with-marked-tombstones.txt +17 -0
  67. data/spec/fixtures/multipart-with-unmarked-tombstone.txt +16 -0
  68. data/spec/integration/riak/cache_store_spec.rb +2 -40
  69. data/spec/integration/riak/cluster_spec.rb +88 -0
  70. data/spec/integration/riak/http_backends_spec.rb +6 -30
  71. data/spec/integration/riak/node_spec.rb +184 -0
  72. data/spec/integration/riak/protobuffs_backends_spec.rb +2 -26
  73. data/spec/integration/riak/test_server_spec.rb +31 -167
  74. data/spec/riak/beefcake_protobuffs_backend_spec.rb +5 -4
  75. data/spec/riak/bucket_spec.rb +26 -36
  76. data/spec/riak/client_spec.rb +44 -38
  77. data/spec/riak/escape_spec.rb +56 -30
  78. data/spec/riak/excon_backend_spec.rb +4 -17
  79. data/spec/riak/headers_spec.rb +1 -14
  80. data/spec/riak/http_backend/configuration_spec.rb +211 -34
  81. data/spec/riak/http_backend/object_methods_spec.rb +52 -18
  82. data/spec/riak/http_backend/transport_methods_spec.rb +5 -38
  83. data/spec/riak/http_backend_spec.rb +84 -78
  84. data/spec/riak/link_spec.rb +19 -18
  85. data/spec/riak/map_reduce/filter_builder_spec.rb +1 -14
  86. data/spec/riak/map_reduce/phase_spec.rb +1 -14
  87. data/spec/riak/map_reduce_spec.rb +141 -43
  88. data/spec/riak/multipart_spec.rb +1 -14
  89. data/spec/riak/net_http_backend_spec.rb +2 -15
  90. data/spec/riak/robject_spec.rb +129 -97
  91. data/spec/riak/search_spec.rb +45 -62
  92. data/spec/riak/serializers_spec.rb +93 -0
  93. data/spec/riak/stamp_spec.rb +54 -0
  94. data/spec/riak/stream_parser_spec.rb +3 -16
  95. data/spec/riak/walk_spec_spec.rb +1 -14
  96. data/spec/spec_helper.rb +22 -27
  97. data/spec/support/http_backend_implementation_examples.rb +49 -79
  98. data/spec/support/integration_setup.rb +10 -0
  99. data/spec/support/mock_server.rb +0 -14
  100. data/spec/support/mocks.rb +0 -13
  101. data/spec/support/test_server.rb +30 -0
  102. data/spec/support/test_server.yml.example +14 -2
  103. data/spec/support/unified_backend_examples.rb +36 -27
  104. metadata +100 -31
  105. data/lib/riak/client/curb_backend.rb +0 -89
  106. data/spec/riak/curb_backend_spec.rb +0 -76
@@ -1,23 +1,6 @@
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__)
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 exclude the index from the URL when not specified" do
30
- @http.should_receive(:get).with(200, "/solr", "select", hash_including("q" => "foo"), {}).and_return({:code => 200, :headers => {"content-type"=>["application/json"]}, :body => "{}"})
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 include extra options in the query string" do
35
- @http.should_receive(:get).with(200, "/solr", "select", hash_including('rows' => 30), {}).and_return({:code => 200, :headers => {"content-type"=>["application/json"]}, :body => "{}"})
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 include the index in the URL when specified" do
40
- @http.should_receive(:get).with(200, "/solr", "search", "select", hash_including("q" => "foo"), {}).and_return({:code => 200, :headers => {"content-type"=>["application/json"]}, :body => "{}"})
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
- it "should include the index in the URL when specified" do
61
- @http.should_receive(:post).with(200, "/solr", "foo", "update", anything, anything).and_return({:code => 200, :headers => {'content-type' => ['text/html']}, :body => ""})
62
- @client.index("foo", {:id => 1, :field => "value"})
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!(:post).and_return(true)
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
- 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>')
78
- @client.index({'id' => 1, 'field' => "value"}, {'id' => 2, 'foo' => "bar"})
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 exclude the index from the URL when not specified" do
84
- @http.should_receive(:post).with(200, "/solr","update", anything, anything).and_return({:code => 200, :headers => {'content-type' => ['text/html']}, :body => ""})
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 include the index in the URL when specified" do
89
- @http.should_receive(:post).with(200, "/solr", "foo", "update", anything, anything).and_return({:code => 200, :headers => {'content-type' => ['text/html']}, :body => ""})
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!(:post).and_return({:code => 200})
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
- args = [200, "/solr", index, "update", body, {"Content-Type" => "text/xml"}].compact
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
- # 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__))
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
@@ -1,17 +1,4 @@
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__))
1
+ require 'spec_helper'
15
2
 
16
3
  describe Riak::WalkSpec do
17
4
  describe "initializing" do
@@ -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
- begin
23
- require 'yaml'
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
- Dir[File.join(File.dirname(__FILE__), "support", "*.rb")].sort.each {|f| require f }
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, @backend.path("/riak/","foo").to_s, :body => "")
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, "/riak/","foo")
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, "/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)
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], "/riak/", "foo") }.should_not raise_error(Riak::FailedRequest)
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, @backend.path("/riak/","foo").to_s, :body => "Success!")
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, "/riak/","foo")
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, "/riak/","foo") }.should raise_error(Riak::FailedRequest)
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], "/riak/","foo") }.should_not raise_error(Riak::FailedRequest)
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, "/riak/","foo") do |chunk|
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, @backend.path("/riak/","foo").to_s, :body => "Success!")
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, "/riak/","foo")
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, "/riak/","foo") }.should raise_error(Riak::FailedRequest)
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], "/riak/","foo") }.should_not raise_error(Riak::FailedRequest)
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, "/riak/","foo") do |chunk|
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, @backend.path("/riak/","foo").to_s, :body => "Success!")
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, "/riak/","foo", "This is the body.")
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, "/riak/","foo", "This is the body.") }.should raise_error(Riak::FailedRequest)
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], "/riak/","foo", "This is the body.") }.should_not raise_error(Riak::FailedRequest)
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, "/riak/","foo", "This is the body.") do |chunk|
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, "/riak/","foo") }.should raise_error(ArgumentError)
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, "/riak/","foo", 123) }.should raise_error(ArgumentError)
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, @backend.path("/riak/","foo").to_s, :body => "Success!")
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, "/riak/","foo", "This is the body.")
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, "/riak/", "foo", "This is the body.") }.should raise_error(Riak::FailedRequest)
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], "/riak/", "foo", "This is the body.") }.should_not raise_error(Riak::FailedRequest)
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, "/riak/", "foo", "This is the body.") do |chunk|
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, "/riak/", "foo") }.should raise_error(ArgumentError)
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, "/riak/", "foo", 123) }.should raise_error(ArgumentError)
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, @backend.path("/riak/","foo").to_s, :status => code)
174
+ setup_http_mock(method, resource.to_s, :status => code)
205
175
  response = if method == :post || method == :put
206
- @backend.send(method, code,"/riak/","foo", "This is the body")
176
+ @backend.send(method, code, resource, "This is the body")
207
177
  else
208
- @backend.send(method, code, "/riak/", "foo")
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, "/riak/","ssl")
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, "/riak/","foo", "body")
217
+ @backend.send(method, 200, resource, "body")
248
218
  else
249
- @backend.send(method, 200, "/riak/","foo")
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, @backend.path("/riak/","foo").to_s, :body => "Failure!", :status => 400, 'Content-Type' => 'text/plain' )
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