hydraulic_brake 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,105 @@
1
+ require File.expand_path '../helper', __FILE__
2
+
3
+ class AsyncSenderTest < Test::Unit::TestCase
4
+ def setup
5
+ reset_config
6
+ end
7
+
8
+ def build_sync_sender
9
+ klass = Class.new do
10
+ attr_reader :notices_sent
11
+
12
+ def send_to_airbrake(notice)
13
+ @notices_sent ||= []
14
+ @notices_sent.push notice
15
+ end
16
+ end
17
+
18
+ klass.new
19
+ end
20
+
21
+ def build_sender(opts = {})
22
+ HydraulicBrake::AsyncSender.new(
23
+ :sync_sender => build_sync_sender,
24
+ :capacity => 5)
25
+ end
26
+
27
+ def build_notice
28
+ HydraulicBrake::Notice.new(
29
+ :error_class => "FooBar", :error_message => "Foo Bar")
30
+ end
31
+
32
+ def wait_for_thread(thread)
33
+ # wait for the sending thread to stop running
34
+ while thread.status == 'run'
35
+ sleep 0.01
36
+ end
37
+ end
38
+
39
+ def mock_logger
40
+ logger_class = Class.new do
41
+ attr_reader :errors
42
+
43
+ def error(blob)
44
+ @errors ||= []
45
+ @errors.push(blob)
46
+ end
47
+
48
+ def debug(blob); end
49
+ end
50
+
51
+ logger_class.new
52
+ end
53
+
54
+ should "send a notice" do
55
+ notice = build_notice
56
+ sender = build_sender
57
+
58
+ sender.send_to_airbrake(notice)
59
+ wait_for_thread(sender.thread)
60
+
61
+ notices_sent = sender.sync_sender.notices_sent
62
+ assert notices_sent == [ notice ]
63
+ end
64
+
65
+ should "send multiple notices" do
66
+ notice1 = build_notice
67
+ notice2 = build_notice
68
+ notice3 = build_notice
69
+ sender = build_sender
70
+
71
+ sender.send_to_airbrake(notice1)
72
+ sender.send_to_airbrake(notice2)
73
+ sender.send_to_airbrake(notice3)
74
+
75
+ wait_for_thread(sender.thread)
76
+
77
+ notices_sent = sender.sync_sender.notices_sent
78
+ assert notices_sent == [ notice1, notice2, notice3 ]
79
+ end
80
+
81
+ should "reach capacity and stop accepting notices" do
82
+ logger = mock_logger
83
+
84
+ HydraulicBrake.configure do |c|
85
+ c.logger = logger
86
+ end
87
+
88
+ notices = (1..100).map { build_notice }
89
+ sender = build_sender
90
+
91
+ notices.each { |n| sender.send_to_airbrake n }
92
+ wait_for_thread(sender.thread)
93
+ notices_sent = sender.sync_sender.notices_sent
94
+
95
+ assert(
96
+ notices_sent[0, 5] == notices[0, 5],
97
+ 'at least the first five errors should be delivered')
98
+ assert(
99
+ notices_sent.size < 100,
100
+ 'less than all the errors should be delivered')
101
+ assert(
102
+ logger.errors.size == notices.size - notices_sent.size,
103
+ 'for every error that was not delivered, an error should be logged')
104
+ end
105
+ end
@@ -5,20 +5,21 @@ class ConfigurationTest < Test::Unit::TestCase
5
5
  include DefinesConstants
6
6
 
7
7
  should "provide default values" do
