1# Copyright (c) 2021 Huawei Device Co., Ltd. 2# Licensed under the Apache License, Version 2.0 (the "License"); 3# you may not use this file except in compliance with the License. 4# You may obtain a copy of the License at 5# 6# http://www.apache.org/licenses/LICENSE-2.0 7# 8# Unless required by applicable law or agreed to in writing, software 9# distributed under the License is distributed on an "AS IS" BASIS, 10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11# See the License for the specific language governing permissions and 12# limitations under the License. 13 14module TestRunner 15 16 ERROR_NODATA = 86 17 ERROR_CANNOT_CREATE_PROCESS = 87 18 ERROR_TIMEOUT = 88 19 20 def self.log(level, *args) 21 puts args if level <= $VERBOSITY 22 end 23 24 def self.print_exception(exception) 25 puts "Exception: exception class : #{exception.class}" 26 puts " exception message : #{exception.message}" 27 exception.backtrace.each do |t| 28 puts " trace : #{t}" 29 end 30 end 31 32 def self.split_separated_by_colon(string) 33 string.split(':') 34 .drop(1) 35 .flat_map { |s| s.split(',').map(&:strip) } 36 end 37 38 class CommandRunner 39 def initialize(command, reporter) 40 @command = command 41 @reporter = reporter 42 end 43 44 def dump_output(t, output_err, output) 45 start = Time.now 46 47 while (Time.now - start) <= $TIMEOUT and t.alive? 48 Kernel.select([output_err], nil, nil, 1) 49 begin 50 output << output_err.read_nonblock(256) 51 rescue IO::WaitReadable 52 rescue EOFError 53 return true 54 end 55 end 56 !t.alive? 57 end 58 59 def start_process_timeout 60 begin 61 input, output_err, t = if $enable_core 62 Open3.popen2e(@command, :pgroup => true) 63 else 64 Open3.popen2e(@command, :pgroup => true, :rlimit_core => 0) 65 end 66 pid = t[:pid] 67 output = "" 68 finished = dump_output t, output_err, output 69 70 input.close 71 output_err.close 72 73 if !finished 74 output << "Process hangs for #{$TIMEOUT}s '#{@command}'\n" \ 75 "Killing pid:#{pid}" 76 begin 77 Process.kill('-TERM', Process.getpgid(pid)) 78 rescue Errno::ESRCH 79 rescue Exception => e 80 TestRunner.print_exception e 81 end 82 return output, ERROR_TIMEOUT, false 83 end 84 85 exitstatus = if t.value.coredump? 86 t.value.termsig + 128 87 else 88 t.value.exitstatus 89 end 90 91 return output, exitstatus, t.value.coredump? 92 rescue Errno::ENOENT => e 93 return "Failed to start #{@command} - no executable", 94 ERROR_CANNOT_CREATE_PROCESS, false 95 rescue 96 return "Failed to start #{@command}", 97 ERROR_CANNOT_CREATE_PROCESS, false 98 end 99 end 100 101 def run_cmd() 102 @reporter.log_start_command @command 103 StringIO.open do |content| 104 content.puts "# Start command: #{@command}" 105 output, exitstatus, core = start_process_timeout 106 content.puts output 107 return content.string, exitstatus, core 108 end 109 end 110 111 end # Runner 112end # module 113