prefab-cloud-ruby 0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.envrc.sample +3 -0
 - data/.github/workflows/ruby.yml +46 -0
 - data/.gitmodules +3 -0
 - data/.rubocop.yml +13 -0
 - data/.tool-versions +1 -0
 - data/CHANGELOG.md +169 -0
 - data/CODEOWNERS +1 -0
 - data/Gemfile +26 -0
 - data/Gemfile.lock +188 -0
 - data/LICENSE.txt +20 -0
 - data/README.md +94 -0
 - data/Rakefile +50 -0
 - data/VERSION +1 -0
 - data/bin/console +21 -0
 - data/compile_protos.sh +18 -0
 - data/lib/prefab/client.rb +153 -0
 - data/lib/prefab/config_client.rb +292 -0
 - data/lib/prefab/config_client_presenter.rb +18 -0
 - data/lib/prefab/config_loader.rb +84 -0
 - data/lib/prefab/config_resolver.rb +77 -0
 - data/lib/prefab/config_value_unwrapper.rb +115 -0
 - data/lib/prefab/config_value_wrapper.rb +18 -0
 - data/lib/prefab/context.rb +179 -0
 - data/lib/prefab/context_shape.rb +20 -0
 - data/lib/prefab/context_shape_aggregator.rb +65 -0
 - data/lib/prefab/criteria_evaluator.rb +136 -0
 - data/lib/prefab/encryption.rb +65 -0
 - data/lib/prefab/error.rb +6 -0
 - data/lib/prefab/errors/env_var_parse_error.rb +11 -0
 - data/lib/prefab/errors/initialization_timeout_error.rb +13 -0
 - data/lib/prefab/errors/invalid_api_key_error.rb +19 -0
 - data/lib/prefab/errors/missing_default_error.rb +13 -0
 - data/lib/prefab/errors/missing_env_var_error.rb +11 -0
 - data/lib/prefab/errors/uninitialized_error.rb +13 -0
 - data/lib/prefab/evaluation.rb +52 -0
 - data/lib/prefab/evaluation_summary_aggregator.rb +87 -0
 - data/lib/prefab/example_contexts_aggregator.rb +78 -0
 - data/lib/prefab/exponential_backoff.rb +21 -0
 - data/lib/prefab/feature_flag_client.rb +42 -0
 - data/lib/prefab/http_connection.rb +41 -0
 - data/lib/prefab/internal_logger.rb +16 -0
 - data/lib/prefab/local_config_parser.rb +151 -0
 - data/lib/prefab/log_path_aggregator.rb +69 -0
 - data/lib/prefab/logger_client.rb +264 -0
 - data/lib/prefab/murmer3.rb +50 -0
 - data/lib/prefab/options.rb +208 -0
 - data/lib/prefab/periodic_sync.rb +69 -0
 - data/lib/prefab/prefab.rb +56 -0
 - data/lib/prefab/rate_limit_cache.rb +41 -0
 - data/lib/prefab/resolved_config_presenter.rb +86 -0
 - data/lib/prefab/time_helpers.rb +7 -0
 - data/lib/prefab/weighted_value_resolver.rb +42 -0
 - data/lib/prefab/yaml_config_parser.rb +34 -0
 - data/lib/prefab-cloud-ruby.rb +57 -0
 - data/lib/prefab_pb.rb +93 -0
 - data/prefab-cloud-ruby.gemspec +155 -0
 - data/test/.prefab.default.config.yaml +2 -0
 - data/test/.prefab.unit_tests.config.yaml +28 -0
 - data/test/integration_test.rb +150 -0
 - data/test/integration_test_helpers.rb +151 -0
 - data/test/support/common_helpers.rb +180 -0
 - data/test/support/mock_base_client.rb +42 -0
 - data/test/support/mock_config_client.rb +19 -0
 - data/test/support/mock_config_loader.rb +1 -0
 - data/test/test_client.rb +444 -0
 - data/test/test_config_client.rb +109 -0
 - data/test/test_config_loader.rb +117 -0
 - data/test/test_config_resolver.rb +430 -0
 - data/test/test_config_value_unwrapper.rb +224 -0
 - data/test/test_config_value_wrapper.rb +42 -0
 - data/test/test_context.rb +203 -0
 - data/test/test_context_shape.rb +50 -0
 - data/test/test_context_shape_aggregator.rb +147 -0
 - data/test/test_criteria_evaluator.rb +726 -0
 - data/test/test_encryption.rb +16 -0
 - data/test/test_evaluation_summary_aggregator.rb +162 -0
 - data/test/test_example_contexts_aggregator.rb +238 -0
 - data/test/test_exponential_backoff.rb +18 -0
 - data/test/test_feature_flag_client.rb +48 -0
 - data/test/test_helper.rb +17 -0
 - data/test/test_integration.rb +58 -0
 - data/test/test_local_config_parser.rb +147 -0
 - data/test/test_log_path_aggregator.rb +62 -0
 - data/test/test_logger.rb +621 -0
 - data/test/test_logger_initialization.rb +12 -0
 - data/test/test_options.rb +75 -0
 - data/test/test_prefab.rb +12 -0
 - data/test/test_rate_limit_cache.rb +44 -0
 - data/test/test_weighted_value_resolver.rb +71 -0
 - metadata +337 -0
 