8
- assert_config_default :proxy_host, nil
9
- assert_config_default :proxy_port, nil
10
- assert_config_default :proxy_user, nil
11
- assert_config_default :proxy_pass, nil
12
- assert_config_default :project_root, nil
13
- assert_config_default :environment_name, nil
14
- assert_config_default :logger, nil
15
- assert_config_default :notifier_version, HydraulicBrake::VERSION
16
- assert_config_default :notifier_name, 'HydraulicBrake Notifier'
17
- assert_config_default :notifier_url, 'https://github.com/stevecrozz/hydraulic_brake'
18
- assert_config_default :secure, false
19
- assert_config_default :host, 'api.airbrake.io'
20
- assert_config_default :http_open_timeout, 2
21
- assert_config_default :http_read_timeout, 5
8
+ assert_config_default :async, false
9
+ assert_config_default :async_queue_capacity, 100
10
+ assert_config_default :proxy_host, nil
11
+ assert_config_default :proxy_port, nil
12
+ assert_config_default :proxy_user, nil
13
+ assert_config_default :proxy_pass, nil
14
+ assert_config_default :project_root, nil
15
+ assert_config_default :environment_name, nil
16
+ assert_config_default :notifier_version, HydraulicBrake::VERSION
17
+ assert_config_default :notifier_name, 'HydraulicBrake Notifier'
18
+ assert_config_default :notifier_url, 'https://github.com/stevecrozz/hydraulic_brake'
19
+ assert_config_default :secure, false
20
+ assert_config_default :host, 'api.airbrake.io'
21
+ assert_config_default :http_open_timeout, 2
22
+ assert_config_default :http_read_timeout, 5
22
23
  assert_config_default :params_filters,
23
24
  HydraulicBrake::Configuration::DEFAULT_PARAMS_FILTERS
24
25
  assert_config_default :backtrace_filters,
@@ -51,6 +52,8 @@ class ConfigurationTest < Test::Unit::TestCase
51
52
  end
52
53
 
53
54
  should "allow values to be overwritten" do
55
+ assert_config_overridable :async
56
+ assert_config_overridable :async_queue_capacity
54
57
  assert_config_overridable :proxy_host
55
58
  assert_config_overridable :proxy_port
56
59
  assert_config_overridable :proxy_user
@@ -110,7 +113,7 @@ class ConfigurationTest < Test::Unit::TestCase
110
113
 
111
114
  should "use development and test as development environments by default" do
112
115
  config = HydraulicBrake::Configuration.new
113
- assert_same_elements %w(development test cucumber), config.development_environments
116
+ assert_same_elements %w(development test), config.development_environments
114
117
  end
115
118
 
116
119
  should "be public in a public environment" do
@@ -132,6 +135,11 @@ class ConfigurationTest < Test::Unit::TestCase
132
135
  assert config.public?
133
136
  end
134
137
 
138
+ should "use the default logger none is set" do
139
+ config = HydraulicBrake::Configuration.new
140
+ assert_kind_of Logger, config.logger
141
+ end
142
+
135
143
  should "use the assigned logger if set" do
136
144
  config = HydraulicBrake::Configuration.new
137
145
  config.logger = "CUSTOM LOGGER"
@@ -1,14 +1,17 @@
1
1
  require 'simplecov'
2
- SimpleCov.start
2
+ SimpleCov.start do
3
+ add_filter '/test/'
4
+ end
3
5
  require 'test/unit'
4
6
  require 'rubygems'
5
7
 
6
8
  $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
7
9
 
10
+ require 'mocha/setup'
11
+ require 'bourne'
8
12
  require 'shoulda'
9
13
  require 'nokogiri'
10
- require 'bourne'
11
- require "hydraulic_brake"
14
+ require 'hydraulic_brake'
12
15
 
13
16
  begin require 'redgreen'; rescue LoadError; end
14
17
 
@@ -93,6 +96,7 @@ class Test::Unit::TestCase
93
96
  HydraulicBrake.configuration = nil
94
97
  HydraulicBrake.configure do |config|
95
98
  config.api_key = 'abc123'
99
+ config.logger = FakeLogger.new
96
100
  end
97
101
  end
98
102
 
@@ -128,6 +132,10 @@ class Test::Unit::TestCase
128
132
  }
129
133
  end
130
134
 
135
+ def build_notice(exception = nil)
136
+ HydraulicBrake::Notice.new(build_notice_data(exception))
137
+ end
138
+
131
139
  def assert_caught_and_sent
132
140
  assert !HydraulicBrake.sender.collected.empty?
133
141
  end
@@ -11,7 +11,7 @@ class LoggerTest < Test::Unit::TestCase
11
11
  end
12
12
 
13
13
  def send_notice
14
- HydraulicBrake.sender.send_to_airbrake({'foo' => "bar"})
14
+ HydraulicBrake.sender.send_to_airbrake(build_notice)
15
15
  end
16
16
 
17
17
  def stub_verbose_log
