right_support 2.11.3 → 2.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -0
  3. data/VERSION +1 -1
  4. data/lib/right_support/notifiers/airbrake.rb +194 -0
  5. data/lib/right_support/notifiers/base.rb +73 -0
  6. data/lib/right_support/notifiers/blacklisters/base.rb +48 -0
  7. data/lib/right_support/notifiers/blacklisters/canonical.rb +60 -0
  8. data/lib/right_support/notifiers/blacklisters/regular_expression.rb +86 -0
  9. data/{features/support/file_utils_bundler_mixin.rb → lib/right_support/notifiers/blacklisters/simple.rb} +21 -20
  10. data/lib/right_support/notifiers/blacklisters/snake_case.rb +60 -0
  11. data/lib/right_support/notifiers/blacklisters/wildcard.rb +65 -0
  12. data/lib/right_support/notifiers/blacklisters.rb +34 -0
  13. data/lib/right_support/notifiers/logger.rb +94 -0
  14. data/lib/right_support/notifiers/notification.rb +57 -0
  15. data/lib/right_support/notifiers/utilities/backtrace_decoder.rb +234 -0
  16. data/lib/right_support/notifiers/utilities.rb +29 -0
  17. data/lib/right_support/notifiers.rb +32 -0
  18. data/lib/right_support/rack/request_logger.rb +13 -9
  19. data/lib/right_support.rb +1 -0
  20. data/right_support.gemspec +19 -70
  21. metadata +17 -69
  22. data/.coveralls.yml +0 -2
  23. data/.rspec +0 -3
  24. data/.simplecov +0 -6
  25. data/.travis.yml +0 -13
  26. data/Gemfile +0 -51
  27. data/Gemfile.lock +0 -153
  28. data/features/balancer_error_handling.feature +0 -34
  29. data/features/balancer_health_check.feature +0 -33
  30. data/features/hash_tools.feature +0 -27
  31. data/features/http_client_timeout.feature +0 -19
  32. data/features/serialization.feature +0 -113
  33. data/features/step_definitions/hash_tools_steps.rb +0 -41
  34. data/features/step_definitions/http_client_steps.rb +0 -27
  35. data/features/step_definitions/request_balancer_steps.rb +0 -93
  36. data/features/step_definitions/ruby_steps.rb +0 -176
  37. data/features/step_definitions/serialization_steps.rb +0 -133
  38. data/features/step_definitions/server_steps.rb +0 -134
  39. data/features/support/env.rb +0 -148
  40. data/right_support.rconf +0 -9
  41. data/spec/config/feature_set_spec.rb +0 -83
  42. data/spec/crypto/signed_hash_spec.rb +0 -73
  43. data/spec/data/hash_tools_spec.rb +0 -602
  44. data/spec/data/mash_spec.rb +0 -313
  45. data/spec/data/token_spec.rb +0 -21
  46. data/spec/data/uuid_spec.rb +0 -45
  47. data/spec/db/cassandra_model_part1_spec.rb +0 -84
  48. data/spec/db/cassandra_model_part2_spec.rb +0 -73
  49. data/spec/db/cassandra_model_spec.rb +0 -375
  50. data/spec/fixtures/encrypted_priv_rsa.pem +0 -30
  51. data/spec/fixtures/good_priv_dsa.pem +0 -12
  52. data/spec/fixtures/good_priv_rsa.pem +0 -15
  53. data/spec/fixtures/good_pub_dsa.ssh +0 -1
  54. data/spec/fixtures/good_pub_rsa.pem +0 -5
  55. data/spec/fixtures/good_pub_rsa.ssh +0 -1
  56. data/spec/log/exception_logger_spec.rb +0 -76
  57. data/spec/log/filter_logger_spec.rb +0 -66
  58. data/spec/log/mixin_spec.rb +0 -141
  59. data/spec/log/multiplexer_spec.rb +0 -54
  60. data/spec/log/null_logger_spec.rb +0 -36
  61. data/spec/log/step_level_logger_spec.rb +0 -49
  62. data/spec/log/system_logger_spec.rb +0 -172
  63. data/spec/net/address_helper_spec.rb +0 -57
  64. data/spec/net/dns_spec.rb +0 -187
  65. data/spec/net/http_client_spec.rb +0 -181
  66. data/spec/net/lb/health_check_spec.rb +0 -417
  67. data/spec/net/lb/round_robin_spec.rb +0 -15
  68. data/spec/net/lb/sticky_spec.rb +0 -92
  69. data/spec/net/request_balancer_spec.rb +0 -690
  70. data/spec/net/s3_helper_spec.rb +0 -160
  71. data/spec/net/ssl_spec.rb +0 -42
  72. data/spec/net/string_encoder_spec.rb +0 -58
  73. data/spec/rack/log_setter_spec.rb +0 -5
  74. data/spec/rack/request_logger_spec.rb +0 -225
  75. data/spec/rack/request_tracker_spec.rb +0 -115
  76. data/spec/rack/runtime_spec.rb +0 -49
  77. data/spec/ruby/easy_singleton_spec.rb +0 -72
  78. data/spec/ruby/object_extensions_spec.rb +0 -27
  79. data/spec/ruby/string_extensions_spec.rb +0 -98
  80. data/spec/spec_helper.rb +0 -188
  81. data/spec/stats/activity_spec.rb +0 -425
  82. data/spec/stats/exceptions_spec.rb +0 -247
  83. data/spec/stats/helpers_spec.rb +0 -685
  84. data/spec/validation/openssl_spec.rb +0 -37
  85. data/spec/validation/ssh_spec.rb +0 -39
