diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-27 18:10:21 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-27 18:10:21 +0300 |
commit | eef9c80f1c3e81fcb50c51d8f419ab095d4747fd (patch) | |
tree | 5052967f5239d74e34527e94600621e6c1ebfcc4 /spec/models | |
parent | d6404862287ded00725865e56cda3a6fb4f2a1c7 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/models')
-rw-r--r-- | spec/models/blob_viewer/metrics_dashboard_yml_spec.rb | 253 | ||||
-rw-r--r-- | spec/models/ci/job_artifact_spec.rb | 36 | ||||
-rw-r--r-- | spec/models/concerns/ci/artifactable_spec.rb | 36 | ||||
-rw-r--r-- | spec/models/namespace_spec.rb | 117 | ||||
-rw-r--r-- | spec/models/performance_monitoring/prometheus_dashboard_spec.rb | 93 | ||||
-rw-r--r-- | spec/models/user_spec.rb | 2 |
6 files changed, 400 insertions, 137 deletions
diff --git a/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb b/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb index 057f0f32158..84dfc5186a8 100644 --- a/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb +++ b/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb @@ -9,119 +9,228 @@ RSpec.describe BlobViewer::MetricsDashboardYml do let_it_be(:project) { create(:project, :repository) } let(:blob) { fake_blob(path: '.gitlab/dashboards/custom-dashboard.yml', data: data) } let(:sha) { sample_commit.id } + let(:data) { fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml') } subject(:viewer) { described_class.new(blob) } - context 'when the definition is valid' do - let(:data) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) } + context 'with metrics_dashboard_exhaustive_validations feature flag on' do + before do + stub_feature_flags(metrics_dashboard_exhaustive_validations: true) + end + + context 'when the definition is valid' do + before do + allow(Gitlab::Metrics::Dashboard::Validator).to receive(:errors).and_return([]) + end + + describe '#valid?' do + it 'calls prepare! on the viewer' do + expect(viewer).to receive(:prepare!) + + viewer.valid? + end + + it 'processes dashboard yaml and returns true', :aggregate_failures do + yml = ::Gitlab::Config::Loader::Yaml.new(data).load_raw! + + expect_next_instance_of(::Gitlab::Config::Loader::Yaml, data) do |loader| + expect(loader).to receive(:load_raw!).and_call_original + end + expect(Gitlab::Metrics::Dashboard::Validator) + .to receive(:errors) + .with(yml, dashboard_path: '.gitlab/dashboards/custom-dashboard.yml', project: project) + .and_call_original + expect(viewer.valid?).to be true + end + end + + describe '#errors' do + it 'returns empty array' do + expect(viewer.errors).to eq [] + end + end + end + + context 'when definition is invalid' do + let(:error) { ::Gitlab::Metrics::Dashboard::Validator::Errors::SchemaValidationError.new } + let(:data) do + <<~YAML + dashboard: + YAML + end + + before do + allow(Gitlab::Metrics::Dashboard::Validator).to receive(:errors).and_return([error]) + end - describe '#valid?' do - it 'calls prepare! on the viewer' do - allow(PerformanceMonitoring::PrometheusDashboard).to receive(:from_json) + describe '#valid?' do + it 'returns false' do + expect(viewer.valid?).to be false + end + end - expect(viewer).to receive(:prepare!) + describe '#errors' do + it 'returns validation errors' do + expect(viewer.errors).to eq ["Dashboard failed schema validation"] + end + end + end - viewer.valid? + context 'when YAML syntax is invalid' do + let(:data) do + <<~YAML + dashboard: 'empty metrics' + panel_groups: + - group: 'Group Title' + YAML end - it 'returns true', :aggregate_failures do - yml = ::Gitlab::Config::Loader::Yaml.new(data).load_raw! + describe '#valid?' do + it 'returns false' do + expect(Gitlab::Metrics::Dashboard::Validator).not_to receive(:errors) + expect(viewer.valid?).to be false + end + end - expect_next_instance_of(::Gitlab::Config::Loader::Yaml, data) do |loader| - expect(loader).to receive(:load_raw!).and_call_original + describe '#errors' do + it 'returns validation errors' do + expect(viewer.errors).to all be_kind_of String end - expect(PerformanceMonitoring::PrometheusDashboard) - .to receive(:from_json) - .with(yml) - .and_call_original - expect(viewer.valid?).to be_truthy end end - describe '#errors' do - it 'returns nil' do - allow(PerformanceMonitoring::PrometheusDashboard).to receive(:from_json) + context 'when YAML loader raises error' do + let(:data) do + <<~YAML + large yaml file + YAML + end + + before do + allow(::Gitlab::Config::Loader::Yaml).to receive(:new) + .and_raise(::Gitlab::Config::Loader::Yaml::DataTooLargeError, 'The parsed YAML is too big') + end - expect(viewer.errors).to be nil + it 'is invalid' do + expect(Gitlab::Metrics::Dashboard::Validator).not_to receive(:errors) + expect(viewer.valid?).to be false + end + + it 'returns validation errors' do + expect(viewer.errors).to eq ['The parsed YAML is too big'] end end end - context 'when definition is invalid' do - let(:error) { ActiveModel::ValidationError.new(PerformanceMonitoring::PrometheusDashboard.new.tap(&:validate)) } - let(:data) do - <<~YAML - dashboard: - YAML + context 'with metrics_dashboard_exhaustive_validations feature flag off' do + before do + stub_feature_flags(metrics_dashboard_exhaustive_validations: false) end - describe '#valid?' do - it 'returns false' do - expect(PerformanceMonitoring::PrometheusDashboard) - .to receive(:from_json).and_raise(error) + context 'when the definition is valid' do + describe '#valid?' do + before do + allow(PerformanceMonitoring::PrometheusDashboard).to receive(:from_json) + end + + it 'calls prepare! on the viewer' do + expect(viewer).to receive(:prepare!) - expect(viewer.valid?).to be_falsey + viewer.valid? + end + + it 'processes dashboard yaml and returns true', :aggregate_failures do + yml = ::Gitlab::Config::Loader::Yaml.new(data).load_raw! + + expect_next_instance_of(::Gitlab::Config::Loader::Yaml, data) do |loader| + expect(loader).to receive(:load_raw!).and_call_original + end + expect(PerformanceMonitoring::PrometheusDashboard) + .to receive(:from_json) + .with(yml) + .and_call_original + expect(viewer.valid?).to be true + end + end + + describe '#errors' do + it 'returns empty array' do + expect(viewer.errors).to eq [] + end end end - describe '#errors' do - it 'returns validation errors' do - allow(PerformanceMonitoring::PrometheusDashboard) - .to receive(:from_json).and_raise(error) + context 'when definition is invalid' do + let(:error) { ActiveModel::ValidationError.new(PerformanceMonitoring::PrometheusDashboard.new.tap(&:validate)) } + let(:data) do + <<~YAML + dashboard: + YAML + end + + describe '#valid?' do + it 'returns false' do + expect(PerformanceMonitoring::PrometheusDashboard) + .to receive(:from_json).and_raise(error) - expect(viewer.errors).to be error.model.errors + expect(viewer.valid?).to be false + end + end + + describe '#errors' do + it 'returns validation errors' do + allow(PerformanceMonitoring::PrometheusDashboard) + .to receive(:from_json).and_raise(error) + + expect(viewer.errors).to eq error.model.errors.messages.map { |messages| messages.join(': ') } + end end end - end - context 'when YAML syntax is invalid' do - let(:data) do - <<~YAML + context 'when YAML syntax is invalid' do + let(:data) do + <<~YAML dashboard: 'empty metrics' panel_groups: - group: 'Group Title' - YAML - end - - describe '#valid?' do - it 'returns false' do - expect(PerformanceMonitoring::PrometheusDashboard).not_to receive(:from_json) - expect(viewer.valid?).to be_falsey + YAML end - end - describe '#errors' do - it 'returns validation errors' do - yaml_wrapped_errors = { 'YAML syntax': ["(<unknown>): did not find expected key while parsing a block mapping at line 1 column 1"] } + describe '#valid?' do + it 'returns false' do + expect(PerformanceMonitoring::PrometheusDashboard).not_to receive(:from_json) + expect(viewer.valid?).to be false + end + end - expect(viewer.errors).to be_kind_of ActiveModel::Errors - expect(viewer.errors.messages).to eql(yaml_wrapped_errors) + describe '#errors' do + it 'returns validation errors' do + expect(viewer.errors).to eq ["YAML syntax: (<unknown>): did not find expected key while parsing a block mapping at line 1 column 1"] + end end end - end - context 'when YAML loader raises error' do - let(:data) do - <<~YAML + context 'when YAML loader raises error' do + let(:data) do + <<~YAML large yaml file - YAML - end - - before do - allow(::Gitlab::Config::Loader::Yaml).to receive(:new) - .and_raise(::Gitlab::Config::Loader::Yaml::DataTooLargeError, 'The parsed YAML is too big') - end + YAML + end - it 'is invalid' do - expect(PerformanceMonitoring::PrometheusDashboard).not_to receive(:from_json) - expect(viewer.valid?).to be(false) - end + before do + allow(::Gitlab::Config::Loader::Yaml).to( + receive(:new).and_raise(::Gitlab::Config::Loader::Yaml::DataTooLargeError, 'The parsed YAML is too big') + ) + end - it 'returns validation errors' do - yaml_wrapped_errors = { 'YAML syntax': ["The parsed YAML is too big"] } + it 'is invalid' do + expect(PerformanceMonitoring::PrometheusDashboard).not_to receive(:from_json) + expect(viewer.valid?).to be false + end - expect(viewer.errors).to be_kind_of(ActiveModel::Errors) - expect(viewer.errors.messages).to eq(yaml_wrapped_errors) + it 'returns validation errors' do + expect(viewer.errors).to eq ["YAML syntax: The parsed YAML is too big"] + end end end end diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb index 91a669aa3f4..0518b2c7540 100644 --- a/spec/models/ci/job_artifact_spec.rb +++ b/spec/models/ci/job_artifact_spec.rb @@ -343,42 +343,6 @@ RSpec.describe Ci::JobArtifact do end end - describe '#each_blob' do - context 'when file format is gzip' do - context 'when gzip file contains one file' do - let(:artifact) { build(:ci_job_artifact, :junit) } - - it 'iterates blob once' do - expect { |b| artifact.each_blob(&b) }.to yield_control.once - end - end - - context 'when gzip file contains three files' do - let(:artifact) { build(:ci_job_artifact, :junit_with_three_testsuites) } - - it 'iterates blob three times' do - expect { |b| artifact.each_blob(&b) }.to yield_control.exactly(3).times - end - end - end - - context 'when file format is raw' do - let(:artifact) { build(:ci_job_artifact, :codequality, file_format: :raw) } - - it 'iterates blob once' do - expect { |b| artifact.each_blob(&b) }.to yield_control.once - end - end - - context 'when there are no adapters for the file format' do - let(:artifact) { build(:ci_job_artifact, :junit, file_format: :zip) } - - it 'raises an error' do - expect { |b| artifact.each_blob(&b) }.to raise_error(described_class::NotSupportedAdapterError) - end - end - end - describe 'expired?' do subject { artifact.expired? } diff --git a/spec/models/concerns/ci/artifactable_spec.rb b/spec/models/concerns/ci/artifactable_spec.rb index 13c2ff5efe5..f05189abdd2 100644 --- a/spec/models/concerns/ci/artifactable_spec.rb +++ b/spec/models/concerns/ci/artifactable_spec.rb @@ -18,4 +18,40 @@ RSpec.describe Ci::Artifactable do it { is_expected.to be_const_defined(:FILE_FORMAT_ADAPTERS) } end end + + describe '#each_blob' do + context 'when file format is gzip' do + context 'when gzip file contains one file' do + let(:artifact) { build(:ci_job_artifact, :junit) } + + it 'iterates blob once' do + expect { |b| artifact.each_blob(&b) }.to yield_control.once + end + end + + context 'when gzip file contains three files' do + let(:artifact) { build(:ci_job_artifact, :junit_with_three_testsuites) } + + it 'iterates blob three times' do + expect { |b| artifact.each_blob(&b) }.to yield_control.exactly(3).times + end + end + end + + context 'when file format is raw' do + let(:artifact) { build(:ci_job_artifact, :codequality, file_format: :raw) } + + it 'iterates blob once' do + expect { |b| artifact.each_blob(&b) }.to yield_control.once + end + end + + context 'when there are no adapters for the file format' do + let(:artifact) { build(:ci_job_artifact, :junit, file_format: :zip) } + + it 'raises an error' do + expect { |b| artifact.each_blob(&b) }.to raise_error(described_class::NotSupportedAdapterError) + end + end + end end diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index f685fe12e13..39ece3d1cb3 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -391,14 +391,14 @@ RSpec.describe Namespace do let(:uploads_dir) { FileUploader.root } let(:pages_dir) { File.join(TestEnv.pages_path) } - def expect_project_directories_at(namespace_path) + def expect_project_directories_at(namespace_path, with_pages: true) expected_repository_path = File.join(TestEnv.repos_path, namespace_path, 'the-project.git') expected_upload_path = File.join(uploads_dir, namespace_path, 'the-project') expected_pages_path = File.join(pages_dir, namespace_path, 'the-project') expect(File.directory?(expected_repository_path)).to be_truthy expect(File.directory?(expected_upload_path)).to be_truthy - expect(File.directory?(expected_pages_path)).to be_truthy + expect(File.directory?(expected_pages_path)).to be(with_pages) end before do @@ -412,7 +412,7 @@ RSpec.describe Namespace do FileUtils.remove_entry(File.join(TestEnv.repos_path, new_parent.full_path), true) FileUtils.remove_entry(File.join(TestEnv.repos_path, child.full_path), true) FileUtils.remove_entry(File.join(uploads_dir, project.full_path), true) - FileUtils.remove_entry(File.join(pages_dir, project.full_path), true) + FileUtils.remove_entry(pages_dir, true) end context 'renaming child' do @@ -426,10 +426,22 @@ RSpec.describe Namespace do end end - it 'correctly moves the repository, uploads and pages', :sidekiq_inline do - child.update!(path: 'renamed') + context 'when no projects have pages deployed' do + it 'moves the repository and uploads', :sidekiq_inline do + project.pages_metadatum.update!(deployed: false) + child.update!(path: 'renamed') + + expect_project_directories_at('parent/renamed', with_pages: false) + end + end + + context 'when the project has pages deployed' do + it 'correctly moves the repository, uploads and pages', :sidekiq_inline do + project.pages_metadatum.update!(deployed: true) + child.update!(path: 'renamed') - expect_project_directories_at('parent/renamed') + expect_project_directories_at('parent/renamed') + end end end @@ -444,10 +456,22 @@ RSpec.describe Namespace do end end - it 'correctly moves the repository, uploads and pages', :sidekiq_inline do - parent.update!(path: 'renamed') + context 'when no projects have pages deployed' do + it 'moves the repository and uploads', :sidekiq_inline do + project.pages_metadatum.update!(deployed: false) + parent.update!(path: 'renamed') + + expect_project_directories_at('renamed/child', with_pages: false) + end + end + + context 'when the project has pages deployed' do + it 'correctly moves the repository, uploads and pages', :sidekiq_inline do + project.pages_metadatum.update!(deployed: true) + parent.update!(path: 'renamed') - expect_project_directories_at('renamed/child') + expect_project_directories_at('renamed/child') + end end end @@ -462,10 +486,22 @@ RSpec.describe Namespace do end end - it 'correctly moves the repository, uploads and pages', :sidekiq_inline do - child.update!(parent: new_parent) + context 'when no projects have pages deployed' do + it 'moves the repository and uploads', :sidekiq_inline do + project.pages_metadatum.update!(deployed: false) + child.update!(parent: new_parent) + + expect_project_directories_at('new_parent/child', with_pages: false) + end + end + + context 'when the project has pages deployed' do + it 'correctly moves the repository, uploads and pages', :sidekiq_inline do + project.pages_metadatum.update!(deployed: true) + child.update!(parent: new_parent) - expect_project_directories_at('new_parent/child') + expect_project_directories_at('new_parent/child') + end end end @@ -480,10 +516,22 @@ RSpec.describe Namespace do end end - it 'correctly moves the repository, uploads and pages', :sidekiq_inline do - child.update!(parent: nil) + context 'when no projects have pages deployed' do + it 'moves the repository and uploads', :sidekiq_inline do + project.pages_metadatum.update!(deployed: false) + child.update!(parent: nil) + + expect_project_directories_at('child', with_pages: false) + end + end + + context 'when the project has pages deployed' do + it 'correctly moves the repository, uploads and pages', :sidekiq_inline do + project.pages_metadatum.update!(deployed: true) + child.update!(parent: nil) - expect_project_directories_at('child') + expect_project_directories_at('child') + end end end @@ -498,10 +546,22 @@ RSpec.describe Namespace do end end - it 'correctly moves the repository, uploads and pages', :sidekiq_inline do - parent.update!(parent: new_parent) + context 'when no projects have pages deployed' do + it 'moves the repository and uploads', :sidekiq_inline do + project.pages_metadatum.update!(deployed: false) + parent.update!(parent: new_parent) - expect_project_directories_at('new_parent/parent/child') + expect_project_directories_at('new_parent/parent/child', with_pages: false) + end + end + + context 'when the project has pages deployed' do + it 'correctly moves the repository, uploads and pages', :sidekiq_inline do + project.pages_metadatum.update!(deployed: true) + parent.update!(parent: new_parent) + + expect_project_directories_at('new_parent/parent/child') + end end end end @@ -1174,6 +1234,27 @@ RSpec.describe Namespace do end end + describe '#any_project_with_pages_deployed?' do + it 'returns true if any project nested under the group has pages deployed' do + parent_1 = create(:group) # Three projects, one with pages + child_1_1 = create(:group, parent: parent_1) # Two projects, one with pages + child_1_2 = create(:group, parent: parent_1) # One project, no pages + parent_2 = create(:group) # No projects + + create(:project, group: child_1_1).tap do |project| + project.pages_metadatum.update!(deployed: true) + end + + create(:project, group: child_1_1) + create(:project, group: child_1_2) + + expect(parent_1.any_project_with_pages_deployed?).to be(true) + expect(child_1_1.any_project_with_pages_deployed?).to be(true) + expect(child_1_2.any_project_with_pages_deployed?).to be(false) + expect(parent_2.any_project_with_pages_deployed?).to be(false) + end + end + describe '#has_parent?' do it 'returns true when the group has a parent' do group = create(:group, :nested) diff --git a/spec/models/performance_monitoring/prometheus_dashboard_spec.rb b/spec/models/performance_monitoring/prometheus_dashboard_spec.rb index 61174a7d0c5..634690d5d0b 100644 --- a/spec/models/performance_monitoring/prometheus_dashboard_spec.rb +++ b/spec/models/performance_monitoring/prometheus_dashboard_spec.rb @@ -219,20 +219,93 @@ RSpec.describe PerformanceMonitoring::PrometheusDashboard do end describe '#schema_validation_warnings' do - context 'when schema is valid' do - it 'returns nil' do - expect(described_class).to receive(:from_json) - expect(described_class.new.schema_validation_warnings).to be_nil + let(:environment) { create(:environment, project: project) } + let(:path) { '.gitlab/dashboards/test.yml' } + let(:project) { create(:project, :repository, :custom_repo, files: { path => dashboard_schema.to_yaml }) } + + subject(:schema_validation_warnings) { described_class.new(dashboard_schema.merge(path: path, environment: environment)).schema_validation_warnings } + + before do + allow(Gitlab::Metrics::Dashboard::Finder).to receive(:find_raw).with(project, dashboard_path: path).and_call_original + end + + context 'metrics_dashboard_exhaustive_validations is on' do + before do + stub_feature_flags(metrics_dashboard_exhaustive_validations: true) + end + + context 'when schema is valid' do + let(:dashboard_schema) { YAML.safe_load(fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml')) } + + it 'returns empty array' do + expect(Gitlab::Metrics::Dashboard::Validator).to receive(:errors).with(dashboard_schema, dashboard_path: path, project: project).and_return([]) + + expect(schema_validation_warnings).to eq [] + end + end + + context 'when schema is invalid' do + let(:dashboard_schema) { YAML.safe_load(fixture_file('lib/gitlab/metrics/dashboard/dashboard_missing_panel_groups.yml')) } + + it 'returns array with errors messages' do + error = ::Gitlab::Metrics::Dashboard::Validator::Errors::SchemaValidationError.new + + expect(Gitlab::Metrics::Dashboard::Validator).to receive(:errors).with(dashboard_schema, dashboard_path: path, project: project).and_return([error]) + + expect(schema_validation_warnings).to eq [error.message] + end + end + + context 'when YAML has wrong syntax' do + let(:project) { create(:project, :repository, :custom_repo, files: { path => fixture_file('lib/gitlab/metrics/dashboard/broken_yml_syntax.yml') }) } + + subject(:schema_validation_warnings) { described_class.new(path: path, environment: environment).schema_validation_warnings } + + it 'returns array with errors messages' do + expect(Gitlab::Metrics::Dashboard::Validator).not_to receive(:errors) + + expect(schema_validation_warnings).to eq ['Invalid yaml'] + end end end - context 'when schema is invalid' do - it 'returns array with errors messages' do - instance = described_class.new - instance.errors.add(:test, 'test error') + context 'metrics_dashboard_exhaustive_validations is off' do + before do + stub_feature_flags(metrics_dashboard_exhaustive_validations: false) + end + + context 'when schema is valid' do + let(:dashboard_schema) { YAML.safe_load(fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml')) } + + it 'returns empty array' do + expect(described_class).to receive(:from_json).with(dashboard_schema) + + expect(schema_validation_warnings).to eq [] + end + end + + context 'when schema is invalid' do + let(:dashboard_schema) { YAML.safe_load(fixture_file('lib/gitlab/metrics/dashboard/dashboard_missing_panel_groups.yml')) } + + it 'returns array with errors messages' do + instance = described_class.new + instance.errors.add(:test, 'test error') + + expect(described_class).to receive(:from_json).and_raise(ActiveModel::ValidationError.new(instance)) + expect(described_class.new.schema_validation_warnings).to eq ['test: test error'] + end + end - expect(described_class).to receive(:from_json).and_raise(ActiveModel::ValidationError.new(instance)) - expect(described_class.new.schema_validation_warnings).to eq ['test: test error'] + context 'when YAML has wrong syntax' do + let(:project) { create(:project, :repository, :custom_repo, files: { path => fixture_file('lib/gitlab/metrics/dashboard/broken_yml_syntax.yml') }) } + + subject(:schema_validation_warnings) { described_class.new(path: path, environment: environment).schema_validation_warnings } + + it 'returns array with errors messages' do + expect(described_class).not_to receive(:from_json) + + expect(schema_validation_warnings).to eq ['Invalid yaml'] + end end end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index f9b819e22cd..9cd666e541f 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1648,7 +1648,7 @@ RSpec.describe User do # add user to project project.add_maintainer(user) - # create invite to projet + # create invite to project create(:project_member, :developer, project: project, invite_token: '1234', invite_email: 'inviteduser1@example.com') # create request to join project |