marty 1.1.5 → 1.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,98 @@
1
+ require 'spec_helper'
2
+
3
+ describe Diagnostic::Base do
4
+ def sample_data consistent=true
5
+ node_data_a = Diagnostic::Base.pack(include_ip=false){'A'}
6
+ node_data_b = Diagnostic::Base.pack(include_ip=false){'B'}
7
+
8
+ data = {
9
+ 'NodeA' => node_data_a,
10
+ 'NodeB' => node_data_a,
11
+ }
12
+
13
+ return data if consistent
14
+ data + {'NodeB' => node_data_b}
15
+ end
16
+
17
+ it 'determines consistency of aggregate diagnostics' do
18
+ a = sample_data
19
+ b = sample_data(consistent=false)
20
+
21
+ expect(Diagnostic::Base.consistent?(a)).to eq(true)
22
+ expect(Diagnostic::Base.consistent?(b)).to eq(false)
23
+ end
24
+
25
+ it 'can produce a valid diagnostic hash from a String' do
26
+ expected = {
27
+ 'Base' => {
28
+ 'description' => 'A',
29
+ 'status' => true,
30
+ 'consistent' => nil
31
+ }
32
+ }
33
+
34
+ expect(Diagnostic::Base.pack(include_ip=false){'A'}).to eq(expected)
35
+ end
36
+
37
+ it 'can produce a valid diagnostic hash from a Hash' do
38
+ test_a = {
39
+ 'ImportantA' => 'A',
40
+ 'ImportantB' => 'B',
41
+ 'ImportantC' => 'C'}
42
+
43
+ test_b = {
44
+ 'ImportantA' => {
45
+ 'description' => 'A', 'status' => true, 'consistent' => nil},
46
+ 'ImportantB' => 'B',
47
+ 'ImportantC' => 'C'}
48
+
49
+ expected = {
50
+ 'ImportantA' => {
51
+ 'description' => 'A', 'status' => true, 'consistent' => nil
52
+ },
53
+ 'ImportantB' => {
54
+ 'description' => 'B', 'status' => true, 'consistent' => nil
55
+ },
56
+ 'ImportantC' => {
57
+ 'description' => 'C', 'status' => true, 'consistent' => nil
58
+ },
59
+ }
60
+
61
+ expect(Diagnostic::Base.pack(include_ip=false){test_a}).to eq(expected)
62
+ expect(Diagnostic::Base.pack(include_ip=false){test_a}).to eq(expected)
63
+ end
64
+
65
+ it 'can produce a valid diagnostic hash from an error Hash' do
66
+ test = Diagnostic::Base.pack(include_ip=false){
67
+ Diagnostic::Base.error('E')
68
+ }
69
+
70
+ expected = {
71
+ "Base"=>{
72
+ "description"=>"E",
73
+ "status"=>false,
74
+ "consistent"=>nil}
75
+ }
76
+
77
+ expect(test).to eq(expected)
78
+ end
79
+
80
+ it 'will raise an error if Hash is invalid.' do
81
+ test_a = {
82
+ 'ImportantA' => 'A',
83
+ 'ImportantB' => 'B',
84
+ 'ImportantC' => Diagnostic::Base.create_info('C') + {'extra' => 'D'}
85
+ }
86
+
87
+ test_b = {
88
+ 'Test' => {
89
+ 'ImportantA' => 'A',
90
+ 'ImportantB' => 'B',
91
+ 'ImportantC' => 'C',
92
+ }
93
+ }
94
+
95
+ expect{Diagnostic::Base.pack{test_a}}.to raise_error(RuntimeError)
96
+ expect{Diagnostic::Base.pack{test_b}}.to raise_error(RuntimeError)
97
+ end
98
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Diagnostic::Collection do
4
+ def sample_data consistent = true
5
+ node_a_data = Diagnostic::Collection.pack(include_ip=false){'A'}
6
+ data = {
7
+ 'NodeA' => node_a_data,
8
+ 'NodeB' => node_a_data,
9
+ }
10
+ return data if consistent
11
+ data + {'NodeB' => {'Base' => Diagnostic::Collection.error('B')}}
12
+ end
13
+
14
+ it 'all diagnostics in diagnostics class attribute are generated' do
15
+ diags = [Diagnostic::Version, Diagnostic::Environment]
16
+ expected = diags.map{|d| d.generate}.reduce(:deep_merge)
17
+ Diagnostic::Collection.diagnostics = diags
18
+ expect(Diagnostic::Collection.generate).to eq(expected)
19
+ end
20
+
21
+ it 'declares data consistency via status consistency' do
22
+ a = sample_data
23
+ b = sample_data + {
24
+ 'NodeB' => Diagnostic::Collection.pack(include_ip=false){'B'}
25
+ }
26
+ c = sample_data(consistent=false)
27
+
28
+ expect(Diagnostic::Collection.consistent?(a)).to eq(true)
29
+ expect(Diagnostic::Collection.consistent?(b)).to eq(true)
30
+ expect(Diagnostic::Collection.consistent?(c)).to eq(false)
31
+ end
32
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+ require 'job_helper'
3
+
4
+ describe Diagnostic::DelayedJob do
5
+ # used to stub request object
6
+ class DummyRequest
7
+ attr_accessor :params, :port
8
+ def initialize
9
+ @params = {}
10
+ end
11
+ end
12
+
13
+ before(:all) do
14
+ Marty::Script.load_scripts(nil, Date.today)
15
+ end
16
+
17
+ before(:each) do
18
+ allow(Diagnostic::DelayedJob).to receive(:scope).and_return(nil)
19
+ end
20
+
21
+ def sample_data
22
+ {
23
+ Diagnostic::Helper.my_ip => {
24
+ 'Version' => {
25
+ 'description' => Marty::VERSION,
26
+ 'status' => true,
27
+ 'consistent' => nil
28
+ },
29
+ }
30
+ }
31
+ end
32
+
33
+ it 'can detect if all workers are running correct application version' do
34
+ ENV['DELAYED_VER'] = Marty::VERSION
35
+ start_delayed_job
36
+ expect(Diagnostic::DelayedJob.generate).to eq(sample_data)
37
+ stop_delayed_job
38
+ end
39
+
40
+ it 'will fail if DELAYED_VER is not set' do
41
+ ENV.delete('DELAYED_VER')
42
+ start_delayed_job
43
+ expect{Diagnostic::DelayedJob.generate}.to raise_error(RuntimeError)
44
+ stop_delayed_job
45
+ end
46
+ end
@@ -0,0 +1,319 @@
1
+ require 'spec_helper'
2
+ require 'job_helper'
3
+
4
+ describe Diagnostic::Reporter do
5
+ # used to stub request object
6
+ class DummyRequest
7
+ attr_accessor :params, :port
8
+ end
9
+
10
+ def params diagnostic='base', scope=nil
11
+ {op: diagnostic, scope: scope}
12
+ end
13
+
14
+ def git
15
+ begin
16
+ message = `cd #{Rails.root.to_s}; git describe --tags --always;`.strip
17
+ rescue
18
+ message = error("Failed accessing git")
19
+ end
20
+ end
21
+
22
+ def aggregate_data opts={}
23
+ {
24
+ 'Diagnostic::Dummy' => {
25
+ 'NodeA' => {
26
+ 'ImportantTest' => {
27
+ 'description' => 'A',
28
+ 'status' => opts[:status].nil? ? true : opts[:status],
29
+ 'consistent' => opts[:consistent].nil? ? true : opts[:consistent],
30
+ }
31
+ }
32
+ }
33
+ }
34
+ end
35
+
36
+ def aggregate_consistency_data diagnostic='Base'
37
+ original_a = Diagnostic::Base.create_info('A')
38
+ original_b = Diagnostic::Base.create_info('B')
39
+
40
+ data = {
41
+ 'CONSTANTA' => original_a,
42
+ 'CONSTANTB' => original_b,
43
+ 'CONSTANTB2' => original_b,
44
+ }
45
+
46
+ different_b = Diagnostic::Base.create_info('C')
47
+
48
+ key = "Diagnostic::" + diagnostic
49
+ test = {
50
+ key => {
51
+ 'NodeA' => data,
52
+ 'NodeB' => data + {
53
+ 'CONSTANTB' => different_b,
54
+ 'CONSTANTB2' => different_b
55
+ },
56
+ }
57
+ }
58
+
59
+ inconsistent_b = Diagnostic::Base.create_info('B', true, false)
60
+ inconsistent_c = Diagnostic::Base.create_info('C', true, false)
61
+
62
+ if diagnostic == 'Env'
63
+ expected = {
64
+ key => {
65
+ 'NodeA' => {
66
+ 'CONSTANTB' => inconsistent_b,
67
+ 'CONSTANTB2' => inconsistent_b,
68
+ },
69
+ 'NodeB' => {
70
+ 'CONSTANTB' => inconsistent_c,
71
+ 'CONSTANTB2' => inconsistent_c,
72
+ },
73
+ }
74
+ }
75
+ else
76
+ expected = {
77
+ key => {
78
+ 'NodeA' => {
79
+ 'CONSTANTA' => original_a + {'consistent' => true},
80
+ 'CONSTANTB' => inconsistent_b,
81
+ 'CONSTANTB2' => inconsistent_b,
82
+ },
83
+ 'NodeB' => {
84
+ 'CONSTANTA' => original_a + {'consistent' => true},
85
+ 'CONSTANTB' => inconsistent_c,
86
+ 'CONSTANTB2' => inconsistent_c,
87
+ },
88
+ }
89
+ }
90
+ end
91
+ [test, expected]
92
+ end
93
+
94
+ def info v, status, consistent
95
+ Diagnostic::Base.create_info(v, status, consistent)
96
+ end
97
+
98
+ def version_data consistent = true
99
+ Diagnostic::Base.pack(include_ip=false){
100
+ {
101
+ "Marty" => info(Marty::VERSION, true, consistent),
102
+ "Delorean" => info(Delorean::VERSION, true, true),
103
+ "Mcfly" => info(Mcfly::VERSION, true, true),
104
+ "Git" => info(git, true, true),
105
+ }
106
+ }
107
+ end
108
+
109
+ def minimize(str)
110
+ str.gsub(/\s+/, "")
111
+ end
112
+
113
+ describe 'display mechanism for version diagnostic' do
114
+ before(:all) do
115
+ Diagnostic::Reporter.diagnostics = [Diagnostic::Version]
116
+ end
117
+
118
+ before(:each) do
119
+ Diagnostic::Reporter.request = DummyRequest.new
120
+ end
121
+
122
+ it 'masks consistent nodes for display (version)' do
123
+ Diagnostic::Reporter.request.params = params(scope='local')
124
+ data = {
125
+ 'Diagnostic::Version' => {
126
+ 'NodeA' => version_data,
127
+ 'NodeB' => version_data,
128
+ }
129
+ }
130
+
131
+ expected = <<-ERB
132
+ <h3>Version</h3>
133
+ <div class="wrapper">
134
+ <table>
135
+ <tr>
136
+ <th colspan="2" scope="col">consistent</th>
137
+ </tr>
138
+ <tr>
139
+ <th class="data" scope="row">Marty</th>
140
+ <td class="overflow passed"><p>#{Marty::VERSION}</p>
141
+ </td>
142
+ </tr>
143
+ <tr>
144
+ <th class="data" scope="row">Delorean</th>
145
+ <td class="overflow passed"><p>#{Delorean::VERSION}</p>
146
+ </td>
147
+ </tr>
148
+ <tr>
149
+ <th class="data" scope="row">Mcfly</th>
150
+ <td class="overflow passed"><p>#{Mcfly::VERSION}</p>
151
+ </td>
152
+ </tr>
153
+ <tr>
154
+ <th class="data" scope="row">Git</th>
155
+ <td class="overflow passed"><p>#{git}</p>
156
+ </td>
157
+ </tr>
158
+ </table>
159
+ </div>
160
+ ERB
161
+
162
+ test = Diagnostic::Reporter.displays(data)
163
+ expect(minimize(test)).to eq(minimize(expected))
164
+ end
165
+
166
+ it 'displays all nodes when there is an inconsistent node (version)' do
167
+ Diagnostic::Reporter.request.params = params
168
+ bad_ver = '0.0.0'
169
+
170
+ data = {
171
+ 'Diagnostic::Version' => {
172
+ 'NodeA' => version_data(consistent=false),
173
+ 'NodeB' => version_data + {
174
+ 'Marty' => Diagnostic::Base.create_info(bad_ver, true, false)
175
+ },
176
+ }
177
+ }
178
+
179
+ expected = <<-ERB
180
+ <h3>Version</h3>
181
+ <h3 class="error">Inconsistency Detected </h3>
182
+ <div class="wrapper">
183
+ <table>
184
+ <tr>
185
+ <th></th>
186
+ <th scope="col">NodeA</th>
187
+ <th scope="col">NodeB</th>
188
+ </tr>
189
+ <tr>
190
+ <th class="data" scope="row">Marty</th>
191
+ <td class="overflow inconsistent"><p>#{Marty::VERSION}</p></td>
192
+ <td class="overflow inconsistent"><p>#{bad_ver}</p></td>
193
+ </tr>
194
+ <tr>
195
+ <th class="data" scope="row">Delorean</th>
196
+ <td class="overflow passed"><p>#{Delorean::VERSION}</p></td>
197
+ <td class="overflow passed"><p>#{Delorean::VERSION}</p></td>
198
+ </tr>
199
+ <tr>
200
+ <th class="data" scope="row">Mcfly</th>
201
+ <td class="overflow passed"><p>#{Mcfly::VERSION}</p></td>
202
+ <td class="overflow passed"><p>#{Mcfly::VERSION}</p></td>
203
+ </tr>
204
+ <tr>
205
+ <th class="data" scope="row">Git</th>
206
+ <td class="overflow passed"><p>#{git}</p></td>
207
+ <td class="overflow passed"><p>#{git}</p></td>
208
+ </tr>
209
+ </table>
210
+ </div>
211
+ ERB
212
+
213
+ test = Diagnostic::Reporter.displays(data)
214
+ expect(minimize(test)).to eq(minimize(expected))
215
+ end
216
+
217
+ it 'can detect errors in diagnostic for display and api' do
218
+ Diagnostic::Reporter.request.params = params
219
+ n = aggregate_data
220
+ e = aggregate_data(status: false)
221
+ c = aggregate_data(consistent: false)
222
+ ce = aggregate_data(status: false, consistent: false)
223
+
224
+ aggregate_failures do
225
+ expect(Diagnostic::Reporter.errors(n)).to eq({})
226
+ expect(Diagnostic::Reporter.errors(e)).not_to eq({})
227
+ expect(Diagnostic::Reporter.errors(c)).not_to eq({})
228
+ expect(Diagnostic::Reporter.errors(ce)).not_to eq({})
229
+ end
230
+ end
231
+
232
+ it 'can survive and display fatal errors' do
233
+ Diagnostic::Reporter.request.params = params
234
+
235
+ a_err_a = Diagnostic::Fatal.message('A',
236
+ node: 'NodeA')
237
+
238
+ a_err_b = Diagnostic::Fatal.message('B',
239
+ node: 'NodeA')
240
+
241
+ b_err_c = Diagnostic::Fatal.message('C',
242
+ node: 'NodeB',
243
+ type: 'OtherError')
244
+
245
+ c_err_d = Diagnostic::Fatal.message('D',
246
+ node: 'NodeC',
247
+ type: 'OtherOtherError')
248
+
249
+ data = [a_err_a, a_err_b, b_err_c, c_err_d].reduce(:deep_merge)
250
+
251
+ expected = <<-ERB
252
+ <h3>Fatal</h3>
253
+ <h3 class="error">Inconsistency Detected</h3>
254
+ <div class="wrapper">
255
+ <table>
256
+ <tr>
257
+ <th></th>
258
+ <th scope="col">NodeA</th>
259
+ <th scope="col">NodeB</th>
260
+ <th scope="col">NodeC</th>
261
+ </tr>
262
+ <tr><th class="data" scope="row">RuntimeError</th>
263
+ <td class="overflow error">
264
+ <p>B</p>
265
+ </td>
266
+ <td class="overflow inconsistent">
267
+ <p>N/A</p>
268
+ </td>
269
+ <td class="overflow inconsistent">
270
+ <p>N/A</p>
271
+ </td>
272
+ </tr>
273
+ <tr><th class="data" scope="row">OtherError</th>
274
+ <td class="overflow inconsistent">
275
+ <p>N/A</p>
276
+ </td>
277
+ <td class="overflow error">
278
+ <p>C</p>
279
+ </td>
280
+ <td class="overflow inconsistent">
281
+ <p>N/A</p>
282
+ </td>
283
+ </tr>
284
+ <tr><th class="data" scope="row">OtherOtherError</th>
285
+ <td class="overflow inconsistent">
286
+ <p>N/A</p>
287
+ </td>
288
+ <td class="overflow inconsistent">
289
+ <p>N/A</p>
290
+ </td>
291
+ <td class="overflow error">
292
+ <p>D</p>
293
+ </td>
294
+ </tr>
295
+ </table>
296
+ </div>
297
+ <h3 class="error">
298
+ Something went wrong.</br>
299
+ Consistency is checked between remaining nodes if applicable.
300
+ </h3>
301
+ ERB
302
+
303
+ result = Diagnostic::Reporter.displays(data)
304
+ expect(minimize(result)).to eq(minimize(expected))
305
+ end
306
+ end
307
+
308
+ describe 'aggregation consistency functionality' do
309
+ it 'env diagnostic' do
310
+ test, expected = aggregate_consistency_data('Env')
311
+ expect(Diagnostic::Reporter.consistency(test)).to eq(expected)
312
+ end
313
+
314
+ it 'marks data as consistent/inconsistent' do
315
+ test, expected = aggregate_consistency_data
316
+ expect(Diagnostic::Reporter.consistency(test)).to eq(expected)
317
+ end
318
+ end
319
+ end