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
@@ -12,11 +12,11 @@ describe Riak::Client::BeefcakeProtobuffsBackend::ObjectMethods do
|
|
12
12
|
|
13
13
|
describe "loading object data from the response" do
|
14
14
|
it "should load the key" do
|
15
|
-
content =
|
16
|
-
pbuf =
|
15
|
+
content = double(:value => '', :vtag => nil, :content_type => nil, :links => nil, :usermeta => nil, :last_mod => nil, :indexes => nil, :charset => nil)
|
16
|
+
pbuf = double(:vclock => nil, :content => [content], :value => nil, :key => 'akey')
|
17
17
|
o = @backend.load_object(pbuf, @object)
|
18
|
-
o.
|
19
|
-
o.key.
|
18
|
+
expect(o).to eq(@object)
|
19
|
+
expect(o.key).to eq(pbuf.key)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -0,0 +1,189 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'riak/client/beefcake/protocol'
|
3
|
+
|
4
|
+
describe Riak::Client::BeefcakeProtobuffsBackend::Protocol do
|
5
|
+
let(:socket){ double 'Socket' }
|
6
|
+
subject{ described_class.new socket }
|
7
|
+
let(:codes){ Riak::Client::BeefcakeMessageCodes }
|
8
|
+
|
9
|
+
let(:yz_req){ Riak::Client::BeefcakeProtobuffsBackend::
|
10
|
+
RpbYokozunaSchemaGetReq.new name: 'schema' }
|
11
|
+
let(:ctr_resp){ Riak::Client::BeefcakeProtobuffsBackend::
|
12
|
+
RpbCounterGetResp.new value: rand(2**10) }
|
13
|
+
let(:error_resp){ Riak::Client::BeefcakeProtobuffsBackend::
|
14
|
+
RpbErrorResp.new errcode: rand(2**10), errmsg: 'message' }
|
15
|
+
|
16
|
+
describe 'writing messages' do
|
17
|
+
# I really wanted to call this "send" but Ruby already has that method
|
18
|
+
|
19
|
+
it 'writes messages without a body' do
|
20
|
+
name = :PingReq
|
21
|
+
|
22
|
+
expect(socket).to receive(:write) { |payload|
|
23
|
+
length, code = payload.unpack 'NC'
|
24
|
+
expect(length).to eq 1
|
25
|
+
expect(code).to eq codes.index name
|
26
|
+
}.ordered
|
27
|
+
expect(socket).to receive(:flush).ordered
|
28
|
+
|
29
|
+
subject.write name
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'writes messages with Beefcake::Message instances as bodies' do
|
33
|
+
message = yz_req
|
34
|
+
name = :YokozunaSchemaGetReq
|
35
|
+
|
36
|
+
expect(socket).to receive(:write) { |payload|
|
37
|
+
header = payload[0..4]
|
38
|
+
body = payload[5..-1]
|
39
|
+
length, code = header.unpack 'NC'
|
40
|
+
expect(code).to eq codes.index name
|
41
|
+
expect(length).to eq(body.length + 1)
|
42
|
+
expect(body).to eq message.encode.to_s
|
43
|
+
}.ordered
|
44
|
+
expect(socket).to receive(:flush).ordered
|
45
|
+
|
46
|
+
subject.write name, message
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'raises an error and writes nothing when passed the wrong thing' do
|
50
|
+
expect{ subject.write :YokozunaSchemaGetReq, Object.new }.
|
51
|
+
to raise_error
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'receiving messages' do
|
56
|
+
it 'receives messages without a body and returns an array of code-symbol and nil' do
|
57
|
+
name = :PingResp
|
58
|
+
header = [1, codes.index(name)].pack 'NC'
|
59
|
+
expect(socket).to receive(:read).
|
60
|
+
ordered.
|
61
|
+
with(5).
|
62
|
+
and_return(header)
|
63
|
+
|
64
|
+
code, payload = subject.receive
|
65
|
+
|
66
|
+
expect(code).to eq name
|
67
|
+
expect(payload).to eq nil
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'receives messages and returns an array of code-symbol and string' do
|
71
|
+
message = ctr_resp
|
72
|
+
message_str = message.encode.to_s
|
73
|
+
message_len = message_str.length
|
74
|
+
name = :CounterGetResp
|
75
|
+
header = [message_len + 1, codes.index(name)].pack 'NC'
|
76
|
+
|
77
|
+
expect(socket).to receive(:read).
|
78
|
+
ordered.
|
79
|
+
with(5).
|
80
|
+
and_return(header)
|
81
|
+
expect(socket).to receive(:read).
|
82
|
+
ordered.
|
83
|
+
with(message_len).
|
84
|
+
and_return(message_str)
|
85
|
+
|
86
|
+
code, payload = subject.receive
|
87
|
+
|
88
|
+
expect(code).to eq name
|
89
|
+
expect(payload).to eq message_str
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe 'expecting messages' do
|
94
|
+
describe 'expected message received' do
|
95
|
+
it 'accepts expected messages without a body and returns true' do
|
96
|
+
name = :PingResp
|
97
|
+
header = [1, codes.index(name)].pack 'NC'
|
98
|
+
|
99
|
+
expect(socket).to receive(:read).
|
100
|
+
with(5).
|
101
|
+
and_return(header)
|
102
|
+
|
103
|
+
payload = subject.expect name
|
104
|
+
|
105
|
+
expect(payload).to eq true
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'accepts expected messages and returns a Beefcake::Message instance' do
|
109
|
+
message = ctr_resp
|
110
|
+
message_str = message.encode.to_s
|
111
|
+
message_len = message_str.length
|
112
|
+
name = :CounterGetResp
|
113
|
+
header = [message_len + 1, codes.index(name)].pack 'NC'
|
114
|
+
|
115
|
+
expect(socket).to receive(:read).
|
116
|
+
ordered.
|
117
|
+
with(5).
|
118
|
+
and_return(header)
|
119
|
+
expect(socket).to receive(:read).
|
120
|
+
ordered.
|
121
|
+
with(message_len).
|
122
|
+
and_return(message_str)
|
123
|
+
|
124
|
+
payload = subject.expect name, message.class
|
125
|
+
|
126
|
+
expect(payload).to eq message
|
127
|
+
expect(payload.value).to eq message.value
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'accepts messages with an empty body when required to' do
|
131
|
+
name = :PutResp
|
132
|
+
header = [1, codes.index(name)].pack 'NC'
|
133
|
+
decoder_class = double 'RpbPutResp'
|
134
|
+
|
135
|
+
expect(socket).to receive(:read).
|
136
|
+
with(5).
|
137
|
+
and_return(header)
|
138
|
+
|
139
|
+
payload = subject.expect name, decoder_class, empty_body_acceptable: true
|
140
|
+
|
141
|
+
expect(payload).to eq :empty
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe 'unexpected message received' do
|
146
|
+
it 'raises a ProtobuffsUnexpectedResponse error' do
|
147
|
+
message = ctr_resp
|
148
|
+
message_str = message.encode.to_s
|
149
|
+
message_len = message_str.length
|
150
|
+
name = :CounterGetResp
|
151
|
+
header = [message_len + 1, codes.index(name)].pack 'NC'
|
152
|
+
|
153
|
+
expect(socket).to receive(:read).
|
154
|
+
ordered.
|
155
|
+
with(5).
|
156
|
+
and_return(header)
|
157
|
+
expect(socket).to receive(:read).
|
158
|
+
ordered.
|
159
|
+
with(message_len).
|
160
|
+
and_return(message_str)
|
161
|
+
|
162
|
+
expect{ subject.expect :PingResp }.
|
163
|
+
to raise_error Riak::ProtobuffsUnexpectedResponse
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe 'ErrorResp received' do
|
168
|
+
it 'raises a ProtobuffsErrorResponse error' do
|
169
|
+
message = error_resp
|
170
|
+
message_str = message.encode.to_s
|
171
|
+
message_len = message_str.length
|
172
|
+
name = :ErrorResp
|
173
|
+
header = [message_len + 1, codes.index(name)].pack 'NC'
|
174
|
+
|
175
|
+
expect(socket).to receive(:read).
|
176
|
+
ordered.
|
177
|
+
with(5).
|
178
|
+
and_return(header)
|
179
|
+
expect(socket).to receive(:read).
|
180
|
+
ordered.
|
181
|
+
with(message_len).
|
182
|
+
and_return(message_str)
|
183
|
+
|
184
|
+
expect{ subject.expect :PingResp }.
|
185
|
+
to raise_error Riak::ProtobuffsErrorResponse
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'riak/client/beefcake/socket'
|
3
|
+
|
4
|
+
describe Riak::Client::BeefcakeProtobuffsBackend::BeefcakeSocket do
|
5
|
+
let(:host){ 'host' }
|
6
|
+
let(:pb_port){ 8087 }
|
7
|
+
let(:tcp_socket_instance){ double 'TCPSocket' }
|
8
|
+
|
9
|
+
let(:ssl){ OpenSSL::SSL }
|
10
|
+
|
11
|
+
describe 'without authentication configured' do
|
12
|
+
let(:options){ Hash.new }
|
13
|
+
it 'should start a tcp connection and not start a tls connection' do
|
14
|
+
expect(TCPSocket).to receive(:new).
|
15
|
+
with(host, pb_port).
|
16
|
+
and_return(tcp_socket_instance)
|
17
|
+
|
18
|
+
expect(tcp_socket_instance).to receive(:setsockopt).
|
19
|
+
with(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, true)
|
20
|
+
|
21
|
+
expect(ssl::SSLSocket).not_to receive(:new)
|
22
|
+
|
23
|
+
described_class.new host, pb_port
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'with authentication configured' do
|
28
|
+
let(:user){ 'user' }
|
29
|
+
let(:password){ 'password' }
|
30
|
+
let(:options) do
|
31
|
+
{
|
32
|
+
authentication: {
|
33
|
+
user: user,
|
34
|
+
password: password
|
35
|
+
}
|
36
|
+
}
|
37
|
+
end
|
38
|
+
let(:ssl_socket_instance){ double 'SSLSocket' }
|
39
|
+
let(:ssl_peer_cert){ double 'Peer Certificate' }
|
40
|
+
let(:r509_cert){ double 'R509::Cert' }
|
41
|
+
let(:rcv_instance){ double 'R509::Cert::Validator instance' }
|
42
|
+
|
43
|
+
it 'should start a tcp and a tls connection, and send authentication info' do
|
44
|
+
expect(TCPSocket).to receive(:new).
|
45
|
+
with(host, pb_port).
|
46
|
+
and_return(tcp_socket_instance)
|
47
|
+
|
48
|
+
expect(tcp_socket_instance).to receive(:setsockopt).
|
49
|
+
with(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, true)
|
50
|
+
|
51
|
+
allow(tcp_socket_instance).to receive(:write)
|
52
|
+
|
53
|
+
# StartTls
|
54
|
+
expect(tcp_socket_instance).to receive(:read).
|
55
|
+
with(5).
|
56
|
+
and_return([1, 255].pack 'NC')
|
57
|
+
|
58
|
+
expect(ssl::SSLSocket).to receive(:new).
|
59
|
+
with(tcp_socket_instance, kind_of(OpenSSL::SSL::SSLContext)).
|
60
|
+
and_return(ssl_socket_instance)
|
61
|
+
|
62
|
+
expect(ssl_socket_instance).to receive(:connect)
|
63
|
+
|
64
|
+
allow(ssl_socket_instance).to receive(:write)
|
65
|
+
|
66
|
+
expect(ssl_socket_instance).to receive(:peer_cert).
|
67
|
+
and_return(ssl_peer_cert)
|
68
|
+
expect(R509::Cert).to receive(:new).
|
69
|
+
with(cert: ssl_peer_cert).
|
70
|
+
and_return(r509_cert)
|
71
|
+
allow(r509_cert).to receive(:valid?).and_return(true)
|
72
|
+
expect(R509::Cert::Validator).to receive(:new).
|
73
|
+
with(r509_cert).
|
74
|
+
and_return(rcv_instance)
|
75
|
+
|
76
|
+
expect(rcv_instance).to receive(:validate).
|
77
|
+
with(ocsp: false, crl: false, crl_file: nil).
|
78
|
+
and_return(true)
|
79
|
+
|
80
|
+
# AuthResp
|
81
|
+
expect(ssl_socket_instance).to receive(:read).
|
82
|
+
with(5).
|
83
|
+
and_return([1, 254].pack 'NC')
|
84
|
+
|
85
|
+
# PingResp
|
86
|
+
expect(ssl_socket_instance).to receive(:read).
|
87
|
+
with(5).
|
88
|
+
and_return([1, 2].pack 'NC')
|
89
|
+
|
90
|
+
described_class.new host, pb_port, options
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should pass pass TLS options through to OpenSSL' do
|
94
|
+
options[:authentication][:ca_file] = 'spec/support/certs/ca.crt'
|
95
|
+
options[:authentication][:key] = 'spec/support/certs/client.key'
|
96
|
+
|
97
|
+
expect(TCPSocket).to receive(:new).
|
98
|
+
with(host, pb_port).
|
99
|
+
and_return(tcp_socket_instance)
|
100
|
+
|
101
|
+
expect(tcp_socket_instance).to receive(:setsockopt).
|
102
|
+
with(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, true)
|
103
|
+
|
104
|
+
allow(tcp_socket_instance).to receive(:write)
|
105
|
+
|
106
|
+
# StartTls
|
107
|
+
expect(tcp_socket_instance).to receive(:read).
|
108
|
+
with(5).
|
109
|
+
and_return([1, 255].pack 'NC')
|
110
|
+
|
111
|
+
expect(ssl::SSLSocket).to receive(:new) do |sock, ctx|
|
112
|
+
expect(sock).to eq tcp_socket_instance
|
113
|
+
expect(ctx).to be_a OpenSSL::SSL::SSLContext
|
114
|
+
expect(ctx.key).to be_a OpenSSL::PKey::PKey
|
115
|
+
expect(ctx.ca_file).to eq 'spec/support/certs/ca.crt'
|
116
|
+
|
117
|
+
ssl_socket_instance
|
118
|
+
end
|
119
|
+
|
120
|
+
expect(ssl_socket_instance).to receive(:connect)
|
121
|
+
|
122
|
+
allow(ssl_socket_instance).to receive(:write)
|
123
|
+
|
124
|
+
expect(ssl_socket_instance).to receive(:peer_cert).
|
125
|
+
and_return(ssl_peer_cert)
|
126
|
+
expect(R509::Cert).to receive(:new).
|
127
|
+
with(cert: ssl_peer_cert).
|
128
|
+
and_return(r509_cert)
|
129
|
+
allow(r509_cert).to receive(:valid?).and_return(true)
|
130
|
+
expect(R509::Cert::Validator).to receive(:new).
|
131
|
+
with(r509_cert).
|
132
|
+
and_return(rcv_instance)
|
133
|
+
|
134
|
+
expect(rcv_instance).to receive(:validate).
|
135
|
+
with(ocsp: false, crl: false, crl_file: nil).
|
136
|
+
and_return(true)
|
137
|
+
|
138
|
+
# AuthResp
|
139
|
+
expect(ssl_socket_instance).to receive(:read).
|
140
|
+
with(5).
|
141
|
+
and_return([1, 254].pack 'NC')
|
142
|
+
|
143
|
+
# PingResp
|
144
|
+
expect(ssl_socket_instance).to receive(:read).
|
145
|
+
with(5).
|
146
|
+
and_return([1, 2].pack 'NC')
|
147
|
+
|
148
|
+
described_class.new host, pb_port, options
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -1,72 +1,46 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Riak::Client::BeefcakeProtobuffsBackend do
|
4
|
-
before(:all) { described_class.
|
5
|
-
before(:each) { backend.stub(:get_server_version => "1.2.0") }
|
4
|
+
before(:all) { expect(described_class).to be_configured }
|
6
5
|
let(:client) { Riak::Client.new }
|
7
6
|
let(:node) { client.nodes.first }
|
8
7
|
let(:backend) { Riak::Client::BeefcakeProtobuffsBackend.new(client, node) }
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
backend.stub!(:socket).and_return(mock_socket)
|
15
|
-
mock_socket.should_receive(:write).exactly(1).with do |param|
|
16
|
-
len, code = param[0,5].unpack("NC")
|
17
|
-
req = Riak::Client::BeefcakeProtobuffsBackend::RpbListKeysReq.decode(param[5..-1])
|
18
|
-
code == 17 && req.bucket == exp_bucket
|
19
|
-
end
|
20
|
-
|
21
|
-
responses = Array.new(2) do |index|
|
22
|
-
resp = Riak::Client::BeefcakeProtobuffsBackend::RpbListKeysResp.new
|
23
|
-
if index == 0
|
24
|
-
resp.keys = exp_keys
|
25
|
-
else
|
26
|
-
resp.done = true
|
27
|
-
end
|
28
|
-
resp
|
29
|
-
end
|
30
|
-
|
31
|
-
responses.each do |response|
|
32
|
-
encoded_response = response.encode
|
33
|
-
mock_socket.should_receive(:read).exactly(1).with(5).and_return([1 + encoded_response.length, 18].pack("NC"))
|
34
|
-
mock_socket.should_receive(:read).exactly(1).with(encoded_response.length).and_return(encoded_response)
|
35
|
-
end
|
36
|
-
|
37
|
-
backend.list_keys(exp_bucket).should == exp_keys
|
8
|
+
let(:protocol){ double 'protocol' }
|
9
|
+
before(:each) do
|
10
|
+
allow(backend).to receive(:get_server_version).and_return("2.0.0")
|
11
|
+
allow(backend).to receive(:protocol).and_yield(protocol)
|
38
12
|
end
|
39
13
|
|
40
14
|
context "secondary index" do
|
41
15
|
before :each do
|
42
|
-
@socket =
|
43
|
-
TCPSocket.
|
16
|
+
@socket = double(:socket).as_null_object
|
17
|
+
allow(TCPSocket).to receive(:new).and_return(@socket)
|
44
18
|
end
|
45
19
|
|
46
20
|
it 'should raise an appropriate error when 2i is not available' do
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
expect{ backend.get_index 'bucket', 'words', 'asdf' }.to raise_error "Expected success from Riak but received 0. Secondary indexes aren't supported on the riak_kv_bitcask_backend backend."
|
21
|
+
expect(protocol).to receive(:write)
|
22
|
+
expect(protocol).to receive(:expect).
|
23
|
+
and_raise(
|
24
|
+
Riak::ProtobuffsErrorResponse.
|
25
|
+
new(Riak::Client::BeefcakeProtobuffsBackend::
|
26
|
+
RpbErrorResp.
|
27
|
+
new(errmsg: '{error,{indexes_not_supported,riak_kv_bitcask_backend}}',
|
28
|
+
errcode: 0)
|
29
|
+
)
|
30
|
+
)
|
31
|
+
|
32
|
+
expect{ backend.get_index 'bucket', 'words', 'asdf' }.to raise_error /Secondary indexes aren't supported/
|
60
33
|
# '
|
61
34
|
end
|
62
35
|
|
63
36
|
context 'when streaming' do
|
64
37
|
it "should stream when a block is given" do
|
65
|
-
|
66
|
-
msg.
|
67
|
-
req[:stream].
|
38
|
+
expect(protocol).to receive(:write) do |msg, req|
|
39
|
+
expect(msg).to eq(:IndexReq)
|
40
|
+
expect(req[:stream]).to eq(true)
|
68
41
|
end
|
69
|
-
|
42
|
+
expect(protocol).to receive(:expect).
|
43
|
+
and_return(Riak::Client::BeefcakeProtobuffsBackend::RpbIndexResp.new keys: %w{'asdf'}, done: true)
|
70
44
|
|
71
45
|
blk = proc{:asdf}
|
72
46
|
|
@@ -74,7 +48,7 @@ describe Riak::Client::BeefcakeProtobuffsBackend do
|
|
74
48
|
end
|
75
49
|
|
76
50
|
it "should send batches of results to the block" do
|
77
|
-
|
51
|
+
expect(protocol).to receive(:write)
|
78
52
|
|
79
53
|
response_sets = [%w{asdf asdg asdh}, %w{gggg gggh gggi}]
|
80
54
|
response_messages = response_sets.map do |s|
|
@@ -82,17 +56,11 @@ describe Riak::Client::BeefcakeProtobuffsBackend do
|
|
82
56
|
end
|
83
57
|
response_messages.last.done = true
|
84
58
|
|
85
|
-
|
86
|
-
encoded = m.encode
|
87
|
-
header = [encoded.length + 1, 26].pack 'NC'
|
88
|
-
[header, encoded]
|
89
|
-
end.flatten
|
90
|
-
|
91
|
-
@socket.should_receive(:read).and_return(*response_chunks)
|
59
|
+
expect(protocol).to receive(:expect).and_return(*response_messages)
|
92
60
|
|
93
|
-
block_body =
|
94
|
-
block_body.
|
95
|
-
block_body.
|
61
|
+
block_body = double 'block'
|
62
|
+
expect(block_body).to receive(:check).with(response_sets.first).once
|
63
|
+
expect(block_body).to receive(:check).with(response_sets.last).once
|
96
64
|
|
97
65
|
blk = proc {|m| block_body.check m }
|
98
66
|
|
@@ -101,44 +69,40 @@ describe Riak::Client::BeefcakeProtobuffsBackend do
|
|
101
69
|
end
|
102
70
|
|
103
71
|
it "should return a full batch of results when not streaming" do
|
104
|
-
|
105
|
-
msg.
|
106
|
-
req[:stream].
|
72
|
+
expect(protocol).to receive(:write) do |msg, req|
|
73
|
+
expect(msg).to eq(:IndexReq)
|
74
|
+
expect(req[:stream]).not_to be
|
107
75
|
end
|
108
76
|
|
109
77
|
response_message = Riak::Client::BeefcakeProtobuffsBackend::
|
110
78
|
RpbIndexResp.new(
|
111
79
|
keys: %w{asdf asdg asdh}
|
112
|
-
)
|
113
|
-
|
114
|
-
|
80
|
+
)
|
81
|
+
expect(protocol).to receive(:expect).
|
82
|
+
and_return(response_message)
|
115
83
|
|
116
84
|
results = backend.get_index 'bucket', 'words', 'asdf'..'hjkl'
|
117
|
-
results.
|
85
|
+
expect(results).to eq(%w{asdf asdg asdh})
|
118
86
|
end
|
119
87
|
|
120
88
|
it "should not crash out when no keys or terms are returned" do
|
121
|
-
|
122
|
-
msg.
|
123
|
-
req[:stream].
|
89
|
+
expect(protocol).to receive(:write) do |msg, req|
|
90
|
+
expect(msg).to eq(:IndexReq)
|
91
|
+
expect(req[:stream]).not_to be
|
124
92
|
end
|
125
93
|
|
126
94
|
response_message = Riak::Client::BeefcakeProtobuffsBackend::
|
127
|
-
RpbIndexResp.new()
|
95
|
+
RpbIndexResp.new()
|
128
96
|
|
129
|
-
|
130
|
-
@socket.
|
131
|
-
should_receive(:read).
|
132
|
-
with(5).
|
133
|
-
and_return(header)
|
97
|
+
expect(protocol).to receive(:expect).and_return(response_message)
|
134
98
|
|
135
99
|
results = nil
|
136
100
|
fetch = proc do
|
137
101
|
results = backend.get_index 'bucket', 'words', 'asdf'
|
138
102
|
end
|
139
103
|
|
140
|
-
fetch.
|
141
|
-
results.
|
104
|
+
expect(fetch).not_to raise_error
|
105
|
+
expect(results).to eq([])
|
142
106
|
end
|
143
107
|
end
|
144
108
|
|
@@ -146,20 +110,24 @@ describe Riak::Client::BeefcakeProtobuffsBackend do
|
|
146
110
|
let(:mapred) { Riak::MapReduce.new(client).add('test').map("function(){}").map("function(){}") }
|
147
111
|
|
148
112
|
it "should not return nil for previous phases that don't return anything" do
|
149
|
-
|
150
|
-
|
151
|
-
message =
|
152
|
-
message.
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
113
|
+
expect(protocol).to receive(:write)
|
114
|
+
|
115
|
+
message = double(:message, :phase => 1, :response => [{}].to_json)
|
116
|
+
allow(message).to receive(:done).and_return(false, true)
|
117
|
+
|
118
|
+
expect(protocol).to receive(:expect).
|
119
|
+
twice.
|
120
|
+
and_return(message)
|
121
|
+
|
122
|
+
expect(backend.mapred(mapred)).to eq([{}])
|
158
123
|
end
|
159
124
|
end
|
160
125
|
|
161
126
|
context "preventing stale writes" do
|
162
|
-
before
|
127
|
+
before do
|
128
|
+
allow(backend).to receive(:decode_response).and_return(nil)
|
129
|
+
allow(backend).to receive(:get_server_version).and_return("1.0.3")
|
130
|
+
end
|
163
131
|
|
164
132
|
let(:robject) do
|
165
133
|
Riak::RObject.new(client['stale'], 'prevent').tap do |obj|
|
@@ -170,31 +138,25 @@ describe Riak::Client::BeefcakeProtobuffsBackend do
|
|
170
138
|
end
|
171
139
|
|
172
140
|
it "should set the if_none_match field when the object is new" do
|
173
|
-
|
174
|
-
msg.
|
175
|
-
req.if_none_match.
|
141
|
+
expect(protocol).to receive(:write) do |msg, req|
|
142
|
+
expect(msg).to eq(:PutReq)
|
143
|
+
expect(req.if_none_match).to be_truthy
|
176
144
|
end
|
145
|
+
expect(protocol).to receive(:expect).
|
146
|
+
and_return(:empty)
|
147
|
+
|
177
148
|
backend.store_object(robject)
|
178
149
|
end
|
179
150
|
|
180
151
|
it "should set the if_not_modified field when the object has a vclock" do
|
181
152
|
robject.vclock = Base64.encode64("foo")
|
182
|
-
|
183
|
-
msg.
|
184
|
-
req.if_not_modified.
|
153
|
+
expect(protocol).to receive(:write) do |msg, req|
|
154
|
+
expect(msg).to eq(:PutReq)
|
155
|
+
expect(req.if_not_modified).to be_truthy
|
185
156
|
end
|
157
|
+
expect(protocol).to receive(:expect).
|
158
|
+
and_return(:empty)
|
186
159
|
backend.store_object(robject)
|
187
160
|
end
|
188
|
-
|
189
|
-
context "when conditional requests are not supported" do
|
190
|
-
before { backend.stub(:get_server_version => "0.14.2") }
|
191
|
-
let(:other) { robject.dup.tap {|o| o.vclock = 'bar' } }
|
192
|
-
|
193
|
-
it "should fetch the original object and raise if not equivalent" do
|
194
|
-
robject.vclock = Base64.encode64("foo")
|
195
|
-
backend.should_receive(:fetch_object).and_return(other)
|
196
|
-
expect { backend.store_object(robject) }.to raise_error(Riak::FailedRequest)
|
197
|
-
end
|
198
|
-
end
|
199
161
|
end
|
200
162
|
end
|