prefab-cloud-ruby 0.24.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/VERSION +1 -1
  4. data/compile_protos.sh +7 -0
  5. data/lib/prefab/client.rb +20 -46
  6. data/lib/prefab/config_client.rb +9 -12
  7. data/lib/prefab/config_resolver.rb +2 -1
  8. data/lib/prefab/config_value_unwrapper.rb +20 -9
  9. data/lib/prefab/context.rb +43 -7
  10. data/lib/prefab/context_shape_aggregator.rb +1 -1
  11. data/lib/prefab/criteria_evaluator.rb +24 -16
  12. data/lib/prefab/evaluation.rb +48 -0
  13. data/lib/prefab/evaluation_summary_aggregator.rb +85 -0
  14. data/lib/prefab/example_contexts_aggregator.rb +76 -0
  15. data/lib/prefab/exponential_backoff.rb +5 -0
  16. data/lib/prefab/feature_flag_client.rb +0 -2
  17. data/lib/prefab/log_path_aggregator.rb +1 -1
  18. data/lib/prefab/logger_client.rb +12 -13
  19. data/lib/prefab/options.rb +52 -43
  20. data/lib/prefab/periodic_sync.rb +30 -13
  21. data/lib/prefab/rate_limit_cache.rb +41 -0
  22. data/lib/prefab/resolved_config_presenter.rb +2 -4
  23. data/lib/prefab/weighted_value_resolver.rb +1 -1
  24. data/lib/prefab-cloud-ruby.rb +5 -5
  25. data/lib/prefab_pb.rb +11 -1
  26. data/prefab-cloud-ruby.gemspec +14 -9
  27. data/test/integration_test.rb +1 -3
  28. data/test/integration_test_helpers.rb +0 -1
  29. data/test/support/common_helpers.rb +174 -0
  30. data/test/support/mock_base_client.rb +44 -0
  31. data/test/support/mock_config_client.rb +19 -0
  32. data/test/support/mock_config_loader.rb +1 -0
  33. data/test/test_client.rb +354 -40
  34. data/test/test_config_client.rb +1 -0
  35. data/test/test_config_loader.rb +1 -0
  36. data/test/test_config_resolver.rb +25 -24
  37. data/test/test_config_value_unwrapper.rb +22 -32
  38. data/test/test_context.rb +1 -0
  39. data/test/test_context_shape_aggregator.rb +11 -1
  40. data/test/test_criteria_evaluator.rb +180 -133
  41. data/test/test_evaluation_summary_aggregator.rb +162 -0
  42. data/test/test_example_contexts_aggregator.rb +238 -0
  43. data/test/test_helper.rb +5 -131
  44. data/test/test_integration.rb +6 -4
  45. data/test/test_local_config_parser.rb +2 -2
  46. data/test/test_log_path_aggregator.rb +9 -1
  47. data/test/test_logger.rb +6 -5
  48. data/test/test_options.rb +33 -2
  49. data/test/test_rate_limit_cache.rb +44 -0
  50. data/test/test_weighted_value_resolver.rb +13 -7
  51. metadata +13 -8
  52. data/lib/prefab/evaluated_configs_aggregator.rb +0 -60
  53. data/lib/prefab/evaluated_keys_aggregator.rb +0 -41
  54. data/lib/prefab/noop_cache.rb +0 -15
  55. data/lib/prefab/noop_stats.rb +0 -8
  56. data/test/test_evaluated_configs_aggregator.rb +0 -254
  57. data/test/test_evaluated_keys_aggregator.rb +0 -54
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+ require 'timecop'
5
+
6
+ class TestEvaluationSummaryAggregator < Minitest::Test
7
+ EFFECTIVELY_NEVER = 99_999 # we sync manually
8
+
9
+ EXAMPLE_VALUE_1 = PrefabProto::ConfigValue.new(bool: true)
10
+ EXAMPLE_VALUE_2 = PrefabProto::ConfigValue.new(bool: false)
11
+
12
+ EXAMPLE_COUNTER = {
13
+ config_id: 1,
14
+ selected_index: 2,
15
+ config_row_index: 3,
16
+ conditional_value_index: 4,
17
+ weighted_value_index: 5,
18
+ seleced_value: EXAMPLE_VALUE_1
19
+ }.freeze
20
+
21
+ def test_increments_counts
22
+ aggregator = Prefab::EvaluationSummaryAggregator.new(client: MockBaseClient.new, max_keys: 10,
23
+ sync_interval: EFFECTIVELY_NEVER)
24
+
25
+ aggregator.record(config_key: 'foo', config_type: 'bar', counter: EXAMPLE_COUNTER)
26
+
27
+ assert_equal 1, aggregator.data[%w[foo bar]][EXAMPLE_COUNTER]
28
+
29
+ 2.times { aggregator.record(config_key: 'foo', config_type: 'bar', counter: EXAMPLE_COUNTER) }
30
+ assert_equal 3, aggregator.data[%w[foo bar]][EXAMPLE_COUNTER]
31
+
32
+ another_counter = EXAMPLE_COUNTER.merge(selected_index: EXAMPLE_COUNTER[:selected_index] + 1)
33
+
34
+ aggregator.record(config_key: 'foo', config_type: 'bar', counter: another_counter)
35
+ assert_equal 3, aggregator.data[%w[foo bar]][EXAMPLE_COUNTER]
36
+ assert_equal 1, aggregator.data[%w[foo bar]][another_counter]
37
+ end
38
+
39
+ def test_prepare_data
40
+ aggregator = Prefab::EvaluationSummaryAggregator.new(client: MockBaseClient.new, max_keys: 10,
41
+ sync_interval: EFFECTIVELY_NEVER)
42
+
43
+ expected = {
44
+ ['config-1', :CONFIG] => {
45
+ { config_id: 1, selected_index: 2, config_row_index: 3, conditional_value_index: 4,
46
+ weighted_value_index: 5, selected_value: EXAMPLE_VALUE_1 } => 3,
47
+ { config_id: 1, selected_index: 3, config_row_index: 7, conditional_value_index: 8,
48
+ weighted_value_index: 10, selected_value: EXAMPLE_VALUE_2 } => 1
49
+ },
50
+ ['config-2', :FEATURE_FLAG] => {
51
+ { config_id: 2, selected_index: 3, config_row_index: 5, conditional_value_index: 7,
52
+ weighted_value_index: 6, selected_value: EXAMPLE_VALUE_1 } => 9
53
+ }
54
+ }
55
+
56
+ add_example_data(aggregator)
57
+ assert_equal expected, aggregator.prepare_data
58
+ assert aggregator.data.empty?
59
+ end
60
+
61
+ def test_sync
62
+ awhile_ago = Time.now - 60
63
+ now = Time.now
64
+
65
+ client = MockBaseClient.new
66
+
67
+ aggregator = nil
68
+
69
+ Timecop.freeze(awhile_ago) do
70
+ # start the aggregator in the past
71
+ aggregator = Prefab::EvaluationSummaryAggregator.new(client: client, max_keys: 10,
72
+ sync_interval: EFFECTIVELY_NEVER)
73
+ end
74
+
75
+ add_example_data(aggregator)
76
+
77
+ expected_post = PrefabProto::TelemetryEvents.new(
78
+ instance_hash: client.instance_hash,
79
+ events: [
80
+ PrefabProto::TelemetryEvent.new(
81
+ summaries:
82
+
83
+ PrefabProto::ConfigEvaluationSummaries.new(
84
+ start: awhile_ago.to_i * 1000,
85
+ end: now.to_i * 1000,
86
+ summaries: [
87
+ PrefabProto::ConfigEvaluationSummary.new(
88
+ key: 'config-1',
89
+ type: :CONFIG,
90
+ counters: [
91
+ PrefabProto::ConfigEvaluationCounter.new(
92
+ config_id: 1,
93
+ selected_index: 2,
94
+ config_row_index: 3,
95
+ conditional_value_index: 4,
96
+ weighted_value_index: 5,
97
+ selected_value: EXAMPLE_VALUE_1,
98
+ count: 3
99
+ ),
100
+ PrefabProto::ConfigEvaluationCounter.new(
101
+ config_id: 1,
102
+ selected_index: 3,
103
+ config_row_index: 7,
104
+ conditional_value_index: 8,
105
+ weighted_value_index: 10,
106
+ selected_value: EXAMPLE_VALUE_2,
107
+ count: 1
108
+ )
109
+ ]
110
+ ),
111
+ PrefabProto::ConfigEvaluationSummary.new(
112
+ key: 'config-2',
113
+ type: :FEATURE_FLAG,
114
+ counters: [
115
+ PrefabProto::ConfigEvaluationCounter.new(
116
+ config_id: 2,
117
+ selected_index: 3,
118
+ config_row_index: 5,
119
+ conditional_value_index: 7,
120
+ weighted_value_index: 6,
121
+ selected_value: EXAMPLE_VALUE_1,
122
+ count: 9
123
+ )
124
+ ]
125
+ )
126
+ ]
127
+ )
128
+ )
129
+ ]
130
+ )
131
+
132
+ requests = wait_for_post_requests(client) do
133
+ Timecop.freeze(now) do
134
+ aggregator.sync
135
+ end
136
+ end
137
+
138
+ assert_equal [[
139
+ '/api/v1/telemetry',
140
+ expected_post
141
+ ]], requests
142
+ end
143
+
144
+ private
145
+
146
+ def add_example_data(aggregator)
147
+ data = {
148
+ ['config-1', :CONFIG] => {
149
+ { config_id: 1, selected_index: 2, config_row_index: 3, conditional_value_index: 4,
150
+ weighted_value_index: 5, selected_value: EXAMPLE_VALUE_1 } => 3,
151
+ { config_id: 1, selected_index: 3, config_row_index: 7, conditional_value_index: 8,
152
+ weighted_value_index: 10, selected_value: EXAMPLE_VALUE_2 } => 1
153
+ },
154
+ ['config-2', :FEATURE_FLAG] => {
155
+ { config_id: 2, selected_index: 3, config_row_index: 5, conditional_value_index: 7,
156
+ weighted_value_index: 6, selected_value: EXAMPLE_VALUE_1 } => 9
157
+ }
158
+ }
159
+
160
+ aggregator.instance_variable_set('@data', data)
161
+ end
162
+ end
@@ -0,0 +1,238 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+ require 'timecop'
5
+
6
+ class TestExampleContextsAggregator < Minitest::Test
7
+ EFFECTIVELY_NEVER = 99_999 # we sync manually
8
+
9
+ def test_record
10
+ aggregator = Prefab::ExampleContextsAggregator.new(client: MockBaseClient.new, max_contexts: 2,
11
+ sync_interval: EFFECTIVELY_NEVER)
12
+
13
+ context = Prefab::Context.new(
14
+ user: { key: 'abc' },
15
+ device: { key: 'def', mobile: true }
16
+ )
17
+
18
+ aggregator.record(context)
19
+ assert_equal [context], aggregator.data
20
+
21
+ # This doesn't get updated because we already have a context for this user/device
22
+ aggregator.record(context)
23
+ assert_equal [context], aggregator.data
24
+
25
+ new_context = Prefab::Context.new(
26
+ user: { key: 'ghi', admin: true },
27
+ team: { key: '999' }
28
+ )
29
+
30
+ aggregator.record(new_context)
31
+ assert_equal [context, new_context], aggregator.data
32
+
33
+ # this doesn't get recorded because we're at max_contexts
34
+ aggregator.record(Prefab::Context.new(user: { key: 'new' }))
35
+ assert_equal [context, new_context], aggregator.data
36
+ end
37
+
38
+ def test_prepare_data
39
+ aggregator = Prefab::ExampleContextsAggregator.new(client: MockBaseClient.new, max_contexts: 10,
40
+ sync_interval: EFFECTIVELY_NEVER)
41
+
42
+ context = Prefab::Context.new(
43
+ user: { key: 'abc' },
44
+ device: { key: 'def', mobile: true }
45
+ )
46
+
47
+ aggregator.record(context)
48
+
49
+ assert_equal [context], aggregator.prepare_data
50
+ assert aggregator.data.empty?
51
+ end
52
+
53
+ def test_record_with_expiry
54
+ aggregator = Prefab::ExampleContextsAggregator.new(client: MockBaseClient.new, max_contexts: 10,
55
+ sync_interval: EFFECTIVELY_NEVER)
56
+
57
+ context = Prefab::Context.new(
58
+ user: { key: 'abc' },
59
+ device: { key: 'def', mobile: true }
60
+ )
61
+
62
+ aggregator.record(context)
63
+
64
+ assert_equal [context], aggregator.data
65
+
66
+ Timecop.travel(Time.now + (60 * 60) - 1) do
67
+ aggregator.record(context)
68
+
69
+ # This doesn't get updated because we already have a context for this user/device in the timeframe
70
+ assert_equal [context], aggregator.data
71
+ end
72
+
73
+ Timecop.travel(Time.now + ((60 * 60) + 1)) do
74
+ # this is new because we've passed the expiry
75
+ aggregator.record(context)
76
+
77
+ assert_equal [context, context], aggregator.data
78
+ end
79
+ end
80
+
81
+ def test_sync
82
+ now = Time.now
83
+
84
+ client = MockBaseClient.new
85
+
86
+ aggregator = Prefab::ExampleContextsAggregator.new(client: client, max_contexts: 10,
87
+ sync_interval: EFFECTIVELY_NEVER)
88
+
89
+ context = Prefab::Context.new(
90
+ user: { key: 'abc' },
91
+ device: { key: 'def', mobile: true }
92
+ )
93
+ aggregator.record(context)
94
+
95
+ # This is the same as above so we shouldn't get anything new
96
+ aggregator.record(context)
97
+
98
+ aggregator.record(
99
+ Prefab::Context.new(
100
+ user: { key: 'ghi' },
101
+ device: { key: 'jkl', mobile: false }
102
+ )
103
+ )
104
+
105
+ aggregator.record(Prefab::Context.new(user: { key: 'kev', name: 'kevin', age: 48.5 }))
106
+
107
+ assert_equal 3, aggregator.cache.data.size
108
+
109
+ expected_post = PrefabProto::TelemetryEvents.new(
110
+ instance_hash: client.instance_hash,
111
+ events: [
112
+ PrefabProto::TelemetryEvent.new(
113
+ example_contexts: PrefabProto::ExampleContexts.new(
114
+ examples: [
115
+ PrefabProto::ExampleContext.new(
116
+ timestamp: now.utc.to_i * 1000,
117
+ contextSet: PrefabProto::ContextSet.new(
118
+ contexts: [
119
+ PrefabProto::Context.new(
120
+ type: 'user',
121
+ values: {
122
+ 'key' => PrefabProto::ConfigValue.new(string: 'abc')
123
+ }
124
+ ),
125
+ PrefabProto::Context.new(
126
+ type: 'device',
127
+ values: {
128
+ 'key' => PrefabProto::ConfigValue.new(string: 'def'),
129
+ 'mobile' => PrefabProto::ConfigValue.new(bool: true)
130
+ }
131
+ )
132
+ ]
133
+ )
134
+ ),
135
+
136
+ PrefabProto::ExampleContext.new(
137
+ timestamp: now.utc.to_i * 1000,
138
+ contextSet: PrefabProto::ContextSet.new(
139
+ contexts: [
140
+ PrefabProto::Context.new(
141
+ type: 'user',
142
+ values: {
143
+ 'key' => PrefabProto::ConfigValue.new(string: 'ghi')
144
+ }
145
+ ),
146
+ PrefabProto::Context.new(
147
+ type: 'device',
148
+ values: {
149
+ 'key' => PrefabProto::ConfigValue.new(string: 'jkl'),
150
+ 'mobile' => PrefabProto::ConfigValue.new(bool: false)
151
+ }
152
+ )
153
+ ]
154
+ )
155
+ ),
156
+
157
+ PrefabProto::ExampleContext.new(
158
+ timestamp: now.utc.to_i * 1000,
159
+ contextSet: PrefabProto::ContextSet.new(
160
+ contexts: [
161
+ PrefabProto::Context.new(
162
+ type: 'user',
163
+ values: {
164
+ 'key' => PrefabProto::ConfigValue.new(string: 'kev'),
165
+ 'name' => PrefabProto::ConfigValue.new(string: 'kevin'),
166
+ 'age' => PrefabProto::ConfigValue.new(double: 48.5)
167
+ }
168
+ )
169
+ ]
170
+ )
171
+ )
172
+ ]
173
+ )
174
+ )
175
+ ]
176
+ )
177
+
178
+ requests = wait_for_post_requests(client) do
179
+ Timecop.freeze(now + (60 * 60) - 1) do
180
+ aggregator.sync
181
+ end
182
+ end
183
+
184
+ assert_equal [[
185
+ '/api/v1/telemetry',
186
+ expected_post
187
+ ]], requests
188
+
189
+ # this hasn't changed because not enough time has passed
190
+ assert_equal 3, aggregator.cache.data.size
191
+
192
+ # a sync past the expiry should clear the cache
193
+ Timecop.freeze(now + (60 * 60) + 1) do
194
+ # we need a new piece of data for the sync to happen
195
+ aggregator.record(Prefab::Context.new(user: { key: 'bozo', name: 'Bozo', age: 99 }))
196
+
197
+ requests = wait_for_post_requests(client) do
198
+ aggregator.sync
199
+ end
200
+ end
201
+
202
+ expected_post = PrefabProto::TelemetryEvents.new(
203
+ instance_hash: client.instance_hash,
204
+ events: [
205
+ PrefabProto::TelemetryEvent.new(
206
+ example_contexts: PrefabProto::ExampleContexts.new(
207
+ examples: [
208
+ PrefabProto::ExampleContext.new(
209
+ timestamp: (now.utc.to_i + (60 * 60) + 1) * 1000,
210
+ contextSet: PrefabProto::ContextSet.new(
211
+ contexts: [
212
+ PrefabProto::Context.new(
213
+ type: 'user',
214
+ values: {
215
+ 'key' => PrefabProto::ConfigValue.new(string: 'bozo'),
216
+ 'name' => PrefabProto::ConfigValue.new(string: 'Bozo'),
217
+ 'age' => PrefabProto::ConfigValue.new(int: 99)
218
+ }
219
+ )
220
+ ]
221
+ )
222
+ )
223
+ ]
224
+ )
225
+ )
226
+ ]
227
+ )
228
+
229
+ assert_equal [[
230
+ '/api/v1/telemetry',
231
+ expected_post
232
+ ]], requests
233
+
234
+ # The last sync should have cleared the cache of everything except the latest context
235
+ assert_equal 1, aggregator.cache.data.size
236
+ assert_equal ['user:bozo'], aggregator.cache.data.keys
237
+ end
238
+ end
data/test/test_helper.rb CHANGED
@@ -7,137 +7,11 @@ Minitest::Reporters.use!
7
7
 
