require "pathname" require "aruba/platform" require "aruba/command" # require 'win32/file' if File::ALT_SEPARATOR # Aruba module Aruba # Api module Api # Command module module Commands # Resolve path for command using the PATH-environment variable # # @param [#to_s] program # The name of the program which should be resolved # # @param [String] path # The PATH, a string concatenated with ":", e.g. /usr/bin/:/bin on a # UNIX-system def which(program, path = nil) with_environment do # ENV is set within this block path = ENV["PATH"] if path.nil? Aruba.platform.which(program, path) end end # Pipe data in file # # @param [String] file_name # The file which should be used to pipe in data def pipe_in_file(file_name) file_name = expand_path(file_name) File.open(file_name, "r").each_line do |line| last_command_started.write(line) end end # Return all commands # # @return [Array] # List of commands def all_commands aruba.command_monitor.registered_commands end # Last command started def last_command_started aruba.command_monitor.last_command_started end # Last command stopped def last_command_stopped aruba.command_monitor.last_command_stopped end # Stop all commands # # @yield [Command] # If block is given use it to filter the commands which should be # stoppend. def stop_all_commands(&block) cmds = if block all_commands.select(&block) else all_commands end cmds.each(&:stop) self end # Terminate all commands # # @yield [Command] # If block is given use it to filter the commands which should be # terminated. def terminate_all_commands(&block) cmds = if block all_commands.select(&block) else all_commands end cmds.each(&:terminate) self end # Get stdout of all processes # # @return [String] # The stdout of all processes which have run before def all_stdout aruba.command_monitor.all_stdout end # Get stderr of all processes # # @return [String] # The stderr of all processes which have run before def all_stderr aruba.command_monitor.all_stderr end # Get stderr and stdout of all processes # # @return [String] # The stderr and stdout of all processes which have run before def all_output aruba.command_monitor.all_output end # Find a started command # # @param [String, Command] commandline # The commandline def find_command(commandline) aruba.command_monitor.find(commandline) end # Run given command and stop it if timeout is reached # # @param [String] cmd # The command which should be executed # # @param [Hash] opts # Options # # @option opts [Numeric] exit_timeout # If the timeout is reached the command will be killed # # @option opts [Numeric] io_wait_timeout # Wait for IO to finish # # @option opts [Numeric] startup_wait_time # Wait for a command to start # # @option opts [String] stop_signal # Use signal to stop command # # @yield [SpawnProcess] # Run block with process # def run_command(cmd, opts = {}) command = prepare_command(cmd, opts) unless command.interactive? raise NotImplementedError, "Running interactively is not supported with this process launcher." end start_command(command) block_given? ? yield(command) : command end # Run a command with aruba # # Checks for error during command execution and checks the output to detect # an timeout error. # # @param [String] cmd # The command to be executed # # @param [Hash] opts # Options for aruba # # @option opts [Boolean] :fail_on_error # Should aruba fail on error? # # @option opts [Numeric] :exit_timeout # Timeout for execution # # @option opts [Numeric] :io_wait_timeout # Timeout for IO - STDERR, STDOUT # def run_command_and_stop(cmd, opts = {}) fail_on_error = if opts.key?(:fail_on_error) opts.delete(:fail_on_error) == true else true end command = prepare_command(cmd, opts) start_command(command) command.stop return unless fail_on_error begin expect(command).to have_finished_in_time expect(command).to be_successfully_executed rescue ::RSpec::Expectations::ExpectationNotMetError => e aruba.announcer.activate(aruba.config.activate_announcer_on_command_failure) aruba.event_bus.notify Events::CommandStopped.new(command) raise e end end # Provide data to command via stdin # # @param [String] input # The input for the command def type(input) return close_input if input == "\u0004" last_command_started.write(input << "\n") end # Close stdin def close_input last_command_started.close_io(:stdin) end private def prepare_command(cmd, opts) exit_timeout = opts[:exit_timeout] || aruba.config.exit_timeout io_wait_timeout = opts[:io_wait_timeout] || aruba.config.io_wait_timeout stop_signal = opts[:stop_signal] || aruba.config.stop_signal startup_wait_time = opts[:startup_wait_time] || aruba.config.startup_wait_time cmd = replace_variables(cmd) @commands ||= [] @commands << cmd environment = aruba.environment working_directory = expand_path(".") event_bus = aruba.event_bus cmd = Aruba.platform.detect_ruby(cmd) mode = aruba.config.command_launcher main_class = aruba.config.main_class Command.new( cmd, mode: mode, exit_timeout: exit_timeout, io_wait_timeout: io_wait_timeout, working_directory: working_directory, environment: environment.to_hash, main_class: main_class, stop_signal: stop_signal, startup_wait_time: startup_wait_time, event_bus: event_bus ) end def start_command(command) aruba.config.run_before_hook(:command, self, command) in_current_directory do command.start end stop_signal = command.stop_signal aruba.announcer.announce(:stop_signal, command.pid, stop_signal) if stop_signal aruba.config.run_after_hook(:command, self, command) end end end end