| 
         @@ -0,0 +1,150 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class IntegrationTest
         
     | 
| 
      
 4 
     | 
    
         
            +
              attr_reader :func, :input, :expected, :data, :expected_data, :aggregator, :endpoint, :test_client
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              def initialize(test_data)
         
     | 
| 
      
 7 
     | 
    
         
            +
                @client_overrides = parse_client_overrides(test_data['client_overrides'])
         
     | 
| 
      
 8 
     | 
    
         
            +
                @func = parse_function(test_data['function'])
         
     | 
| 
      
 9 
     | 
    
         
            +
                @input = parse_input(test_data['input'])
         
     | 
| 
      
 10 
     | 
    
         
            +
                @expected = parse_expected(test_data['expected'])
         
     | 
| 
      
 11 
     | 
    
         
            +
                @data = test_data['data']
         
     | 
| 
      
 12 
     | 
    
         
            +
                @expected_data = test_data['expected_data'] || []
         
     | 
| 
      
 13 
     | 
    
         
            +
                @aggregator = test_data['aggregator']
         
     | 
| 
      
 14 
     | 
    
         
            +
                @endpoint = test_data['endpoint']
         
     | 
| 
      
 15 
     | 
    
         
            +
                @test_client = capture_telemetry(base_client)
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              def test_type
         
     | 
| 
      
 19 
     | 
    
         
            +
                if @data
         
     | 
| 
      
 20 
     | 
    
         
            +
                  :telemetry
         
     | 
| 
      
 21 
     | 
    
         
            +
                elsif @input[0] && @input[0].start_with?('log-level.')
         
     | 
| 
      
 22 
     | 
    
         
            +
                  :log_level
         
     | 
| 
      
 23 
     | 
    
         
            +
                elsif @expected[:status] == 'raise'
         
     | 
| 
      
 24 
     | 
    
         
            +
                  :raise
         
     | 
| 
      
 25 
     | 
    
         
            +
                elsif @expected[:value].nil?
         
     | 
| 
      
 26 
     | 
    
         
            +
                  :nil
         
     | 
| 
      
 27 
     | 
    
         
            +
                else
         
     | 
| 
      
 28 
     | 
    
         
            +
                  :simple_equality
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              def last_data_sent
         
     | 
| 
      
 33 
     | 
    
         
            +
                test_client.last_data_sent
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              def last_post_result
         
     | 
| 
      
 37 
     | 
    
         
            +
                test_client.last_post_result
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              def last_post_endpoint
         
     | 
| 
      
 41 
     | 
    
         
            +
                test_client.last_post_endpoint
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              private
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
              def parse_client_overrides(overrides)
         
     | 
| 
      
 47 
     | 
    
         
            +
                Hash[
         
     | 
| 
      
 48 
     | 
    
         
            +
                  (overrides || {}).map do |(k, v)|
         
     | 
| 
      
 49 
     | 
    
         
            +
                    [k.to_sym, v]
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                ]
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
              def parse_function(function)
         
     | 
| 
      
 55 
     | 
    
         
            +
                case function
         
     | 
| 
      
 56 
     | 
    
         
            +
                when 'get_or_raise' then :get
         
     | 
| 
      
 57 
     | 
    
         
            +
                when 'enabled' then :enabled?
         
     | 
| 
      
 58 
     | 
    
         
            +
                else :"#{function}"
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              def parse_input(input)
         
     | 
| 
      
 63 
     | 
    
         
            +
                return nil if input.nil?
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                if input['key']
         
     | 
| 
      
 66 
     | 
    
         
            +
                  parse_config_input(input)
         
     | 
| 
      
 67 
     | 
    
         
            +
                elsif input['flag']
         
     | 
| 
      
 68 
     | 
    
         
            +
                  parse_ff_input(input)
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
              end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
              def parse_config_input(input)
         
     | 
| 
      
 73 
     | 
    
         
            +
                if !input['default'].nil?
         
     | 
| 
      
 74 
     | 
    
         
            +
                  [input['key'], input['default']]
         
     | 
| 
      
 75 
     | 
    
         
            +
                else
         
     | 