8
8
  require 'prefab-cloud-ruby'
9
9
 
10
- class MockBaseClient
11
- STAGING_ENV_ID = 1
12
- PRODUCTION_ENV_ID = 2
13
- TEST_ENV_ID = 3
14
- attr_reader :namespace
15
- attr_reader :logger
16
- attr_reader :config_client
17
- attr_reader :options
18
-
19
- def initialize(options = Prefab::Options.new)
20
- @options = options
21
- @namespace = namespace
22
- @logger = Prefab::LoggerClient.new($stdout)
23
- @config_client = MockConfigClient.new
24
- end
25
-
26
- def project_id
27
- 1
28
- end
29
-
30
- def log
31
- @logger
32
- end
33
-
34
- def log_internal(level, message); end
35
-
36
- def context_shape_aggregator; end
37
-
38
- def evaluated_keys_aggregator; end
39
-
40
- def evaluated_configs_aggregator; end
41
-
42
- def config_value(key)
43
- @config_values[key]
44
- end
45
- end
46
-
47
- class MockConfigClient
48
- def initialize(config_values = {})
49
- @config_values = config_values
50
- end
51
-
52
- def get(key, default = nil)
53
- @config_values.fetch(key, default)
54
- end
55
-
56
- def get_config(key)
57
- PrefabProto::Config.new(value: @config_values[key], key: key)
58
- end
59
-
60
- def mock_this_config(key, config_value)
61
- @config_values[key] = config_value
62
- end
63
- end
64
-
65
- class MockConfigLoader
66
- def calc_config; end
67
- end
68
-
69
- private
70
-
71
- def default_ff_rule(variant_idx)
72
- [
73
- Prefab::Rule.new(
74
- criteria: Prefab::Criteria.new(operator: Prefab::Criteria::CriteriaOperator::ALWAYS_TRUE),
75
- variant_weights: [
76
- Prefab::VariantWeight.new(weight: 1000,
77
- variant_idx: variant_idx)
78
- ]
79
- )
80
- ]
81
- end
82
-
83
- def with_env(key, value, &block)
84
- old_value = ENV[key]
85
-
86
- ENV[key] = value
87
- block.call
88
- ensure
89
- ENV[key] = old_value
90
- end
91
-
92
- def new_client(overrides = {})
93
- options = Prefab::Options.new(**{
94
- prefab_config_override_dir: 'none',
95
- prefab_config_classpath_dir: 'test',
96
- prefab_envs: ['unit_tests'],
97
- prefab_datasources: Prefab::Options::DATASOURCES::LOCAL_ONLY
98
- }.merge(overrides))
99
-
100
- Prefab::Client.new(options)
101
- end
102
-
103
- def string_list(values)
104
- PrefabProto::ConfigValue.new(string_list: PrefabProto::StringList.new(values: values))
105
- end
106
-
107
- def inject_config(client, config)
108
- resolver = client.config_client.instance_variable_get('@config_resolver')
109
- store = resolver.instance_variable_get('@local_store')
110
-
111
- store[config.key] = { config: config }
10
+ Dir.glob(File.join(File.dirname(__FILE__), 'support', '**', '*.rb')).each do |file|
11
+ require file
112
12
  end
