diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-03 18:09:46 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-03 18:09:46 +0300 |
commit | bbd9e2c915c46920ceb51376db19599cbf9ba836 (patch) | |
tree | 897c9abbe0afa31f077dd7ca7c76ba755b75237a /spec | |
parent | f145ef4be75f3711c52a680b86d96568e9acf385 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
18 files changed, 256 insertions, 213 deletions
diff --git a/spec/graphql/types/terraform/state_version_type_spec.rb b/spec/graphql/types/terraform/state_version_type_spec.rb index 1c1e95039dc..18f869e4f1f 100644 --- a/spec/graphql/types/terraform/state_version_type_spec.rb +++ b/spec/graphql/types/terraform/state_version_type_spec.rb @@ -7,13 +7,15 @@ RSpec.describe GitlabSchema.types['TerraformStateVersion'] do it { expect(described_class).to require_graphql_authorizations(:read_terraform_state) } describe 'fields' do - let(:fields) { %i[id created_by_user job created_at updated_at] } + let(:fields) { %i[id created_by_user job download_path serial created_at updated_at] } it { expect(described_class).to have_graphql_fields(fields) } it { expect(described_class.fields['id'].type).to be_non_null } it { expect(described_class.fields['createdByUser'].type).not_to be_non_null } it { expect(described_class.fields['job'].type).not_to be_non_null } + it { expect(described_class.fields['downloadPath'].type).not_to be_non_null } + it { expect(described_class.fields['serial'].type).not_to be_non_null } it { expect(described_class.fields['createdAt'].type).to be_non_null } it { expect(described_class.fields['updatedAt'].type).to be_non_null } end diff --git a/spec/initializers/lograge_spec.rb b/spec/initializers/lograge_spec.rb index de722764bf4..d5f9ef569c7 100644 --- a/spec/initializers/lograge_spec.rb +++ b/spec/initializers/lograge_spec.rb @@ -153,32 +153,22 @@ RSpec.describe 'lograge', type: :request do end end - context 'with transaction' do - let(:transaction) { Gitlab::Metrics::WebTransaction.new({}) } - - before do - allow(Gitlab::Metrics::Transaction).to receive(:current).and_return(transaction) - end - + context 'with db payload' do context 'when RequestStore is enabled', :request_store do - context 'with db payload' do - it 'includes db counters', :request_store do - ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);') - subscriber.process_action(event) + it 'includes db counters' do + ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);') + subscriber.process_action(event) - expect(log_data).to include("db_count" => 1, "db_write_count" => 0, "db_cached_count" => 0) - end + expect(log_data).to include("db_count" => a_value >= 1, "db_write_count" => 0, "db_cached_count" => 0) end end context 'when RequestStore is disabled' do - context 'with db payload' do - it 'does not include db counters' do - ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);') - subscriber.process_action(event) + it 'does not include db counters' do + ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);') + subscriber.process_action(event) - expect(log_data).not_to include("db_count" => 1, "db_write_count" => 0, "db_cached_count" => 0) - end + expect(log_data).not_to include("db_count", "db_write_count", "db_cached_count") end end end diff --git a/spec/lib/bulk_imports/common/transformers/prohibited_attributes_transformer_spec.rb b/spec/lib/bulk_imports/common/transformers/prohibited_attributes_transformer_spec.rb new file mode 100644 index 00000000000..03d138b227c --- /dev/null +++ b/spec/lib/bulk_imports/common/transformers/prohibited_attributes_transformer_spec.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe BulkImports::Common::Transformers::ProhibitedAttributesTransformer do + describe '#transform' do + let_it_be(:hash) do + { + 'id' => 101, + 'service_id' => 99, + 'moved_to_id' => 99, + 'namespace_id' => 99, + 'ci_id' => 99, + 'random_project_id' => 99, + 'random_id' => 99, + 'milestone_id' => 99, + 'project_id' => 99, + 'user_id' => 99, + 'random_id_in_the_middle' => 99, + 'notid' => 99, + 'import_source' => 'test', + 'import_type' => 'test', + 'non_existent_attr' => 'test', + 'some_html' => '<p>dodgy html</p>', + 'legit_html' => '<p>legit html</p>', + '_html' => '<p>perfectly ordinary html</p>', + 'cached_markdown_version' => 12345, + 'custom_attributes' => 'test', + 'some_attributes_metadata' => 'test', + 'group_id' => 99, + 'commit_id' => 99, + 'issue_ids' => [1, 2, 3], + 'merge_request_ids' => [1, 2, 3], + 'note_ids' => [1, 2, 3], + 'remote_attachment_url' => 'http://something.dodgy', + 'remote_attachment_request_header' => 'bad value', + 'remote_attachment_urls' => %w(http://something.dodgy http://something.okay), + 'attributes' => { + 'issue_ids' => [1, 2, 3], + 'merge_request_ids' => [1, 2, 3], + 'note_ids' => [1, 2, 3] + }, + 'variables_attributes' => { + 'id' => 1 + }, + 'attr_with_nested_attrs' => { + 'nested_id' => 1, + 'nested_attr' => 2 + } + } + end + + let(:expected_hash) do + { + 'random_id_in_the_middle' => 99, + 'notid' => 99, + 'import_source' => 'test', + 'import_type' => 'test', + 'non_existent_attr' => 'test', + 'attr_with_nested_attrs' => { + 'nested_attr' => 2 + } + } + end + + it 'removes prohibited attributes' do + transformed_hash = subject.transform(nil, hash) + + expect(transformed_hash).to eq(expected_hash) + end + end +end diff --git a/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb index a132e964141..c9b481388c3 100644 --- a/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb +++ b/spec/lib/bulk_imports/groups/pipelines/group_pipeline_spec.rb @@ -91,6 +91,7 @@ RSpec.describe BulkImports::Groups::Pipelines::GroupPipeline do .to contain_exactly( { klass: BulkImports::Common::Transformers::HashKeyDigger, options: { key_path: %w[data group] } }, { klass: BulkImports::Common::Transformers::UnderscorifyKeysTransformer, options: nil }, + { klass: BulkImports::Common::Transformers::ProhibitedAttributesTransformer, options: nil }, { klass: BulkImports::Groups::Transformers::GroupAttributesTransformer, options: nil } ) end diff --git a/spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb index ace8eb4d9f6..788a6e98c45 100644 --- a/spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb +++ b/spec/lib/bulk_imports/groups/pipelines/subgroup_entities_pipeline_spec.rb @@ -66,8 +66,8 @@ RSpec.describe BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline do it 'has transformers' do expect(described_class.transformers).to contain_exactly( - klass: BulkImports::Groups::Transformers::SubgroupToEntityTransformer, - options: nil + { klass: BulkImports::Common::Transformers::ProhibitedAttributesTransformer, options: nil }, + { klass: BulkImports::Groups::Transformers::SubgroupToEntityTransformer, options: nil } ) end diff --git a/spec/lib/gitlab/checks/snippet_check_spec.rb b/spec/lib/gitlab/checks/snippet_check_spec.rb index 5e1aedcaff8..89417aaca4d 100644 --- a/spec/lib/gitlab/checks/snippet_check_spec.rb +++ b/spec/lib/gitlab/checks/snippet_check_spec.rb @@ -13,7 +13,7 @@ RSpec.describe Gitlab::Checks::SnippetCheck do let(:creation) { false } let(:deletion) { false } - subject { Gitlab::Checks::SnippetCheck.new(changes, default_branch: default_branch, logger: logger) } + subject { Gitlab::Checks::SnippetCheck.new(changes, default_branch: default_branch, root_ref: snippet.repository.root_ref, logger: logger) } describe '#validate!' do it 'does not raise any error' do @@ -45,10 +45,18 @@ RSpec.describe Gitlab::Checks::SnippetCheck do let(:branch_name) { 'feature' } end - context "when branch is 'master'" do - let(:ref) { 'refs/heads/master' } + context 'when branch is the same as the default branch' do + let(:ref) { "refs/heads/#{default_branch}" } - it "allows the operation" do + it 'allows the operation' do + expect { subject.validate! }.not_to raise_error + end + end + + context 'when snippet has an empty repo' do + let_it_be(:snippet) { create(:personal_snippet, :empty_repo) } + + it 'allows the operation' do expect { subject.validate! }.not_to raise_error end end diff --git a/spec/lib/gitlab/database/postgres_hll_batch_distinct_counter_spec.rb b/spec/lib/gitlab/database/postgres_hll_batch_distinct_counter_spec.rb index 5da86538297..a3efe1d20b2 100644 --- a/spec/lib/gitlab/database/postgres_hll_batch_distinct_counter_spec.rb +++ b/spec/lib/gitlab/database/postgres_hll_batch_distinct_counter_spec.rb @@ -3,9 +3,9 @@ require 'spec_helper' RSpec.describe Gitlab::Database::PostgresHllBatchDistinctCounter do - let_it_be(:error_rate) { 4.9 } # HyperLogLog is a probabilistic algorithm, which provides estimated data, with given error margin + let_it_be(:error_rate) { described_class::ERROR_RATE } # HyperLogLog is a probabilistic algorithm, which provides estimated data, with given error margin let_it_be(:fallback) { ::Gitlab::Database::BatchCounter::FALLBACK } - let_it_be(:small_batch_size) { calculate_batch_size(::Gitlab::Database::BatchCounter::MIN_REQUIRED_BATCH_SIZE) } + let_it_be(:small_batch_size) { calculate_batch_size(described_class::MIN_REQUIRED_BATCH_SIZE) } let(:model) { Issue } let(:column) { :author_id } @@ -118,8 +118,8 @@ RSpec.describe Gitlab::Database::PostgresHllBatchDistinctCounter do expect(described_class.new(model, column).estimate_distinct_count(start: 1, finish: 0)).to eq(fallback) end - it 'returns fallback if loops more than allowed' do - large_finish = Gitlab::Database::PostgresHllBatchDistinctCounter::MAX_ALLOWED_LOOPS * default_batch_size + 1 + it 'returns fallback if data volume exceeds upper limit' do + large_finish = Gitlab::Database::PostgresHllBatchDistinctCounter::MAX_DATA_VOLUME + 1 expect(described_class.new(model, column).estimate_distinct_count(start: 1, finish: large_finish)).to eq(fallback) end diff --git a/spec/lib/gitlab/instrumentation_helper_spec.rb b/spec/lib/gitlab/instrumentation_helper_spec.rb index 88f2def34d9..c00b0fdf043 100644 --- a/spec/lib/gitlab/instrumentation_helper_spec.rb +++ b/spec/lib/gitlab/instrumentation_helper_spec.rb @@ -34,7 +34,10 @@ RSpec.describe Gitlab::InstrumentationHelper do :redis_shared_state_calls, :redis_shared_state_duration_s, :redis_shared_state_read_bytes, - :redis_shared_state_write_bytes + :redis_shared_state_write_bytes, + :db_count, + :db_write_count, + :db_cached_count ] expect(described_class.keys).to eq(expected_keys) @@ -46,10 +49,10 @@ RSpec.describe Gitlab::InstrumentationHelper do subject { described_class.add_instrumentation_data(payload) } - it 'adds nothing' do + it 'adds only DB counts by default' do subject - expect(payload).to eq({}) + expect(payload).to eq(db_count: 0, db_cached_count: 0, db_write_count: 0) end context 'when Gitaly calls are made' do diff --git a/spec/lib/gitlab/metrics/background_transaction_spec.rb b/spec/lib/gitlab/metrics/background_transaction_spec.rb deleted file mode 100644 index b2a53fe1626..00000000000 --- a/spec/lib/gitlab/metrics/background_transaction_spec.rb +++ /dev/null @@ -1,56 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::Metrics::BackgroundTransaction do - let(:test_worker_class) { double(:class, name: 'TestWorker') } - let(:prometheus_metric) { instance_double(Prometheus::Client::Metric, base_labels: {}) } - - before do - allow(described_class).to receive(:prometheus_metric).and_return(prometheus_metric) - end - - subject { described_class.new(test_worker_class) } - - RSpec.shared_examples 'metric with worker labels' do |metric_method| - it 'measures with correct labels and value' do - value = 1 - expect(prometheus_metric).to receive(metric_method).with({ controller: 'TestWorker', action: 'perform', feature_category: '' }, value) - - subject.send(metric_method, :bau, value) - end - end - - describe '#label' do - it 'returns labels based on class name' do - expect(subject.labels).to eq(controller: 'TestWorker', action: 'perform', feature_category: '') - end - - it 'contains only the labels defined for metrics' do - expect(subject.labels.keys).to contain_exactly(*described_class.superclass::BASE_LABEL_KEYS) - end - - it 'includes the feature category if there is one' do - expect(test_worker_class).to receive(:get_feature_category).and_return('source_code_management') - expect(subject.labels).to include(feature_category: 'source_code_management') - end - end - - describe '#increment' do - let(:prometheus_metric) { instance_double(Prometheus::Client::Counter, :increment, base_labels: {}) } - - it_behaves_like 'metric with worker labels', :increment - end - - describe '#set' do - let(:prometheus_metric) { instance_double(Prometheus::Client::Gauge, :set, base_labels: {}) } - - it_behaves_like 'metric with worker labels', :set - end - - describe '#observe' do - let(:prometheus_metric) { instance_double(Prometheus::Client::Histogram, :observe, base_labels: {}) } - - it_behaves_like 'metric with worker labels', :observe - end -end diff --git a/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb b/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb deleted file mode 100644 index 047d1e5d205..00000000000 --- a/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb +++ /dev/null @@ -1,66 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::Metrics::SidekiqMiddleware do - let(:middleware) { described_class.new } - let(:message) { { 'args' => ['test'], 'enqueued_at' => Time.new(2016, 6, 23, 6, 59).to_f } } - - describe '#call' do - it 'tracks the transaction' do - worker = double(:worker, class: double(:class, name: 'TestWorker')) - - expect_next_instance_of(Gitlab::Metrics::BackgroundTransaction) do |transaction| - expect(transaction).to receive(:set).with(:gitlab_transaction_sidekiq_queue_duration_total, instance_of(Float)) - expect(transaction).to receive(:increment).with(:gitlab_transaction_db_count_total, 1) - end - - middleware.call(worker, message, :test) do - ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);') - end - end - - it 'prevents database counters from leaking to the next transaction' do - worker = double(:worker, class: double(:class, name: 'TestWorker')) - - 2.times do - Gitlab::WithRequestStore.with_request_store do - middleware.call(worker, message, :test) do - ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);') - end - end - end - - expect(message).to include(db_count: 1, db_write_count: 0, db_cached_count: 0) - end - - it 'tracks the transaction (for messages without `enqueued_at`)', :aggregate_failures do - worker = double(:worker, class: double(:class, name: 'TestWorker')) - - expect(Gitlab::Metrics::BackgroundTransaction).to receive(:new) - .with(worker.class) - .and_call_original - - expect_any_instance_of(Gitlab::Metrics::Transaction).to receive(:set) - .with(:gitlab_transaction_sidekiq_queue_duration_total, instance_of(Float)) - - middleware.call(worker, {}, :test) { nil } - end - - it 'tracks any raised exceptions', :aggregate_failures, :request_store do - worker = double(:worker, class: double(:class, name: 'TestWorker')) - - expect_any_instance_of(Gitlab::Metrics::Transaction) - .to receive(:add_event).with(:sidekiq_exception) - - expect do - middleware.call(worker, message, :test) do - ActiveRecord::Base.connection.execute('SELECT pg_sleep(0.1);') - raise RuntimeError - end - end.to raise_error(RuntimeError) - - expect(message).to include(db_count: 1, db_write_count: 0, db_cached_count: 0) - end - end -end diff --git a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb index a31686b8061..edcd5b31941 100644 --- a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb +++ b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb @@ -18,59 +18,73 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do end describe '#sql' do - describe 'without a current transaction' do - it 'simply returns' do - expect_any_instance_of(Gitlab::Metrics::Transaction) - .not_to receive(:increment) + shared_examples 'track query in metrics' do + before do + allow(subscriber).to receive(:current_transaction) + .at_least(:once) + .and_return(transaction) + end + + it 'increments only db count value' do + described_class::DB_COUNTERS.each do |counter| + prometheus_counter = "gitlab_transaction_#{counter}_total".to_sym + if expected_counters[counter] > 0 + expect(transaction).to receive(:increment).with(prometheus_counter, 1) + else + expect(transaction).not_to receive(:increment).with(prometheus_counter, 1) + end + end subscriber.sql(event) end end - describe 'with a current transaction' do - shared_examples 'track executed query' do - before do - allow(subscriber).to receive(:current_transaction) - .at_least(:once) - .and_return(transaction) - end + shared_examples 'track query in RequestStore' do + context 'when RequestStore is enabled' do + it 'caches db count value', :request_store, :aggregate_failures do + subscriber.sql(event) - it 'increments only db count value' do described_class::DB_COUNTERS.each do |counter| - prometheus_counter = "gitlab_transaction_#{counter}_total".to_sym - if expected_counters[counter] > 0 - expect(transaction).to receive(:increment).with(prometheus_counter, 1) - else - expect(transaction).not_to receive(:increment).with(prometheus_counter, 1) - end + expect(Gitlab::SafeRequestStore[counter].to_i).to eq expected_counters[counter] end - - subscriber.sql(event) end - context 'when RequestStore is enabled' do - it 'caches db count value', :request_store, :aggregate_failures do - subscriber.sql(event) + it 'prevents db counters from leaking to the next transaction' do + 2.times do + Gitlab::WithRequestStore.with_request_store do + subscriber.sql(event) - described_class::DB_COUNTERS.each do |counter| - expect(Gitlab::SafeRequestStore[counter].to_i).to eq expected_counters[counter] + described_class::DB_COUNTERS.each do |counter| + expect(Gitlab::SafeRequestStore[counter].to_i).to eq expected_counters[counter] + end end end + end + end + end + + describe 'without a current transaction' do + it 'does not track any metrics' do + expect_any_instance_of(Gitlab::Metrics::Transaction) + .not_to receive(:increment) - it 'prevents db counters from leaking to the next transaction' do - 2.times do - Gitlab::WithRequestStore.with_request_store do - subscriber.sql(event) + subscriber.sql(event) + end - described_class::DB_COUNTERS.each do |counter| - expect(Gitlab::SafeRequestStore[counter].to_i).to eq expected_counters[counter] - end - end - end - end + context 'with read query' do + let(:expected_counters) do + { + db_count: 1, + db_write_count: 0, + db_cached_count: 0 + } end + + it_behaves_like 'track query in RequestStore' end + end + describe 'with a current transaction' do it 'observes sql_duration metric' do expect(subscriber).to receive(:current_transaction) .at_least(:once) @@ -96,12 +110,14 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do } end - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' context 'with only select' do let(:payload) { { sql: 'WITH active_milestones AS (SELECT COUNT(*), state FROM milestones GROUP BY state) SELECT * FROM active_milestones' } } - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' end end @@ -117,33 +133,38 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do context 'with select for update sql event' do let(:payload) { { sql: 'SELECT * FROM users WHERE id = 10 FOR UPDATE' } } - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' end context 'with common table expression' do context 'with insert' do let(:payload) { { sql: 'WITH archived_rows AS (SELECT * FROM users WHERE archived = true) INSERT INTO products_log SELECT * FROM archived_rows' } } - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' end end context 'with delete sql event' do let(:payload) { { sql: 'DELETE FROM users where id = 10' } } - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' end context 'with insert sql event' do let(:payload) { { sql: 'INSERT INTO project_ci_cd_settings (project_id) SELECT id FROM projects' } } - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' end context 'with update sql event' do let(:payload) { { sql: 'UPDATE users SET admin = true WHERE id = 10' } } - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' end end @@ -164,18 +185,20 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do } end - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' end context 'with cached payload name' do let(:payload) do { - sql: 'SELECT * FROM users WHERE id = 10', - name: 'CACHE' + sql: 'SELECT * FROM users WHERE id = 10', + name: 'CACHE' } end - it_behaves_like 'track executed query' + it_behaves_like 'track query in metrics' + it_behaves_like 'track query in RequestStore' end end @@ -227,8 +250,8 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do it 'skips schema/begin/commit sql commands' do allow(subscriber).to receive(:current_transaction) - .at_least(:once) - .and_return(transaction) + .at_least(:once) + .and_return(transaction) expect(transaction).not_to receive(:increment) diff --git a/spec/lib/gitlab/utils/usage_data_spec.rb b/spec/lib/gitlab/utils/usage_data_spec.rb index 9c0dc69ccd1..7d7a2d48c07 100644 --- a/spec/lib/gitlab/utils/usage_data_spec.rb +++ b/spec/lib/gitlab/utils/usage_data_spec.rb @@ -37,6 +37,36 @@ RSpec.describe Gitlab::Utils::UsageData do end end + describe '#estimate_batch_distinct_count' do + let(:relation) { double(:relation) } + + it 'delegates counting to counter class instance' do + expect_next_instance_of(Gitlab::Database::PostgresHllBatchDistinctCounter, relation, 'column') do |instance| + expect(instance).to receive(:estimate_distinct_count) + .with(batch_size: nil, start: nil, finish: nil) + .and_return(5) + end + + expect(described_class.estimate_batch_distinct_count(relation, 'column')).to eq(5) + end + + it 'returns default fallback value when counting fails due to database error' do + stub_const("Gitlab::Utils::UsageData::FALLBACK", 15) + allow(Gitlab::Database::PostgresHllBatchDistinctCounter).to receive(:new).and_raise(ActiveRecord::StatementInvalid.new('')) + + expect(described_class.estimate_batch_distinct_count(relation)).to eq(15) + end + + it 'logs error and returns DISTRIBUTED_HLL_FALLBACK value when counting raises any error', :aggregate_failures do + error = StandardError.new('') + stub_const("Gitlab::Utils::UsageData::DISTRIBUTED_HLL_FALLBACK", 15) + allow(Gitlab::Database::PostgresHllBatchDistinctCounter).to receive(:new).and_raise(error) + + expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).with(error) + expect(described_class.estimate_batch_distinct_count(relation)).to eq(15) + end + end + describe '#sum' do let(:relation) { double(:relation) } diff --git a/spec/models/group_import_state_spec.rb b/spec/models/group_import_state_spec.rb index 469b5c96ac9..52ea20aeac8 100644 --- a/spec/models/group_import_state_spec.rb +++ b/spec/models/group_import_state_spec.rb @@ -70,4 +70,24 @@ RSpec.describe GroupImportState do end end end + + context 'when import failed' do + context 'when error message is present' do + it 'truncates error message' do + group_import_state = build(:group_import_state, :started) + group_import_state.fail_op('e' * 300) + + expect(group_import_state.last_error.length).to eq(255) + end + end + + context 'when error message is missing' do + it 'has no error message' do + group_import_state = build(:group_import_state, :started) + group_import_state.fail_op + + expect(group_import_state.last_error).to be_nil + end + end + end end diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb index 7f70a68a198..3e8c66ab1ae 100644 --- a/spec/models/service_spec.rb +++ b/spec/models/service_spec.rb @@ -245,7 +245,7 @@ RSpec.describe Service do context 'with a previous existing service (MockCiService) and a new service (Asana)' do before do - Service.insert(type: 'MockCiService', instance: true) + Service.insert({ type: 'MockCiService', instance: true }) Service.delete_by(type: 'AsanaService', instance: true) end @@ -291,7 +291,7 @@ RSpec.describe Service do context 'with a previous existing service (Previous) and a new service (Asana)' do before do - Service.insert(type: 'PreviousService', template: true) + Service.insert({ type: 'PreviousService', template: true }) Service.delete_by(type: 'AsanaService', template: true) end diff --git a/spec/models/wiki_page/meta_spec.rb b/spec/models/wiki_page/meta_spec.rb index aaac72cbc68..24906d4fb79 100644 --- a/spec/models/wiki_page/meta_spec.rb +++ b/spec/models/wiki_page/meta_spec.rb @@ -25,13 +25,8 @@ RSpec.describe WikiPage::Meta do end it { is_expected.to validate_presence_of(:project_id) } - it { is_expected.to validate_presence_of(:title) } - - it 'is forbidden to add extremely long titles' do - expect do - create(:wiki_page_meta, project: project, title: FFaker::Lorem.characters(300)) - end.to raise_error(ActiveRecord::ValueTooLong) - end + it { is_expected.to validate_length_of(:title).is_at_most(255) } + it { is_expected.not_to allow_value(nil).for(:title) } it 'is forbidden to have two records for the same project with the same canonical_slug' do the_slug = generate(:sluggified_title) diff --git a/spec/models/wiki_page/slug_spec.rb b/spec/models/wiki_page/slug_spec.rb index cf256c67277..9e83b9a8182 100644 --- a/spec/models/wiki_page/slug_spec.rb +++ b/spec/models/wiki_page/slug_spec.rb @@ -48,8 +48,9 @@ RSpec.describe WikiPage::Slug do build(:wiki_page_slug, canonical: canonical, wiki_page_meta: meta) end - it { is_expected.to validate_presence_of(:slug) } it { is_expected.to validate_uniqueness_of(:slug).scoped_to(:wiki_page_meta_id) } + it { is_expected.to validate_length_of(:slug).is_at_most(2048) } + it { is_expected.not_to allow_value(nil).for(:slug) } describe 'only_one_slug_can_be_canonical_per_meta_record' do context 'there are no other slugs' do diff --git a/spec/requests/api/graphql/project/terraform/states_spec.rb b/spec/requests/api/graphql/project/terraform/states_spec.rb index 8b67b549efa..f1dcd530218 100644 --- a/spec/requests/api/graphql/project/terraform/states_spec.rb +++ b/spec/requests/api/graphql/project/terraform/states_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe 'query terraform states' do include GraphqlHelpers + include ::API::Helpers::RelatedResourcesHelpers let_it_be(:project) { create(:project) } let_it_be(:terraform_state) { create(:terraform_state, :with_version, :locked, project: project) } @@ -23,6 +24,8 @@ RSpec.describe 'query terraform states' do latestVersion { id + downloadPath + serial createdAt updatedAt @@ -62,6 +65,16 @@ RSpec.describe 'query terraform states' do expect(state.dig('lockedByUser', 'id')).to eq(terraform_state.locked_by_user.to_global_id.to_s) expect(version['id']).to eq(latest_version.to_global_id.to_s) + expect(version['serial']).to eq(latest_version.version) + expect(version['downloadPath']).to eq( + expose_path( + api_v4_projects_terraform_state_versions_path( + id: project.id, + name: terraform_state.name, + serial: latest_version.version + ) + ) + ) expect(version['createdAt']).to eq(latest_version.created_at.iso8601) expect(version['updatedAt']).to eq(latest_version.updated_at.iso8601) expect(version.dig('createdByUser', 'id')).to eq(latest_version.created_by_user.to_global_id.to_s) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 55ee846090f..688deb78020 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -332,6 +332,13 @@ RSpec.configure do |config| Gitlab::WithRequestStore.with_request_store { example.run } end + config.before(:example, :request_store) do + # Clear request store before actually starting the spec (the + # `around` above will have the request store enabled for all + # `before` blocks) + RequestStore.clear! + end + config.around do |example| # Wrap each example in it's own context to make sure the contexts don't # leak |