| 
      
 76 
     | 
    
         
            +
                  [input['key']]
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
              def parse_ff_input(input)
         
     | 
| 
      
 81 
     | 
    
         
            +
                [input['flag'], input['default'], input['context']]
         
     | 
| 
      
 82 
     | 
    
         
            +
              end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
              def parse_expected(expected)
         
     | 
| 
      
 85 
     | 
    
         
            +
                return {} if expected.nil?
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                {
         
     | 
| 
      
 88 
     | 
    
         
            +
                  status: expected['status'],
         
     | 
| 
      
 89 
     | 
    
         
            +
                  error: parse_error_type(expected['error']),
         
     | 
| 
      
 90 
     | 
    
         
            +
                  message: expected['message'],
         
     | 
| 
      
 91 
     | 
    
         
            +
                  value: expected['value']
         
     | 
| 
      
 92 
     | 
    
         
            +
                }
         
     | 
| 
      
 93 
     | 
    
         
            +
              end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
              def parse_error_type(error_type)
         
     | 
| 
      
 96 
     | 
    
         
            +
                case error_type
         
     | 
| 
      
 97 
     | 
    
         
            +
                when 'missing_default' then Prefab::Errors::MissingDefaultError
         
     | 
| 
      
 98 
     | 
    
         
            +
                when 'initialization_timeout' then Prefab::Errors::InitializationTimeoutError
         
     | 
| 
      
 99 
     | 
    
         
            +
                when 'unable_to_decrypt' then OpenSSL::Cipher::CipherError
         
     | 
| 
      
 100 
     | 
    
         
            +
                when 'missing_env_var' then Prefab::Errors::MissingEnvVarError
         
     | 
| 
      
 101 
     | 
    
         
            +
                when 'unable_to_coerce_env_var' then Prefab::Errors::EnvVarParseError
         
     | 
| 
      
 102 
     | 
    
         
            +
                else
         
     | 
| 
      
 103 
     | 
    
         
            +
                  unless error_type.nil?
         
     | 
| 
      
 104 
     | 
    
         
            +
                    throw "Unknown error type: #{error_type}"
         
     | 
| 
      
 105 
     | 
    
         
            +
                  end
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
              end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
              def base_client
         
     | 
| 
      
 110 
     | 
    
         
            +
                @_base_client ||= Prefab::Client.new(base_client_options)
         
     | 
| 
      
 111 
     | 
    
         
            +
              end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
              def base_client_options
         
     | 
| 
      
 114 
     | 
    
         
            +
                @_options ||= Prefab::Options.new(**{
         
     | 
| 
      
 115 
     | 
    
         
            +
                  prefab_config_override_dir: 'none',
         
     | 
| 
      
 116 
     | 
    
         
            +
                  prefab_config_classpath_dir: 'test',
         
     | 
| 
      
 117 
     | 
    
         
            +
                  prefab_envs: ['unit_tests'],
         
     | 
| 
      
 118 
     | 
    
         
            +
                  prefab_datasources: Prefab::Options::DATASOURCES::ALL,
         
     | 
| 
      
 119 
     | 
    
         
            +
                  api_key: ENV['PREFAB_INTEGRATION_TEST_API_KEY'],
         
     | 
| 
      
 120 
     | 
    
         
            +
                  prefab_api_url: 'https://api.staging-prefab.cloud',
         
     | 
| 
      
 121 
     | 
    
         
            +
                }.merge(@client_overrides))
         
     | 
| 
      
 122 
     | 
    
         
            +
              end
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
              def capture_telemetry(client)
         
     | 
| 
      
 125 
     | 
    
         
            +
                client.define_singleton_method(:post) do |url, data|
         
     | 
| 
      
 126 
     | 
    
         
            +
                  client.instance_variable_set(:@last_data_sent, data)
         
     | 
| 
      
 127 
     | 
    
         
            +
                  client.instance_variable_set(:@last_post_endpoint, url)
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                  result = super(url, data)
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                  client.instance_variable_set(:@last_post_result, result)
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                  result
         
     | 
| 
      
 134 
     | 
    
         
            +
                end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                client.define_singleton_method(:last_data_sent) do
         
     | 
| 
      
 137 
     | 
    
         
            +
                  client.instance_variable_get(:@last_data_sent)
         
     | 
| 
      
 138 
     | 
    
         
            +
                end
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                client.define_singleton_method(:last_post_endpoint) do
         
     | 
| 
      
 141 
     | 
    
         
            +
                  client.instance_variable_get(:@last_post_endpoint)
         
     | 
| 
      
 142 
     | 
    
         
            +
                end
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                client.define_singleton_method(:last_post_result) do
         
     | 
