prefab-cloud-ruby 0.24.5 → 1.0.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.
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
@@ -6,22 +6,33 @@ require 'timecop'
6
6
  class TestCriteriaEvaluator < Minitest::Test
7
7
  PROJECT_ENV_ID = 1
8
8
  TEST_ENV_ID = 2
9
- KEY = 'key'
9
+ KEY = 'the-key'
10
10
  DEFAULT_VALUE = 'default_value'
11
11
  DESIRED_VALUE = 'desired_value'
12
12
  WRONG_ENV_VALUE = 'wrong_env_value'
13
13
 
14
+ DEFAULT_VALUE_CONFIG = PrefabProto::ConfigValue.new(string: DEFAULT_VALUE)
15
+ DESIRED_VALUE_CONFIG = PrefabProto::ConfigValue.new(string: DESIRED_VALUE)
16
+
17
+ TRUE_CONFIG = PrefabProto::ConfigValue.new(bool: true)
18
+ FALSE_CONFIG = PrefabProto::ConfigValue.new(bool: false)
19
+
14
20
  DEFAULT_ROW = PrefabProto::ConfigRow.new(
15
21
  values: [
16
- PrefabProto::ConditionalValue.new(
17
- value: PrefabProto::ConfigValue.new(string: DEFAULT_VALUE)
18
- )
22
+ PrefabProto::ConditionalValue.new(value: DEFAULT_VALUE_CONFIG)
19
23
  ]
20
24
  )
21
25
 
26
+ def setup
27
+ super
28
+ @base_client = FakeBaseClient.new
29
+ end
30
+
22
31
  def test_always_true
23
32
  config = PrefabProto::Config.new(
33
+ id: 123,
24
34
  key: KEY,
35
+ config_type: PrefabProto::ConfigType::CONFIG,
25
36
  rows: [
26
37
  DEFAULT_ROW,
27
38
  PrefabProto::ConfigRow.new(
@@ -29,17 +40,16 @@ class TestCriteriaEvaluator < Minitest::Test
29
40
  values: [
30
41
  PrefabProto::ConditionalValue.new(
31
42
  criteria: [PrefabProto::Criterion.new(operator: PrefabProto::Criterion::CriterionOperator::ALWAYS_TRUE)],
32
- value: PrefabProto::ConfigValue.new(string: DESIRED_VALUE)
43
+ value: DESIRED_VALUE_CONFIG
33
44
  )
34
45
  ]
35
46
  )
36
47
  ]
37
48
  )
38
49
 
39
- evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: FakeBaseClient.new,
40
- namespace: nil)
50
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client, namespace: nil)
41
51
 
42
- assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).string
52
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).unwrapped_value
43
53
  end
44
54
 
45
55
  def test_nested_props_in
@@ -58,19 +68,19 @@ class TestCriteriaEvaluator < Minitest::Test
58
68
  property_name: 'user.key'
59
69
  )
60
70
  ],
61
- value: PrefabProto::ConfigValue.new(string: DESIRED_VALUE)
71
+ value: DESIRED_VALUE_CONFIG
62
72
  )
63
73
  ]
64
74
  )
65
75
  ]
66
76
  )
67
77
 
68
- evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: FakeBaseClient.new,
78
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
69
79
  namespace: nil)
70
80
 
71
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).string
72
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context({ user: { key: 'wrong' } })).string
73
- assert_equal DESIRED_VALUE, evaluator.evaluate(context({ user: { key: 'ok' } })).string
81
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
82
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({ user: { key: 'wrong' } })).unwrapped_value
83
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context({ user: { key: 'ok' } })).unwrapped_value
74
84
  end
75
85
 
76
86
  def test_nested_props_not_in
@@ -89,26 +99,25 @@ class TestCriteriaEvaluator < Minitest::Test
89
99
  property_name: 'user.key'
90
100
  )
91
101
  ],
92
- value: PrefabProto::ConfigValue.new(string: DESIRED_VALUE)
102
+ value: DESIRED_VALUE_CONFIG
93
103
  )
94
104
  ]
95
105
  )
96
106
  ]
97
107
  )
98
108
 
99
- evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: FakeBaseClient.new,
109
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
100
110
  namespace: nil)
101
111
 
