riak-client 1.4.5 → 2.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/Gemfile +0 -1
- data/{LICENSE → LICENSE.md} +0 -0
- data/README.markdown +211 -66
- data/RELEASE_NOTES.md +22 -47
- data/Rakefile +45 -0
- data/lib/riak.rb +1 -1
- data/lib/riak/bucket.rb +2 -2
- data/lib/riak/client.rb +22 -195
- data/lib/riak/client/beefcake/crdt_loader.rb +127 -0
- data/lib/riak/client/beefcake/crdt_operator.rb +222 -0
- data/lib/riak/client/beefcake/footer +4 -0
- data/lib/riak/client/beefcake/header +6 -0
- data/lib/riak/client/beefcake/message_codes.rb +29 -0
- data/lib/riak/client/beefcake/message_overlay.rb +61 -0
- data/lib/riak/client/beefcake/messages.rb +733 -371
- data/lib/riak/client/beefcake/object_methods.rb +1 -1
- data/lib/riak/client/beefcake/protocol.rb +105 -0
- data/lib/riak/client/beefcake/socket.rb +243 -0
- data/lib/riak/client/beefcake_protobuffs_backend.rb +262 -122
- data/lib/riak/client/node.rb +4 -75
- data/lib/riak/client/protobuffs_backend.rb +6 -14
- data/lib/riak/client/search.rb +0 -64
- data/lib/riak/client/yokozuna.rb +52 -0
- data/lib/riak/counter.rb +1 -1
- data/lib/riak/crdt.rb +21 -0
- data/lib/riak/crdt/base.rb +97 -0
- data/lib/riak/crdt/batch_counter.rb +19 -0
- data/lib/riak/crdt/batch_map.rb +41 -0
- data/lib/riak/crdt/counter.rb +71 -0
- data/lib/riak/crdt/inner_counter.rb +74 -0
- data/lib/riak/crdt/inner_flag.rb +42 -0
- data/lib/riak/crdt/inner_map.rb +53 -0
- data/lib/riak/crdt/inner_register.rb +26 -0
- data/lib/riak/crdt/inner_set.rb +95 -0
- data/lib/riak/crdt/map.rb +88 -0
- data/lib/riak/crdt/operation.rb +19 -0
- data/lib/riak/crdt/set.rb +156 -0
- data/lib/riak/crdt/typed_collection.rb +131 -0
- data/lib/riak/errors/base.rb +9 -0
- data/lib/riak/errors/connection_error.rb +44 -0
- data/lib/riak/errors/crdt_error.rb +18 -0
- data/lib/riak/errors/failed_request.rb +56 -0
- data/lib/riak/errors/protobuffs_error.rb +11 -0
- data/lib/riak/i18n.rb +2 -0
- data/lib/riak/json.rb +1 -1
- data/lib/riak/locale/en.yml +26 -1
- data/lib/riak/locale/fr.yml +0 -1
- data/lib/riak/map_reduce.rb +1 -1
- data/lib/riak/map_reduce/results.rb +1 -1
- data/lib/riak/multiget.rb +1 -2
- data/lib/riak/rcontent.rb +8 -3
- data/lib/riak/robject.rb +2 -8
- data/lib/riak/secondary_index.rb +4 -4
- data/lib/riak/serializers.rb +1 -1
- data/lib/riak/util/escape.rb +3 -5
- data/lib/riak/version.rb +1 -1
- data/lib/riak/walk_spec.rb +7 -3
- data/riak-client.gemspec +10 -8
- data/spec/fixtures/bitcask.txt +25 -0
- data/spec/integration/riak/bucket_types_spec.rb +61 -0
- data/spec/integration/riak/counters_spec.rb +17 -32
- data/spec/integration/riak/crdt_spec.rb +181 -0
- data/spec/integration/riak/crdt_validation/map_spec.rb +63 -0
- data/spec/integration/riak/crdt_validation/set_spec.rb +122 -0
- data/spec/integration/riak/protobuffs_backends_spec.rb +9 -26
- data/spec/integration/riak/security_spec.rb +94 -0
- data/spec/integration/riak/threading_spec.rb +24 -67
- data/spec/integration/yokozuna/index_spec.rb +61 -0
- data/spec/integration/yokozuna/queries_spec.rb +116 -0
- data/spec/integration/yokozuna/schema_spec.rb +49 -0
- data/spec/riak/beefcake_protobuffs_backend/crdt_operator_spec.rb +222 -0
- data/spec/riak/beefcake_protobuffs_backend/object_methods_spec.rb +4 -4
- data/spec/riak/beefcake_protobuffs_backend/protocol_spec.rb +189 -0
- data/spec/riak/beefcake_protobuffs_backend/socket_spec.rb +151 -0
- data/spec/riak/beefcake_protobuffs_backend_spec.rb +68 -106
- data/spec/riak/bucket_spec.rb +81 -77
- data/spec/riak/client_spec.rb +43 -340
- data/spec/riak/core_ext/to_param_spec.rb +2 -2
- data/spec/riak/counter_spec.rb +20 -20
- data/spec/riak/crdt/counter_spec.rb +52 -0
- data/spec/riak/crdt/inner_counter_spec.rb +21 -0
- data/spec/riak/crdt/inner_flag_spec.rb +39 -0
- data/spec/riak/crdt/inner_map_spec.rb +47 -0
- data/spec/riak/crdt/inner_register_spec.rb +40 -0
- data/spec/riak/crdt/inner_set_spec.rb +33 -0
- data/spec/riak/crdt/map_spec.rb +77 -0
- data/spec/riak/crdt/set_spec.rb +58 -0
- data/spec/riak/crdt/shared_examples.rb +74 -0
- data/spec/riak/crdt/typed_collection_spec.rb +231 -0
- data/spec/riak/escape_spec.rb +33 -37
- data/spec/riak/feature_detection_spec.rb +45 -45
- data/spec/riak/index_collection_spec.rb +12 -12
- data/spec/riak/link_spec.rb +34 -34
- data/spec/riak/list_buckets_spec.rb +7 -7
- data/spec/riak/map_reduce/filter_builder_spec.rb +6 -6
- data/spec/riak/map_reduce/phase_spec.rb +35 -35
- data/spec/riak/map_reduce_spec.rb +89 -87
- data/spec/riak/multiget_spec.rb +20 -15
- data/spec/riak/node_spec.rb +5 -152
- data/spec/riak/robject_spec.rb +95 -108
- data/spec/riak/search_spec.rb +17 -139
- data/spec/riak/secondary_index_spec.rb +49 -49
- data/spec/riak/serializers_spec.rb +9 -9
- data/spec/riak/stamp_spec.rb +9 -9
- data/spec/riak/walk_spec_spec.rb +46 -46
- data/spec/spec_helper.rb +14 -22
- data/spec/support/certs/README.md +13 -0
- data/spec/support/certs/ca.crt +22 -0
- data/spec/support/certs/client.crt +95 -0
- data/spec/support/certs/client.key +27 -0
- data/spec/support/certs/empty_ca.crt +21 -0
- data/spec/support/certs/server.crl +13 -0
- data/spec/support/certs/server.crt +95 -0
- data/spec/support/certs/server.key +27 -0
- data/spec/support/integration_setup.rb +1 -1
- data/spec/support/search_corpus_setup.rb +29 -8
- data/spec/support/test_client.rb +46 -0
- data/spec/support/test_client.yml.example +10 -0
- data/spec/support/unified_backend_examples.rb +104 -83
- data/spec/support/version_filter.rb +2 -2
- data/spec/support/wait_until.rb +14 -0
- metadata +134 -132
- data/erl_src/riak_kv_test014_backend.beam +0 -0
- data/erl_src/riak_kv_test014_backend.erl +0 -189
- data/erl_src/riak_kv_test_backend.beam +0 -0
- data/erl_src/riak_kv_test_backend.erl +0 -731
- data/erl_src/riak_search_test_backend.beam +0 -0
- data/erl_src/riak_search_test_backend.erl +0 -175
- data/lib/riak/client/excon_backend.rb +0 -172
- data/lib/riak/client/http_backend.rb +0 -413
- data/lib/riak/client/http_backend/bucket_streamer.rb +0 -15
- data/lib/riak/client/http_backend/chunked_json_streamer.rb +0 -42
- data/lib/riak/client/http_backend/configuration.rb +0 -227
- data/lib/riak/client/http_backend/key_streamer.rb +0 -15
- data/lib/riak/client/http_backend/object_methods.rb +0 -114
- data/lib/riak/client/http_backend/request_headers.rb +0 -34
- data/lib/riak/client/http_backend/transport_methods.rb +0 -201
- data/lib/riak/client/instrumentation.rb +0 -25
- data/lib/riak/client/net_http_backend.rb +0 -82
- data/lib/riak/cluster.rb +0 -151
- data/lib/riak/failed_request.rb +0 -81
- data/lib/riak/instrumentation.rb +0 -6
- data/lib/riak/node.rb +0 -40
- data/lib/riak/node/configuration.rb +0 -304
- data/lib/riak/node/console.rb +0 -133
- data/lib/riak/node/control.rb +0 -207
- data/lib/riak/node/defaults.rb +0 -85
- data/lib/riak/node/generation.rb +0 -127
- data/lib/riak/node/log.rb +0 -34
- data/lib/riak/node/version.rb +0 -29
- data/lib/riak/search.rb +0 -3
- data/lib/riak/test_server.rb +0 -89
- data/lib/riak/util/headers.rb +0 -32
- data/lib/riak/util/multipart.rb +0 -52
- data/lib/riak/util/multipart/stream_parser.rb +0 -62
- data/spec/fixtures/munchausen.txt +0 -1033
- data/spec/integration/riak/cluster_spec.rb +0 -88
- data/spec/integration/riak/http_backends_spec.rb +0 -180
- data/spec/integration/riak/node_spec.rb +0 -170
- data/spec/integration/riak/test_server_spec.rb +0 -57
- data/spec/riak/excon_backend_spec.rb +0 -102
- data/spec/riak/headers_spec.rb +0 -21
- data/spec/riak/http_backend/configuration_spec.rb +0 -273
- data/spec/riak/http_backend/object_methods_spec.rb +0 -243
- data/spec/riak/http_backend/transport_methods_spec.rb +0 -97
- data/spec/riak/http_backend_spec.rb +0 -367
- data/spec/riak/instrumentation_spec.rb +0 -167
- data/spec/riak/multipart_spec.rb +0 -23
- data/spec/riak/net_http_backend_spec.rb +0 -15
- data/spec/riak/stream_parser_spec.rb +0 -53
- data/spec/support/drb_mock_server.rb +0 -39
- data/spec/support/http_backend_implementation_examples.rb +0 -253
- data/spec/support/mock_server.rb +0 -81
- data/spec/support/mocks.rb +0 -4
- data/spec/support/riak_test.rb +0 -77
- data/spec/support/sometimes.rb +0 -46
- data/spec/support/test_server.rb +0 -61
- data/spec/support/test_server.yml.example +0 -14
data/spec/riak/multiget_spec.rb
CHANGED
@@ -9,14 +9,14 @@ describe Riak::Multiget do
|
|
9
9
|
|
10
10
|
describe "initialization" do
|
11
11
|
it "should accept a client and an array of bucket/key pairs" do
|
12
|
-
|
12
|
+
expect { Riak::Multiget.new(@client, @pairs) }.not_to raise_error
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
16
|
describe "operation" do
|
17
17
|
it "should fetch both keys from the bucket" do
|
18
|
-
@bucket.
|
19
|
-
@bucket.
|
18
|
+
expect(@bucket).to receive(:[]).with('key1')
|
19
|
+
expect(@bucket).to receive(:[]).with('key2')
|
20
20
|
|
21
21
|
@multiget = Riak::Multiget.new(@client, @pairs)
|
22
22
|
@multiget.fetch
|
@@ -29,48 +29,53 @@ describe Riak::Multiget do
|
|
29
29
|
@slow_mtx.lock
|
30
30
|
|
31
31
|
# set up fetch process to wait on key2
|
32
|
-
@bucket.
|
32
|
+
expect(@bucket).to receive(:[]) { |key|
|
33
33
|
next if key == 'key1'
|
34
34
|
|
35
35
|
# wait for test process
|
36
36
|
@slow_mtx.lock
|
37
|
-
|
37
|
+
}.twice
|
38
38
|
|
39
39
|
# start fetch process
|
40
40
|
@multiget = Riak::Multiget.new(@client, @pairs)
|
41
41
|
@multiget.fetch
|
42
42
|
|
43
|
-
@multiget.finished
|
43
|
+
expect(@multiget.finished?).to be_falsey
|
44
44
|
|
45
45
|
# allow fetch
|
46
46
|
@slow_mtx.unlock
|
47
47
|
|
48
48
|
@results = @multiget.results
|
49
|
-
@multiget.finished
|
50
|
-
@results.
|
49
|
+
expect(@multiget.finished?).to be_truthy
|
50
|
+
expect(@results).to be_a Hash
|
51
51
|
end
|
52
52
|
|
53
53
|
it "should not die when objects aren't found" do
|
54
|
-
@bucket.
|
55
|
-
|
54
|
+
expect(@bucket).to receive(:[]).
|
55
|
+
with('key1').
|
56
|
+
and_raise(Riak::ProtobuffsFailedRequest.new(:not_found, "not found"))
|
57
|
+
|
58
|
+
expect(@bucket).to receive(:[]).
|
59
|
+
with('key2').
|
60
|
+
and_return(true)
|
56
61
|
|
57
62
|
@results = Riak::Multiget.get_all @client, @pairs
|
58
63
|
|
59
|
-
@results[[@bucket, 'key1']].
|
60
|
-
@results[[@bucket, 'key2']].
|
64
|
+
expect(@results[[@bucket, 'key1']]).to be_nil
|
65
|
+
expect(@results[[@bucket, 'key2']]).to be_truthy
|
61
66
|
end
|
62
67
|
end
|
63
68
|
|
64
69
|
describe "results" do
|
65
70
|
it "should return a hash of pairs to values" do
|
66
|
-
@bucket.
|
67
|
-
@bucket.
|
71
|
+
expect(@bucket).to receive(:[]).with('key1')
|
72
|
+
expect(@bucket).to receive(:[]).with('key2')
|
68
73
|
|
69
74
|
@multiget = Riak::Multiget.new(@client, @pairs)
|
70
75
|
@multiget.fetch
|
71
76
|
@results = @multiget.results
|
72
77
|
|
73
|
-
@results.
|
78
|
+
expect(@results).to be_a Hash
|
74
79
|
end
|
75
80
|
end
|
76
81
|
end
|
data/spec/riak/node_spec.rb
CHANGED
@@ -7,167 +7,20 @@ describe Riak::Client::Node do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
describe 'when initializing' do
|
10
|
-
it 'should default to the local interface on port
|
10
|
+
it 'should default to the local interface on port 8087' do
|
11
11
|
node = Riak::Client::Node.new @client
|
12
|
-
node.host.
|
13
|
-
node.
|
14
|
-
node.pb_port.should == 8087
|
12
|
+
expect(node.host).to eq('127.0.0.1')
|
13
|
+
expect(node.pb_port).to eq(8087)
|
15
14
|
end
|
16
15
|
|
17
16
|
it 'should accept a host' do
|
18
17
|
node = Riak::Client::Node.new(@client, :host => 'riak.basho.com')
|
19
|
-
node.host.
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'should accept an HTTP port' do
|
23
|
-
node = Riak::Client::Node.new(@client, :http_port => 9000)
|
24
|
-
node.http_port.should == 9000
|
18
|
+
expect(node.host).to eq("riak.basho.com")
|
25
19
|
end
|
26
20
|
|
27
21
|
it 'should accept a Protobuffs port' do
|
28
22
|
node = Riak::Client::Node.new @client, :pb_port => 9000
|
29
|
-
node.pb_port.
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'should accept basic_auth' do
|
33
|
-
node = Riak::Client::Node.new @client, :basic_auth => 'user:pass'
|
34
|
-
node.basic_auth.should == "user:pass"
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'should accept a path prefix' do
|
38
|
-
node = Riak::Client::Node.new @client, :prefix => "/jiak/"
|
39
|
-
node.http_paths[:prefix].should == "/jiak/"
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'default prefix should be /riak/' do
|
43
|
-
@node.http_paths[:prefix].should == "/riak/"
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'should accept a mapreduce path' do
|
47
|
-
node = Riak::Client::Node.new @client, :mapred => "/mr"
|
48
|
-
node.http_paths[:mapred].should == "/mr"
|
49
|
-
end
|
50
|
-
|
51
|
-
it "default mapreduce path should be /mapred" do
|
52
|
-
@node.http_paths[:mapred].should == "/mapred"
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'should accept a solr path' do
|
56
|
-
node = Riak::Client::Node.new @client, :solr => "/mr"
|
57
|
-
node.http_paths[:solr].should == "/mr"
|
58
|
-
end
|
59
|
-
|
60
|
-
it "default solr path should be /solr" do
|
61
|
-
@node.http_paths[:solr].should == "/solr"
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'should accept a luwak path' do
|
65
|
-
node = Riak::Client::Node.new @client, :luwak => "/mr"
|
66
|
-
node.http_paths[:luwak].should == "/mr"
|
67
|
-
end
|
68
|
-
|
69
|
-
it "default luwak path should be /luwak" do
|
70
|
-
@node.http_paths[:luwak].should == "/luwak"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
describe "setting http auth" do
|
75
|
-
it "should allow setting basic_auth" do
|
76
|
-
@node.should respond_to(:basic_auth=)
|
77
|
-
@node.basic_auth = "user:pass"
|
78
|
-
@node.basic_auth.should == "user:pass"
|
79
|
-
@node.basic_auth = nil
|
80
|
-
@node.basic_auth.should == nil
|
81
|
-
end
|
82
|
-
|
83
|
-
it "should require that basic auth splits into two even parts" do
|
84
|
-
lambda { @node.basic_auth ="user" }.should raise_error(ArgumentError, "basic auth must be set using 'user:pass'")
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
describe 'ssl' do
|
89
|
-
before :each do
|
90
|
-
@client = Riak::Client.new
|
91
|
-
@node = Riak::Client::Node.new @client
|
92
|
-
end
|
93
|
-
|
94
|
-
it 'should not allow reading ssl options via ssl' do
|
95
|
-
@node.should_not respond_to(:ssl)
|
96
|
-
end
|
97
|
-
|
98
|
-
it 'should allow setting ssl to true' do
|
99
|
-
@node.ssl = true
|
100
|
-
@node.ssl_options[:verify_mode].should eq('none')
|
101
|
-
end
|
102
|
-
|
103
|
-
it "should should clear ssl options when setting ssl to false" do
|
104
|
-
@node.ssl = true
|
105
|
-
@node.ssl_options.should_not be_nil
|
106
|
-
@node.ssl = false
|
107
|
-
@node.ssl_options.should be_nil
|
108
|
-
end
|
109
|
-
|
110
|
-
it "should allow setting the verify_mode to none" do
|
111
|
-
@node.ssl = {:verify_mode => "none"}
|
112
|
-
@node.ssl_options[:verify_mode].should eq("none")
|
113
|
-
end
|
114
|
-
|
115
|
-
it "should allow setting the verify_mode to peer" do
|
116
|
-
@node.ssl = {:verify_mode => "peer"}
|
117
|
-
@node.ssl_options[:verify_mode].should eq("peer")
|
118
|
-
end
|
119
|
-
|
120
|
-
it "should not allow setting the verify_mode to anything else" do
|
121
|
-
lambda {@node.ssl = {:verify_mode => :your_mom}}.should raise_error(ArgumentError)
|
122
|
-
end
|
123
|
-
|
124
|
-
it "should default verify_mode to none" do
|
125
|
-
@node.ssl = true
|
126
|
-
@node.ssl_options[:verify_mode].should eq("none")
|
127
|
-
end
|
128
|
-
|
129
|
-
it "should let the backend know if ssl is enabled" do
|
130
|
-
@node.should_not be_ssl_enabled
|
131
|
-
@node.ssl = true
|
132
|
-
@node.should be_ssl_enabled
|
133
|
-
end
|
134
|
-
|
135
|
-
it "should allow setting the pem" do
|
136
|
-
@node.ssl = {:pem => 'i-am-a-pem'}
|
137
|
-
@node.ssl_options[:pem].should eq('i-am-a-pem')
|
138
|
-
end
|
139
|
-
|
140
|
-
it "should set them pem from the contents of pem_file" do
|
141
|
-
filepath = File.expand_path(File.join(File.dirname(__FILE__), '../fixtures/test.pem'))
|
142
|
-
@node.ssl = {:pem_file => filepath}
|
143
|
-
@node.ssl_options[:pem].should eq("i-am-a-pem\n")
|
144
|
-
end
|
145
|
-
|
146
|
-
it "should allow setting the pem_password" do
|
147
|
-
@node.ssl = {:pem_password => 'pem-pass'}
|
148
|
-
@node.ssl_options[:pem_password].should eq('pem-pass')
|
149
|
-
end
|
150
|
-
|
151
|
-
it "should allow setting the ca_file" do
|
152
|
-
@node.ssl = {:ca_file => '/path/to/ca.crt'}
|
153
|
-
@node.ssl_options[:ca_file].should eq('/path/to/ca.crt')
|
154
|
-
end
|
155
|
-
|
156
|
-
it "should allow setting the ca_path" do
|
157
|
-
@node.ssl = {:ca_path => '/path/to/certs/'}
|
158
|
-
@node.ssl_options[:ca_path].should eq('/path/to/certs/')
|
159
|
-
end
|
160
|
-
|
161
|
-
%w[pem ca_file ca_path].each do |option|
|
162
|
-
it "should default the verify_mode to peer when setting the #{option}" do
|
163
|
-
@node.ssl = {option.to_sym => 'test-data'}
|
164
|
-
@node.ssl_options[:verify_mode].should eq("peer")
|
165
|
-
end
|
166
|
-
|
167
|
-
it "should allow setting the verify mode when setting the #{option}" do
|
168
|
-
@node.ssl = {option.to_sym => 'test-data', :verify_mode => "none"}
|
169
|
-
@node.ssl_options[:verify_mode].should eq("none")
|
170
|
-
end
|
23
|
+
expect(node.pb_port).to eq(9000)
|
171
24
|
end
|
172
25
|
end
|
173
26
|
end
|
data/spec/riak/robject_spec.rb
CHANGED
@@ -9,34 +9,34 @@ describe Riak::RObject do
|
|
9
9
|
describe "initialization" do
|
10
10
|
it "should set the bucket" do
|
11
11
|
@object = Riak::RObject.new(@bucket)
|
12
|
-
@object.bucket.
|
12
|
+
expect(@object.bucket).to eq(@bucket)
|
13
13
|
end
|
14
14
|
|
15
15
|
it "should set the key" do
|
16
16
|
@object = Riak::RObject.new(@bucket, "bar")
|
17
|
-
@object.key.
|
17
|
+
expect(@object.key).to eq("bar")
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should initialize the links to an empty set" do
|
21
21
|
@object = Riak::RObject.new(@bucket, "bar")
|
22
|
-
@object.links.
|
22
|
+
expect(@object.links).to eq(Set.new)
|
23
23
|
end
|
24
24
|
|
25
25
|
it "should initialize the meta to an empty hash" do
|
26
26
|
@object = Riak::RObject.new(@bucket, "bar")
|
27
|
-
@object.meta.
|
27
|
+
expect(@object.meta).to eq({})
|
28
28
|
end
|
29
29
|
|
30
30
|
it "should initialize indexes to an empty hash with a Set for the default value" do
|
31
31
|
@object = Riak::RObject.new(@bucket, "bar")
|
32
|
-
@object.indexes.
|
33
|
-
@object.indexes.
|
34
|
-
@object.indexes['foo_bin'].
|
32
|
+
expect(@object.indexes).to be_kind_of(Hash)
|
33
|
+
expect(@object.indexes).to be_empty
|
34
|
+
expect(@object.indexes['foo_bin']).to be_kind_of(Set)
|
35
35
|
end
|
36
36
|
|
37
37
|
it "should yield itself to a given block" do
|
38
38
|
Riak::RObject.new(@bucket, "bar") do |r|
|
39
|
-
r.key.
|
39
|
+
expect(r.key).to eq("bar")
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
@@ -48,16 +48,16 @@ describe Riak::RObject do
|
|
48
48
|
|
49
49
|
it 'delegates #serialize to the appropriate serializer for the content type' do
|
50
50
|
@object.content_type = 'text/plain'
|
51
|
-
Riak::Serializers.
|
52
|
-
Riak::Serializers.
|
53
|
-
@object.content.serialize("foo").
|
51
|
+
expect(Riak::Serializers).to respond_to(:serialize).with(2).arguments
|
52
|
+
expect(Riak::Serializers).to receive(:serialize).with('text/plain', "foo").and_return("serialized foo")
|
53
|
+
expect(@object.content.serialize("foo")).to eq("serialized foo")
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'delegates #deserialize to the appropriate serializer for the content type' do
|
57
57
|
@object.content_type = 'text/plain'
|
58
|
-
Riak::Serializers.
|
59
|
-
Riak::Serializers.
|
60
|
-
@object.content.deserialize("foo").
|
58
|
+
expect(Riak::Serializers).to respond_to(:deserialize).with(2).arguments
|
59
|
+
expect(Riak::Serializers).to receive(:deserialize).with('text/plain', "foo").and_return("deserialized foo")
|
60
|
+
expect(@object.content.deserialize("foo")).to eq("deserialized foo")
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -76,20 +76,20 @@ describe Riak::RObject do
|
|
76
76
|
it "should reset unserialized forms when stored" do
|
77
77
|
@object.raw_data = value = '{ "raw": "json" }'
|
78
78
|
|
79
|
-
@object.raw_data.
|
80
|
-
@object.data.
|
79
|
+
expect(@object.raw_data).to eq(value)
|
80
|
+
expect(@object.data).to eq({ "raw" => "json" })
|
81
81
|
end
|
82
82
|
|
83
83
|
it "should lazily serialize when read" do
|
84
|
-
@object.raw_data.
|
84
|
+
expect(@object.raw_data).to eq('{"some":"data"}')
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
88
|
it "should not unnecessarily marshal/demarshal" do
|
89
|
-
@object.
|
90
|
-
@object.
|
89
|
+
expect(@object).not_to receive(:serialize)
|
90
|
+
expect(@object).not_to receive(:deserialize)
|
91
91
|
@object.raw_data = value = "{not even valid json!}}"
|
92
|
-
@object.raw_data.
|
92
|
+
expect(@object.raw_data).to eq(value)
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
@@ -101,21 +101,21 @@ describe Riak::RObject do
|
|
101
101
|
|
102
102
|
it "should reset previously stored raw data" do
|
103
103
|
@object.data = value = { "new" => "data" }
|
104
|
-
@object.raw_data.
|
105
|
-
@object.data.
|
104
|
+
expect(@object.raw_data).to eq('{"new":"data"}')
|
105
|
+
expect(@object.data).to eq(value)
|
106
106
|
end
|
107
107
|
|
108
108
|
it "should lazily deserialize when read" do
|
109
|
-
@object.data.
|
109
|
+
expect(@object.data).to eq({ "some" => "data" })
|
110
110
|
end
|
111
111
|
|
112
112
|
context 'for an IO-like object' do
|
113
|
-
let(:io_object) {
|
113
|
+
let(:io_object) { double(:read => 'the io object') }
|
114
114
|
|
115
115
|
it 'reads the object before deserializing it' do
|
116
|
-
@object.content.
|
116
|
+
expect(@object.content).to receive(:deserialize).with('the io object').and_return('deserialized')
|
117
117
|
@object.raw_data = io_object
|
118
|
-
@object.data.
|
118
|
+
expect(@object.data).to eq('deserialized')
|
119
119
|
end
|
120
120
|
|
121
121
|
it 'does not allow it to be assigned directly to data since it should be assigned to raw_data instead' do
|
@@ -127,10 +127,10 @@ describe Riak::RObject do
|
|
127
127
|
end
|
128
128
|
|
129
129
|
it "should not unnecessarily marshal/demarshal" do
|
130
|
-
@object.
|
131
|
-
@object.
|
130
|
+
expect(@object).not_to receive(:serialize)
|
131
|
+
expect(@object).not_to receive(:deserialize)
|
132
132
|
@object.data = value = { "some" => "data" }
|
133
|
-
@object.data.
|
133
|
+
expect(@object.data).to eq(value)
|
134
134
|
end
|
135
135
|
end
|
136
136
|
end
|
@@ -138,7 +138,7 @@ describe Riak::RObject do
|
|
138
138
|
|
139
139
|
describe "instantiating new object from a map reduce operation" do
|
140
140
|
before :each do
|
141
|
-
@client.
|
141
|
+
allow(@client).to receive(:[]).and_return(@bucket)
|
142
142
|
|
143
143
|
@sample_response = [
|
144
144
|
{"bucket"=>"users",
|
@@ -163,59 +163,59 @@ describe Riak::RObject do
|
|
163
163
|
}
|
164
164
|
]
|
165
165
|
@object = Riak::RObject.load_from_mapreduce(@client,@sample_response).first
|
166
|
-
@object.
|
166
|
+
expect(@object).to be_kind_of(Riak::RObject)
|
167
167
|
end
|
168
168
|
|
169
169
|
it "should load the content type" do
|
170
|
-
@object.content_type.
|
170
|
+
expect(@object.content_type).to eq("application/json")
|
171
171
|
end
|
172
172
|
|
173
173
|
it "should load the body data" do
|
174
|
-
@object.data.
|
174
|
+
expect(@object.data).to be_present
|
175
175
|
end
|
176
176
|
|
177
177
|
it "should deserialize the body data" do
|
178
|
-
@object.data.
|
178
|
+
expect(@object.data).to eq({"email" => "mail@test.com", "_type" => "User"})
|
179
179
|
end
|
180
180
|
|
181
181
|
it "should set the vclock" do
|
182
|
-
@object.vclock.
|
182
|
+
expect(@object.vclock).to eq("a85hYGBgzmDKBVIsCfs+fc9gSN9wlA8q/hKosDpIOAsA")
|
183
183
|
end
|
184
184
|
|
185
185
|
it "should load and parse links" do
|
186
|
-
@object.links.
|
187
|
-
@object.links.first.url.
|
188
|
-
@object.links.first.rel.
|
186
|
+
expect(@object.links.size).to eq(1)
|
187
|
+
expect(@object.links.first.url).to eq("/riak/addresses/A2cbUQ2KEMbeyWGtdz97LoTi1DN")
|
188
|
+
expect(@object.links.first.rel).to eq("home_address")
|
189
189
|
end
|
190
190
|
|
191
191
|
it "should load and parse indexes" do
|
192
|
-
@object.indexes.
|
193
|
-
@object.indexes['email_bin'].
|
194
|
-
@object.indexes['rank_int'].
|
192
|
+
expect(@object.indexes.size).to eq(2)
|
193
|
+
expect(@object.indexes['email_bin'].size).to eq(2)
|
194
|
+
expect(@object.indexes['rank_int'].size).to eq(1)
|
195
195
|
end
|
196
196
|
|
197
197
|
it "should set the ETag" do
|
198
|
-
@object.etag.
|
198
|
+
expect(@object.etag).to eq("5bnavU3rrubcxLI8EvFXhB")
|
199
199
|
end
|
200
200
|
|
201
201
|
it "should set modified date" do
|
202
|
-
@object.last_modified.to_i.
|
202
|
+
expect(@object.last_modified.to_i).to eq(Time.httpdate("Mon, 12 Jul 2010 21:37:43 GMT").to_i)
|
203
203
|
end
|
204
204
|
|
205
205
|
it "should load meta information" do
|
206
|
-
@object.meta["King-Of-Robots"].
|
206
|
+
expect(@object.meta["King-Of-Robots"]).to eq(["I"])
|
207
207
|
end
|
208
208
|
|
209
209
|
it "should set the key" do
|
210
|
-
@object.key.
|
210
|
+
expect(@object.key).to eq("A2IbUQ2KEMbe4WGtdL97LoTi1DN[(\\/)]")
|
211
211
|
end
|
212
212
|
|
213
213
|
it "should not set conflict when there is none" do
|
214
|
-
@object.conflict
|
214
|
+
expect(@object.conflict?).to be_falsey
|
215
215
|
end
|
216
216
|
|
217
217
|
it 'should return [RContent] for siblings' do
|
218
|
-
@object.siblings.
|
218
|
+
expect(@object.siblings).to eq([@object.content])
|
219
219
|
end
|
220
220
|
|
221
221
|
describe "when there are multiple values in an object" do
|
@@ -235,14 +235,14 @@ describe Riak::RObject do
|
|
235
235
|
end
|
236
236
|
|
237
237
|
it "should expose siblings" do
|
238
|
-
@object.
|
239
|
-
@object.siblings[0].etag.
|
240
|
-
@object.siblings[1].etag.
|
238
|
+
expect(@object.siblings.size).to eq(2)
|
239
|
+
expect(@object.siblings[0].etag).to eq("5bnavU3rrubcxLI8EvFXhB")
|
240
|
+
expect(@object.siblings[1].etag).to eq("7jDZLdu0fIj2iRsjGD8qq8")
|
241
241
|
end
|
242
242
|
|
243
243
|
it "should be in conflict" do
|
244
244
|
expect { @object.data }.to raise_error(Riak::Conflict)
|
245
|
-
@object.
|
245
|
+
expect(@object).to be_conflict
|
246
246
|
end
|
247
247
|
end
|
248
248
|
end
|
@@ -251,21 +251,21 @@ describe Riak::RObject do
|
|
251
251
|
@object = Riak::RObject.new(@bucket, "foo")
|
252
252
|
@object.links << Riak::Link.new("/riak/foo/baz", "next")
|
253
253
|
@object.links << Riak::Link.new("/riak/foo/baz", "next")
|
254
|
-
@object.links.length.
|
254
|
+
expect(@object.links.length).to eq(1)
|
255
255
|
end
|
256
256
|
|
257
257
|
it "should allow mass-overwriting indexes while preserving default behavior" do
|
258
258
|
@object = described_class.new(@bucket, 'foo')
|
259
259
|
@object.indexes = {"ts_int" => [12345], "foo_bin" => "bar"}
|
260
|
-
@object.indexes['ts_int'].
|
261
|
-
@object.indexes['foo_bin'].
|
262
|
-
@object.indexes['unset_bin'].
|
260
|
+
expect(@object.indexes['ts_int']).to eq(Set.new([12345]))
|
261
|
+
expect(@object.indexes['foo_bin']).to eq(Set.new(["bar"]))
|
262
|
+
expect(@object.indexes['unset_bin']).to eq(Set.new)
|
263
263
|
end
|
264
264
|
|
265
265
|
describe "when storing the object normally" do
|
266
266
|
before :each do
|
267
|
-
@backend =
|
268
|
-
@client.
|
267
|
+
@backend = double("Backend")
|
268
|
+
allow(@client).to receive(:backend).and_yield(@backend)
|
269
269
|
@object = Riak::RObject.new(@bucket)
|
270
270
|
@object.content_type = "text/plain"
|
271
271
|
@object.data = "This is some text."
|
@@ -273,16 +273,16 @@ describe Riak::RObject do
|
|
273
273
|
end
|
274
274
|
|
275
275
|
it "should raise an error when the content_type is blank" do
|
276
|
-
|
277
|
-
|
276
|
+
expect { @object.content_type = nil; @object.store }.to raise_error(ArgumentError)
|
277
|
+
expect { @object.content_type = " "; @object.store }.to raise_error(ArgumentError)
|
278
278
|
end
|
279
279
|
|
280
280
|
it "should raise an error when given an empty string as key" do
|
281
|
-
|
281
|
+
expect { @object.key = ''; @object.store }.to raise_error(ArgumentError)
|
282
282
|
end
|
283
283
|
|
284
284
|
it "should pass along quorum parameters and returnbody to the backend" do
|
285
|
-
@backend.
|
285
|
+
expect(@backend).to receive(:store_object).with(@object, :returnbody => false, :w => 3, :dw => 2).and_return(true)
|
286
286
|
@object.store(:returnbody => false, :w => 3, :dw => 2)
|
287
287
|
end
|
288
288
|
|
@@ -294,103 +294,90 @@ describe Riak::RObject do
|
|
294
294
|
|
295
295
|
describe "when reloading the object" do
|
296
296
|
before :each do
|
297
|
-
@backend =
|
298
|
-
@client.
|
297
|
+
@backend = double("Backend")
|
298
|
+
allow(@client).to receive(:backend).and_yield(@backend)
|
299
299
|
@object = Riak::RObject.new(@bucket, "bar")
|
300
300
|
@object.vclock = "somereallylongstring"
|
301
301
|
end
|
302
302
|
|
303
303
|
it "should return without requesting if the key is blank" do
|
304
304
|
@object.key = nil
|
305
|
-
@backend.
|
305
|
+
expect(@backend).not_to receive(:reload_object)
|
306
306
|
@object.reload
|
307
307
|
end
|
308
308
|
|
309
309
|
it "should return without requesting if the vclock is blank" do
|
310
310
|
@object.vclock = nil
|
311
|
-
@backend.
|
311
|
+
expect(@backend).not_to receive(:reload_object)
|
312
312
|
@object.reload
|
313
313
|
end
|
314
314
|
|
315
315
|
it "should reload the object if the key is present" do
|
316
|
-
@backend.
|
316
|
+
expect(@backend).to receive(:reload_object).with(@object, {}).and_return(@object)
|
317
317
|
@object.reload
|
318
318
|
end
|
319
319
|
|
320
320
|
it "should pass along the requested R quorum" do
|
321
|
-
@backend.
|
321
|
+
expect(@backend).to receive(:reload_object).with(@object, :r => 2).and_return(@object)
|
322
322
|
@object.reload :r => 2
|
323
323
|
end
|
324
324
|
|
325
325
|
it "should disable matching conditions if the key is present and the :force option is given" do
|
326
|
-
@backend.
|
327
|
-
obj.etag.
|
328
|
-
obj.last_modified.
|
326
|
+
expect(@backend).to receive(:reload_object) do |obj, _|
|
327
|
+
expect(obj.etag).to be_nil
|
328
|
+
expect(obj.last_modified).to be_nil
|
329
329
|
obj
|
330
330
|
end
|
331
331
|
@object.reload :force => true
|
332
332
|
end
|
333
333
|
end
|
334
334
|
|
335
|
-
describe "walking from the object to linked objects" do
|
336
|
-
before :each do
|
337
|
-
@http = mock("HTTPBackend")
|
338
|
-
@client.stub!(:http).and_yield(@http)
|
339
|
-
@client.stub!(:bucket).and_return(@bucket)
|
340
|
-
@object = Riak::RObject.new(@bucket, "bar")
|
341
|
-
end
|
342
|
-
|
343
|
-
it "should normalize the walk specs and submit the link-walking request to the HTTP backend" do
|
344
|
-
@http.should_receive(:link_walk).with(@object, [instance_of(Riak::WalkSpec)]).and_return([])
|
345
|
-
@object.walk(nil,"next",true).should == []
|
346
|
-
end
|
347
|
-
end
|
348
|
-
|
349
335
|
describe "when deleting" do
|
350
336
|
before :each do
|
351
|
-
@backend =
|
352
|
-
@client.
|
337
|
+
@backend = double("Backend")
|
338
|
+
allow(@client).to receive(:backend).and_yield(@backend)
|
353
339
|
@object = Riak::RObject.new(@bucket, "bar")
|
354
340
|
end
|
355
341
|
|
356
342
|
it "should make a DELETE request to the Riak server and freeze the object" do
|
357
|
-
@backend.
|
343
|
+
expect(@backend).to receive(:delete_object).with(@bucket, "bar", {})
|
358
344
|
@object.delete
|
359
|
-
@object.
|
345
|
+
expect(@object).to be_frozen
|
360
346
|
end
|
361
347
|
|
362
348
|
it "should do nothing when the key is blank" do
|
363
|
-
@backend.
|
349
|
+
expect(@backend).not_to receive(:delete_object)
|
364
350
|
@object.key = nil
|
365
351
|
@object.delete
|
366
352
|
end
|
367
353
|
|
368
354
|
it "should pass through a failed request exception" do
|
369
|
-
@backend.
|
370
|
-
|
355
|
+
expect(@backend).to receive(:delete_object).
|
356
|
+
and_raise(Riak::ProtobuffsFailedRequest.new(:server_error, "server error"))
|
357
|
+
expect { @object.delete }.to raise_error(Riak::FailedRequest)
|
371
358
|
end
|
372
359
|
|
373
360
|
it "should send the vector clock if present" do
|
374
361
|
@object.vclock = "somevclock"
|
375
|
-
@backend.
|
362
|
+
expect(@backend).to receive(:delete_object).with(@bucket, "bar", {:vclock => "somevclock"})
|
376
363
|
@object.delete
|
377
364
|
end
|
378
365
|
end
|
379
366
|
|
380
367
|
it "should not convert to link without a tag" do
|
381
368
|
@object = Riak::RObject.new(@bucket, "bar")
|
382
|
-
|
369
|
+
expect { @object.to_link }.to raise_error
|
383
370
|
end
|
384
371
|
|
385
372
|
it "should convert to a link having the same url and a supplied tag" do
|
386
373
|
@object = Riak::RObject.new(@bucket, "bar")
|
387
|
-
@object.to_link("next").
|
374
|
+
expect(@object.to_link("next")).to eq(Riak::Link.new("/riak/foo/bar", "next"))
|
388
375
|
end
|
389
376
|
|
390
377
|
it "should escape the bucket and key when converting to a link" do
|
391
378
|
@object = Riak::RObject.new(@bucket, "deep/path")
|
392
|
-
@bucket.
|
393
|
-
@object.to_link("bar").url.
|
379
|
+
expect(@bucket).to receive(:name).and_return("bucket spaces")
|
380
|
+
expect(@object.to_link("bar").url).to eq("/riak/bucket%20spaces/deep%2Fpath")
|
394
381
|
end
|
395
382
|
|
396
383
|
describe "#inspect" do
|
@@ -398,7 +385,7 @@ describe Riak::RObject do
|
|
398
385
|
|
399
386
|
it "provides useful output even when the key is nil" do
|
400
387
|
expect { object.inspect }.not_to raise_error
|
401
|
-
object.inspect.
|
388
|
+
expect(object.inspect).to be_kind_of(String)
|
402
389
|
end
|
403
390
|
|
404
391
|
it 'uses the serializer output in inspect' do
|
@@ -408,18 +395,18 @@ describe Riak::RObject do
|
|
408
395
|
def o.load(object); "serialize for inspect"; end
|
409
396
|
end
|
410
397
|
|
411
|
-
object.inspect.
|
398
|
+
expect(object.inspect).to match(/serialize for inspect/)
|
412
399
|
end
|
413
400
|
end
|
414
401
|
|
415
402
|
describe '.on_conflict' do
|
416
403
|
it 'adds the hook to the list of on conflict hooks' do
|
417
404
|
hook_run = false
|
418
|
-
described_class.on_conflict_hooks.
|
405
|
+
expect(described_class.on_conflict_hooks).to be_empty
|
419
406
|
described_class.on_conflict { hook_run = true }
|
420
|
-
described_class.on_conflict_hooks.size.
|
407
|
+
expect(described_class.on_conflict_hooks.size).to eq(1)
|
421
408
|
described_class.on_conflict_hooks.first.call
|
422
|
-
hook_run.
|
409
|
+
expect(hook_run).to eq(true)
|
423
410
|
end
|
424
411
|
end
|
425
412
|
|
@@ -441,27 +428,27 @@ describe Riak::RObject do
|
|
441
428
|
described_class.on_conflict(&resolver_3)
|
442
429
|
described_class.on_conflict(&resolver_4)
|
443
430
|
conflicted_robject.attempt_conflict_resolution
|
444
|
-
invoked_resolvers.
|
431
|
+
expect(invoked_resolvers).to eq([:resolver_1, :resolver_2, :resolver_3])
|
445
432
|
end
|
446
433
|
|
447
434
|
it 'returns the robject returned by the last invoked resolver' do
|
448
435
|
described_class.on_conflict(&resolver_4)
|
449
|
-
conflicted_robject.attempt_conflict_resolution.
|
436
|
+
expect(conflicted_robject.attempt_conflict_resolution).to be(resolved_robject)
|
450
437
|
end
|
451
438
|
|
452
439
|
it 'allows the resolver to return the original robject' do
|
453
440
|
described_class.on_conflict(&resolver_3)
|
454
|
-
conflicted_robject.attempt_conflict_resolution.
|
441
|
+
expect(conflicted_robject.attempt_conflict_resolution).to be(conflicted_robject)
|
455
442
|
end
|
456
443
|
|
457
444
|
it 'returns the robject and does not call any resolvers if the robject is not in conflict' do
|
458
|
-
resolved_robject.attempt_conflict_resolution.
|
459
|
-
invoked_resolvers.
|
445
|
+
expect(resolved_robject.attempt_conflict_resolution).to be(resolved_robject)
|
446
|
+
expect(invoked_resolvers).to eq([])
|
460
447
|
end
|
461
448
|
|
462
449
|
it 'returns the original robject if none of the resolvers returns an robject' do
|
463
|
-
conflicted_robject.attempt_conflict_resolution.
|
464
|
-
invoked_resolvers.
|
450
|
+
expect(conflicted_robject.attempt_conflict_resolution).to be(conflicted_robject)
|
451
|
+
expect(invoked_resolvers).to eq([:resolver_1, :resolver_2])
|
465
452
|
end
|
466
453
|
end
|
467
454
|
end
|