| 
      
 145 
     | 
    
         
            +
                  client.instance_variable_get(:@last_post_result)
         
     | 
| 
      
 146 
     | 
    
         
            +
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                client
         
     | 
| 
      
 149 
     | 
    
         
            +
              end
         
     | 
| 
      
 150 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,151 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module IntegrationTestHelpers
         
     | 
| 
      
 4 
     | 
    
         
            +
              SUBMODULE_PATH = 'test/prefab-cloud-integration-test-data'
         
     | 
| 
      
 5 
     | 
    
         
            +
              RAISE_IF_NO_TESTS_FOUND = ENV['PREFAB_INTEGRATION_TEST_RAISE'] == 'true'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              def self.find_integration_tests
         
     | 
| 
      
 8 
     | 
    
         
            +
                version = find_integration_test_version
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                files = find_versioned_test_files(version)
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                if files.none?
         
     | 
| 
      
 13 
     | 
    
         
            +
                  message = "No integration tests found for version: #{version}"
         
     | 
| 
      
 14 
     | 
    
         
            +
                  raise message if RAISE_IF_NO_TESTS_FOUND
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  puts message
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                files
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              def self.find_integration_test_version
         
     | 
| 
      
 23 
     | 
    
         
            +
                File.read(File.join(SUBMODULE_PATH, 'version')).strip
         
     | 
| 
      
 24 
     | 
    
         
            +
              rescue StandardError => e
         
     | 
| 
      
 25 
     | 
    
         
            +
                puts "No version found for integration tests: #{e.message}"
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              def self.find_versioned_test_files(version)
         
     | 
| 
      
 29 
     | 
    
         
            +
                if version.nil?
         
     | 
| 
      
 30 
     | 
    
         
            +
                  []
         
     | 
| 
      
 31 
     | 
    
         
            +
                else
         
     | 
| 
      
 32 
     | 
    
         
            +
                  Dir[File.join(SUBMODULE_PATH, "tests/#{version}/**/*")]
         
     | 
| 
      
 33 
     | 
    
         
            +
                    .select { |file| file =~ /\.ya?ml$/ }
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
              SEVERITY_LOOKUP = Prefab::LogPathAggregator::SEVERITY_KEY.invert
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              def self.prepare_post_data(it)
         
     | 
| 
      
 40 
     | 
    
         
            +
                case it.aggregator
         
     | 
| 
      
 41 
     | 
    
         
            +
                when "log_path"
         
     | 
| 
      
 42 
     | 
    
         
            +
                  aggregator = it.test_client.log_path_aggregator
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  it.data.each do |data|
         
     | 
| 
      
 45 
     | 
    
         
            +
                    data['counts'].each_pair do |severity, count|
         
     | 
| 
      
 46 
     | 
    
         
            +
                      count.times { aggregator.push(data['logger_name'], SEVERITY_LOOKUP[severity]) }
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  expected_loggers = Hash.new { |h, k| h[k] = PrefabProto::Logger.new }
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  it.expected_data.each do |data|
         
     | 
| 
      
 53 
     | 
    
         
            +
                    data["counts"].each do |(severity, count)|
         
     | 
| 
      
 54 
     | 
    
         
            +
                      expected_loggers[data["logger_name"]][severity] = count
         
     | 
| 
      
 55 
     | 
    
         
            +
                      expected_loggers[data["logger_name"]]["logger_name"] = data["logger_name"]
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  [aggregator, ->(data) { data.loggers }, expected_loggers.values]
         
     | 
| 
      
 60 
     | 
    
         
            +
                when "context_shape"
         
     | 
| 
      
 61 
     | 
    
         
            +
                  aggregator = it.test_client.context_shape_aggregator
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  context = Prefab::Context.new(it.data)
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                  aggregator.push(context)
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  expected = it.expected_data.map do |data|
         
     | 
| 
      
 68 
     | 
    
         
            +
                    PrefabProto::ContextShape.new(
         
     | 
| 
      
 69 
     | 
    
         
            +
                      name: data["name"],
         
     | 
| 
      
 70 
     | 
    
         
            +
                      field_types: data["field_types"]
         
     | 
| 
      
 71 
     | 
    
         
            +
                    )
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                  [aggregator, ->(data) { data.shapes }, expected]
         
     | 
| 
      
 75 
     | 
    
         
            +
                when "evaluation_summary"
         
     | 
| 
      
 76 
     | 
    
         
            +
                  aggregator = it.test_client.evaluation_summary_aggregator
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                  aggregator.instance_variable_set("@data", Concurrent::Hash.new)
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  it.data.each do |key|
         
     | 
| 
      
 81 
     | 
    
         
            +
                    it.test_client.get(key)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  expected_data = []
         
     | 
