liri 0.3.1 → 0.4.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.
- checksums.yaml +4 -4
- data/.gitignore +2 -2
- data/Gemfile.lock +14 -7
- data/Rakefile +5 -0
- data/lib/agent/agent.rb +74 -41
- data/lib/all_libraries.rb +3 -0
- data/lib/common/benchmarking.rb +2 -8
- data/lib/common/compressor/zip.rb +3 -2
- data/lib/common/duration.rb +28 -0
- data/lib/common/hardware.rb +29 -0
- data/lib/common/log.rb +59 -17
- data/lib/common/progressbar.rb +3 -3
- data/lib/common/source_code.rb +2 -2
- data/lib/common/tests_result.rb +28 -16
- data/lib/common/text_time_parser.rb +6 -2
- data/lib/common/tty_progressbar.rb +70 -0
- data/lib/common/unit_test/rspec_result_parser.rb +10 -0
- data/lib/hash_extend.rb +7 -0
- data/lib/liri.rb +23 -23
- data/lib/manager/credential.rb +14 -0
- data/lib/manager/manager.rb +375 -133
- data/lib/task.rb +1 -1
- data/liri.gemspec +6 -6
- data/template/liri-config.yml +74 -36
- metadata +12 -10
- data/config/locales/to_duration_es.yml +0 -25
data/lib/manager/manager.rb
CHANGED
@@ -19,8 +19,8 @@ module Liri
|
|
19
19
|
manager_folder_path = setup_manager.manager_folder_path
|
20
20
|
manager_tests_results_folder_path = setup_manager.manager_tests_results_folder_path
|
21
21
|
|
22
|
-
Liri.set_logger(setup_manager.logs_folder_path, '
|
23
|
-
Liri.logger.info('Manager process started')
|
22
|
+
Liri.set_logger(setup_manager.logs_folder_path, 'lirimanager.log')
|
23
|
+
Liri.logger.info('Manager process started', true)
|
24
24
|
Liri.logger.info("Press Ctrl + c to finish Manager process manually\n", true)
|
25
25
|
|
26
26
|
user, password = get_credentials(setup_manager.setup_folder_path)
|
@@ -33,19 +33,68 @@ module Liri
|
|
33
33
|
|
34
34
|
threads = []
|
35
35
|
threads << manager.start_client_socket_to_search_agents(manager_data) # Enviar peticiones broadcast a toda la red para encontrar Agents
|
36
|
-
|
36
|
+
unless stop
|
37
|
+
# Esperar y enviar los test unitarios a los Agents
|
38
|
+
manager.start_server_socket_to_process_tests(threads[0])
|
39
|
+
end
|
37
40
|
|
38
|
-
|
41
|
+
Liri.init_exit(stop, threads)
|
42
|
+
rescue SignalException
|
43
|
+
# Liri.logger.info("\nManager process finished manually", true)
|
44
|
+
ensure
|
45
|
+
# Siempre se ejecutan estos comandos, haya o no excepción
|
46
|
+
Liri.kill(threads) if threads&.any?
|
47
|
+
manager&.print_results
|
48
|
+
source_code&.delete_compressed_file
|
49
|
+
Liri.logger.info("Manager process finished", true)
|
50
|
+
end
|
39
51
|
|
40
|
-
|
41
|
-
Liri.
|
42
|
-
rescue SignalException => e
|
43
|
-
Liri.logger.info("Exception(#{e}) Proceso Manager process finished manually")
|
44
|
-
Liri.kill(threads)
|
52
|
+
def udp_request_delay
|
53
|
+
Liri.setup.manager.udp_request_delay
|
45
54
|
end
|
46
55
|
|
47
56
|
def test_files_by_runner
|
48
|
-
Liri.setup.test_files_by_runner
|
57
|
+
Liri.setup.manager.test_files_by_runner
|
58
|
+
end
|
59
|
+
|
60
|
+
def show_share_source_code_progress_bar
|
61
|
+
Liri.setup.manager.bar.share_source_code
|
62
|
+
end
|
63
|
+
|
64
|
+
def print_summary_table
|
65
|
+
Liri.setup.manager.print.table.summary
|
66
|
+
end
|
67
|
+
|
68
|
+
def print_detailed_table
|
69
|
+
Liri.setup.manager.print.table.detailed
|
70
|
+
end
|
71
|
+
|
72
|
+
def print_summary_failures
|
73
|
+
Liri.setup.manager.print.failures.summary
|
74
|
+
end
|
75
|
+
|
76
|
+
def print_detailed_failures
|
77
|
+
Liri.setup.manager.print.failures.detailed
|
78
|
+
end
|
79
|
+
|
80
|
+
def show_failed_files_column
|
81
|
+
Liri.setup.manager.print.column.failed_files
|
82
|
+
end
|
83
|
+
|
84
|
+
def show_files_load_column
|
85
|
+
Liri.setup.manager.print.column.files_load
|
86
|
+
end
|
87
|
+
|
88
|
+
def show_finish_in_column
|
89
|
+
Liri.setup.manager.print.column.finish_in
|
90
|
+
end
|
91
|
+
|
92
|
+
def show_batch_run_column
|
93
|
+
Liri.setup.manager.print.column.batch_run
|
94
|
+
end
|
95
|
+
|
96
|
+
def show_share_source_code_column
|
97
|
+
Liri.setup.manager.print.column.share_source_code
|
49
98
|
end
|
50
99
|
|
51
100
|
private
|
@@ -66,14 +115,19 @@ module Liri
|
|
66
115
|
end
|
67
116
|
|
68
117
|
def compress_source_code(source_code_folder_path, manager_folder_path)
|
69
|
-
source_code = Common::SourceCode.new(source_code_folder_path, manager_folder_path, Liri.compression_class, Liri.unit_test_class)
|
70
|
-
|
71
|
-
Common::
|
118
|
+
source_code = Common::SourceCode.new(source_code_folder_path, manager_folder_path, Liri.ignored_folders_in_compress, Liri.compression_class, Liri.unit_test_class)
|
119
|
+
#Common::Progressbar.start(total: nil, length: 120, format: 'Compressing source code |%B| %a') do
|
120
|
+
Common::TtyProgressbar.start("Compressing source code |:bar| :percent | Time: :time", total: nil, width: 80, bar_format: :box) do
|
72
121
|
source_code.compress_folder
|
73
122
|
end
|
74
|
-
puts "\n
|
75
|
-
|
123
|
+
puts "\n"
|
124
|
+
Liri.logger.info("Batch Files: #{test_files_by_runner}", true)
|
125
|
+
puts "\n"
|
76
126
|
source_code
|
127
|
+
rescue SignalException => e
|
128
|
+
# Se captura la excepción sólo para imprimir espacios despues de la barra de progreso
|
129
|
+
puts "\n\n"
|
130
|
+
raise e
|
77
131
|
end
|
78
132
|
|
79
133
|
def get_manager_data(user, password, tests_results_folder_path, source_code)
|
@@ -88,12 +142,17 @@ module Liri
|
|
88
142
|
def get_all_tests(source_code)
|
89
143
|
all_tests = {}
|
90
144
|
|
91
|
-
Common::
|
145
|
+
#Common::TtyProgressbar.start("Getting unit tests |:bar| Time::elapsed", total: nil, width: 100) do
|
146
|
+
#Common::Progressbar.start(total: nil, length: 120, format: 'Getting unit tests |%B| %a') do
|
92
147
|
all_tests = source_code.all_tests
|
93
|
-
end
|
94
|
-
puts "\n\n"
|
148
|
+
#end
|
149
|
+
#puts "\n\n"
|
95
150
|
|
96
151
|
all_tests
|
152
|
+
rescue SignalException => e
|
153
|
+
# Se captura la excepción sólo para imprimir espacios despues de la barra de progreso
|
154
|
+
puts "\n\n"
|
155
|
+
raise e
|
97
156
|
end
|
98
157
|
end
|
99
158
|
|
@@ -102,23 +161,33 @@ module Liri
|
|
102
161
|
@udp_socket = UDPSocket.new
|
103
162
|
@tcp_port = tcp_port
|
104
163
|
|
105
|
-
@
|
106
|
-
@
|
107
|
-
@
|
164
|
+
@batch_num = 0
|
165
|
+
@tests_batches = {}
|
166
|
+
@tests_files_count = 0
|
167
|
+
build_tests_batches(all_tests)
|
168
|
+
|
108
169
|
@files_processed = 0
|
109
|
-
@all_tests_processing_count = 0
|
110
170
|
@agents = {}
|
111
|
-
|
112
|
-
@
|
113
|
-
@test_processing_enabled = true
|
114
|
-
|
115
|
-
@tests_batch_number = 0
|
116
|
-
@processed_tests_batches = {}
|
171
|
+
@connected_agents = {}
|
172
|
+
@working_agents = {}
|
117
173
|
|
118
174
|
@tests_result = tests_result
|
119
175
|
@semaphore = Mutex.new
|
120
176
|
|
121
|
-
@
|
177
|
+
@tests_processing_bar = TTY::ProgressBar::Multi.new("Tests Running Progress")
|
178
|
+
@tests_running_progress_bar = @tests_processing_bar.register("Tests files processed :current/:total |:bar| :percent | Time: :time", total: @tests_files_count, width: 80, bar_format: :box)
|
179
|
+
@agents_bar = @tests_processing_bar.register("Agents: Connected: :connected, Working: :working")
|
180
|
+
@tests_result_bar = @tests_processing_bar.register("Examples: :examples, Passed: :passed, Failures: :failures")
|
181
|
+
|
182
|
+
@tests_processing_bar.start # Se inicia la multi barra de progreso
|
183
|
+
|
184
|
+
# Se establece el estado inicial de las barras
|
185
|
+
@tests_running_progress_bar.use(Common::TtyProgressbar::TimeFormatter) # Se configura el uso de un nuevo token llamado time para mostrar el tiempo de ejcución
|
186
|
+
@tests_running_progress_bar.advance(0) # Esto obliga a que esta barra se muestre antes que los siguientes
|
187
|
+
@tests_running_progress_bar.pause
|
188
|
+
|
189
|
+
@agents_bar.advance(0, connected: "0", working: "0")
|
190
|
+
@tests_result_bar.advance(0, examples: "0", passed: "0", failures: "0")
|
122
191
|
end
|
123
192
|
|
124
193
|
# Inicia un cliente udp que hace un broadcast en toda la red para iniciar una conexión con los Agent que estén escuchando
|
@@ -127,11 +196,11 @@ module Liri
|
|
127
196
|
# la red para obtener mas Agents. Una vez que los tests terminan de ejecutarse, este hilo será finalizado.
|
128
197
|
Thread.new do
|
129
198
|
Liri.logger.info('Searching agents... Wait')
|
130
|
-
Liri.logger.info("Sending UDP broadcast each #{
|
131
|
-
while
|
199
|
+
Liri.logger.info("Sending UDP broadcast each #{Manager.udp_request_delay} seconds in UDP port: #{@udp_port}")
|
200
|
+
while processing
|
132
201
|
@udp_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
|
133
202
|
@udp_socket.send(manager_data.to_h.to_json, 0, '<broadcast>', @udp_port)
|
134
|
-
sleep(
|
203
|
+
sleep(Manager.udp_request_delay) # Se pausa un momento antes de efectuar nuevamente la petición broadcast
|
135
204
|
end
|
136
205
|
end
|
137
206
|
end
|
@@ -149,11 +218,13 @@ module Liri
|
|
149
218
|
Liri.logger.info("Waiting Agents connection in TCP port: #{@tcp_port}")
|
150
219
|
# El siguiente bucle permite que varios clientes es decir Agents se conecten
|
151
220
|
# De: http://www.w3big.com/es/ruby/ruby-socket-programming.html
|
152
|
-
while
|
221
|
+
while processing
|
153
222
|
Thread.start(tcp_socket.accept) do |client|
|
154
223
|
agent_ip_address = client.remote_address.ip_address
|
155
|
-
|
224
|
+
hardware_specs = nil
|
156
225
|
run_tests_batch_time_start = nil
|
226
|
+
share_source_code_time_start = nil
|
227
|
+
share_source_code_progress_bar = nil
|
157
228
|
|
158
229
|
while line = client.gets
|
159
230
|
client_data = JSON.parse(line.chop)
|
@@ -166,23 +237,38 @@ module Liri
|
|
166
237
|
break
|
167
238
|
else
|
168
239
|
register_agent(agent_ip_address)
|
169
|
-
|
170
|
-
|
240
|
+
update_connected_agents(agent_ip_address)
|
241
|
+
hardware_specs = client_data['hardware_specs']
|
242
|
+
msg = processing ? 'proceed_get_source_code' : 'no_exist_tests'
|
243
|
+
share_source_code_time_start = Time.now
|
244
|
+
|
245
|
+
share_source_code_progress_bar = start_share_source_code_progress_bar(hardware_specs, msg)
|
246
|
+
|
171
247
|
client.puts({ msg: msg }.to_json)
|
172
248
|
end
|
173
249
|
end
|
174
250
|
|
175
251
|
if msg == 'get_source_code_fail'
|
252
|
+
stop_share_source_code_progress_bar(hardware_specs, share_source_code_progress_bar)
|
253
|
+
|
176
254
|
client.puts({ msg: 'finish_agent' }.to_json)
|
177
255
|
client.close
|
178
256
|
break
|
179
257
|
end
|
180
258
|
|
259
|
+
# Primera ejecucion de pruebas
|
181
260
|
if msg == 'get_tests_files'
|
261
|
+
stop_share_source_code_progress_bar(hardware_specs, share_source_code_progress_bar)
|
262
|
+
|
263
|
+
share_source_code_time_end = Time.now - share_source_code_time_start
|
264
|
+
|
182
265
|
Liri.logger.info("Running unit tests. Agent: #{agent_ip_address}. Wait... ", false)
|
266
|
+
|
267
|
+
start_tests_running_progress_bar
|
183
268
|
run_tests_batch_time_start = Time.now
|
269
|
+
update_working_agents(agent_ip_address)
|
270
|
+
tests_batch = tests_batch(agent_ip_address, hardware_specs, share_source_code_time_end)
|
184
271
|
|
185
|
-
tests_batch = tests_batch(agent_ip_address)
|
186
272
|
if tests_batch.empty?
|
187
273
|
client.puts({ msg: 'no_exist_tests' }.to_json)
|
188
274
|
client.close
|
@@ -192,15 +278,15 @@ module Liri
|
|
192
278
|
end
|
193
279
|
end
|
194
280
|
|
281
|
+
# Segunda ejecucion de pruebas y las siguientes ejecuciones
|
195
282
|
if msg == 'processed_tests'
|
196
283
|
tests_result = client_data
|
197
284
|
Liri.logger.debug("Agent response #{agent_ip_address}: #{tests_result}")
|
198
|
-
|
199
|
-
process_tests_result(agent_ip_address, hardware_model, tests_result, batch_run)
|
285
|
+
process_tests_result(agent_ip_address, hardware_specs, tests_result, run_tests_batch_time_start)
|
200
286
|
|
201
287
|
run_tests_batch_time_start = Time.now
|
202
288
|
|
203
|
-
tests_batch = tests_batch(agent_ip_address)
|
289
|
+
tests_batch = tests_batch(agent_ip_address, hardware_specs, 0)
|
204
290
|
if tests_batch.empty?
|
205
291
|
client.puts({ msg: 'no_exist_tests' }.to_json)
|
206
292
|
client.close
|
@@ -211,161 +297,257 @@ module Liri
|
|
211
297
|
end
|
212
298
|
end
|
213
299
|
|
214
|
-
update_processing_statuses
|
215
300
|
Thread.kill(search_agents_thread)
|
216
|
-
unregister_agent(agent_ip_address)
|
217
301
|
rescue Errno::EPIPE => e
|
218
302
|
# Esto al parecer se da cuando el Agent ya cerró las conexiones y el Manager intenta contactar
|
219
303
|
Liri.logger.error("Exception(#{e}) Agent #{agent_ip_address} already finished connection")
|
220
304
|
# Si el Agente ya no responde es mejor terminar el hilo. Aunque igual quedará colgado el Manager
|
221
305
|
# mientras sigan pruebas pendientes
|
222
|
-
unregister_agent(agent_ip_address)
|
223
306
|
Thread.exit
|
224
307
|
end
|
225
308
|
end
|
226
|
-
|
227
|
-
@tests_result.print_summary
|
228
|
-
print_agents_summary
|
229
|
-
print_agents_detailed_summary if Liri.print_agents_detailed_summary
|
230
|
-
@tests_result.print_failures_list if Liri.print_failures_list
|
231
|
-
@tests_result.print_failed_examples if Liri.print_failed_examples
|
232
309
|
end
|
233
310
|
|
234
|
-
def
|
311
|
+
def processing
|
235
312
|
@semaphore.synchronize do
|
236
|
-
@
|
313
|
+
@unfinished_tests_batches.positive?
|
237
314
|
end
|
238
315
|
end
|
239
316
|
|
240
|
-
def
|
241
|
-
|
242
|
-
@
|
317
|
+
def build_tests_batches(all_tests)
|
318
|
+
while all_tests.any?
|
319
|
+
@batch_num += 1 # Se numera cada lote
|
320
|
+
samples = all_tests.sample!(Manager.test_files_by_runner) # Se obtiene algunos tests
|
321
|
+
samples_keys = samples.keys # Se obtiene la clave asignada a los tests
|
322
|
+
files_count = samples.size
|
323
|
+
status = "pending"
|
324
|
+
@tests_files_count += files_count
|
325
|
+
# Se construye el lote a enviar
|
326
|
+
tests_batch = {
|
327
|
+
batch_num: @batch_num,
|
328
|
+
tests_batch_keys: samples_keys,
|
329
|
+
msg: "process_tests",
|
330
|
+
files_count: files_count,
|
331
|
+
status: status,
|
332
|
+
files_status: "#{files_count} #{status}",
|
333
|
+
agent_ip_address: "",
|
334
|
+
examples: 0,
|
335
|
+
passed: 0,
|
336
|
+
failures: 0,
|
337
|
+
pending: 0,
|
338
|
+
failed_files: "",
|
339
|
+
files_load: 0,
|
340
|
+
finish_in: 0,
|
341
|
+
batch_run: 0,
|
342
|
+
share_source_code: 0,
|
343
|
+
tests_runtime: 0,
|
344
|
+
hardware_specs: ""
|
345
|
+
}
|
346
|
+
@tests_batches[@batch_num] = tests_batch
|
243
347
|
end
|
244
|
-
end
|
245
348
|
|
246
|
-
|
247
|
-
@semaphore.synchronize do
|
248
|
-
@agents_search_processing_enabled
|
249
|
-
end
|
349
|
+
@unfinished_tests_batches = @batch_num
|
250
350
|
end
|
251
351
|
|
252
|
-
def
|
352
|
+
def tests_batch(agent_ip_address, hardware_specs, share_source_code_time_end)
|
353
|
+
# Se inicia un semáforo para evitar que varios hilos actualicen variables compartidas
|
253
354
|
@semaphore.synchronize do
|
254
|
-
@
|
255
|
-
|
256
|
-
|
355
|
+
return {} if @unfinished_tests_batches.zero?
|
356
|
+
|
357
|
+
tests_batch = {}
|
358
|
+
pending_tests_batch = {}
|
359
|
+
sent_tests_batch = {}
|
360
|
+
|
361
|
+
@tests_batches.each_value do |batch|
|
362
|
+
if batch[:status] == "pending"
|
363
|
+
pending_tests_batch = batch
|
364
|
+
break
|
365
|
+
elsif batch[:status] == "sent"
|
366
|
+
sent_tests_batch = batch # Es importante que este no tenga un break para guardar el ultimo enviado
|
367
|
+
# el cual tiene menos probabilidades de terminar de ejecutarse rapido
|
368
|
+
end
|
369
|
+
end
|
257
370
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
371
|
+
# Es importante setear el status y el hardware_spec solo si los hashes no estan vacios
|
372
|
+
# Porque si estan vacios significa que ya no hay tests que ejecutar, y si seteamos algun valor en el hash
|
373
|
+
# estando este vacio entonces se tratara de ejecutar algo sin los datos suficientes y fallara
|
374
|
+
if pending_tests_batch.any?
|
375
|
+
tests_batch = pending_tests_batch
|
376
|
+
tests_batch[:status] = "sent"
|
377
|
+
tests_batch[:agent_ip_address] = agent_ip_address
|
378
|
+
tests_batch[:hardware_specs] = hardware_specs
|
379
|
+
elsif sent_tests_batch.any?
|
380
|
+
tests_batch = sent_tests_batch
|
381
|
+
tests_batch[:status] = "resent"
|
382
|
+
tests_batch[:agent_ip_address] = agent_ip_address
|
383
|
+
tests_batch[:hardware_specs] = hardware_specs
|
384
|
+
end
|
264
385
|
|
265
|
-
|
266
|
-
# Se inicia un semáforo para evitar que varios hilos actualicen variables compartidas
|
267
|
-
@semaphore.synchronize do
|
268
|
-
return {} if @all_tests.empty?
|
386
|
+
return {} if tests_batch.empty?
|
269
387
|
|
270
|
-
|
271
|
-
|
272
|
-
samples_keys = samples.keys # Se obtiene la clave asignada a los tests
|
273
|
-
@all_tests_processing_count += samples_keys.size
|
388
|
+
tests_batch[:agent_ip_address] = agent_ip_address
|
389
|
+
tests_batch[:share_source_code] = share_source_code_time_end
|
274
390
|
|
275
|
-
tests_batch = { msg: 'process_tests', tests_batch_number: @tests_batch_number, tests_batch_keys: samples_keys } # Se construye el lote a enviar
|
276
391
|
Liri.logger.debug("Tests batches sent to Agent #{agent_ip_address}: #{tests_batch}")
|
277
|
-
|
392
|
+
# se devuelve el hash con los datos que se enviarán al agente, por eso, primero se remueven los datos innecesarios
|
393
|
+
tests_batch.remove(:files_count, :status, :files_status, :agent_ip_address, :examples, :passed, :failures,
|
394
|
+
:pending, :failed_files, :files_load, :finish_in, :batch_run, :share_source_code,
|
395
|
+
:tests_runtime, :hardware_specs)
|
278
396
|
end
|
279
397
|
end
|
280
398
|
|
281
|
-
def process_tests_result(agent_ip_address,
|
399
|
+
def process_tests_result(agent_ip_address, hardware_specs, tests_result, run_tests_batch_time_start)
|
282
400
|
# Se inicia un semáforo para evitar que varios hilos actualicen variables compartidas
|
283
401
|
@semaphore.synchronize do
|
284
|
-
|
402
|
+
batch_num = tests_result['batch_num']
|
285
403
|
tests_result_file_name = tests_result['tests_result_file_name']
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
@
|
296
|
-
@
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
404
|
+
status = "processed"
|
405
|
+
# Sólo se procesan las pruebas en estado sent o resent, caso contrario no se avanza con el procesamiento
|
406
|
+
return if (["pending", status]).include?(@tests_batches[batch_num][:status])
|
407
|
+
|
408
|
+
tests_result = @tests_result.process(tests_result_file_name)
|
409
|
+
return if tests_result.empty?
|
410
|
+
|
411
|
+
@unfinished_tests_batches -= 1
|
412
|
+
|
413
|
+
files_count = @tests_batches[batch_num][:files_count]
|
414
|
+
@files_processed += files_count
|
415
|
+
|
416
|
+
batch_runtime = Time.now - run_tests_batch_time_start
|
417
|
+
|
418
|
+
@tests_running_progress_bar.advance(files_count)
|
419
|
+
@tests_result_bar.advance(1, examples: @tests_result.examples.to_s, passed: @tests_result.passed.to_s, failures: @tests_result.failures.to_s)
|
420
|
+
@tests_running_progress_bar.stop if @unfinished_tests_batches.zero?
|
421
|
+
|
422
|
+
@tests_batches[batch_num][:status] = status
|
423
|
+
@tests_batches[batch_num][:files_status] = "#{files_count} #{status}"
|
424
|
+
@tests_batches[batch_num][:agent_ip_address] = agent_ip_address
|
425
|
+
@tests_batches[batch_num][:examples] = tests_result[:examples]
|
426
|
+
@tests_batches[batch_num][:passed] = tests_result[:passed]
|
427
|
+
@tests_batches[batch_num][:failures] = tests_result[:failures]
|
428
|
+
@tests_batches[batch_num][:pending] = tests_result[:pending]
|
429
|
+
@tests_batches[batch_num][:failed_files] = tests_result[:failed_files]
|
430
|
+
@tests_batches[batch_num][:files_load] = tests_result[:files_load]
|
431
|
+
@tests_batches[batch_num][:finish_in] = tests_result[:finish_in]
|
432
|
+
@tests_batches[batch_num][:batch_run] = batch_runtime
|
433
|
+
@tests_batches[batch_num][:tests_runtime] = @tests_batches[batch_num][:batch_run] + @tests_batches[batch_num][:share_source_code]
|
434
|
+
@tests_batches[batch_num][:hardware_specs] = hardware_specs
|
435
|
+
|
436
|
+
Liri.logger.info("Processed unit tests by Agent: #{agent_ip_address}: #{files_count}")
|
301
437
|
end
|
302
438
|
end
|
303
439
|
|
304
|
-
def
|
440
|
+
def print_results
|
441
|
+
@tests_processing_bar&.stop
|
442
|
+
print_summary_table if Manager.print_summary_table
|
443
|
+
print_detailed_table if Manager.print_detailed_table
|
444
|
+
@tests_result.print_summary_failures if Manager.print_summary_failures
|
445
|
+
@tests_result.print_detailed_failures if Manager.print_detailed_failures
|
446
|
+
end
|
447
|
+
|
448
|
+
def print_summary_table
|
305
449
|
processed_tests_batches_by_agent = processed_tests_batches_by_agents
|
306
450
|
rows = processed_tests_batches_by_agent.values.map do |value|
|
307
|
-
value[:
|
308
|
-
value[:
|
309
|
-
value[:batch_run] = value[:batch_run]
|
451
|
+
value[:files_load] = to_duration(value[:files_load]) if value[:files_load]
|
452
|
+
value[:finish_in] = to_duration(value[:finish_in]) if value[:finish_in]
|
453
|
+
value[:batch_run] = to_duration(value[:batch_run]) if value[:batch_run]
|
454
|
+
value[:share_source_code] = to_duration(value[:share_source_code]) if value[:share_source_code]
|
455
|
+
value[:tests_runtime] = to_duration(value[:tests_runtime]) if value[:tests_runtime]
|
310
456
|
value.values
|
311
457
|
end
|
312
458
|
|
313
|
-
rows << Array.new(
|
314
|
-
rows <<
|
459
|
+
rows << Array.new(rows.size) # Se agrega una linea vacia antes de mostrar los totales
|
460
|
+
rows << summary_footer.remove(:batch_num).values
|
315
461
|
header = processed_tests_batches_by_agent.values.first.keys
|
316
462
|
|
317
463
|
table = Terminal::Table.new title: 'Summary', headings: header, rows: rows
|
318
464
|
table.style = { padding_left: 3, border_x: '=', border_i: 'x'}
|
319
|
-
|
465
|
+
|
466
|
+
Liri.logger.info("\n#{table}", true)
|
320
467
|
end
|
321
468
|
|
322
469
|
def processed_tests_batches_by_agents
|
323
470
|
tests_batches = {}
|
324
|
-
|
471
|
+
files_count = {}
|
472
|
+
@tests_batches.each_value do |processed_test_batch|
|
325
473
|
agent_ip_address = processed_test_batch[:agent_ip_address]
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
tests_batches[
|
331
|
-
tests_batches[
|
332
|
-
tests_batches[
|
333
|
-
tests_batches[
|
334
|
-
tests_batches[
|
474
|
+
status = processed_test_batch[:status]
|
475
|
+
key = "#{agent_ip_address}#{status}"
|
476
|
+
if tests_batches[key]
|
477
|
+
files_count[key] += processed_test_batch[:files_count]
|
478
|
+
tests_batches[key][:files_status] = "#{files_count[key]} #{status}"
|
479
|
+
tests_batches[key][:examples] += processed_test_batch[:examples]
|
480
|
+
tests_batches[key][:passed] += processed_test_batch[:passed]
|
481
|
+
tests_batches[key][:failures] += processed_test_batch[:failures]
|
482
|
+
tests_batches[key][:failed_files] += processed_test_batch[:failed_files] if Manager.show_failed_files_column
|
483
|
+
tests_batches[key][:files_load] += processed_test_batch[:files_load] if Manager.show_files_load_column
|
484
|
+
tests_batches[key][:finish_in] += processed_test_batch[:finish_in] if Manager.show_finish_in_column
|
485
|
+
tests_batches[key][:batch_run] += processed_test_batch[:batch_run] if Manager.show_batch_run_column
|
486
|
+
tests_batches[key][:share_source_code] += processed_test_batch[:share_source_code] if Manager.show_share_source_code_column
|
487
|
+
tests_batches[key][:tests_runtime] += processed_test_batch[:tests_runtime]
|
335
488
|
else
|
489
|
+
files_count[key] = processed_test_batch[:files_count]
|
490
|
+
|
336
491
|
_processed_test_batch = processed_test_batch.clone # Clone to change values in other hash
|
337
|
-
_processed_test_batch.remove!(:
|
338
|
-
|
492
|
+
_processed_test_batch.remove!(:batch_num, :tests_batch_keys, :msg, :files_count, :status, :agent_ip_address,
|
493
|
+
:pending)
|
494
|
+
|
495
|
+
_processed_test_batch.remove!(:failed_files) unless Manager.show_failed_files_column
|
496
|
+
_processed_test_batch.remove!(:files_load) unless Manager.show_files_load_column
|
497
|
+
_processed_test_batch.remove!(:finish_in) unless Manager.show_finish_in_column
|
498
|
+
_processed_test_batch.remove!(:batch_run) unless Manager.show_batch_run_column
|
499
|
+
_processed_test_batch.remove!(:share_source_code) unless Manager.show_share_source_code_column
|
500
|
+
_processed_test_batch[:files_status] = "#{files_count[key]} #{status}"
|
501
|
+
|
502
|
+
tests_batches[key] = _processed_test_batch
|
339
503
|
end
|
340
504
|
end
|
341
505
|
tests_batches
|
342
506
|
end
|
343
507
|
|
344
|
-
def
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
value
|
349
|
-
value
|
350
|
-
value
|
508
|
+
def print_detailed_table
|
509
|
+
rows = @tests_batches.values.map do |value|
|
510
|
+
value.remove!(:tests_batch_keys, :msg, :files_count, :status, :agent_ip_address, :pending)
|
511
|
+
|
512
|
+
value.remove!(:failed_files) unless Manager.show_failed_files_column
|
513
|
+
value.remove!(:files_load) unless Manager.show_files_load_column
|
514
|
+
value.remove!(:finish_in) unless Manager.show_finish_in_column
|
515
|
+
value.remove!(:batch_run) unless Manager.show_batch_run_column
|
516
|
+
value.remove!(:share_source_code) unless Manager.show_share_source_code_column
|
517
|
+
|
518
|
+
value[:files_load] = to_duration(value[:files_load]) if value[:files_load]
|
519
|
+
value[:finish_in] = to_duration(value[:finish_in]) if value[:finish_in]
|
520
|
+
value[:batch_run] = to_duration(value[:batch_run]) if value[:batch_run]
|
521
|
+
value[:share_source_code] = to_duration(value[:share_source_code]) if value[:share_source_code]
|
522
|
+
value[:tests_runtime] = to_duration(value[:tests_runtime])
|
351
523
|
value.values
|
352
524
|
end
|
353
525
|
|
354
|
-
rows << Array.new(
|
355
|
-
rows <<
|
356
|
-
header = @
|
526
|
+
rows << Array.new(rows.size) # Se agrega una linea vacia antes de mostrar los totales
|
527
|
+
rows << summary_footer.values
|
528
|
+
header = @tests_batches.values.first.keys
|
357
529
|
|
358
530
|
table = Terminal::Table.new title: 'Detailed Summary', headings: header, rows: rows
|
359
531
|
table.style = { padding_left: 3, border_x: '=', border_i: 'x' }
|
360
532
|
|
361
|
-
|
533
|
+
Liri.logger.info("\n#{table}", true)
|
362
534
|
end
|
363
535
|
|
364
|
-
def
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
536
|
+
def summary_footer
|
537
|
+
hash = {}
|
538
|
+
hash[:batch_num] = ""
|
539
|
+
hash[:files_status] = "#{@tests_files_count} in total"
|
540
|
+
hash[:examples] = @tests_result.examples
|
541
|
+
hash[:passed] = @tests_result.passed
|
542
|
+
hash[:failures] = @tests_result.failures
|
543
|
+
hash[:failed_files] = "" if Manager.show_failed_files_column
|
544
|
+
hash[:files_load] = "" if Manager.show_files_load_column
|
545
|
+
hash[:finish_in] = "" if Manager.show_finish_in_column
|
546
|
+
hash[:batch_run] = "" if Manager.show_batch_run_column
|
547
|
+
hash[:share_source_code] = "" if Manager.show_share_source_code_column
|
548
|
+
hash[:tests_runtime] = ""
|
549
|
+
hash[:hardware_specs] = ""
|
550
|
+
hash
|
369
551
|
end
|
370
552
|
|
371
553
|
def registered_agent?(agent_ip_address)
|
@@ -377,8 +559,68 @@ module Liri
|
|
377
559
|
Liri.logger.info("\nStarted connection with Agent: #{agent_ip_address} in TCP port: #{@tcp_port}")
|
378
560
|
end
|
379
561
|
|
380
|
-
def
|
381
|
-
@
|
562
|
+
def update_connected_agents(agent_ip_address)
|
563
|
+
unless @connected_agents[agent_ip_address]
|
564
|
+
@connected_agents[agent_ip_address] = agent_ip_address
|
565
|
+
update_agents_bar
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
569
|
+
def update_working_agents(agent_ip_address)
|
570
|
+
unless @working_agents[agent_ip_address]
|
571
|
+
@working_agents[agent_ip_address] = agent_ip_address
|
572
|
+
update_agents_bar
|
573
|
+
end
|
574
|
+
end
|
575
|
+
|
576
|
+
def update_agents_bar
|
577
|
+
@agents_bar.advance(1, connected: @connected_agents.size.to_s, working: @working_agents.size.to_s)
|
578
|
+
end
|
579
|
+
|
580
|
+
def start_share_source_code_progress_bar(hardware_specs, msg)
|
581
|
+
if msg == 'proceed_get_source_code' && Manager.show_share_source_code_progress_bar
|
582
|
+
share_source_code_progress_bar = @tests_processing_bar.register("Sharing source code |:bar| :percent | Time: :time | Agent: [:agent ]", total: nil, width: 20, bar_format: :box)
|
583
|
+
share_source_code_progress_bar.start
|
584
|
+
share_source_code_progress_bar.use(Common::TtyProgressbar::TimeFormatter)
|
585
|
+
Thread.new do
|
586
|
+
animation_count = 0
|
587
|
+
while !share_source_code_progress_bar.stopped?
|
588
|
+
share_source_code_progress_bar.advance(1, agent: hardware_specs)
|
589
|
+
|
590
|
+
share_source_code_progress_bar.update(unknown: Common::TtyProgressbar::ANIMATION2[animation_count])
|
591
|
+
animation_count += 1
|
592
|
+
animation_count = 0 if animation_count == 3
|
593
|
+
|
594
|
+
sleep(0.1)
|
595
|
+
end
|
596
|
+
end
|
597
|
+
end
|
598
|
+
share_source_code_progress_bar
|
599
|
+
end
|
600
|
+
|
601
|
+
def stop_share_source_code_progress_bar(hardware_specs, share_source_code_progress_bar)
|
602
|
+
if Manager.show_share_source_code_progress_bar
|
603
|
+
share_source_code_progress_bar.update(total: 1, agent: hardware_specs)
|
604
|
+
share_source_code_progress_bar.stop
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
def start_tests_running_progress_bar
|
609
|
+
@semaphore.synchronize do
|
610
|
+
# Es importante hacer un reset acá osino va a contar desde que se instancia y no desde que se inicia la ejecución
|
611
|
+
# del primer test. Solo se resetea si esta paused para evitar que al conectarse con cada Agent se vuelva a resetear
|
612
|
+
@tests_running_progress_bar.reset if @tests_running_progress_bar.paused?
|
613
|
+
Thread.new do
|
614
|
+
while !@tests_running_progress_bar.stopped?
|
615
|
+
@tests_running_progress_bar.advance(0)
|
616
|
+
sleep(0.1) # Es importante que las otras barras tambien tengan el mismo sleep para que sean mas consistentes en sus resultados
|
617
|
+
end
|
618
|
+
end
|
619
|
+
end
|
620
|
+
end
|
621
|
+
|
622
|
+
def to_duration(value)
|
623
|
+
Common::Duration.humanize(value, times_round: Liri.times_round, times_round_type: Liri.times_round_type)
|
382
624
|
end
|
383
625
|
end
|
384
626
|
end
|