...
1 package evaluation
2
3 import (
4 "fmt"
5 "testing"
6
7 "github.com/launchdarkly/go-sdk-common/v3/ldattr"
8 "github.com/launchdarkly/go-sdk-common/v3/ldcontext"
9 "github.com/launchdarkly/go-sdk-common/v3/ldreason"
10 "github.com/launchdarkly/go-sdk-common/v3/ldvalue"
11 "github.com/launchdarkly/go-server-sdk-evaluation/v2/ldbuilders"
12 "github.com/launchdarkly/go-server-sdk-evaluation/v2/ldmodel"
13 "github.com/stretchr/testify/assert"
14 )
15
16 func assertResultDetail(t *testing.T, expected ldreason.EvaluationDetail, result Result) {
17 assert.Equal(t, expected, result.Detail)
18 }
19
20 type simpleDataProvider struct {
21 getFlag func(string) *ldmodel.FeatureFlag
22 getSegment func(string) *ldmodel.Segment
23 }
24
25 func (s *simpleDataProvider) GetFeatureFlag(key string) *ldmodel.FeatureFlag {
26 return s.getFlag(key)
27 }
28
29 func (s *simpleDataProvider) GetSegment(key string) *ldmodel.Segment {
30 return s.getSegment(key)
31 }
32
33 func (s *simpleDataProvider) withStoredFlags(flags ...ldmodel.FeatureFlag) *simpleDataProvider {
34 return &simpleDataProvider{
35 getFlag: func(key string) *ldmodel.FeatureFlag {
36 for _, f := range flags {
37 if f.Key == key {
38 ff := f
39 return &ff
40 }
41 }
42 return s.getFlag(key)
43 },
44 getSegment: s.getSegment,
45 }
46 }
47
48 func (s *simpleDataProvider) withNonexistentFlag(flagKey string) *simpleDataProvider {
49 return &simpleDataProvider{
50 getFlag: func(key string) *ldmodel.FeatureFlag {
51 if key == flagKey {
52 return nil
53 }
54 return s.getFlag(key)
55 },
56 getSegment: s.getSegment,
57 }
58 }
59
60 func (s *simpleDataProvider) withStoredSegments(segments ...ldmodel.Segment) *simpleDataProvider {
61 return &simpleDataProvider{
62 getFlag: s.getFlag,
63 getSegment: func(key string) *ldmodel.Segment {
64 for _, seg := range segments {
65 if seg.Key == key {
66 ss := seg
67 return &ss
68 }
69 }
70 return s.getSegment(key)
71 },
72 }
73 }
74
75 func (s *simpleDataProvider) withNonexistentSegment(segmentKey string) *simpleDataProvider {
76 return &simpleDataProvider{
77 getFlag: s.getFlag,
78 getSegment: func(key string) *ldmodel.Segment {
79 if key == segmentKey {
80 return nil
81 }
82 return s.getSegment(key)
83 },
84 }
85 }
86
87 func basicDataProvider() *simpleDataProvider {
88 return &simpleDataProvider{
89 getFlag: func(key string) *ldmodel.FeatureFlag {
90 panic(fmt.Errorf("unexpectedly queried feature flag: %s", key))
91 },
92 getSegment: func(key string) *ldmodel.Segment {
93 panic(fmt.Errorf("unexpectedly queried segment: %s", key))
94 },
95 }
96 }
97
98 func basicEvaluator() Evaluator {
99 return NewEvaluator(basicDataProvider())
100 }
101
102 func makeClauseToMatchContext(context ldcontext.Context) ldmodel.Clause {
103 return ldbuilders.ClauseWithKind(context.Kind(), ldattr.KeyAttr, ldmodel.OperatorIn, ldvalue.String(context.Key()))
104 }
105
106 func makeClauseToMatchAnyContextOfKind(kind ldcontext.Kind) ldmodel.Clause {
107 return ldbuilders.Negate(ldbuilders.ClauseWithKind(kind, ldattr.KeyAttr, ldmodel.OperatorIn, ldvalue.String("")))
108 }
109
110 func makeClauseToMatchAnyContextOfAnyKind() ldmodel.Clause {
111 return ldbuilders.Negate(ldbuilders.Clause(ldattr.KindAttr, ldmodel.OperatorIn, ldvalue.String("")))
112 }
113
114 func makeFlagToMatchContext(user ldcontext.Context, variationOrRollout ldmodel.VariationOrRollout) ldmodel.FeatureFlag {
115 return ldbuilders.NewFlagBuilder("feature").
116 On(true).
117 OffVariation(1).
118 AddRule(ldbuilders.NewRuleBuilder().ID("rule-id").VariationOrRollout(variationOrRollout).
119 Clauses(makeClauseToMatchContext(user))).
120 FallthroughVariation(0).
121 Variations(fallthroughValue, offValue, onValue).
122 Build()
123 }
124
125 func makeRuleToMatchUserKeyPrefix(prefix string, variationOrRollout ldmodel.VariationOrRollout) *ldbuilders.RuleBuilder {
126 return ldbuilders.NewRuleBuilder().ID("rule-id").
127 VariationOrRollout(variationOrRollout).
128 Clauses(ldbuilders.Clause(ldattr.KeyAttr, ldmodel.OperatorStartsWith, ldvalue.String(prefix)))
129 }
130
131 func makeBooleanFlagWithClauses(clauses ...ldmodel.Clause) ldmodel.FeatureFlag {
132 return ldbuilders.NewFlagBuilder("feature").
133 On(true).
134 AddRule(ldbuilders.NewRuleBuilder().Variation(1).Clauses(clauses...)).
135 Variations(ldvalue.Bool(false), ldvalue.Bool(true)).
136 FallthroughVariation(0).
137 Build()
138 }
139
140 func makeBooleanFlagToMatchAnyOfSegments(segmentKeys ...string) ldmodel.FeatureFlag {
141 return makeBooleanFlagWithClauses(ldbuilders.SegmentMatchClause(segmentKeys...))
142 }
143
144 func makeBooleanFlagToMatchAllOfSegments(segmentKeys ...string) ldmodel.FeatureFlag {
145 var clauses []ldmodel.Clause
146 for _, segmentKey := range segmentKeys {
147 clauses = append(clauses, ldbuilders.SegmentMatchClause(segmentKey))
148 }
149 return makeBooleanFlagWithClauses(clauses...)
150 }
151
View as plain text