cloudtrapper 0.0.2.pre

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 (81) hide show
  1. data/CHANGELOG +823 -0
  2. data/Gemfile +12 -0
  3. data/Guardfile +6 -0
  4. data/INSTALL +20 -0
  5. data/MIT-LICENSE +22 -0
  6. data/README.md +465 -0
  7. data/README_FOR_HEROKU_ADDON.md +94 -0
  8. data/Rakefile +223 -0
  9. data/SUPPORTED_RAILS_VERSIONS +23 -0
  10. data/TESTING.md +33 -0
  11. data/cloudtrapper.gemspec +35 -0
  12. data/features/metal.feature +18 -0
  13. data/features/rack.feature +56 -0
  14. data/features/rails.feature +211 -0
  15. data/features/rails_with_js_notifier.feature +97 -0
  16. data/features/rake.feature +27 -0
  17. data/features/sinatra.feature +29 -0
  18. data/features/step_definitions/file_steps.rb +10 -0
  19. data/features/step_definitions/metal_steps.rb +23 -0
  20. data/features/step_definitions/rack_steps.rb +23 -0
  21. data/features/step_definitions/rails_application_steps.rb +433 -0
  22. data/features/step_definitions/rake_steps.rb +17 -0
  23. data/features/support/airbrake_shim.rb.template +11 -0
  24. data/features/support/env.rb +18 -0
  25. data/features/support/matchers.rb +35 -0
  26. data/features/support/rails.rb +201 -0
  27. data/features/support/rake/Rakefile +68 -0
  28. data/features/support/terminal.rb +107 -0
  29. data/features/user_informer.feature +63 -0
  30. data/generators/cloudtrapper/airbrake_generator.rb +94 -0
  31. data/generators/cloudtrapper/lib/insert_commands.rb +34 -0
  32. data/generators/cloudtrapper/lib/rake_commands.rb +24 -0
  33. data/generators/cloudtrapper/templates/capistrano_hook.rb +6 -0
  34. data/generators/cloudtrapper/templates/cloudtrapper_tasks.rake +25 -0
  35. data/generators/cloudtrapper/templates/initializer.rb +6 -0
  36. data/install.rb +1 -0
  37. data/lib/cloudtrapper/backtrace.rb +100 -0
  38. data/lib/cloudtrapper/capistrano.rb +44 -0
  39. data/lib/cloudtrapper/configuration.rb +281 -0
  40. data/lib/cloudtrapper/notice.rb +348 -0
  41. data/lib/cloudtrapper/rack.rb +55 -0
  42. data/lib/cloudtrapper/rails/action_controller_catcher.rb +30 -0
  43. data/lib/cloudtrapper/rails/controller_methods.rb +74 -0
  44. data/lib/cloudtrapper/rails/error_lookup.rb +33 -0
  45. data/lib/cloudtrapper/rails/javascript_notifier.rb +48 -0
  46. data/lib/cloudtrapper/rails/middleware/exceptions_catcher.rb +29 -0
  47. data/lib/cloudtrapper/rails.rb +40 -0
  48. data/lib/cloudtrapper/rails3_tasks.rb +85 -0
  49. data/lib/cloudtrapper/railtie.rb +48 -0
  50. data/lib/cloudtrapper/rake_handler.rb +66 -0
  51. data/lib/cloudtrapper/sender.rb +116 -0
  52. data/lib/cloudtrapper/shared_tasks.rb +36 -0
  53. data/lib/cloudtrapper/tasks.rb +83 -0
  54. data/lib/cloudtrapper/user_informer.rb +27 -0
  55. data/lib/cloudtrapper/version.rb +3 -0
  56. data/lib/cloudtrapper.rb +155 -0
  57. data/lib/cloudtrapper_tasks.rb +65 -0
  58. data/lib/rails/generators/cloudtrapper/cloudtrapper_generator.rb +100 -0
  59. data/lib/templates/javascript_notifier.erb +15 -0
  60. data/lib/templates/rescue.erb +91 -0
  61. data/rails/init.rb +1 -0
  62. data/resources/README.md +34 -0
  63. data/resources/ca-bundle.crt +3376 -0
  64. data/script/integration_test.rb +38 -0
  65. data/test/backtrace_test.rb +162 -0
  66. data/test/capistrano_test.rb +34 -0
  67. data/test/catcher_test.rb +333 -0
  68. data/test/cloudtrapper_2_2.xsd +78 -0
  69. data/test/cloudtrapper_tasks_test.rb +170 -0
  70. data/test/configuration_test.rb +221 -0
  71. data/test/helper.rb +263 -0
  72. data/test/javascript_notifier_test.rb +52 -0
  73. data/test/logger_test.rb +73 -0
  74. data/test/notice_test.rb +468 -0
  75. data/test/notifier_test.rb +246 -0
  76. data/test/rack_test.rb +58 -0
  77. data/test/rails_initializer_test.rb +36 -0
  78. data/test/recursion_test.rb +10 -0
  79. data/test/sender_test.rb +261 -0
  80. data/test/user_informer_test.rb +29 -0
  81. metadata +301 -0