102
- assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).string
103
- assert_equal DESIRED_VALUE, evaluator.evaluate(context({ user: { key: 'ok' } })).string
104
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context({ user: { key: 'wrong' } })).string
112
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).unwrapped_value
113
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context({ user: { key: 'ok' } })).unwrapped_value
114
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({ user: { key: 'wrong' } })).unwrapped_value
105
115
  end
106
116
 
107
117
  def test_prop_is_one_of
108
118
  config = PrefabProto::Config.new(
109
119
  key: KEY,
110
120
  rows: [
111
- DEFAULT_ROW,
112
121
  PrefabProto::ConfigRow.new(
113
122
  project_env_id: PROJECT_ENV_ID,
114
123
  values: [
@@ -120,19 +129,20 @@ class TestCriteriaEvaluator < Minitest::Test
120
129
  property_name: 'user.email_suffix'
121
130
  )
122
131
  ],
123
- value: PrefabProto::ConfigValue.new(string: DESIRED_VALUE)
132
+ value: DESIRED_VALUE_CONFIG
124
133
  )
125
134
  ]
126
- )
135
+ ),
136
+ DEFAULT_ROW
127
137
  ]
128
138
  )
129
139
 
130
- evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: FakeBaseClient.new,
140
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
131
141
  namespace: nil)
132
142
 
133
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).string
134
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email_suffix: 'prefab.cloud' })).string
135
- assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email_suffix: 'hotmail.com' })).string
143
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
144
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email_suffix: 'prefab.cloud' })).unwrapped_value
145
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email_suffix: 'hotmail.com' })).unwrapped_value
136
146
  end
137
147
 
138
148
  def test_prop_is_not_one_of
@@ -151,19 +161,19 @@ class TestCriteriaEvaluator < Minitest::Test
151
161
  property_name: 'user.email_suffix'
152
162
  )
153
163
  ],
154
- value: PrefabProto::ConfigValue.new(string: DESIRED_VALUE)
164
+ value: DESIRED_VALUE_CONFIG
155
165
  )
156
166
  ]
157
167
  )
158
168
  ]
159
169
  )
160
170
 
161
- evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: FakeBaseClient.new,
171
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
162
172
  namespace: nil)
163
173
 
164
- assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).string
165
- assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email_suffix: 'prefab.cloud' })).string
166
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email_suffix: 'hotmail.com' })).string
174
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).unwrapped_value
175
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email_suffix: 'prefab.cloud' })).unwrapped_value
176
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email_suffix: 'hotmail.com' })).unwrapped_value
167
177
  end
168
178
 
169
179
  def test_prop_ends_with_one_of
@@ -182,19 +192,19 @@ class TestCriteriaEvaluator < Minitest::Test
182
192
  property_name: 'user.email'
183
193
  )
184
194
  ],
185
- value: PrefabProto::ConfigValue.new(string: DESIRED_VALUE)
195
+ value: DESIRED_VALUE_CONFIG
186
196
  )
187
197
  ]
188
198
  )
189
199
  ]
190
200
  )
191
201
 
192
- evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: FakeBaseClient.new,
202
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
193
203
  namespace: nil)
194
204
 
195
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).string
196
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email: 'example@prefab.cloud' })).string
197
- assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@hotmail.com' })).string
205
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
206
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email: 'example@prefab.cloud' })).unwrapped_value
207
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@hotmail.com' })).unwrapped_value
198
208
  end
199
209
 
200
210
  def test_prop_does_not_end_with_one_of
@@ -213,19 +223,19 @@ class TestCriteriaEvaluator < Minitest::Test
213
223
  property_name: 'user.email'
214
224
  )
215
225
  ],
216
- value: PrefabProto::ConfigValue.new(string: DESIRED_VALUE)
226
+ value: DESIRED_VALUE_CONFIG
217
227
  )
218
228
  ]
219
229
  )
220
230
  ]
221
231
  )
222
232
 
223
- evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: FakeBaseClient.new,
233
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
224
234
  namespace: nil)
225
235
 
226
- assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).string
227
- assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@prefab.cloud' })).string
228
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email: 'example@hotmail.com' })).string
236
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).unwrapped_value
237
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@prefab.cloud' })).unwrapped_value
238
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email: 'example@hotmail.com' })).unwrapped_value
229
239
  end
