Commit 6a1017b4 authored by Micael Bergeron's avatar Micael Bergeron

Port the named query spec to WebMock

This commit changes the method to assert for Elastic named queries to
leverage WebMock instead of a custom Faraday middleware.
parent 12a98f61
...@@ -136,6 +136,7 @@ module Elastic ...@@ -136,6 +136,7 @@ module Elastic
} }
end end
# rubocop:disable Metrics/AbcSize
def search_blob(query, type: 'blob', page: 1, per: 20, options: {}) def search_blob(query, type: 'blob', page: 1, per: 20, options: {})
page ||= 1 page ||= 1
......
...@@ -12,7 +12,7 @@ module Elastic ...@@ -12,7 +12,7 @@ module Elastic
def build_name(*args) def build_name(*args)
::Gitlab::Elastic::ExprName ::Gitlab::Elastic::ExprName
.new(self) .new(self)
.build(*current, *args) .build(*contexts.last, *args)
end end
def name(*args, &block) def name(*args, &block)
...@@ -28,12 +28,6 @@ module Elastic ...@@ -28,12 +28,6 @@ module Elastic
end end
end end
def current
return if contexts.empty?
contexts.last
end
private private
def contexts def contexts
......
...@@ -9,7 +9,7 @@ module Gitlab ...@@ -9,7 +9,7 @@ module Gitlab
# Takes a hash as returned by `ApplicationSetting#elasticsearch_config`, # Takes a hash as returned by `ApplicationSetting#elasticsearch_config`,
# and configures itself based on those parameters # and configures itself based on those parameters
def self.build(config, &block) def self.build(config)
base_config = { base_config = {
urls: config[:url], urls: config[:url],
request_timeout: config[:client_request_timeout], request_timeout: config[:client_request_timeout],
...@@ -23,11 +23,9 @@ module Gitlab ...@@ -23,11 +23,9 @@ module Gitlab
::Elasticsearch::Client.new(base_config) do |fmid| ::Elasticsearch::Client.new(base_config) do |fmid|
fmid.request(:aws_sigv4, credentials_provider: creds, service: 'es', region: region) fmid.request(:aws_sigv4, credentials_provider: creds, service: 'es', region: region)
yield fmid if block_given?
end end
else else
::Elasticsearch::Client.new(base_config, &block) ::Elasticsearch::Client.new(base_config)
end end
end end
......
...@@ -32,12 +32,10 @@ RSpec.describe Elastic::Latest::GitClassProxy, :elastic do ...@@ -32,12 +32,10 @@ RSpec.describe Elastic::Latest::GitClassProxy, :elastic do
end end
end end
it "names elasticsearch queries" do |example| it "names elasticsearch queries" do
expect_named_queries(example) do |inspector|
subject.elastic_search_as_found_blob('*') subject.elastic_search_as_found_blob('*')
expect(inspector).to have_named_query('doc:is_a:blob') assert_named_queries('doc:is_a:blob',
expect(inspector).to have_named_query('blob:match:search_terms') 'blob:match:search_terms')
end
end end
end end
...@@ -32,12 +32,10 @@ RSpec.describe Elastic::Latest::ProjectWikiClassProxy, :elastic do ...@@ -32,12 +32,10 @@ RSpec.describe Elastic::Latest::ProjectWikiClassProxy, :elastic do
end end
end end
it 'names elasticsearch queries' do |example| it 'names elasticsearch queries' do
expect_named_queries(example) do |inspector|
subject.elastic_search_as_wiki_page('*') subject.elastic_search_as_wiki_page('*')
expect(inspector).to have_named_query('doc:is_a:wiki_blob') assert_named_queries('doc:is_a:wiki_blob',
expect(inspector).to have_named_query('blob:match:search_terms') 'blob:match:search_terms')
end
end end
end end
...@@ -75,14 +75,12 @@ RSpec.describe Issue, :elastic do ...@@ -75,14 +75,12 @@ RSpec.describe Issue, :elastic do
expect(described_class.elastic_search('bla-bla', options: { project_ids: :any, public_and_internal_projects: true }).total_count).to eq(3) expect(described_class.elastic_search('bla-bla', options: { project_ids: :any, public_and_internal_projects: true }).total_count).to eq(3)
end end
it "names elasticsearch queries" do |example| it "names elasticsearch queries" do
expect_named_queries(example) do |inspector|
described_class.elastic_search('*').total_count described_class.elastic_search('*').total_count
expect(inspector).to have_named_query('doc:is_a:issue') assert_named_queries('doc:is_a:issue',
expect(inspector).to have_named_query('issue:match:search_terms') 'issue:match:search_terms',
expect(inspector).to have_named_query('issue:authorized:project') 'issue:authorized:project')
end
end end
it "searches by iid and scopes to type: issue only" do it "searches by iid and scopes to type: issue only" do
......
...@@ -40,14 +40,12 @@ RSpec.describe MergeRequest, :elastic do ...@@ -40,14 +40,12 @@ RSpec.describe MergeRequest, :elastic do
expect(described_class.elastic_search('term3', options: { project_ids: :any, public_and_internal_projects: true }).total_count).to eq(1) expect(described_class.elastic_search('term3', options: { project_ids: :any, public_and_internal_projects: true }).total_count).to eq(1)
end end
it "names elasticsearch queries" do |example| it "names elasticsearch queries" do
expect_named_queries(example) do |inspector|
described_class.elastic_search('*').total_count described_class.elastic_search('*').total_count
expect(inspector).to have_named_query('doc:is_a:merge_request') assert_named_queries('doc:is_a:merge_request',
expect(inspector).to have_named_query('merge_request:match:search_terms') 'merge_request:match:search_terms',
expect(inspector).to have_named_query('merge_request:authorized:project') 'merge_request:authorized:project')
end
end end
it "searches by iid and scopes to type: merge_request only", :sidekiq_might_not_need_inline do it "searches by iid and scopes to type: merge_request only", :sidekiq_might_not_need_inline do
......
...@@ -55,14 +55,12 @@ RSpec.describe Note, :elastic do ...@@ -55,14 +55,12 @@ RSpec.describe Note, :elastic do
expect(described_class.elastic_search('bla-bla', options: { project_ids: :any }).records).to contain_exactly(outside_note) expect(described_class.elastic_search('bla-bla', options: { project_ids: :any }).records).to contain_exactly(outside_note)
end end
it "names elasticsearch queries" do |example| it "names elasticsearch queries" do
expect_named_queries(example) do |inspector|
described_class.elastic_search('*').total_count described_class.elastic_search('*').total_count
expect(inspector).to have_named_query('doc:is_a:note') assert_named_queries("doc:is_a:note",
expect(inspector).to have_named_query('note:match:search_terms') "note:match:search_terms",
expect(inspector).to have_named_query('note:authorized') "note:authorized")
end
end end
it "indexes && searches diff notes" do it "indexes && searches diff notes" do
......
...@@ -198,13 +198,11 @@ RSpec.describe Project, :elastic do ...@@ -198,13 +198,11 @@ RSpec.describe Project, :elastic do
expect(described_class.elastic_search('tesla', options: { project_ids: project_ids }).total_count).to eq(2) expect(described_class.elastic_search('tesla', options: { project_ids: project_ids }).total_count).to eq(2)
end end
it "names elasticsearch queries" do |example| it "names elasticsearch queries" do
expect_named_queries(example) do |inspector|
described_class.elastic_search('*').total_count described_class.elastic_search('*').total_count
expect(inspector).to have_named_query('doc:is_a:project') assert_named_queries('doc:is_a:project',
expect(inspector).to have_named_query('project:match:search_terms') 'project:match:search_terms')
end
end end
it "returns json with all needed elements" do it "returns json with all needed elements" do
......
...@@ -31,19 +31,18 @@ RSpec.describe Repository, :elastic do ...@@ -31,19 +31,18 @@ RSpec.describe Repository, :elastic do
expect(project.repository.elastic_search(partial_ref + '*')[:commits][:total_count]).to eq(1) expect(project.repository.elastic_search(partial_ref + '*')[:commits][:total_count]).to eq(1)
end end
it "names elasticsearch queries" do |example| it "names elasticsearch queries" do
project = create :project, :repository project = create :project, :repository
expect_named_queries(example) do |inspector|
project.repository.elastic_search('*') project.repository.elastic_search('*')
expect(inspector).to have_named_query('doc:is_a:blob') assert_named_queries('doc:is_a:blob',
expect(inspector).to have_named_query('doc:is_a:wiki_blob') 'blob:match:search_terms')
expect(inspector).to have_named_query('blob:match:search_terms')
expect(inspector).to have_named_query('doc:is_a:commit') assert_named_queries('doc:is_a:wiki_blob',
expect(inspector).to have_named_query('commit:match:search_terms') 'blob:match:search_terms')
end
assert_named_queries('doc:is_a:commit',
'commit:match:search_terms')
end end
it 'can filter blobs' do it 'can filter blobs' do
......
...@@ -35,14 +35,12 @@ RSpec.describe Snippet, :elastic do ...@@ -35,14 +35,12 @@ RSpec.describe Snippet, :elastic do
expect(described_class.elastic_search('test snippet', options: options).total_count).to eq(1) expect(described_class.elastic_search('test snippet', options: options).total_count).to eq(1)
end end
it "names elasticsearch queries" do |example| it "names elasticsearch queries" do
expect_named_queries(example) do |inspector|
described_class.elastic_search('*').total_count described_class.elastic_search('*').total_count
expect(inspector).to have_named_query('doc:is_a:snippet') assert_named_queries('doc:is_a:snippet',
expect(inspector).to have_named_query('snippet:match:search_terms') 'snippet:match:search_terms',
expect(inspector).to have_named_query('snippet:authorized') 'snippet:authorized')
end
end end
it 'returns json with all needed elements' do it 'returns json with all needed elements' do
......
# frozen_string_literal: true # frozen_string_literal: true
RSpec.configure do |config| RSpec.configure do |config|
config.before(:each, :elastic) do |example| config.before(:each, :elastic) do
Elastic::ProcessBookkeepingService.clear_tracking! Elastic::ProcessBookkeepingService.clear_tracking!
Gitlab::Elastic::Helper.default.delete_index Gitlab::Elastic::Helper.default.delete_index
Gitlab::Elastic::Helper.default.create_empty_index(options: { settings: { number_of_replicas: 0 } }) Gitlab::Elastic::Helper.default.create_empty_index(options: { settings: { number_of_replicas: 0 } })
name_inspector = ElasticQueryNameInspector.new
es_config = Gitlab::CurrentSettings.elasticsearch_config
es_client = Gitlab::Elastic::Client.build(es_config) do |faraday|
faraday.use(ElasticQueryInspectorMiddleware, inspector: name_inspector)
end
example.metadata[:query_inspector] = name_inspector
# inject a client that records Elastic named queries
GemExtensions::Elasticsearch::Model::Client.cached_client = es_client
GemExtensions::Elasticsearch::Model::Client.cached_config = es_config
end end
config.after(:each, :elastic) do config.after(:each, :elastic) do
......
# frozen_string_literal: true
require 'hashie'
class ElasticQueryInspectorMiddleware < Faraday::Middleware
def initialize(app, options = {})
super(app)
@inspector = options.fetch(:inspector)
@env = nil
end
def call(env)
@env = env
return continue! unless is_search?
query = begin
payload = Gitlab::Json.parse(env[:request_body])
payload["query"]
rescue ::JSON::ParserError
nil
end
return continue! unless query.present?
query.extend(Hashie::Extensions::DeepFind)
@inspector.inspect(query)
continue!
end
def continue!
@app.call(@env)
end
def is_search?
@env.url.path.ends_with?("_search")
end
end
# frozen_string_literal: true # frozen_string_literal: true
class ElasticQueryNameInspector class ElasticQueryNameInspector
attr_reader :names
def initialize def initialize
@buckets = [] @names = Set.new
end end
def inspect(query) def inspect(query)
@buckets << query.deep_find_all("_name") query.extend(Hashie::Extensions::DeepFind)
end @names += query.deep_find_all("_name")
def reset!
@buckets = []
end
def names
@buckets.clone
end
def all_names
@buckets.flatten
end end
def has_named_query?(*names) def has_named_query?(*expected_names)
names.all? { |name| all_names.include?(name) } @names.superset?(expected_names.to_set)
end end
end end
# frozen_string_literal: true # frozen_string_literal: true
module ElasticsearchHelpers module ElasticsearchHelpers
def expect_named_queries(example, &block) def assert_named_queries(*expected_names)
query_inspector = example.metadata[:query_inspector] es_host = Gitlab::CurrentSettings.elasticsearch_url.first
query_inspector.reset! search_uri =
Addressable::Template.new("#{es_host}/{index}/doc/_search{?params*}")
yield query_inspector ensure_names_present = lambda do |req|
payload = Gitlab::Json.parse(req.body)
query = payload["query"]
expect(query_inspector.names).not_to be_empty return false unless query.present?
expect(query_inspector.names).not_to include(be_empty)
inspector = ElasticQueryNameInspector.new
inspector.inspect(query)
inspector.has_named_query?(*expected_names)
rescue ::JSON::ParserError
false
end
a_named_query = a_request(:get, search_uri).with(&ensure_names_present)
message = "Expected a query with the following names: #{expected_names.inspect}"
expect(a_named_query).to have_been_made.at_least_once, message
end end
def ensure_elasticsearch_index! def ensure_elasticsearch_index!
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment