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..4acf405b --- /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.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) && args[:attributes][@attribute.to_sym].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?(value_to_match.compare(@semver)) + @logger.log_if_debug("[LessThanOrEqualsToSemverMatcher] #{value_to_match} matches -> #{matches}") + matches + end + end +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. # 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..f25b76b3 --- /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.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.11"})).to eq(false) + expect(matcher.match?(:attributes=>{"version": "2.2.0"})).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