Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/metrics/dashboard/validator')
-rw-r--r--spec/lib/gitlab/metrics/dashboard/validator/client_spec.rb29
-rw-r--r--spec/lib/gitlab/metrics/dashboard/validator/custom_formats_spec.rb15
-rw-r--r--spec/lib/gitlab/metrics/dashboard/validator/errors_spec.rb140
-rw-r--r--spec/lib/gitlab/metrics/dashboard/validator/post_schema_validator_spec.rb78
4 files changed, 262 insertions, 0 deletions
diff --git a/spec/lib/gitlab/metrics/dashboard/validator/client_spec.rb b/spec/lib/gitlab/metrics/dashboard/validator/client_spec.rb
new file mode 100644
index 00000000000..4b07f9dbbab
--- /dev/null
+++ b/spec/lib/gitlab/metrics/dashboard/validator/client_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Metrics::Dashboard::Validator::Client do
+ include MetricsDashboardHelpers
+
+ let_it_be(:schema_path) { 'lib/gitlab/metrics/dashboard/validator/schemas/dashboard.json' }
+
+ subject { described_class.new(dashboard, schema_path) }
+
+ describe '#execute' do
+ context 'with no validation errors' do
+ let(:dashboard) { load_sample_dashboard }
+
+ it 'returns empty array' do
+ expect(subject.execute).to eq([])
+ end
+ end
+
+ context 'with validation errors' do
+ let(:dashboard) { load_dashboard_yaml(fixture_file('lib/gitlab/metrics/dashboard/invalid_dashboard.yml')) }
+
+ it 'returns array of error objects' do
+ expect(subject.execute).to include(Gitlab::Metrics::Dashboard::Validator::Errors::SchemaValidationError)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/dashboard/validator/custom_formats_spec.rb b/spec/lib/gitlab/metrics/dashboard/validator/custom_formats_spec.rb
new file mode 100644
index 00000000000..129fb631f3e
--- /dev/null
+++ b/spec/lib/gitlab/metrics/dashboard/validator/custom_formats_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Metrics::Dashboard::Validator::CustomFormats do
+ describe '#format_handlers' do
+ describe 'add_to_metric_id_cache' do
+ it 'adds data to metric id cache' do
+ subject.format_handlers['add_to_metric_id_cache'].call('metric_id', '_schema')
+
+ expect(subject.metric_ids_cache).to eq(["metric_id"])
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/dashboard/validator/errors_spec.rb b/spec/lib/gitlab/metrics/dashboard/validator/errors_spec.rb
new file mode 100644
index 00000000000..f0db1bd0d33
--- /dev/null
+++ b/spec/lib/gitlab/metrics/dashboard/validator/errors_spec.rb
@@ -0,0 +1,140 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Metrics::Dashboard::Validator::Errors do
+ describe Gitlab::Metrics::Dashboard::Validator::Errors::SchemaValidationError do
+ context 'empty error hash' do
+ let(:error_hash) { {} }
+
+ it 'uses default error message' do
+ expect(described_class.new(error_hash).message).to eq('Dashboard failed schema validation')
+ end
+ end
+
+ context 'formatted message' do
+ subject { described_class.new(error_hash).message }
+
+ let(:error_hash) do
+ {
+ 'data' => 'property_name',
+ 'data_pointer' => pointer,
+ 'type' => type,
+ 'schema' => 'schema',
+ 'details' => details
+ }
+ end
+
+ context 'for root object' do
+ let(:pointer) { '' }
+
+ context 'when required keys are missing' do
+ let(:type) { 'required' }
+ let(:details) { { 'missing_keys' => ['one'] } }
+
+ it { is_expected.to eq 'root is missing required keys: one' }
+ end
+ end
+
+ context 'for nested object' do
+ let(:pointer) { '/nested_objects/0' }
+
+ context 'when required keys are missing' do
+ let(:type) { 'required' }
+ let(:details) { { 'missing_keys' => ['two'] } }
+
+ it { is_expected.to eq '/nested_objects/0 is missing required keys: two' }
+ end
+
+ context 'when there is type mismatch' do
+ %w(null string boolean integer number array object).each do |expected_type|
+ context "on type: #{expected_type}" do
+ let(:type) { expected_type }
+ let(:details) { nil }
+
+ subject { described_class.new(error_hash).message }
+
+ it { is_expected.to eq "'property_name' at /nested_objects/0 is not of type: #{expected_type}" }
+ end
+ end
+ end
+
+ context 'when data does not match pattern' do
+ let(:type) { 'pattern' }
+ let(:error_hash) do
+ {
+ 'data' => 'property_name',
+ 'data_pointer' => pointer,
+ 'type' => type,
+ 'schema' => { 'pattern' => 'aa.*' }
+ }
+ end
+
+ it { is_expected.to eq "'property_name' at /nested_objects/0 does not match pattern: aa.*" }
+ end
+
+ context 'when data does not match format' do
+ let(:type) { 'format' }
+ let(:error_hash) do
+ {
+ 'data' => 'property_name',
+ 'data_pointer' => pointer,
+ 'type' => type,
+ 'schema' => { 'format' => 'date-time' }
+ }
+ end
+
+ it { is_expected.to eq "'property_name' at /nested_objects/0 does not match format: date-time" }
+ end
+
+ context 'when data is not const' do
+ let(:type) { 'const' }
+ let(:error_hash) do
+ {
+ 'data' => 'property_name',
+ 'data_pointer' => pointer,
+ 'type' => type,
+ 'schema' => { 'const' => 'one' }
+ }
+ end
+
+ it { is_expected.to eq "'property_name' at /nested_objects/0 is not: \"one\"" }
+ end
+
+ context 'when data is not included in enum' do
+ let(:type) { 'enum' }
+ let(:error_hash) do
+ {
+ 'data' => 'property_name',
+ 'data_pointer' => pointer,
+ 'type' => type,
+ 'schema' => { 'enum' => %w(one two) }
+ }
+ end
+
+ it { is_expected.to eq "'property_name' at /nested_objects/0 is not one of: [\"one\", \"two\"]" }
+ end
+
+ context 'when data is not included in enum' do
+ let(:type) { 'unknown' }
+ let(:error_hash) do
+ {
+ 'data' => 'property_name',
+ 'data_pointer' => pointer,
+ 'type' => type,
+ 'schema' => 'schema'
+ }
+ end
+
+ it { is_expected.to eq "'property_name' at /nested_objects/0 is invalid: error_type=unknown" }
+ end
+ end
+ end
+ end
+
+ describe Gitlab::Metrics::Dashboard::Validator::Errors::DuplicateMetricIds do
+ it 'has custom error message' do
+ expect(described_class.new.message).to eq('metric_id must be unique across a project')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/dashboard/validator/post_schema_validator_spec.rb b/spec/lib/gitlab/metrics/dashboard/validator/post_schema_validator_spec.rb
new file mode 100644
index 00000000000..e7cb1429ca9
--- /dev/null
+++ b/spec/lib/gitlab/metrics/dashboard/validator/post_schema_validator_spec.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Metrics::Dashboard::Validator::PostSchemaValidator do
+ describe '#validate' do
+ context 'with no project and dashboard_path provided' do
+ context 'unique local metric_ids' do
+ it 'returns empty array' do
+ expect(described_class.new(metric_ids: [1, 2, 3]).validate).to eq([])
+ end
+ end
+
+ context 'duplicate local metrics_ids' do
+ it 'returns error' do
+ expect(described_class.new(metric_ids: [1, 1]).validate)
+ .to eq([Gitlab::Metrics::Dashboard::Validator::Errors::DuplicateMetricIds])
+ end
+ end
+ end
+
+ context 'with project and dashboard_path' do
+ let(:project) { create(:project) }
+
+ subject do
+ described_class.new(
+ project: project,
+ metric_ids: ['some_identifier'],
+ dashboard_path: 'test/path.yml'
+ ).validate
+ end
+
+ context 'with unique metric identifiers' do
+ before do
+ create(:prometheus_metric,
+ project: project,
+ identifier: 'some_other_identifier',
+ dashboard_path: 'test/path.yml'
+ )
+ end
+
+ it 'returns empty array' do
+ expect(subject).to eq([])
+ end
+ end
+
+ context 'duplicate metric identifiers in database' do
+ context 'with different dashboard_path' do
+ before do
+ create(:prometheus_metric,
+ project: project,
+ identifier: 'some_identifier',
+ dashboard_path: 'some/other/path.yml'
+ )
+ end
+
+ it 'returns error' do
+ expect(subject).to include(Gitlab::Metrics::Dashboard::Validator::Errors::DuplicateMetricIds)
+ end
+ end
+
+ context 'with same dashboard_path' do
+ before do
+ create(:prometheus_metric,
+ project: project,
+ identifier: 'some_identifier',
+ dashboard_path: 'test/path.yml'
+ )
+ end
+
+ it 'returns empty array' do
+ expect(subject).to eq([])
+ end
+ end
+ end
+ end
+ end
+end