class BaseChip::Action

Attributes

random_generator[W]

Public Instance Methods

clean() click to toggle source
# File lib/base_chip/action.rb, line 274
def clean
  return if @needs_clobber
  clobber
end
clobber() click to toggle source
# File lib/base_chip/action.rb, line 278
def clobber
  @clean_proc.call(self) if @clean_proc
  FileUtils.rm_rf    @directory
  FileUtils.rm_rf "#{@directory}.tgz"
end
configure() click to toggle source
Calls superclass method
# File lib/base_chip/action.rb, line 55
def configure
  return if @configured
  unless @test
    @bundle_name  ||= if BaseChip.options.random_bundle_names
                        random_string
                      else
                        @name.to_s
                      end
    @directory    ||= @configuration.out_directory + "/#{@bundle_name}"
  end
  super
end
generate_seed(format, bits=32) click to toggle source
# File lib/base_chip/action.rb, line 288
def generate_seed(format, bits=32)
  case format
  when :num
     @random_generator.rand(2 ** bits)
  when :hex
    (@random_generator.rand(2 ** bits)).to_hex
  when :dec
    (@random_generator.rand(2 ** bits)).to_s
  when :alphanumeric
    random_string(bits)
  end
end
inner_run() click to toggle source
# File lib/base_chip/action.rb, line 114
def inner_run
  # puts "#{full_name} started"
  script_file = "#{@name}.bash"
  script = File.open(script_file,'w')
  script.puts "#!/bin/bash"
  # $environment.each do |n,v|
  #   script.puts "export #{n}=#{v}"
  # end
  if @environment
    @environment.each do |n,v|
      script.puts "export #{n}=#{v}"
    end
  end

  script.puts "NAME=#{@name}"
  script.puts "BLOCK=#{@block.name}"
  if @args
    script.puts "ARGS='#{@args.gsub(/'/,"\\'")}'"
  end

  # FIXME fault if commands and command both exist
  if            @commands
    script.puts @commands
  elsif         @command 
    script.puts @pre_commands  if @pre_commands
    script.puts "#{@command_prefix} #{@command} #{@command_suffix} $*"
    script.puts @post_commands if @post_commands
  else
    fault "Action #{@name} has no command(s) specified to run"
  end

  script.chmod 0777
  script.close
  process_status = nil
  errmsg         = ''

  STDOUT.sync = true
  STDERR.sync = true

  @before.call if @before

  script_call = (@foreground || @log_to || @stdout_to) ? script.path : "#{script.path} > /dev/null"

     log_storage = (   @log_to                         ) ? File.open(   @log_to, 'w') : nil
  stdout_storage = (@stdout_to && @stdout_to != @log_to) ? File.open(@stdout_to, 'w') : nil
  stderr_storage = (@stderr_to && @stderr_to != @log_to) ? File.open(@stderr_to, 'w') : nil

  # stdin, stdout, stderr, wait_thr = Open3.popen3([env,] cmd... [, opts])
  Open3.popen3(script_call) do |stdin, stdout, stderr, wait_thr|
   
    to = Thread.new(stdout) do |pipe|
      out_data = nil
      loop do
        begin
          out_data = pipe.readpartial(4096)
        rescue EOFError, IOError
          break
        end
                STDOUT.print out_data if @foreground
           log_storage.print out_data if    log_storage
        stderr_storage.print out_data if stderr_storage
      end
    end
    ti = Thread.new(STDIN) do |pipe|
      in_data = nil
      loop do
        begin
          in_data = pipe.readpartial(4096)
        rescue EOFError, IOError
          break
        end
                   stdin.print in_data if @foreground && !stdin.closed?
        if @echo_stdin
                  STDOUT.print in_data if @foreground
             log_storage.print in_data if    log_storage
          stderr_storage.print in_data if stdout_storage
        end
      end
    end
    te = Thread.new(stderr) do |pipe|
      err_data = nil
      loop do
        begin
          err_data = pipe.readpartial(4096)
        rescue EOFError, IOError
          break
        end
        errmsg += err_data
                STDERR.print err_data if @foreground
           log_storage.print err_data if    log_storage
        stderr_storage.print err_data if stderr_storage
      end
    end

    begin
      wait_thr.join
      if @foreground
        ti.kill
        to.kill unless te.join(10)
      end
      te  .kill unless te.join(10)
    rescue Interrupt
      if @foreground #  && @int_for_shell
        Process.kill 'INT', wait_thr.pid
        retry
      else
        raise
      end
    end
    process_status = wait_thr.value # Process::Status object returned.
  end

     log_storage.close if    log_storage
  stdout_storage.close if stdout_storage
  stderr_storage.close if stderr_storage

  @after.call if @after

  statistics = {}
  totals     = {}
  if @out_files
    @out_files.each_value do |f|
      f.go(@name)
     
      take_state(f)

      statistics.merge! f.statistics if f.statistics
      totals    .merge! f.totals     if f.totals

      # warning!(pf,ps) if f.warning?
      # error!(  pf,ps) if f.error?
      # fault!(  pf,ps) if f.fault?
    end
  end
  error!(nil, errmsg) if !process_status.success? || errmsg.size > 0

  @state ||= 'pass'
  @state = 'fail' unless self.pass? # state is error, warning or fault up to this point

  # puts "log file produced #{totals}"
  totals.each do |k,v|
    if statistics[k].for_states.include? @state
      if statistics[k].across_states
        @totals[k] = v
      end
      if statistics[k].per_state
        @totals["#{@state}_#{k}"] = v
      end
      # FIXME error_if_missing
    end
  end
  # puts "we collected #{@totals}"

  unless pass?
    @problem.bundle=(@bundle_tgz || @directory)
    # error(@problem.to_s)
  end
  # puts "#{full_name} ended"
