From 30232f8632c3d81ffe4db3b2bd93799aefe24517 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Fri, 29 Mar 2024 11:01:04 -0700 Subject: [PATCH 1/3] added less than or equal semver matcher --- lib/splitclient-rb.rb | 1 + .../less_than_or_equal_to_semver_matcher.rb | 31 ++++++++++++++ lib/splitclient-rb/engine/parser/condition.rb | 8 ++++ ...ss_than_or_equal_to_semver_matcher_spec.rb | 40 +++++++++++++++++++ 4 files changed, 80 insertions(+) create mode 100644 lib/splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher.rb create mode 100644 spec/engine/matchers/matches_less_than_or_equal_to_semver_matcher_spec.rb diff --git a/lib/splitclient-rb.rb b/lib/splitclient-rb.rb index 10a12a56..b2fd8c99 100644 --- a/lib/splitclient-rb.rb +++ b/lib/splitclient-rb.rb @@ -93,6 +93,7 @@ require 'splitclient-rb/engine/matchers/semver' require 'splitclient-rb/engine/matchers/equal_to_semver_matcher' require 'splitclient-rb/engine/matchers/greater_than_or_equal_to_semver_matcher' +require 'splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher' require 'splitclient-rb/engine/evaluator/splitter' require 'splitclient-rb/engine/impressions/noop_unique_keys_tracker' require 'splitclient-rb/engine/impressions/unique_keys_tracker' diff --git a/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher.rb b/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher.rb new file mode 100644 index 00000000..eb95702f --- /dev/null +++ b/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module SplitIoClient + class LessThanOrEqualToSemverMatcher < Matcher + MATCHER_TYPE = 'LESS_THAN_OR_EQUAL_TO_SEMVER' + + attr_reader :attribute + + def initialize(attribute, string_value, logger, validator) + super(logger) + @validator = validator + @attribute = attribute + @semver = SplitIoClient::Semver.new(string_value) + @logger = logger + end + + def match?(args) + @logger.log_if_debug('[LessThanOrEqualsToSemverMatcher] evaluating value and attributes.') + return false unless @validator.valid_matcher_arguments(args) + + value_to_match = args[:attributes][@attribute.to_sym] + unless value_to_match.is_a?(String) + @logger.log_if_debug('stringMatcherData is required for LESS_THAN_OR_EQUAL_TO_SEMVER matcher type') + return false + end + matches = [0, -1].include?(@semver.compare(SplitIoClient::Semver.new(value_to_match))) + @logger.log_if_debug("[LessThanOrEqualsToSemverMatcher] #{value_to_match} matches -> #{matches}") + matches + end + end +end diff --git a/lib/splitclient-rb/engine/parser/condition.rb b/lib/splitclient-rb/engine/parser/condition.rb index 1670ecde..cd99225b 100644 --- a/lib/splitclient-rb/engine/parser/condition.rb +++ b/lib/splitclient-rb/engine/parser/condition.rb @@ -205,6 +205,14 @@ def matcher_greater_than_or_equal_to_semver(params) ) end + def matcher_less_than_or_equal_to_semver(params) + LessThanOrEqualToSemverMatcher.new( + params[:matcher][:keySelector][:attribute], + params[:matcher][:stringMatcherData], + @config.split_logger, @config.split_validator + ) + end + # # @return [object] the negate value for this condition def negate diff --git a/spec/engine/matchers/matches_less_than_or_equal_to_semver_matcher_spec.rb b/spec/engine/matchers/matches_less_than_or_equal_to_semver_matcher_spec.rb new file mode 100644 index 00000000..0a8bc6d3 --- /dev/null +++ b/spec/engine/matchers/matches_less_than_or_equal_to_semver_matcher_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe SplitIoClient::LessThanOrEqualToSemverMatcher do + let(:raw) { { + 'negate': false, + 'matcherType': 'LESS_THAN_OR_EQUAL_TO_SEMVER', + 'stringMatcherData': "2.1.8" + } } + let(:config) { SplitIoClient::SplitConfig.new } + + it 'initilized params' do + matcher = described_class.new("version", raw[:stringMatcherData], config.split_logger, config.split_validator) + expect(matcher.attribute).to eq("version") + semver = matcher.instance_variable_get(:@semver) + expect(semver.instance_variable_get(:@old_version)).to eq("2.1.8") + end + + it 'matches' do + matcher = described_class.new("version", raw[:stringMatcherData], config.split_logger, config.split_validator) + expect(matcher.match?(:attributes=>{"version": "2.1.8+rc"})).to eq(true) + expect(matcher.match?(:attributes=>{"version": "2.1.8"})).to eq(true) + expect(matcher.match?(:attributes=>{"version": "2.1.11"})).to eq(true) + expect(matcher.match?(:attributes=>{"version": "2.2.0"})).to eq(true) + end + + it 'does not match' do + matcher = described_class.new("version", raw[:stringMatcherData], config.split_logger, config.split_validator) + expect(matcher.match?(:attributes=>{"version": "2.1.5"})).to eq(false) + expect(matcher.match?(:attributes=>{"version": "2.1.5-rc1"})).to eq(false) + end + + it 'invalid attribute' do + matcher = described_class.new("version", raw[:stringMatcherData], config.split_logger, config.split_validator) + expect(matcher.match?(:attributes=>{"version": 2.1})).to eq(false) + expect(matcher.match?(:attributes=>{"version": nil})).to eq(false) + end + +end From e9677d93fcfd2fa38f726fde1bb8d2f87b66536a Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 1 Apr 2024 10:14:54 -0700 Subject: [PATCH 2/3] fixed matcher logic --- .../matchers/less_than_or_equal_to_semver_matcher.rb | 2 +- .../matches_less_than_or_equal_to_semver_matcher_spec.rb | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher.rb b/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher.rb index eb95702f..95c55f73 100644 --- a/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher.rb +++ b/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher.rb @@ -23,7 +23,7 @@ def match?(args) @logger.log_if_debug('stringMatcherData is required for LESS_THAN_OR_EQUAL_TO_SEMVER matcher type') return false end - matches = [0, -1].include?(@semver.compare(SplitIoClient::Semver.new(value_to_match))) + matches = [0, -1].include?(SplitIoClient::Semver.new(value_to_match).compare(@semver)) @logger.log_if_debug("[LessThanOrEqualsToSemverMatcher] #{value_to_match} matches -> #{matches}") matches end diff --git a/spec/engine/matchers/matches_less_than_or_equal_to_semver_matcher_spec.rb b/spec/engine/matchers/matches_less_than_or_equal_to_semver_matcher_spec.rb index 0a8bc6d3..f25b76b3 100644 --- a/spec/engine/matchers/matches_less_than_or_equal_to_semver_matcher_spec.rb +++ b/spec/engine/matchers/matches_less_than_or_equal_to_semver_matcher_spec.rb @@ -21,14 +21,14 @@ matcher = described_class.new("version", raw[:stringMatcherData], config.split_logger, config.split_validator) expect(matcher.match?(:attributes=>{"version": "2.1.8+rc"})).to eq(true) expect(matcher.match?(:attributes=>{"version": "2.1.8"})).to eq(true) - expect(matcher.match?(:attributes=>{"version": "2.1.11"})).to eq(true) - expect(matcher.match?(:attributes=>{"version": "2.2.0"})).to eq(true) + expect(matcher.match?(:attributes=>{"version": "2.1.5"})).to eq(true) + expect(matcher.match?(:attributes=>{"version": "2.1.5-rc1"})).to eq(true) end it 'does not match' do matcher = described_class.new("version", raw[:stringMatcherData], config.split_logger, config.split_validator) - expect(matcher.match?(:attributes=>{"version": "2.1.5"})).to eq(false) - expect(matcher.match?(:attributes=>{"version": "2.1.5-rc1"})).to eq(false) + expect(matcher.match?(:attributes=>{"version": "2.1.11"})).to eq(false) + expect(matcher.match?(:attributes=>{"version": "2.2.0"})).to eq(false) end it 'invalid attribute' do From 1e4a23822cde2b9cd8adf3f6ee1cdc7a6f9b4ec8 Mon Sep 17 00:00:00 2001 From: Bilal Al Date: Mon, 8 Apr 2024 19:09:35 -0700 Subject: [PATCH 3/3] used build for semver class --- .../less_than_or_equal_to_semver_matcher.rb | 10 +++++----- lib/splitclient-rb/engine/matchers/semver.rb | 17 +++++++++++++---- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher.rb b/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher.rb index 95c55f73..4acf405b 100644 --- a/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher.rb +++ b/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher.rb @@ -10,20 +10,20 @@ def initialize(attribute, string_value, logger, validator) super(logger) @validator = validator @attribute = attribute - @semver = SplitIoClient::Semver.new(string_value) + @semver = SplitIoClient::Semver.build(string_value, logger) @logger = logger end def match?(args) @logger.log_if_debug('[LessThanOrEqualsToSemverMatcher] evaluating value and attributes.') - return false unless @validator.valid_matcher_arguments(args) + return false unless @validator.valid_matcher_arguments(args) && args[:attributes][@attribute.to_sym].is_a?(String) - value_to_match = args[:attributes][@attribute.to_sym] - unless value_to_match.is_a?(String) + value_to_match = SplitIoClient::Semver.build(args[:attributes][@attribute.to_sym], @logger) + unless !value_to_match.nil? && !@semver.nil? @logger.log_if_debug('stringMatcherData is required for LESS_THAN_OR_EQUAL_TO_SEMVER matcher type') return false end - matches = [0, -1].include?(SplitIoClient::Semver.new(value_to_match).compare(@semver)) + matches = [0, -1].include?(value_to_match.compare(@semver)) @logger.log_if_debug("[LessThanOrEqualsToSemverMatcher] #{value_to_match} matches -> #{matches}") matches end diff --git a/lib/splitclient-rb/engine/matchers/semver.rb b/lib/splitclient-rb/engine/matchers/semver.rb index ac9b7a58..92d9a6a8 100644 --- a/lib/splitclient-rb/engine/matchers/semver.rb +++ b/lib/splitclient-rb/engine/matchers/semver.rb @@ -8,10 +8,6 @@ class Semver attr_reader :major, :minor, :patch, :pre_release, :is_stable, :old_version - # - # Class Initializer - # - # @param version [String] raw version as read from splitChanges response. def initialize(version) @major = 0 @minor = 0 @@ -22,6 +18,19 @@ def initialize(version) parse end + # + # Class builder + # + # @param version [String] raw version as read from splitChanges response. + # + # @return [type] Semver instance + def self.build(version, logger) + new(version) + rescue RuntimeError => e + logger.warn("Failed to parse Semver data: #{e}") + nil + end + # # Check if there is any metadata characters in self._old_version. #