marty 1.1.5 → 1.1.6

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,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