right_support 2.6.17 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +4 -0
- data/CHANGELOG.rdoc +37 -0
- data/Gemfile +29 -0
- data/Gemfile.lock +111 -0
- data/README.rdoc +2 -0
- data/Rakefile +62 -0
- data/VERSION +1 -0
- data/features/balancer_error_handling.feature +34 -0
- data/features/balancer_health_check.feature +33 -0
- data/features/continuous_integration.feature +51 -0
- data/features/continuous_integration_cucumber.feature +28 -0
- data/features/continuous_integration_rspec1.feature +28 -0
- data/features/continuous_integration_rspec2.feature +28 -0
- data/features/http_client_timeout.feature +19 -0
- data/features/serialization.feature +95 -0
- data/features/step_definitions/http_client_steps.rb +27 -0
- data/features/step_definitions/request_balancer_steps.rb +93 -0
- data/features/step_definitions/ruby_steps.rb +176 -0
- data/features/step_definitions/serialization_steps.rb +96 -0
- data/features/step_definitions/server_steps.rb +134 -0
- data/features/support/env.rb +138 -0
- data/features/support/file_utils_bundler_mixin.rb +45 -0
- data/lib/right_support/ci/java_cucumber_formatter.rb +22 -8
- data/lib/right_support/ci/java_spec_formatter.rb +26 -8
- data/lib/right_support/ci/rake_task.rb +3 -0
- data/lib/right_support/ci.rb +24 -0
- data/lib/right_support/crypto/signed_hash.rb +22 -0
- data/lib/right_support/data/serializer.rb +24 -2
- data/lib/right_support/net/address_helper.rb +20 -8
- data/lib/right_support/net/dns.rb +20 -8
- data/lib/right_support/net/http_client.rb +22 -0
- data/lib/right_support/net/request_balancer.rb +27 -21
- data/lib/right_support/net/s3_helper.rb +20 -8
- data/lib/right_support/net/ssl/open_ssl_patch.rb +22 -0
- data/lib/right_support/net/ssl.rb +20 -8
- data/lib/right_support/ruby/easy_singleton.rb +22 -0
- data/lib/right_support/ruby/object_extensions.rb +22 -0
- data/lib/right_support/ruby/string_extensions.rb +1 -1
- data/lib/right_support.rb +13 -10
- data/right_support.gemspec +180 -18
- data/right_support.rconf +8 -0
- data/spec/config/feature_set_spec.rb +83 -0
- data/spec/crypto/signed_hash_spec.rb +60 -0
- data/spec/data/hash_tools_spec.rb +471 -0
- data/spec/data/uuid_spec.rb +45 -0
- data/spec/db/cassandra_model_part1_spec.rb +84 -0
- data/spec/db/cassandra_model_part2_spec.rb +73 -0
- data/spec/db/cassandra_model_spec.rb +359 -0
- data/spec/fixtures/encrypted_priv_rsa.pem +30 -0
- data/spec/fixtures/good_priv_dsa.pem +12 -0
- data/spec/fixtures/good_priv_rsa.pem +15 -0
- data/spec/fixtures/good_pub_dsa.ssh +1 -0
- data/spec/fixtures/good_pub_rsa.pem +5 -0
- data/spec/fixtures/good_pub_rsa.ssh +1 -0
- data/spec/log/exception_logger_spec.rb +76 -0
- data/spec/log/filter_logger_spec.rb +8 -0
- data/spec/log/mixin_spec.rb +62 -0
- data/spec/log/multiplexer_spec.rb +54 -0
- data/spec/log/null_logger_spec.rb +36 -0
- data/spec/log/system_logger_spec.rb +92 -0
- data/spec/net/address_helper_spec.rb +57 -0
- data/spec/net/balancing/health_check_spec.rb +382 -0
- data/spec/net/balancing/round_robin_spec.rb +15 -0
- data/spec/net/balancing/sticky_policy_spec.rb +92 -0
- data/spec/net/dns_spec.rb +152 -0
- data/spec/net/http_client_spec.rb +171 -0
- data/spec/net/request_balancer_spec.rb +579 -0
- data/spec/net/s3_helper_spec.rb +160 -0
- data/spec/net/ssl_spec.rb +42 -0
- data/spec/net/string_encoder_spec.rb +58 -0
- data/spec/rack/log_setter_spec.rb +5 -0
- data/spec/rack/request_logger_spec.rb +68 -0
- data/spec/rack/request_tracker_spec.rb +5 -0
- data/spec/ruby/easy_singleton_spec.rb +72 -0
- data/spec/ruby/object_extensions_spec.rb +27 -0
- data/spec/ruby/string_extensions_spec.rb +98 -0
- data/spec/spec_helper.rb +181 -0
- data/spec/stats/activity_spec.rb +193 -0
- data/spec/stats/exceptions_spec.rb +123 -0
- data/spec/stats/helpers_spec.rb +603 -0
- data/spec/validation/openssl_spec.rb +37 -0
- data/spec/validation/ssh_spec.rb +39 -0
- metadata +218 -19
@@ -0,0 +1,359 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RightSupport::DB::CassandraModel do
|
4
|
+
|
5
|
+
class Cassandra
|
6
|
+
class OrderedHash < Hash
|
7
|
+
def keys
|
8
|
+
super.sort
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def init_app_state(column_family,keyspace,server,env)
|
14
|
+
ENV["RACK_ENV"] = env
|
15
|
+
RightSupport::DB::CassandraModel.column_family = column_family
|
16
|
+
RightSupport::DB::CassandraModel.keyspace = keyspace
|
17
|
+
RightSupport::DB::CassandraModel.config = {"#{env}" => {"server" => server}}
|
18
|
+
end
|
19
|
+
|
20
|
+
context "initialization" do
|
21
|
+
# This method determines the current keyspace based on the return value of the CassandraModel.keyspace method
|
22
|
+
# which looks at the value of @@current_keyspace or @@default_keyspace to determine the keyspace it is operating
|
23
|
+
# under. If a connection already exists for the keyspace it will re-use it. If a connection does not exist,
|
24
|
+
# it will create a new persistent connection for that keyspace that can be re-used with future requests
|
25
|
+
context :conn do
|
26
|
+
let(:column_family) { 'column_family' }
|
27
|
+
let(:env) { 'test' }
|
28
|
+
let(:server) { 'localhost:9160' }
|
29
|
+
let(:keyspace) { 'SatelliteService_1' }
|
30
|
+
let(:default_keyspace) { 'SatelliteService' }
|
31
|
+
let(:current_keyspace_connection) { flexmock('cassandra') }
|
32
|
+
let(:default_keyspace_connection) { flexmock('cassandra') }
|
33
|
+
|
34
|
+
before(:each) do
|
35
|
+
ENV["RACK_ENV"] = env
|
36
|
+
RightSupport::DB::CassandraModel.column_family = column_family
|
37
|
+
RightSupport::DB::CassandraModel.keyspace = default_keyspace
|
38
|
+
RightSupport::DB::CassandraModel.config = {env => {"server" => server}}
|
39
|
+
|
40
|
+
current_keyspace_connection.should_receive(:disable_node_auto_discovery!).and_return(true)
|
41
|
+
current_keyspace_connection.should_receive(:name).and_return('connection1')
|
42
|
+
|
43
|
+
default_keyspace_connection.should_receive(:disable_node_auto_discovery!).and_return(true)
|
44
|
+
default_keyspace_connection.should_receive(:name).and_return('connection2')
|
45
|
+
|
46
|
+
flexmock(Cassandra).should_receive(:new).with(keyspace + '_' + (ENV['RACK_ENV'] || 'development'), "localhost:9160", {:timeout=>10}).and_return(current_keyspace_connection)
|
47
|
+
flexmock(Cassandra).should_receive(:new).with(default_keyspace + '_' + (ENV['RACK_ENV'] || 'development'), "localhost:9160", {:timeout=>10}).and_return(default_keyspace_connection)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'raises a meaningful exception when a config stanza is missing' do
|
51
|
+
old_rack_env = ENV['RACK_ENV']
|
52
|
+
|
53
|
+
begin
|
54
|
+
ENV['RACK_ENV'] = 'foobar_12345'
|
55
|
+
bad_proc = lambda { RightSupport::DB::CassandraModel.reconnect }
|
56
|
+
bad_proc.should raise_error(RightSupport::DB::MissingConfiguration)
|
57
|
+
# This must be the very first attempt to call #conn during the execution of this spec
|
58
|
+
bad_proc = lambda { RightSupport::DB::CassandraModel.conn }
|
59
|
+
bad_proc.should raise_error(RightSupport::DB::MissingConfiguration)
|
60
|
+
ensure
|
61
|
+
ENV['RACK_ENV'] = old_rack_env
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# This method assumes that keyspaces being requested to connect to already exist.
|
66
|
+
# If they do not exist, it should NOT create them. If the connection is able
|
67
|
+
# to be successfully established then it should be stored in a pool of connections
|
68
|
+
it 'creates a new connection if no connection exists for provided keyspace' do
|
69
|
+
RightSupport::DB::CassandraModel.conn.name.should == default_keyspace_connection.name
|
70
|
+
end
|
71
|
+
|
72
|
+
# If a connection has already been opened for a keyspace it should be re-used
|
73
|
+
it 're-uses an existing connection if it exists for provided keyspace' do
|
74
|
+
RightSupport::DB::CassandraModel.conn.name.should == RightSupport::DB::CassandraModel.conn.name
|
75
|
+
end
|
76
|
+
|
77
|
+
# The keyspace being used for the connection should be either the current keyspace or the default keyspace
|
78
|
+
it 'uses the connection that corresponds to the provided keyspace' do
|
79
|
+
RightSupport::DB::CassandraModel.with_keyspace(keyspace) do
|
80
|
+
RightSupport::DB::CassandraModel.conn.name.should == current_keyspace_connection.name
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context "use" do
|
87
|
+
|
88
|
+
before(:each) do
|
89
|
+
@column_family = "TestApp"
|
90
|
+
@keyspace = "TestAppService"
|
91
|
+
@server = "localhost:9160"
|
92
|
+
@env = "test"
|
93
|
+
@timeout = {:timeout => RightSupport::DB::CassandraModel::DEFAULT_TIMEOUT}
|
94
|
+
|
95
|
+
init_app_state(@column_family, @keyspace, @server, @env)
|
96
|
+
|
97
|
+
@key = 'key'
|
98
|
+
@value = 'foo'
|
99
|
+
@offset = 'bar'
|
100
|
+
@attrs = {@offset => @value}
|
101
|
+
@opt = {}
|
102
|
+
@get_opt = {:count => RightSupport::DB::CassandraModel::DEFAULT_COUNT}
|
103
|
+
|
104
|
+
@instance = RightSupport::DB::CassandraModel.new(@key, @attrs)
|
105
|
+
|
106
|
+
@conn = flexmock(:connection)
|
107
|
+
flexmock(RightSupport::DB::CassandraModel).should_receive(:conn).and_return(@conn)
|
108
|
+
@conn.should_receive(:insert).with(@column_family, @key, @attrs,@opt).and_return(true)
|
109
|
+
@conn.should_receive(:remove).with(@column_family, @key).and_return(true)
|
110
|
+
@conn.should_receive(:get).with(@column_family, @key, @get_opt).and_return(@attrs).by_default
|
111
|
+
@conn.should_receive(:multi_get).with(@column_family, [1,2], @opt).and_return(Hash.new)
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "instance methods" do
|
115
|
+
context :save do
|
116
|
+
it 'saves the row' do
|
117
|
+
@instance.save.should be_true
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context :destroy do
|
122
|
+
it 'destroys the row' do
|
123
|
+
@instance.destroy.should be_true
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context :reload do
|
128
|
+
it 'returns a new object for the row' do
|
129
|
+
@instance.reload.should be_a_kind_of(RightSupport::DB::CassandraModel)
|
130
|
+
@instance.reload!.should be_a_kind_of(RightSupport::DB::CassandraModel)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "class methods" do
|
136
|
+
# We want to remain backward-compatible for existing services so we expect this call to be made
|
137
|
+
# as such: RightSupport::DB::CassandraModel.keyspace = "SatelliteService" and CassandraModel
|
138
|
+
# will append the RACK_ENV to the end of it. Ex: "SatelliteService_development"
|
139
|
+
context :keyspace= do
|
140
|
+
let(:keyspace) { 'SatelliteService' }
|
141
|
+
|
142
|
+
it 'appends the environment to the keyspace provided' do
|
143
|
+
RightSupport::DB::CassandraModel.keyspace = keyspace
|
144
|
+
RightSupport::DB::CassandraModel.send(:class_variable_get, :@@default_keyspace).should == (keyspace + "_" + (ENV['RACK_ENV'] || 'development'))
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# If a current keyspace is provided it takes precedence over the default keyspace. If none is
|
149
|
+
# provided, the default keyspace should be returned.
|
150
|
+
context :keyspace do
|
151
|
+
let(:keyspace) { 'SatelliteService_' + ENV['RACK_ENV'] }
|
152
|
+
|
153
|
+
it 'returns the default keyspace if no current keyspace is set' do
|
154
|
+
RightSupport::DB::CassandraModel.send(:class_variable_set, :@@current_keyspace, nil)
|
155
|
+
RightSupport::DB::CassandraModel.send(:class_variable_set, :@@default_keyspace, keyspace)
|
156
|
+
RightSupport::DB::CassandraModel.keyspace.should == keyspace
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'returns the current keyspace if a current keyspace is set' do
|
160
|
+
RightSupport::DB::CassandraModel.send(:class_variable_set, :@@current_keyspace, keyspace)
|
161
|
+
RightSupport::DB::CassandraModel.send(:class_variable_set, :@@default_keyspace, nil)
|
162
|
+
RightSupport::DB::CassandraModel.keyspace.should == keyspace
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# This method assumes that a valid keyspace is passed in. If the keyspace does not exist we do NOT
|
167
|
+
# want to create it. CassandraModel should use the keyspace provided for the duration of the code
|
168
|
+
# executed within the block. Any requests processed outside of the block should execute using the
|
169
|
+
# default keyspace.
|
170
|
+
context :with_keyspace do
|
171
|
+
let(:keyspace) { 'SatelliteService_1' }
|
172
|
+
let(:default_keyspace) { 'SatelliteService' }
|
173
|
+
|
174
|
+
before(:each) do
|
175
|
+
RightSupport::DB::CassandraModel.keyspace = default_keyspace
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'sets the current keyspace to the keyspace provided for execution within the block' do
|
179
|
+
RightSupport::DB::CassandraModel.with_keyspace(keyspace) do
|
180
|
+
RightSupport::DB::CassandraModel.keyspace.should == keyspace + "_" + 'test'
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'resets back to the default keyspace for execution outside of the block' do
|
185
|
+
RightSupport::DB::CassandraModel.with_keyspace(keyspace) {}
|
186
|
+
RightSupport::DB::CassandraModel.keyspace.should == default_keyspace + "_" + 'test'
|
187
|
+
end
|
188
|
+
context 'append_env parameter' do
|
189
|
+
it 'appends the environment by default' do
|
190
|
+
RightSupport::DB::CassandraModel.with_keyspace('Monkey') do
|
191
|
+
RightSupport::DB::CassandraModel.keyspace.should == 'Monkey_test'
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'appends the environment when append_env == true' do
|
196
|
+
RightSupport::DB::CassandraModel.with_keyspace('Monkey', true) do
|
197
|
+
RightSupport::DB::CassandraModel.keyspace.should == 'Monkey_test'
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'does NOT append the environment when append_env == false' do
|
202
|
+
RightSupport::DB::CassandraModel.with_keyspace('Monkey_notatest', false) do
|
203
|
+
RightSupport::DB::CassandraModel.keyspace.should == 'Monkey_notatest'
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'avoids double-appending the environment' do
|
208
|
+
RightSupport::DB::CassandraModel.with_keyspace('Monkey_test') do
|
209
|
+
RightSupport::DB::CassandraModel.keyspace.should == 'Monkey_test'
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
context :insert do
|
216
|
+
it 'inserts a row by using the class method' do
|
217
|
+
RightSupport::DB::CassandraModel.insert(@key, @attrs, @opt).should be_true
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
context :remove do
|
222
|
+
it 'removes a row by using the class method' do
|
223
|
+
RightSupport::DB::CassandraModel.remove(@key).should be_true
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
context :all do
|
228
|
+
it 'returns all existing rows for the specified array of keys' do
|
229
|
+
RightSupport::DB::CassandraModel.all([1, 2]).should be_a_kind_of(Hash)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
context :get do
|
234
|
+
it 'returns row for the specified key' do
|
235
|
+
RightSupport::DB::CassandraModel.get(@key).should be_a_kind_of(RightSupport::DB::CassandraModel)
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'returns only number of columns requested' do
|
239
|
+
attrs = {@offset + '1' => @value, @offset + '2' => @value}
|
240
|
+
get_opt = {:count => 2}
|
241
|
+
@conn.should_receive(:get).with(@column_family, @key, get_opt).and_return(attrs).once
|
242
|
+
RightSupport::DB::CassandraModel.get(@key, get_opt).attributes.should == attrs
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'returns all columns for the specified key if no count specified' do
|
246
|
+
pending "Unpredictable behavior on ruby < 1.9" unless RUBY_VERSION >= "1.9"
|
247
|
+
default_count = RightSupport::DB::CassandraModel::DEFAULT_COUNT
|
248
|
+
|
249
|
+
RightSupport::DB::CassandraModel.instance_eval { remove_const :DEFAULT_COUNT }
|
250
|
+
RightSupport::DB::CassandraModel.const_set(:DEFAULT_COUNT, 2)
|
251
|
+
begin
|
252
|
+
|
253
|
+
attrs1 = {@offset + '1' => @value, @offset + '2' => @value}
|
254
|
+
attrs2 = {@offset + '3' => @value}
|
255
|
+
attrs = attrs1.merge(attrs2)
|
256
|
+
get_opt1 = {:count => 2}
|
257
|
+
get_opt2 = {:count => 2, :start => @offset + '2'}
|
258
|
+
@conn.should_receive(:get).with(@column_family, @key, get_opt1).and_return(attrs1).once
|
259
|
+
@conn.should_receive(:get).with(@column_family, @key, get_opt2).and_return(attrs2).once
|
260
|
+
RightSupport::DB::CassandraModel.get(@key).attributes.should == attrs
|
261
|
+
ensure
|
262
|
+
RightSupport::DB::CassandraModel.instance_eval { remove_const :DEFAULT_COUNT }
|
263
|
+
RightSupport::DB::CassandraModel.const_set(:DEFAULT_COUNT, default_count)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
it 'returns nil if key not found' do
|
268
|
+
@conn.should_receive(:get).with(@column_family, @key, @get_opt).and_return({})
|
269
|
+
RightSupport::DB::CassandraModel.get(@key).should be_nil
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
def real_get_indexed(index, key, columns = nil, opt = {})
|
274
|
+
rows = {}
|
275
|
+
start = ""
|
276
|
+
count = DEFAULT_COUNT
|
277
|
+
expr = do_op(:create_idx_expr, index, key, "EQ")
|
278
|
+
opt = opt[:consistency] ? {:consistency => opt[:consistency]} : {}
|
279
|
+
while true
|
280
|
+
clause = do_op(:create_idx_clause, [expr], start, count)
|
281
|
+
chunk = do_op(:get_indexed_slices, column_family, clause, columns, opt)
|
282
|
+
rows.merge!(chunk)
|
283
|
+
if chunk.size == count
|
284
|
+
# Assume there are more chunks, use last key as start of next get
|
285
|
+
start = chunk.keys.last
|
286
|
+
else
|
287
|
+
# This must be the last chunk
|
288
|
+
break
|
289
|
+
end
|
290
|
+
end
|
291
|
+
rows
|
292
|
+
end
|
293
|
+
|
294
|
+
context :get_indexed do
|
295
|
+
|
296
|
+
before(:each) do
|
297
|
+
@column = flexmock(:column, :name => 'foo', :value => 'bar')
|
298
|
+
@column_or_super = flexmock(:column_or_super, :column => @column)
|
299
|
+
@rows = {@key => [@column_or_super]}
|
300
|
+
@index = 'index'
|
301
|
+
@index_key = 'index_key'
|
302
|
+
@start = ""
|
303
|
+
@count = RightSupport::DB::CassandraModel::DEFAULT_COUNT
|
304
|
+
@expr = flexmock(:expr)
|
305
|
+
@conn.should_receive(:create_idx_expr).and_return(@expr)
|
306
|
+
@clause = flexmock(:clause)
|
307
|
+
@conn.should_receive(:create_idx_clause).with([@expr], @start, @count).and_return(@clause).by_default
|
308
|
+
@conn.should_receive(:get_indexed_slices).with(@column_family, @clause, nil, {}).and_return(@rows).by_default
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'returns row for the specified key' do
|
312
|
+
rows = RightSupport::DB::CassandraModel.get_indexed(@index, @index_key)
|
313
|
+
rows.should be_a_kind_of(Array)
|
314
|
+
rows.size.should == 1
|
315
|
+
rows.first.should be_a_kind_of(RightSupport::DB::CassandraModel)
|
316
|
+
end
|
317
|
+
|
318
|
+
it 'returns all rows for the specified key if no count specified' do
|
319
|
+
pending "Unpredictable behavior on ruby < 1.9" unless RUBY_VERSION >= "1.9"
|
320
|
+
|
321
|
+
default_count = RightSupport::DB::CassandraModel::DEFAULT_COUNT
|
322
|
+
|
323
|
+
RightSupport::DB::CassandraModel.instance_eval { remove_const :DEFAULT_COUNT }
|
324
|
+
RightSupport::DB::CassandraModel.const_set(:DEFAULT_COUNT, 2)
|
325
|
+
begin
|
326
|
+
key1 = @key + '8'
|
327
|
+
key2 = @key + '12'
|
328
|
+
key3 = @key + '13'
|
329
|
+
cols = {'foo' => 'bar'}
|
330
|
+
rows1 = {key1 => [@column_or_super], key2 => [@column_or_super]}
|
331
|
+
rows2 = {key3 => [@column_or_super]}
|
332
|
+
@conn.should_receive(:create_idx_clause).with([@expr], @start, 2).and_return(@clause).once
|
333
|
+
@conn.should_receive(:get_indexed_slices).with(@column_family, @clause, nil, {}).and_return(rows1).once
|
334
|
+
@conn.should_receive(:create_idx_clause).with([@expr], key2, 2).and_return(@clause).once
|
335
|
+
@conn.should_receive(:get_indexed_slices).with(@column_family, @clause, nil, {}).and_return(rows2).once
|
336
|
+
rows = RightSupport::DB::CassandraModel.get_indexed(@index, @index_key)
|
337
|
+
rows.size.should == 3
|
338
|
+
rows.inject({}) { |s, r| s[r.key] = r.attributes; s }.should == {key1 => cols, key2 => cols, key3 => cols}
|
339
|
+
ensure
|
340
|
+
RightSupport::DB::CassandraModel.instance_eval { remove_const :DEFAULT_COUNT }
|
341
|
+
RightSupport::DB::CassandraModel.const_set(:DEFAULT_COUNT, default_count)
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
it 'returns empty array if no rows found for key' do
|
346
|
+
@conn.should_receive(:get_indexed_slices).with(@column_family, @clause, nil, {}).and_return({}).once
|
347
|
+
RightSupport::DB::CassandraModel.get_indexed(@index, @index_key).should == []
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
context '.calculate_random_partitioner_token' do
|
354
|
+
it 'works' do
|
355
|
+
expected = 73001115008341200964825964898370608784
|
356
|
+
described_class.calculate_random_partitioner_token('71:foomonkeys').should == expected
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
Proc-Type: 4,ENCRYPTED
|
3
|
+
DEK-Info: DES-EDE3-CBC,61C0BBB816A708D4
|
4
|
+
|
5
|
+
SQ/Y+U7z51OL/hx4YnfVPl6uqsOjpSjU2w4NFqB6EyBtMFgOoqW6ryuIi6ycHgWJ
|
6
|
+
YabUlMPdnexU+1BGqu9P2M9kQejfVddBFmbE09s54dwamk7q6RjaARN0UvHq6Ms9
|
7
|
+
r5/nqRBrinWtOeU/+7cV5qGp2/HbWC2bHAUCCwBcq+ymEpLOw/dpHpxjuiB5ZOLt
|
8
|
+
QzcEJ8ePlNDYvPxw4Wjvb5IDjS4MSoJfA5Y2ZXwVSI1d7mhx4Cekx3CkTMWKYIU8
|
9
|
+
FS6hO39tfPTcxb4os3FYl8D8TlRHv5atrsptKqYE4DKhZhoDA5yFbFJHZlEp+G6H
|
10
|
+
t+snMyuzEWNWq3wGI/gaglatUMq6airA50qticbw8kvz+67pPh2gkAgMXBHEGgPW
|
11
|
+
m0xnqaWf+MyQCUfaxjvxAq68Ced+H9ULLYFrzWAIuSh1M+QartuvP1ZOIcDpY83i
|
12
|
+
RybTJC5MLgGE0COM7oOtPfXO/rvdf6jqTr54HhYwq18aWrqjnacZi0JzNEFRtpNa
|
13
|
+
5FNbwbQGT4Y8J1rOgbyjrd712oRhfjMAU39w4b6gEIATB4zDnMVkdb/Rde/nB7i4
|
14
|
+
CqDB9iSEbtQN4Ev5fXpIDrmhbdT/CURpzRvIt68x08qvX8KQwqDbLz39luocApxN
|
15
|
+
lnTihGiYAiNflMpDvhNL8MSLxYgL5Or2KVF/Ppc+1Qw23BEYDlaRRzc71PWdrVr8
|
16
|
+
UxEdFtqQnnthO7PabrwmLiPeArIGL4U8wrbXA3GbkbDtClftWMaC9JrzVJvXp1z7
|
17
|
+
sXZPhdZzSCg3n3ZbAGKYUx/G8AHojLKfAF3BHufnU9qM+6TS/KtTnhrvHSgYPcBn
|
18
|
+
etI7DWZ/mUnLwnsWfiQ3n5PeeUq/nU+IFJT+Y3r+TfFVCiGPW60XpfLzH1U4otKq
|
19
|
+
KaEnCQX6S7p1Jinx+FHL9fg1I50E6QUNO+N8XO4ay3Jzumz2yjZeudyt+uy954Hq
|
20
|
+
RfmDGYImqrkYrzd8d6hNUTBGnUfUTvq2k/orKhvcxtX+tr9WhNshnJcK18SgBRKT
|
21
|
+
6XLybyioikVSpUGsL95kIhrspryO8v7/M1igWWrLu9fe/jUJLCFzlbGSRYDn+QTp
|
22
|
+
z7qpbBvxHPgu1fKurZ96nCcigVxQgY5rPwpQvG+mkD6YOhgDvSAjTos7Fagz6nb6
|
23
|
+
01MufCVvFx+BBZEsol0Ag23RhXeJXvxkcF//hcPseCA/oB9Aqzyu+ml9mgp4v6P+
|
24
|
+
AgVopgGCfZR31CQ2b9AxdSARFCj2AFE9AdeNy268KSx8wLWAlzUcnGi57eK8WJM3
|
25
|
+
KTDOwJZDgZkjYyMZATpxOj8w3euAflQjQmyXpN1/Q0BW66Mj9+XzVk2yEpF2S0iE
|
26
|
+
xKzPcNEzlGMo1xo6mqVE/kIuRSodXuGp5Eoo8ITvpYWcSdtCTSKJNxAUqry/k9bg
|
27
|
+
9sf3jSmSHzUd92pdM02p8A42HcaPGLmbuFjIfZPK7KoYmIdhJqy7s08CFUlk9XI/
|
28
|
+
PxdYph5J4WkAbeomPGUTFxEWV1cM2lvW4hotrx8MS50WLVZxxY1p7D+JxN3KeJyc
|
29
|
+
mytYpg2dxr8UF64NFKuyEmunkDTdYH2Oi7B7mAcw/QlBN+qCARP+tA==
|
30
|
+
-----END RSA PRIVATE KEY-----
|
@@ -0,0 +1,12 @@
|
|
1
|
+
-----BEGIN DSA PRIVATE KEY-----
|
2
|
+
MIIBvAIBAAKBgQC1RlSYmT8VVtunF3xcpSdJfihaHAGzLH0nf2ooHcKIH6PyxjCe
|
3
|
+
Q93rFB69uyGPUJVawz3w0Y1B7B6h5eXI4SEKA4iqmSHXdFonO7wvOT5DTkzQl3yX
|
4
|
+
B1s4xU8+GW1MtUNKxHPzFpX40797Z1enO/EZRNLYt0P4IG86s/O+BqD6IwIVAJ24
|
5
|
+
m8A6ZFqsunyy2L5o9UInE+gfAoGAPuEeCrIginLFwSdwyrxEwC/gblKvOf/9+iMB
|
6
|
+
Jo+5fN2E9AHKrCsCa53E2lnUbXOdSKDR6yVmUQSB3EsBDoLqDOVJh/BWVTABebIO
|
7
|
+
WwnjQZX9UBGnsJwD4zpvtXLU4qnyFywSr1kdLDHMsGS3WVocJ9jOEH7Rh0xMM423
|
8
|
+
yYS4bUQCgYEApxLO5sTQS/Ej8+BFJQrMS3xHpONQxiMnTLE3q6qZXJRgHDgsqqwZ
|
9
|
+
pAfZCjRxvvfUfBGzjKwJlGQOLZVaGZOArGQF7NRtOfCHZtMBg1vubewXs64gmH5G
|
10
|
+
aXvJ17D6W2vCO04R/vXh43qKLDcPu7wGng+eWNaw/LkbdfC4k8uVfp4CFQCHe0yn
|
11
|
+
rgxFphSFqf8Spchmsg/coA==
|
12
|
+
-----END DSA PRIVATE KEY-----
|
@@ -0,0 +1,15 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIICWwIBAAKBgQDm4VY+mDoYUsH+7idaNXP6Bq+YIXwqGNar6zgbPEe6qgpF9nSQ
|
3
|
+
B98gMObcZ9H7qGm3e/bQTCrlBAB/jMUQQbTyPsEy3pIKeWoPl7GTQpcSS9WZoHYX
|
4
|
+
yf4TN8MMOeJ3rGbyGb8Xm13R+SBpOMOZfnT3KUJLznIYVtBvv+uFz/C9ewIDAQAB
|
5
|
+
AoGAMJzLkvxsZwitziaI5KaSl9dmi4qpYRe/w40QUDO+CqCY7yg4XMc7hMSnJ0s4
|
6
|
+
3FsWf0q7qhoPgg74p+KU75pWJbEHoYor6LqDuxov4DSx/2SfqmDBIAb9IQ4KWDr2
|
7
|
+
WU/o2/ivbHJ89FxCCroMzNg+qm8pAHVYQ72E/w/1sSRuQPECQQD4fes0OrE8qlJ0
|
8
|
+
0UCxiTbotreNY7N/pKPIFqL/+ODcXJIHCyvVAMXw469r9KacrC/t8qKNatWk3mP1
|
9
|
+
uZzfoAJJAkEA7dsxOJcTqMAncOzbP2cXPkGvzyS06mUoziuZWDc+NAOy4R/V/xHW
|
10
|
+
+CUleXs06G9c/LoZ+E80MP600YvPtKUBowJAZXXMfnPkgDevGUGDX7n98IECazml
|
11
|
+
Rd3sfbs4bLmq3m7xtOyLxhnduGDO9I5dJSVtIIPseT+A4iNnvyI9elVz+QJALTBe
|
12
|
+
mpTBTGctVxv4z4Pje5V5NE6R/JI5fWn1GThtne4x9ulYe7xE7iIIi5rnw10c+nrU
|
13
|
+
4kMR9Fj/u2vnizdqJwJACb7DY5rKZa/xgzgLtE5jW60zZWvwS9LYUs+1ND6CeiFy
|
14
|
+
s3EiH2z+zbSO+cnMtCutdRKIHk3wy6tyRKOq0EMafA==
|
15
|
+
-----END RSA PRIVATE KEY-----
|
@@ -0,0 +1 @@
|
|
1
|
+
ssh-dss AAAAB3NzaC1kc3MAAACBALVGVJiZPxVW26cXfFylJ0l+KFocAbMsfSd/aigdwogfo/LGMJ5D3esUHr27IY9QlVrDPfDRjUHsHqHl5cjhIQoDiKqZIdd0Wic7vC85PkNOTNCXfJcHWzjFTz4ZbUy1Q0rEc/MWlfjTv3tnV6c78RlE0ti3Q/ggbzqz874GoPojAAAAFQCduJvAOmRarLp8sti+aPVCJxPoHwAAAIA+4R4KsiCKcsXBJ3DKvETAL+BuUq85//36IwEmj7l83YT0AcqsKwJrncTaWdRtc51IoNHrJWZRBIHcSwEOguoM5UmH8FZVMAF5sg5bCeNBlf1QEaewnAPjOm+1ctTiqfIXLBKvWR0sMcywZLdZWhwn2M4QftGHTEwzjbfJhLhtRAAAAIEApxLO5sTQS/Ej8+BFJQrMS3xHpONQxiMnTLE3q6qZXJRgHDgsqqwZpAfZCjRxvvfUfBGzjKwJlGQOLZVaGZOArGQF7NRtOfCHZtMBg1vubewXs64gmH5GaXvJ17D6W2vCO04R/vXh43qKLDcPu7wGng+eWNaw/LkbdfC4k8uVfp4= user@host
|
@@ -0,0 +1 @@
|
|
1
|
+
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEApfGJ2lzcKgWq50u4yhZyP7yDjA4CF2pV19TUOlXg4a40FCuKi7JIqPCyixmrWYrvRFz+5zY+gHWOHkCfjNaDryUgPsBMzk2DZDD8fsrJ5KU7QDAa1RMbixnWsWTDcXGhHxC7jtRV7qKFvribLYEoUfVbWZYQR3Wl9kfc78sF6Z2TZuL2Fb9YJc5f2uDz6+I6oy8LtGci4Y2hKVYxrN5tgvFcwkE8JsRaAnjWicfoHRUIBZ/tdT76EMhBEKdO63hO9AZ8phTyZoJyLzykDRaelBUYXjG0LQXTq4jiJhKa07kv0XIgNwnz4zB9qtiOHXm6KZZDxy7xnVXOFum+JqcUxQ== user@host
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RightSupport::Log::ExceptionLogger do
|
4
|
+
before(:all) do
|
5
|
+
@actual_logger = Logger.new(StringIO.new)
|
6
|
+
@logger = RightSupport::Log::ExceptionLogger.new(@actual_logger)
|
7
|
+
@exception = Exception.new('message')
|
8
|
+
end
|
9
|
+
|
10
|
+
context :exception do
|
11
|
+
it 'logs an error with exception information' do
|
12
|
+
flexmock(@actual_logger).should_receive(:fatal)
|
13
|
+
@logger.exception('desc', @exception)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'class methods' do
|
18
|
+
context :format_exception do
|
19
|
+
it 'includes the description' do
|
20
|
+
RightSupport::Log::ExceptionLogger.format_exception('desc').should == 'desc'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'includes the exception message if present' do
|
24
|
+
e = ArgumentError.new("err")
|
25
|
+
RightSupport::Log::ExceptionLogger.format_exception('desc', e).should =~ /desc \(ArgumentError: err.*/
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'includes the exception string if present' do
|
29
|
+
RightSupport::Log::ExceptionLogger.format_exception('desc', 'err', :no_trace).should == 'desc (err)'
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'with backtrace=:no_trace' do
|
33
|
+
it 'does not include a backtrace' do
|
34
|
+
e = ArgumentError.new("err")
|
35
|
+
RightSupport::Log::ExceptionLogger.format_exception('desc', e, :no_trace).should == 'desc (ArgumentError: err)'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'with backtrace=:caller' do
|
40
|
+
it 'includes a single line of backtrace' do
|
41
|
+
begin
|
42
|
+
raise ArgumentError.new("err")
|
43
|
+
rescue Exception => e
|
44
|
+
RightSupport::Log::ExceptionLogger.format_exception('desc', e, :caller).should == "desc (ArgumentError: err IN #{e.backtrace[0]})"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'defaults to :caller trace' do
|
49
|
+
begin
|
50
|
+
raise ArgumentError.new("err")
|
51
|
+
rescue Exception => e
|
52
|
+
RightSupport::Log::ExceptionLogger.format_exception('desc', e).should == "desc (ArgumentError: err IN #{e.backtrace[0]})"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'excludes backtrace if the exception does not respond to backtrace' do
|
57
|
+
RightSupport::Log::ExceptionLogger.format_exception('desc', 'err').should == "desc (err)"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'with backtrace=:trace' do
|
62
|
+
it 'includes a full backtrace' do
|
63
|
+
begin
|
64
|
+
raise ArgumentError.new("err")
|
65
|
+
rescue Exception => e
|
66
|
+
RightSupport::Log::ExceptionLogger.format_exception('desc', e, :trace).should == "desc (ArgumentError: err IN\n " + e.backtrace.join("\n ") + ")"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'excludes backtrace if the exception does not respond to backtrace' do
|
71
|
+
RightSupport::Log::ExceptionLogger.format_exception('desc', 'err').should == "desc (err)"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class InnocentVictim
|
4
|
+
include RightSupport::Log::Mixin
|
5
|
+
end
|
6
|
+
|
7
|
+
describe RightSupport::Log::Mixin do
|
8
|
+
context 'when mixed into a base class' do
|
9
|
+
before(:each) do
|
10
|
+
@victim = InnocentVictim.new
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'provides a class-level accessor' do
|
14
|
+
@victim.class.should respond_to(:logger)
|
15
|
+
@victim.class.should respond_to(:logger=)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'provides an instance-level accessor' do
|
19
|
+
@victim.should respond_to(:logger)
|
20
|
+
end
|
21
|
+
|
22
|
+
context :logger do
|
23
|
+
context 'without a logger' do
|
24
|
+
before(:each) do
|
25
|
+
@victim.class.logger = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'uses the default logger' do
|
29
|
+
flexmock(RightSupport::Log::Mixin.default_logger).should_receive(:info).twice.and_return(true)
|
30
|
+
@victim.class.logger.info('lalalala').should be_true
|
31
|
+
@victim.logger.info('lalalala').should be_true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'with class logger' do
|
36
|
+
before(:each) do
|
37
|
+
@logger = mock_logger
|
38
|
+
@victim.class.logger = @logger
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'uses class logger' do
|
42
|
+
@logger.should_receive(:info).and_return(true).twice
|
43
|
+
@victim.class.logger.info('lalalala').should be_true
|
44
|
+
@victim.logger.info('lalalala').should be_true
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'with instance logger' do
|
48
|
+
before(:each) do
|
49
|
+
@instance_logger = mock_logger
|
50
|
+
@victim.logger = @instance_logger
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'uses instance logger' do
|
54
|
+
@instance_logger.should_receive(:info).and_return(true).once
|
55
|
+
@logger.should_receive(:info).never
|
56
|
+
@victim.logger.info('lalalala').should be_true
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009-2012 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'spec_helper'
|
24
|
+
|
25
|
+
describe RightSupport::Log::Multiplexer do
|
26
|
+
|
27
|
+
before(:all) do
|
28
|
+
@target1 = RightSupport::Log::NullLogger.new
|
29
|
+
@target2 = RightSupport::Log::NullLogger.new
|
30
|
+
@target3 = RightSupport::Log::NullLogger.new
|
31
|
+
@multiplexer = RightSupport::Log::Multiplexer.new(@target1, @target2, @target3)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'multiplexes method calls to all callers' do
|
35
|
+
flexmock(@target1).should_receive(:some_method).with('arg', 'arg2').once
|
36
|
+
flexmock(@target2).should_receive(:some_method).with('arg', 'arg2').once
|
37
|
+
flexmock(@target3).should_receive(:some_method).with('arg', 'arg2').once
|
38
|
+
@multiplexer.some_method('arg', 'arg2')
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'returns the result returned by the first target' do
|
42
|
+
flexmock(@target1).should_receive(:some_method).with('arg', 'arg2').and_return('res1').once
|
43
|
+
flexmock(@target2).should_receive(:some_method).with('arg', 'arg2').and_return('res2').once
|
44
|
+
flexmock(@target3).should_receive(:some_method).with('arg', 'arg2').and_return('res3').once
|
45
|
+
@multiplexer.some_method('arg', 'arg2').should == 'res1'
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'multiplexes #warn by undefining Object#warn' do
|
49
|
+
flexmock(@target1).should_receive(:warn).with('arg').and_return('res1')
|
50
|
+
flexmock(@target2).should_receive(:warn).with('arg').and_return('res2')
|
51
|
+
flexmock(@target3).should_receive(:warn).with('arg').and_return('res3')
|
52
|
+
@multiplexer.warn('arg').should == 'res1'
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RightSupport::Log::NullLogger do
|
4
|
+
before(:each) do
|
5
|
+
@logger = RightSupport::Log::NullLogger.new
|
6
|
+
end
|
7
|
+
|
8
|
+
context 'log levels' do
|
9
|
+
[:debug, :info, :warn, :error, :fatal].each do |method|
|
10
|
+
it "responds to ##{method}" do
|
11
|
+
block_called = false
|
12
|
+
@logger.__send__(method, 'lalalala').should be_true
|
13
|
+
@logger.__send__(method) { block_called = true ; 'lalalala' }.should be_true
|
14
|
+
block_called.should be_true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context '<< method' do
|
20
|
+
it 'responds like Logger' do
|
21
|
+
(@logger << 'lalalala').should == 8
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context :close do
|
26
|
+
it 'responds' do
|
27
|
+
@logger.close.should be_nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'is idempotent' do
|
31
|
+
@logger.close.should be_nil
|
32
|
+
@logger.close.should be_nil
|
33
|
+
@logger.close.should be_nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|