#
# == epcb/test/common
# 単体テスト/インタフェーステスト向けの共通ファイル。
#
# Revision:: $Id$
#

module EPCB
  #
  # テスト用名前空間。
  #
  module Test
    # 
    # コマンドを実行するためのユーティリティ。
    #
    class ProcessUtil

      def initialize(rm_redirected_files = false)
        @redirect_map = Hash.new
      end

      # このオブジェクトを使用してコマンドを実行する際に、
      # 標準出力、標準エラー出力をリダイレクトするように設定する。
      # === ARGS
      # redirect_io:: リダイレクト先のIOオブジェクト
      # type:: リダイレクトする出力の種別。
      #        (stdout: 標準出力, stderr:: 標準エラー出力)
      def set_redirection(redirect_io, type)
        @redirect_map[type] = redirect_io
      end

      # 標準出力、標準エラー出力をリダイレクトさせるように設定した状態で、
      # 引数のコマンドを実行する。
      # === ARGS
      # command:: 実行するコマンド
      def quiet_run(command, file = nil, line = nil)
        stdout = @redirect_map["stdout"]
        stderr = @redirect_map["stderr"]
        if stdout.nil? || stderr.nil?
          raise(StandardError, "You must set redirection by \"set_redirection\".")
        end
        redirect_run(command, stdout, stderr, file, line)
      end

      def redirect_run(command, out, err, file = nil, line = nil)
        stdout_save = STDOUT.dup
        stderr_save = STDERR.dup
        list = [ STDOUT, STDERR ]
        begin
          STDOUT.reopen(out)
          STDERR.reopen(err)
          if /^(.+?):(\d+)(?::in `(.*)')?/ =~ caller[2]
            file = $1 if file.nil?
            line = $2.to_i if line.nil?
          end
          list.each do |io|
            f = ""
            f = File.basename(file) if file != nil
            io.puts "FILE:#{f} LINE:#{line}"
            io.puts "$ #{command}"
          end
          system(command)
        ensure
          begin
            list.each do |io|
              io.puts ""
              io.flush
            end
          rescue
            # Ignore
          end
          STDOUT.reopen(stdout_save)
          STDERR.reopen(stderr_save)
        end
      end

      # このオブジェクトが最後に実行したコマンドのexitステータスを取得する。
      # === RETURNS
      # 最後に実行したコマンドのexitステータス
      def exit_status
        return $? >> 8
      end
    end #ProcessUtil#

    #
    # コマンドインタフェーステスト用の名前空間
    #
    module CLI
      class Helper < ::EPCB::CLI::Helper
        def initialize(option_holder)
          super(option_holder)
        end

        def register_at_exit(ios)
          at_exit do
            ios.each do |io|
              begin
                io.close
              rescue IOError
                # Ignore
              ensure
                begin
                  if File.exists?(io.path) && $options.remove_std
                    FileUtils.rm(io.path)
                  end
                rescue
                  # Ignore
                end
              end
            end
          end
        end

        # --data-dirオプションを定義する。
        # === ARGS
        # opts:: オプション
        def define_data_dir(opts)
          # --datadir
          opts.on("-d", "--data-dir DIR", String,
                  "specify test data directory. " \
                  "(default: \"#{$options.data_dir}\")") do |arg|
            $options.data_dir = arg
          end
        end

        # --programオプションを定義する。
        # === ARGS
        # opts:: オプション
        def define_program(opts)
          opts.on("-p", "--program FILE", String,
                  "sepcify a program of epcb-csv to run. " \
                  "(default: \"#{$options.program}\")") do |arg|
            $options.program = arg
          end
        end

        # --removeオプションを定義する。
        # === ARGS
        # opts:: オプション
        def define_remove(opts)
          opts.on("-r", "--remove",
                  "remove temporarily redirected \"stdout\" and \"stderr\".") do |arg|
            $options.remove_std = arg
          end
        end

        # --tmp-dirオプションを定義する。
        # === ARGS
        # opts:: オプション
        def define_tmp_dir(opts)
          opts.on("-t", "--tmp-dir DIR",
                  "specify temporary directory. " \
                  "(default: \"#{$options.tmp_dir}\"") do |arg|
            $options.tmp_dir = arg
          end
        end
      end #Helper#

    end #CLI#

  end #Test#

end #EPCB#