| 
      
 85 
     | 
    
         
            +
                  it.expected_data.each do |data|
         
     | 
| 
      
 86 
     | 
    
         
            +
                    value = if data["value_type"] == "string_list"
         
     | 
| 
      
 87 
     | 
    
         
            +
                              PrefabProto::StringList.new(values: data["value"])
         
     | 
| 
      
 88 
     | 
    
         
            +
                            else
         
     | 
| 
      
 89 
     | 
    
         
            +
                              data["value"]
         
     | 
| 
      
 90 
     | 
    
         
            +
                            end
         
     | 
| 
      
 91 
     | 
    
         
            +
                    expected_data << PrefabProto::ConfigEvaluationSummary.new(
         
     | 
| 
      
 92 
     | 
    
         
            +
                      key: data["key"],
         
     | 
| 
      
 93 
     | 
    
         
            +
                      type: data["type"].to_sym,
         
     | 
| 
      
 94 
     | 
    
         
            +
                      counters: [
         
     | 
| 
      
 95 
     | 
    
         
            +
                        PrefabProto::ConfigEvaluationCounter.new(
         
     | 
| 
      
 96 
     | 
    
         
            +
                          count: data["count"],
         
     | 
| 
      
 97 
     | 
    
         
            +
                          config_id: 0,
         
     | 
| 
      
 98 
     | 
    
         
            +
                          selected_value: PrefabProto::ConfigValue.new(data["value_type"] => value),
         
     | 
| 
      
 99 
     | 
    
         
            +
                          config_row_index: data["summary"]["config_row_index"],
         
     | 
| 
      
 100 
     | 
    
         
            +
                          conditional_value_index: data["summary"]["conditional_value_index"] || 0,
         
     | 
| 
      
 101 
     | 
    
         
            +
                          weighted_value_index: data["summary"]["weighted_value_index"],
         
     | 
| 
      
 102 
     | 
    
         
            +
                          reason: :UNKNOWN
         
     | 
| 
      
 103 
     | 
    
         
            +
                        )
         
     | 
| 
      
 104 
     | 
    
         
            +
                      ]
         
     | 
| 
      
 105 
     | 
    
         
            +
                    )
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                  [aggregator, ->(data) {
         
     | 
| 
      
 109 
     | 
    
         
            +
                                 data.events[0].summaries.summaries.each { |e|
         
     | 
| 
      
 110 
     | 
    
         
            +
                                   e.counters.each { |c|
         
     | 
| 
      
 111 
     | 
    
         
            +
                                     c.config_id = 0
         
     | 
| 
      
 112 
     | 
    
         
            +
                                   }
         
     | 
| 
      
 113 
     | 
    
         
            +
                                 }
         
     | 
| 
      
 114 
     | 
    
         
            +
                               }, expected_data]
         
     | 
| 
      
 115 
     | 
    
         
            +
                when "example_contexts"
         
     | 
| 
      
 116 
     | 
    
         
            +
                  aggregator = it.test_client.example_contexts_aggregator
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                  it.data.each do |key, values|
         
     | 
| 
      
 119 
     | 
    
         
            +
                    aggregator.record(Prefab::Context.new({ key => values }))
         
     | 
| 
      
 120 
     | 
    
         
            +
                  end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                  expected_data = []
         
     | 
| 
      
 123 
     | 
    
         
            +
                  it.expected_data.each do |k, vs|
         
     | 
| 
      
 124 
     | 
    
         
            +
                    expected_data << PrefabProto::ExampleContext.new(
         
     | 
| 
      
 125 
     | 
    
         
            +
                      timestamp: 0,
         
     | 
| 
      
 126 
     | 
    
         
            +
                      contextSet: PrefabProto::ContextSet.new(
         
     | 
| 
      
 127 
     | 
    
         
            +
                        contexts: [
         
     | 
| 
      
 128 
     | 
    
         
            +
                          PrefabProto::Context.new(
         
     | 
| 
      
 129 
     | 
    
         
            +
                            type: k,
         
     | 
| 
      
 130 
     | 
    
         
            +
                            values: vs.each_pair.map do |key, value|
         
     | 
| 
      
 131 
     | 
    
         
            +
                              [key, Prefab::ConfigValueWrapper.wrap(value)]
         
     | 
| 
      
 132 
     | 
    
         
            +
                            end.to_h
         
     | 
| 
      
 133 
     | 
    
         
            +
                          )
         
     | 
| 
      
 134 
     | 
    
         
            +
                        ]
         
     | 
| 
      
 135 
     | 
    
         
            +
                      )
         
     | 
| 
      
 136 
     | 
    
         
            +
                    )
         
     | 