113
13
 
114
- def inject_project_env_id(client, project_env_id)
115
- resolver = client.config_client.instance_variable_get('@config_resolver')
116
- resolver.project_env_id = project_env_id
117
- end
118
-
119
- def wait_for_post_requests(client)
120
- max_wait = 2
121
- sleep_time = 0.01
122
-
123
- requests = []
124
-
125
- client.define_singleton_method(:post) do |*params|
126
- requests.push(params)
127
-
128
- OpenStruct.new(status: 200)
129
- end
130
-
131
- yield
132
-
133
- # let the flush thread run
134
- wait_time = 0
135
- while requests.empty?
136
- wait_time += sleep_time
137
- sleep sleep_time
138
-
139
- raise "Waited #{max_wait} seconds for the flush thread to run, but it never did" if wait_time > max_wait
140
- end
141
-
142
- requests
14
+ MiniTest::Test.class_eval do
15
+ include CommonHelpers
16
+ extend CommonHelpers
143
17
  end
@@ -25,11 +25,13 @@ class TestIntegration < Minitest::Test
25
25
  assert_match(/#{it.expected[:message]}/, err.message)
26
26
  when :nil
27
27
  assert_nil it.test_client.send(it.func, *it.input)
28
- when :feature_flag
29
- flag, context = *it.input
30
- assert_equal it.expected[:value], it.test_client.send(it.func, flag, context)
31
28
  when :simple_equality
32
- assert_equal it.expected[:value], it.test_client.send(it.func, *it.input)
29
+ if it.func == :enabled?
30
+ flag, _default, context = *it.input
31
+ assert_equal it.expected[:value], it.test_client.send(it.func, flag, context)
32
+ else
33
+ assert_equal it.expected[:value], it.test_client.send(it.func, *it.input)
34
+ end
33
35
  when :log_level
34
36
  assert_equal it.expected[:value].to_sym, it.test_client.send(it.func, *it.input)
35
37
  else
@@ -34,7 +34,7 @@ class TestLocalConfigParser < Minitest::Test
34
34
  assert_equal 1, config.rows[0].values.size
35
35
 
36
36
  value_row = config.rows[0].values[0]
37
- assert_equal 'all-features', Prefab::ConfigValueUnwrapper.unwrap(value_row.value, key, {})
37
+ assert_equal 'all-features', Prefab::ConfigValueUnwrapper.deepest_value(value_row.value, key, {}).unwrap
38
38
  end
39
39
 
40
40
  def test_flag_in_user_key
@@ -53,7 +53,7 @@ class TestLocalConfigParser < Minitest::Test
53
53
  assert_equal 1, config.rows[0].values[0].criteria.size
54
54
 
55
55
  value_row = config.rows[0].values[0]
56
- assert_equal true, Prefab::ConfigValueUnwrapper.unwrap(value_row.value, key, {})
56
+ assert_equal true, Prefab::ConfigValueUnwrapper.deepest_value(value_row.value, key, {}).unwrap
57
57
 
58
58
  assert_equal 'user.key', value_row.criteria[0].property_name
59
59
  assert_equal :PROP_IS_ONE_OF, value_row.criteria[0].operator
@@ -8,7 +8,8 @@ class TestLogPathAggregator < Minitest::Test
8
8
  SLEEP_TIME = 0.01
9
9
 
10
10
  def test_push
11
- aggregator = Prefab::LogPathAggregator.new(client: new_client, max_paths: 2, sync_interval: 1000)
11
+ client = new_client
12
+ aggregator = Prefab::LogPathAggregator.new(client: client, max_paths: 2, sync_interval: 1000)
12
13
 
13
14
  aggregator.push('test.test_log_path_aggregator.test_push.1', ::Logger::INFO)
14
15
  aggregator.push('test.test_log_path_aggregator.test_push.2', ::Logger::DEBUG)
@@ -18,6 +19,8 @@ class TestLogPathAggregator < Minitest::Test
18
19
  # we've reached the limit, so no more
19
20
  aggregator.push('test.test_log_path_aggregator.test_push.3', ::Logger::INFO)
20
21
  assert_equal 2, aggregator.data.size
22
+
23
+ assert_only_expected_logs
21
24
  end
22
25
 
23
26
  def test_sync
@@ -42,6 +45,11 @@ class TestLogPathAggregator < Minitest::Test
42
45
  namespace: 'this.is.a.namespace'
43
46
  )
