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,97 @@
1
+ require File.dirname(__FILE__) << "/test_helper"
2
+
3
+ class ConfigurationTest < Test::Unit::TestCase
4
+
5
+ context "Configuration" do
6
+
7
+ setup do
8
+ no_recipe_loading!
9
+ mock_streams!
10
+ end
11
+
12
+ teardown do
13
+ restore_streams!
14
+ Fiveruns::Dash.class_eval { @configuration = nil }
15
+ end
16
+
17
+ should "update options passed by Fiveruns::Dash.configure convenience method" do
18
+ assert_nil config.options[:app]
19
+ token = 'foo-bar'
20
+ Fiveruns::Dash.configure :app => token
21
+ assert_equal token, config.options[:app]
22
+ end
23
+
24
+ context "metric definitions" do
25
+ setup do
26
+ @configuration = Configuration.new do |config|
27
+ metric_types.each do |type|
28
+ config.__send__(type, "Metric: #{type}") do
29
+ # Empty block for metric types that require it
30
+ end
31
+ end
32
+ end
33
+ end
34
+ should "assign all metrics" do
35
+ assert_equal 3, @configuration.metrics.size
36
+ types = @configuration.metrics.map { |metric| metric.class.metric_type }
37
+ assert_equal metric_types.map(&:to_s).sort, types.map(&:to_s).sort
38
+ end
39
+ should "not allow invalid types" do
40
+ assert_raises NoMethodError do
41
+ @configuration.__send__(:bad_type, 'My Horrible Metric')
42
+ end
43
+ end
44
+ end
45
+
46
+ context "setting by version" do
47
+ setup do
48
+ @version = '0.1.6'
49
+ @config = Configuration.new do |config|
50
+ config.for_version @version, '0.1.6' do
51
+ config.counter :foo do
52
+ 1
53
+ end
54
+ end
55
+ config.for_version @version, ['=', '0.1.6'] do
56
+ config.counter :bar do
57
+ 1
58
+ end
59
+ end
60
+ config.for_version @version, ['==', '0.1.5'] do
61
+ config.counter :spam do
62
+ 1
63
+ end
64
+ end
65
+ config.for_version @version, ['>', '0.1.6'] do
66
+ config.counter :baz do
67
+ 1
68
+ end
69
+ end
70
+ config.for_version nil, ['>', '0.1.6'] do
71
+ config.counter :quux do
72
+ 1
73
+ end
74
+ end
75
+ end
76
+ end
77
+ should "execute if correct version" do
78
+ assert_equal 2, @config.metrics.size
79
+ assert_equal %w(bar foo), @config.metrics.map(&:name).map(&:to_s).sort
80
+ end
81
+ end
82
+
83
+ end
84
+
85
+ #######
86
+ private
87
+ #######
88
+
89
+ def metric_types
90
+ [:counter, :percentage, :absolute]
91
+ end
92
+
93
+ def config
94
+ Fiveruns::Dash.configuration
95
+ end
96
+
97
+ end
@@ -0,0 +1,112 @@
1
+ require File.dirname(__FILE__) << "/test_helper"
2
+
3
+ class ExceptionRecorderTest < Test::Unit::TestCase
4
+
5
+ attr_reader :payload
6
+ attr_reader :recorder, :exceptions
7
+
8
+ context "ExceptionRecorder" do
9
+
10
+ setup do
11
+ @recorder = Fiveruns::Dash::ExceptionRecorder.new(flexmock(:session))
12
+ flexmock(ExceptionRecorder).should_receive(:replacements).and_return({
13
+ :foo => /^foo\b/
14
+ })
15
+ end
16
+
17
+ context "when recording an exception" do
18
+ setup do
19
+ recorder.record(build("Message", "foo/bar/baz"))
20
+ end
21
+ should "record an exception" do
22
+ assert_equal 1, recorder.data.size
23
+ end
24
+ should "normalize a backtrace" do
25
+ assert(recorder.data.first[:backtrace] =~ /\[FOO\]/)
26
+ end
27
+ end
28
+
29
+ context "when recording an exception with a sample" do
30
+ setup do
31
+ recorder.record(build("Message", "foo/bar/baz"), {:key => :value})
32
+ end
33
+ should "record an exception" do
34
+ assert_equal 1, recorder.data.size
35
+ end
36
+ should "normalize a backtrace" do
37
+ assert(recorder.data.first[:backtrace] =~ /\[FOO\]/)
38
+ end
39
+ should "not serialize sample" do
40
+ assert_equal({'key' => 'value'}, recorder.data.first[:sample])
41
+ end
42
+ end
43
+
44
+ context "when recording exceptions with the same message and backtrace" do
45
+ setup do
46
+ recorder.record(build, :key1=>:value1)
47
+ recorder.record(build, :key2=>:value2)
48
+ end
49
+ should "collapse" do
50
+ assert_equal 1, recorder.data.size
51
+ end
52
+ should "count them together" do
53
+ assert_equal [2], recorder.data.map { |exc| exc[:total] }
54
+ end
55
+ should "store only the first sample" do
56
+ assert_equal({'key1' => 'value1'}, recorder.data.first[:sample])
57
+ end
58
+ end
59
+
60
+ context "when recording exceptions with different messages" do
61
+ setup do
62
+ recorder.record(build("Message1", "Line 1"))
63
+ recorder.record(build("Message2", "Line 1"))
64
+ end
65
+ should "collapse" do
66
+ assert_equal 1, recorder.data.size
67
+ end
68
+ should "count them together" do
69
+ assert_equal [2], recorder.data.map { |exc| exc[:total] }
70
+ end
71
+ end
72
+
73
+ context "when recording exceptions with different backtraces" do
74
+ setup do
75
+ recorder.record(build("Message", "Line 1"))
76
+ recorder.record(build("Message", "Line 2"))
77
+ end
78
+ should "not collapse" do
79
+ assert_equal 2, recorder.data.size
80
+ end
81
+ should "count them separately" do
82
+ assert_equal [1, 1], recorder.data.map { |exc| exc[:total] }
83
+ end
84
+ end
85
+
86
+ context "when retrieving the data" do
87
+ should "call reset when returning data hash" do
88
+ flexmock(recorder).should_receive(:reset).once
89
+ recorder.data
90
+ end
91
+
92
+ should "empty the exception list on reset" do
93
+ recorder.send(:exceptions) << "Item"
94
+ assert_equal( 1, recorder.send(:exceptions).size )
95
+ recorder.send(:reset)
96
+ assert_equal( 0, recorder.send(:exceptions).size )
97
+ end
98
+ end
99
+
100
+ end
101
+
102
+ #######
103
+ private
104
+ #######
105
+
106
+ def build(message = 'This is a message', line = 'backtrace line')
107
+ flexmock(:exception) do |mock|
108
+ mock.should_receive(:backtrace).and_return([line])
109
+ mock.should_receive(:message).and_return(message)
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,56 @@
1
+ require File.dirname(__FILE__) << "/test_helper"
2
+
3
+ class FileStoreTest < Test::Unit::TestCase
4
+
5
+ context "FileStore" do
6
+
7
+ setup do
8
+ mock_storage!
9
+ directories.each do |dir|
10
+ FileUtils.mkdir_p dir
11
+ end
12
+ @update = @klass.new
13
+ @update.store_file(*uris)
14
+ end
15
+
16
+ teardown do
17
+ FileUtils.rm_rf(File.dirname(__FILE__) << "/tmp")
18
+ end
19
+
20
+ should "write to all filenames" do
21
+ assert_equal 2, files.size
22
+ end
23
+
24
+ should "name all filenames the same" do
25
+ assert_equal 1, files.map { |f| File.basename(f) }.uniq.size
26
+ end
27
+
28
+ end
29
+
30
+ #######
31
+ private
32
+ #######
33
+
34
+ def files
35
+ Dir[File.dirname(__FILE__) << "/tmp/**/*.json"]
36
+ end
37
+
38
+ def mock_storage!
39
+ @klass = Class.new { include Store::File }
40
+ flexmock(@klass).new_instances do |mock|
41
+ mock.should_receive(:payload).and_return(:foo => 1, :bar => 2)
42
+ mock.should_receive(:guid).and_return('GUID')
43
+ end
44
+ end
45
+
46
+ def directories
47
+ %w(foo bar).map do |name|
48
+ File.expand_path(File.join(File.dirname(__FILE__), 'tmp', 'file_store', name))
49
+ end
50
+ end
51
+
52
+ def uris
53
+ directories.map { |path| URI.parse("file://#{path}") }
54
+ end
55
+
56
+ end
@@ -0,0 +1,6 @@
1
+ {
2
+ "process_id":1,
3
+ "metric_infos": [
4
+ {"id":1, "name":"MetricTest.time_me","recipe_url":null, "recipe_name":null}
5
+ ]
6
+ }
@@ -0,0 +1,210 @@
1
+ require File.dirname(__FILE__) << "/test_helper"
2
+
3
+ class HTTPStoreTest < Test::Unit::TestCase
4
+
5
+ attr_reader :payload
6
+
7
+ context "HTTPStore" do
8
+
9
+ setup do
10
+ Thread.current[:resolved_hostnames] = nil
11
+ @urls = %w(http://metrics.foo.com http://metrics02.bar.com http://metrics03.bar.com)
12
+ @klass = Class.new { include Store::HTTP }
13
+ @params = {:this_is_a_param => 'value'}
14
+ @metric = flexmock(:metric) do |mock|
15
+ mock.should_receive(:key).and_return(:name => 'MetricTest.time_me', :recipe_name => nil, :recipe_url => nil)
16
+ mock.should_receive(:info_id=)
17
+ end
18
+ @configuration = flexmock(:config) do |mock|
19
+ mock.should_receive(:options).and_return(:app => '123')
20
+ mock.should_receive(:metrics).and_return([@metric])
21
+ end
22
+ flexmock(::Fiveruns::Dash).should_receive(:configuration).and_return(@configuration)
23
+ flexmock(@klass).new_instances do |mock|
24
+ mock.should_receive(:payload).and_return { payload }
25
+ mock.should_receive(:params).and_return(@params)
26
+ end
27
+ @update = @klass.new
28
+ no_recipe_loading!
29
+ # mock_streams!
30
+ end
31
+
32
+ teardown do
33
+ FakeWeb.clean_registry
34
+ # restore_streams!
35
+ end
36
+
37
+ #TODO
38
+ context "collector hostnames" do
39
+ should "should be resolved on the first access" do
40
+ flexmock(IPSocket).should_receive(:getaddress).times(1).returns("1.1.1.1")
41
+ assert_equal @update.resolved_hostnames.keys.size, 0
42
+ new_uri = @update.resolved_hostname(uris.first.host)
43
+ assert_equal new_uri, "1.1.1.1"
44
+ assert_equal @update.resolved_hostnames.keys.size, 1
45
+ assert @update.resolved_hostnames[uris.first.host].next_update > (Time.now + 23.hours)
46
+ assert_equal @update.resolved_hostname(uris.first.host), "1.1.1.1"
47
+ junk = @update.resolved_hostname(uris.first.host)
48
+
49
+ end
50
+
51
+ should "re-cache address if time has expired" do
52
+ flexmock(@update).should_receive(:rand).returns(1)
53
+ flexmock(IPSocket).should_receive(:getaddress).returns("1.1.1.1", "2.2.2.2")
54
+ assert_equal @update.resolved_hostnames.keys.size, 0
55
+ new_uri = @update.resolved_hostname(uris.first.host)
56
+ assert_equal new_uri, "1.1.1.1"
57
+ @update.resolved_hostnames[uris.first.host].next_update = 10.hours.ago
58
+ first_expire = @update.resolved_hostnames[uris.first.host].next_update
59
+
60
+ new_uri = @update.resolved_hostname(uris.first.host)
61
+ second_expire = @update.resolved_hostnames[uris.first.host].next_update
62
+ assert_equal new_uri, "2.2.2.2"
63
+ assert second_expire < (Time.now + 25.hours)
64
+ assert second_expire > (Time.now + 23.hours)
65
+ end
66
+ end
67
+
68
+ context "with info payload" do
69
+ setup do
70
+ @payload = InfoPayload.new({:pid => 987}, Time.now.utc)
71
+ @update#TODO
72
+ flexmock(@update).should_receive(:resolved_hostname).and_return {|c| c }
73
+ # restore_streams!
74
+ end
75
+ teardown do
76
+ # mock_streams!
77
+ end
78
+ context "on connection error" do
79
+ setup do
80
+ FakeWeb.register_uri full_urls(:processes).first, :string => 'FAIL!', :exception => Net::HTTPError
81
+ full_urls(:processes)[1..-1].each do |url|
82
+ FakeWeb.register_uri url, :status => 201, :string => File.read(File.dirname(__FILE__) << "/fixtures/http_store_test/response.json")
83
+ end
84
+ end
85
+ should "fallback to working URL" do
86
+ returning @update.store_http(*uris) do |pass_uri|
87
+ assert_equal uris[1], pass_uri
88
+ end
89
+ end
90
+ end
91
+ context "on non-201 response" do
92
+ setup do
93
+ [500, 403, 200].zip(full_urls(:processes)).each do |status, url|
94
+ FakeWeb.register_uri url, :string => 'Not what we want', :status => status
95
+ end
96
+ end
97
+ should "not succeed" do
98
+ assert !@update.store_http(*uris)
99
+ end
100
+ end
101
+ end
102
+
103
+ context "with data payload" do
104
+
105
+ setup do
106
+ @payload = DataPayload.new([{:metric_info_id => 123, :name => 'bar'}])
107
+ flexmock(@update).should_receive(:resolved_hostname).and_return {|c| c}
108
+
109
+ end
110
+
111
+ context "fallback URLs" do
112
+ context "on connection error" do
113
+ setup do
114
+ FakeWeb.register_uri full_urls(:metrics).first, :string => 'FAIL!', :exception => Net::HTTPError
115
+ full_urls(:metrics)[1..-1].each do |url|
116
+ FakeWeb.register_uri url, :string => '{"message" : "OK!"}', :status => 201
117
+ end
118
+ end
119
+ should "fallback to working URL" do
120
+ returning @update.store_http(*uris) do |pass_uri|
121
+ assert_equal uris[1], pass_uri
122
+ end
123
+ end
124
+ end
125
+ context "on non-201 response" do
126
+ setup do
127
+ [500, 403, 200].zip(full_urls(:metrics)).each do |status, url|
128
+ FakeWeb.register_uri url, :string => 'Not what we want', :status => status
129
+ end
130
+ end
131
+ should "not succeed" do
132
+ assert !@update.store_http(*uris)
133
+ end
134
+ end
135
+ end
136
+
137
+ end
138
+
139
+ context "with exceptions payload" do
140
+
141
+ setup do
142
+ @payload = ExceptionsPayload.new([
143
+ {
144
+ :name => 'FooError',
145
+ :message => 'Fake Foo Error',
146
+ :backtrace => '--- This is not real',
147
+ :total => 3
148
+ },
149
+ {
150
+ :name => 'BarError',
151
+ :message => 'Fake Bar Error',
152
+ :backtrace => '--- This is not real',
153
+ :total => 10
154
+ }
155
+ ])
156
+ flexmock(@update).should_receive(:resolved_hostname).and_return {|c| c}
157
+
158
+ end
159
+
160
+ context "fallback URLs" do
161
+ context "on connection error" do
162
+ setup do
163
+ FakeWeb.register_uri full_urls(:exceptions).first, :string => 'FAIL!', :exception => Net::HTTPError
164
+ full_urls(:exceptions)[1..-1].each do |url|
165
+ FakeWeb.register_uri url, :string => '{"message" : "OK!"}', :status => 201
166
+ end
167
+ end
168
+ should "fallback to working URL" do
169
+ returning @update.store_http(*uris) do |pass_uri|
170
+ assert_equal uris[1], pass_uri
171
+ end
172
+ end
173
+ end
174
+ context "on non-201 response" do
175
+ setup do
176
+ [500, 403, 200].zip(full_urls(:exceptions)).each do |status, url|
177
+ FakeWeb.register_uri url, :string => 'Not what we want', :status => status
178
+ end
179
+ end
180
+ should "not succeed" do
181
+ assert !@update.store_http(*uris)
182
+ end
183
+ end
184
+ end
185
+
186
+ end
187
+
188
+ end
189
+
190
+ #######
191
+ private
192
+ #######
193
+
194
+ def full_urls(service)
195
+ full_uris(service).map(&:to_s)
196
+ end
197
+
198
+ def full_uris(service)
199
+ @urls.map do |url|
200
+ uri = URI.parse(url)
201
+ uri.path = "/apps/123/#{service}.json"
202
+ uri
203
+ end
204
+ end
205
+
206
+ def uris
207
+ @urls.map { |url| URI.parse(url) }
208
+ end
209
+
210
+ end