|
| 1 | +<?php |
| 2 | + |
| 3 | +namespace LaunchDarkly\Tests\Impl\Evaluation; |
| 4 | + |
| 5 | +use LaunchDarkly\EvaluationReason; |
| 6 | +use LaunchDarkly\Impl\Evaluation\Evaluator; |
| 7 | +use LaunchDarkly\Impl\Model\FeatureFlag; |
| 8 | +use LaunchDarkly\LDContext; |
| 9 | +use LaunchDarkly\Tests\FlagBuilder; |
| 10 | +use LaunchDarkly\Tests\ModelBuilders; |
| 11 | +use PHPUnit\Framework\TestCase; |
| 12 | + |
| 13 | +class EvaluatorTargetTest extends TestCase |
| 14 | +{ |
| 15 | + const FALLTHROUGH_VAR = 0, MATCH_VAR_1 = 1, MATCH_VAR_2 = 2; |
| 16 | + const VARIATIONS = ['fallthrough', 'match1', 'match2']; |
| 17 | + |
| 18 | + private static Evaluator $basicEvaluator; |
| 19 | + |
| 20 | + public static function setUpBeforeClass(): void |
| 21 | + { |
| 22 | + static::$basicEvaluator = EvaluatorTestUtil::basicEvaluator(); |
| 23 | + } |
| 24 | + |
| 25 | + public function testUserTargetsOnly() |
| 26 | + { |
| 27 | + $f = self::baseFlagBuilder() |
| 28 | + ->target(self::MATCH_VAR_1, 'c') |
| 29 | + ->target(self::MATCH_VAR_2, 'b', 'a') |
| 30 | + ->build(); |
| 31 | + |
| 32 | + self::expectMatch($f, LDContext::create('a'), self::MATCH_VAR_2); |
| 33 | + self::expectMatch($f, LDContext::create('b'), self::MATCH_VAR_2); |
| 34 | + self::expectMatch($f, LDContext::create('c'), self::MATCH_VAR_1); |
| 35 | + self::expectFallthrough($f, LDContext::create('z')); |
| 36 | + |
| 37 | + // in a multi-kind context, these targets match only the key for the user kind |
| 38 | + self::expectMatch( |
| 39 | + $f, |
| 40 | + LDContext::createMulti(LDContext::create('b', 'dog'), LDContext::create('a')), |
| 41 | + self::MATCH_VAR_2 |
| 42 | + ); |
| 43 | + self::expectMatch( |
| 44 | + $f, |
| 45 | + LDContext::createMulti(LDContext::create('a', 'dog'), LDContext::create('c')), |
| 46 | + self::MATCH_VAR_1 |
| 47 | + ); |
| 48 | + self::expectFallthrough( |
| 49 | + $f, |
| 50 | + LDContext::createMulti(LDContext::create('b', 'dog'), LDContext::create('z')) |
| 51 | + ); |
| 52 | + self::expectFallthrough( |
| 53 | + $f, |
| 54 | + LDContext::createMulti(LDContext::create('a', 'dog'), LDContext::create('b', 'cat')) |
| 55 | + ); |
| 56 | + } |
| 57 | + |
| 58 | + public function userTargetsAndContextTargets() |
| 59 | + { |
| 60 | + $f = self::baseFlagBuilder() |
| 61 | + ->target(self::MATCH_VAR_1, 'c') |
| 62 | + ->target(self::MATCH_VAR_2, 'b', 'a') |
| 63 | + ->contextTarget('dog', self::MATCH_VAR_1, 'a', 'b') |
| 64 | + ->contextTarget('dog', self::MATCH_VAR_2, 'c') |
| 65 | + ->contextTarget(LDContext::DEFAULT_KIND, self::MATCH_VAR_1) |
| 66 | + ->contextTarget(LDContext::DEFAULT_KIND, self::MATCH_VAR_2) |
| 67 | + ->build(); |
| 68 | + |
| 69 | + self::expectMatch($f, LDContext::create('a'), self::MATCH_VAR_2); |
| 70 | + self::expectMatch($f, LDContext::create('b'), self::MATCH_VAR_2); |
| 71 | + self::expectMatch($f, LDContext::create('c'), self::MATCH_VAR_1); |
| 72 | + self::expectFallthrough($f, LDContext::create('z')); |
| 73 | + |
| 74 | + self::expectMatch( |
| 75 | + $f, |
| 76 | + LDContext::createMulti(LDContext::create('b', 'dog'), LDContext::create('a')), |
| 77 | + self::MATCH_VAR_1 // the "dog" target takes precedence due to ordering |
| 78 | + ); |
| 79 | + self::expectMatch( |
| 80 | + $f, |
| 81 | + LDContext::createMulti(LDContext::create('z', 'dog'), LDContext::create('a')), |
| 82 | + self::MATCH_VAR_2 // "dog" targets don't match, continue to "user" targets |
| 83 | + ); |
| 84 | + self::expectFallthrough( |
| 85 | + $f, |
| 86 | + LDContext::createMulti(LDContext::create('x', 'dog'), LDContext::create('z')) // nothing matches |
| 87 | + ); |
| 88 | + self::expectMatch( |
| 89 | + $f, |
| 90 | + LDContext::createMulti(LDContext::create('a', 'dog'), LDContext::create('b', 'cat')), |
| 91 | + self::MATCH_VAR_1 |
| 92 | + ); |
| 93 | + } |
| 94 | + |
| 95 | + private static function baseFlagBuilder(): FlagBuilder |
| 96 | + { |
| 97 | + return ModelBuilders::flagBuilder('feature')->on(true)->variations(...self::VARIATIONS) |
| 98 | + ->fallthroughVariation(self::FALLTHROUGH_VAR)->offVariation(self::FALLTHROUGH_VAR); |
| 99 | + } |
| 100 | + |
| 101 | + private function expectMatch(FeatureFlag $f, LDContext $c, int $v) |
| 102 | + { |
| 103 | + $result = EvaluatorTestUtil::basicEvaluator()->evaluate($f, $c, EvaluatorTestUtil::expectNoPrerequisiteEvals()); |
| 104 | + self::assertEquals($v, $result->getDetail()->getVariationIndex()); |
| 105 | + self::assertEquals(self::VARIATIONS[$v], $result->getDetail()->getValue()); |
| 106 | + self::assertEquals(EvaluationReason::targetMatch(), $result->getDetail()->getReason()); |
| 107 | + } |
| 108 | + |
| 109 | + private function expectFallthrough(FeatureFlag $f, LDContext $c) |
| 110 | + { |
| 111 | + $result = EvaluatorTestUtil::basicEvaluator()->evaluate($f, $c, EvaluatorTestUtil::expectNoPrerequisiteEvals()); |
| 112 | + self::assertEquals(self::FALLTHROUGH_VAR, $result->getDetail()->getVariationIndex()); |
| 113 | + self::assertEquals(self::VARIATIONS[self::FALLTHROUGH_VAR], $result->getDetail()->getValue()); |
| 114 | + self::assertEquals(EvaluationReason::fallthrough(), $result->getDetail()->getReason()); |
| 115 | + } |
| 116 | +} |
0 commit comments