44
47
  ]], requests
48
+
49
+ assert_logged [
50
+ 'WARN 2023-08-09 15:18:12 -0400: cloud.prefab.client No success loading checkpoints',
51
+ 'ERROR 2023-08-09 15:18:12 -0400: test.test_log_path_aggregator.test_sync here is a message'
52
+ ]
45
53
  end
46
54
  end
47
55
 
data/test/test_logger.rb CHANGED
@@ -19,6 +19,7 @@ class TestLogger < Minitest::Test
19
19
  )
20
20
 
21
21
  def setup
22
+ super
22
23
  Prefab::LoggerClient.send(:public, :get_path)
23
24
  Prefab::LoggerClient.send(:public, :get_loc_path)
24
25
  Prefab::LoggerClient.send(:public, :level_of)
@@ -65,20 +66,20 @@ class TestLogger < Minitest::Test
65
66
  assert_equal ::Logger::INFO,
66
67
  @logger.level_of('app.models.user'), 'PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL is info'
67
68
 
68
- @logger.set_config_client(MockConfigClient.new({}))
69
+ @logger.config_client = MockConfigClient.new({})
69
70
  assert_equal ::Logger::WARN,
70
71
  @logger.level_of('app.models.user'), 'default is warn'
71
72
 
72
- @logger.set_config_client(MockConfigClient.new('log-level.app' => :INFO))
73
+ @logger.config_client = MockConfigClient.new('log-level.app' => :INFO)
73
74
  assert_equal ::Logger::INFO,
74
75
  @logger.level_of('app.models.user')
75
76
 
76
- @logger.set_config_client(MockConfigClient.new('log-level.app' => :DEBUG))
77
+ @logger.config_client = MockConfigClient.new('log-level.app' => :DEBUG)
77
78
  assert_equal ::Logger::DEBUG,
78
79
  @logger.level_of('app.models.user')
79
80
 
80
- @logger.set_config_client(MockConfigClient.new('log-level.app' => :DEBUG,
81
- 'log-level.app.models' => :ERROR))
81
+ @logger.config_client = MockConfigClient.new('log-level.app' => :DEBUG,
82
+ 'log-level.app.models' => :ERROR)
82
83
  assert_equal ::Logger::ERROR,
83
84
  @logger.level_of('app.models.user'), 'test leveling'
84
85
  end
data/test/test_options.rb CHANGED
@@ -36,9 +36,40 @@ class TestOptions < Minitest::Test
36
36
  assert_equal 0, options.collect_max_paths
37
37
  end
38
38
 
39
- def test_collect_max_paths_with_collect_logs_false
39
+ def test_collect_max_paths_with_collect_logger_counts_false
40
40
  options = Prefab::Options.new(collect_max_paths: 100,
41
- collect_logs: false)
41
+ collect_logger_counts: false)
42
42
  assert_equal 0, options.collect_max_paths
