fiveruns-dash-ruby 0.7.0

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.
@@ -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