diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-17 19:05:49 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-17 19:05:49 +0300 |
commit | 43a25d93ebdabea52f99b05e15b06250cd8f07d7 (patch) | |
tree | dceebdc68925362117480a5d672bcff122fb625b /spec/support/shared_examples/lib/gitlab | |
parent | 20c84b99005abd1c82101dfeff264ac50d2df211 (diff) |
Add latest changes from gitlab-org/gitlab@16-0-stable-eev16.0.0-rc42
Diffstat (limited to 'spec/support/shared_examples/lib/gitlab')
16 files changed, 531 insertions, 73 deletions
diff --git a/spec/support/shared_examples/lib/gitlab/cycle_analytics/deployment_metrics.rb b/spec/support/shared_examples/lib/gitlab/cycle_analytics/deployment_metrics.rb index d471a758f3e..c8d62205c1e 100644 --- a/spec/support/shared_examples/lib/gitlab/cycle_analytics/deployment_metrics.rb +++ b/spec/support/shared_examples/lib/gitlab/cycle_analytics/deployment_metrics.rb @@ -1,14 +1,7 @@ # frozen_string_literal: true RSpec.shared_examples 'deployment metrics examples' do - def create_deployment(args) - project = args[:project] - environment = project.environments.production.first || create(:environment, :production, project: project) - create(:deployment, :success, args.merge(environment: environment)) - - # this is needed for the DORA API so we have aggregated data - ::Dora::DailyMetrics::RefreshWorker.new.perform(environment.id, Time.current.to_date.to_s) if Gitlab.ee? - end + include CycleAnalyticsHelpers describe "#deploys" do subject { stage_summary.third } diff --git a/spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb index bce889b454d..5740adb3f0e 100644 --- a/spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb @@ -68,3 +68,64 @@ RSpec.shared_examples_for 'LEFT JOIN-able value stream analytics event' do end end end + +RSpec.shared_examples_for 'value stream analytics first assignment event methods' do + let_it_be(:model1) { create(model_factory) } # rubocop: disable Rails/SaveBang + let_it_be(:model2) { create(model_factory) } # rubocop: disable Rails/SaveBang + + let_it_be(:assignment_event1) do + create(event_factory, action: :add, created_at: 3.years.ago, model_factory => model1) + end + + let_it_be(:assignment_event2) do + create(event_factory, action: :add, created_at: 2.years.ago, model_factory => model1) + end + + let_it_be(:unassignment_event1) do + create(event_factory, action: :remove, created_at: 1.year.ago, model_factory => model1) + end + + let(:query) { model1.class.where(id: [model1.id, model2.id]) } + let(:event) { described_class.new({}) } + + describe '#apply_query_customization' do + subject(:records) { event.apply_query_customization(query).pluck(:id, *event.column_list).to_a } + + it 'looks up the first assignment event timestamp' do + expect(records).to match_array([[model1.id, be_within(1.second).of(assignment_event1.created_at)]]) + end + end + + describe '#apply_negated_query_customization' do + subject(:records) { event.apply_negated_query_customization(query).pluck(:id).to_a } + + it 'returns records where the event has not happened yet' do + expect(records).to eq([model2.id]) + end + end + + describe '#include_in' do + subject(:records) { event.include_in(query).pluck(:id, *event.column_list).to_a } + + it 'returns both records' do + expect(records).to match_array([ + [model1.id, be_within(1.second).of(assignment_event1.created_at)], + [model2.id, nil] + ]) + end + + context 'when invoked multiple times' do + subject(:records) do + scope = event.include_in(query) + event.include_in(scope).pluck(:id, *event.column_list).to_a + end + + it 'returns both records' do + expect(records).to match_array([ + [model1.id, be_within(1.second).of(assignment_event1.created_at)], + [model2.id, nil] + ]) + end + end + end +end diff --git a/spec/support/shared_examples/lib/gitlab/database/async_constraints_validation_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/database/async_constraints_validation_shared_examples.rb new file mode 100644 index 00000000000..b9d71183851 --- /dev/null +++ b/spec/support/shared_examples/lib/gitlab/database/async_constraints_validation_shared_examples.rb @@ -0,0 +1,131 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'async constraints validation' do + include ExclusiveLeaseHelpers + + let!(:lease) { stub_exclusive_lease(lease_key, :uuid, timeout: lease_timeout) } + let(:lease_key) { "gitlab/database/asyncddl/actions/#{Gitlab::Database::PRIMARY_DATABASE_NAME}" } + let(:lease_timeout) { described_class::TIMEOUT_PER_ACTION } + + let(:constraints_model) { Gitlab::Database::AsyncConstraints::PostgresAsyncConstraintValidation } + let(:table_name) { '_test_async_constraints' } + let(:constraint_name) { 'constraint_parent_id' } + + let(:validation) do + create(:postgres_async_constraint_validation, + table_name: table_name, + name: constraint_name, + constraint_type: constraint_type) + end + + let(:connection) { validation.connection } + + subject { described_class.new(validation) } + + it 'validates the constraint while controlling statement timeout' do + allow(connection).to receive(:execute).and_call_original + expect(connection).to receive(:execute) + .with("SET statement_timeout TO '43200s'").ordered.and_call_original + expect(connection).to receive(:execute) + .with(/ALTER TABLE "#{table_name}" VALIDATE CONSTRAINT "#{constraint_name}";/).ordered.and_call_original + expect(connection).to receive(:execute) + .with("RESET statement_timeout").ordered.and_call_original + + subject.perform + end + + it 'removes the constraint validation record from table' do + expect(validation).to receive(:destroy!).and_call_original + + expect { subject.perform }.to change { constraints_model.count }.by(-1) + end + + it 'skips logic if not able to acquire exclusive lease' do + expect(lease).to receive(:try_obtain).ordered.and_return(false) + expect(connection).not_to receive(:execute).with(/ALTER TABLE/) + expect(validation).not_to receive(:destroy!) + + expect { subject.perform }.not_to change { constraints_model.count } + end + + it 'logs messages around execution' do + allow(Gitlab::AppLogger).to receive(:info).and_call_original + + subject.perform + + expect(Gitlab::AppLogger) + .to have_received(:info) + .with(a_hash_including(message: 'Starting to validate constraint')) + + expect(Gitlab::AppLogger) + .to have_received(:info) + .with(a_hash_including(message: 'Finished validating constraint')) + end + + context 'when the constraint does not exist' do + before do + connection.create_table(table_name, force: true) + end + + it 'skips validation and removes the record' do + expect(connection).not_to receive(:execute).with(/ALTER TABLE/) + + expect { subject.perform }.to change { constraints_model.count }.by(-1) + end + + it 'logs an appropriate message' do + expected_message = /Skipping #{constraint_name} validation since it does not exist/ + + allow(Gitlab::AppLogger).to receive(:info).and_call_original + + subject.perform + + expect(Gitlab::AppLogger) + .to have_received(:info) + .with(a_hash_including(message: expected_message)) + end + end + + context 'with error handling' do + before do + allow(connection).to receive(:execute).and_call_original + + allow(connection).to receive(:execute) + .with(/ALTER TABLE "#{table_name}" VALIDATE CONSTRAINT "#{constraint_name}";/) + .and_raise(ActiveRecord::StatementInvalid) + end + + context 'on production' do + before do + allow(Gitlab::ErrorTracking).to receive(:should_raise_for_dev?).and_return(false) + end + + it 'increases execution attempts' do + expect { subject.perform }.to change { validation.attempts }.by(1) + + expect(validation.last_error).to be_present + expect(validation).not_to be_destroyed + end + + it 'logs an error message including the constraint_name' do + expect(Gitlab::AppLogger) + .to receive(:error) + .with(a_hash_including(:message, :constraint_name)) + .and_call_original + + subject.perform + end + end + + context 'on development' do + it 'also raises errors' do + expect { subject.perform } + .to raise_error(ActiveRecord::StatementInvalid) + .and change { validation.attempts }.by(1) + + expect(validation.last_error).to be_present + expect(validation).not_to be_destroyed + end + end + end +end diff --git a/spec/support/shared_examples/lib/gitlab/database/index_validators_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/database/index_validators_shared_examples.rb new file mode 100644 index 00000000000..6f0cede7130 --- /dev/null +++ b/spec/support/shared_examples/lib/gitlab/database/index_validators_shared_examples.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.shared_examples "index validators" do |validator, expected_result| + let(:structure_file_path) { Rails.root.join('spec/fixtures/structure.sql') } + let(:database_indexes) do + [ + ['wrong_index', 'CREATE UNIQUE INDEX wrong_index ON public.table_name (column_name)'], + ['extra_index', 'CREATE INDEX extra_index ON public.table_name (column_name)'], + ['index', 'CREATE UNIQUE INDEX "index" ON public.achievements USING btree (namespace_id, lower(name))'] + ] + end + + let(:inconsistency_type) { validator.name.demodulize.underscore } + + let(:database_name) { 'main' } + + let(:database_model) { Gitlab::Database.database_base_models[database_name] } + + let(:connection) { database_model.connection } + + let(:schema) { connection.current_schema } + + let(:database) { Gitlab::Database::SchemaValidation::Database.new(connection) } + let(:structure_file) { Gitlab::Database::SchemaValidation::StructureSql.new(structure_file_path, schema) } + + subject(:result) { validator.new(structure_file, database).execute } + + before do + allow(connection).to receive(:select_rows).and_return(database_indexes) + end + + it 'returns index inconsistencies' do + expect(result.map(&:object_name)).to match_array(expected_result) + expect(result.map(&:type)).to all(eql inconsistency_type) + end +end diff --git a/spec/support/shared_examples/lib/gitlab/database/schema_objects_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/database/schema_objects_shared_examples.rb new file mode 100644 index 00000000000..ec7a881f7ce --- /dev/null +++ b/spec/support/shared_examples/lib/gitlab/database/schema_objects_shared_examples.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.shared_examples "schema objects assertions for" do |stmt_name| + let(:stmt) { PgQuery.parse(statement).tree.stmts.first.stmt } + let(:schema_object) { described_class.new(stmt.public_send(stmt_name)) } + + describe '#name' do + it 'returns schema object name' do + expect(schema_object.name).to eq(name) + end + end + + describe '#statement' do + it 'returns schema object statement' do + expect(schema_object.statement).to eq(statement) + end + end + + describe '#table_name' do + it 'returns schema object table_name' do + expect(schema_object.table_name).to eq(table_name) + end + end +end diff --git a/spec/support/shared_examples/lib/gitlab/database/table_validators_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/database/table_validators_shared_examples.rb new file mode 100644 index 00000000000..96e58294675 --- /dev/null +++ b/spec/support/shared_examples/lib/gitlab/database/table_validators_shared_examples.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.shared_examples "table validators" do |validator, expected_result| + subject(:result) { validator.new(structure_file, database).execute } + + let(:structure_file_path) { Rails.root.join('spec/fixtures/structure.sql') } + let(:inconsistency_type) { validator.name.demodulize.underscore } + let(:database_model) { Gitlab::Database.database_base_models['main'] } + let(:connection) { database_model.connection } + let(:schema) { connection.current_schema } + let(:database) { Gitlab::Database::SchemaValidation::Database.new(connection) } + let(:structure_file) { Gitlab::Database::SchemaValidation::StructureSql.new(structure_file_path, schema) } + let(:database_tables) do + [ + { + 'table_name' => 'wrong_table', + 'column_name' => 'id', + 'not_null' => true, + 'data_type' => 'integer', + 'column_default' => "nextval('audit_events_id_seq'::regclass)" + }, + { + 'table_name' => 'wrong_table', + 'column_name' => 'description', + 'not_null' => true, + 'data_type' => 'character varying', + 'column_default' => nil + }, + { + 'table_name' => 'extra_table', + 'column_name' => 'id', + 'not_null' => true, + 'data_type' => 'integer', + 'column_default' => "nextval('audit_events_id_seq'::regclass)" + }, + { + 'table_name' => 'extra_table', + 'column_name' => 'email', + 'not_null' => true, + 'data_type' => 'character varying', + 'column_default' => nil + }, + { + 'table_name' => 'extra_table_columns', + 'column_name' => 'id', + 'not_null' => true, + 'data_type' => 'bigint', + 'column_default' => "nextval('audit_events_id_seq'::regclass)" + }, + { + 'table_name' => 'extra_table_columns', + 'column_name' => 'name', + 'not_null' => true, + 'data_type' => 'character varying(255)', + 'column_default' => nil + }, + { + 'table_name' => 'extra_table_columns', + 'column_name' => 'extra_column', + 'not_null' => true, + 'data_type' => 'character varying(255)', + 'column_default' => nil + }, + { + 'table_name' => 'missing_table_columns', + 'column_name' => 'id', + 'not_null' => true, + 'data_type' => 'bigint', + 'column_default' => 'NOT NULL' + } + ] + end + + before do + allow(connection).to receive(:exec_query).and_return(database_tables) + end + + it 'returns table inconsistencies' do + expect(result.map(&:object_name)).to match_array(expected_result) + expect(result.map(&:type)).to all(eql inconsistency_type) + end +end diff --git a/spec/support/shared_examples/lib/gitlab/database/trigger_validators_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/database/trigger_validators_shared_examples.rb new file mode 100644 index 00000000000..13a112275c2 --- /dev/null +++ b/spec/support/shared_examples/lib/gitlab/database/trigger_validators_shared_examples.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.shared_examples 'trigger validators' do |validator, expected_result| + subject(:result) { validator.new(structure_file, database).execute } + + let(:structure_file_path) { Rails.root.join('spec/fixtures/structure.sql') } + let(:structure_file) { Gitlab::Database::SchemaValidation::StructureSql.new(structure_file_path, schema) } + let(:inconsistency_type) { validator.name.demodulize.underscore } + let(:database_name) { 'main' } + let(:schema) { 'public' } + let(:database_model) { Gitlab::Database.database_base_models[database_name] } + let(:connection) { database_model.connection } + let(:database) { Gitlab::Database::SchemaValidation::Database.new(connection) } + + let(:database_triggers) do + [ + ['trigger', 'CREATE TRIGGER trigger AFTER INSERT ON public.t1 FOR EACH ROW EXECUTE FUNCTION t1()'], + ['wrong_trigger', 'CREATE TRIGGER wrong_trigger BEFORE UPDATE ON public.t2 FOR EACH ROW EXECUTE FUNCTION t2()'], + ['extra_trigger', 'CREATE TRIGGER extra_trigger BEFORE INSERT ON public.t4 FOR EACH ROW EXECUTE FUNCTION t4()'] + ] + end + + before do + allow(connection).to receive(:select_rows).and_return(database_triggers) + end + + it 'returns trigger inconsistencies' do + expect(result.map(&:object_name)).to match_array(expected_result) + expect(result.map(&:type)).to all(eql inconsistency_type) + end +end diff --git a/spec/support/shared_examples/lib/gitlab/gitaly_client_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/gitaly_client_shared_examples.rb index f26b9a4a7bd..d388abb16c6 100644 --- a/spec/support/shared_examples/lib/gitlab/gitaly_client_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/gitaly_client_shared_examples.rb @@ -1,10 +1,12 @@ # frozen_string_literal: true def raw_repo_without_container(repository) - Gitlab::Git::Repository.new(repository.shard, - "#{repository.disk_path}.git", - repository.repo_type.identifier_for_container(repository.container), - repository.container.full_path) + Gitlab::Git::Repository.new( + repository.shard, + "#{repository.disk_path}.git", + repository.repo_type.identifier_for_container(repository.container), + repository.container.full_path + ) end RSpec.shared_examples 'Gitaly feature flag actors are inferred from repository' do diff --git a/spec/support/shared_examples/lib/gitlab/json_logger_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/json_logger_shared_examples.rb new file mode 100644 index 00000000000..8a5e8397c3d --- /dev/null +++ b/spec/support/shared_examples/lib/gitlab/json_logger_shared_examples.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'a json logger' do |extra_params| + let(:now) { Time.now } + let(:correlation_id) { Labkit::Correlation::CorrelationId.current_id } + + it 'formats strings' do + output = subject.format_message('INFO', now, 'test', 'Hello world') + data = Gitlab::Json.parse(output) + + expect(data['severity']).to eq('INFO') + expect(data['time']).to eq(now.utc.iso8601(3)) + expect(data['message']).to eq('Hello world') + expect(data['correlation_id']).to eq(correlation_id) + expect(data).to include(extra_params) + end + + it 'formats hashes' do + output = subject.format_message('INFO', now, 'test', { hello: 1 }) + data = Gitlab::Json.parse(output) + + expect(data['severity']).to eq('INFO') + expect(data['time']).to eq(now.utc.iso8601(3)) + expect(data['hello']).to eq(1) + expect(data['message']).to be_nil + expect(data['correlation_id']).to eq(correlation_id) + expect(data).to include(extra_params) + end +end diff --git a/spec/support/shared_examples/lib/gitlab/local_and_remote_storage_migration_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/local_and_remote_storage_migration_shared_examples.rb index 27ca27a9035..4b0e3234750 100644 --- a/spec/support/shared_examples/lib/gitlab/local_and_remote_storage_migration_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/local_and_remote_storage_migration_shared_examples.rb @@ -8,9 +8,9 @@ RSpec.shared_examples 'local and remote storage migration' do where(:start_store, :end_store, :method) do ObjectStorage::Store::LOCAL | ObjectStorage::Store::REMOTE | :migrate_to_remote_storage - ObjectStorage::Store::REMOTE | ObjectStorage::Store::REMOTE | :migrate_to_remote_storage # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands + ObjectStorage::Store::REMOTE | ObjectStorage::Store::REMOTE | :migrate_to_remote_storage ObjectStorage::Store::REMOTE | ObjectStorage::Store::LOCAL | :migrate_to_local_storage - ObjectStorage::Store::LOCAL | ObjectStorage::Store::LOCAL | :migrate_to_local_storage # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands + ObjectStorage::Store::LOCAL | ObjectStorage::Store::LOCAL | :migrate_to_local_storage end with_them do diff --git a/spec/support/shared_examples/lib/gitlab/project_search_results_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/project_search_results_shared_examples.rb index f83fecee4ea..0016f1e670d 100644 --- a/spec/support/shared_examples/lib/gitlab/project_search_results_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/project_search_results_shared_examples.rb @@ -38,8 +38,7 @@ RSpec.shared_examples 'access restricted confidential issues' do let(:user) { author } it 'lists project confidential issues' do - expect(objects).to contain_exactly(issue, - security_issue_1) + expect(objects).to contain_exactly(issue, security_issue_1) expect(results.limited_issues_count).to eq 2 end end @@ -48,8 +47,7 @@ RSpec.shared_examples 'access restricted confidential issues' do let(:user) { assignee } it 'lists project confidential issues for assignee' do - expect(objects).to contain_exactly(issue, - security_issue_2) + expect(objects).to contain_exactly(issue, security_issue_2) expect(results.limited_issues_count).to eq 2 end end @@ -60,9 +58,7 @@ RSpec.shared_examples 'access restricted confidential issues' do end it 'lists project confidential issues' do - expect(objects).to contain_exactly(issue, - security_issue_1, - security_issue_2) + expect(objects).to contain_exactly(issue, security_issue_1, security_issue_2) expect(results.limited_issues_count).to eq 3 end end @@ -72,9 +68,7 @@ RSpec.shared_examples 'access restricted confidential issues' do context 'when admin mode is enabled', :enable_admin_mode do it 'lists all project issues' do - expect(objects).to contain_exactly(issue, - security_issue_1, - security_issue_2) + expect(objects).to contain_exactly(issue, security_issue_1, security_issue_2) end end diff --git a/spec/support/shared_examples/lib/gitlab/repo_type_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/repo_type_shared_examples.rb index 025f0d5c7ea..c2898513424 100644 --- a/spec/support/shared_examples/lib/gitlab/repo_type_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/repo_type_shared_examples.rb @@ -15,7 +15,7 @@ RSpec.shared_examples 'a repo type' do describe '#repository_for' do it 'finds the repository for the repo type' do - expect(described_class.repository_for(expected_container)).to eq(expected_repository) + expect(described_class.repository_for(expected_repository_resolver)).to eq(expected_repository) end it 'returns nil when container is nil' do diff --git a/spec/support/shared_examples/lib/gitlab/search_language_filter_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/search_language_filter_shared_examples.rb index a3e4379f4d3..18545698c27 100644 --- a/spec/support/shared_examples/lib/gitlab/search_language_filter_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/search_language_filter_shared_examples.rb @@ -26,29 +26,4 @@ RSpec.shared_examples 'search results filtered by language' do expect(blob_results.size).to eq(5) expect(paths).to match_array(expected_paths) end - - context 'when the search_blobs_language_aggregation feature flag is disabled' do - before do - stub_feature_flags(search_blobs_language_aggregation: false) - end - - it 'does not filter by language', :sidekiq_inline, :aggregate_failures do - expected_paths = %w[ - CHANGELOG - CONTRIBUTING.md - bar/branch-test.txt - custom-highlighting/test.gitlab-custom - files/ruby/popen.rb - files/ruby/regex.rb - files/ruby/version_info.rb - files/whitespace - encoding/test.txt - files/markdown/ruby-style-guide.md - ] - - paths = blob_results.map { |blob| blob.binary_path } - expect(blob_results.size).to eq(10) - expect(paths).to match_array(expected_paths) - end - end end diff --git a/spec/support/shared_examples/lib/gitlab/sidekiq_middleware/strategy_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/sidekiq_middleware/strategy_shared_examples.rb index ff03051ed37..74570a4da5c 100644 --- a/spec/support/shared_examples/lib/gitlab/sidekiq_middleware/strategy_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/sidekiq_middleware/strategy_shared_examples.rb @@ -5,7 +5,7 @@ RSpec.shared_examples 'deduplicating jobs when scheduling' do |strategy_name| instance_double(Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, duplicate_key_ttl: Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob::DEFAULT_DUPLICATE_KEY_TTL) end - let(:expected_message) { "dropped #{strategy_name.to_s.humanize.downcase}" } + let(:humanized_strategy_name) { strategy_name.to_s.humanize.downcase } subject(:strategy) { Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies.for(strategy_name).new(fake_duplicate_job) } @@ -155,7 +155,7 @@ RSpec.shared_examples 'deduplicating jobs when scheduling' do |strategy_name| fake_logger = instance_double(Gitlab::SidekiqLogging::DeduplicationLogger) expect(Gitlab::SidekiqLogging::DeduplicationLogger).to receive(:instance).and_return(fake_logger) - expect(fake_logger).to receive(:deduplicated_log).with(a_hash_including({ 'jid' => 'new jid' }), expected_message, {}) + expect(fake_logger).to receive(:deduplicated_log).with(a_hash_including({ 'jid' => 'new jid' }), humanized_strategy_name, {}) strategy.schedule({ 'jid' => 'new jid' }) {} end @@ -165,7 +165,7 @@ RSpec.shared_examples 'deduplicating jobs when scheduling' do |strategy_name| expect(Gitlab::SidekiqLogging::DeduplicationLogger).to receive(:instance).and_return(fake_logger) allow(fake_duplicate_job).to receive(:options).and_return({ foo: :bar }) - expect(fake_logger).to receive(:deduplicated_log).with(a_hash_including({ 'jid' => 'new jid' }), expected_message, { foo: :bar }) + expect(fake_logger).to receive(:deduplicated_log).with(a_hash_including({ 'jid' => 'new jid' }), humanized_strategy_name, { foo: :bar }) strategy.schedule({ 'jid' => 'new jid' }) {} end diff --git a/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb index d4802a19202..169fceced7a 100644 --- a/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/usage_data_counters/issuable_activity_shared_examples.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -RSpec.shared_examples 'a daily tracked issuable snowplow and service ping events for given event params' do +RSpec.shared_examples 'tracked issuable snowplow and service ping events for given event params' do before do stub_application_setting(usage_ping_enabled: true) end - def count_unique(date_from: 1.minute.ago, date_to: 1.minute.from_now) + def count_unique(date_from: Date.today.beginning_of_week, date_to: 1.week.from_now) Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: action, start_date: date_from, end_date: date_to) end @@ -27,35 +27,23 @@ RSpec.shared_examples 'a daily tracked issuable snowplow and service ping events expect_snowplow_event(**{ category: category, action: event_action, user: user1 }.merge(event_params)) end - - context 'with route_hll_to_snowplow_phase2 disabled' do - before do - stub_feature_flags(route_hll_to_snowplow_phase2: false) - end - - it 'does not emit snowplow event' do - track_action({ author: user1 }.merge(track_params)) - - expect_no_snowplow_event - end - end end -RSpec.shared_examples 'daily tracked issuable snowplow and service ping events with project' do - it_behaves_like 'a daily tracked issuable snowplow and service ping events for given event params' do +RSpec.shared_examples 'tracked issuable snowplow and service ping events with project' do + it_behaves_like 'tracked issuable snowplow and service ping events for given event params' do let(:context) do Gitlab::Tracking::ServicePingContext .new(data_source: :redis_hll, event: event_property) .to_h end - let(:track_params) { { project: project } } - let(:event_params) { track_params.merge(label: event_label, property: event_property, namespace: project.namespace, context: [context]) } + let(:track_params) { original_params || { project: project } } + let(:event_params) { { project: project }.merge(label: event_label, property: event_property, namespace: project.namespace, context: [context]) } end end -RSpec.shared_examples 'a daily tracked issuable snowplow and service ping events with namespace' do - it_behaves_like 'a daily tracked issuable snowplow and service ping events for given event params' do +RSpec.shared_examples 'tracked issuable snowplow and service ping events with namespace' do + it_behaves_like 'tracked issuable snowplow and service ping events for given event params' do let(:context) do Gitlab::Tracking::ServicePingContext .new(data_source: :redis_hll, event: event_property) diff --git a/spec/support/shared_examples/lib/gitlab/utils/username_and_email_generator_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/utils/username_and_email_generator_shared_examples.rb new file mode 100644 index 00000000000..a42d1450e4d --- /dev/null +++ b/spec/support/shared_examples/lib/gitlab/utils/username_and_email_generator_shared_examples.rb @@ -0,0 +1,104 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'username and email pair is generated by Gitlab::Utils::UsernameAndEmailGenerator' do + let(:randomhex) { 'randomhex' } + + it 'check email domain' do + expect(subject.email).to end_with("@#{email_domain}") + end + + it 'contains SecureRandom part' do + allow(SecureRandom).to receive(:hex).at_least(:once).and_return(randomhex) + + expect(subject.username).to include("_#{randomhex}") + expect(subject.email).to include("_#{randomhex}@") + end + + it 'email name is the same as username' do + expect(subject.email).to include("#{subject.username}@") + end + + context 'when conflicts' do + let(:reserved_username) { "#{username_prefix}_#{randomhex}" } + let(:reserved_email) { "#{reserved_username}@#{email_domain}" } + + shared_examples 'uniquifies username and email' do + it 'uniquifies username and email' do + expect(subject.username).to eq("#{reserved_username}1") + expect(subject.email).to include("#{subject.username}@") + end + end + + context 'when username is reserved' do + context 'when username is reserved by user' do + before do + create(:user, username: reserved_username) + allow(SecureRandom).to receive(:hex).at_least(:once).and_return(randomhex) + end + + include_examples 'uniquifies username and email' + end + + context 'when it conflicts with top-level group namespace' do + before do + create(:group, path: reserved_username) + allow(SecureRandom).to receive(:hex).at_least(:once).and_return(randomhex) + end + + include_examples 'uniquifies username and email' + end + + context 'when it conflicts with top-level group namespace that includes upcased characters' do + before do + create(:group, path: reserved_username.upcase) + allow(SecureRandom).to receive(:hex).at_least(:once).and_return(randomhex) + end + + include_examples 'uniquifies username and email' + end + end + + context 'when email is reserved' do + context 'when it conflicts with confirmed primary email' do + before do + create(:user, email: reserved_email) + allow(SecureRandom).to receive(:hex).at_least(:once).and_return(randomhex) + end + + include_examples 'uniquifies username and email' + end + + context 'when it conflicts with unconfirmed primary email' do + before do + create(:user, :unconfirmed, email: reserved_email) + allow(SecureRandom).to receive(:hex).at_least(:once).and_return(randomhex) + end + + include_examples 'uniquifies username and email' + end + + context 'when it conflicts with confirmed secondary email' do + before do + create(:email, :confirmed, email: reserved_email) + allow(SecureRandom).to receive(:hex).at_least(:once).and_return(randomhex) + end + + include_examples 'uniquifies username and email' + end + end + + context 'when email and username is reserved' do + before do + create(:user, email: reserved_email) + create(:user, username: "#{reserved_username}1") + allow(SecureRandom).to receive(:hex).at_least(:once).and_return(randomhex) + end + + it 'uniquifies username and email' do + expect(subject.username).to eq("#{reserved_username}2") + + expect(subject.email).to include("#{subject.username}@") + end + end + end +end |