@@ -131,7 +131,8 @@ class NotifierTest < Test::Unit::TestCase
131
131
  config_opts = { 'one' => 'two', 'three' => 'four' }
132
132
  stub_notice!
133
133
  stub_sender!
134
- HydraulicBrake.configuration = stub('config', :merge => config_opts, :public? => true)
134
+ HydraulicBrake.configuration = stub(
135
+ 'config', :merge => config_opts, :public? => true, :async => false)
135
136
 
136
137
  HydraulicBrake.notify(exception)
137
138
 
@@ -140,6 +141,22 @@ class NotifierTest < Test::Unit::TestCase
140
141
  end
141
142
  end
142
143
 
144
+ should "use sync sender when async is false" do
145
+ HydraulicBrake.configure do |config|
146
+ config.async = false
147
+ end
148
+
149
+ assert_kind_of HydraulicBrake::Sender, HydraulicBrake.sender
150
+ end
151
+
152
+ should "use async sender when async is true" do
153
+ HydraulicBrake.configure do |config|
154
+ config.async = true
155
+ end
156
+
157
+ assert_kind_of HydraulicBrake::AsyncSender, HydraulicBrake.sender
158
+ end
159
+
143
160
  context "building notice JSON for an exception" do
144
161
  setup do
145
162
  @params = { :controller => "users", :action => "create" }
@@ -12,15 +12,27 @@ class SenderTest < Test::Unit::TestCase
12
12
  end
13
13
  end
14
14
 
15
+ def build_logger
16
+ klass = Class.new do
17
+ attr_reader :errors, :infos, :debugs
18
+
19
+ def error(i); @errors ||= []; @errors << i; end
20
+ def info(i); @infos ||= []; @infos << i; end
21
+ def debug(i); @debugs ||= []; @debugs << i; end
22
+ end
23
+
24
+ klass.new
25
+ end
26
+
15
27
  def send_exception(args = {})
16
- notice = args.delete(:notice) || build_notice_data
17
- notice.stubs(:to_xml)
28
+ notice = args.delete(:notice) || HydraulicBrake::Notice.new(args)
18
29
  sender = args.delete(:sender) || build_sender(args)
19
30
  sender.send_to_airbrake(notice)
20
31
  end
21
32
 
