diff options
Diffstat (limited to 'spec/lib/gitlab/usage')
12 files changed, 282 insertions, 110 deletions
diff --git a/spec/lib/gitlab/usage/metric_definition_spec.rb b/spec/lib/gitlab/usage/metric_definition_spec.rb index e99d720058a..92e51b8ea23 100644 --- a/spec/lib/gitlab/usage/metric_definition_spec.rb +++ b/spec/lib/gitlab/usage/metric_definition_spec.rb @@ -25,6 +25,12 @@ RSpec.describe Gitlab::Usage::MetricDefinition do let(:definition) { described_class.new(path, attributes) } let(:yaml_content) { attributes.deep_stringify_keys.to_yaml } + around do |example| + described_class.instance_variable_set(:@definitions, nil) + example.run + described_class.instance_variable_set(:@definitions, nil) + end + def write_metric(metric, path, content) path = File.join(metric, path) dir = File.dirname(path) @@ -32,6 +38,11 @@ RSpec.describe Gitlab::Usage::MetricDefinition do File.write(path, content) end + after do + # Reset memoized `definitions` result + described_class.instance_variable_set(:@definitions, nil) + end + it 'has all definitons valid' do expect { described_class.definitions }.not_to raise_error(Gitlab::Usage::Metric::InvalidMetricError) end @@ -62,6 +73,9 @@ RSpec.describe Gitlab::Usage::MetricDefinition do :distribution | 'test' :tier | %w(test ee) :name | 'count_<adjective_describing>_boards' + + :instrumentation_class | 'Metric_Class' + :instrumentation_class | 'metricClass' end with_them do @@ -184,8 +198,6 @@ RSpec.describe Gitlab::Usage::MetricDefinition do File.join(metric2, '**', '*.yml') ] ) - # Reset memoized `definitions` result - described_class.instance_variable_set(:@definitions, nil) end after do diff --git a/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb b/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb index 7d8e3056384..0fb3a69df05 100644 --- a/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb +++ b/spec/lib/gitlab/usage/metrics/aggregates/aggregate_spec.rb @@ -65,76 +65,35 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Aggregate, :clean_gitlab_redi end context 'there are aggregated metrics defined' do + let(:aggregated_metrics) do + [ + aggregated_metric(name: "gmau_1", source: datasource, time_frame: time_frame, operator: operator) + ] + end + + let(:results) { { 'gmau_1' => 5 } } + let(:params) { { start_date: start_date, end_date: end_date, recorded_at: recorded_at } } + before do allow_next_instance_of(described_class) do |instance| allow(instance).to receive(:aggregated_metrics).and_return(aggregated_metrics) end end - context 'with AND operator' do - let(:aggregated_metrics) do - params = { source: datasource, operator: "AND", time_frame: time_frame } - [ - aggregated_metric(**params.merge(name: "gmau_1", events: %w[event3 event5])), - aggregated_metric(**params.merge(name: "gmau_2")) - ] - end - - it 'returns the number of unique events recorded for every metric in aggregate', :aggregate_failures do - results = { - 'gmau_1' => 2, - 'gmau_2' => 1 - } - params = { start_date: start_date, end_date: end_date, recorded_at: recorded_at } - - # gmau_1 data is as follow - # |A| => 4 - expect(namespace::SOURCES[datasource]).to receive(:calculate_metrics_union).with(params.merge(metric_names: 'event3')).and_return(4) - # |B| => 6 - expect(namespace::SOURCES[datasource]).to receive(:calculate_metrics_union).with(params.merge(metric_names: 'event5')).and_return(6) - # |A + B| => 8 - expect(namespace::SOURCES[datasource]).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event3 event5])).and_return(8) - # Exclusion inclusion principle formula to calculate intersection of 2 sets - # |A & B| = (|A| + |B|) - |A + B| => (4 + 6) - 8 => 2 - - # gmau_2 data is as follow: - # |A| => 2 - expect(namespace::SOURCES[datasource]).to receive(:calculate_metrics_union).with(params.merge(metric_names: 'event1')).and_return(2) - # |B| => 3 - expect(namespace::SOURCES[datasource]).to receive(:calculate_metrics_union).with(params.merge(metric_names: 'event2')).and_return(3) - # |C| => 5 - expect(namespace::SOURCES[datasource]).to receive(:calculate_metrics_union).with(params.merge(metric_names: 'event3')).and_return(5) - - # |A + B| => 4 therefore |A & B| = (|A| + |B|) - |A + B| => 2 + 3 - 4 => 1 - expect(namespace::SOURCES[datasource]).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event1 event2])).and_return(4) - # |A + C| => 6 therefore |A & C| = (|A| + |C|) - |A + C| => 2 + 5 - 6 => 1 - expect(namespace::SOURCES[datasource]).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event1 event3])).and_return(6) - # |B + C| => 7 therefore |B & C| = (|B| + |C|) - |B + C| => 3 + 5 - 7 => 1 - expect(namespace::SOURCES[datasource]).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event2 event3])).and_return(7) - # |A + B + C| => 8 - expect(namespace::SOURCES[datasource]).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event1 event2 event3])).and_return(8) - # Exclusion inclusion principle formula to calculate intersection of 3 sets - # |A & B & C| = (|A & B| + |A & C| + |B & C|) - (|A| + |B| + |C|) + |A + B + C| - # (1 + 1 + 1) - (2 + 3 + 5) + 8 => 1 + context 'with OR operator' do + let(:operator) { Gitlab::Usage::Metrics::Aggregates::UNION_OF_AGGREGATED_METRICS } + it 'returns the number of unique events occurred for any metric in aggregate', :aggregate_failures do + expect(namespace::SOURCES[datasource]).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event1 event2 event3])).and_return(5) expect(aggregated_metrics_data).to eq(results) end end - context 'with OR operator' do - let(:aggregated_metrics) do - [ - aggregated_metric(name: "gmau_1", source: datasource, time_frame: time_frame, operator: "OR") - ] - end - - it 'returns the number of unique events occurred for any metric in aggregate', :aggregate_failures do - results = { - 'gmau_1' => 5 - } - params = { start_date: start_date, end_date: end_date, recorded_at: recorded_at } + context 'with AND operator' do + let(:operator) { Gitlab::Usage::Metrics::Aggregates::INTERSECTION_OF_AGGREGATED_METRICS } - expect(namespace::SOURCES[datasource]).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event1 event2 event3])).and_return(5) + it 'returns the number of unique events that occurred for all of metrics in the aggregate', :aggregate_failures do + expect(namespace::SOURCES[datasource]).to receive(:calculate_metrics_intersections).with(params.merge(metric_names: %w[event1 event2 event3])).and_return(5) expect(aggregated_metrics_data).to eq(results) end end @@ -331,36 +290,6 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Aggregate, :clean_gitlab_redi it_behaves_like 'database_sourced_aggregated_metrics' it_behaves_like 'redis_sourced_aggregated_metrics' it_behaves_like 'db sourced aggregated metrics without database_sourced_aggregated_metrics feature' - - context 'metrics union calls' do - it 'caches intermediate operations', :aggregate_failures do - events = %w[event1 event2 event3 event5] - allow_next_instance_of(described_class) do |instance| - allow(instance).to receive(:aggregated_metrics) - .and_return([aggregated_metric(name: 'gmau_1', events: events, operator: "AND", time_frame: time_frame)]) - end - - params = { start_date: start_date, end_date: end_date, recorded_at: recorded_at } - - events.each do |event| - expect(sources::RedisHll).to receive(:calculate_metrics_union) - .with(params.merge(metric_names: event)) - .once - .and_return(0) - end - - 2.upto(4) do |subset_size| - events.combination(subset_size).each do |events| - expect(sources::RedisHll).to receive(:calculate_metrics_union) - .with(params.merge(metric_names: events)) - .once - .and_return(0) - end - end - - aggregated_metrics_data - end - end end end end diff --git a/spec/lib/gitlab/usage/metrics/aggregates/sources/calculations/intersection_spec.rb b/spec/lib/gitlab/usage/metrics/aggregates/sources/calculations/intersection_spec.rb new file mode 100644 index 00000000000..41cb445155e --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/aggregates/sources/calculations/intersection_spec.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Aggregates::Sources::Calculations::Intersection do + let_it_be(:recorded_at) { Time.current.to_i } + let_it_be(:start_date) { 4.weeks.ago.to_date } + let_it_be(:end_date) { Date.current } + + shared_examples 'aggregated_metrics_data with source' do + context 'with AND operator' do + let(:params) { { start_date: start_date, end_date: end_date, recorded_at: recorded_at } } + + context 'with even number of metrics' do + it 'calculates intersection correctly', :aggregate_failures do + # gmau_1 data is as follow + # |A| => 4 + expect(source).to receive(:calculate_metrics_union).with(params.merge(metric_names: 'event3')).and_return(4) + # |B| => 6 + expect(source).to receive(:calculate_metrics_union).with(params.merge(metric_names: 'event5')).and_return(6) + # |A + B| => 8 + expect(source).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event3 event5])).and_return(8) + # Exclusion inclusion principle formula to calculate intersection of 2 sets + # |A & B| = (|A| + |B|) - |A + B| => (4 + 6) - 8 => 2 + expect(source.calculate_metrics_intersections(metric_names: %w[event3 event5], start_date: start_date, end_date: end_date, recorded_at: recorded_at)).to eq(2) + end + end + + context 'with odd number of metrics' do + it 'calculates intersection correctly', :aggregate_failures do + # gmau_2 data is as follow: + # |A| => 2 + expect(source).to receive(:calculate_metrics_union).with(params.merge(metric_names: 'event1')).and_return(2) + # |B| => 3 + expect(source).to receive(:calculate_metrics_union).with(params.merge(metric_names: 'event2')).and_return(3) + # |C| => 5 + expect(source).to receive(:calculate_metrics_union).with(params.merge(metric_names: 'event3')).and_return(5) + + # |A + B| => 4 therefore |A & B| = (|A| + |B|) - |A + B| => 2 + 3 - 4 => 1 + expect(source).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event1 event2])).and_return(4) + # |A + C| => 6 therefore |A & C| = (|A| + |C|) - |A + C| => 2 + 5 - 6 => 1 + expect(source).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event1 event3])).and_return(6) + # |B + C| => 7 therefore |B & C| = (|B| + |C|) - |B + C| => 3 + 5 - 7 => 1 + expect(source).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event2 event3])).and_return(7) + # |A + B + C| => 8 + expect(source).to receive(:calculate_metrics_union).with(params.merge(metric_names: %w[event1 event2 event3])).and_return(8) + # Exclusion inclusion principle formula to calculate intersection of 3 sets + # |A & B & C| = (|A & B| + |A & C| + |B & C|) - (|A| + |B| + |C|) + |A + B + C| + # (1 + 1 + 1) - (2 + 3 + 5) + 8 => 1 + expect(source.calculate_metrics_intersections(metric_names: %w[event1 event2 event3], start_date: start_date, end_date: end_date, recorded_at: recorded_at)).to eq(1) + end + end + end + end + + describe '.aggregated_metrics_data' do + let(:source) do + Class.new do + extend Gitlab::Usage::Metrics::Aggregates::Sources::Calculations::Intersection + end + end + + it 'caches intermediate operations', :aggregate_failures do + events = %w[event1 event2 event3 event5] + + params = { start_date: start_date, end_date: end_date, recorded_at: recorded_at } + + events.each do |event| + expect(source).to receive(:calculate_metrics_union) + .with(params.merge(metric_names: event)) + .once + .and_return(0) + end + + 2.upto(4) do |subset_size| + events.combination(subset_size).each do |events| + expect(source).to receive(:calculate_metrics_union) + .with(params.merge(metric_names: events)) + .once + .and_return(0) + end + end + + expect(source.calculate_metrics_intersections(metric_names: events, start_date: start_date, end_date: end_date, recorded_at: recorded_at)).to eq(0) + end + + it_behaves_like 'aggregated_metrics_data with source' + end +end diff --git a/spec/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll_spec.rb b/spec/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll_spec.rb index db878828cd6..1ae4c9414dd 100644 --- a/spec/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll_spec.rb +++ b/spec/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll_spec.rb @@ -12,11 +12,7 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll, :clean_ let(:metric_2) { 'metric_2' } let(:metric_names) { [metric_1, metric_2] } - describe '.calculate_events_union' do - subject(:calculate_metrics_union) do - described_class.calculate_metrics_union(metric_names: metric_names, start_date: start_date, end_date: end_date, recorded_at: recorded_at) - end - + describe 'metric calculations' do before do [ { @@ -36,23 +32,55 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll, :clean_ end end - it 'returns the number of unique events in the union of all metrics' do - expect(calculate_metrics_union.round(2)).to eq(3.12) - end + describe '.calculate_events_union' do + subject(:calculate_metrics_union) do + described_class.calculate_metrics_union(metric_names: metric_names, start_date: start_date, end_date: end_date, recorded_at: recorded_at) + end + + it 'returns the number of unique events in the union of all metrics' do + expect(calculate_metrics_union.round(2)).to eq(3.12) + end + + context 'when there is no aggregated data saved' do + let(:metric_names) { [metric_1, 'i do not have any records'] } + + it 'raises error when union data is missing' do + expect { calculate_metrics_union }.to raise_error Gitlab::Usage::Metrics::Aggregates::Sources::UnionNotAvailable + end + end - context 'when there is no aggregated data saved' do - let(:metric_names) { [metric_1, 'i do not have any records'] } + context 'when there is only one metric defined as aggregated' do + let(:metric_names) { [metric_1] } - it 'raises error when union data is missing' do - expect { calculate_metrics_union }.to raise_error Gitlab::Usage::Metrics::Aggregates::Sources::UnionNotAvailable + it 'returns the number of unique events for that metric' do + expect(calculate_metrics_union.round(2)).to eq(2.08) + end end end - context 'when there is only one metric defined as aggregated' do - let(:metric_names) { [metric_1] } + describe '.calculate_metrics_intersections' do + subject(:calculate_metrics_intersections) do + described_class.calculate_metrics_intersections(metric_names: metric_names, start_date: start_date, end_date: end_date, recorded_at: recorded_at) + end + + it 'returns the number of common events in the intersection of all metrics' do + expect(calculate_metrics_intersections.round(2)).to eq(1.04) + end + + context 'when there is no aggregated data saved' do + let(:metric_names) { [metric_1, 'i do not have any records'] } - it 'returns the number of unique events for that metric' do - expect(calculate_metrics_union.round(2)).to eq(2.08) + it 'raises error when union data is missing' do + expect { calculate_metrics_intersections }.to raise_error Gitlab::Usage::Metrics::Aggregates::Sources::UnionNotAvailable + end + end + + context 'when there is only one metric defined in aggregate' do + let(:metric_names) { [metric_1] } + + it 'returns the number of common/unique events for the intersection of that metric' do + expect(calculate_metrics_intersections.round(2)).to eq(2.08) + end end end end diff --git a/spec/lib/gitlab/usage/metrics/aggregates/sources/redis_hll_spec.rb b/spec/lib/gitlab/usage/metrics/aggregates/sources/redis_hll_spec.rb index af2de5ea343..83b155b41b1 100644 --- a/spec/lib/gitlab/usage/metrics/aggregates/sources/redis_hll_spec.rb +++ b/spec/lib/gitlab/usage/metrics/aggregates/sources/redis_hll_spec.rb @@ -3,11 +3,12 @@ require 'spec_helper' RSpec.describe Gitlab::Usage::Metrics::Aggregates::Sources::RedisHll do - describe '.calculate_events_union' do - let(:event_names) { %w[event_a event_b] } - let(:start_date) { 7.days.ago } - let(:end_date) { Date.current } + let_it_be(:event_names) { %w[event_a event_b] } + let_it_be(:start_date) { 7.days.ago } + let_it_be(:end_date) { Date.current } + let_it_be(:recorded_at) { Time.current } + describe '.calculate_events_union' do subject(:calculate_metrics_union) do described_class.calculate_metrics_union(metric_names: event_names, start_date: start_date, end_date: end_date, recorded_at: nil) end @@ -26,4 +27,30 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Sources::RedisHll do expect { calculate_metrics_union }.to raise_error Gitlab::Usage::Metrics::Aggregates::Sources::UnionNotAvailable end end + + describe '.calculate_metrics_intersections' do + subject(:calculate_metrics_intersections) do + described_class.calculate_metrics_intersections(metric_names: event_names, start_date: start_date, end_date: end_date, recorded_at: recorded_at) + end + + it 'uses values returned by union to compute the intersection' do + event_names.each do |event| + expect(Gitlab::Usage::Metrics::Aggregates::Sources::RedisHll).to receive(:calculate_metrics_union) + .with(metric_names: event, start_date: start_date, end_date: end_date, recorded_at: recorded_at) + .and_return(5) + end + + expect(Gitlab::Usage::Metrics::Aggregates::Sources::RedisHll).to receive(:calculate_metrics_union) + .with(metric_names: event_names, start_date: start_date, end_date: end_date, recorded_at: recorded_at) + .and_return(2) + + expect(calculate_metrics_intersections).to eq(8) + end + + it 'raises error if union is < 0' do + allow(Gitlab::Usage::Metrics::Aggregates::Sources::RedisHll).to receive(:calculate_metrics_union).and_raise(Gitlab::Usage::Metrics::Aggregates::Sources::UnionNotAvailable) + + expect { calculate_metrics_intersections }.to raise_error(Gitlab::Usage::Metrics::Aggregates::Sources::UnionNotAvailable) + end + end end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_boards_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_boards_metric_spec.rb new file mode 100644 index 00000000000..52c1ccdcd47 --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_boards_metric_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountBoardsMetric do + let_it_be(:board) { create(:board) } + + it_behaves_like 'a correct instrumented metric value', { time_frame: 'all', data_source: 'database' }, 1 +end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_issues_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_issues_metric_spec.rb new file mode 100644 index 00000000000..c3b59904f41 --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_issues_metric_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountIssuesMetric do + let_it_be(:issue) { create(:issue) } + + it_behaves_like 'a correct instrumented metric value', { time_frame: 'all', data_source: 'database' }, 1 +end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb new file mode 100644 index 00000000000..9f4686ab6cd --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_issues_metric_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountUsersCreatingIssuesMetric do + let_it_be(:author) { create(:user) } + let_it_be(:issues) { create_list(:issue, 2, author: author, created_at: 4.days.ago) } + let_it_be(:old_issue) { create(:issue, author: author, created_at: 2.months.ago) } + + context 'with all time frame' do + it_behaves_like 'a correct instrumented metric value', { time_frame: 'all', data_source: 'database' }, 1 + end + + context 'for 28d time frame' do + it_behaves_like 'a correct instrumented metric value', { time_frame: '28d', data_source: 'database' }, 1 + end +end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric_spec.rb new file mode 100644 index 00000000000..7adba825a13 --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_users_using_approve_quick_action_metric_spec.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountUsersUsingApproveQuickActionMetric, :clean_gitlab_redis_shared_state do + before do + Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 1.week.ago) + Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 2.weeks.ago) + Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 2, time: 2.weeks.ago) + Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 2, time: 2.months.ago) + end + + it_behaves_like 'a correct instrumented metric value', { time_frame: '28d', data_source: 'redis_hll' }, 2 + it_behaves_like 'a correct instrumented metric value', { time_frame: '7d', data_source: 'redis_hll' }, 1 +end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/hostname_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/hostname_metric_spec.rb new file mode 100644 index 00000000000..83e07200025 --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/instrumentations/hostname_metric_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Instrumentations::HostnameMetric do + it_behaves_like 'a correct instrumented metric value', { time_frame: 'none', data_source: 'ruby' }, Gitlab.config.gitlab.host +end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/uuid_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/uuid_metric_spec.rb new file mode 100644 index 00000000000..212dd3dc851 --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/instrumentations/uuid_metric_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Instrumentations::UuidMetric do + it_behaves_like 'a correct instrumented metric value', { time_frame: 'none' }, Gitlab::CurrentSettings.uuid +end diff --git a/spec/lib/gitlab/usage/metrics/key_path_processor_spec.rb b/spec/lib/gitlab/usage/metrics/key_path_processor_spec.rb new file mode 100644 index 00000000000..91c27825cce --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/key_path_processor_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::KeyPathProcessor do + describe '#unflatten_default_path' do + using RSpec::Parameterized::TableSyntax + + where(:key_path, :value, :expected_hash) do + 'uuid' | nil | { uuid: nil } + 'uuid' | '1111' | { uuid: '1111' } + 'counts.issues' | nil | { counts: { issues: nil } } + 'counts.issues' | 100 | { counts: { issues: 100 } } + 'usage_activity_by_stage.verify.ci_builds' | 100 | { usage_activity_by_stage: { verify: { ci_builds: 100 } } } + end + + with_them do + subject { described_class.process(key_path, value) } + + it { is_expected.to eq(expected_hash) } + end + end +end |