| 
      
 137 
     | 
    
         
            +
                  end
         
     | 
| 
      
 138 
     | 
    
         
            +
                  [aggregator, ->(data) { data.events[0].example_contexts.examples.each { |e| e.timestamp = 0 } }, expected_data]
         
     | 
| 
      
 139 
     | 
    
         
            +
                else
         
     | 
| 
      
 140 
     | 
    
         
            +
                  puts "unknown aggregator #{it.aggregator}"
         
     | 
| 
      
 141 
     | 
    
         
            +
                end
         
     | 
| 
      
 142 
     | 
    
         
            +
              end
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
              def self.with_parent_context_maybe(context, &block)
         
     | 
| 
      
 145 
     | 
    
         
            +
                if context
         
     | 
| 
      
 146 
     | 
    
         
            +
                  Prefab::Context.with_context(context, &block)
         
     | 
| 
      
 147 
     | 
    
         
            +
                else
         
     | 
| 
      
 148 
     | 
    
         
            +
                  yield
         
     | 
| 
      
 149 
     | 
    
         
            +
                end
         
     | 
| 
      
 150 
     | 
    
         
            +
              end
         
     | 
| 
      
 151 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,180 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module CommonHelpers
         
     | 
| 
      
 4 
     | 
    
         
            +
              require 'timecop'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              def setup
         
     | 
| 
      
 7 
     | 
    
         
            +
                $oldstderr, $stderr = $stderr, StringIO.new
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                $logs = nil
         
     | 
| 
      
 10 
     | 
    
         
            +
                Timecop.freeze('2023-08-09 15:18:12 -0400')
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              def teardown
         
     | 
| 
      
 14 
     | 
    
         
            +
                if $logs && !$logs.string.empty?
         
     | 
| 
      
 15 
     | 
    
         
            +
                  raise "Unexpected logs. Handle logs with assert_only_expected_logs or assert_logged\n\n#{$logs.string}"
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                if $stderr != $oldstderr && !$stderr.string.empty?
         
     | 
| 
      
 19 
     | 
    
         
            +
                  # we ignore 2.X because of the number of `instance variable @xyz not initialized` warnings
         
     | 
| 
      
 20 
     | 
    
         
            +
                  if !RUBY_VERSION.start_with?('2.')
         
     | 
| 
      
 21 
     | 
    
         
            +
                    raise "Unexpected stderr. Handle stderr with assert_stderr\n\n#{$stderr.string}"
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                $stderr = $oldstderr
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                Timecop.return
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              def with_env(key, value, &block)
         
     | 
| 
      
 31 
     | 
    
         
            +
                old_value = ENV.fetch(key, nil)
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                ENV[key] = value
         
     | 
| 
      
 34 
     | 
    
         
            +
                block.call
         
     | 
| 
      
 35 
     | 
    
         
            +
              ensure
         
     | 
| 
      
 36 
     | 
    
         
            +
                ENV[key] = old_value
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              DEFAULT_NEW_CLIENT_OPTIONS = {
         
     | 
| 
      
 40 
     | 
    
         
            +
                prefab_config_override_dir: 'none',
         
     | 
| 
      
 41 
     | 
    
         
            +
                prefab_config_classpath_dir: 'test',
         
     | 
| 
      
 42 
     | 
    
         
            +
                prefab_envs: ['unit_tests'],
         
     | 
| 
      
 43 
     | 
    
         
            +
                prefab_datasources: Prefab::Options::DATASOURCES::LOCAL_ONLY
         
     | 
| 
      
 44 
     | 
    
         
            +
              }.freeze
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
              def new_client(overrides = {})
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                config = overrides.delete(:config)
         
     | 
| 
      
 49 
     | 
    
         
            +
                project_env_id = overrides.delete(:project_env_id)
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                Prefab::Client.new(prefab_options(overrides)).tap do |client|
         
     | 
| 
      
 52 
     | 
    
         
            +
                  inject_config(client, config) if config
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  client.resolver.project_env_id = project_env_id if project_env_id
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
              end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
              def prefab_options(overrides = {})
         
     | 
| 
      
 59 
     | 
    
         
            +
                $logs ||= StringIO.new
         
     | 
| 
      
 60 
     | 
    
         
            +
                Prefab::Options.new(
         
     | 
| 
      
 61 
     | 
    
         
            +
                  **DEFAULT_NEW_CLIENT_OPTIONS.merge(
         
     | 
| 
      
 62 
     | 
    
         
            +
                    overrides.merge(logdev: $logs)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  )
         
     | 
| 
      
 64 
     | 
    
         
            +
                )
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
              def string_list(values)
         
     | 
