Module: Elasticsearch::Tests::CodeRunner

Includes:
Printer
Included in:
Test
Defined in:
lib/elasticsearch/tests/code_runner.rb

Overview

The module in charge of actually running actions and matching expected results with actual response results.

Constant Summary collapse

COMPARATORS =
{
  'lt' => '<',
  'lte' => '<=',
  'gt' => '>',
  'gte' => '>='
}.freeze

Constants included from Printer

Printer::BOX_WIDTH

Instance Method Summary collapse

Methods included from Printer

display_errors, display_summary, #print_debug_catchable, #print_debug_message, #print_error, #print_failure, #print_match_failure, #print_success, #quiet?

Instance Method Details

#compare(action) ⇒ Object

Used for comparing gte (greater or equal than), gt (greater than), lte (less or equal than) and lt (less than) action - { ‘gte’ => { ‘key’ => value } }



192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/elasticsearch/tests/code_runner.rb', line 192

def compare(action)
  operator, value = action.first

  result = search_in_response(value.keys.first)
  if result&.send(COMPARATORS[operator], value[value.keys.first])
    print_success
  else
    print_failure(action, @response)
    message = "comparision failure\n#{result} #{COMPARATORS[operator]} #{value[value.keys.first]}"
    raise ActionError.new(message, $test_file, action)
  end
end

#do_action(action) ⇒ Object

The main functionality in the test runner, run actions with the client from YAML ‘do` specifications. These are function calls to the Elasticsearch clients.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/elasticsearch/tests/code_runner.rb', line 39

def do_action(action)
  @response = nil
  catchable = action.delete('catch')
  client = @client
  if action['headers']
    client.transport.options[:transport_options][:headers].merge(
      { headers: action.delete('headers') }
    )
  end

  action = action.first if action.is_a?(Array)
  method, params = action.is_a?(String) ? [action, {}] : action.first

  # Get the namespace client if the method is namespaced
  if method.include?('.')
    arrayed_method = method.split('.')
    client = @client.send(arrayed_method.first)
    method = arrayed_method.last
  end
  params = process_params(params)
  @response = client.send(method.to_sym, params)
  print_debug_message(method.to_sym, params) if debug?
  @response
rescue StandardError => e
  # Raise if it's an actual error:
  unless expected_exception?(catchable, e)
    print_failure(action, @response, e)
    raise e
  end
  # Show success if we caught an expected exception:
  print_success
  print_debug_catchable(e) if debug?
end

#do_length(action) ⇒ Object



143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/elasticsearch/tests/code_runner.rb', line 143

def do_length(action)
  k, v = action['length'].first
  result = search_in_response(k)
  result = result.count
  if result && result == v
    print_success
  else
    print_failure(action, @response)
    message = "do_length failure\nExpected #{k}: #{v}.\nResult: #{result}"
    raise ActionError.new(message, $test_file, action)
  end
end

#do_match(action) ⇒ Object

Code for matching expectations and response



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/elasticsearch/tests/code_runner.rb', line 110

def do_match(action)
  k, v = action['match'].first

  v = if v.is_a?(String) && v.include?('$')
        instance_variable_get(v.gsub('$', '@'))
      elsif v.is_a?(Array)
        v.map do |a|
          a.is_a?(String) && a.start_with?('$') ? instance_variable_get(a.gsub('$', '@')) : a
        end
      else
        v
      end
  result = search_in_response(k)

  if !result.nil? && (
       result == v ||
       (result.respond_to?(:include?) && result.include?(v)) ||
       match_regexp(v, result)
     )
    print_success
  else
    print_match_failure(action)
    message = "Match failure\nExpected #{k}: #{v}.\nResult: #{result}"
    raise ActionError.new(message, $test_file, action)
  end
end

#expected_exception?(error_type, e) ⇒ Boolean

The keyword ‘catch` is used in the yaml tests to catch exceptions. This code looks at the expected error and the response error to compare them and check that we got the expected exception.

Returns:

  • (Boolean)


76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/elasticsearch/tests/code_runner.rb', line 76

def expected_exception?(error_type, e)
  return false if error_type.nil?

  case error_type
  when 'request_timeout'
    e.is_a?(Elastic::Transport::Transport::Errors::RequestTimeout)
  when 'missing', /resource_not_found_exception/
    e.is_a?(Elastic::Transport::Transport::Errors::NotFound)
  when 'conflict'
    e.is_a?(Elastic::Transport::Transport::Errors::Conflict)
  when 'request'
    e.is_a?(Elastic::Transport::Transport::Errors::InternalServerError)
  when 'bad_request'
    e.is_a?(Elastic::Transport::Transport::Errors::BadRequest)
  when 'param'
    actual_error.is_a?(ArgumentError)
  when 'unauthorized'
    e.is_a?(Elastic::Transport::Transport::Errors::Unauthorized)
  when 'forbidden'
    e.is_a?(Elastic::Transport::Transport::Errors::Forbidden)
  when /error parsing field/, /illegal_argument_exception/
    e.message.match?(/\[400\]/) ||
      e.is_a?(Elastic::Transport::Transport::Errors::BadRequest)
  when /NullPointerException/
    e.message.match?(/\[400\]/)
  when /status_exception/
    e.message.match?(/\[409\]/)
  else
    e.message.match?(/#{error_type}/)
  end
end

#is_false(action) ⇒ Object



176
177
178
179
180
181
182
183
184
185
# File 'lib/elasticsearch/tests/code_runner.rb', line 176

def is_false(action)
  response_value = search_in_response(action['is_false']) unless [true, false].include? @response
  if @response == false || response_value.nil? || [false, 'false'].include?(response_value)
    print_success
  else
    print_failure(action, @response)
    message = "is_false failure\nResponse: #{response_value || @response}."
    raise ActionError.new(message, $test_file, action)
  end
end

#is_true(action) ⇒ Object

The specified key exists and has a true value (ie not 0, false, undefined, null) action - { ‘is_true’ => field } or { ‘is_true’ => ” }



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/elasticsearch/tests/code_runner.rb', line 160

def is_true(action)
  if @response.respond_to?(:body) && !@response&.nil? && ['', []].include?(action['is_true'])
    print_success
    return
  end

  response_value = search_in_response(action['is_true']) unless [true, false].include?(@response)
  if @response == true || !response_value.nil?
    print_success
  else
    print_failure(action, @response)
    message = "is_true failure\nResponse: #{response_value || @response}."
    raise ActionError.new(message, $test_file, action)
  end
end

#match_regexp(expected, result) ⇒ Object



137
138
139
140
141
# File 'lib/elasticsearch/tests/code_runner.rb', line 137

def match_regexp(expected, result)
  expected.is_a?(String) &&
    expected.match?(%r{^/}) &&
    result.match?(Regexp.new(expected.gsub('/', '').strip))
end

#set_variable(action) ⇒ Object

When the yaml test has a set instruction, set an instance variable with that value coming from the response.



207
208
209
210
# File 'lib/elasticsearch/tests/code_runner.rb', line 207

def set_variable(action)
  k, v = action['set'].first
  instance_variable_set("@#{v}", search_in_response(k))
end