230
240
 
231
241
  def test_in_seg
@@ -238,7 +248,7 @@ class TestCriteriaEvaluator < Minitest::Test
238
248
  PrefabProto::ConfigRow.new(
239
249
  values: [
240
250
  PrefabProto::ConditionalValue.new(
241
- value: PrefabProto::ConfigValue.new(bool: true),
251
+ value: TRUE_CONFIG,
242
252
  criteria: [
243
253
  PrefabProto::Criterion.new(
244
254
  operator: PrefabProto::Criterion::CriterionOperator::PROP_ENDS_WITH_ONE_OF,
@@ -247,9 +257,7 @@ class TestCriteriaEvaluator < Minitest::Test
247
257
  )
248
258
  ]
249
259
  ),
250
- PrefabProto::ConditionalValue.new(
251
- value: PrefabProto::ConfigValue.new(bool: false)
252
- )
260
+ PrefabProto::ConditionalValue.new(value: FALSE_CONFIG)
253
261
  ]
254
262
  )
255
263
  ]
@@ -260,23 +268,6 @@ class TestCriteriaEvaluator < Minitest::Test
260
268
  rows: [
261
269
  DEFAULT_ROW,
262
270
 
263
- # wrong env
264
- PrefabProto::ConfigRow.new(
265
- project_env_id: TEST_ENV_ID,
266
- values: [
267
- PrefabProto::ConditionalValue.new(
268
- criteria: [
269
- PrefabProto::Criterion.new(
270
- operator: PrefabProto::Criterion::CriterionOperator::IN_SEG,
271
- value_to_match: PrefabProto::ConfigValue.new(string: segment_key)
272
- )
273
- ],
274
- value: PrefabProto::ConfigValue.new(string: WRONG_ENV_VALUE)
275
- )
276
- ]
277
- ),
278
-
279
- # correct env
280
271
  PrefabProto::ConfigRow.new(
281
272
  project_env_id: PROJECT_ENV_ID,
282
273
  values: [
@@ -287,7 +278,7 @@ class TestCriteriaEvaluator < Minitest::Test
287
278
  value_to_match: PrefabProto::ConfigValue.new(string: segment_key)
288
279
  )
289
280
  ],
290
- value: PrefabProto::ConfigValue.new(string: DESIRED_VALUE)
281
+ value: DESIRED_VALUE_CONFIG
291
282
  )
292
283
  ]
293
284
  )
@@ -295,12 +286,12 @@ class TestCriteriaEvaluator < Minitest::Test
295
286
  )
296
287
 
297
288
  evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID,
298
- base_client: FakeBaseClient.new, namespace: nil,
289
+ base_client: @base_client, namespace: nil,
299
290
  resolver: resolver_fake({ segment_key => segment_config }))
300
291
 
301
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).string
302
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email: 'example@prefab.cloud' })).string
303
- assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@hotmail.com' })).string
292
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
293
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email: 'example@prefab.cloud' })).unwrapped_value
294
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@hotmail.com' })).unwrapped_value
304
295
  end
305
296
 
306
297
  def test_not_in_seg
@@ -313,7 +304,7 @@ class TestCriteriaEvaluator < Minitest::Test
313
304
  PrefabProto::ConfigRow.new(
314
305
  values: [
315
306
  PrefabProto::ConditionalValue.new(
316
- value: PrefabProto::ConfigValue.new(bool: true),
307
+ value: TRUE_CONFIG,
317
308
  criteria: [
318
309
  PrefabProto::Criterion.new(
319
310
  operator: PrefabProto::Criterion::CriterionOperator::PROP_ENDS_WITH_ONE_OF,
@@ -322,9 +313,7 @@ class TestCriteriaEvaluator < Minitest::Test
322
313
  )
323
314
  ]
324
315
  ),
325
- PrefabProto::ConditionalValue.new(
326
- value: PrefabProto::ConfigValue.new(bool: false)
327
- )
316
+ PrefabProto::ConditionalValue.new(value: FALSE_CONFIG)
328
317
  ]
329
318
  )
330
319
  ]
@@ -344,7 +333,7 @@ class TestCriteriaEvaluator < Minitest::Test
344
333
  value_to_match: PrefabProto::ConfigValue.new(string: segment_key)