22
- def stub_http(options = {})
23
- response = stub(:body => options[:body] || 'body')
33
+ def stub_http(response=nil)
34
+ response ||= stub(:body => 'body')
35
+
24
36
  http = stub(:post => response,
25
37
  :read_timeout= => nil,
26
38
  :open_timeout= => nil,
@@ -31,19 +43,6 @@ class SenderTest < Test::Unit::TestCase
31
43
  http
32
44
  end
33
45
 
34
- should "post to Airbrake with XML passed" do
35
- xml_notice = HydraulicBrake::Notice.new(:error_class => "FooBar", :error_message => "Foo Bar").to_xml
36
-
37
- http = stub_http
38
-
39
- sender = build_sender
40
- sender.send_to_airbrake(xml_notice)
41
-
42
- assert_received(http, :post) do |expect|
43
- expect.with(anything, xml_notice, HydraulicBrake::HEADERS)
44
- end
45
- end
46
-
47
46
  should "post to Airbrake with a Notice instance passed" do
48
47
  notice = HydraulicBrake::Notice.new(:error_class => "FooBar", :error_message => "Foo Bar")
49
48
 
@@ -87,10 +86,33 @@ class SenderTest < Test::Unit::TestCase
87
86
  end
88
87
 
89
88
  should "return the created group's id on successful posting" do
90
- http = stub_http(:body => '<id type="integer">3799307</id>')
89
+ response = Net::HTTPSuccess.new(1.0, 200, "OK")
90
+ def response.body
91
+ '<id type="integer">3799307</id>'
92
+ end
93
+
94
+ stub_http(response)
91
95
  assert_equal "3799307", send_exception(:secure => false)
92
96
  end
93
97
 
98
+ should "log the url to the error on successful posting" do
99
+ response = Net::HTTPSuccess.new(1.0, 200, "OK")
100
+ def response.body
101
+ '<id type="integer">3799307</id><url>http://some-url.com/foo</url>'
102
+ end
103
+
104
+ logger = build_logger
105
+
106
+ HydraulicBrake.configure do |c|
107
+ c.logger = logger
108
+ end
109
+
110
+ stub_http(response)
111
+ send_exception(:secure => false)
112
+ matcher = %r{Success: sent error to Airbrake: http://some-url.com/foo}
113
+ assert_match matcher, logger.infos.first
114
+ end
115
+
94
116
  context "when encountering exceptions: " do
95
117
  context "HTTP connection setup problems" do
96
118
  should "not be rescued" do
metadata CHANGED
@@ -1,190 +1,139 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hydraulic_brake
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
5
- prerelease:
4
+ version: 0.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Stephen Crosby
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-07-19 00:00:00.000000000 Z
11
+ date: 2015-09-03 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: builder
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: bourne
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - "~>"
36
32
  - !ruby/object:Gem::Version
37
- version: '1.0'
33
+ version: 1.5.0
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - "~>"
44
39
  - !ruby/object:Gem::Version
45
- version: '1.0'
46
- - !ruby/object:Gem::Dependency
47
- name: cucumber
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
- requirements:
51
- - - ~>
52
- - !ruby/object:Gem::Version
53
- version: 0.10.6
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ~>
60
- - !ruby/object:Gem::Version
61
- version: 0.10.6
40
+ version: 1.5.0
62
41
  - !ruby/object:Gem::Dependency
63
42
  name: fakeweb
64
43
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
44
  requirements:
67
- - - ~>
45
+ - - "~>"
68
46
  - !ruby/object:Gem::Version
69
47
  version: 1.3.0
70
48
  type: :development
71
49
  prerelease: false
72
50
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
51
  requirements:
75
- - - ~>
52
+ - - "~>"
76
53
  - !ruby/object:Gem::Version
77
54
  version: 1.3.0
78
55
  - !ruby/object:Gem::Dependency
79
56
  name: jeweler
80
57
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
58
  requirements:
83
- - - ! '>='
59
+ - - ">="
84
60
  - !ruby/object:Gem::Version
85
61
  version: '0'
86
62
  type: :development
87
63
  prerelease: false
88
64
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
65
  requirements:
91
- - - ! '>='
66
+ - - ">="
92
67
  - !ruby/object:Gem::Version
93
68
  version: '0'
94
69
  - !ruby/object:Gem::Dependency
95
70
  name: nokogiri
96
71
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
72
  requirements:
99
- - - ~>
73
+ - - "~>"
100
74
  - !ruby/object:Gem::Version
101
75
  version: 1.4.3.1
102
76
  type: :development
103
77
  prerelease: false
104
78
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
79
  requirements:
107
- - - ~>
80
+ - - "~>"
108
81
  - !ruby/object:Gem::Version
109
82
  version: 1.4.3.1
110
83
  - !ruby/object:Gem::Dependency
111
84
  name: rake
112
85
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
86
  requirements:
115
- - - ! '>='
87
+ - - ">="
116
88
  - !ruby/object:Gem::Version
117
89
  version: '0'
118
90
  type: :development
119
91
  prerelease: false
120
92
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
93
  requirements:
123
- - - ! '>='
94
+ - - ">="
124
95
  - !ruby/object:Gem::Version
125
96
  version: '0'
126
- - !ruby/object:Gem::Dependency
127
- name: rspec
128
- requirement: !ruby/object:Gem::Requirement
129
- none: false
130
- requirements:
131
- - - ~>
132
- - !ruby/object:Gem::Version
133
- version: 2.6.0
134
- type: :development
135
- prerelease: false
136
- version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
- requirements:
139
- - - ~>
140
- - !ruby/object:Gem::Version
141
- version: 2.6.0
142
97
  - !ruby/object:Gem::Dependency
143
98
  name: shoulda
144
99
  requirement: !ruby/object:Gem::Requirement
145
- none: false
146
100
  requirements:
147
- - - ~>
101
+ - - "~>"
148
102
  - !ruby/object:Gem::Version
149
103
  version: 2.11.3
150
104
  type: :development
151
105
  prerelease: false
152
106
  version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
107
  requirements:
155
- - - ~>
108
+ - - "~>"
156
109
  - !ruby/object:Gem::Version
157
110
  version: 2.11.3
158
111
  - !ruby/object:Gem::Dependency
159
112
  name: simplecov
160
113
  requirement: !ruby/object:Gem::Requirement
161
- none: false
162
114
  requirements:
163
- - - ! '>='
115
+ - - ">="
164
116
  - !ruby/object:Gem::Version
165
117
  version: '0'
166
118
  type: :development
167
119
  prerelease: false
168
120
  version_requirements: !ruby/object:Gem::Requirement
169
- none: false
170
121
  requirements:
171
- - - ! '>='
122
+ - - ">="
172
123
  - !ruby/object:Gem::Version
173
124
  version: '0'
174
125
  - !ruby/object:Gem::Dependency
175
126
  name: yard
176
127
  requirement: !ruby/object:Gem::Requirement
177
- none: false
178
128
  requirements:
179
- - - ! '>='
129
+ - - ">="
180
130
  - !ruby/object:Gem::Version
181
131
  version: '0'
182
132
  type: :development
183
133
  prerelease: false
184
134
  version_requirements: !ruby/object:Gem::Requirement
185
- none: false
186
135
  requirements:
187
- - - ! '>='
136
+ - - ">="
188
137
  - !ruby/object:Gem::Version
189
138
  version: '0'
190
139
  description: Sends notifications to an Airbrake server
@@ -194,35 +143,30 @@ extensions: []
194
143
  extra_rdoc_files:
195
144
  - README.md
196
145
  files:
197
- - .rbenv-version
198
- - .rvmrc
199
- - .yardopts
146
+ - ".gitignore"
147
+ - ".rvmrc"
148
+ - ".travis.yml"
149
+ - ".yardopts"
200
150
  - Gemfile
201
151
  - INSTALL
202
152
  - MIT-LICENSE
203
153
  - README.md
204
154
  - Rakefile
205
155
  - VERSION
206
- - features/rake.feature
207
- - features/step_definitions/rake_steps.rb
208
- - features/support/matchers.rb
209
- - features/support/rake/Rakefile
210
- - features/support/terminal.rb
211
156
  - hydraulic_brake.gemspec
212
157
  - lib/hydraulic_brake.rb
158
+ - lib/hydraulic_brake/async_sender.rb
213
159
  - lib/hydraulic_brake/backtrace.rb
214
160
  - lib/hydraulic_brake/configuration.rb
215
- - lib/hydraulic_brake/hook.rb
216
161
  - lib/hydraulic_brake/notice.rb
217
162
  - lib/hydraulic_brake/sender.rb
218
163
  - lib/hydraulic_brake/test_notification.rb
219
164
  - lib/hydraulic_brake/version.rb
220
- - lib/hydraulic_brake_tasks.rb
221
165
  - resources/README.md
222
166
  - resources/ca-bundle.crt
223
- - script/deploy_integration_test.rb
224
167
  - script/notify_integration_test.rb
225
168
  - test/airbrake_2_3.xsd
169
+ - test/async_sender_test.rb
226
170
  - test/backtrace_test.rb
227
171
  - test/configuration_test.rb
228
172
  - test/helper.rb
@@ -234,29 +178,26 @@ files:
234
178
  homepage: http://github.com/stevecrozz/hydraulic_brake
235
179
  licenses:
236
180
  - MIT
181
+ metadata: {}
237
182
  post_install_message:
238
183
  rdoc_options: []
239
184
  require_paths:
240
185
  - lib
241
186
  required_ruby_version: !ruby/object:Gem::Requirement
242
- none: false
243
187
  requirements:
244
- - - ! '>='
188
+ - - ">="
245
189
  - !ruby/object:Gem::Version
246
190
  version: '0'
247
- segments:
248
- - 0
249
- hash: -2276683694056635469
250
191
  required_rubygems_version: !ruby/object:Gem::Requirement
251
- none: false
252
192
  requirements:
253
- - - ! '>='
193
+ - - ">="
254
194
  - !ruby/object:Gem::Version
255
195
  version: '0'
256
196
  requirements: []
257
197
  rubyforge_project:
258
- rubygems_version: 1.8.23
198
+ rubygems_version: 2.2.2
259
199
  signing_key:
260
200
  specification_version: 3
261
201
  summary: Simple Airbrake client
262
202
  test_files: []
203
+ has_rdoc: