lib/manager/manager.rb in liri-0.3.1 vs lib/manager/manager.rb in liri-0.4.0
- old
+ new
@@ -17,12 +17,12 @@
setup_manager = Liri.set_setup(source_code_folder_path, :manager, manager_tests_results_folder_time: DateTime.now.strftime("%d_%m_%y_%H_%M_%S"))
manager_folder_path = setup_manager.manager_folder_path
manager_tests_results_folder_path = setup_manager.manager_tests_results_folder_path
- Liri.set_logger(setup_manager.logs_folder_path, 'liri-manager.log')
- Liri.logger.info('Manager process started')
+ Liri.set_logger(setup_manager.logs_folder_path, 'lirimanager.log')
+ Liri.logger.info('Manager process started', true)
Liri.logger.info("Press Ctrl + c to finish Manager process manually\n", true)
user, password = get_credentials(setup_manager.setup_folder_path)
source_code = compress_source_code(source_code_folder_path, manager_folder_path)
manager_data = get_manager_data(user, password, manager_tests_results_folder_path, source_code)
@@ -31,25 +31,74 @@
manager = Manager.new(Liri.udp_port, Liri.tcp_port, all_tests, tests_result)
threads = []
threads << manager.start_client_socket_to_search_agents(manager_data) # Enviar peticiones broadcast a toda la red para encontrar Agents
- manager.start_server_socket_to_process_tests(threads[0]) unless stop # Esperar y enviar los test unitarios a los Agents
+ unless stop
+ # Esperar y enviar los test unitarios a los Agents
+ manager.start_server_socket_to_process_tests(threads[0])
+ end
- source_code.delete_compressed_file
+ Liri.init_exit(stop, threads)
+ rescue SignalException
+ # Liri.logger.info("\nManager process finished manually", true)
+ ensure
+ # Siempre se ejecutan estos comandos, haya o no excepción
+ Liri.kill(threads) if threads&.any?
+ manager&.print_results
+ source_code&.delete_compressed_file
+ Liri.logger.info("Manager process finished", true)
+ end
- Liri.init_exit(stop, threads, 'Manager')
- Liri.logger.info('Manager process finished')
- rescue SignalException => e
- Liri.logger.info("Exception(#{e}) Proceso Manager process finished manually")
- Liri.kill(threads)
+ def udp_request_delay
+ Liri.setup.manager.udp_request_delay
end
def test_files_by_runner
- Liri.setup.test_files_by_runner
+ Liri.setup.manager.test_files_by_runner
end
+ def show_share_source_code_progress_bar
+ Liri.setup.manager.bar.share_source_code
+ end
+
+ def print_summary_table
+ Liri.setup.manager.print.table.summary
+ end
+
+ def print_detailed_table
+ Liri.setup.manager.print.table.detailed
+ end
+
+ def print_summary_failures
+ Liri.setup.manager.print.failures.summary
+ end
+
+ def print_detailed_failures
+ Liri.setup.manager.print.failures.detailed
+ end
+
+ def show_failed_files_column
+ Liri.setup.manager.print.column.failed_files
+ end
+
+ def show_files_load_column
+ Liri.setup.manager.print.column.files_load
+ end
+
+ def show_finish_in_column
+ Liri.setup.manager.print.column.finish_in
+ end
+
+ def show_batch_run_column
+ Liri.setup.manager.print.column.batch_run
+ end
+
+ def show_share_source_code_column
+ Liri.setup.manager.print.column.share_source_code
+ end
+
private
def valid_project
if File.exist?(File.join(Dir.pwd, 'Gemfile'))
true
else
@@ -64,18 +113,23 @@
credential = Liri::Manager::Credential.new(setup_folder_path)
credential.get
end
def compress_source_code(source_code_folder_path, manager_folder_path)
- source_code = Common::SourceCode.new(source_code_folder_path, manager_folder_path, Liri.compression_class, Liri.unit_test_class)
-
- Common::Progressbar.start(total: nil, length: 100, format: 'Compressing source code |%B| %a') do
+ source_code = Common::SourceCode.new(source_code_folder_path, manager_folder_path, Liri.ignored_folders_in_compress, Liri.compression_class, Liri.unit_test_class)
+ #Common::Progressbar.start(total: nil, length: 120, format: 'Compressing source code |%B| %a') do
+ Common::TtyProgressbar.start("Compressing source code |:bar| :percent | Time: :time", total: nil, width: 80, bar_format: :box) do
source_code.compress_folder
end
- puts "\n\n"
-
+ puts "\n"
+ Liri.logger.info("Batch Files: #{test_files_by_runner}", true)
+ puts "\n"
source_code
+ rescue SignalException => e
+ # Se captura la excepción sólo para imprimir espacios despues de la barra de progreso
+ puts "\n\n"
+ raise e
end
def get_manager_data(user, password, tests_results_folder_path, source_code)
Common::ManagerData.new(
tests_results_folder_path: tests_results_folder_path,
@@ -86,54 +140,69 @@
end
def get_all_tests(source_code)
all_tests = {}
- Common::Progressbar.start(total: nil, length: 100, format: 'Getting unit tests |%B| %a') do
+ #Common::TtyProgressbar.start("Getting unit tests |:bar| Time::elapsed", total: nil, width: 100) do
+ #Common::Progressbar.start(total: nil, length: 120, format: 'Getting unit tests |%B| %a') do
all_tests = source_code.all_tests
- end
- puts "\n\n"
+ #end
+ #puts "\n\n"
all_tests
+ rescue SignalException => e
+ # Se captura la excepción sólo para imprimir espacios despues de la barra de progreso
+ puts "\n\n"
+ raise e
end
end
def initialize(udp_port, tcp_port, all_tests, tests_result)
@udp_port = udp_port
@udp_socket = UDPSocket.new
@tcp_port = tcp_port
- @all_tests = all_tests
- @all_tests_count = all_tests.size
- @all_tests_results = {}
+ @batch_num = 0
+ @tests_batches = {}
+ @tests_files_count = 0
+ build_tests_batches(all_tests)
+
@files_processed = 0
- @all_tests_processing_count = 0
@agents = {}
+ @connected_agents = {}
+ @working_agents = {}
- @agents_search_processing_enabled = true
- @test_processing_enabled = true
-
- @tests_batch_number = 0
- @processed_tests_batches = {}
-
@tests_result = tests_result
@semaphore = Mutex.new
- @progressbar = ProgressBar.create(starting_at: 0, total: @all_tests_count, length: 100, format: 'Progress %c/%C |%b=%i| %p%% | %a')
+ @tests_processing_bar = TTY::ProgressBar::Multi.new("Tests Running Progress")
+ @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)
+ @agents_bar = @tests_processing_bar.register("Agents: Connected: :connected, Working: :working")
+ @tests_result_bar = @tests_processing_bar.register("Examples: :examples, Passed: :passed, Failures: :failures")
+
+ @tests_processing_bar.start # Se inicia la multi barra de progreso
+
+ # Se establece el estado inicial de las barras
+ @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
+ @tests_running_progress_bar.advance(0) # Esto obliga a que esta barra se muestre antes que los siguientes
+ @tests_running_progress_bar.pause
+
+ @agents_bar.advance(0, connected: "0", working: "0")
+ @tests_result_bar.advance(0, examples: "0", passed: "0", failures: "0")
end
# Inicia un cliente udp que hace un broadcast en toda la red para iniciar una conexión con los Agent que estén escuchando
def start_client_socket_to_search_agents(manager_data)
# El cliente udp se ejecuta en bucle dentro de un hilo, esto permite realizar otras tareas mientras este hilo sigue sondeando
# la red para obtener mas Agents. Una vez que los tests terminan de ejecutarse, este hilo será finalizado.
Thread.new do
Liri.logger.info('Searching agents... Wait')
- Liri.logger.info("Sending UDP broadcast each #{Liri.udp_request_delay} seconds in UDP port: #{@udp_port}")
- while agents_search_processing_enabled
+ Liri.logger.info("Sending UDP broadcast each #{Manager.udp_request_delay} seconds in UDP port: #{@udp_port}")
+ while processing
@udp_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
@udp_socket.send(manager_data.to_h.to_json, 0, '<broadcast>', @udp_port)
- sleep(Liri.udp_request_delay) # Se pausa un momento antes de efectuar nuevamente la petición broadcast
+ sleep(Manager.udp_request_delay) # Se pausa un momento antes de efectuar nuevamente la petición broadcast
end
end
end
# Inicia un servidor tcp para procesar los pruebas después de haberse iniciado la conexión a través de udp
@@ -147,15 +216,17 @@
end
Liri.logger.info("Waiting Agents connection in TCP port: #{@tcp_port}")
# El siguiente bucle permite que varios clientes es decir Agents se conecten
# De: http://www.w3big.com/es/ruby/ruby-socket-programming.html
- while test_processing_enabled
+ while processing
Thread.start(tcp_socket.accept) do |client|
agent_ip_address = client.remote_address.ip_address
- hardware_model = nil
+ hardware_specs = nil
run_tests_batch_time_start = nil
+ share_source_code_time_start = nil
+ share_source_code_progress_bar = nil
while line = client.gets
client_data = JSON.parse(line.chop)
msg = client_data['msg']
@@ -164,210 +235,321 @@
client.puts({ msg: 'already_connected' }.to_json)
client.close
break
else
register_agent(agent_ip_address)
- hardware_model = client_data['hardware_model']
- msg = all_tests.any? ? 'proceed_get_source_code' : 'no_exist_tests'
+ update_connected_agents(agent_ip_address)
+ hardware_specs = client_data['hardware_specs']
+ msg = processing ? 'proceed_get_source_code' : 'no_exist_tests'
+ share_source_code_time_start = Time.now
+
+ share_source_code_progress_bar = start_share_source_code_progress_bar(hardware_specs, msg)
+
client.puts({ msg: msg }.to_json)
end
end
if msg == 'get_source_code_fail'
+ stop_share_source_code_progress_bar(hardware_specs, share_source_code_progress_bar)
+
client.puts({ msg: 'finish_agent' }.to_json)
client.close
break
end
+ # Primera ejecucion de pruebas
if msg == 'get_tests_files'
+ stop_share_source_code_progress_bar(hardware_specs, share_source_code_progress_bar)
+
+ share_source_code_time_end = Time.now - share_source_code_time_start
+
Liri.logger.info("Running unit tests. Agent: #{agent_ip_address}. Wait... ", false)
+
+ start_tests_running_progress_bar
run_tests_batch_time_start = Time.now
+ update_working_agents(agent_ip_address)
+ tests_batch = tests_batch(agent_ip_address, hardware_specs, share_source_code_time_end)
- tests_batch = tests_batch(agent_ip_address)
if tests_batch.empty?
client.puts({ msg: 'no_exist_tests' }.to_json)
client.close
break
else
client.puts(tests_batch.to_json) # Se envia el lote de tests
end
end
+ # Segunda ejecucion de pruebas y las siguientes ejecuciones
if msg == 'processed_tests'
tests_result = client_data
Liri.logger.debug("Agent response #{agent_ip_address}: #{tests_result}")
- batch_run = Time.now - run_tests_batch_time_start
- process_tests_result(agent_ip_address, hardware_model, tests_result, batch_run)
+ process_tests_result(agent_ip_address, hardware_specs, tests_result, run_tests_batch_time_start)
run_tests_batch_time_start = Time.now
- tests_batch = tests_batch(agent_ip_address)
+ tests_batch = tests_batch(agent_ip_address, hardware_specs, 0)
if tests_batch.empty?
client.puts({ msg: 'no_exist_tests' }.to_json)
client.close
break
else
client.puts(tests_batch.to_json) # Se envia el lote de tests
end
end
end
- update_processing_statuses
Thread.kill(search_agents_thread)
- unregister_agent(agent_ip_address)
rescue Errno::EPIPE => e
# Esto al parecer se da cuando el Agent ya cerró las conexiones y el Manager intenta contactar
Liri.logger.error("Exception(#{e}) Agent #{agent_ip_address} already finished connection")
# Si el Agente ya no responde es mejor terminar el hilo. Aunque igual quedará colgado el Manager
# mientras sigan pruebas pendientes
- unregister_agent(agent_ip_address)
Thread.exit
end
end
-
- @tests_result.print_summary
- print_agents_summary
- print_agents_detailed_summary if Liri.print_agents_detailed_summary
- @tests_result.print_failures_list if Liri.print_failures_list
- @tests_result.print_failed_examples if Liri.print_failed_examples
end
- def all_tests
+ def processing
@semaphore.synchronize do
- @all_tests
+ @unfinished_tests_batches.positive?
end
end
- def agents_search_processing_enabled=(value)
- @semaphore.synchronize do
- @agents_search_processing_enabled = value
+ def build_tests_batches(all_tests)
+ while all_tests.any?
+ @batch_num += 1 # Se numera cada lote
+ samples = all_tests.sample!(Manager.test_files_by_runner) # Se obtiene algunos tests
+ samples_keys = samples.keys # Se obtiene la clave asignada a los tests
+ files_count = samples.size
+ status = "pending"
+ @tests_files_count += files_count
+ # Se construye el lote a enviar
+ tests_batch = {
+ batch_num: @batch_num,
+ tests_batch_keys: samples_keys,
+ msg: "process_tests",
+ files_count: files_count,
+ status: status,
+ files_status: "#{files_count} #{status}",
+ agent_ip_address: "",
+ examples: 0,
+ passed: 0,
+ failures: 0,
+ pending: 0,
+ failed_files: "",
+ files_load: 0,
+ finish_in: 0,
+ batch_run: 0,
+ share_source_code: 0,
+ tests_runtime: 0,
+ hardware_specs: ""
+ }
+ @tests_batches[@batch_num] = tests_batch
end
- end
- def agents_search_processing_enabled
- @semaphore.synchronize do
- @agents_search_processing_enabled
- end
+ @unfinished_tests_batches = @batch_num
end
- def test_processing_enabled
+ def tests_batch(agent_ip_address, hardware_specs, share_source_code_time_end)
+ # Se inicia un semáforo para evitar que varios hilos actualicen variables compartidas
@semaphore.synchronize do
- @test_processing_enabled
- end
- end
+ return {} if @unfinished_tests_batches.zero?
- def update_processing_statuses
- @semaphore.synchronize do
- @test_processing_enabled = false if @all_tests_count == @files_processed
- @agents_search_processing_enabled = false if @all_tests_count == @all_tests_processing_count
- end
- end
+ tests_batch = {}
+ pending_tests_batch = {}
+ sent_tests_batch = {}
- def tests_batch(agent_ip_address)
- # Se inicia un semáforo para evitar que varios hilos actualicen variables compartidas
- @semaphore.synchronize do
- return {} if @all_tests.empty?
+ @tests_batches.each_value do |batch|
+ if batch[:status] == "pending"
+ pending_tests_batch = batch
+ break
+ elsif batch[:status] == "sent"
+ sent_tests_batch = batch # Es importante que este no tenga un break para guardar el ultimo enviado
+ # el cual tiene menos probabilidades de terminar de ejecutarse rapido
+ end
+ end
- @tests_batch_number += 1 # Se numera cada lote
- samples = @all_tests.sample!(Manager.test_files_by_runner) # Se obtiene algunos tests
- samples_keys = samples.keys # Se obtiene la clave asignada a los tests
- @all_tests_processing_count += samples_keys.size
+ # Es importante setear el status y el hardware_spec solo si los hashes no estan vacios
+ # Porque si estan vacios significa que ya no hay tests que ejecutar, y si seteamos algun valor en el hash
+ # estando este vacio entonces se tratara de ejecutar algo sin los datos suficientes y fallara
+ if pending_tests_batch.any?
+ tests_batch = pending_tests_batch
+ tests_batch[:status] = "sent"
+ tests_batch[:agent_ip_address] = agent_ip_address
+ tests_batch[:hardware_specs] = hardware_specs
+ elsif sent_tests_batch.any?
+ tests_batch = sent_tests_batch
+ tests_batch[:status] = "resent"
+ tests_batch[:agent_ip_address] = agent_ip_address
+ tests_batch[:hardware_specs] = hardware_specs
+ end
- tests_batch = { msg: 'process_tests', tests_batch_number: @tests_batch_number, tests_batch_keys: samples_keys } # Se construye el lote a enviar
+ return {} if tests_batch.empty?
+
+ tests_batch[:agent_ip_address] = agent_ip_address
+ tests_batch[:share_source_code] = share_source_code_time_end
+
Liri.logger.debug("Tests batches sent to Agent #{agent_ip_address}: #{tests_batch}")
- tests_batch
+ # se devuelve el hash con los datos que se enviarán al agente, por eso, primero se remueven los datos innecesarios
+ tests_batch.remove(:files_count, :status, :files_status, :agent_ip_address, :examples, :passed, :failures,
+ :pending, :failed_files, :files_load, :finish_in, :batch_run, :share_source_code,
+ :tests_runtime, :hardware_specs)
end
end
- def process_tests_result(agent_ip_address, hardware_model, tests_result, batch_run)
+ def process_tests_result(agent_ip_address, hardware_specs, tests_result, run_tests_batch_time_start)
# Se inicia un semáforo para evitar que varios hilos actualicen variables compartidas
@semaphore.synchronize do
- tests_batch_number = tests_result['tests_batch_number']
+ batch_num = tests_result['batch_num']
tests_result_file_name = tests_result['tests_result_file_name']
- files_processed = tests_result['tests_batch_keys_size']
+ status = "processed"
+ # Sólo se procesan las pruebas en estado sent o resent, caso contrario no se avanza con el procesamiento
+ return if (["pending", status]).include?(@tests_batches[batch_num][:status])
- @files_processed += files_processed
+ tests_result = @tests_result.process(tests_result_file_name)
+ return if tests_result.empty?
- @progressbar.progress = @files_processed
+ @unfinished_tests_batches -= 1
- tests_result = @tests_result.process(tests_result_file_name, files_processed)
+ files_count = @tests_batches[batch_num][:files_count]
+ @files_processed += files_count
- @processed_tests_batches[tests_batch_number] = tests_result.clone
- @processed_tests_batches[tests_batch_number][:batch_run] = batch_run
- @processed_tests_batches[tests_batch_number][:agent_ip_address] = agent_ip_address
- @processed_tests_batches[tests_batch_number][:hardware_model] = hardware_model
- @processed_tests_batches[tests_batch_number][:tests_batch_number] = tests_batch_number
+ batch_runtime = Time.now - run_tests_batch_time_start
- Liri.logger.info("Processed unit tests by Agent: #{agent_ip_address}: #{files_processed}")
+ @tests_running_progress_bar.advance(files_count)
+ @tests_result_bar.advance(1, examples: @tests_result.examples.to_s, passed: @tests_result.passed.to_s, failures: @tests_result.failures.to_s)
+ @tests_running_progress_bar.stop if @unfinished_tests_batches.zero?
+
+ @tests_batches[batch_num][:status] = status
+ @tests_batches[batch_num][:files_status] = "#{files_count} #{status}"
+ @tests_batches[batch_num][:agent_ip_address] = agent_ip_address
+ @tests_batches[batch_num][:examples] = tests_result[:examples]
+ @tests_batches[batch_num][:passed] = tests_result[:passed]
+ @tests_batches[batch_num][:failures] = tests_result[:failures]
+ @tests_batches[batch_num][:pending] = tests_result[:pending]
+ @tests_batches[batch_num][:failed_files] = tests_result[:failed_files]
+ @tests_batches[batch_num][:files_load] = tests_result[:files_load]
+ @tests_batches[batch_num][:finish_in] = tests_result[:finish_in]
+ @tests_batches[batch_num][:batch_run] = batch_runtime
+ @tests_batches[batch_num][:tests_runtime] = @tests_batches[batch_num][:batch_run] + @tests_batches[batch_num][:share_source_code]
+ @tests_batches[batch_num][:hardware_specs] = hardware_specs
+
+ Liri.logger.info("Processed unit tests by Agent: #{agent_ip_address}: #{files_count}")
end
end
- def print_agents_summary
+ def print_results
+ @tests_processing_bar&.stop
+ print_summary_table if Manager.print_summary_table
+ print_detailed_table if Manager.print_detailed_table
+ @tests_result.print_summary_failures if Manager.print_summary_failures
+ @tests_result.print_detailed_failures if Manager.print_detailed_failures
+ end
+
+ def print_summary_table
processed_tests_batches_by_agent = processed_tests_batches_by_agents
rows = processed_tests_batches_by_agent.values.map do |value|
- value[:finish_in] = value[:finish_in].to_duration
- value[:files_load] = value[:files_load].to_duration
- value[:batch_run] = value[:batch_run].to_duration
+ value[:files_load] = to_duration(value[:files_load]) if value[:files_load]
+ value[:finish_in] = to_duration(value[:finish_in]) if value[:finish_in]
+ value[:batch_run] = to_duration(value[:batch_run]) if value[:batch_run]
+ value[:share_source_code] = to_duration(value[:share_source_code]) if value[:share_source_code]
+ value[:tests_runtime] = to_duration(value[:tests_runtime]) if value[:tests_runtime]
value.values
end
- rows << Array.new(9) # Se agrega una linea vacia antes de mostrar los totales
- rows << get_footer_values
+ rows << Array.new(rows.size) # Se agrega una linea vacia antes de mostrar los totales
+ rows << summary_footer.remove(:batch_num).values
header = processed_tests_batches_by_agent.values.first.keys
table = Terminal::Table.new title: 'Summary', headings: header, rows: rows
table.style = { padding_left: 3, border_x: '=', border_i: 'x'}
- puts table
+
+ Liri.logger.info("\n#{table}", true)
end
def processed_tests_batches_by_agents
tests_batches = {}
- @processed_tests_batches.values.each do |processed_test_batch|
+ files_count = {}
+ @tests_batches.each_value do |processed_test_batch|
agent_ip_address = processed_test_batch[:agent_ip_address]
- if tests_batches[agent_ip_address]
- tests_batches[agent_ip_address][:examples] += processed_test_batch[:examples]
- tests_batches[agent_ip_address][:failures] += processed_test_batch[:failures]
- tests_batches[agent_ip_address][:pending] += processed_test_batch[:pending]
- tests_batches[agent_ip_address][:passed] += processed_test_batch[:passed]
- tests_batches[agent_ip_address][:finish_in] += processed_test_batch[:finish_in]
- tests_batches[agent_ip_address][:files_load] += processed_test_batch[:files_load]
- tests_batches[agent_ip_address][:files_processed] += processed_test_batch[:files_processed]
- tests_batches[agent_ip_address][:batch_run] += processed_test_batch[:batch_run]
+ status = processed_test_batch[:status]
+ key = "#{agent_ip_address}#{status}"
+ if tests_batches[key]
+ files_count[key] += processed_test_batch[:files_count]
+ tests_batches[key][:files_status] = "#{files_count[key]} #{status}"
+ tests_batches[key][:examples] += processed_test_batch[:examples]
+ tests_batches[key][:passed] += processed_test_batch[:passed]
+ tests_batches[key][:failures] += processed_test_batch[:failures]
+ tests_batches[key][:failed_files] += processed_test_batch[:failed_files] if Manager.show_failed_files_column
+ tests_batches[key][:files_load] += processed_test_batch[:files_load] if Manager.show_files_load_column
+ tests_batches[key][:finish_in] += processed_test_batch[:finish_in] if Manager.show_finish_in_column
+ tests_batches[key][:batch_run] += processed_test_batch[:batch_run] if Manager.show_batch_run_column
+ tests_batches[key][:share_source_code] += processed_test_batch[:share_source_code] if Manager.show_share_source_code_column
+ tests_batches[key][:tests_runtime] += processed_test_batch[:tests_runtime]
else
+ files_count[key] = processed_test_batch[:files_count]
+
_processed_test_batch = processed_test_batch.clone # Clone to change values in other hash
- _processed_test_batch.remove!(:failures_list, :failed_examples, :agent_ip_address, :tests_batch_number)
- tests_batches[agent_ip_address] = _processed_test_batch
+ _processed_test_batch.remove!(:batch_num, :tests_batch_keys, :msg, :files_count, :status, :agent_ip_address,
+ :pending)
+
+ _processed_test_batch.remove!(:failed_files) unless Manager.show_failed_files_column
+ _processed_test_batch.remove!(:files_load) unless Manager.show_files_load_column
+ _processed_test_batch.remove!(:finish_in) unless Manager.show_finish_in_column
+ _processed_test_batch.remove!(:batch_run) unless Manager.show_batch_run_column
+ _processed_test_batch.remove!(:share_source_code) unless Manager.show_share_source_code_column
+ _processed_test_batch[:files_status] = "#{files_count[key]} #{status}"
+
+ tests_batches[key] = _processed_test_batch
end
end
tests_batches
end
- def print_agents_detailed_summary
- puts "\n"
- rows = @processed_tests_batches.values.map do |value|
- value.remove!(:failures_list, :failed_examples, :agent_ip_address, :tests_batch_number)
- value[:finish_in] = value[:finish_in].to_duration
- value[:files_load] = value[:files_load].to_duration
- value[:batch_run] = value[:batch_run].to_duration
+ def print_detailed_table
+ rows = @tests_batches.values.map do |value|
+ value.remove!(:tests_batch_keys, :msg, :files_count, :status, :agent_ip_address, :pending)
+
+ value.remove!(:failed_files) unless Manager.show_failed_files_column
+ value.remove!(:files_load) unless Manager.show_files_load_column
+ value.remove!(:finish_in) unless Manager.show_finish_in_column
+ value.remove!(:batch_run) unless Manager.show_batch_run_column
+ value.remove!(:share_source_code) unless Manager.show_share_source_code_column
+
+ value[:files_load] = to_duration(value[:files_load]) if value[:files_load]
+ value[:finish_in] = to_duration(value[:finish_in]) if value[:finish_in]
+ value[:batch_run] = to_duration(value[:batch_run]) if value[:batch_run]
+ value[:share_source_code] = to_duration(value[:share_source_code]) if value[:share_source_code]
+ value[:tests_runtime] = to_duration(value[:tests_runtime])
value.values
end
- rows << Array.new(9) # Se agrega una linea vacia antes de mostrar los totales
- rows << get_footer_values
- header = @processed_tests_batches.values.first.keys
+ rows << Array.new(rows.size) # Se agrega una linea vacia antes de mostrar los totales
+ rows << summary_footer.values
+ header = @tests_batches.values.first.keys
table = Terminal::Table.new title: 'Detailed Summary', headings: header, rows: rows
table.style = { padding_left: 3, border_x: '=', border_i: 'x' }
- puts table
+ Liri.logger.info("\n#{table}", true)
end
- def get_footer_values
- footer = { examples: @tests_result.examples, failures: @tests_result.failures, pending: @tests_result.pending,
- passed: @tests_result.passed, finish_in: "", files_load: "",
- files_processed: @tests_result.files_processed, batch_run: "", hardware_model: "" }
- footer.values
+ def summary_footer
+ hash = {}
+ hash[:batch_num] = ""
+ hash[:files_status] = "#{@tests_files_count} in total"
+ hash[:examples] = @tests_result.examples
+ hash[:passed] = @tests_result.passed
+ hash[:failures] = @tests_result.failures
+ hash[:failed_files] = "" if Manager.show_failed_files_column
+ hash[:files_load] = "" if Manager.show_files_load_column
+ hash[:finish_in] = "" if Manager.show_finish_in_column
+ hash[:batch_run] = "" if Manager.show_batch_run_column
+ hash[:share_source_code] = "" if Manager.show_share_source_code_column
+ hash[:tests_runtime] = ""
+ hash[:hardware_specs] = ""
+ hash
end
def registered_agent?(agent_ip_address)
@agents[agent_ip_address]
end
@@ -375,10 +557,70 @@
def register_agent(agent_ip_address)
@agents[agent_ip_address] = agent_ip_address
Liri.logger.info("\nStarted connection with Agent: #{agent_ip_address} in TCP port: #{@tcp_port}")
end
- def unregister_agent(agent_ip_address)
- @agents.remove!(agent_ip_address)
+ def update_connected_agents(agent_ip_address)
+ unless @connected_agents[agent_ip_address]
+ @connected_agents[agent_ip_address] = agent_ip_address
+ update_agents_bar
+ end
+ end
+
+ def update_working_agents(agent_ip_address)
+ unless @working_agents[agent_ip_address]
+ @working_agents[agent_ip_address] = agent_ip_address
+ update_agents_bar
+ end
+ end
+
+ def update_agents_bar
+ @agents_bar.advance(1, connected: @connected_agents.size.to_s, working: @working_agents.size.to_s)
+ end
+
+ def start_share_source_code_progress_bar(hardware_specs, msg)
+ if msg == 'proceed_get_source_code' && Manager.show_share_source_code_progress_bar
+ 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)
+ share_source_code_progress_bar.start
+ share_source_code_progress_bar.use(Common::TtyProgressbar::TimeFormatter)
+ Thread.new do
+ animation_count = 0
+ while !share_source_code_progress_bar.stopped?
+ share_source_code_progress_bar.advance(1, agent: hardware_specs)
+
+ share_source_code_progress_bar.update(unknown: Common::TtyProgressbar::ANIMATION2[animation_count])
+ animation_count += 1
+ animation_count = 0 if animation_count == 3
+
+ sleep(0.1)
+ end
+ end
+ end
+ share_source_code_progress_bar
+ end
+
+ def stop_share_source_code_progress_bar(hardware_specs, share_source_code_progress_bar)
+ if Manager.show_share_source_code_progress_bar
+ share_source_code_progress_bar.update(total: 1, agent: hardware_specs)
+ share_source_code_progress_bar.stop
+ end
+ end
+
+ def start_tests_running_progress_bar
+ @semaphore.synchronize do
+ # Es importante hacer un reset acá osino va a contar desde que se instancia y no desde que se inicia la ejecución
+ # del primer test. Solo se resetea si esta paused para evitar que al conectarse con cada Agent se vuelva a resetear
+ @tests_running_progress_bar.reset if @tests_running_progress_bar.paused?
+ Thread.new do
+ while !@tests_running_progress_bar.stopped?
+ @tests_running_progress_bar.advance(0)
+ sleep(0.1) # Es importante que las otras barras tambien tengan el mismo sleep para que sean mas consistentes en sus resultados
+ end
+ end
+ end
+ end
+
+ def to_duration(value)
+ Common::Duration.humanize(value, times_round: Liri.times_round, times_round_type: Liri.times_round_type)
end
end
end
\ No newline at end of file