Module: Baf::Testing

Defined in:
lib/baf/testing.rb,
lib/baf/testing/process.rb

Defined Under Namespace

Classes: Process, WaitError

Constant Summary collapse

ExecutionTimeout =
Class.new Error
ExitStatusMismatch =
Class.new Error
ENV_WHITELIST =
[
  /\ACHRUBY_/,
  /\AGEM_/,
  'PATH',
  /\ARB_/,
  'RUBYOPT'
].freeze
EXEC_TIMEOUT_ERROR_FMT =
'process did not exit after %.03f seconds'.freeze
EXIT_STATUS_MISMATCH_FMT =
<<~eoh.freeze
  expected %<expected>d exit status got %<actual>d; output was:
  %{separator}
  %{output}
  %{separator}
eoh
OUTPUT_SEPARATOR =
(?- * 70).freeze
WAIT_MESSAGE_FMT =
'condition not met after %.03f seconds'.freeze
WAIT_OUTPUT_MESSAGE_FMT =
<<~eoh.freeze
  expected `%{pattern}' not seen after %<timeout>.03f seconds in:
  %{separator}
  %{output}
  %{separator}
eoh
WAIT_TIMEOUT =
ENV.key?('BAF_TEST_TIMEOUT') ?
ENV['BAF_TEST_TIMEOUT'].to_i :
2
WORKING_DIR =
'tmp/uat'.freeze

Class Method Summary collapse

Class Method Details

.build_regexp(pattern, options = '') ⇒ Object



53
54
55
56
57
58
59
60
61
# File 'lib/baf/testing.rb', line 53

def build_regexp pattern, options = ''
  Regexp.new(pattern, options.each_char.inject(0) do |m, e|
    m | case e
      when ?i then Regexp::IGNORECASE
      when ?m then Regexp::MULTILINE
      when ?x then Regexp::EXTENDED
    end
  end)
end

.exercise_scenario(dir: WORKING_DIR) ⇒ Object



63
64
65
66
67
68
69
# File 'lib/baf/testing.rb', line 63

def exercise_scenario dir: WORKING_DIR
  FileUtils.remove_entry_secure dir, true
  FileUtils.mkdir_p dir
  Dir.chdir dir do
    yield
  end
end

.expect_ex(process, exit_status) ⇒ Object



71
72
73
74
75
76
77
78
79
80
# File 'lib/baf/testing.rb', line 71

def expect_ex process, exit_status
  return if process.exit_status == exit_status

  fail ExitStatusMismatch, EXIT_STATUS_MISMATCH_FMT % {
    expected: exit_status,
    actual: process.exit_status,
    separator: OUTPUT_SEPARATOR,
    output: process.output.chomp
  }
end

.run(command, wait: true, env_allow: [], timeout: nil) ⇒ Object



82
83
84
85
86
87
88
89
90
91
# File 'lib/baf/testing.rb', line 82

def run command, wait: true, env_allow: [], timeout: nil
  Process.new(
    command,
    env_allow: ENV_WHITELIST + env_allow,
    timeout: timeout || Process::TIMEOUT
  ).tap do |process|
    process.start
    wait process if wait
  end
end

.unescape_step_arg(str) ⇒ Object



100
101
102
# File 'lib/baf/testing.rb', line 100

def unescape_step_arg str
  str.gsub '\n', "\n"
end

.wait(process) ⇒ Object



93
94
95
96
97
98
# File 'lib/baf/testing.rb', line 93

def wait process
  process.wait do
    process.stop
    fail ExecutionTimeout, EXEC_TIMEOUT_ERROR_FMT % process.timeout
  end
end

.wait_output(pattern, stream:, times: 1, timeout: WAIT_TIMEOUT) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/baf/testing.rb', line 114

def wait_output pattern, stream:, times: 1, timeout: WAIT_TIMEOUT
  results = nil
  wait_until timeout: timeout do
    case pattern
      when Regexp then (results = stream.call.scan(pattern)).size >= times
      when String then stream.call.include? pattern
    end
  end
  results
rescue Baf::Testing::WaitError => e
  fail Baf::Testing::WaitError.new(WAIT_OUTPUT_MESSAGE_FMT % {
    pattern: pattern,
    timeout: timeout,
    separator: OUTPUT_SEPARATOR,
    output: stream.call.chomp
  }, timeout)
end

.wait_until(message: WAIT_MESSAGE_FMT, timeout: WAIT_TIMEOUT) ⇒ Object



104
105
106
107
108
109
110
111
112
# File 'lib/baf/testing.rb', line 104

def wait_until message: WAIT_MESSAGE_FMT, timeout: WAIT_TIMEOUT
  return if yield
  deadline = Time.now + timeout
  until Time.now >= deadline
    return if yield
    sleep 0.05
  end
  fail WaitError.new message % timeout, timeout
end

.write_file(path, content) ⇒ Object



132
133
134
135
# File 'lib/baf/testing.rb', line 132

def write_file path, content
  FileUtils.mkdir_p File.dirname path
  IO.write path, content
end