345
334
  )
346
335
  ],
347
- value: PrefabProto::ConfigValue.new(string: DESIRED_VALUE)
336
+ value: DESIRED_VALUE_CONFIG
348
337
  )
349
338
  ]
350
339
  )
@@ -352,12 +341,12 @@ class TestCriteriaEvaluator < Minitest::Test
352
341
  )
353
342
 
354
343
  evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID,
355
- base_client: FakeBaseClient.new, namespace: nil,
344
+ base_client: @base_client, namespace: nil,
356
345
  resolver: resolver_fake({ segment_key => segment_config }))
357
346
 
358
- assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).string
359
- assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@prefab.cloud' })).string
360
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email: 'example@hotmail.com' })).string
347
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).unwrapped_value
348
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@prefab.cloud' })).unwrapped_value
349
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email: 'example@hotmail.com' })).unwrapped_value
361
350
  end
362
351
 
363
352
  def test_multiple_conditions_in_one_value
@@ -370,7 +359,7 @@ class TestCriteriaEvaluator < Minitest::Test
370
359
  PrefabProto::ConfigRow.new(
371
360
  values: [
372
361
  PrefabProto::ConditionalValue.new(
373
- value: PrefabProto::ConfigValue.new(bool: true),
362
+ value: TRUE_CONFIG,
374
363
  criteria: [
375
364
  PrefabProto::Criterion.new(
376
365
  operator: PrefabProto::Criterion::CriterionOperator::PROP_ENDS_WITH_ONE_OF,
@@ -380,14 +369,12 @@ class TestCriteriaEvaluator < Minitest::Test
380
369
 
381
370
  PrefabProto::Criterion.new(
382
371
  operator: PrefabProto::Criterion::CriterionOperator::PROP_IS_ONE_OF,
383
- value_to_match: PrefabProto::ConfigValue.new(bool: true),
372
+ value_to_match: TRUE_CONFIG,
384
373
  property_name: 'user.admin'
385
374
  )
386
375
  ]
387
376
  ),
388
- PrefabProto::ConditionalValue.new(
389
- value: PrefabProto::ConfigValue.new(bool: false)
390
- )
377
+ PrefabProto::ConditionalValue.new(value: FALSE_CONFIG)
391
378
  ]
392
379
  )
393
380
  ]
@@ -409,11 +396,11 @@ class TestCriteriaEvaluator < Minitest::Test
409
396
 
410
397
  PrefabProto::Criterion.new(
411
398
  operator: PrefabProto::Criterion::CriterionOperator::PROP_IS_NOT_ONE_OF,
412
- value_to_match: PrefabProto::ConfigValue.new(bool: true),
399
+ value_to_match: TRUE_CONFIG,
413
400
  property_name: 'user.deleted'
414
401
  )
415
402
  ],
416
- value: PrefabProto::ConfigValue.new(string: DESIRED_VALUE)
403
+ value: DESIRED_VALUE_CONFIG
417
404
  )
418
405
  ]
419
406
  )
@@ -421,18 +408,18 @@ class TestCriteriaEvaluator < Minitest::Test
421
408
  )
422
409
 
423
410
  evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID,
424
- base_client: FakeBaseClient.new, namespace: nil,
411
+ base_client: @base_client, namespace: nil,
425
412
  resolver: resolver_fake({ segment_key => segment_config }))
426
413
 
427
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).string
428
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email: 'example@prefab.cloud' })).string
429
- assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@prefab.cloud', admin: true })).string
414
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
415
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email: 'example@prefab.cloud' })).unwrapped_value
416
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@prefab.cloud', admin: true })).unwrapped_value
430
417
  assert_equal DEFAULT_VALUE,
431
- evaluator.evaluate(context(user: { email: 'example@prefab.cloud', admin: true, deleted: true })).string
432
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email: 'example@gmail.com' })).string
433
- assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@gmail.com', admin: true })).string
418
+ evaluator.evaluate(context(user: { email: 'example@prefab.cloud', admin: true, deleted: true })).unwrapped_value
419
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email: 'example@gmail.com' })).unwrapped_value
420
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@gmail.com', admin: true })).unwrapped_value
434
421
  assert_equal DEFAULT_VALUE,