end
random_generator() click to toggle source
# File lib/base_chip/action.rb, line 285
def random_generator
  @random_generator ||= BaseChip.new_random_generator
end
rerun_data() click to toggle source
# File lib/base_chip/action.rb, line 301
def rerun_data
  { 'full_name'         => full_name                          ,
    'seed'              => random_generator.seed              ,
    'modes'             => modes                              ,
     'append_arguments' => BaseChip.options. append_arguments ,
    'replace_arguments' => BaseChip.options.replace_arguments }
end
run() click to toggle source
# File lib/base_chip/action.rb, line 67
def run
  if @run_action_in_tmp
    bundle_name   = random_string
    run_directory = "/tmp/#{bundle_name}"
  else
    bundle_name   = @bundle_name
    run_directory = @directory
  end
  FileUtils.rm_rf   run_directory
  FileUtils.mkdir_p run_directory
  Dir.pushd         run_directory

  File.open('seed','w') do |f|
    f.write random_generator.seed
  end
  File.open('rerun.yaml','w') do |f|
    f.write rerun_data.to_yaml
  end

  # Where the magic happens
  inner_run

  FileUtils.touch "#{run_directory}/.fail_detected" unless self.pass?

  Dir.chdir '..'
  if (@clean_passing_action && pass? && !@foreground)
    FileUtils.rm_rf run_directory
  else
    bundle_tgz = nil
    if @zip_failing_action || (@zip_passing_action && pass?)
       bundle_tgz = run_directory + ".tgz"
      @bundle_tgz =    @directory + ".tgz"
      tgz = Zlib::GzipWriter.new(File.open(bundle_tgz, 'wb'))
      Archive::Tar::Minitar.pack(bundle_name, tgz)
      FileUtils.rm_rf bundle_name
    end
    if @run_action_in_tmp
      FileUtils.mkdir_p                           "#{@directory}/.."
      FileUtils.mv((bundle_tgz || run_directory), "#{@directory}/..")
    end
  end

  puts "Debug information here: #{@bundle_tgz || @directory}" if @foreground

  # p @totals if @foreground
  Dir.popd
end