fiveruns-dash-ruby 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,204 @@
1
+ require File.dirname(__FILE__) << "/test_helper"
2
+
3
+ class MetricTest < Test::Unit::TestCase
4
+
5
+ attr_reader :metric
6
+
7
+ def self.time_me(val=0)
8
+ if val == 0
9
+ time_me(1)
10
+ end
11
+ sleep 0.01
12
+ end
13
+
14
+ context "Metric" do
15
+
16
+ teardown do
17
+ # Hacked 'uninstrument' until it's built-in
18
+ ::Fiveruns::Dash::Instrument.handlers.each do |handler|
19
+ (class << MetricTest; self; end).class_eval <<-EOCE
20
+ remove_method :time_me_with_instrument_#{handler.hash}
21
+ alias_method :time_me, :time_me_without_instrument_#{handler.hash}
22
+ remove_method :time_me_without_instrument_#{handler.hash}
23
+ EOCE
24
+ end
25
+ ::Fiveruns::Dash::Instrument.handlers.clear
26
+ end
27
+
28
+ context "should parse arguments for name, description and help_text" do
29
+ setup do
30
+ @options = Hash.new
31
+ @options[:method] = time_method
32
+ @metric = TimeMetric.new(:name, "Description", "HelpText", :method => time_method)
33
+ end
34
+
35
+ should "interpret name" do
36
+ assert_equal "name", @metric.name
37
+ end
38
+
39
+ should "interpret description" do
40
+ assert_equal "Description", @metric.description
41
+ end
42
+
43
+ should "interpret help text" do
44
+ assert_equal "HelpText", @metric.help_text
45
+ end
46
+
47
+ should "interpret options" do
48
+ assert_equal @options, @metric.options
49
+ end
50
+ end
51
+
52
+ context "should parse arguments for name, description using defaults" do
53
+ setup do
54
+ @options = Hash.new
55
+ @options[:method] = time_method
56
+ @metric = TimeMetric.new(:name, :method => time_method)
57
+ end
58
+
59
+ should "interpret name" do
60
+ assert_equal "name", @metric.name
61
+ end
62
+
63
+ should "default description to titleized name" do
64
+ assert_equal "Name", @metric.description
65
+ end
66
+
67
+ should "default help text to nil" do
68
+ assert_nil @metric.help_text
69
+ end
70
+
71
+ should "interpret options" do
72
+ assert_equal @options, @metric.options
73
+ end
74
+ end
75
+
76
+ context "using reentrant time" do
77
+ setup do
78
+ @metric = TimeMetric.new(:time_mes, :method => time_method, :reentrant => true)
79
+ flexmock(@metric).should_receive(:info_id).and_return(1)
80
+ end
81
+ teardown do
82
+ # Hacked 'uninstrument' until it's built-in
83
+ ::Fiveruns::Dash::Instrument.handlers.each do |handler|
84
+ (class << MetricTest; self; end).class_eval <<-EOCE
85
+ remove_method :time_me_with_instrument_#{handler.hash}
86
+ alias_method :time_me, :time_me_without_instrument_#{handler.hash}
87
+ remove_method :time_me_without_instrument_#{handler.hash}
88
+ EOCE
89
+ end
90
+ ::Fiveruns::Dash::Instrument.handlers.clear
91
+ end
92
+ should "get correct number of invocations" do
93
+ invoke 4
94
+ assert_invocations_reported 4
95
+ invoke 1
96
+ assert_invocations_reported 1
97
+ end
98
+ end
99
+
100
+ context "using time" do
101
+ setup do
102
+ @metric = TimeMetric.new(:time_mes, :method => time_method)
103
+ flexmock(@metric).should_receive(:info_id).and_return(1)
104
+ end
105
+ teardown do
106
+ # Hacked 'uninstrument' until it's built-in
107
+ ::Fiveruns::Dash::Instrument.handlers.each do |handler|
108
+ (class << MetricTest; self; end).class_eval <<-EOCE
109
+ remove_method :time_me_with_instrument_#{handler.hash}
110
+ alias_method :time_me, :time_me_without_instrument_#{handler.hash}
111
+ remove_method :time_me_without_instrument_#{handler.hash}
112
+ EOCE
113
+ end
114
+ ::Fiveruns::Dash::Instrument.handlers.clear
115
+ end
116
+ should "raise exception without :on option" do
117
+ assert_raises ArgumentError do
118
+ TimeMetric.new(:time_mes, 'A Name')
119
+ end
120
+ end
121
+ should "get correct number of invocations" do
122
+ invoke 4
123
+ assert_invocations_reported 8
124
+ invoke 1
125
+ assert_invocations_reported 2
126
+ end
127
+ should "time invocations" do
128
+ last_total = 0
129
+ 4.times do |i|
130
+ invoke
131
+ assert_equal (i + 1)*2, current_invocations
132
+ reported_total = current_time_total
133
+ assert(reported_total > last_total)
134
+ last_total = reported_total
135
+ end
136
+ metric.data # clears
137
+ assert_equal 0, current_time_total
138
+ end
139
+ should "have correct info" do
140
+ assert_equal 'time_mes', metric.info[:name]
141
+ assert_equal 'Time Mes', metric.info[:description]
142
+ end
143
+ should "be able to set context finder" do
144
+ finder = lambda { |obj, *args| [:class, obj.name] }
145
+ @metric.find_context_with(&finder)
146
+ invoke 4
147
+ assert_equal 8, metric.data[:values].select { |m| m[:context] == [:class, 'MetricTest'] }.first[:invocations]
148
+ end
149
+ end
150
+
151
+ context "using incremented counter" do
152
+ setup do
153
+ @metric = CounterMetric.new(:time_mes_counter, :incremented_by => time_method)
154
+ flexmock(@metric).should_receive(:info_id).and_return(1)
155
+ end
156
+ should "default to 0 before being incremented, and after reset" do
157
+ assert_counted 0
158
+ invoke 4
159
+ assert_counted 8
160
+ assert_counted 0
161
+ end
162
+ should "get correct number after being incremented" do
163
+ invoke 4
164
+ assert_counted 8
165
+ end
166
+ end
167
+
168
+ end
169
+
170
+ #######
171
+ private
172
+ #######
173
+
174
+ def current_time_total
175
+ metric.instance_eval { @data[[]][:value] }
176
+ end
177
+
178
+ def current_invocations
179
+ metric.instance_eval { @data[[]][:invocations] }
180
+ end
181
+
182
+ def time_method
183
+ 'MetricTest.time_me'
184
+ end
185
+
186
+ def assert_counted(number)
187
+ counted = nil
188
+ assert_nothing_raised do
189
+ # We fetch to ensure values aren't just being returned due to hash defaults
190
+ counted = metric.data[:values].detect { |m| m[:context] == [] }[:value]
191
+ end
192
+ assert_kind_of Numeric, counted
193
+ assert_equal number, counted
194
+ end
195
+
196
+ def assert_invocations_reported(number = 1)
197
+ assert_equal number, metric.data[:values].detect { |m| m[:context] == [] }[:invocations]
198
+ end
199
+
200
+ def invoke(number = 1)
201
+ number.times { MetricTest.time_me }
202
+ end
203
+
204
+ end
@@ -0,0 +1,146 @@
1
+ require File.dirname(__FILE__) << "/test_helper"
2
+
3
+ class RecipeTest < Test::Unit::TestCase
4
+
5
+ attr_reader :config
6
+
7
+ context "Recipe" do
8
+
9
+ setup do
10
+ mock_streams!
11
+ Fiveruns::Dash.recipes.clear
12
+ @config = Fiveruns::Dash::Configuration.new
13
+ end
14
+
15
+ teardown do
16
+ restore_streams!
17
+ end
18
+
19
+ context "when registering" do
20
+ context "with valid metadata" do
21
+ setup do
22
+ assert_nothing_raised do
23
+ recipe do |metrics|
24
+ metrics.counter :foo do
25
+ 1
26
+ end
27
+ end
28
+ end
29
+ end
30
+ should "is added to available recipes" do
31
+ assert_equal 1, Fiveruns::Dash.recipes.size
32
+ assert_kind_of Array, Fiveruns::Dash.recipes[:test]
33
+ assert_kind_of Fiveruns::Dash::Recipe, Fiveruns::Dash.recipes[:test].first
34
+ end
35
+ end
36
+ context "without url" do
37
+ should "raise error" do
38
+ assert_raises Fiveruns::Dash::Recipe::ConfigurationError do
39
+ recipe(:test, {}) do |metrics|
40
+ metrics.counter :foo do
41
+ 1
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ context "when adding" do
51
+ context "with single matching recipe" do
52
+ setup do
53
+ recipe :test, :url => 'http://test1.com' do |r|
54
+ r.counter(:test1) { }
55
+ end
56
+ config.add_recipe :test
57
+ end
58
+ should "description" do
59
+ assert_metrics(*%w(test1))
60
+ end
61
+ end
62
+ context "with multiple similiarly-named recipes" do
63
+ setup do
64
+ recipe :test, :url => 'http://test1.com' do |r|
65
+ r.counter(:test1) { }
66
+ end
67
+ recipe :test, :url => 'http://test2.com' do |r|
68
+ r.counter(:test2) { }
69
+ end
70
+ end
71
+ should "load all by default" do
72
+ config.add_recipe :test
73
+ assert_equal 2, config.metrics.size
74
+ assert_metrics(*%w(test1 test2))
75
+ end
76
+ should "allow specific recipe to be loaded" do
77
+ config.add_recipe :test, :url => 'http://test2.com'
78
+ assert_equal 1, config.metrics.size
79
+ assert_metrics(*%w(test2))
80
+ end
81
+ end
82
+ end
83
+
84
+ context "when added" do
85
+ setup do
86
+ @fired = false
87
+ recipe :test, :url => 'http://test.com' do |recipe|
88
+ recipe.added do
89
+ @fired = true
90
+ end
91
+ recipe.counter(:countme) { }
92
+ end
93
+ end
94
+ should "fire recipe hook" do
95
+ config.add_recipe :test
96
+ assert @fired
97
+ end
98
+ should "allow metrics with same name and different recipes" do
99
+ config.counter(:countme) { }
100
+ config.add_recipe :test
101
+ assert_metrics(*%w(countme countme))
102
+ end
103
+ context "modifying existing metrics" do
104
+ setup do
105
+ recipe :test3 do |r|
106
+ r.modify :name => :countme do |metric|
107
+ metric.find_context_with do |obj, *args|
108
+ [:modified, true]
109
+ end
110
+ end
111
+ end
112
+ end
113
+ should "only occur on addition" do
114
+ config.metrics.each do |metric|
115
+ if metric.name == 'countme'
116
+ assert_nil metric.instance_eval { @metric_finder }
117
+ end
118
+ end
119
+ end
120
+ should "change context finder" do
121
+ config.add_recipe :test3
122
+ config.metrics.each do |metric|
123
+ if metric.name == 'countme'
124
+ assert_kind_of Proc, metric.instance_eval { @metric_finder }
125
+ end
126
+ end
127
+ end
128
+ end
129
+
130
+ end
131
+
132
+ end
133
+
134
+ #######
135
+ private
136
+ #######
137
+
138
+ def assert_metrics(*names)
139
+ assert_equal names.sort, config.metrics.map(&:name).map(&:to_s).sort
140
+ end
141
+
142
+ def recipe(name = :test, options = {:url => 'http://test.com'}, &block)
143
+ Fiveruns::Dash.register_recipe(name, options, &block)
144
+ end
145
+
146
+ end
@@ -0,0 +1,60 @@
1
+ require File.dirname(__FILE__) << "/test_helper"
2
+
3
+ class Gizmo
4
+
5
+ def oops!
6
+ raise 'I made an oopsie!'
7
+ end
8
+
9
+ end
10
+
11
+ class ReliabilityTest < Test::Unit::TestCase
12
+
13
+ context "FiveRuns Dash" do
14
+
15
+ should 'not swallow user-created exceptions' do
16
+ dash do |metrics|
17
+ metrics.time(:oops, 'Time spent messing up', 'Ooops!',
18
+ :method => 'Gizmo#oops!')
19
+ end
20
+
21
+ assert_raises(RuntimeError) { Gizmo.new.oops! }
22
+ end
23
+
24
+ should 'report an exception if instrumentation cannot proceed' do
25
+ assert_raises(Fiveruns::Dash::Instrument::Error) do
26
+ dash do |metrics|
27
+ metrics.time(:wheee, 'Time spent having fun', 'Wheeee!',
28
+ :method => 'Gizmo.wheeeeeeee!')
29
+ metrics.time(:oops, 'Time spent messing up', 'Ooops!',
30
+ :method => 'Gizmo#oops!')
31
+ end
32
+ end
33
+ end
34
+
35
+ should 'not proceed with instrumentation if an error occurs' do
36
+ begin
37
+ dash do |metrics|
38
+ metrics.time(:wheee, 'Time spent having fun', 'Wheeee!',
39
+ :method => 'Gizmo.wheeeeeeee!')
40
+ metrics.time(:oops, 'Time spent messing up', 'Ooops!',
41
+ :method => 'Gizmo#oops!')
42
+ end
43
+ rescue Fiveruns::Dash::Instrument::Error
44
+ end
45
+ assert_equal 0, Fiveruns::Dash.configuration.metrics.length
46
+ end
47
+
48
+ should 'not modify Thread.abort_on_exception if the user has set it' do
49
+ assert !Thread.abort_on_exception
50
+ end
51
+
52
+ end
53
+
54
+ def dash(&block)
55
+ Fiveruns::Dash.configure({:app => ENV['DASH_APP']}, &block)
56
+ Fiveruns::Dash.session.reporter.interval = 10
57
+ Fiveruns::Dash.session.start
58
+ end
59
+
60
+ end
@@ -0,0 +1,46 @@
1
+ require File.dirname(__FILE__) << "/test_helper"
2
+
3
+ class ReporterTest < Test::Unit::TestCase
4
+
5
+ include Fiveruns::Dash
6
+
7
+ attr_reader :reporter
8
+
9
+ context "Reporter" do
10
+
11
+ setup do
12
+ mock!
13
+ end
14
+
15
+ context "instance" do
16
+ setup do
17
+ @reporter = Reporter.new(@session)
18
+ end
19
+ should "start normally" do
20
+ assert !@reporter.started?
21
+ assert !@reporter.background?
22
+ @reporter.start
23
+ assert_kind_of Time, @reporter.started_at
24
+ assert @reporter.started?
25
+ assert @reporter.background?
26
+ assert !@restarted
27
+ end
28
+ should "allow restart" do
29
+ @reporter.start
30
+ time = @reporter.started_at
31
+ assert_kind_of Time, time
32
+ assert !@restarted
33
+ @reporter.start
34
+ assert @restarted
35
+ assert_equal time.to_f, @reporter.started_at.to_f
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ #######
42
+ private
43
+ #######
44
+
45
+
46
+ end