diff --git a/CHANGES.txt b/CHANGES.txt index a1ddf824..a1b3e034 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,9 @@ CHANGES +8.4.0 (May 3, 2024) +- Fixed issue preventing Impressopns and Events posting if client.destroy is called before the post threads started +- Added support for targeting rules based on semantic versions (https://semver.org/). + 8.3.1 (Mar 22, 2024) - Fixed ruby process hanging due to failed thread.join command, when calling destroy and a http request still active. - Fixed streaming notification parser. Issue ref: https://github.com/splitio/ruby-client/issues/511 diff --git a/lib/splitclient-rb.rb b/lib/splitclient-rb.rb index 642db7d5..94386cf8 100644 --- a/lib/splitclient-rb.rb +++ b/lib/splitclient-rb.rb @@ -90,6 +90,12 @@ require 'splitclient-rb/engine/matchers/equal_to_boolean_matcher' require 'splitclient-rb/engine/matchers/equal_to_matcher' require 'splitclient-rb/engine/matchers/matches_string_matcher' +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/matchers/between_semver_matcher' +require 'splitclient-rb/engine/matchers/in_list_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' @@ -105,6 +111,8 @@ require 'splitclient-rb/engine/synchronizer' require 'splitclient-rb/utilitites' +require 'splitclient-rb/spec.rb' + # SSE require 'splitclient-rb/sse/event_source/client' require 'splitclient-rb/sse/event_source/event_parser' diff --git a/lib/splitclient-rb/cache/repositories/events/memory_repository.rb b/lib/splitclient-rb/cache/repositories/events/memory_repository.rb index 93339e8c..f38e238f 100644 --- a/lib/splitclient-rb/cache/repositories/events/memory_repository.rb +++ b/lib/splitclient-rb/cache/repositories/events/memory_repository.rb @@ -29,6 +29,10 @@ def clear @adapter.clear end + def empty? + @adapter.empty? + end + def batch return [] if @config.events_queue_size.zero? diff --git a/lib/splitclient-rb/cache/repositories/events_repository.rb b/lib/splitclient-rb/cache/repositories/events_repository.rb index 307f22ea..75c3e7c7 100644 --- a/lib/splitclient-rb/cache/repositories/events_repository.rb +++ b/lib/splitclient-rb/cache/repositories/events_repository.rb @@ -25,6 +25,10 @@ def post_events @config.log_found_exception(__method__.to_s, e) end + def empty? + @repository.empty? + end + protected def metadata diff --git a/lib/splitclient-rb/cache/repositories/splits_repository.rb b/lib/splitclient-rb/cache/repositories/splits_repository.rb index 3f17a0c7..e98e0d84 100644 --- a/lib/splitclient-rb/cache/repositories/splits_repository.rb +++ b/lib/splitclient-rb/cache/repositories/splits_repository.rb @@ -5,6 +5,32 @@ module Cache module Repositories class SplitsRepository < Repository attr_reader :adapter + DEFAULT_CONDITIONS_TEMPLATE = [{ + conditionType: "ROLLOUT", + matcherGroup: { + combiner: "AND", + matchers: [ + { + keySelector: nil, + matcherType: "ALL_KEYS", + negate: false, + userDefinedSegmentMatcherData: nil, + whitelistMatcherData: nil, + unaryNumericMatcherData: nil, + betweenMatcherData: nil, + dependencyMatcherData: nil, + booleanMatcherData: nil, + stringMatcherData: nil + }] + }, + partitions: [ + { + treatment: "control", + size: 100 + } + ], + label: "targeting rule type unsupported by sdk" + }] def initialize(config, flag_sets_repository, flag_set_filter) super(config) @@ -155,6 +181,10 @@ def add_feature_flag(split) remove_from_flag_sets(existing_split) end + if check_undefined_matcher(split) + @config.logger.warn("Feature Flag #{split[:name]} has undefined matcher, setting conditions to default template.") + split[:conditions] = SplitsRepository::DEFAULT_CONDITIONS_TEMPLATE + end if !split[:sets].nil? for flag_set in split[:sets] if !@flag_sets.flag_set_exist?(flag_set) @@ -170,6 +200,18 @@ def add_feature_flag(split) @adapter.set_string(namespace_key(".split.#{split[:name]}"), split.to_json) end + def check_undefined_matcher(split) + for condition in split[:conditions] + for matcher in condition[:matcherGroup][:matchers] + if !SplitIoClient::Condition.instance_methods(false).map(&:to_s).include?("matcher_#{matcher[:matcherType].downcase}") + @config.logger.error("Detected undefined matcher #{matcher[:matcherType].downcase} in feature flag #{split[:name]}") + return true + end + end + end + return false + end + def remove_feature_flag(split) decrease_tt_name_count(split[:trafficTypeName]) remove_from_flag_sets(split) diff --git a/lib/splitclient-rb/clients/split_client.rb b/lib/splitclient-rb/clients/split_client.rb index 322efd30..2b2eed6c 100644 --- a/lib/splitclient-rb/clients/split_client.rb +++ b/lib/splitclient-rb/clients/split_client.rb @@ -96,7 +96,16 @@ def get_treatments_with_config_by_flag_sets(key, flag_sets, attributes = {}) def destroy @config.logger.info('Split client shutdown started...') if @config.debug_enabled - + if !@config.cache_adapter.is_a?(SplitIoClient::Cache::Adapters::RedisAdapter) && @config.impressions_mode != :none && + (!@impressions_repository.empty? || !@events_repository.empty?) + @config.logger.debug("Impressions and/or Events cache is not empty") + # Adding small delay to ensure sender threads are fully running + sleep(0.1) + if !@config.threads.key?(:impressions_sender) || !@config.threads.key?(:events_sender) + @config.logger.debug("Periodic data recording thread has not started yet, waiting for service startup.") + @config.threads[:start_sdk].join(5) if @config.threads.key?(:start_sdk) + end + end @config.threads.select { |name, thread| name.to_s.end_with? 'sender' }.values.each do |thread| thread.raise(SplitIoClient::SDKShutdownException) thread.join diff --git a/lib/splitclient-rb/engine/api/client.rb b/lib/splitclient-rb/engine/api/client.rb index 9ddaf94c..65dcd027 100644 --- a/lib/splitclient-rb/engine/api/client.rb +++ b/lib/splitclient-rb/engine/api/client.rb @@ -10,6 +10,7 @@ def initialize(config) end def get_api(url, api_key, params = {}, cache_control_headers = false) + api_client.options.params_encoder.sort_params = false api_client.get(url, params) do |req| req.headers = common_headers(api_key).merge('Accept-Encoding' => 'gzip') req.headers = req.headers.merge('Cache-Control' => 'no-cache') if cache_control_headers @@ -29,7 +30,7 @@ def post_api(url, api_key, data, headers = {}, params = {}) req.headers = common_headers(api_key) .merge('Content-Type' => 'application/json') .merge(headers) - + machine_ip = @config.machine_ip machine_name = @config.machine_name @@ -55,6 +56,7 @@ def api_client @api_client ||= Faraday.new do |builder| builder.use SplitIoClient::FaradayMiddleware::Gzip builder.adapter :net_http_persistent + builder.options.params_encoder = Faraday::FlatParamsEncoder end end diff --git a/lib/splitclient-rb/engine/api/splits.rb b/lib/splitclient-rb/engine/api/splits.rb index 2bcb804c..b4d17bda 100644 --- a/lib/splitclient-rb/engine/api/splits.rb +++ b/lib/splitclient-rb/engine/api/splits.rb @@ -4,6 +4,7 @@ module SplitIoClient module Api # Retrieves split definitions from the Split Backend class Splits < Client + def initialize(api_key, config, telemetry_runtime_producer) super(config) @api_key = api_key @@ -11,12 +12,12 @@ def initialize(api_key, config, telemetry_runtime_producer) @flag_sets_filter = @config.flag_sets_filter end - def since(since, fetch_options = { cache_control_headers: false, till: nil, sets: nil }) + def since(since, fetch_options = { cache_control_headers: false, till: nil, sets: nil}) start = Time.now - params = { since: since } - params[:till] = fetch_options[:till] unless fetch_options[:till].nil? + params = { s: SplitIoClient::Spec::FeatureFlags::SPEC_VERSION, since: since } params[:sets] = @flag_sets_filter.join(",") unless @flag_sets_filter.empty? + params[:till] = fetch_options[:till] unless fetch_options[:till].nil? @config.logger.debug("Fetching from splitChanges with #{params}: ") response = get_api("#{@config.base_uri}/splitChanges", @api_key, params, fetch_options[:cache_control_headers]) if response.status == 414 diff --git a/lib/splitclient-rb/engine/auth_api_client.rb b/lib/splitclient-rb/engine/auth_api_client.rb index e0d7a903..475842a2 100644 --- a/lib/splitclient-rb/engine/auth_api_client.rb +++ b/lib/splitclient-rb/engine/auth_api_client.rb @@ -14,7 +14,7 @@ def initialize(config, telemetry_runtime_producer) def authenticate(api_key) start = Time.now - response = @api_client.get_api(@config.auth_service_url, api_key) + response = @api_client.get_api("#{@config.auth_service_url}?s=#{SplitIoClient::Spec::FeatureFlags::SPEC_VERSION}", api_key) return process_success(response, start) if response.success? diff --git a/lib/splitclient-rb/engine/matchers/between_semver_matcher.rb b/lib/splitclient-rb/engine/matchers/between_semver_matcher.rb new file mode 100644 index 00000000..71bd072b --- /dev/null +++ b/lib/splitclient-rb/engine/matchers/between_semver_matcher.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module SplitIoClient + class BetweenSemverMatcher < Matcher + MATCHER_TYPE = 'BETWEEN_SEMVER' + + attr_reader :attribute + + def initialize(attribute, start_value, end_value, logger, validator) + super(logger) + @validator = validator + @attribute = attribute + @semver_start = SplitIoClient::Semver.build(start_value, logger) + @semver_end = SplitIoClient::Semver.build(end_value, logger) + @logger = logger + end + + def match?(args) + return false unless verify_semver_arg?(args, 'BetweenSemverMatcher') + + value_to_match = SplitIoClient::Semver.build(args[:attributes][@attribute.to_sym], @logger) + if value_to_match.nil? || @semver_start.nil? || @semver_end.nil? + @logger.error('betweenStringMatcherData is required for BETWEEN_SEMVER matcher type') + return false + + end + matches = ([0, -1].include?(@semver_start.compare(value_to_match)) && + [0, 1].include?(@semver_end.compare(value_to_match))) + @logger.debug("[BetweenMatcher] #{value_to_match} matches -> #{matches}") + matches + end + end +end diff --git a/lib/splitclient-rb/engine/matchers/equal_to_semver_matcher.rb b/lib/splitclient-rb/engine/matchers/equal_to_semver_matcher.rb new file mode 100644 index 00000000..476467b3 --- /dev/null +++ b/lib/splitclient-rb/engine/matchers/equal_to_semver_matcher.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module SplitIoClient + class EqualToSemverMatcher < Matcher + MATCHER_TYPE = '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) + return false unless verify_semver_arg?(args, 'EqualsToSemverMatcher') + + value_to_match = SplitIoClient::Semver.build(args[:attributes][@attribute.to_sym], @logger) + return false unless check_semver_value_to_match(value_to_match, MATCHER_TYPE) + + matches = (@semver.version == value_to_match.version) + @logger.debug("[EqualsToSemverMatcher] #{value_to_match} matches -> #{matches}") + matches + end + end +end diff --git a/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_semver_matcher.rb b/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_semver_matcher.rb new file mode 100644 index 00000000..7f11f8df --- /dev/null +++ b/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_semver_matcher.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module SplitIoClient + class GreaterThanOrEqualToSemverMatcher < Matcher + MATCHER_TYPE = 'GREATER_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) + return false unless verify_semver_arg?(args, 'GreaterThanOrEqualsToSemverMatcher') + + value_to_match = SplitIoClient::Semver.build(args[:attributes][@attribute.to_sym], @logger) + return false unless check_semver_value_to_match(value_to_match, MATCHER_TYPE) + + matches = [0, 1].include?(value_to_match.compare(@semver)) + @logger.debug("[GreaterThanOrEqualsToSemverMatcher] #{value_to_match} matches -> #{matches}") + matches + end + end +end diff --git a/lib/splitclient-rb/engine/matchers/in_list_semver_matcher.rb b/lib/splitclient-rb/engine/matchers/in_list_semver_matcher.rb new file mode 100644 index 00000000..7b411ae7 --- /dev/null +++ b/lib/splitclient-rb/engine/matchers/in_list_semver_matcher.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module SplitIoClient + class InListSemverMatcher < Matcher + MATCHER_TYPE = 'IN_LIST_SEMVER' + + attr_reader :attribute + + def initialize(attribute, list_value, logger, validator) + super(logger) + @validator = validator + @attribute = attribute + @semver_list = [] + + list_value.map do |item| + version = SplitIoClient::Semver.build(item, logger) + @semver_list << version unless version.nil? + end + @logger = logger + end + + def match?(args) + return false if @semver_list.empty? || !verify_semver_arg?(args, 'InListSemverMatcher') + + value_to_match = SplitIoClient::Semver.build(args[:attributes][@attribute.to_sym], @logger) + if value_to_match.nil? + @logger.error('whitelistMatcherData is required for IN_LIST_SEMVER matcher type') + return false + + end + matches = (@semver_list.map { |item| item.version == value_to_match.version }).any? { |item| item == true } + @logger.debug("[InListSemverMatcher] #{value_to_match} matches -> #{matches}") + matches + end + end +end 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..5ca527c5 --- /dev/null +++ b/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher.rb @@ -0,0 +1,28 @@ +# 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) + return false unless verify_semver_arg?(args, 'LessThanOrEqualsToSemverMatcher') + + value_to_match = SplitIoClient::Semver.build(args[:attributes][@attribute.to_sym], @logger) + return false unless check_semver_value_to_match(value_to_match, MATCHER_TYPE) + + matches = [0, -1].include?(value_to_match.compare(@semver)) + @logger.debug("[LessThanOrEqualsToSemverMatcher] #{value_to_match} matches -> #{matches}") + matches + end + end +end diff --git a/lib/splitclient-rb/engine/matchers/matcher.rb b/lib/splitclient-rb/engine/matchers/matcher.rb index 9f7a43d6..2a54bf00 100644 --- a/lib/splitclient-rb/engine/matchers/matcher.rb +++ b/lib/splitclient-rb/engine/matchers/matcher.rb @@ -30,5 +30,23 @@ def equals?(obj) def string_type? false end + + private + + def verify_semver_arg?(args, matcher_name) + @logger.debug("[#{matcher_name}] evaluating value and attributes.") + return false unless @validator.valid_matcher_arguments(args) + + true + end + + def check_semver_value_to_match(value_to_match, matcher_spec_name) + if value_to_match.nil? || @semver.nil? + @logger.error("stringMatcherData is required for #{matcher_spec_name} matcher type") + return false + + end + true + end end end diff --git a/lib/splitclient-rb/engine/matchers/semver.rb b/lib/splitclient-rb/engine/matchers/semver.rb new file mode 100644 index 00000000..ddc7c4ac --- /dev/null +++ b/lib/splitclient-rb/engine/matchers/semver.rb @@ -0,0 +1,201 @@ +# frozen_string_literal: true + +module SplitIoClient + class Semver + METADATA_DELIMITER = '+' + PRE_RELEASE_DELIMITER = '-' + VALUE_DELIMITER = '.' + + attr_reader :major, :minor, :patch, :pre_release, :is_stable, :version + + def initialize(version) + @major = 0 + @minor = 0 + @patch = 0 + @pre_release = [] + @is_stable = false + @version = '' + @metadata = '' + parse(version) + 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 NoMethodError => e + logger.error("Failed to parse Semver data, incorrect data type: #{e}") + nil + rescue StandardError => e + logger.error("Failed to parse Semver data: #{e}") + nil + end + + # + # Check if there is any metadata characters in version. + # + # @return [type] String semver without the metadata + # + def remove_metadata_if_exists(old_version) + index = old_version.index(METADATA_DELIMITER) + return old_version if index.nil? + + @metadata = old_version[index + 1, old_version.length] + old_version[0, index] + end + + # Compare the current Semver object to a given Semver object, return: + # 0: if self == passed + # 1: if self > passed + # -1: if self < passed + # + # @param to_compare [trype] splitio.models.grammar.matchers.semver.Semver object + # + # @returns [Integer] based on comparison + def compare(to_compare) + return 0 if @version == to_compare.version + + # Compare major, minor, and patch versions numerically + result = compare_attributes(to_compare) + return result if result != 0 + + # Compare pre-release versions lexically + compare_pre_release(to_compare) + end + + private + + def integer?(value) + !!value.match(/^(\d)+$/) + end + + # + # Parse the string in version to update the other internal variables + # + def parse(old_version) + without_metadata = remove_metadata_if_exists(old_version) + + index = without_metadata.index(PRE_RELEASE_DELIMITER) + if index.nil? + @is_stable = true + else + pre_release_data = without_metadata[index + 1..-1] + without_metadata = without_metadata[0, index] + @pre_release = pre_release_data.split(VALUE_DELIMITER) + end + assign_major_minor_and_patch(without_metadata) + end + + # + # Set the major, minor and patch internal variables based on string passed. + # + # @param version [String] raw version containing major.minor.patch numbers. + def assign_major_minor_and_patch(version) + parts = version.split(VALUE_DELIMITER) + if parts.length != 3 || + !(integer?(parts[0]) && + integer?(parts[1]) && + integer?(parts[2])) + raise "Unable to convert to Semver, incorrect format: #{version}" + end + + @major = parts[0].to_i + @minor = parts[1].to_i + @patch = parts[2].to_i + @version = "#{@major}#{VALUE_DELIMITER}#{@minor}#{VALUE_DELIMITER}#{@patch}" + @version += parse_pre_release + @version += "#{METADATA_DELIMITER}#{@metadata}" unless @metadata.empty? + end + + def parse_pre_release + return '' if @pre_release.empty? + + pre_parsed = [] + @pre_release.each do |pre_digit| + pre_digit = pre_digit.to_i if integer?(pre_digit) + pre_parsed << pre_digit + end + "#{PRE_RELEASE_DELIMITER}#{pre_parsed.join('.')}" + end + + # + # Compare 2 variables and return int as follows: + # 0: if var1 == var2 + # 1: if var1 > var2 + # -1: if var1 < var2 + # + # @param var1 [type] String/Integer object that accept ==, < or > operators + # @param var2 [type] String/Integer object that accept ==, < or > operators + # + # @returns [Integer] based on comparison + def compare_vars(var1, var2) + return 0 if var1 == var2 + + return 1 if var1 > var2 + + -1 + end + + # Compare the current Semver object's major, minor, patch and is_stable attributes to a given Semver object, return: + # 0: if self == passed + # 1: if self > passed + # -1: if self < passed + # + # @param to_compare [trype] splitio.models.grammar.matchers.semver.Semver object + # + # @returns [Integer] based on comparison + def compare_attributes(to_compare) + result = compare_vars(@major, to_compare.major) + return result if result != 0 + + result = compare_vars(@minor, to_compare.minor) + return result if result != 0 + + result = compare_vars(@patch, to_compare.patch) + return result if result != 0 + + return -1 if !@is_stable && to_compare.is_stable + + return 1 if @is_stable && !to_compare.is_stable + + 0 + end + + # Compare the current Semver object's pre_release attribute to a given Semver object, return: + # 0: if self == passed + # 1: if self > passed + # -1: if self < passed + # + # @param to_compare [trype] splitio.models.grammar.matchers.semver.Semver object + # + # @returns [Integer] based on comparison + def compare_pre_release(to_compare) + min_length = get_pre_min_length(to_compare) + 0.upto(min_length - 1) do |i| + next if @pre_release[i] == to_compare.pre_release[i] + + if integer?(@pre_release[i]) && integer?(to_compare.pre_release[i]) + return compare_vars(@pre_release[i].to_i, to_compare.pre_release[i].to_i) + + end + + return compare_vars(@pre_release[i], to_compare.pre_release[i]) + end + # Compare lengths of pre-release versions + compare_vars(@pre_release.length, to_compare.pre_release.length) + end + + # Get minimum of current Semver object's pre_release attributes length to a given Semver object + # + # @param to_compare [trype] splitio.models.grammar.matchers.semver.Semver object + # + # @returns [Integer] + def get_pre_min_length(to_compare) + [@pre_release.length, to_compare.pre_release.length].min + end + end +end diff --git a/lib/splitclient-rb/engine/parser/condition.rb b/lib/splitclient-rb/engine/parser/condition.rb index f80fbffb..b5d7567b 100644 --- a/lib/splitclient-rb/engine/parser/condition.rb +++ b/lib/splitclient-rb/engine/parser/condition.rb @@ -189,6 +189,47 @@ def matcher_matches_string(params) ) end + def matcher_equal_to_semver(params) + EqualToSemverMatcher.new( + params[:matcher][:keySelector][:attribute], + params[:matcher][:stringMatcherData], + @config.split_logger, @config.split_validator + ) + end + + def matcher_greater_than_or_equal_to_semver(params) + GreaterThanOrEqualToSemverMatcher.new( + params[:matcher][:keySelector][:attribute], + params[:matcher][:stringMatcherData], + @config.split_logger, @config.split_validator + ) + 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 + + def matcher_between_semver(params) + BetweenSemverMatcher.new( + params[:matcher][:keySelector][:attribute], + params[:matcher][:betweenStringMatcherData][:start], + params[:matcher][:betweenStringMatcherData][:end], + @config.split_logger, @config.split_validator + ) + end + + def matcher_in_list_semver(params) + InListSemverMatcher.new( + params[:matcher][:keySelector][:attribute], + params[:matcher][:whitelistMatcherData][:whitelist], + @config.split_logger, @config.split_validator + ) + end + # # @return [object] the negate value for this condition def negate diff --git a/lib/splitclient-rb/spec.rb b/lib/splitclient-rb/spec.rb new file mode 100644 index 00000000..bd991ccc --- /dev/null +++ b/lib/splitclient-rb/spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module SplitIoClient + module Spec + class FeatureFlags + SPEC_VERSION = "1.1" + end + end +end diff --git a/lib/splitclient-rb/split_logger.rb b/lib/splitclient-rb/split_logger.rb index 5a82b0ce..fa901744 100644 --- a/lib/splitclient-rb/split_logger.rb +++ b/lib/splitclient-rb/split_logger.rb @@ -11,5 +11,13 @@ def log_if_debug(message) def log_if_transport(message) @config.logger.debug(message) if @config.transport_debug_enabled end + + def error(message) + @config.logger.error(message) + end + + def debug(message) + @config.logger.debug(message) if @config.debug_enabled + end end end diff --git a/lib/splitclient-rb/sse/notification_manager_keeper.rb b/lib/splitclient-rb/sse/notification_manager_keeper.rb index 451f9009..33ff2b96 100644 --- a/lib/splitclient-rb/sse/notification_manager_keeper.rb +++ b/lib/splitclient-rb/sse/notification_manager_keeper.rb @@ -14,8 +14,8 @@ def initialize(config, telemetry_runtime_producer, status_queue) @telemetry_runtime_producer = telemetry_runtime_producer @status_queue = status_queue @publisher_available = Concurrent::AtomicBoolean.new(true) - @publishers_pri = Concurrent::AtomicFixnum.new - @publishers_sec = Concurrent::AtomicFixnum.new + @publishers_pri = Concurrent::AtomicFixnum.new(2) + @publishers_sec = Concurrent::AtomicFixnum.new(2) end def handle_incoming_occupancy_event(event) diff --git a/lib/splitclient-rb/version.rb b/lib/splitclient-rb/version.rb index b330c8de..1cd7e252 100644 --- a/lib/splitclient-rb/version.rb +++ b/lib/splitclient-rb/version.rb @@ -1,3 +1,3 @@ module SplitIoClient - VERSION = '8.3.1' + VERSION = '8.4.0' end diff --git a/spec/cache/fetchers/segment_fetch_spec.rb b/spec/cache/fetchers/segment_fetch_spec.rb index e49c788a..f816f445 100644 --- a/spec/cache/fetchers/segment_fetch_spec.rb +++ b/spec/cache/fetchers/segment_fetch_spec.rb @@ -26,7 +26,7 @@ stub_request(:get, 'https://sdk.split.io/api/segmentChanges/employees?since=1473863075059') .to_return(status: 200, body: segments_json2) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: splits_with_segments_json) end diff --git a/spec/cache/fetchers/split_fetch_spec.rb b/spec/cache/fetchers/split_fetch_spec.rb index 2d320734..957d4101 100644 --- a/spec/cache/fetchers/split_fetch_spec.rb +++ b/spec/cache/fetchers/split_fetch_spec.rb @@ -11,7 +11,7 @@ end before do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: active_splits_json) end @@ -48,7 +48,7 @@ active_split = store.splits_repository.splits['test_1_ruby'] expect(active_split[:status]).to eq('ACTIVE') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1473413807667') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1473413807667') .to_return(status: 200, body: archived_splits_json) store.send(:fetch_splits) @@ -81,7 +81,7 @@ let(:store) { described_class.new(splits_repository, '', config, telemetry_runtime_producer) } before do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?sets=set_2&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1&sets=set_2') .to_return(status: 200, body: active_splits_json) end @@ -103,14 +103,14 @@ expect(store.splits_repository.get_split('sample_feature')[:name]).to eq('sample_feature') expect(store.splits_repository.get_split('test_1_ruby')).to eq(nil) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?sets=set_2&since=1473413807667') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1473413807667&sets=set_2') .to_return(status: 200, body: archived_splits_json) store.send(:fetch_splits) expect(store.splits_repository.get_split('sample_feature')).to eq(nil) store.splits_repository.set_change_number(-1) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?sets=set_2&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1&sets=set_2') .to_return(status: 200, body: active_splits_json) store.send(:fetch_splits) @@ -149,7 +149,7 @@ active_split = store.splits_repository.splits['test_1_ruby'] expect(active_split[:status]).to eq('ACTIVE') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1473413807667') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1473413807667') .to_return(status: 200, body: archived_splits_json) store.send(:fetch_splits) diff --git a/spec/cache/repositories/splits_repository_spec.rb b/spec/cache/repositories/splits_repository_spec.rb index 351ed30d..b55bfd11 100644 --- a/spec/cache/repositories/splits_repository_spec.rb +++ b/spec/cache/repositories/splits_repository_spec.rb @@ -17,9 +17,9 @@ before do # in memory setup - repository.update([{name: 'foo', trafficTypeName: 'tt_name_1'}, - {name: 'bar', trafficTypeName: 'tt_name_2'}, - {name: 'baz', trafficTypeName: 'tt_name_1'}], [], -1) + repository.update([{name: 'foo', trafficTypeName: 'tt_name_1', conditions: []}, + {name: 'bar', trafficTypeName: 'tt_name_2', conditions: []}, + {name: 'baz', trafficTypeName: 'tt_name_1', conditions: []}], [], -1) # redis setup repository.instance_variable_get(:@adapter).set_string( @@ -31,13 +31,13 @@ end after do - repository.update([], [{name: 'foo', trafficTypeName: 'tt_name_1'}, - {name: 'bar', trafficTypeName: 'tt_name_2'}, - {name: 'bar', trafficTypeName: 'tt_name_2'}, - {name: 'qux', trafficTypeName: 'tt_name_3'}, - {name: 'quux', trafficTypeName: 'tt_name_4'}, - {name: 'corge', trafficTypeName: 'tt_name_5'}, - {name: 'corge', trafficTypeName: 'tt_name_6'}], -1) + repository.update([], [{name: 'foo', trafficTypeName: 'tt_name_1', conditions: []}, + {name: 'bar', trafficTypeName: 'tt_name_2', conditions: []}, + {name: 'bar', trafficTypeName: 'tt_name_2', conditions: []}, + {name: 'qux', trafficTypeName: 'tt_name_3', conditions: []}, + {name: 'quux', trafficTypeName: 'tt_name_4', conditions: []}, + {name: 'corge', trafficTypeName: 'tt_name_5', conditions: []}, + {name: 'corge', trafficTypeName: 'tt_name_6', conditions: []}], -1) end it 'returns splits names' do @@ -52,7 +52,7 @@ expect(repository.traffic_type_exists('tt_name_1')).to be true expect(repository.traffic_type_exists('tt_name_2')).to be true - split = { name: 'qux', trafficTypeName: 'tt_name_3' } + split = { name: 'qux', trafficTypeName: 'tt_name_3', conditions: [] } repository.update([split], [], -1) repository.update([], [split], -1) @@ -61,7 +61,7 @@ end it 'does not increment traffic type count when adding same split twice' do - split = { name: 'quux', trafficTypeName: 'tt_name_4' } + split = { name: 'quux', trafficTypeName: 'tt_name_4', conditions: [] } repository.update([split, split], [], -1) repository.update([], [split], -1) @@ -70,7 +70,7 @@ end it 'updates traffic type count accordingly when split changes traffic type' do - split = { name: 'corge', trafficTypeName: 'tt_name_5' } + split = { name: 'corge', trafficTypeName: 'tt_name_5', conditions: [] } repository.update([split], [], -1) repository.instance_variable_get(:@adapter).set_string( @@ -79,7 +79,7 @@ expect(repository.traffic_type_exists('tt_name_5')).to be true - split = { name: 'corge', trafficTypeName: 'tt_name_6' } + split = { name: 'corge', trafficTypeName: 'tt_name_6', conditions: [] } repository.update([split], [], -1) @@ -97,11 +97,81 @@ it 'returns splits data' do expect(repository.splits).to eq( - 'foo' => { name: 'foo', trafficTypeName: 'tt_name_1' }, - 'bar' => { name: 'bar', trafficTypeName: 'tt_name_2' }, - 'baz' => { name: 'baz', trafficTypeName: 'tt_name_1' } + 'foo' => { name: 'foo', trafficTypeName: 'tt_name_1', conditions: [] }, + 'bar' => { name: 'bar', trafficTypeName: 'tt_name_2', conditions: [] }, + 'baz' => { name: 'baz', trafficTypeName: 'tt_name_1', conditions: [] } ) end + + it 'remove undefined matcher with template condition' do + split = { name: 'corge', trafficTypeName: 'tt_name_5', conditions: [ + { + partitions: [ + {treatment: 'on', size: 50}, + {treatment: 'off', size: 50} + ], + contitionType: 'WHITELIST', + label: 'some_label', + matcherGroup: { + matchers: [ + { + matcherType: 'UNDEFINED', + whitelistMatcherData: { + whitelist: ['k1', 'k2', 'k3'] + }, + negate: false, + } + ], + combiner: 'AND' + } + }] + } + + repository.update([split], [], -1) + expect(repository.get_split('corge')[:conditions]).to eq SplitIoClient::Cache::Repositories::SplitsRepository::DEFAULT_CONDITIONS_TEMPLATE + + # test with multiple conditions + split2 = { + name: 'corge2', + trafficTypeName: 'tt_name_5', + conditions: [ + { + partitions: [ + {treatment: 'on', size: 50}, + {treatment: 'off', size: 50} + ], + contitionType: 'WHITELIST', + label: 'some_label', + matcherGroup: { + matchers: [ + { + matcherType: 'UNDEFINED', + whitelistMatcherData: { + whitelist: ['k1', 'k2', 'k3'] + }, + negate: false, + } + ], + combiner: 'AND' + } + }, + { + partitions: [ + {treatment: 'on', size: 25}, + {treatment: 'off', size: 75} + ], + contitionType: 'WHITELIST', + label: 'some_other_label', + matcherGroup: { + matchers: [{matcherType: 'ALL_KEYS', negate: false}], + combiner: 'AND' + } + }] + } + + repository.update([split2], [], -1) + expect(repository.get_split('corge2')[:conditions]).to eq SplitIoClient::Cache::Repositories::SplitsRepository::DEFAULT_CONDITIONS_TEMPLATE + end end describe 'with Memory Adapter' do diff --git a/spec/engine/api/splits_spec.rb b/spec/engine/api/splits_spec.rb index 7850e6db..63e00943 100644 --- a/spec/engine/api/splits_spec.rb +++ b/spec/engine/api/splits_spec.rb @@ -18,7 +18,7 @@ let(:splits_api) { described_class.new('', config, telemetry_runtime_producer) } it 'returns splits with segment names' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: splits) parsed_splits = splits_api.send(:splits_with_segment_names, splits) @@ -41,7 +41,7 @@ let(:splits_api) { described_class.new('', config, telemetry_runtime_producer) } it 'returns the splits - with 2 sets param' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?sets=set_1,set_2&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1&sets=set_1,set_2') .with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip', @@ -61,7 +61,7 @@ end it 'raise api exception when status 414' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?sets=set_1,set_2&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1&sets=set_1,set_2') .with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip', @@ -96,7 +96,7 @@ let(:splits_api) { described_class.new('', config, telemetry_runtime_producer) } it 'returns the splits - checking headers when cache_control_headers is false' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip', @@ -115,7 +115,7 @@ end it 'returns the splits - with till param' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1&till=123123') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1&till=123123') .with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip', @@ -135,7 +135,7 @@ end it 'returns the splits - checking headers when cache_control_headers is true' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .with(headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip', @@ -156,7 +156,7 @@ end it 'throws exception if request to get splits from API returns unexpected status code' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 404) expect { splits_api.since(-1) }.to raise_error( @@ -166,7 +166,7 @@ end it 'throws exception if request to get splits from API fails' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_raise(StandardError) expect { splits_api.since(-1) }.to raise_error( @@ -175,7 +175,7 @@ end it 'throws exception if request to get splits from API times out' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_timeout expect { splits_api.since(-1) }.to raise_error( diff --git a/spec/engine/auth_api_client_spec.rb b/spec/engine/auth_api_client_spec.rb index 096aae2c..0235c130 100644 --- a/spec/engine/auth_api_client_spec.rb +++ b/spec/engine/auth_api_client_spec.rb @@ -15,7 +15,7 @@ let(:telemetry_runtime_producer) { SplitIoClient::Telemetry::RuntimeProducer.new(config) } it 'authenticate success' do - stub_request(:get, config.auth_service_url).to_return(status: 200, body: body_response) + stub_request(:get, config.auth_service_url + "?s=1.1").to_return(status: 200, body: body_response) auth_api_client = subject.new(config, telemetry_runtime_producer) response = auth_api_client.authenticate(api_key) @@ -26,7 +26,7 @@ end it 'auth server return 500' do - stub_request(:get, config.auth_service_url).to_return(status: 500) + stub_request(:get, config.auth_service_url + "?s=1.1").to_return(status: 500) auth_api_client = subject.new(config, telemetry_runtime_producer) response = auth_api_client.authenticate(api_key) @@ -36,7 +36,7 @@ end it 'auth server return 401' do - stub_request(:get, config.auth_service_url).to_return(status: 401) + stub_request(:get, config.auth_service_url + "?s=1.1").to_return(status: 401) auth_api_client = subject.new(config, telemetry_runtime_producer) response = auth_api_client.authenticate(api_key) diff --git a/spec/engine/matchers/between_matcher_spec.rb b/spec/engine/matchers/between_matcher_spec.rb index ba8b980c..9e16e550 100644 --- a/spec/engine/matchers/between_matcher_spec.rb +++ b/spec/engine/matchers/between_matcher_spec.rb @@ -43,7 +43,7 @@ # .to_return(status: 200, body: number_matcher_splits) stub_request(:get, 'https://sdk.split.io/api/splitChanges') .to_return(status: 200, body: number_matcher_splits) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: number_matcher_splits) subject.block_until_ready sleep 1 @@ -69,7 +69,7 @@ let(:non_matching_low_value_negative_attributes) { { income: -999 } } before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since.*/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since.*/) .to_return(status: 200, body: negative_number_matcher_splits) subject.block_until_ready sleep 1 @@ -97,7 +97,7 @@ let(:non_matching_high_value_attributes) { { created: 1_459_775_460 } } # "2016/04/04T13:11Z" before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: datetime_matcher_splits) subject.block_until_ready sleep 1 diff --git a/spec/engine/matchers/combining_matcher_spec.rb b/spec/engine/matchers/combining_matcher_spec.rb index a602ebbd..bdaccaa7 100644 --- a/spec/engine/matchers/combining_matcher_spec.rb +++ b/spec/engine/matchers/combining_matcher_spec.rb @@ -19,7 +19,7 @@ before do stub_request(:get, 'https://sdk.split.io/api/segmentChanges/employees?since=-1') .to_return(status: 200, body: segments_json) - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: splits_json) stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') diff --git a/spec/engine/matchers/equal_to_matcher_spec.rb b/spec/engine/matchers/equal_to_matcher_spec.rb index a9daf292..043b39df 100644 --- a/spec/engine/matchers/equal_to_matcher_spec.rb +++ b/spec/engine/matchers/equal_to_matcher_spec.rb @@ -37,7 +37,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: 'ok') @@ -64,7 +64,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: zero_splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: 'ok') @@ -90,7 +90,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: negative_splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: 'ok') @@ -117,7 +117,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: date_splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: 'ok') diff --git a/spec/engine/matchers/greater_than_or_equal_to_matcher_spec.rb b/spec/engine/matchers/greater_than_or_equal_to_matcher_spec.rb index 0307dae7..5283bfb9 100644 --- a/spec/engine/matchers/greater_than_or_equal_to_matcher_spec.rb +++ b/spec/engine/matchers/greater_than_or_equal_to_matcher_spec.rb @@ -35,7 +35,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: "", headers: {}) @@ -61,7 +61,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: negative_splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: "", headers: {}) @@ -92,7 +92,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: date_splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: "", headers: {}) diff --git a/spec/engine/matchers/less_than_or_equal_to_matcher_spec.rb b/spec/engine/matchers/less_than_or_equal_to_matcher_spec.rb index bd53166c..60936dc0 100644 --- a/spec/engine/matchers/less_than_or_equal_to_matcher_spec.rb +++ b/spec/engine/matchers/less_than_or_equal_to_matcher_spec.rb @@ -37,7 +37,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: "", headers: {}) @@ -64,7 +64,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: negative_splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: "", headers: {}) @@ -93,7 +93,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: date_splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: "", headers: {}) @@ -119,7 +119,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: date_splits2_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: "", headers: {}) diff --git a/spec/engine/matchers/matches_between_semver_matcher_spec.rb b/spec/engine/matchers/matches_between_semver_matcher_spec.rb new file mode 100644 index 00000000..b4431fe4 --- /dev/null +++ b/spec/engine/matchers/matches_between_semver_matcher_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe SplitIoClient::BetweenSemverMatcher do + let(:raw) { { + 'negate': false, + 'matcherType': 'BETWEEN_SEMVER', + 'betweenStringMatcherData': {"start": "2.1.8", "end": "2.1.11"} +} } + let(:config) { SplitIoClient::SplitConfig.new } + + it 'initilized params' do + matcher = described_class.new("version", raw[:betweenStringMatcherData][:start], raw[:betweenStringMatcherData][:end], config.logger, config.split_validator) + expect(matcher.attribute).to eq("version") + semver_start = matcher.instance_variable_get(:@semver_start) + expect(semver_start.instance_variable_get(:@version)).to eq("2.1.8") + semver_end = matcher.instance_variable_get(:@semver_end) + expect(semver_end.instance_variable_get(:@version)).to eq("2.1.11") + end + + it 'matches' do + matcher = described_class.new("version", raw[:betweenStringMatcherData][:start], raw[:betweenStringMatcherData][:end], config.logger, config.split_validator) + expect(matcher.match?(:attributes=>{"version": "2.1.8+rc"})).to eq(true) + expect(matcher.match?(:attributes=>{"version": "2.1.9"})).to eq(true) + expect(matcher.match?(:attributes=>{"version": "2.1.11-rc12"})).to eq(true) + end + + it 'does not match' do + matcher = described_class.new("version", raw[:betweenStringMatcherData][:start], raw[:betweenStringMatcherData][:end], config.logger, config.split_validator) + expect(matcher.match?(:attributes=>{"version": "2.1.5"})).to eq(false) + expect(matcher.match?(:attributes=>{"version": "2.1.12-rc1"})).to eq(false) + end + + it 'invalid attribute' do + matcher = described_class.new("version", raw[:betweenStringMatcherData][:start], raw[:betweenStringMatcherData][:end], config.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 diff --git a/spec/engine/matchers/matches_equal_to_semver_matcher_spec.rb b/spec/engine/matchers/matches_equal_to_semver_matcher_spec.rb new file mode 100644 index 00000000..6d382bb3 --- /dev/null +++ b/spec/engine/matchers/matches_equal_to_semver_matcher_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe SplitIoClient::EqualToSemverMatcher do + let(:raw) { { + 'negate': false, + 'matcherType': 'EQUAL_TO_SEMVER', + 'stringMatcherData': "2.1.8" + } } + let(:config) { SplitIoClient::SplitConfig.new } + + it 'initilized params' do + matcher = described_class.new("version", raw[:stringMatcherData], config.logger, config.split_validator) + expect(matcher.attribute).to eq("version") + semver = matcher.instance_variable_get(:@semver) + expect(semver.instance_variable_get(:@version)).to eq("2.1.8") + end + + it 'matches' do + matcher = described_class.new("version", raw[:stringMatcherData], config.logger, config.split_validator) + expect(matcher.match?(:attributes=>{"version": "2.1.8"})).to eq(true) + end + + it 'does not match' do + matcher = described_class.new("version", raw[:stringMatcherData], config.logger, config.split_validator) + expect(matcher.match?(:attributes=>{"version": "2.1.8+rc"})).to eq(false) + 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.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 diff --git a/spec/engine/matchers/matches_greater_than_or_equal_to_semver_matcher_spec.rb b/spec/engine/matchers/matches_greater_than_or_equal_to_semver_matcher_spec.rb new file mode 100644 index 00000000..91c81dec --- /dev/null +++ b/spec/engine/matchers/matches_greater_than_or_equal_to_semver_matcher_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe SplitIoClient::GreaterThanOrEqualToSemverMatcher do + let(:raw) { { + 'negate': false, + 'matcherType': 'GREATER_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.logger, config.split_validator) + expect(matcher.attribute).to eq("version") + semver = matcher.instance_variable_get(:@semver) + expect(semver.instance_variable_get(:@version)).to eq("2.1.8") + end + + it 'matches' do + matcher = described_class.new("version", raw[:stringMatcherData], config.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.logger, config.split_validator) + expect(matcher.match?(:attributes=>{"version": "2.1.7"})).to eq(false) + expect(matcher.match?(:attributes=>{"version": "2.0.22"})).to eq(false) + end + + it 'invalid attribute' do + matcher = described_class.new("version", raw[:stringMatcherData], config.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 diff --git a/spec/engine/matchers/matches_in_list_semver_matcher_spec.rb b/spec/engine/matchers/matches_in_list_semver_matcher_spec.rb new file mode 100644 index 00000000..76461a65 --- /dev/null +++ b/spec/engine/matchers/matches_in_list_semver_matcher_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe SplitIoClient::InListSemverMatcher do + let(:raw) { { + 'negate': false, + 'matcherType': 'INLIST_SEMVER', + 'whitelistMatcherData': {"whitelist": ["2.1.8", "2.1.11"]} +} } + let(:config) { SplitIoClient::SplitConfig.new } + + it 'initilized params' do + matcher = described_class.new("version", raw[:whitelistMatcherData][:whitelist], config.logger, config.split_validator) + expect(matcher.attribute).to eq("version") + semver_list = matcher.instance_variable_get(:@semver_list) + expect(semver_list[0].instance_variable_get(:@version)).to eq("2.1.8") + expect(semver_list[1].instance_variable_get(:@version)).to eq("2.1.11") + end + + it 'matches' do + matcher = described_class.new("version", raw[:whitelistMatcherData][:whitelist], config.logger, config.split_validator) + expect(matcher.match?(:attributes=>{"version": "2.1.8"})).to eq(true) + expect(matcher.match?(:attributes=>{"version": "2.1.11"})).to eq(true) + end + + it 'does not match' do + matcher = described_class.new("version", raw[:whitelistMatcherData][:whitelist], config.logger, config.split_validator) + expect(matcher.match?(:attributes=>{"version": "2.1.8+rc"})).to eq(false) + expect(matcher.match?(:attributes=>{"version": "2.1.7"})).to eq(false) + expect(matcher.match?(:attributes=>{"version": "2.1.11-rc12"})).to eq(false) + expect(matcher.match?(:attributes=>{"version": "2.1.8-rc1"})).to eq(false) + end + + it 'invalid attribute' do + matcher = described_class.new("version", raw[:whitelistMatcherData][:whitelist], config.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 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..a551e657 --- /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({:logger => Logger.new('/dev/null')}) } + + it 'initilized params' do + matcher = described_class.new("version", raw[:stringMatcherData], config.logger, config.split_validator) + expect(matcher.attribute).to eq("version") + semver = matcher.instance_variable_get(:@semver) + expect(semver.instance_variable_get(:@version)).to eq("2.1.8") + end + + it 'matches' do + matcher = described_class.new("version", raw[:stringMatcherData], config.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.logger, config.split_validator) + expect(matcher.match?(:attributes=>{"version": "2.1.10"})).to eq(false) + expect(matcher.match?(:attributes=>{"version": "2.2.0-rc1"})).to eq(false) + end + + it 'invalid attribute' do + matcher = described_class.new("version", raw[:stringMatcherData], config.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 diff --git a/spec/engine/matchers/semver_matchers_integration_spec.rb b/spec/engine/matchers/semver_matchers_integration_spec.rb new file mode 100644 index 00000000..86909af5 --- /dev/null +++ b/spec/engine/matchers/semver_matchers_integration_spec.rb @@ -0,0 +1,168 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Semver matchers integration' do + subject do + SplitIoClient::SplitFactory.new('test_api_key', { + logger: Logger.new(log), + streaming_enabled: false, + impressions_refresh_rate: 9999, + impressions_mode: :none, + features_refresh_rate: 9999, + telemetry_refresh_rate: 99999}).client + end + + let(:log) { StringIO.new } + + let(:semver_between_matcher_splits) do + File.read(File.expand_path(File.join(File.dirname(__FILE__), + '../../test_data/splits/semver_matchers/semver_between.json'))) + end + + let(:semver_equalto_matcher_splits) do + File.read(File.expand_path(File.join(File.dirname(__FILE__), + '../../test_data/splits/semver_matchers/semver_equalto.json'))) + end + + let(:semver_greater_or_equalto_matcher_splits) do + File.read(File.expand_path(File.join(File.dirname(__FILE__), + '../../test_data/splits/semver_matchers/semver_greater_or_equalto.json'))) + end + + let(:semver_less_or_equalto_matcher_splits) do + File.read(File.expand_path(File.join(File.dirname(__FILE__), + '../../test_data/splits/semver_matchers/semver_less_or_equalto.json'))) + end + + let(:semver_inlist_matcher_splits) do + File.read(File.expand_path(File.join(File.dirname(__FILE__), + '../../test_data/splits/semver_matchers/semver_inlist.json'))) + end + + let(:user) { 'fake_user_id_1' } + + before do + stub_request(:any, /https:\/\/telemetry\.*/).to_return(status: 200, body: 'ok') + stub_request(:any, /https:\/\/events\.*/).to_return(status: 200, body: "", headers: {}) + stub_request(:any, /https:\/\/metrics\.*/).to_return(status: 200, body: "", headers: {}) + stub_request(:post, "https://telemetry.split.io/api/v1/metrics/config").to_return(status: 200, body: "", headers: {}) + end + + context 'equal to matcher' do + before do + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since\.*/) + .to_return(status: 200, body: semver_equalto_matcher_splits) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + .to_return(status: 200, body: semver_equalto_matcher_splits) + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1675259356568") + .to_return(status: 200, body: semver_equalto_matcher_splits) + sleep 1 + subject.block_until_ready + end + + it 'validates the treatment is ON for correct attribute value' do + expect(subject.get_treatment(user, 'semver_equalto', {:version => "1.22.9"})).to eq 'on' + end + + it 'validates the treatment is the default treatment for incorrect attributes hash and nil' do + expect(subject.get_treatment(user, 'semver_equalto')).to eq 'off' + expect(subject.get_treatment(user, 'semver_equalto', {:version => "1.22.10"})).to eq 'off' + sleep 0.2 + subject.destroy() + end + end + + context 'greater than or equal to matcher' do + before do + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + .to_return(status: 200, body: semver_greater_or_equalto_matcher_splits) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + .to_return(status: 200, body: semver_greater_or_equalto_matcher_splits) + sleep 1 + subject.block_until_ready + end + + it 'validates the treatment is ON for correct attribute value' do + expect(subject.get_treatment(user, 'semver_greater_or_equalto', {:version => "1.22.9"})).to eq 'on' + expect(subject.get_treatment(user, 'semver_greater_or_equalto', {:version => "1.22.10"})).to eq 'on' + end + + it 'validates the treatment is the default treatment for incorrect attributes hash and nil' do + expect(subject.get_treatment(user, 'semver_greater_or_equalto')).to eq 'off' + expect(subject.get_treatment(user, 'semver_greater_or_equalto', {:version => "1.22.8"})).to eq 'off' + sleep 0.2 + subject.destroy() + end + end + + context 'less than or equal to matcher' do + before do + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + .to_return(status: 200, body: semver_less_or_equalto_matcher_splits) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + .to_return(status: 200, body: semver_less_or_equalto_matcher_splits) + sleep 1 + subject.block_until_ready + end + + it 'validates the treatment is ON for correct attribute value' do + expect(subject.get_treatment(user, 'semver_less_or_equalto', {:version => "1.22.9"})).to eq 'on' + expect(subject.get_treatment(user, 'semver_less_or_equalto', {:version => "1.22.8"})).to eq 'on' + end + + it 'validates the treatment is the default treatment for incorrect attributes hash and nil' do + expect(subject.get_treatment(user, 'semver_less_or_equalto')).to eq 'off' + expect(subject.get_treatment(user, 'semver_less_or_equalto', {:version => "1.22.10"})).to eq 'off' + sleep 0.2 + subject.destroy() + end + end + + context 'in list matcher' do + before do + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + .to_return(status: 200, body: semver_inlist_matcher_splits) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + .to_return(status: 200, body: semver_inlist_matcher_splits) + sleep 1 + subject.block_until_ready + end + + it 'validates the treatment is ON for correct attribute value' do + expect(subject.get_treatment(user, 'semver_inlist', {:version => "1.22.9"})).to eq 'on' + expect(subject.get_treatment(user, 'semver_inlist', {:version => "2.1.0"})).to eq 'on' + end + + it 'validates the treatment is the default treatment for incorrect attributes hash and nil' do + expect(subject.get_treatment(user, 'semver_inlist')).to eq 'off' + expect(subject.get_treatment(user, 'semver_inlist', {:version => "1.22.10"})).to eq 'off' + sleep 0.2 + subject.destroy() + end + end + + context 'between matcher' do + before do + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) + .to_return(status: 200, body: semver_between_matcher_splits) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + .to_return(status: 200, body: semver_between_matcher_splits) + sleep 1 + subject.block_until_ready + end + + it 'validates the treatment is ON for correct attribute value' do + expect(subject.get_treatment(user, 'semver_between', {:version => "1.22.9"})).to eq 'on' + expect(subject.get_treatment(user, 'semver_between', {:version => "2.0.10"})).to eq 'on' + end + + it 'validates the treatment is the default treatment for incorrect attributes hash and nil' do + expect(subject.get_treatment(user, 'semver_between')).to eq 'off' + expect(subject.get_treatment(user, 'semver_between', {:version => "1.22.9-rc1"})).to eq 'off' + expect(subject.get_treatment(user, 'semver_between', {:version => "2.1.1"})).to eq 'off' + sleep 0.2 + subject.destroy() + end + end +end diff --git a/spec/engine/matchers/semver_spec.rb b/spec/engine/matchers/semver_spec.rb new file mode 100644 index 00000000..2e1ca0f1 --- /dev/null +++ b/spec/engine/matchers/semver_spec.rb @@ -0,0 +1,76 @@ +require 'spec_helper' +require 'csv' + +describe SplitIoClient::Semver do + let(:valid_versions) do + CSV.parse(File.read(File.expand_path(File.join(File.dirname(__FILE__), + '../../test_data/splits/semver/valid-semantic-versions.csv'))), headers: true) + end + let(:invalid_versions) do + CSV.parse(File.read(File.expand_path(File.join(File.dirname(__FILE__), + '../../test_data/splits/semver/invalid-semantic-versions.csv'))), headers: true) + end + let(:equal_to_versions) do + CSV.parse(File.read(File.expand_path(File.join(File.dirname(__FILE__), + '../../test_data/splits/semver/equal-to-semver.csv'))), headers: true) + end + + let(:between_versions) do + CSV.parse(File.read(File.expand_path(File.join(File.dirname(__FILE__), + '../../test_data/splits/semver/between-semver.csv'))), headers: true) + end + + let(:logger) { Logger.new('/dev/null') } + + context 'check versions' do + it 'accept valid versions' do + for i in (0..valid_versions.length-1) + expect(described_class.build(valid_versions[i][0], logger)).not_to be_nil + end + end + it 'reject invalid versions' do + for version in invalid_versions + expect(described_class.build(version[0], logger)).to eq(nil) + end + end + + it 'verify leading-zero integers are converted' do + semver = described_class.build('1.01.2', logger) + expect(semver.version).to eq('1.1.2') + expect(described_class.build('1.01.2-rc.04', logger).version).to eq('1.1.2-rc.4') + end + + end + + context 'compare versions' do + it 'equal and not equal' do + for i in (1..valid_versions.length-1) + expect(described_class.build(valid_versions[i][0], logger).compare(described_class.build(valid_versions[i][1], logger))).to eq(1) + expect(described_class.build(valid_versions[i][1], logger).compare(described_class.build(valid_versions[i][0], logger))).to eq(-1) + expect(described_class.build(valid_versions[i][0], logger).compare(described_class.build(valid_versions[i][0], logger))).to eq(0) + expect(described_class.build(valid_versions[i][1], logger).compare(described_class.build(valid_versions[i][1], logger))).to eq(0) + end + for i in (1..equal_to_versions.length-1) + if equal_to_versions[i][2]=='true' + expect(described_class.build(equal_to_versions[i][0], logger).version == described_class.build(equal_to_versions[i][1], logger).version).to eq(true) + else + expect(described_class.build(equal_to_versions[i][0], logger) == described_class.build(equal_to_versions[i][1], logger)).to eq(false) + end + end + for i in (1..between_versions.length-1) + sem1 = described_class.build(between_versions[i][0], logger) + sem2 = described_class.build(between_versions[i][2], logger) + to_check = described_class.build(between_versions[i][1], logger) + if between_versions[i][3]=='true' + expect(sem1.compare(to_check)).to eq(-1) + expect(sem2.compare(to_check)).to eq(1) + else + compare1 = sem1.compare(to_check) + compare2 = sem2.compare(to_check) + expect(compare1 == -1 && compare2 == 1).to eq(false) + end + end + + end + end +end diff --git a/spec/engine/matchers/whitelist_matcher_spec.rb b/spec/engine/matchers/whitelist_matcher_spec.rb index e2472867..25f4a4ba 100644 --- a/spec/engine/matchers/whitelist_matcher_spec.rb +++ b/spec/engine/matchers/whitelist_matcher_spec.rb @@ -22,7 +22,7 @@ before do stub_request(:any, /https:\/\/telemetry.*/) .to_return(status: 200, body: 'ok') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: splits_json) stub_request(:any, /https:\/\/events.*/) .to_return(status: 200, body: "", headers: {}) diff --git a/spec/engine/push_manager_spec.rb b/spec/engine/push_manager_spec.rb index 03f2187b..a1a6d9e7 100644 --- a/spec/engine/push_manager_spec.rb +++ b/spec/engine/push_manager_spec.rb @@ -43,7 +43,7 @@ send_mock_content(res, 'content') end - stub_request(:get, config.auth_service_url).to_return(status: 200, body: body_response) + stub_request(:get, config.auth_service_url + "?s=1.1").to_return(status: 200, body: body_response) config.streaming_service_url = server.base_uri sse_handler = SplitIoClient::SSE::SSEHandler.new(config, splits_worker, segments_worker, sse_client) @@ -51,7 +51,7 @@ push_manager = subject.new(config, sse_handler, api_key, runtime_producer) connected = push_manager.start_sse - expect(a_request(:get, config.auth_service_url)).to have_been_made.times(1) + expect(a_request(:get, config.auth_service_url + "?s=1.1")).to have_been_made.times(1) sleep(1.5) expect(connected).to eq(true) @@ -61,14 +61,14 @@ end it 'must not connect to server. Auth server return 500' do - stub_request(:get, config.auth_service_url).to_return(status: 500) + stub_request(:get, config.auth_service_url + "?s=1.1").to_return(status: 500) sse_handler = SplitIoClient::SSE::SSEHandler.new(config, splits_worker, segments_worker, sse_client) push_manager = subject.new(config, sse_handler, api_key, runtime_producer) connected = push_manager.start_sse - expect(a_request(:get, config.auth_service_url)).to have_been_made.times(1) + expect(a_request(:get, config.auth_service_url + "?s=1.1")).to have_been_made.times(1) sleep(1.5) @@ -77,14 +77,14 @@ end it 'must not connect to server. Auth server return 401' do - stub_request(:get, config.auth_service_url).to_return(status: 401) + stub_request(:get, config.auth_service_url + "?s=1.1").to_return(status: 401) sse_handler = SplitIoClient::SSE::SSEHandler.new(config, splits_worker, segments_worker, sse_client) push_manager = subject.new(config, sse_handler, api_key, runtime_producer) connected = push_manager.start_sse - expect(a_request(:get, config.auth_service_url)).to have_been_made.times(1) + expect(a_request(:get, config.auth_service_url + "?s=1.1")).to have_been_made.times(1) sleep(1.5) @@ -100,14 +100,14 @@ send_mock_content(res, 'content') end - stub_request(:get, config.auth_service_url).to_return(status: 200, body: body_response) + stub_request(:get, config.auth_service_url + "?s=1.1").to_return(status: 200, body: body_response) config.streaming_service_url = server.base_uri sse_handler = SplitIoClient::SSE::SSEHandler.new(config, splits_worker, segments_worker, sse_client) push_manager = subject.new(config, sse_handler, api_key, runtime_producer) connected = push_manager.start_sse - expect(a_request(:get, config.auth_service_url)).to have_been_made.times(1) + expect(a_request(:get, config.auth_service_url + "?s=1.1")).to have_been_made.times(1) sleep(1.5) diff --git a/spec/engine/sync_manager_spec.rb b/spec/engine/sync_manager_spec.rb index 7bedc97b..d472de01 100644 --- a/spec/engine/sync_manager_spec.rb +++ b/spec/engine/sync_manager_spec.rb @@ -68,7 +68,7 @@ mock_segment_changes('segment2', segment2, '-1') mock_segment_changes('segment2', segment2, '1470947453878') mock_segment_changes('segment3', segment3, '-1') - stub_request(:get, config.auth_service_url).to_return(status: 200, body: body_response) + stub_request(:get, config.auth_service_url + "?s=1.1").to_return(status: 200, body: body_response) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') end @@ -84,7 +84,7 @@ sync_manager.start sleep(2) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1')).to have_been_made.once + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.once expect(config.threads.size).to eq(11) config.threads.values.each { |thread| Thread.kill(thread) } @@ -104,7 +104,7 @@ sync_manager.start sleep(2) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1')).to have_been_made.once + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.once expect(config.threads.size).to eq(8) config.threads.values.each { |thread| Thread.kill(thread) } @@ -136,7 +136,7 @@ private def mock_split_changes_with_since(splits_json, since) - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=#{since}") + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=#{since}") .to_return(status: 200, body: splits_json) end diff --git a/spec/engine/synchronizer_spec.rb b/spec/engine/synchronizer_spec.rb index 5a406419..74599346 100644 --- a/spec/engine/synchronizer_spec.rb +++ b/spec/engine/synchronizer_spec.rb @@ -52,7 +52,7 @@ sleep(2) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1')).to have_been_made.once + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.once expect(a_request(:get, 'https://sdk.split.io/api/segmentChanges/segment1?since=-1')).to have_been_made.once expect(a_request(:get, 'https://sdk.split.io/api/segmentChanges/segment1?since=1470947453877')).to have_been_made.once expect(a_request(:get, 'https://sdk.split.io/api/segmentChanges/segment2?since=-1')).to have_been_made.once @@ -66,7 +66,7 @@ sleep(2) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1')).to have_been_made.once + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.once expect(a_request(:get, 'https://sdk.split.io/api/segmentChanges/segment1?since=-1')).to have_been_made.once expect(a_request(:get, 'https://sdk.split.io/api/segmentChanges/segment1?since=1470947453877')).to have_been_made.once expect(a_request(:get, 'https://sdk.split.io/api/segmentChanges/segment2?since=-1')).to have_been_made.once @@ -84,7 +84,7 @@ it 'start_periodic_fetch' do synchronizer.start_periodic_fetch - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1')).to have_been_made.once + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.once expect(a_request(:get, 'https://sdk.split.io/api/segmentChanges/segment1?since=-1')).to have_been_made.once expect(a_request(:get, 'https://sdk.split.io/api/segmentChanges/segment1?since=1470947453877')).to have_been_made.once expect(a_request(:get, 'https://sdk.split.io/api/segmentChanges/segment2?since=-1')).to have_been_made.once @@ -94,7 +94,7 @@ end it 'sync_all synchronous - should return false' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1').to_return(status: 500) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1').to_return(status: 500) result = synchronizer.sync_all(false) @@ -112,11 +112,11 @@ mock_segment_changes('segment1', segment1, '1470947453877') synchronizer.fetch_splits(0) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1')).to have_been_made.once + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.once end it 'fetch_splits - with CDN bypassed' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: '{ "splits": [], @@ -124,7 +124,7 @@ "till": 1506703262918 }') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262918') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262918') .to_return(status: 200, body: '{ "splits": [], @@ -132,7 +132,7 @@ "till": 1506703262918 }') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262918&till=1506703262920') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262918&till=1506703262920') .to_return(status: 200, body: '{ "splits": [], @@ -142,9 +142,9 @@ synchronizer.fetch_splits(1_506_703_262_920) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1')).to have_been_made.once - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262918')).to have_been_made.times(9) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262918&till=1506703262920')).to have_been_made.once + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.once + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262918')).to have_been_made.times(9) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262918&till=1506703262920')).to have_been_made.once end it 'fetch_segment' do @@ -227,7 +227,7 @@ private def mock_split_changes(splits_json) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1').to_return(status: 200, body: splits_json) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1').to_return(status: 200, body: splits_json) end def mock_segment_changes(segment_name, segment_json, since) diff --git a/spec/engine_spec.rb b/spec/engine_spec.rb index 1919879c..8d09ae25 100644 --- a/spec/engine_spec.rb +++ b/spec/engine_spec.rb @@ -46,7 +46,7 @@ @mode = cache_adapter.equal?(:memory) ? :standalone : :consumer stub_request(:any, /https:\/\/telemetry.*/).to_return(status: 200, body: 'ok') stub_request(:any, /https:\/\/events.*/).to_return(status: 200, body: '') - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: '') end @@ -126,7 +126,7 @@ context '#get_treatment' do before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/).to_return(status: 200, body: '') + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/).to_return(status: 200, body: '') load_splits(all_keys_matcher_json, flag_sets_json) subject.block_until_ready @@ -832,7 +832,7 @@ before do impressions_test_json = File.read(File.join(SplitIoClient.root, 'spec/test_data/splits/engine/impressions_test.json')) load_splits(impressions_test_json, flag_sets_json) - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/).to_return(status: 200, body: '') + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/).to_return(status: 200, body: '') end it 'returns correct impressions for get_treatments checking ' do @@ -926,7 +926,7 @@ end it 'returns control' do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: all_keys_matcher_json) subject.block_until_ready @@ -940,7 +940,7 @@ describe 'redis outage' do before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: all_keys_matcher_json) end @@ -953,7 +953,7 @@ describe 'events' do before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: all_keys_matcher_json) subject.block_until_ready end @@ -983,7 +983,7 @@ context '#track' do before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since/) .to_return(status: 200, body: all_keys_matcher_json) subject.block_until_ready end @@ -1190,7 +1190,7 @@ end before do - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since.*/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since.*/) .to_return(status: 200, body: all_keys_matcher_json) end @@ -1267,7 +1267,7 @@ def load_splits(splits_json, flag_sets_json) if @mode.equal?(:standalone) - stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?since.*/) + stub_request(:get, /https:\/\/sdk\.split\.io\/api\/splitChanges\?s=1\.1&since.*/) .to_return(status: 200, body: splits_json) else add_splits_to_repository(splits_json) diff --git a/spec/integrations/dedupe_impression_spec.rb b/spec/integrations/dedupe_impression_spec.rb index 8aa67ef7..399d3045 100644 --- a/spec/integrations/dedupe_impression_spec.rb +++ b/spec/integrations/dedupe_impression_spec.rb @@ -33,8 +33,8 @@ context 'checking logic impressions' do it 'get_treament should post 7 impressions - debug mode' do stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916').to_return(status: 200, body: '') - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=-1").to_return(status: 200, body: splits, headers: {}) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916').to_return(status: 200, body: '') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=-1").to_return(status: 200, body: splits, headers: {}) factory = SplitIoClient::SplitFactory.new('test_api_key_debug-1', streaming_enabled: false, impressions_mode: :debug) debug_client = factory.client @@ -61,7 +61,7 @@ it 'get_treaments should post 9 impressions - debug mode' do stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916').to_return(status: 200, body: '') factory = SplitIoClient::SplitFactory.new('test_api_key_debug-2', streaming_enabled: false, impressions_mode: :debug) debug_client = factory.client @@ -81,7 +81,7 @@ it 'get_treament should post 3 impressions - optimized mode' do stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916').to_return(status: 200, body: '') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/usage').to_return(status: 200, body: '') factory = SplitIoClient::SplitFactory.new('test_api_key-1', streaming_enabled: false, impressions_mode: :optimized, impressions_refresh_rate: 60) @@ -113,7 +113,7 @@ it 'get_treaments should post 8 impressions - optimized mode' do stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/usage').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916').to_return(status: 200, body: '') factory = SplitIoClient::SplitFactory.new('test_api_key-2', streaming_enabled: false, impressions_mode: :optimized) client = factory.client @@ -149,7 +149,7 @@ private def mock_split_changes_v2(splits_json) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: splits_json) end diff --git a/spec/integrations/in_memory_client_spec.rb b/spec/integrations/in_memory_client_spec.rb index 85956360..1120b57a 100644 --- a/spec/integrations/in_memory_client_spec.rb +++ b/spec/integrations/in_memory_client_spec.rb @@ -47,7 +47,7 @@ context '#get_treatment' do it 'returns treatments with FACUNDO_TEST feature and check impressions' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') client.block_until_ready expect(client.get_treatment('nico_test', 'FACUNDO_TEST')).to eq 'on' expect(client.get_treatment('mauro_test', 'FACUNDO_TEST')).to eq 'off' @@ -71,7 +71,7 @@ end it 'returns treatments with Test_Save_1 feature and check impressions' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') client.block_until_ready expect(client.get_treatment('1', 'Test_Save_1')).to eq 'on' expect(client.get_treatment('24', 'Test_Save_1')).to eq 'off' @@ -95,7 +95,7 @@ end it 'returns treatments with input validations' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') client.block_until_ready expect(client.get_treatment('nico_test', 'FACUNDO_TEST')).to eq 'on' expect(client.get_treatment('', 'FACUNDO_TEST')).to eq 'control' @@ -123,7 +123,7 @@ end it 'returns CONTROL with treatment doesnt exist' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') expect(client.get_treatment('nico_test', 'random_treatment')).to eq 'control' impressions = custom_impression_listener.queue @@ -131,7 +131,7 @@ end it 'returns CONTROL when server return 500' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') mock_split_changes_error expect(client.get_treatment('nico_test', 'FACUNDO_TEST')).to eq 'control' @@ -148,7 +148,7 @@ end it 'with multiple factories returns on' do -# stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') +# stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') local_log = StringIO.new logger = Logger.new(local_log) @@ -228,7 +228,7 @@ context '#get_treatment_with_config' do it 'returns treatments and configs with FACUNDO_TEST treatment and check impressions' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') client.block_until_ready expect(client.get_treatment_with_config('nico_test', 'FACUNDO_TEST')).to eq( treatment: 'on', @@ -258,7 +258,7 @@ end it 'returns treatments and configs with MAURO_TEST treatment and check impressions' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') client.block_until_ready expect(client.get_treatment_with_config('mauro', 'MAURO_TEST')).to eq( @@ -289,7 +289,7 @@ end it 'returns treatments with input validations' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') client.block_until_ready expect(client.get_treatment_with_config('nico_test', 'FACUNDO_TEST')).to eq( @@ -336,7 +336,7 @@ end it 'returns CONTROL with treatment doesnt exist' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') client.block_until_ready expect(client.get_treatment_with_config('nico_test', 'random_treatment')).to eq( @@ -350,7 +350,7 @@ end it 'returns CONTROL when server return 500' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') mock_split_changes_error expect(client.get_treatment_with_config('nico_test', 'FACUNDO_TEST')).to eq( @@ -372,7 +372,7 @@ context '#get_treatments' do before do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') end it 'returns treatments and check impressions' do @@ -476,7 +476,7 @@ context '#get_treatments_by_flag_set' do before do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') end it 'returns treatments and check impressions' do @@ -561,7 +561,7 @@ context '#get_treatments_by_flag_sets' do before do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') end it 'returns treatments and check impressions' do @@ -644,7 +644,7 @@ context '#get_treatments_with_config_by_flag_set' do before do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') end it 'returns treatments and check impressions' do @@ -754,7 +754,7 @@ context '#get_treatments_with_config_by_flag_sets' do before do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') end it 'returns treatments and check impressions' do @@ -858,7 +858,7 @@ context '#get_treatments_with_config' do it 'returns treatments and check impressions' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') client.block_until_ready result = client.get_treatments_with_config('nico_test', %w[FACUNDO_TEST MAURO_TEST Test_Save_1]) expect(result[:FACUNDO_TEST]).to eq( @@ -898,7 +898,7 @@ end it 'returns treatments with input validation' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') client.block_until_ready result1 = client.get_treatments_with_config('nico_test', %w[FACUNDO_TEST "" nil]) result2 = client.get_treatments_with_config('', %w["" MAURO_TEST Test_Save_1]) @@ -937,7 +937,7 @@ end it 'returns CONTROL with treatment doesnt exist' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') client.block_until_ready result = client.get_treatments_with_config('nico_test', %w[FACUNDO_TEST random_treatment]) @@ -962,7 +962,7 @@ end it 'returns CONTROL when server return 500' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') mock_split_changes_error result = client.get_treatments_with_config('nico_test', %w[FACUNDO_TEST MAURO_TEST Test_Save_1]) @@ -1082,7 +1082,7 @@ context '#track' do it 'returns true' do stub_request(:post, 'https://events.split.io/api/events/bulk').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916').to_return(status: 200, body: '') properties = { property_1: 1, @@ -1141,7 +1141,7 @@ flag_sets_filter: ['set_3', '@3we']) end before do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?sets=set_3&since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1&sets=set_3') .to_return(status: 200, body: splits) mock_segment_changes('segment1', segment1, '-1') mock_segment_changes('segment1', segment1, '1470947453877') @@ -1203,12 +1203,12 @@ private def mock_split_changes(splits_json) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: splits_json) end def mock_split_changes_error - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 500) end diff --git a/spec/integrations/push_client_spec.rb b/spec/integrations/push_client_spec.rb index 6c28960b..721340b2 100644 --- a/spec/integrations/push_client_spec.rb +++ b/spec/integrations/push_client_spec.rb @@ -16,11 +16,10 @@ let(:event_segment_update_must_fetch) { "fb\r\nid: 123\nevent: message\ndata: {\"id\":\"1\",\"clientId\":\"emptyClientId\",\"connectionId\":\"1\",\"timestamp\":1582045421733,\"channel\":\"mauroc\",\"data\":\"{\\\"type\\\" : \\\"SEGMENT_UPDATE\\\",\\\"changeNumber\\\": 1470947453879, \\\"segmentName\\\" : \\\"segment3\\\"}\",\"name\":\"asdasd\"}\n\n\r\n" } let(:event_segment_update_must_not_fetch) { "fb\r\nid: 123\nevent: message\ndata: {\"id\":\"1\",\"clientId\":\"emptyClientId\",\"connectionId\":\"1\",\"timestamp\":1582045421733,\"channel\":\"mauroc\",\"data\":\"{\\\"type\\\" : \\\"SEGMENT_UPDATE\\\",\\\"changeNumber\\\": -1, \\\"segmentName\\\" : \\\"segment3\\\"}\",\"name\":\"asdasd\"}\n\n\r\n" } let(:event_occupancy_with_publishers) { "d4\r\nevent: message\ndata: {\"id\":\"123\",\"timestamp\":1586803930362,\"encoding\":\"json\",\"channel\":\"[?occupancy=metrics.publishers]control_pri\",\"data\":\"{\\\"metrics\\\":{\\\"publishers\\\":2}}\",\"name\":\"[meta]occupancy\"}\n\n\r\nfb\r\nid: 123\nevent: message\ndata: {\"id\":\"1\",\"clientId\":\"emptyClientId\",\"connectionId\":\"1\",\"timestamp\":1582045421733,\"channel\":\"mauroc\",\"data\":\"{\\\"type\\\" : \\\"SPLIT_UPDATE\\\",\\\"changeNumber\\\": 1585948850111}\",\"name\":\"asdasd\"}\n\n\r\n" } - let(:event_occupancy_without_publishers) { "d4\r\nevent: message\ndata: {\"id\":\"123\",\"timestamp\":1586803930362,\"encoding\":\"json\",\"channel\":\"[?occupancy=metrics.publishers]control_pri\",\"data\":\"{\\\"metrics\\\":{\\\"publishers\\\":0}}\",\"name\":\"[meta]occupancy\"}\n\n\r\n" } + let(:event_occupancy_without_publishers) { "d4\r\nevent: message\ndata: {\"id\":\"123\",\"timestamp\":1586803930362,\"encoding\":\"json\",\"channel\":\"[?occupancy=metrics.publishers]control_sec\",\"data\":\"{\\\"metrics\\\":{\\\"publishers\\\":0}}\",\"name\":\"[meta]occupancy\"}\n\n\r\nd4\r\nevent: message\ndata: {\"id\":\"123\",\"timestamp\":1586803930362,\"encoding\":\"json\",\"channel\":\"[?occupancy=metrics.publishers]control_pri\",\"data\":\"{\\\"metrics\\\":{\\\"publishers\\\":0}}\",\"name\":\"[meta]occupancy\"}\n\n\r\n" } let(:event_control_STREAMING_PAUSED) { "d4\r\nevent: message\ndata: {\"id\":\"123\",\"clientId\":\"emptyClientId\",\"timestamp\":1582056812285,\"encoding\":\"json\",\"channel\":\"control_pri\",\"data\":\"{\\\"type\\\":\\\"CONTROL\\\",\\\"controlType\\\":\\\"STREAMING_PAUSED\\\"}\"}\n\n\r\n" } let(:event_control_STREAMING_RESUMED) { "d4\r\nevent: message\ndata: {\"id\":\"123\",\"clientId\":\"emptyClientId\",\"timestamp\":1582056812285,\"encoding\":\"json\",\"channel\":\"control_pri\",\"data\":\"{\\\"type\\\":\\\"CONTROL\\\",\\\"controlType\\\":\\\"STREAMING_RESUMED\\\"}\"}\n\n\r\n" } let(:event_control_STREAMING_DISABLED) { "d4\r\nevent: message\ndata: {\"id\":\"123\",\"clientId\":\"emptyClientId\",\"timestamp\":1582056812285,\"encoding\":\"json\",\"channel\":\"control_pri\",\"data\":\"{\\\"type\\\":\\\"CONTROL\\\",\\\"controlType\\\":\\\"STREAMING_DISABLED\\\"}\"}\n\n\r\n" } - let(:auth_service_url) { 'https://auth.fake.io/api/auth' } let(:splits) do File.read(File.join(SplitIoClient.root, 'spec/test_data/integrations/splits_push.json')) @@ -52,14 +51,14 @@ mock_splits_request(splits2, '1585948850109') mock_splits_request(splits3, '1585948850110') mock_segment_changes('segment3', segment3, '-1') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850111').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850111').to_return(status: 200, body: '') mock_server do |server| server.setup_response('/') do |_, res| send_content(res, event_split_update_must_fetch) end - stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -75,9 +74,9 @@ client.block_until_ready sleep(2) expect(client.get_treatment('admin', 'push_test')).to eq('after_fetch') - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1')).to have_been_made.at_least_times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850109')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850110')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.at_least_times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850109')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850110')).to have_been_made.times(1) client.destroy end end @@ -92,7 +91,7 @@ send_content(res, event_split_update_must_not_fetch) end - stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -106,9 +105,9 @@ client.block_until_ready(1) sleep(1) expect(client.get_treatment('admin', 'push_test')).to eq('on') - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850109')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850110')).to have_been_made.times(0) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850109')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850110')).to have_been_made.times(0) client.destroy end end @@ -124,7 +123,7 @@ send_content(res, event_split_update_missing_change_number) end - stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -138,9 +137,9 @@ client.block_until_ready(1) sleep(1) expect(client.get_treatment('admin', 'push_test')).to eq('on') - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850109')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850110')).to have_been_made.times(0) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850109')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850110')).to have_been_made.times(0) end end @@ -150,14 +149,11 @@ mock_splits_request(splits3, '1585948850110') mock_segment_changes('segment3', segment3, '-1') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1585948850111").to_return(status: 200, body: '') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850111").to_return(status: 200, body: '') stub_request(:get, "https://sdk.split.io/api/segmentChanges/bilal_segment?since=-1").to_return(status: 200, body: '') - mock_server do |server| - server.setup_response('/') do |_, res| - send_content(res, event_split_iff_update_no_compression) - end + stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) - stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + mock_server do |server| streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -169,9 +165,12 @@ client = factory.client client.block_until_ready + server.setup_response('/') do |_, res| + send_content(res, event_split_iff_update_no_compression) + end + treatment = 'control' for i in 1..5 do - p i sleep(1) treatment = client.get_treatment('admin', 'bilal_split') break if treatment != 'control' @@ -187,13 +186,13 @@ mock_splits_request(splits3, '1585948850110') mock_segment_changes('segment3', segment3, '-1') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850111').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850111').to_return(status: 200, body: '') mock_server do |server| server.setup_response('/') do |_, res| send_content(res, event_split_iff_update_incorrect_pcn) end - stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -216,13 +215,13 @@ mock_splits_request(splits3, '1585948850110') mock_segment_changes('segment3', segment3, '-1') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850111').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850111').to_return(status: 200, body: '') mock_server do |server| server.setup_response('/') do |_, res| send_content(res, event_split_iff_update_missing_definition) end - stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -245,13 +244,13 @@ mock_splits_request(splits3, '1585948850110') mock_segment_changes('segment3', segment3, '-1') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850111').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850111').to_return(status: 200, body: '') mock_server do |server| server.setup_response('/') do |_, res| send_content(res, event_split_iff_update_incorrect_compression) end - stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -281,7 +280,7 @@ send_content(res, event_split_kill_must_fetch) end - stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -294,9 +293,9 @@ client.block_until_ready sleep(2) expect(client.get_treatment('admin', 'push_test')).to eq('after_fetch') - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850109')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850110')).to have_been_made.at_least_times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850109')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850110')).to have_been_made.at_least_times(1) client.destroy end end @@ -305,14 +304,14 @@ mock_splits_request(splits, -1) mock_splits_request(splits2, 1_585_948_850_109) mock_segment_changes('segment3', segment3, '-1') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850110').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850110').to_return(status: 200, body: '') mock_server do |server| server.setup_response('/') do |_, res| send_content(res, event_split_kill_must_not_fetch) end - stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -326,9 +325,9 @@ client.block_until_ready(1) sleep(2) expect(client.get_treatment('admin', 'push_test')).to eq('on') - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850109')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850110')).to have_been_made.times(0) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850109')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850110')).to have_been_made.times(0) client.destroy end end @@ -347,7 +346,7 @@ send_content(res, event_segment_update_must_fetch) end - stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -376,7 +375,7 @@ send_content(res, event_segment_update_must_not_fetch) end - stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -401,14 +400,14 @@ mock_splits_request(splits2, 1_585_948_850_109) mock_splits_request(splits3, 1_585_948_850_110) mock_segment_changes('segment3', segment3, '-1') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850111').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850111').to_return(status: 200, body: '') mock_server do |server| server.setup_response('/') do |_, res| send_content(res, event_occupancy_with_publishers) end - stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -437,7 +436,7 @@ send_content(res, event_occupancy_without_publishers) end - stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -468,7 +467,7 @@ send_content(res, event_control_STREAMING_PAUSED) end - stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -497,7 +496,7 @@ send_content(res, event_control_STREAMING_RESUMED) end - stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -520,14 +519,14 @@ mock_splits_request(splits2, 1_585_948_850_109) mock_splits_request(splits3, 1_585_948_850_110) mock_segment_changes('segment3', segment3, '-1') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1585948850111').to_return(status: 200, body: '') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1585948850111').to_return(status: 200, body: '') mock_server do |server| server.setup_response('/') do |_, res| send_content(res, event_control_STREAMING_DISABLED) end - stub_request(:get, auth_service_url).to_return(status: 200, body: auth_body_response) + stub_request(:get, auth_service_url + "?s=1.1").to_return(status: 200, body: auth_body_response) streaming_service_url = server.base_uri factory = SplitIoClient::SplitFactory.new( @@ -560,7 +559,7 @@ def send_content(res, content) end def mock_splits_request(splits_json, since) - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=#{since}") + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=#{since}") .to_return(status: 200, body: splits_json) end diff --git a/spec/repository_helper.rb b/spec/repository_helper.rb index 994c9ca9..f4a72ab6 100644 --- a/spec/repository_helper.rb +++ b/spec/repository_helper.rb @@ -13,16 +13,16 @@ flag_sets_repository, flag_set_filter) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', :sets => []}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', conditions: [], :sets => []}], -1, config) expect(feature_flag_repository.get_split('split1').nil?).to eq(true) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', :sets => ['set_3']}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', conditions: [], :sets => ['set_3']}], -1, config) expect(feature_flag_repository.get_split('split1').nil?).to eq(true) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', :sets => ['set_1']}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', conditions: [], :sets => ['set_1']}], -1, config) expect(feature_flag_repository.get_split('split1').nil?).to eq(false) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ARCHIVED', :sets => ['set_1']}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ARCHIVED', conditions: [], :sets => ['set_1']}], -1, config) expect(feature_flag_repository.get_split('split1').nil?).to eq(true) end @@ -35,16 +35,16 @@ flag_sets_repository, flag_set_filter) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', :sets => []}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ACTIVE', conditions: [], :sets => []}], -1, config) expect(feature_flag_repository.get_split('split1').nil?).to eq(false) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split2', :status => 'ACTIVE', :sets => ['set_3']}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split2', :status => 'ACTIVE', conditions: [], :sets => ['set_3']}], -1, config) expect(feature_flag_repository.get_split('split2').nil?).to eq(false) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split3', :status => 'ACTIVE', :sets => ['set_1']}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split3', :status => 'ACTIVE', conditions: [], :sets => ['set_1']}], -1, config) expect(feature_flag_repository.get_split('split1').nil?).to eq(false) - SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ARCHIVED', :sets => ['set_1']}], -1, config) + SplitIoClient::Helpers::RepositoryHelper.update_feature_flag_repository(feature_flag_repository, [{:name => 'split1', :status => 'ARCHIVED', conditions: [], :sets => ['set_1']}], -1, config) expect(feature_flag_repository.get_split('split1').nil?).to eq(true) end end diff --git a/spec/splitclient/split_client_spec.rb b/spec/splitclient/split_client_spec.rb index c82d225d..55b4447d 100644 --- a/spec/splitclient/split_client_spec.rb +++ b/spec/splitclient/split_client_spec.rb @@ -3,40 +3,96 @@ require 'spec_helper' describe SplitIoClient::SplitClient do - let(:config) { SplitIoClient::SplitConfig.new(cache_adapter: :memory, impressions_mode: :debug) } - let(:segments_repository) { SplitIoClient::Cache::Repositories::SegmentsRepository.new(config) } - let(:flag_sets_repository) {SplitIoClient::Cache::Repositories::MemoryFlagSetsRepository.new([]) } - let(:flag_set_filter) {SplitIoClient::Cache::Filter::FlagSetsFilter.new([]) } - let(:splits_repository) { SplitIoClient::Cache::Repositories::SplitsRepository.new(config, flag_sets_repository, flag_set_filter) } - let(:impressions_repository) {SplitIoClient::Cache::Repositories::ImpressionsRepository.new(config) } - let(:runtime_producer) { SplitIoClient::Telemetry::RuntimeProducer.new(config) } - let(:events_repository) { SplitIoClient::Cache::Repositories::EventsRepository.new(config, 'sdk_key', runtime_producer) } - let(:impression_manager) { SplitIoClient::Engine::Common::ImpressionManager.new(config, impressions_repository, SplitIoClient::Engine::Common::NoopImpressionCounter.new, runtime_producer, SplitIoClient::Observers::NoopImpressionObserver.new, SplitIoClient::Engine::Impressions::NoopUniqueKeysTracker.new) } - let(:evaluation_producer) { SplitIoClient::Telemetry::EvaluationProducer.new(config) } - let(:evaluator) { SplitIoClient::Engine::Parser::Evaluator.new(segments_repository, splits_repository, config) } - let(:split_client) { SplitIoClient::SplitClient.new('sdk_key', {:splits => splits_repository, :segments => segments_repository, :impressions => impressions_repository, :events => events_repository}, nil, config, impression_manager, evaluation_producer, evaluator, SplitIoClient::Validators.new(config)) } - - let(:splits) do - File.read(File.join(SplitIoClient.root, 'spec/test_data/integrations/splits.json')) - end + context 'split client methods' do + let(:config) { SplitIoClient::SplitConfig.new(cache_adapter: :memory, impressions_mode: :debug) } + let(:segments_repository) { SplitIoClient::Cache::Repositories::SegmentsRepository.new(config) } + let(:flag_sets_repository) {SplitIoClient::Cache::Repositories::MemoryFlagSetsRepository.new([]) } + let(:flag_set_filter) {SplitIoClient::Cache::Filter::FlagSetsFilter.new([]) } + let(:splits_repository) { SplitIoClient::Cache::Repositories::SplitsRepository.new(config, flag_sets_repository, flag_set_filter) } + let(:impressions_repository) {SplitIoClient::Cache::Repositories::ImpressionsRepository.new(config) } + let(:runtime_producer) { SplitIoClient::Telemetry::RuntimeProducer.new(config) } + let(:events_repository) { SplitIoClient::Cache::Repositories::EventsRepository.new(config, 'sdk_key', runtime_producer) } + let(:impression_manager) { SplitIoClient::Engine::Common::ImpressionManager.new(config, impressions_repository, SplitIoClient::Engine::Common::NoopImpressionCounter.new, runtime_producer, SplitIoClient::Observers::NoopImpressionObserver.new, SplitIoClient::Engine::Impressions::NoopUniqueKeysTracker.new) } + let(:evaluation_producer) { SplitIoClient::Telemetry::EvaluationProducer.new(config) } + let(:evaluator) { SplitIoClient::Engine::Parser::Evaluator.new(segments_repository, splits_repository, config) } + let(:split_client) { SplitIoClient::SplitClient.new('sdk_key', {:splits => splits_repository, :segments => segments_repository, :impressions => impressions_repository, :events => events_repository}, nil, config, impression_manager, evaluation_producer, evaluator, SplitIoClient::Validators.new(config)) } - before do - splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:splits][2]], [], -1) - end + let(:splits) do + File.read(File.join(SplitIoClient.root, 'spec/test_data/integrations/splits.json')) + end + + before do + splits_repository.update([JSON.parse(splits,:symbolize_names => true)[:splits][2]], [], -1) + end - it 'check getting treatments' do - expect(split_client.get_treatment('key', 'testing222')).to eq('off') - expect(split_client.get_treatments('key', ['testing222'])).to eq({:testing222 => 'off'}) - expect(split_client.get_treatment_with_config('key', 'testing222')).to eq({:treatment => 'off', :config => nil}) - expect(split_client.get_treatments_with_config('key', ['testing222'])).to eq({:testing222 => {:treatment => 'off', :config => nil}}) - expect(split_client.get_treatments_by_flag_set('key', 'set_1')).to eq({:testing222 => 'off'}) - expect(split_client.get_treatments_by_flag_sets('key', ['set_2'])).to eq({:testing222 => 'off'}) - expect(split_client.get_treatments_with_config_by_flag_set('key', 'set_1')).to eq({:testing222 => {:treatment => 'off', :config => nil}}) - expect(split_client.get_treatments_with_config_by_flag_sets('key', ['set_2'])).to eq({:testing222 => {:treatment => 'off', :config => nil}}) + it 'check getting treatments' do + expect(split_client.get_treatment('key', 'testing222')).to eq('off') + expect(split_client.get_treatments('key', ['testing222'])).to eq({:testing222 => 'off'}) + expect(split_client.get_treatment_with_config('key', 'testing222')).to eq({:treatment => 'off', :config => nil}) + expect(split_client.get_treatments_with_config('key', ['testing222'])).to eq({:testing222 => {:treatment => 'off', :config => nil}}) + expect(split_client.get_treatments_by_flag_set('key', 'set_1')).to eq({:testing222 => 'off'}) + expect(split_client.get_treatments_by_flag_sets('key', ['set_2'])).to eq({:testing222 => 'off'}) + expect(split_client.get_treatments_with_config_by_flag_set('key', 'set_1')).to eq({:testing222 => {:treatment => 'off', :config => nil}}) + expect(split_client.get_treatments_with_config_by_flag_sets('key', ['set_2'])).to eq({:testing222 => {:treatment => 'off', :config => nil}}) + end + + it 'check track' do + expect(split_client.track('key', 'account', 'event', 1)).to eq(true) + end end - it 'check track' do - expect(split_client.track('key', 'account', 'event', 1)).to eq(true) + context 'post data before shutdown' do + let(:splits) do + File.read(File.join(SplitIoClient.root, 'spec/test_data/integrations/splits.json')) + end + let(:segment1) do + File.read(File.join(SplitIoClient.root, 'spec/test_data/integrations/segment1.json')) + end + let(:segment2) do + File.read(File.join(SplitIoClient.root, 'spec/test_data/integrations/segment2.json')) + end + let(:segment3) do + File.read(File.join(SplitIoClient.root, 'spec/test_data/integrations/segment3.json')) + end + + it 'posting impressions and events' do + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') + .to_return(status: 200, body: splits) + stub_request(:post, 'https://events.split.io/api/events/bulk').to_return(status: 200, body: '') + stub_request(:post, 'https://events.split.io/api/testImpressions/bulk').to_return(status: 200, body: '') + stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: '') + stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/usage').to_return(status: 200, body: '') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916").to_return(status: 200, body: 'ok') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916sets=set_3&").to_return(status: 200, body: 'ok') + mock_segment_changes('segment1', segment1, '-1') + mock_segment_changes('segment1', segment1, '1470947453877') + mock_segment_changes('segment2', segment2, '-1') + mock_segment_changes('segment2', segment2, '1470947453878') + mock_segment_changes('segment3', segment3, '-1') + + factory5 = SplitIoClient::SplitFactory.new('test_api_key', + features_refresh_rate: 9999, + streaming_enabled: false) + client5 = factory5.client + client5.block_until_ready(5) + + for a in 1..100 do + expect(client5.track('id' + a.to_s, 'account', 'event', 1)).to be_truthy + end + expect(client5.instance_variable_get(:@events_repository).empty?).to be(false) + + expect(client5.get_treatment('nico_test', 'FACUNDO_TEST')).to eq 'on' + expect(client5.instance_variable_get(:@impressions_repository).empty?).to be(false) + + client5.destroy() + + expect(client5.instance_variable_get(:@impressions_repository).empty?).to be(true) + expect(client5.instance_variable_get(:@events_repository).empty?).to be(true) + end end +end +def mock_segment_changes(segment_name, segment_json, since) + stub_request(:get, "https://sdk.split.io/api/segmentChanges/#{segment_name}?since=#{since}") + .to_return(status: 200, body: segment_json) end diff --git a/spec/splitclient/split_factory_spec.rb b/spec/splitclient/split_factory_spec.rb index 14a1b20d..5cfec28c 100644 --- a/spec/splitclient/split_factory_spec.rb +++ b/spec/splitclient/split_factory_spec.rb @@ -69,7 +69,7 @@ let(:mode) { :standalone } it 'log an error stating Api Key is invalid' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: []) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: '') @@ -89,7 +89,7 @@ let(:mode) { :standalone } it 'log an error stating Api Key is invalid' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: []) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: '') @@ -112,9 +112,9 @@ end it 'log an error stating Api Key is invalid' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: splits_with_segments_json) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1473863097220') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1473863097220') .to_return(status: 200, body: []) stub_request(:get, 'https://sdk.split.io/api/segmentChanges/employees?since=-1') .to_return(status: 403, body: []) @@ -140,7 +140,7 @@ let(:mode) { :standalone } it 'log an error' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: []) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/usage') @@ -174,7 +174,7 @@ end it 'logs warnings stating number of factories' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: []) described_class.new('API_KEY', options) @@ -188,7 +188,7 @@ end it 'decreases number of registered factories on client destroy' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: []) expect(SplitIoClient.split_factory_registry.number_of_factories_for('API_KEY')).to eq 0 @@ -203,7 +203,7 @@ end it 'active and redundant factories' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: []) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') @@ -239,7 +239,7 @@ .to_return(status: 200, body: 'ok') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: 'ok') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: []) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: '') @@ -260,7 +260,7 @@ .to_return(status: 200, body: 'ok') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: 'ok') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: []) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: '') @@ -281,7 +281,7 @@ .to_return(status: 200, body: 'ok') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: 'ok') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: []) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: '') @@ -302,7 +302,7 @@ .to_return(status: 200, body: 'ok') stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: 'ok') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: []) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: '') diff --git a/spec/splitclient/split_manager_spec.rb b/spec/splitclient/split_manager_spec.rb index bc2d9c6f..4714a40f 100644 --- a/spec/splitclient/split_manager_spec.rb +++ b/spec/splitclient/split_manager_spec.rb @@ -10,7 +10,7 @@ let(:segments) { File.read(File.expand_path(File.join(File.dirname(__FILE__), '../test_data/segments/engine_segments.json'))) } before do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: splits) stub_request(:get, 'https://sdk.split.io/api/segmentChanges/demo?since=-1') @@ -25,7 +25,7 @@ stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config') .to_return(status: 200, body: 'ok') - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1473413807667") + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1473413807667") .to_return(status: 200, body: "", headers: {}) end @@ -85,7 +85,7 @@ context '#splits' do it 'returns empty array and logs error when not ready' do - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=-1") + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=-1") .to_return(status: 200, body: "", headers: {}) allow(subject).to receive(:ready?).and_return(false) @@ -109,10 +109,10 @@ let(:splits3) { File.read(File.expand_path(File.join(File.dirname(__FILE__), '../test_data/splits/splits3.json'))) } before do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: splits3) - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1473863097220") + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1473863097220") .to_return(status: 200, body: "", headers: {}) end @@ -137,10 +137,10 @@ let(:splits4) { File.read(File.expand_path(File.join(File.dirname(__FILE__), '../test_data/splits/splits4.json'))) } before do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: splits4) - stub_request(:get, "https://sdk.split.io/api/splitChanges?since") + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since") .to_return(status: 200, body: "", headers: {}) end diff --git a/spec/splitclient_rb_corner_cases_spec.rb b/spec/splitclient_rb_corner_cases_spec.rb index bbed0468..b5d763ea 100644 --- a/spec/splitclient_rb_corner_cases_spec.rb +++ b/spec/splitclient_rb_corner_cases_spec.rb @@ -21,10 +21,10 @@ before do stub_request(:post, 'https://events.split.io/api/testImpressions/bulk').to_return(status: 200, body: '') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1').to_return(status: 200, body: splits_json) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1').to_return(status: 200, body: splits_json) stub_request(:get, 'https://sdk.split.io/api/segmentChanges/demo?since=-1').to_return(status: 200, body: segment_res) stub_request(:get, 'https://sdk.split.io/api/segmentChanges/employees?since=-1').to_return(status: 200, body: segment_res) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1473413807667').to_return(status: 200, body: segment_res) + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1473413807667').to_return(status: 200, body: segment_res) stub_request(:post, 'https://telemetry.split.io/api/v1/metrics/config').to_return(status: 200, body: segment_res) stub_request(:post, 'https://events.split.io/api/testImpressions/count').to_return(status: 200, body: '') end diff --git a/spec/sse/event_source/client_spec.rb b/spec/sse/event_source/client_spec.rb index 416b66ad..3547f6a1 100644 --- a/spec/sse/event_source/client_spec.rb +++ b/spec/sse/event_source/client_spec.rb @@ -48,10 +48,10 @@ context 'tests' do it 'receive split update event' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .with(headers: { 'Authorization' => 'Bearer client-spec-key' }) .to_return(status: 200, body: '{"splits":[],"since":-1,"till":5564531221}') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=5564531221') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=5564531221') .with(headers: { 'Authorization' => 'Bearer client-spec-key' }) .to_return(status: 200, body: '{"splits":[],"since":5564531221,"till":5564531221}') @@ -68,7 +68,7 @@ expect(sse_client.connected?).to eq(true) expect(push_status_queue.pop(true)).to eq(SplitIoClient::Constants::PUSH_CONNECTED) sleep 1 - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1').with(headers: { 'Authorization' => 'Bearer client-spec-key' })).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1').with(headers: { 'Authorization' => 'Bearer client-spec-key' })).to have_been_made.times(1) sse_client.close @@ -79,10 +79,10 @@ end it 'receive split kill event' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .with(headers: { 'Authorization' => 'Bearer client-spec-key' }) .to_return(status: 200, body: '{"splits":[],"since":-1,"till":5564531221}') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=5564531221') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=5564531221') .with(headers: { 'Authorization' => 'Bearer client-spec-key' }) .to_return(status: 200, body: '{"splits":[],"since":5564531221,"till":5564531221}') @@ -99,7 +99,7 @@ expect(sse_client.connected?).to eq(true) expect(push_status_queue.pop(true)).to eq(SplitIoClient::Constants::PUSH_CONNECTED) sleep 1 - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1').with(headers: { 'Authorization' => 'Bearer client-spec-key' })).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1').with(headers: { 'Authorization' => 'Bearer client-spec-key' })).to have_been_made.times(1) sse_client.close @@ -150,7 +150,7 @@ expect(connected).to eq(true) expect(sse_client.connected?).to eq(true) expect(push_status_queue.pop(true)).to eq(SplitIoClient::Constants::PUSH_CONNECTED) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1').with(headers: { 'Authorization' => 'Bearer client-spec-key' })).to have_been_made.times(0) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1').with(headers: { 'Authorization' => 'Bearer client-spec-key' })).to have_been_made.times(0) expect(a_request(:get, 'https://sdk.split.io/api/segmentChanges/segment-test?since=-1').with(headers: { 'Authorization' => 'Bearer client-spec-key' })).to have_been_made.times(0) sse_client.close @@ -172,7 +172,7 @@ expect(connected).to eq(true) expect(sse_client.connected?).to eq(true) expect(push_status_queue.pop(true)).to eq(SplitIoClient::Constants::PUSH_CONNECTED) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1').with(headers: { 'Authorization' => 'Bearer client-spec-key' })).to have_been_made.times(0) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1').with(headers: { 'Authorization' => 'Bearer client-spec-key' })).to have_been_made.times(0) expect(a_request(:get, 'https://sdk.split.io/api/segmentChanges/segment-test?since=-1').with(headers: { 'Authorization' => 'Bearer client-spec-key' })).to have_been_made.times(0) sse_client.close diff --git a/spec/sse/notification_manager_keeper_spec.rb b/spec/sse/notification_manager_keeper_spec.rb index 038ab2d5..00b9b62c 100644 --- a/spec/sse/notification_manager_keeper_spec.rb +++ b/spec/sse/notification_manager_keeper_spec.rb @@ -30,6 +30,9 @@ it 'STREAMING_RESUMED without publishers enabled' do data = { 'metrics' => { 'publishers' => 0 } } + event = SplitIoClient::SSE::EventSource::StreamData.new('message', 'test-client-id', data, 'control_sec') + noti_manager_keeper.handle_incoming_occupancy_event(event) + event = SplitIoClient::SSE::EventSource::StreamData.new('message', 'test-client-id', data, 'control_pri') noti_manager_keeper.handle_incoming_occupancy_event(event) @@ -54,6 +57,9 @@ context 'OCCUPANCY EVENT' do it 'first time without publishers available' do data = { 'metrics' => { 'publishers' => 0 } } + event = SplitIoClient::SSE::EventSource::StreamData.new('message', 'test-client-id', data, 'control_sec') + noti_manager_keeper.handle_incoming_occupancy_event(event) + event = SplitIoClient::SSE::EventSource::StreamData.new('message', 'test-client-id', data, 'control_pri') noti_manager_keeper.handle_incoming_occupancy_event(event) @@ -70,6 +76,9 @@ it 'handle many events' do data = { 'metrics' => { 'publishers' => 0 } } + event = SplitIoClient::SSE::EventSource::StreamData.new('message', 'test-client-id', data, 'control_sec') + noti_manager_keeper.handle_incoming_occupancy_event(event) + event = SplitIoClient::SSE::EventSource::StreamData.new('message', 'test-client-id', data, 'control_pri') noti_manager_keeper.handle_incoming_occupancy_event(event) expect(push_status_queue.pop(true)).to eq(SplitIoClient::Constants::PUSH_SUBSYSTEM_DOWN) diff --git a/spec/sse/workers/segments_worker_spec.rb b/spec/sse/workers/segments_worker_spec.rb index 37d6e868..aad5db85 100644 --- a/spec/sse/workers/segments_worker_spec.rb +++ b/spec/sse/workers/segments_worker_spec.rb @@ -101,7 +101,7 @@ private def mock_split_changes(splits_json) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: splits_json) end diff --git a/spec/sse/workers/splits_worker_spec.rb b/spec/sse/workers/splits_worker_spec.rb index 5cae7f59..b45aef73 100644 --- a/spec/sse/workers/splits_worker_spec.rb +++ b/spec/sse/workers/splits_worker_spec.rb @@ -51,9 +51,9 @@ end it 'add change number - must tigger fetch - with retries' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1').to_return(status: 200, body: '{"splits": [],"since": -1,"till": 1506703262918}') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262918').to_return(status: 200, body: '{"splits": [],"since": 1506703262918,"till": 1506703262918}') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262918&till=1506703262919').to_return(status: 200, body: '{"splits": [],"since": 1506703262919,"till": 1506703262919}') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1').to_return(status: 200, body: '{"splits": [],"since": -1,"till": 1506703262918}') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262918').to_return(status: 200, body: '{"splits": [],"since": 1506703262918,"till": 1506703262918}') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262918&till=1506703262919').to_return(status: 200, body: '{"splits": [],"since": 1506703262919,"till": 1506703262919}') worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher) worker.start @@ -61,39 +61,39 @@ sleep 1 - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1')).to have_been_made.times(1) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262918')).to have_been_made.at_least_times(2) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262918&till=1506703262919')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1')).to have_been_made.times(1) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262918')).to have_been_made.at_least_times(2) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262918&till=1506703262919')).to have_been_made.times(1) end it 'must trigger fetch' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1').to_return(status: 200, body: '{"splits": [],"since": -1,"till": 1506703262916}') - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916').to_return(status: 200, body: '{"splits": [],"since": 1506703262916,"till": 1506703262918}') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1').to_return(status: 200, body: '{"splits": [],"since": -1,"till": 1506703262916}') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916').to_return(status: 200, body: '{"splits": [],"since": 1506703262916,"till": 1506703262918}') worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher) worker.start worker.add_to_queue(SplitIoClient::SSE::EventSource::StreamData.new("SPLIT_UPDATE", 123, JSON.parse('{"type":"SPLIT_UPDATE","changeNumber":1506703262918}'), 'test')) sleep 1 - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916')).to have_been_made.once + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916')).to have_been_made.once end it 'must not trigger fetch' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1').to_return(status: 200, body: '{"splits": [],"since": -1,"till": 1506703262916}') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1').to_return(status: 200, body: '{"splits": [],"since": -1,"till": 1506703262916}') worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher) worker.start worker.add_to_queue(SplitIoClient::SSE::EventSource::StreamData.new("SPLIT_UPDATE", 123, JSON.parse('{"type":"SPLIT_UPDATE","changeNumber":1506703262916}'), 'test')) sleep 1 - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916')).to have_been_made.times(0) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916')).to have_been_made.times(0) end it 'without start, must not fetch' do worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher) worker.add_to_queue(SplitIoClient::SSE::EventSource::StreamData.new("SPLIT_UPDATE", 123, JSON.parse('{"type":"SPLIT_UPDATE","changeNumber":1506703262918}'), 'test')) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916')).to have_been_made.times(0) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916')).to have_been_made.times(0) end end @@ -136,7 +136,7 @@ end it 'must kill split and trigger fetch' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916').to_return(status: 200, body: '{"splits": [],"since": 1506703262916,"till": 1506703262918}') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916').to_return(status: 200, body: '{"splits": [],"since": 1506703262916,"till": 1506703262918}') worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher) worker.start @@ -148,7 +148,7 @@ expect(split[:killed]).to be_truthy expect(split[:defaultTreatment]).to eq('on') expect(split[:changeNumber]).to eq(1_506_703_262_918) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916')).to have_been_made.once + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916')).to have_been_made.once end it 'must kill split and must not trigger fetch' do @@ -163,7 +163,7 @@ expect(split[:killed]).to be_truthy expect(split[:defaultTreatment]).to eq('on') expect(split[:changeNumber]).to eq(1_506_703_262_916) - expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?since=1506703262916')).to have_been_made.times(0) + expect(a_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1506703262916')).to have_been_made.times(0) end end @@ -195,8 +195,8 @@ SplitIoClient::Engine::Synchronizer.new(repositories, config, params) end it 'update split with and without flagset' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1234').to_return(status: 200, body: '{"splits": [],"since": 1234,"till": 1234}') - stub_request(:get, "https://sdk.split.io/api/splitChanges?since=1234&till=5564531221").to_return(status: 200, body: '{"splits": [],"since": 1234,"till": 5564531221}') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1234').to_return(status: 200, body: '{"splits": [],"since": 1234,"till": 1234}') + stub_request(:get, "https://sdk.split.io/api/splitChanges?s=1.1&since=1234&till=5564531221").to_return(status: 200, body: '{"splits": [],"since": 1234,"till": 5564531221}') stub_request(:get, "https://sdk.split.io/api/segmentChanges/bilal_segment?since=-1").to_return(status: 200, body: "") worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher) worker.start @@ -276,7 +276,7 @@ end it 'instant ff update split notification with segment matcher.' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1234').to_return(status: 200, body: '{"splits": [],"since": 1234,"till": 1234}') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1234').to_return(status: 200, body: '{"splits": [],"since": 1234,"till": 1234}') stub_request(:get, 'https://sdk.split.io/api/segmentChanges/maur-2?since=-1').to_return(status: 200, body: '{"name":"maur-2","added":["admin"],"removed":[],"since":-1,"till":-1}') worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher) worker.start @@ -290,7 +290,7 @@ end it 'should not update if definition is nil' do - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=1234').to_return(status: 200, body: '{"splits": [],"since": -1,"till": 1506703262918}') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=1234').to_return(status: 200, body: '{"splits": [],"since": -1,"till": 1506703262918}') worker = subject.new(synchronizer, config, splits_repository, telemetry_runtime_producer, segment_fetcher) worker.start @@ -304,7 +304,7 @@ private def mock_split_changes(splits_json) - stub_request(:get, 'https://sdk.split.io/api/splitChanges?since=-1') + stub_request(:get, 'https://sdk.split.io/api/splitChanges?s=1.1&since=-1') .to_return(status: 200, body: splits_json) end diff --git a/spec/telemetry/synchronizer_spec.rb b/spec/telemetry/synchronizer_spec.rb index 18e67594..5448027c 100644 --- a/spec/telemetry/synchronizer_spec.rb +++ b/spec/telemetry/synchronizer_spec.rb @@ -65,9 +65,9 @@ end it 'with data' do - splits_repository.update([{name: 'foo', trafficTypeName: 'tt_name_1'}, - {name: 'bar', trafficTypeName: 'tt_name_2'}, - {name: 'baz', trafficTypeName: 'tt_name_1'}], [], -1) + splits_repository.update([{name: 'foo', trafficTypeName: 'tt_name_1', conditions: []}, + {name: 'bar', trafficTypeName: 'tt_name_2', conditions: []}, + {name: 'baz', trafficTypeName: 'tt_name_1', conditions: []}], [], -1) segments_repository.add_to_segment(name: 'foo-1', added: [1, 2, 3], removed: []) segments_repository.add_to_segment(name: 'foo-2', added: [1, 2, 3, 4], removed: []) diff --git a/spec/test_data/splits/semver/between-semver.csv b/spec/test_data/splits/semver/between-semver.csv new file mode 100644 index 00000000..4225e710 --- /dev/null +++ b/spec/test_data/splits/semver/between-semver.csv @@ -0,0 +1,18 @@ +# version1, version2, version3, expected +1.1.1,2.2.2,3.3.3,true +1.1.1-rc.1,1.1.1-rc.2,1.1.1-rc.3,true +1.0.0-alpha,1.0.0-alpha.1,1.0.0-alpha.beta,true +1.0.0-alpha.1,1.0.0-alpha.beta,1.0.0-beta,true +1.0.0-alpha.beta,1.0.0-beta,1.0.0-beta.2,true +1.0.0-beta,1.0.0-beta.2,1.0.0-beta.11,true +1.0.0-beta.2,1.0.0-beta.11,1.0.0-rc.1,true +1.0.0-beta.11,1.0.0-rc.1,1.0.0,true +1.1.2,1.1.3,1.1.4,true +1.2.1,1.3.1,1.4.1,true +2.0.0,3.0.0,4.0.0,true +2.2.2,2.2.3-rc1,2.2.3,true +2.2.2,2.3.2-rc100,2.3.3,true +1.0.0-rc.1+build.1,1.2.3-beta,1.2.3-rc.1+build.123,true +3.3.3,3.3.3-alpha,3.3.4,false +2.2.2-rc.1,2.2.2+metadata,2.2.2-rc.10,false +1.1.1-rc.1,1.1.1-rc.3,1.1.1-rc.2,false \ No newline at end of file diff --git a/spec/test_data/splits/semver/equal-to-semver.csv b/spec/test_data/splits/semver/equal-to-semver.csv new file mode 100644 index 00000000..4ac0b7c6 --- /dev/null +++ b/spec/test_data/splits/semver/equal-to-semver.csv @@ -0,0 +1,7 @@ +# version1, version2, equals +1.1.1,1.1.1,true +1.1.1,1.1.1+metadata,false +1.1.1,1.1.1-rc.1,false +88.88.88,88.88.88,true +1.2.3----RC-SNAPSHOT.12.9.1--.12,1.2.3----RC-SNAPSHOT.12.9.1--.12,true +10.2.3-DEV-SNAPSHOT,10.2.3-SNAPSHOT-123,false \ No newline at end of file diff --git a/spec/test_data/splits/semver/invalid-semantic-versions.csv b/spec/test_data/splits/semver/invalid-semantic-versions.csv new file mode 100644 index 00000000..b9eb3e50 --- /dev/null +++ b/spec/test_data/splits/semver/invalid-semantic-versions.csv @@ -0,0 +1,26 @@ +# invalid +1 +1.2 +1.alpha.2 ++invalid +-invalid +-invalid+invalid +-invalid.01 +alpha +alpha.beta +alpha.beta.1 +alpha.1 +alpha+beta +alpha_beta +alpha. +alpha.. +beta +-alpha. +1.2 +1.2.3.DEV +1.2-SNAPSHOT +1.2.31.2.3----RC-SNAPSHOT.12.09.1--..12+788 +1.2-RC-SNAPSHOT +-1.0.3-gamma+b7718 ++justmeta +#99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..12 \ No newline at end of file diff --git a/spec/test_data/splits/semver/valid-semantic-versions.csv b/spec/test_data/splits/semver/valid-semantic-versions.csv new file mode 100644 index 00000000..da85709c --- /dev/null +++ b/spec/test_data/splits/semver/valid-semantic-versions.csv @@ -0,0 +1,25 @@ +# higher, lower +1.1.2,1.1.1 +1.0.0,1.0.0-rc.1 +1.1.0-rc.1,1.0.0-beta.11 +1.0.0-beta.11,1.0.0-beta.2 +1.0.0-beta.2,1.0.0-beta +1.0.0-beta,1.0.0-alpha.beta +1.0.0-alpha.beta,1.0.0-alpha.1 +1.0.0-alpha.1,1.0.0-alpha +2.2.2-rc.2+metadata-lalala,2.2.2-rc.1.2 +1.2.3,0.0.4 +1.1.2+meta,1.1.2-prerelease+meta +1.0.0-beta,1.0.0-alpha +1.0.0-alpha0.valid,1.0.0-alpha.0valid +1.0.0-rc.1+build.1,1.0.0-alpha-a.b-c-somethinglong+build.1-aef.1-its-okay +10.2.3-DEV-SNAPSHOT,1.2.3-SNAPSHOT-123 +1.1.1-rc2,1.0.0-0A.is.legal +1.2.3----RC-SNAPSHOT.12.9.1--.12+788,1.2.3----R-S.12.9.1--.12+meta +1.2.3----RC-SNAPSHOT.12.9.1--.12.88,1.2.3----RC-SNAPSHOT.12.9.1--.12 +9223372036854775807.9223372036854775807.9223372036854775807,9223372036854775807.9223372036854775807.9223372036854775806 +1.1.1-alpha.beta.rc.build.java.pr.support.10,1.1.1-alpha.beta.rc.build.java.pr.support +1.1.2,1.1.1 +1.2.1,1.1.1 +2.1.1,1.1.1 +1.1.1-rc.1,1.1.1-rc.0 \ No newline at end of file diff --git a/spec/test_data/splits/semver_matchers/semver_between.json b/spec/test_data/splits/semver_matchers/semver_between.json new file mode 100644 index 00000000..44edc2b6 --- /dev/null +++ b/spec/test_data/splits/semver_matchers/semver_between.json @@ -0,0 +1,86 @@ +{ + "splits": [ + { + "trafficTypeName": "user", + "name": "semver_between", + "trafficAllocation": 100, + "trafficAllocationSeed": 1068038034, + "seed": -1053389887, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "off", + "changeNumber": 1675259356568, + "algo": 2, + "configurations": {}, + "conditions": [ + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": + [ + {"keySelector": {"trafficType": "user", "attribute": "version"}, + "matcherType": "BETWEEN_SEMVER", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "dependencyMatcherData": null, + "booleanMatcherData": null, + "stringMatcherData": null, + "betweenStringMatcherData": {"start": "1.22.9", "end": "2.1.0"}} + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 + }, + { + "treatment": "off", + "size": 0 + } + ], + "label": "between semver" + }, + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user", + "attribute": null + }, + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 + } + ], + "label": "default rule" + } + ] + } + ], + "since": -1, + "till": 1675259356568 +} diff --git a/spec/test_data/splits/semver_matchers/semver_equalto.json b/spec/test_data/splits/semver_matchers/semver_equalto.json new file mode 100644 index 00000000..c3daa9ea --- /dev/null +++ b/spec/test_data/splits/semver_matchers/semver_equalto.json @@ -0,0 +1,85 @@ +{ + "splits": [ + { + "trafficTypeName": "user", + "name": "semver_equalto", + "trafficAllocation": 100, + "trafficAllocationSeed": 1068038034, + "seed": -1053389887, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "off", + "changeNumber": 1675259356568, + "algo": 2, + "configurations": {}, + "conditions": [ + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": + [ + {"keySelector": {"trafficType": "user", "attribute": "version"}, + "matcherType": "EQUAL_TO_SEMVER", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "dependencyMatcherData": null, + "booleanMatcherData": null, + "stringMatcherData": "1.22.9"} + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 + }, + { + "treatment": "off", + "size": 0 + } + ], + "label": "equal to semver" + }, + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user", + "attribute": null + }, + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 + } + ], + "label": "default rule" + } + ] + } + ], + "since": -1, + "till": 1675259356568 +} diff --git a/spec/test_data/splits/semver_matchers/semver_greater_or_equalto.json b/spec/test_data/splits/semver_matchers/semver_greater_or_equalto.json new file mode 100644 index 00000000..40f0f036 --- /dev/null +++ b/spec/test_data/splits/semver_matchers/semver_greater_or_equalto.json @@ -0,0 +1,85 @@ +{ + "splits": [ + { + "trafficTypeName": "user", + "name": "semver_greater_or_equalto", + "trafficAllocation": 100, + "trafficAllocationSeed": 1068038034, + "seed": -1053389887, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "off", + "changeNumber": 1675259356568, + "algo": 2, + "configurations": {}, + "conditions": [ + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": + [ + {"keySelector": {"trafficType": "user", "attribute": "version"}, + "matcherType": "GREATER_THAN_OR_EQUAL_TO_SEMVER", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "dependencyMatcherData": null, + "booleanMatcherData": null, + "stringMatcherData": "1.22.9"} + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 + }, + { + "treatment": "off", + "size": 0 + } + ], + "label": "greater than or equal to semver" + }, + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user", + "attribute": null + }, + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 + } + ], + "label": "default rule" + } + ] + } + ], + "since": -1, + "till": 1675259356568 +} diff --git a/spec/test_data/splits/semver_matchers/semver_inlist.json b/spec/test_data/splits/semver_matchers/semver_inlist.json new file mode 100644 index 00000000..9f1e6246 --- /dev/null +++ b/spec/test_data/splits/semver_matchers/semver_inlist.json @@ -0,0 +1,86 @@ +{ + "splits": [ + { + "trafficTypeName": "user", + "name": "semver_inlist", + "trafficAllocation": 100, + "trafficAllocationSeed": 1068038034, + "seed": -1053389887, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "off", + "changeNumber": 1675259356568, + "algo": 2, + "configurations": {}, + "conditions": [ + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": + [ + {"keySelector": {"trafficType": "user", "attribute": "version"}, + "matcherType": "IN_LIST_SEMVER", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": {"whitelist": ["1.22.9", "2.1.0"]}, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "dependencyMatcherData": null, + "booleanMatcherData": null, + "stringMatcherData": null, + "betweenStringMatcherData": null} + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 + }, + { + "treatment": "off", + "size": 0 + } + ], + "label": "between semver" + }, + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user", + "attribute": null + }, + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 + } + ], + "label": "default rule" + } + ] + } + ], + "since": -1, + "till": 1675259356568 +} diff --git a/spec/test_data/splits/semver_matchers/semver_less_or_equalto.json b/spec/test_data/splits/semver_matchers/semver_less_or_equalto.json new file mode 100644 index 00000000..9a46807f --- /dev/null +++ b/spec/test_data/splits/semver_matchers/semver_less_or_equalto.json @@ -0,0 +1,85 @@ +{ + "splits": [ + { + "trafficTypeName": "user", + "name": "semver_less_or_equalto", + "trafficAllocation": 100, + "trafficAllocationSeed": 1068038034, + "seed": -1053389887, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "off", + "changeNumber": 1675259356568, + "algo": 2, + "configurations": {}, + "conditions": [ + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": + [ + {"keySelector": {"trafficType": "user", "attribute": "version"}, + "matcherType": "LESS_THAN_OR_EQUAL_TO_SEMVER", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "dependencyMatcherData": null, + "booleanMatcherData": null, + "stringMatcherData": "1.22.9"} + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 100 + }, + { + "treatment": "off", + "size": 0 + } + ], + "label": "less than or equal to semver" + }, + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user", + "attribute": null + }, + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null, + "booleanMatcherData": null, + "dependencyMatcherData": null, + "stringMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "off", + "size": 100 + } + ], + "label": "default rule" + } + ] + } + ], + "since": -1, + "till": 1675259356568 +}