@@ -1,160 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe RightSupport::Net::S3Helper do
4
-
5
- def digest
6
- OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, passphrase, @valid_params[:data])
7
- end
8
-
9
- def ciphertext
10
- "\203\346\271\273\323\377r\246\002\204\231\374h\327!\323"
11
- end
12
-
13
- def passphrase
14
- "#{@valid_params[:key]}:key"
15
- end
16
-
17
- before(:each) do
18
- @valid_params = { :key => "foo", :data => "bar" }
19
-
20
- # Mock right_aws config & objects with reasonable default behavior
21
- @s3_config = {'creds' =>
22
- {'aws_access_key_id' => 'knock_knock',
23
- 'aws_secret_access_key' => 'open_sesame'},
24
- 'bucket_name' => 'my_own_personal_bucket',
25
- 'master_secret' => 'if i told you i would have to kill you'}
26
- @s3_class = flexmock("s3")
27
- @s3_object = flexmock("s3_object")
28
- @s3_bucket = flexmock("s3_bucket")
29
- @s3_class.should_receive(:new).with(String, String, Hash).and_return(@s3_object)
30
- @s3_object.should_receive(:bucket).with('my_own_personal_bucket').and_return(@s3_bucket).by_default
31
- @s3_bucket.should_receive(:key).and_return(@s3_object).by_default
32
- @s3_bucket.should_receive(:put).with(String, String, Hash).and_return(true).by_default
33
-
34
- @s3_object.should_receive(:meta_headers).and_return({"digest" => digest})
35
- @s3_object.should_receive(:data).and_return(ciphertext)
36
-
37
- flexmock(RightSupport::Net::S3Helper).should_receive(:s3_enabled?).and_return(:true)
38
- flexmock(RightSupport::Net::S3Helper).should_receive(:master_secret).and_return('key')
39
-
40
- @encrypt = flexmock("encrypt")
41
- @encrypt.should_receive(:encrypt).with(String, String, Hash).and_return(ciphertext)
42
- @encrypt.should_receive(:encrypt).with(Hash).and_return(ciphertext)
43
- @encrypt.should_receive(:decrypt).with(Hash).and_return(@valid_params[:data])
44
- end
45
-
46
- context :init do
47
- context "when all params are valid" do
48
- it "succeeds" do
49
- RightSupport::Net::S3Helper.init(@s3_config, @s3_class, @encrypt).should be_true
50
- end
51
- end
52
-
53
- context "when bucket does not exist" do
54
- before(:each) do
55
- @bad_s3_config = @s3_config.clone
56
- @bad_s3_config['bucket_name'] = "supercallifragilisticexpialidocious"
57
- @s3_object.should_receive(:bucket).with("supercallifragilisticexpialidocious").and_return(nil)
58
- end
59
-
60
- it "raises BucketNotFound" do
61
- lambda {
62
- RightSupport::Net::S3Helper.init(@bad_s3_config, @s3_class, @encrypt)
63
- }.should raise_error(RightSupport::Net::S3Helper::BucketNotFound)
64
- end
65
- end
66
- end
67
-
68
- context :get do
69
- before(:each) do
70
- RightSupport::Net::S3Helper.init(@s3_config, @s3_class, @encrypt)
71
- end
72
-
73
- context "with valid params" do
74
- it 'returns plaintext' do
75
- RightSupport::Net::S3Helper.get(@valid_params[:key]).should be_eql(@valid_params[:data])
76
- end
77
- end
78
- end
79
-
80
- context :post do
81
- before(:each) do
82
- RightSupport::Net::S3Helper.init(@s3_config, @s3_class, @encrypt)
83
- end
84
-
85
- context "with valid params" do
86
- it 'encrypts and saves data' do
87
- @s3_bucket.should_receive(:put).with(@valid_params[:key], ciphertext, {"digest" => digest}).and_return(true)
88
- RightSupport::Net::S3Helper.post(@valid_params[:key], @valid_params[:data]).should be_true
89
- end
90
- end
91
- end
92
-
93
- context :health_check do
94
- before(:each) do
95
- RightSupport::Net::S3Helper.init(@s3_config, @s3_class, @encrypt)
96
- end
97
-
98
- context 'with invalid configuration' do
99
- before :each do
100
- flexmock(RightSupport::Net::S3Helper).should_receive(:config).and_return({'creds' => {'aws_access_key_id' => '@@AWS_ACCESS_KEY_ID@@', 'aws_secret_access_key' => '@@AWS_SECRET_ACCESS_KEY@@'}, 'bucket_name' => '@@s3_bucket_NAME@@', 'master_secret' => '@@MASTER_SECRET@@'})
101
- end
102
-
103
- it 'return error' do
104
- RightSupport::Net::S3Helper.health_check.class.should == String
105
- end
106
- end
107
-
108
- context 'with valid configuration but invalid s3 connection credentials' do
109
- before :each do
110
- flexmock(RightSupport::Net::S3Helper).should_receive(:config).and_return({'creds' => {'aws_access_key_id' => 'AWS_ACCESS_KEY_ID', 'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY'}, 'bucket_name' => 'BUCKET_NAME', 'master_secret' => 'MASTER_SECRET'})
111
- end
112
-
113
- it 'returns error ' do
114
- RightSupport::Net::S3Helper.health_check.class.should == String
115
- end
116
- end
117
-
118
- context 'with valid configuration and s3 connection' do
119
- before :each do
120
- flexmock(RightSupport::Net::S3Helper).should_receive(:config).and_return({'creds' => {'aws_access_key_id' => 'dsfgdsfgdsfgdsfg', 'aws_secret_access_key' => 'sdghdhsdg'}, 'bucket_name' => 'dshdshdfgh', 'master_secret' => 'dshdshg'})
121
- flexmock(RightSupport::Net::S3Helper).should_receive(:post).with('ping', 'heath check').and_return(true)
122
- flexmock(RightSupport::Net::S3Helper).should_receive(:get).with('ping').and_return('heath check')
123
- end
124
-
125
- it 'returns ok' do
126
- RightSupport::Net::S3Helper.health_check.should == true
127
- end
128
- end
129
- end
130
-
131
- context 'test/development environment' do
132
-
133
- before :each do
134
- @key1 = 'aws_access_key_id'
135
- @key2 = 'aws_secret_access_key'
136
- @opt_with_no_subdomains = {:no_subdomains => true}
137
- @opt_without_subdoamins = {}
138
- @config = {}
139
- @config["creds"] = {}
140
- @config["creds"]["aws_access_key_id"] = @key1
141
- @config["creds"]["aws_secret_access_key"] = @key2
142
- @s3_class = flexmock('Rightscale::S3')
143
- flexmock(RightSupport::Net::S3Helper).should_receive(:bucket).and_return(true)
144
- end
145
-
146
- it 'works ok with :no_subdomains' do
147
- @s3_class.should_receive(:new).with(@key1, @key2, @opt_with_no_subdomains)
148
- RightSupport::Net::S3Helper.init(@config, @s3_class, @s3_class, :no_subdomains => true)
149
- RightSupport::Net::S3Helper.s3
150
- end
151
-
152
- it 'works ok without subdomains' do
153
- @s3_class.should_receive(:new).with(@key1, @key2, @opt_without_subdoamins)
154
- RightSupport::Net::S3Helper.init(@config, @s3_class, @s3_class)
155
- RightSupport::Net::S3Helper.s3
156
- end
157
-
158
- end
159
-
160
- end
data/spec/net/ssl_spec.rb DELETED
@@ -1,42 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe RightSupport::Net::SSL do
4
- PATCH = RightSupport::Net::SSL::OpenSSLPatch
5
-
6
- context :with_expected_hostname do
7
- before(:all) do
8
- PATCH.enable!
9
- end
10
-
11
- it 'works' do
12
- OpenSSL::SSL.should respond_to(:verify_certificate_identity_without_hack)
13
- PATCH.enabled?.should be_true
14
-
15
- cert = flexmock('SSL certificate')
16
-
17
- flexmock(OpenSSL::SSL).
18
- should_receive(:verify_certificate_identity_without_hack).
19
- with(cert, 'reposeX.rightscale.com').and_return(true)
20
- RightSupport::Net::SSL.with_expected_hostname('reposeX.rightscale.com') do
21
- OpenSSL::SSL.verify_certificate_identity(cert, '1.2.3.4').should be_true
22
- end
23
- end
24
-
25
- context 'with disabled monkey-patch' do
26
- before(:all) do
27
- PATCH.disable!
28
- end
29
- it 'does not work' do
30
- PATCH.enabled?.should be_false
31
- cert = flexmock('SSL certificate')
32
- flexmock(OpenSSL::SSL).
33
- should_receive(:verify_certificate_identity_without_hack).
34
- with(cert, '1.2.3.4').and_return(false)
35
-
36
- RightSupport::Net::SSL.with_expected_hostname('reposeX.rightscale.com') do
37
- OpenSSL::SSL.verify_certificate_identity(cert, '1.2.3.4').should be_false
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,58 +0,0 @@
1
- require 'spec_helper'
2
- require 'cgi'
3
-
4
- describe RightSupport::Net::StringEncoder do
5
- #Alias for brevity's sake
6
- ENCODINGS = RightSupport::Net::StringEncoder::ENCODINGS
7
-
8
- before(:all) do
9
- #Generate some random binary test vectors with varying
10
- #lengths, 2-1024 bytes
11
- @strings = []
12
- (1..10).each do |i|
13
- s = ''
14
- i.times { s << rand(256) }
15
-
16
- if RUBY_VERSION >= '1.9'
17
- @strings << s.force_encoding(Encoding::ASCII_8BIT)
18
- else
19
- @strings << s
20
- end
21
- end
22
- end
23
-
24
- context :initialize do
25
- it 'accepts a glob of encodings' do
26
- obj = RightSupport::Net::StringEncoder.new(:base64, :url)
27
- obj.decode(obj.encode('moo')).should == 'moo'
28
- end
29
-
30
- it 'accepts an Array of encodings' do
31
- obj = RightSupport::Net::StringEncoder.new([:base64, :url])
32
- obj.decode(obj.encode('moo')).should == 'moo'
33
- end
34
-
35
- context 'when unknown encodings are specified' do
36
- it 'raises ArgumentError' do
37
- lambda do
38
- RightSupport::Net::StringEncoder.new(:xyzzy, :foobar)
39
- end.should raise_error(ArgumentError)
40
- end
41
- end
42
- end
43
-
44
- #Ensure that encodings are symmetrical and commutative by testing round-trip
45
- #for all combinations.
46
- (1..ENCODINGS.length).each do |n|
47
- context "when using any #{n} encoding#{n > 1 ? 's' : ''}" do
48
- ENCODINGS.combination(n).each do |list|
49
- it "round-trips #{list.join(', ')}" do
50
- obj = RightSupport::Net::StringEncoder.new(*list)
51
- @strings.each do |str|
52
- obj.decode(obj.encode(str)).should == str
53
- end
54
- end
55
- end
56
- end
57
- end
58
- end
@@ -1,5 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe RightSupport::Rack::LogSetter do
4
- it 'has test coverage'
5
- end
@@ -1,225 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe RightSupport::Rack::RequestLogger do
4
- class OhNoes < Exception; end
5
-
6
- before(:each) do
7
- @app = flexmock('Rack app')
8
- @app.should_receive(:call).and_return([200, {}, 'body']).by_default
9
- @logger = mock_logger
10
- @env = {'rack.logger' => @logger}
11
- @options = {}
12
- end
13
-
14
- subject { described_class.new(@app, @options) }
15
-
16
- context :initialize do
17
- context 'without :logger option' do
18
- it 'uses rack.logger' do
19
- @logger.should_receive(:info).at_least.once
20
- subject.call(@env).should == [200, {}, 'body']
21
- end
22
- end
23
-
24
- context 'with :logger option' do
25
- it 'uses given logger' do
26
- @env = {'rack.logger' => flexmock('overridden')}
27
- @options[:logger] = @logger
28
- @logger.should_receive(:info).at_least.once
29
- subject.call(@env).should == [200, {}, 'body']
30
- end
31
- end
32
-
33
- context 'with :normalize_40x option' do
34
- it 'omits some 40x details and disables global session Set-Cookie fields' do
35
- @options[:normalize_40x] = true
36
- @app = flexmock('Rack app')
37
- body = 'insecure information'
38
- headers = { 'TooMuch' => 'info', 'Content-Type' => 'text/plain', 'Content-Length' => body.bytesize.to_s }
39
- iterative = [nil, headers, body]
40
- @app.should_receive(:call).and_return(iterative)
41
-
42
- # note that sending 'X-Debug' header should have no effect on a
43
- # normalized 40x response
44
- @env.merge!(described_class::DEBUG_MODE_HTTP_HEADER => 'true')
45
- (400..499).each do |code|
46
- iterative[0] = code
47
- if described_class::NORMALIZE_40X.include?(code)
48
- env = @env.dup
49
- subject.call(env).should == [code, { 'Content-Length' => '0'}, []]
50
- env.should == @env.merge(
51
- 'global_session.req.renew' => false,
52
- 'global_session.req.update' => false,
53
- described_class::DEBUG_MODE_ENV_KEY => false)
54
- else
55
- subject.call(@env).should == iterative
56
- end
57
- end
58
- end
59
- end
60
-
61
- context 'with :normalize_40x_set_cookie option' do
62
- it 'disables global session Set-Cookie fields' do
63
- @options[:normalize_40x_set_cookie] = true
64
- @app = flexmock('Rack app')
65
- body = 'whatever'
66
- headers = { 'Content-Type' => 'text/plain', 'Content-Length' => body.bytesize.to_s }
67
- iterative = [nil, headers, body]
68
- @app.should_receive(:call).and_return(iterative)
69
-
70
- (400..499).each do |code|
71
- iterative[0] = code
72
- if described_class::NORMALIZE_40X.include?(code)
73
- env = @env.dup
74
- subject.call(env).should == iterative
75
- env.should == @env.merge(
76
- 'global_session.req.renew' => false,
77
- 'global_session.req.update' => false)
78
- else
79
- subject.call(@env).should == iterative
80
- end
81
- end
82
- end
83
- end
84
- end
85
-
86
- context :call do
87
- context 'when the app raises an exception' do
88
- before(:each) do
89
- @app.should_receive(:call).and_raise(OhNoes)
90
- end
91
-
92
- it 'logs the exception' do
93
- @logger.should_receive(:error).at_least.once
94
- lambda {
95
- subject.call(@env)
96
- }.should raise_error
97
- end
98
- end
99
-
100
- context 'when Sinatra stores an exception' do
101
- before(:each) do
102
- @app.should_receive(:call).and_return([500, {}, 'body'])
103
- @env['sinatra.error'] = OhNoes.new
104
- end
105
-
106
- it 'logs the exception' do
107
- @logger.should_receive(:info)
108
- @logger.should_receive(:error).at_least.once
109
- subject.call(@env)
110
- end
111
-
112
- it 'skips logging the exception when already handled' do
113
- @logger.should_receive(:info)
114
- @logger.should_receive(:error).never
115
- @env['sinatra.error.handled'] = true
116
- subject.call(@env)
117
- end
118
- end
119
-
120
- context 'given limiting options' do
121
- before(:each) do
122
- @options = {:except => [/bar/]}
123
- @env.merge!('PATH_INFO' => '/foo/bar')
124
- subject = described_class.new(@app, @options)
125
- @logger.should_receive(:level).and_return(Logger::INFO).by_default
126
- end
127
-
128
- it 'limits if logger in debug mode' do
129
- @logger.should_receive(:level).and_return(Logger::DEBUG)
130
- @logger.should_receive(:info).never
131
- subject.call(@env)
132
- end
133
-
134
- it 'does not limit if HTTP_X_DEBUG set' do
135
- @logger.should_receive(:info).at_least.once
136
- subject.call(@env.merge('HTTP_X_DEBUG' => true))
137
- end
138
-
139
- it 'does not log for paths matching :except option' do
140
- @logger.should_receive(:info).never
141
- subject.call(@env)
142
- end
143
-
144
- it 'does log for paths matching :only option' do
145
- @options = {:only => [/bar/]}
146
- subject = described_class.new(@app, @options)
147
- @logger.should_receive(:info)
148
- subject.call(@env)
149
- end
150
-
151
- it 'sets rack.logging.enabled in Rack environment' do
152
- @logger.should_receive(:info).at_least.once
153
- @env.merge!('PATH_INFO' => '/my/app')
154
- subject.call(@env)
155
- @env['rack.logging.enabled'].should be_true
156
- end
157
- end
158
-
159
- context 'when logging the query string' do
160
- before(:each) do
161
- @options = {}
162
- @env.merge!('PATH_INFO' => '/my/app', 'QUERY_STRING' => 'foo=bar')
163
- subject = described_class.new(@app, @options)
164
- end
165
-
166
- it 'does not log the query string by default' do
167
- @logger.should_receive(:info).with(FlexMock.on { |arg| arg.should =~ /\/my\/app\?\.{3}/ } )
168
- subject.send(:log_request_begin, @logger, @env)
169
- end
170
-
171
- context 'when the include_query_string option is true' do
172
- it 'logs the query string' do
173
- @options[:include_query_string] = true
174
- subject = described_class.new(@app, @options)
175
- @logger.should_receive(:info).with(FlexMock.on { |arg| arg.should =~ /\/my\/app\?foo%3Dbar/ } )
176
- subject.send(:log_request_begin, @logger, @env)
177
- end
178
- end
179
-
180
- context 'when the include_query_string option is false' do
181
- it 'does not log the query string' do
182
- @options[:include_query_string] = false
183
- subject = described_class.new(@app, @options)
184
- @logger.should_receive(:info).with(FlexMock.on { |arg| arg.should =~ /\/my\/app\?\.{3}/ } )
185
- subject.send(:log_request_begin, @logger, @env)
186
- end
187
- end
188
- end
189
-
190
- context 'Shard ID logging' do
191
- before(:each) do
192
- @logger = mock_logger
193
- end
194
-
195
- it 'logs X-Shard header if it is present' do
196
- @env['HTTP_X_SHARD'] = '9'
197
- @logger.should_receive(:info).with(FlexMock.on { |arg| arg.should =~ /Shard: 9$/ } )
198
- subject.send(:log_request_begin, @logger, @env)
199
- end
200
-
201
- it 'logs "default" if X-Shard header is absent' do
202
- @logger.should_receive(:info).with(FlexMock.on { |arg| arg.should =~ /Shard: default$/ } )
203
- subject.send(:log_request_begin, @logger, @env)
204
- end
205
- end
206
-
207
- context 'request ID logging' do
208
- before(:each) do
209
- @logger = mock_logger
210
- @env['rack.request_uuid'] = 'some-uuid'
211
- end
212
-
213
- it 'tags the Started line' do
214
- @logger.should_receive(:info).with(FlexMock.on { |arg| arg.should =~ /^\[some\-uuid\] Started / } )
215
- subject.send(:log_request_begin, @logger, @env)
216
- end
217
-
218
- it 'tags the Completed line' do
219
- @logger.should_receive(:info).with(FlexMock.on { |arg| arg.should =~ /^\[some\-uuid\] Completed / } )
220
- subject.send(:log_request_end, @logger, @env, 200, {}, '', Time.now)
221
- end
222
- end
223
-
224
- end
225
- end
@@ -1,115 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe RightSupport::Rack::RequestTracker do
4
-
5
- let(:app) { flexmock('next middleware or rack app') }
6
-
7
- let(:generator) { described_class::Generator }
8
- let(:generated_request_uuid) { 'generated-uuid' }
9
- let(:request_uuid) { 'given-uuid' }
10
-
11
- subject { described_class.new(app) }
12
-
13
- context :call do
14
- context 'when ID is missing from request headers' do
15
- it 'generates a new request ID and responds as UUID for legacy reasons' do
16
- flexmock(generator).
17
- should_receive(:generate).
18
- and_return(generated_request_uuid).
19
- once
20
- original_env = {}
21
- expected_env = original_env.merge(described_class::REQUEST_UUID_ENV_NAME => generated_request_uuid)
22
- app.should_receive(:call).with(expected_env).and_return([200, {}, 'body']).once
23
-
24
- actual = subject.call(original_env)
25
-
26
- expected_headers = { described_class::REQUEST_UUID_HEADER => generated_request_uuid }
27
- actual[1].should == expected_headers
28
- end
29
- end
30
-
31
- context 'when ID sent with request' do
32
- it 'passes incoming request ID and responds as ID' do
33
- flexmock(generator).should_receive(:generate).never
34
- original_env = { described_class::HTTP_REQUEST_ID_HEADER => request_uuid }
35
- expected_env = original_env.merge(described_class::REQUEST_UUID_ENV_NAME => request_uuid)
36
- app.should_receive(:call).with(expected_env).and_return([200, {}, 'body']).once
37
-
38
- actual = subject.call(original_env)
39
-
40
- expected_headers = { described_class::REQUEST_ID_HEADER => request_uuid }
41
- actual[1].should == expected_headers
42
- end
43
- end
44
-
45
- context 'when UUID sent with request' do
46
- it 'passes incoming request UUID and responds as UUID' do
47
- flexmock(generator).should_receive(:generate).never
48
- original_env = { described_class::HTTP_REQUEST_UUID_HEADER => request_uuid }
49
- expected_env = original_env.merge(described_class::REQUEST_UUID_ENV_NAME => request_uuid)
50
- app.should_receive(:call).with(expected_env).and_return([200, {}, 'body']).once
51
-
52
- actual = subject.call(original_env)
53
-
54
- expected_headers = { described_class::REQUEST_UUID_HEADER => request_uuid }
55
- actual[1].should == expected_headers
56
- end
57
- end
58
-
59
- context 'when lineage sent with request' do
60
- it 'passes all UUIDs in header under length limit' do
61
- uuids = []
62
- 3.times do
63
- uuids << ::RightSupport::Data::UUID.generate
64
- end
65
- lineage_uuid = uuids.join(described_class::UUID_SEPARATOR)
66
- flexmock(generator).should_receive(:generate).never
67
- original_env = { described_class::REQUEST_LINEAGE_UUID_HEADER => lineage_uuid }
68
- expected_env = original_env.merge(described_class::REQUEST_UUID_ENV_NAME => lineage_uuid)
69
- app.should_receive(:call).with(expected_env).and_return([200, {}, 'body']).once
70
-
71
- actual = subject.call(original_env)
72
-
73
- expected_headers = { described_class::REQUEST_UUID_HEADER => lineage_uuid }
74
- actual[1].should == expected_headers
75
- end
76
- end
77
-
78
- context 'when sent ID exceeds length limit' do
79
- it 'passes truncated request ID' do
80
- flexmock(generator).should_receive(:generate).never
81
- too_long_id = 'x' * 1024
82
- truncated_id = 'x' * described_class::MAX_REQUEST_UUID_LENGTH
83
- original_env = { described_class::HTTP_REQUEST_ID_HEADER => too_long_id }
84
- expected_env = original_env.merge(described_class::REQUEST_UUID_ENV_NAME => truncated_id)
85
- app.should_receive(:call).with(expected_env).and_return([200, {}, 'body']).once
86
-
87
- actual = subject.call(original_env)
88
-
89
- expected_headers = { described_class::REQUEST_ID_HEADER => truncated_id }
90
- actual[1].should == expected_headers
91
- end
92
- end
93
-
94
- end
95
-
96
- context :copy_request_uuid do
97
- it 'does nothing when request UUID is missing' do
98
- described_class.copy_request_uuid(nil, nil).should be_empty
99
- end
100
-
101
- it 'copies request UUID to target hash when present' do
102
- env = {
103
- described_class::REQUEST_UUID_ENV_NAME => request_uuid,
104
- 'other' => 'stuff'
105
- }
106
- other_headers = { 'Foo' => 'bar' }
107
- expected = {
108
- described_class::REQUEST_ID_HEADER => request_uuid
109
- }.merge(other_headers)
110
- actual = described_class.copy_request_uuid(env, other_headers)
111
- actual.should == expected
112
- end
113
- end
114
-
115
- end
@@ -1,49 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class FasterApp
4
- def self.call(env)
5
- sleep 0.05; [200, {}, "50ms"]
6
- end
7
- end
8
-
9
- class SlowerApp
10
- def self.call(env)
11
- sleep 0.2; [200, {}, "200ms"]
12
- end
13
- end
14
-
15
- describe RightSupport::Rack::Runtime do
16
- before(:each) do
17
- @app = flexmock('Rack app')
18
- @app.should_receive(:call).and_return([200, {}, 'body']).by_default
19
- @env = {'rack.logger' => @logger}
20
- @middleware = RightSupport::Rack::Runtime.new(@app)
21
- end
22
-
23
- context :call do
24
- it 'sets an X-Runtime header in response' do
25
- @middleware.call(@env).should == [200, {"X-Runtime"=>"0"}, 'body']
26
- end
27
-
28
- it 'sets a correct X-Runtime value for 50 ms app' do
29
- faster = RightSupport::Rack::Runtime.new(FasterApp)
30
- result = faster.call(@env)
31
- result[1].keys.should == ['X-Runtime']
32
- result[1]['X-Runtime'].to_i.should >= 50
33
- result[1]['X-Runtime'].to_i.should < 70
34
- end
35
-
36
- it 'sets a correct X-Runtime value for 200 ms app' do
37
- slower = RightSupport::Rack::Runtime.new(SlowerApp)
38
- result = slower.call(@env)
39
- result[1].keys.should == ['X-Runtime']
40
- result[1]['X-Runtime'].to_i.should >= 200
41
- result[1]['X-Runtime'].to_i.should < 270
42
- end
43
-
44
- it 'allows appending custom name to X-Runtime header' do
45
- customized = RightSupport::Rack::Runtime.new(@app, "Test")
46
- customized.call(@env).should == [200, {"X-Runtime-Test"=>"0"}, 'body']
47
- end
48
- end
49
- end