435
- evaluator.evaluate(context(user: { email: 'example@gmail.com', admin: true, deleted: true })).string
422
+ evaluator.evaluate(context(user: { email: 'example@gmail.com', admin: true, deleted: true })).unwrapped_value
436
423
  end
437
424
 
438
425
  def test_multiple_conditions_in_multiple_values
@@ -445,7 +432,7 @@ class TestCriteriaEvaluator < Minitest::Test
445
432
  PrefabProto::ConfigRow.new(
446
433
  values: [
447
434
  PrefabProto::ConditionalValue.new(
448
- value: PrefabProto::ConfigValue.new(bool: true),
435
+ value: TRUE_CONFIG,
449
436
  criteria: [
450
437
  PrefabProto::Criterion.new(
451
438
  operator: PrefabProto::Criterion::CriterionOperator::PROP_ENDS_WITH_ONE_OF,
@@ -455,18 +442,16 @@ class TestCriteriaEvaluator < Minitest::Test
455
442
  ]
456
443
  ),
457
444
  PrefabProto::ConditionalValue.new(
458
- value: PrefabProto::ConfigValue.new(bool: true),
445
+ value: TRUE_CONFIG,
459
446
  criteria: [
460
447
  PrefabProto::Criterion.new(
461
448
  operator: PrefabProto::Criterion::CriterionOperator::PROP_IS_ONE_OF,
462
- value_to_match: PrefabProto::ConfigValue.new(bool: true),
449
+ value_to_match: TRUE_CONFIG,
463
450
  property_name: 'user.admin'
464
451
  )
465
452
  ]
466
453
  ),
467
- PrefabProto::ConditionalValue.new(
468
- value: PrefabProto::ConfigValue.new(bool: false)
469
- )
454
+ PrefabProto::ConditionalValue.new(value: FALSE_CONFIG)
470
455
  ]
471
456
  )
472
457
  ]
@@ -488,11 +473,11 @@ class TestCriteriaEvaluator < Minitest::Test
488
473
 
489
474
  PrefabProto::Criterion.new(
490
475
  operator: PrefabProto::Criterion::CriterionOperator::PROP_IS_NOT_ONE_OF,
491
- value_to_match: PrefabProto::ConfigValue.new(bool: true),
476
+ value_to_match: TRUE_CONFIG,
492
477
  property_name: 'user.deleted'
493
478
  )
494
479
  ],
495
- value: PrefabProto::ConfigValue.new(string: DESIRED_VALUE)
480
+ value: DESIRED_VALUE_CONFIG
496
481
  )
497
482
  ]
498
483
  )
@@ -500,19 +485,19 @@ class TestCriteriaEvaluator < Minitest::Test
500
485
  )
501
486
 
502
487
  evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID,
503
- base_client: FakeBaseClient.new, namespace: nil,
488
+ base_client: @base_client, namespace: nil,
504
489
  resolver: resolver_fake({ segment_key => segment_config }))
505
490
 
506
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).string
507
- assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@prefab.cloud' })).string
508
- assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { admin: true })).string
509
- assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@prefab.cloud', admin: true })).string
491
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
492
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@prefab.cloud' })).unwrapped_value
493
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { admin: true })).unwrapped_value
494
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@prefab.cloud', admin: true })).unwrapped_value
510
495
  assert_equal DEFAULT_VALUE,
511
- evaluator.evaluate(context(user: { email: 'example@prefab.cloud', admin: true, deleted: true })).string
512
- assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@gmail.com' })).string
513
- assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@gmail.com', admin: true })).string
496
+ evaluator.evaluate(context(user: { email: 'example@prefab.cloud', admin: true, deleted: true })).unwrapped_value
497
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@gmail.com' })).unwrapped_value
498
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { email: 'example@gmail.com', admin: true })).unwrapped_value
514
499
  assert_equal DEFAULT_VALUE,
515
- evaluator.evaluate(context(user: { email: 'example@gmail.com', admin: true, deleted: true })).string
500
+ evaluator.evaluate(context(user: { email: 'example@gmail.com', admin: true, deleted: true })).unwrapped_value
516
501
  end
517
502
 
518
503
  def test_stringifying_property_values_and_names