@@ -0,0 +1,246 @@
1
+ require File.expand_path( File.join(File.dirname(__FILE__), 'helper') )
2
+
3
+ class NotifierTest < Test::Unit::TestCase
4
+
5
+ class OriginalException < Exception
6
+ end
7
+
8
+ class ContinuedException < Exception
9
+ end
10
+
11
+ include DefinesConstants
12
+
13
+ def setup
14
+ super
15
+ reset_config
16
+ end
17
+
18
+ def assert_sent(notice, notice_args)
19
+ assert_received(Cloudtrapper::Notice, :new) {|expect| expect.with(has_entries(notice_args)) }
20
+ assert_received(notice, :to_xml)
21
+ assert_received(Cloudtrapper.sender, :send_to_cloudtrapper) {|expect| expect.with(notice.to_xml) }
22
+ end
23
+
24
+ def set_public_env
25
+ Cloudtrapper.configure { |config| config.environment_name = 'production' }
26
+ end
27
+
28
+ def set_development_env
29
+ Cloudtrapper.configure { |config| config.environment_name = 'development' }
30
+ end
31
+
32
+ should "yield and save a configuration when configuring" do
33
+ yielded_configuration = nil
34
+ Cloudtrapper.configure do |config|
35
+ yielded_configuration = config
36
+ end
37
+
38
+ assert_kind_of Cloudtrapper::Configuration, yielded_configuration
39
+ assert_equal yielded_configuration, Cloudtrapper.configuration
40
+ end
41
+
42
+ should "not remove existing config options when configuring twice" do
43
+ first_config = nil
44
+ Cloudtrapper.configure do |config|
45
+ first_config = config
46
+ end
47
+ Cloudtrapper.configure do |config|
48
+ assert_equal first_config, config
49
+ end
50
+ end
51
+
52
+ should "configure the sender" do
53
+ sender = stub_sender
54
+ Cloudtrapper::Sender.stubs(:new => sender)
55
+ configuration = nil
56
+
57
+ Cloudtrapper.configure { |yielded_config| configuration = yielded_config }
58
+
59
+ assert_received(Cloudtrapper::Sender, :new) { |expect| expect.with(configuration) }
60
+ assert_equal sender, Cloudtrapper.sender
61
+ end
62
+
63
+ should "create and send a notice for an exception" do
64
+ set_public_env
65
+ exception = build_exception
66
+ stub_sender!
67
+ notice = stub_notice!
68
+
69
+ Cloudtrapper.notify(exception)
70
+
71
+ assert_sent notice, :exception => exception
72
+ end
73
+
74
+ should "create and send a notice for a hash" do
75
+ set_public_env
76
+ notice = stub_notice!
77
+ notice_args = { :error_message => 'uh oh' }
78
+ stub_sender!
79
+
80
+ Cloudtrapper.notify(notice_args)
81
+
82
+ assert_sent(notice, notice_args)
83
+ end
84
+
85
+ should "not pass the hash as an exception when sending a notice for it" do
86
+ set_public_env
87
+ notice = stub_notice!
88
+ notice_args = { :error_message => 'uh oh' }
89
+ stub_sender!
90
+
91
+ Cloudtrapper.notify(notice_args)
92
+
93
+ assert_received(Cloudtrapper::Notice, :new) {|expect| expect.with(Not(has_key(:exception))) }
94
+ end
95
+
96
+ should "create and send a notice for an exception that responds to to_hash" do
97
+ set_public_env
98
+ exception = build_exception
99
+ notice = stub_notice!
100
+ notice_args = { :error_message => 'uh oh' }
101
+ exception.stubs(:to_hash).returns(notice_args)
102
+ stub_sender!
103
+
104
+ Cloudtrapper.notify(exception)
105
+
106
+ assert_sent(notice, notice_args.merge(:exception => exception))
107
+ end
108
+
109
+ should "create and sent a notice for an exception and hash" do
110
+ set_public_env
111
+ exception = build_exception
112
+ notice = stub_notice!
113
+ notice_args = { :error_message => 'uh oh' }
114
+ stub_sender!
115
+
116
+ Cloudtrapper.notify(exception, notice_args)
117
+
118
+ assert_sent(notice, notice_args.merge(:exception => exception))
119
+ end
120
+
121
+ should "not create a notice in a development environment" do
122
+ set_development_env
123
+ sender = stub_sender!
124
+
125
+ Cloudtrapper.notify(build_exception)
126
+ Cloudtrapper.notify_or_ignore(build_exception)
127
+
128
+ assert_received(sender, :send_to_cloudtrapper) {|expect| expect.never }
129
+ end
130
+
131
+ should "not deliver an ignored exception when notifying implicitly" do
132
+ set_public_env
133
+ exception = build_exception
134
+ sender = stub_sender!
135
+ notice = stub_notice!
136
+ notice.stubs(:ignore? => true)
137
+
138
+ Cloudtrapper.notify_or_ignore(exception)
139
+
140
+ assert_received(sender, :send_to_cloudtrapper) {|expect| expect.never }
141
+ end
142
+
143
+ should "deliver an ignored exception when notifying manually" do
144
+ set_public_env
145
+ exception = build_exception
146
+ sender = stub_sender!
147
+ notice = stub_notice!
148
+ notice.stubs(:ignore? => true)
149
+
150
+ Cloudtrapper.notify(exception)
151
+
152
+ assert_sent(notice, :exception => exception)
153
+ end
154
+
155
+ should "pass config to created notices" do
156
+ exception = build_exception
157
+ config_opts = { 'one' => 'two', 'three' => 'four' }
158
+ notice = stub_notice!
159
+ stub_sender!
160
+ Cloudtrapper.configuration = stub('config', :merge => config_opts, :public? => true)
161
+
162
+ Cloudtrapper.notify(exception)
163
+
164
+ assert_received(Cloudtrapper::Notice, :new) do |expect|
165
+ expect.with(has_entries(config_opts))
166
+ end
167
+ end
168
+
169
+ context "building notice JSON for an exception" do
170
+ setup do
171
+ @params = { :controller => "users", :action => "create" }
172
+ @exception = build_exception
173
+ @hash = Cloudtrapper.build_lookup_hash_for(@exception, @params)
174
+ end
175
+
176
+ should "set action" do
177
+ assert_equal @params[:action], @hash[:action]
178
+ end
179
+
180
+ should "set controller" do
181
+ assert_equal @params[:controller], @hash[:component]
182
+ end
183
+
184
+ should "set line number" do
185
+ assert @hash[:line_number] =~ /\d+/
186
+ end
187
+
188
+ should "set file" do
189
+ assert_match /test\/helper\.rb$/, @hash[:file]
190
+ end
191
+
192
+ should "set rails_env to production" do
193
+ assert_equal 'production', @hash[:environment_name]
194
+ end
195
+
196
+ should "set error class" do
197
+ assert_equal @exception.class.to_s, @hash[:error_class]
198
+ end
199
+
200
+ should "not set file or line number with no backtrace" do
201
+ @exception.stubs(:backtrace).returns([])
202
+
203
+ @hash = Cloudtrapper.build_lookup_hash_for(@exception)
204
+
205
+ assert_nil @hash[:line_number]
206
+ assert_nil @hash[:file]
207
+ end
208
+
209
+ should "not set action or controller when not provided" do
210
+ @hash = Cloudtrapper.build_lookup_hash_for(@exception)
211
+
212
+ assert_nil @hash[:action]
213
+ assert_nil @hash[:controller]
214
+ end
215
+
216
+ context "when an exception that provides #original_exception is raised" do
217
+ setup do
218
+ @exception.stubs(:original_exception).returns(begin
219
+ raise NotifierTest::OriginalException.new
220
+ rescue Exception => e
221
+ e
222
+ end)
223
+ end
224
+
225
+ should "unwrap exceptions that provide #original_exception" do
226
+ @hash = Cloudtrapper.build_lookup_hash_for(@exception)
227
+ assert_equal "NotifierTest::OriginalException", @hash[:error_class]
228
+ end
229
+ end
230
+
231
+ context "when an exception that provides #continued_exception is raised" do
232
+ setup do
233
+ @exception.stubs(:continued_exception).returns(begin
234
+ raise NotifierTest::ContinuedException.new
235
+ rescue Exception => e
236
+ e
237
+ end)
238
+ end
239
+
240
+ should "unwrap exceptions that provide #continued_exception" do
241
+ @hash = Cloudtrapper.build_lookup_hash_for(@exception)
242
+ assert_equal "NotifierTest::ContinuedException", @hash[:error_class]
243
+ end
244
+ end
245
+ end
246
+ end
data/test/rack_test.rb ADDED
@@ -0,0 +1,58 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class RackTest < Test::Unit::TestCase
4
+
5
+ should "call the upstream app with the environment" do
6
+ environment = { 'key' => 'value' }
7
+ app = lambda { |env| ['response', {}, env] }
8
+ stack = Cloudtrapper::Rack.new(app)
9
+
10
+ response = stack.call(environment)
11
+
12
+ assert_equal ['response', {}, environment], response
13
+ end
14
+
15
+ should "deliver an exception raised while calling an upstream app" do
16
+ Cloudtrapper.stubs(:notify_or_ignore)
17
+
18
+ exception = build_exception
19
+ environment = { 'key' => 'value' }
20
+ app = lambda do |env|
21
+ raise exception
22
+ end
23
+
24
+ begin
25
+ stack = Cloudtrapper::Rack.new(app)
26
+ stack.call(environment)
27
+ rescue Exception => raised
28
+ assert_equal exception, raised
29
+ else
30
+ flunk "Didn't raise an exception"
31
+ end
32
+
33
+ assert_received(Cloudtrapper, :notify_or_ignore) do |expect|
34
+ expect.with(exception, :rack_env => environment)
35
+ end
36
+ end
37
+
38
+ should "deliver an exception in rack.exception" do
39
+ Cloudtrapper.stubs(:notify_or_ignore)
40
+ exception = build_exception
41
+ environment = { 'key' => 'value' }
42
+
43
+ response = [200, {}, ['okay']]
44
+ app = lambda do |env|
45
+ env['rack.exception'] = exception
46
+ response
47
+ end
48
+ stack = Cloudtrapper::Rack.new(app)
49
+
50
+ actual_response = stack.call(environment)
51
+
52
+ assert_equal response, actual_response
53
+ assert_received(Cloudtrapper, :notify_or_ignore) do |expect|
54
+ expect.with(exception, :rack_env => environment)
55
+ end
56
+ end
57
+
58
+ end
@@ -0,0 +1,36 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ require 'cloudtrapper/rails'
4
+
5
+ class RailsInitializerTest < Test::Unit::TestCase
6
+ include DefinesConstants
7
+
8
+ should "trigger use of Rails' logger if logger isn't set and Rails' logger exists" do
9
+ rails = Module.new do
10
+ def self.logger
11
+ "RAILS LOGGER"
12
+ end
13
+ end
14
+ define_constant("Rails", rails)
15
+ Cloudtrapper::Rails.initialize
16
+ assert_equal "RAILS LOGGER", Cloudtrapper.logger
17
+ end
18
+
19
+ should "trigger use of Rails' default logger if logger isn't set and Rails.logger doesn't exist" do
20
+ define_constant("RAILS_DEFAULT_LOGGER", "RAILS DEFAULT LOGGER")
21
+
22
+ Cloudtrapper::Rails.initialize
23
+ assert_equal "RAILS DEFAULT LOGGER", Cloudtrapper.logger
24
+ end
25
+
26
+ should "allow overriding of the logger if already assigned" do
27
+ define_constant("RAILS_DEFAULT_LOGGER", "RAILS DEFAULT LOGGER")
28
+ Cloudtrapper::Rails.initialize
29
+
30
+ Cloudtrapper.configure(true) do |config|
31
+ config.logger = "OVERRIDDEN LOGGER"
32
+ end
33
+
34
+ assert_equal "OVERRIDDEN LOGGER", Cloudtrapper.logger
35
+ end
36
+ end
@@ -0,0 +1,10 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class RecursionTest < Test::Unit::TestCase
4
+ should "not allow infinite recursion" do
5
+ hash = {:a => :a}
6
+ hash[:hash] = hash
7
+ notice = Cloudtrapper::Notice.new(:parameters => hash)
8
+ assert_equal "[possible infinite recursion halted]", notice.parameters[:hash]
9
+ end
10
+ end
@@ -0,0 +1,261 @@
1
+ require File.expand_path( File.join(File.dirname(__FILE__), 'helper') )
2
+
3
+ class SenderTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ reset_config
7
+ end
8
+
9
+ def build_sender(opts = {})
10
+ Cloudtrapper.configure do |conf|
11
+ opts.each {|opt, value| conf.send(:"#{opt}=", value) }
12
+ end
13
+ end
14
+
15
+ def send_exception(args = {})
16
+ notice = args.delete(:notice) || build_notice_data
17
+ sender = args.delete(:sender) || build_sender(args)
18
+ sender.send_to_cloudtrapper(notice)
19
+ end
20
+
21
+ def stub_http(options = {})
22
+ response = stub(:body => options[:body] || 'body')
23
+ http = stub(:post => response,
24
+ :read_timeout= => nil,
25
+ :open_timeout= => nil,
26
+ :ca_file= => nil,
27
+ :verify_mode= => nil,
28
+ :use_ssl= => nil)
29
+ Net::HTTP.stubs(:new => http)
30
+ http
31
+ end
32
+
33
+ should "post to Cloudtrapper when using an HTTP proxy" do
34
+ response = stub(:body => 'body')
35
+ http = stub(:post => response,
36
+ :read_timeout= => nil,
37
+ :open_timeout= => nil,
38
+ :use_ssl= => nil)
39
+ proxy = stub(:new => http)
40
+ Net::HTTP.stubs(:Proxy => proxy)
41
+
42
+ url = "http://api.cloudtrapper.io:80#{Cloudtrapper::Sender::NOTICES_URI}"
43
+ uri = URI.parse(url)
44
+
45
+ proxy_host = 'some.host'
46
+ proxy_port = 88
47
+ proxy_user = 'login'
48
+ proxy_pass = 'passwd'
49
+
50
+ send_exception(:proxy_host => proxy_host,
51
+ :proxy_port => proxy_port,
52
+ :proxy_user => proxy_user,
53
+ :proxy_pass => proxy_pass)
54
+ assert_received(http, :post) do |expect|
55
+ expect.with(uri.path, anything, Cloudtrapper::HEADERS)
56
+ end
57
+ assert_received(Net::HTTP, :Proxy) do |expect|
58
+ expect.with(proxy_host, proxy_port, proxy_user, proxy_pass)
59
+ end
60
+ end
61
+
62
+ should "return the created group's id on successful posting" do
63
+ http = stub_http(:body => '<id type="integer">3799307</id>')
64
+ assert_equal "3799307", send_exception(:secure => false)
65
+ end
66
+
67
+ context "when encountering exceptions: " do
68
+ context "HTTP connection setup problems" do
69
+ should "not be rescued" do
70
+ proxy = stub()
71
+ proxy.stubs(:new).raises(NoMemoryError)
72
+ Net::HTTP.stubs(:Proxy => proxy)
73
+
74
+ assert_raise NoMemoryError do
75
+ build_sender.send(:setup_http_connection)
76
+ end
77
+ end
78
+
79
+ should "be logged" do
80
+ proxy = stub()
81
+ proxy.stubs(:new).raises(RuntimeError)
82
+ Net::HTTP.stubs(:Proxy => proxy)
83
+
84
+ sender = build_sender
85
+ sender.expects(:log).with(:error, includes('Failure initializing the HTTP connection'))
86
+
87
+ assert_raise RuntimeError do
88
+ sender.send(:setup_http_connection)
89
+ end
90
+
91
+ end
92
+ end
93
+
94
+ context "unexpected exception sending problems" do
95
+ should "be logged" do
96
+ sender = build_sender
97
+ sender.stubs(:setup_http_connection).raises(RuntimeError.new)
98
+
99
+ sender.expects(:log).with(:error, includes('Cannot send notification. Error'))
100
+ sender.send_to_cloudtrapper("stuff")
101
+ end
102
+
103
+ should "return nil no matter what" do
104
+ sender = build_sender
105
+ sender.stubs(:setup_http_connection).raises(LocalJumpError)
106
+
107
+ assert_nothing_thrown do
108
+ assert_nil sender.send_to_cloudtrapper("stuff")
109
+ end
110
+ end
111
+ end
112
+
113
+ should "return nil on failed posting" do
114
+ http = stub_http
115
+ http.stubs(:post).raises(Errno::ECONNREFUSED)
116
+ assert_equal nil, send_exception(:secure => false)
117
+ end
118
+
119
+ should "not fail when posting and a timeout exception occurs" do
120
+ http = stub_http
121
+ http.stubs(:post).raises(TimeoutError)
122
+ assert_nothing_thrown do
123
+ send_exception(:secure => false)
124
+ end
125
+ end
126
+
127
+ should "not fail when posting and a connection refused exception occurs" do
128
+ http = stub_http
129
+ http.stubs(:post).raises(Errno::ECONNREFUSED)
130
+ assert_nothing_thrown do
131
+ send_exception(:secure => false)
132
+ end
133
+ end
134
+
135
+ should "not fail when posting any http exception occurs" do
136
+ http = stub_http
137
+ Cloudtrapper::Sender::HTTP_ERRORS.each do |error|
138
+ http.stubs(:post).raises(error)
139
+ assert_nothing_thrown do
140
+ send_exception(:secure => false)
141
+ end
142
+ end
143
+ end
144
+ end
145
+
146
+ context "SSL" do
147
+ should "post to the right url for non-ssl" do
148
+ http = stub_http
149
+ url = "http://api.cloudtrapper.io:80#{Cloudtrapper::Sender::NOTICES_URI}"
150
+ uri = URI.parse(url)
151
+ send_exception(:secure => false)
152
+ assert_received(http, :post) {|expect| expect.with(uri.path, anything, Cloudtrapper::HEADERS) }
153
+ end
154
+
155
+ should "post to the right path for ssl" do
156
+ http = stub_http
157
+ send_exception(:secure => true)
158
+ assert_received(http, :post) {|expect| expect.with(Cloudtrapper::Sender::NOTICES_URI, anything, Cloudtrapper::HEADERS) }
159
+ end
160
+
161
+ should "verify the SSL peer when the use_ssl option is set to true" do
162
+ url = "https://api.cloudtrapper.io#{Cloudtrapper::Sender::NOTICES_URI}"
163
+ uri = URI.parse(url)
164
+
165
+ real_http = Net::HTTP.new(uri.host, uri.port)
166
+ real_http.stubs(:post => nil)
167
+ proxy = stub(:new => real_http)
168
+ Net::HTTP.stubs(:Proxy => proxy)
169
+ File.stubs(:exist?).with(OpenSSL::X509::DEFAULT_CERT_FILE).returns(false)
170
+
171
+ send_exception(:secure => true)
172
+ assert(real_http.use_ssl?)
173
+ assert_equal(OpenSSL::SSL::VERIFY_PEER, real_http.verify_mode)
174
+ assert_equal(Cloudtrapper.configuration.local_cert_path, real_http.ca_file)
175
+ end
176
+
177
+ should "use the default DEFAULT_CERT_FILE if asked to" do
178
+ config = Cloudtrapper::Configuration.new
179
+ config.use_system_ssl_cert_chain = true
180
+ sender = Cloudtrapper::Sender.new(config)
181
+
182
+ assert(sender.use_system_ssl_cert_chain?)
183
+
184
+ http = sender.send(:setup_http_connection)
185
+ assert_not_equal http.ca_file, config.local_cert_path
186
+ end
187
+
188
+ should "verify the connection when the use_ssl option is set (VERIFY_PEER)" do
189
+ sender = build_sender(:secure => true)
190
+ http = sender.send(:setup_http_connection)
191
+ assert_equal(OpenSSL::SSL::VERIFY_PEER, http.verify_mode)
192
+ end
193
+
194
+ should "use the default cert (OpenSSL::X509::DEFAULT_CERT_FILE) only if explicitly told to" do
195
+ sender = build_sender(:secure => true)
196
+ http = sender.send(:setup_http_connection)
197
+
198
+ assert_equal(Cloudtrapper.configuration.local_cert_path, http.ca_file)
199
+
200
+ File.stubs(:exist?).with(OpenSSL::X509::DEFAULT_CERT_FILE).returns(true)
201
+ sender = build_sender(:secure => true, :use_system_ssl_cert_chain => true)
202
+ http = sender.send(:setup_http_connection)
203
+
204
+ assert_not_equal(Cloudtrapper.configuration.local_cert_path, http.ca_file)
205
+ assert_equal(OpenSSL::X509::DEFAULT_CERT_FILE, http.ca_file)
206
+ end
207
+
208
+ should "connect to the right port for ssl" do
209
+ stub_http
210
+ send_exception(:secure => true)
211
+ assert_received(Net::HTTP, :new) {|expect| expect.with("api.cloudtrapper.io", 443) }
212
+ end
213
+
214
+ should "connect to the right port for non-ssl" do
215
+ stub_http
216
+ send_exception(:secure => false)
217
+ assert_received(Net::HTTP, :new) {|expect| expect.with("api.cloudtrapper.io", 80) }
218
+ end
219
+
220
+ should "use ssl if secure" do
221
+ stub_http
222
+ send_exception(:secure => true, :host => 'example.org')
223
+ assert_received(Net::HTTP, :new) {|expect| expect.with('example.org', 443) }
224
+ end
225
+
226
+ should "not use ssl if not secure" do
227
+ stub_http
228
+ send_exception(:secure => false, :host => 'example.org')
229
+ assert_received(Net::HTTP, :new) {|expect| expect.with('example.org', 80) }
230
+ end
231
+
232
+
233
+ end
234
+
235
+ context "network timeouts" do
236
+ should "default the open timeout to 2 seconds" do
237
+ http = stub_http
238
+ send_exception
239
+ assert_received(http, :open_timeout=) {|expect| expect.with(2) }
240
+ end
241
+
242
+ should "default the read timeout to 5 seconds" do
243
+ http = stub_http
244
+ send_exception
245
+ assert_received(http, :read_timeout=) {|expect| expect.with(5) }
246
+ end
247
+
248
+ should "allow override of the open timeout" do
249
+ http = stub_http
250
+ send_exception(:http_open_timeout => 4)
251
+ assert_received(http, :open_timeout=) {|expect| expect.with(4) }
252
+ end
253
+
254
+ should "allow override of the read timeout" do
255
+ http = stub_http
256
+ send_exception(:http_read_timeout => 10)
257
+ assert_received(http, :read_timeout=) {|expect| expect.with(10) }
258
+ end
259
+ end
260
+
261
+ end
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class UserInformerTest < Test::Unit::TestCase
4
+ should "modify output if there is an cloudtrapper id" do
5
+ main_app = lambda do |env|
6
+ env['cloudtrapper.error_id'] = 1
7
+ [200, {}, ["<!-- AIRBRAKE ERROR -->"]]
8
+ end
9
+ informer_app = Cloudtrapper::UserInformer.new(main_app)
10
+
11
+ ShamRack.mount(informer_app, "example.com")
12
+
13
+ response = Net::HTTP.get_response(URI.parse("http://example.com/"))
14
+ assert_equal "Cloudtrapper Error 1", response.body
15
+ assert_equal 16, response["Content-Length"].to_i
16
+ end
17
+
18
+ should "not modify output if there is no cloudtrapper id" do
19
+ main_app = lambda do |env|
20
+ [200, {}, ["<!-- AIRBRAKE ERROR -->"]]
21
+ end
22
+ informer_app = Cloudtrapper::UserInformer.new(main_app)
23
+
24
+ ShamRack.mount(informer_app, "example.com")
25
+
26
+ response = Net::HTTP.get_response(URI.parse("http://example.com/"))
27
+ assert_equal "<!-- AIRBRAKE ERROR -->", response.body
28
+ end
29
+ end