| 
      
 68 
     | 
    
         
            +
                PrefabProto::ConfigValue.new(string_list: PrefabProto::StringList.new(values: values))
         
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
              def inject_config(client, config)
         
     | 
| 
      
 72 
     | 
    
         
            +
                resolver = client.config_client.instance_variable_get('@config_resolver')
         
     | 
| 
      
 73 
     | 
    
         
            +
                store = resolver.instance_variable_get('@local_store')
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                Array(config).each do |c|
         
     | 
| 
      
 76 
     | 
    
         
            +
                  store[c.key] = { config: c }
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
              def inject_project_env_id(client, project_env_id)
         
     | 
| 
      
 81 
     | 
    
         
            +
                resolver = client.config_client.instance_variable_get('@config_resolver')
         
     | 
| 
      
 82 
     | 
    
         
            +
                resolver.project_env_id = project_env_id
         
     | 
| 
      
 83 
     | 
    
         
            +
              end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
              FakeResponse = Struct.new(:status, :body)
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
              def wait_for(condition, max_wait: 2, sleep_time: 0.01)
         
     | 
| 
      
 88 
     | 
    
         
            +
                wait_time = 0
         
     | 
| 
      
 89 
     | 
    
         
            +
                while !condition.call
         
     | 
| 
      
 90 
     | 
    
         
            +
                  wait_time += sleep_time
         
     | 
| 
      
 91 
     | 
    
         
            +
                  sleep sleep_time
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                  raise "Waited #{max_wait} seconds for the condition to be true, but it never was" if wait_time > max_wait
         
     | 
| 
      
 94 
     | 
    
         
            +
                end
         
     | 
| 
      
 95 
     | 
    
         
            +
              end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
              def wait_for_post_requests(client, max_wait: 2, sleep_time: 0.01)
         
     | 
| 
      
 98 
     | 
    
         
            +
                # we use ivars to avoid re-mocking the post method on subsequent calls
         
     | 
| 
      
 99 
     | 
    
         
            +
                client.instance_variable_set("@_requests", [])
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                if !client.instance_variable_get("@_already_faked_post")
         
     | 
| 
      
 102 
     | 
    
         
            +
                  client.define_singleton_method(:post) do |*params|
         
     | 
| 
      
 103 
     | 
    
         
            +
                    @_requests.push(params)
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                    FakeResponse.new(200, '')
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                client.instance_variable_set("@_already_faked_post", true)
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                yield
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                # let the flush thread run
         
     | 
| 
      
 114 
     | 
    
         
            +
                wait_for -> { client.instance_variable_get("@_requests").size > 0 }, max_wait: max_wait, sleep_time: sleep_time
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                client.instance_variable_get("@_requests")
         
     | 
| 
      
 117 
     | 
    
         
            +
              end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
              def assert_summary(client, data)
         
     | 
| 
      
 120 
     | 
    
         
            +
                raise 'Evaluation summary aggregator not enabled' unless client.evaluation_summary_aggregator
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                assert_equal data, client.evaluation_summary_aggregator.data
         
     | 
| 
      
 123 
     | 
    
         
            +
              end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
              def assert_example_contexts(client, data)
         
     | 
| 
      
 126 
     | 
    
         
            +
                raise 'Example contexts aggregator not enabled' unless client.example_contexts_aggregator
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                assert_equal data, client.example_contexts_aggregator.data
         
     | 
| 
      
 129 
     | 
    
         
            +
              end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
              def weighted_values(values_and_weights, hash_by_property_name: 'user.key')
         
     | 
| 
      
 132 
     | 
    
         
            +
                values = values_and_weights.map do |value, weight|
         
     | 
| 
      
 133 
     | 
    
         
            +
                  weighted_value(value, weight)
         
     | 
| 
      
 134 
     | 
    
         
            +
                end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                PrefabProto::WeightedValues.new(weighted_values: values, hash_by_property_name: hash_by_property_name)
         
     | 
| 
      
 137 
     | 
    
         
            +
              end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
              def weighted_value(string, weight)
         
     | 
| 
      
 140 
     | 
    
         
            +
                PrefabProto::WeightedValue.new(
         
     | 
| 
      
 141 
     | 
    
         
            +
                  value: PrefabProto::ConfigValue.new(string: string), weight: weight
         
     | 
| 
      
 142 
     | 
    
         
            +
                )
         
     | 
| 
      
 143 
     | 
    
         
            +
              end
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
              def context(properties)
         
     | 
| 
      
 146 
     | 
    
         
            +
                Prefab::Context.new(properties)
         
     | 
| 
      
 147 
     | 
    
         
            +
              end
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
              def assert_only_expected_logs
         
     | 