@@ -531,7 +516,7 @@ class TestCriteriaEvaluator < Minitest::Test
531
516
  property_name: 'team.name'
532
517
  )
533
518
  ],
534
- value: PrefabProto::ConfigValue.new(string: DESIRED_VALUE)
519
+ value: DESIRED_VALUE_CONFIG
535
520
  )
536
521
  ]
537
522
  )
@@ -539,15 +524,15 @@ class TestCriteriaEvaluator < Minitest::Test
539
524
  )
540
525
 
541
526
  evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil,
542
- namespace: nil, base_client: FakeBaseClient.new)
527
+ namespace: nil, base_client: @base_client)
543
528
 
544
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).string
545
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context(team: { name: 'prefab.cloud' })).string
529
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
530
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(team: { name: 'prefab.cloud' })).unwrapped_value
546
531
 
547
532
  [1, true, :hello].each do |value|
548
533
  [:name, 'name'].each do |property_name|
549
- assert_equal DESIRED_VALUE, evaluator.evaluate(context(team: { property_name => value })).string
550
- assert_equal DESIRED_VALUE, evaluator.evaluate(context(team: { property_name => value.to_s })).string
534
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(team: { property_name => value })).unwrapped_value
535
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(team: { property_name => value.to_s })).unwrapped_value
551
536
  end
552
537
  end
553
538
  end
@@ -564,7 +549,7 @@ class TestCriteriaEvaluator < Minitest::Test
564
549
  PrefabProto::Criterion.new(operator: PrefabProto::Criterion::CriterionOperator::IN_INT_RANGE,
565
550
  value_to_match: PrefabProto::ConfigValue.new(int_range: PrefabProto::IntRange.new(start: 30, end: 40)), property_name: 'user.age')
566
551
  ],
567
- value: PrefabProto::ConfigValue.new(string: DESIRED_VALUE)
552
+ value: DESIRED_VALUE_CONFIG
568
553
  ),
569
554
 
570
555
  PrefabProto::ConditionalValue.new(
@@ -579,12 +564,12 @@ class TestCriteriaEvaluator < Minitest::Test
579
564
  )
580
565
 
581
566
  evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil,
582
- namespace: nil, base_client: FakeBaseClient.new)
567
+ namespace: nil, base_client: @base_client)
583
568
 
584
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).string
585
- assert_equal DESIRED_VALUE, evaluator.evaluate(context({ 'user' => { 'age' => 32 } })).string
586
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context({ 'user' => { 'age' => 29 } })).string
587
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context({ 'user' => { 'age' => 41 } })).string
569
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
570
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context({ 'user' => { 'age' => 32 } })).unwrapped_value
571
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({ 'user' => { 'age' => 29 } })).unwrapped_value
572
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({ 'user' => { 'age' => 41 } })).unwrapped_value
588
573
  end
589
574
 
590
575
  def test_in_int_range_for_time
@@ -605,7 +590,7 @@ class TestCriteriaEvaluator < Minitest::Test
605
590
  )
606
591
  ), property_name: 'prefab.current-time')
607
592
  ],
608
- value: PrefabProto::ConfigValue.new(string: DESIRED_VALUE)
593
+ value: DESIRED_VALUE_CONFIG
609
594
  ),
610
595
 
611
596
  PrefabProto::ConditionalValue.new(
@@ -620,27 +605,82 @@ class TestCriteriaEvaluator < Minitest::Test
620
605
  )
621
606
 
622
607
  evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil,
623
- namespace: nil, base_client: FakeBaseClient.new)
608
+ namespace: nil, base_client: @base_client)
624
609
 
625
610
  Timecop.freeze(now) do
626
- assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).string
611
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).unwrapped_value
627
612
  end
628
613
 
629
614
  Timecop.freeze(now - 60) do
630
- assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).string
615
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).unwrapped_value
631
616
  end
632
617
 
633
618
  Timecop.freeze(now - 61) do
634
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).string
619
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
635
620
  end
636
621
 
637
622
  Timecop.freeze(now + 59) do
638
- assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).string
623
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).unwrapped_value
639
624
  end
640
625
 
641
626
  Timecop.freeze(now + 60) do
