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
@@ -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