43
43
  end
44
+
45
+ def test_collect_max_evaluation_summaries
46
+ assert_equal 100_000, Prefab::Options.new.collect_max_evaluation_summaries
47
+ assert_equal 0, Prefab::Options.new(collect_evaluation_summaries: false).collect_max_evaluation_summaries
48
+ assert_equal 3,
49
+ Prefab::Options.new(collect_max_evaluation_summaries: 3).collect_max_evaluation_summaries
50
+ end
51
+
52
+ def test_context_upload_mode_periodic
53
+ options = Prefab::Options.new(context_upload_mode: :periodic_example, context_max_size: 100)
54
+ assert_equal 100, options.collect_max_example_contexts
55
+
56
+ options = Prefab::Options.new(context_upload_mode: :none)
57
+ assert_equal 0, options.collect_max_example_contexts
58
+ end
59
+
60
+ def test_context_upload_mode_shape_only
61
+ options = Prefab::Options.new(context_upload_mode: :shape_only, context_max_size: 100)
62
+ assert_equal 100, options.collect_max_shapes
63
+
64
+ options = Prefab::Options.new(context_upload_mode: :none)
65
+ assert_equal 0, options.collect_max_shapes
66
+ end
67
+
68
+ def test_context_upload_mode_none
69
+ options = Prefab::Options.new(context_upload_mode: :none)
70
+ assert_equal 0, options.collect_max_example_contexts
71
+
72
+ options = Prefab::Options.new(context_upload_mode: :none)
73
+ assert_equal 0, options.collect_max_shapes
74
+ end
44
75
  end