642
- assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).string
627
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
628
+ end
629
+ end
630
+
631
+ def test_evaluating_a_log_level
632
+ config = PrefabProto::Config.new(
633
+ id: 999,
634
+ key: 'log-level',
635
+ config_type: PrefabProto::ConfigType::LOG_LEVEL,
636
+ rows: [
637
+ PrefabProto::ConfigRow.new(
638
+ values: [
639
+ PrefabProto::ConditionalValue.new(
640
+ criteria: [PrefabProto::Criterion.new(operator: PrefabProto::Criterion::CriterionOperator::ALWAYS_TRUE)],
641
+ value: PrefabProto::ConfigValue.new(log_level: PrefabProto::LogLevel::DEBUG)
642
+ )
643
+ ]
644
+ )
645
+ ]
646
+ )
647
+
648
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client, namespace: nil)
649
+
650
+ assert_equal :DEBUG, evaluator.evaluate(context({})).unwrapped_value
651
+ end
652
+
653
+ def test_evaluating_a_weighted_value
654
+ config = PrefabProto::Config.new(
655
+ id: 123,
656
+ key: KEY,
657
+ config_type: PrefabProto::ConfigType::CONFIG,
658
+ rows: [
659
+ PrefabProto::ConfigRow.new(
660
+ project_env_id: PROJECT_ENV_ID,
661
+ values: [
662
+ PrefabProto::ConditionalValue.new(
663
+ criteria: [PrefabProto::Criterion.new(operator: PrefabProto::Criterion::CriterionOperator::ALWAYS_TRUE)],
664
+ value: PrefabProto::ConfigValue.new(weighted_values: weighted_values([['abc', 98], ['def', 1], ['ghi', 1]]))
665
+ )
666
+ ]
667
+ )
668
+ ]
669
+ )
670
+
671
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client, namespace: nil)
672
+
673
+ 2.times do
674
+ assert_equal 'abc', evaluator.evaluate(context('user' => { 'key' => '1' })).unwrapped_value
675
+ end
676
+
677
+ 3.times do
678
+ context = context({ 'user' => { 'key' => '12' } })
679
+ assert_equal 'def', evaluator.evaluate(context).unwrapped_value
643
680
  end
681
+
682
+ context = context({ 'user' => { 'key' => '4' } })
683
+ assert_equal 'ghi', evaluator.evaluate(context).unwrapped_value
644
684
  end
645
685
 
646
686
  private
@@ -650,8 +690,9 @@ class TestCriteriaEvaluator < Minitest::Test
650
690
  end
651
691
 
652
692
  class FakeResolver
653
- def initialize(config)
693
+ def initialize(config, base_client)
654
694
  @config = config
695
+ @base_client = base_client
655
696
  end
656
697
 
657
698
  def raw(key)
@@ -661,16 +702,12 @@ class TestCriteriaEvaluator < Minitest::Test
661
702
  def get(key, properties = {})
662
703
  # This only gets called for segments, so we don't need to pass in a resolver
663
704
  Prefab::CriteriaEvaluator.new(@config[key], project_env_id: nil, resolver: nil,
664
- namespace: nil, base_client: FakeBaseClient.new).evaluate(properties)
705
+ namespace: nil, base_client: @base_client).evaluate(properties)
665
706
  end
666
707
  end
667
708
 
668
709
  def resolver_fake(config)
669
- FakeResolver.new(config)
670
- end
671
-
672
- def context(properties)
673
- Prefab::Context.new(properties)
710
+ FakeResolver.new(config, @base_client)
674
711
  end
675
712
 
676
713
  class FakeLogger
@@ -678,11 +715,21 @@ class TestCriteriaEvaluator < Minitest::Test
678
715
  # loudly complain about unexpected log messages
679
716
  raise msg
680
717
  end
718
+
719
+ def log_internal(*args); end
681
720
  end
682
721
 
683
722
  class FakeBaseClient
684
723
  def log
685
724
  FakeLogger.new
686
725
  end
726
+
727
+ def evaluation_summary_aggregator
728
+ @evaluation_summary_aggregator ||= Prefab::EvaluationSummaryAggregator.new(client: self, max_keys: 9999, sync_interval: 9999)
729
+ end
730
+
731
+ def instance_hash
732
+ 'fake-base-client-instance_hash'
733
+ end
687
734
  end
688
735
  end