| 
      
 150 
     | 
    
         
            +
                assert_equal "WARN  2023-08-09 15:18:12 -0400: cloud.prefab.client.configclient No success loading checkpoints\n", $logs.string
         
     | 
| 
      
 151 
     | 
    
         
            +
                # mark nil to indicate we handled it
         
     | 
| 
      
 152 
     | 
    
         
            +
                $logs = nil
         
     | 
| 
      
 153 
     | 
    
         
            +
              end
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
              def assert_logged(expected)
         
     | 
| 
      
 156 
     | 
    
         
            +
                # we do a uniq here because logging can happen in a separate thread so the
         
     | 
| 
      
 157 
     | 
    
         
            +
                # number of times a log might happen could be slightly variable.
         
     | 
| 
      
 158 
     | 
    
         
            +
                assert_equal expected, $logs.string.split("\n").uniq
         
     | 
| 
      
 159 
     | 
    
         
            +
                # mark nil to indicate we handled it
         
     | 
| 
      
 160 
     | 
    
         
            +
                $logs = nil
         
     | 
| 
      
 161 
     | 
    
         
            +
              end
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
              def assert_stderr(expected)
         
     | 
| 
      
 164 
     | 
    
         
            +
                assert ($stderr.string.split("\n").uniq & expected).size > 0
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                # Ruby 2.X has a lot of warnings about instance variables not being
         
     | 
| 
      
 167 
     | 
    
         
            +
                # initialized so we don't try to assert on stderr for those versions.
         
     | 
| 
      
 168 
     | 
    
         
            +
                # Instead we just stop after asserting that our expected errors are
         
     | 
| 
      
 169 
     | 
    
         
            +
                # included in the output.
         
     | 
| 
      
 170 
     | 
    
         
            +
                if RUBY_VERSION.start_with?('2.')
         
     | 
| 
      
 171 
     | 
    
         
            +
                  puts $stderr.string
         
     | 
| 
      
 172 
     | 
    
         
            +
                  return
         
     | 
| 
      
 173 
     | 
    
         
            +
                end
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                assert_equal expected, $stderr.string.split("\n")
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                # restore since we've handled it
         
     | 
| 
      
 178 
     | 
    
         
            +
                $stderr = $oldstderr
         
     | 
| 
      
 179 
     | 
    
         
            +
              end
         
     | 
| 
      
 180 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class MockBaseClient
         
     | 
| 
      
 4 
     | 
    
         
            +
              STAGING_ENV_ID = 1
         
     | 
| 
      
 5 
     | 
    
         
            +
              PRODUCTION_ENV_ID = 2
         
     | 
| 
      
 6 
     | 
    
         
            +
              TEST_ENV_ID = 3
         
     | 
| 
      
 7 
     | 
    
         
            +
              attr_reader :namespace, :logger, :config_client, :options, :posts
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              def initialize(options = Prefab::Options.new)
         
     | 
| 
      
 10 
     | 
    
         
            +
                @options = options
         
     | 
| 
      
 11 
     | 
    
         
            +
                @namespace = namespace
         
     | 
| 
      
 12 
     | 
    
         
            +
                @config_client = MockConfigClient.new
         
     | 
| 
      
 13 
     | 
    
         
            +
                Prefab::LoggerClient.new(options.logdev)
         
     | 
| 
      
 14 
     | 
    
         
            +
                @posts = []
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              def instance_hash
         
     | 
| 
      
 18 
     | 
    
         
            +
                'mock-base-client-instance-hash'
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              def project_id
         
     | 
| 
      
 22 
     | 
    
         
            +
                1
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              def post(_, _)
         
     | 
| 
      
 26 
     | 
    
         
            +
                raise 'Use wait_for_post_requests'
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              def log
         
     | 
| 
      
 30 
     | 
    
         
            +
                @logger
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              def context_shape_aggregator; end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              def evaluation_summary_aggregator; end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
              def example_contexts_aggregator; end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              def config_value(key)
         
     | 
| 
      
 40 
     | 
    
         
            +
                @config_values[key]
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class MockConfigClient
         
     | 
| 
      
 4 
     | 
    
         
            +
              def initialize(config_values = {})
         
     | 
| 
      
 5 
     | 
    
         
            +
                @config_values = config_values
         
     | 
| 
      
 6 
     | 
    
         
            +
              end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              def get(key, default = nil)
         
     | 
| 
      
 9 
     | 
    
         
            +
                @config_values.fetch(key, default)
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              def get_config(key)
         
     | 
| 
      
 13 
     | 
    
         
            +
                PrefabProto::Config.new(value: @config_values[key], key: key)
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              def mock_this_config(key, config_value)
         
     | 
| 
      
 17 
     | 
    
         
            +
                @config_values[key] = config_value
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     |