Skip to content

Commit e9a646e

Browse files
author
Michael Ng
authored
fix: support audience ids (#161)
1 parent da04ff2 commit e9a646e

File tree

13 files changed

+81
-30
lines changed

13 files changed

+81
-30
lines changed

pkg/config/datafileprojectconfig/entities/entities.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ type Experiment struct {
4242
TrafficAllocation []trafficAllocation `json:"trafficAllocation"`
4343
AudienceIds []string `json:"audienceIds"`
4444
ForcedVariations map[string]string `json:"forcedVariations"`
45-
AudienceConditions interface{} `json:"audienceConditions"`
45+
AudienceConditions []interface{} `json:"audienceConditions"`
4646
}
4747

4848
// FeatureFlag represents a FeatureFlag object from the Optimizely datafile

pkg/config/datafileprojectconfig/mappers/condition_trees.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func buildAudienceConditionTree(conditions interface{}) (conditionTree *entities
108108
value := reflect.ValueOf(conditions)
109109
visited := make(map[interface{}]bool)
110110

111-
conditionTree = &entities.TreeNode{}
111+
conditionTree = &entities.TreeNode{ Operator: "or" }
112112
var populateConditions func(v reflect.Value, root *entities.TreeNode)
113113
populateConditions = func(v reflect.Value, root *entities.TreeNode) {
114114

pkg/config/datafileprojectconfig/mappers/condition_trees_test.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ func TestBuildAudienceConditionTreeEmpty(t *testing.T) {
3030
json.Unmarshal([]byte(conditionString), &conditions)
3131
conditionTree, err := buildAudienceConditionTree(conditions)
3232

33-
assert.NotNil(t, err)
34-
assert.Equal(t, (*entities.TreeNode)(nil), conditionTree)
33+
expectedTree := &entities.TreeNode{Operator: "or"}
34+
assert.NoError(t, err)
35+
assert.Equal(t, expectedTree, conditionTree)
3536
}
3637

3738
func TestBuildAudienceConditionTreeSimpleAudienceCondition(t *testing.T) {
@@ -70,6 +71,22 @@ func TestBuildAudienceConditionTreeSimpleAudienceCondition(t *testing.T) {
7071
assert.Equal(t, expectedConditionTree, conditionTree)
7172
}
7273

74+
func TestBuildAudienceConditionTreeNoOperators(t *testing.T) {
75+
conditions := []string{"123"}
76+
expectedConditionTree := &entities.TreeNode{
77+
Operator: "or",
78+
Nodes: []*entities.TreeNode{
79+
{
80+
Item: "123",
81+
},
82+
},
83+
}
84+
85+
conditionTree, err := buildAudienceConditionTree(conditions)
86+
assert.Equal(t, expectedConditionTree, conditionTree)
87+
assert.NoError(t, err)
88+
}
89+
7390
func TestBuildConditionTreeUsingDatafileAudienceConditions(t *testing.T) {
7491

7592
audience := datafileConfig.Audience{

pkg/config/datafileprojectconfig/mappers/experiment.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,13 @@ func mapVariation(rawVariation datafileEntities.Variation) entities.Variation {
5656

5757
// Maps the raw experiment entity from the datafile into an SDK Experiment entity
5858
func mapExperiment(rawExperiment datafileEntities.Experiment) entities.Experiment {
59-
audienceConditionTree, err := buildAudienceConditionTree(rawExperiment.AudienceConditions)
59+
var audienceConditionTree *entities.TreeNode
60+
var err error
61+
if rawExperiment.AudienceConditions == nil && len(rawExperiment.AudienceIds) > 0 {
62+
audienceConditionTree, err = buildAudienceConditionTree(rawExperiment.AudienceIds)
63+
} else if len(rawExperiment.AudienceConditions) > 0 {
64+
audienceConditionTree, err = buildAudienceConditionTree(rawExperiment.AudienceConditions)
65+
}
6066
if err != nil {
6167
// @TODO: handle error
6268
func() {}() // cheat the linters

pkg/config/datafileprojectconfig/mappers/experiment_test.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ package mappers
1919
import (
2020
"testing"
2121

22-
"github.com/json-iterator/go"
22+
jsoniter "github.com/json-iterator/go"
2323
datafileEntities "github.com/optimizely/go-sdk/pkg/config/datafileprojectconfig/entities"
2424
"github.com/optimizely/go-sdk/pkg/entities"
2525
"github.com/stretchr/testify/assert"
@@ -113,3 +113,31 @@ func TestMapExperiments(t *testing.T) {
113113
assert.Equal(t, expectedExperiments, experiments)
114114
assert.Equal(t, expectedExperimentKeyMap, experimentKeyMap)
115115
}
116+
117+
func TestMapExperimentsAudienceIdsOnly(t *testing.T) {
118+
var rawExperiment datafileEntities.Experiment
119+
rawExperiment.AudienceIds = []string{"11111", "11112"}
120+
rawExperiment.Key = "test_experiment_1"
121+
rawExperiment.ID = "22222"
122+
123+
expectedExperiment := entities.Experiment{
124+
AudienceIds: rawExperiment.AudienceIds,
125+
ID: rawExperiment.ID,
126+
Key: rawExperiment.Key,
127+
AudienceConditionTree: &entities.TreeNode{
128+
Operator: "or",
129+
Nodes: []*entities.TreeNode{
130+
{
131+
Operator: "",
132+
Item: "11111",
133+
},
134+
{
135+
Operator: "",
136+
Item: "11112",
137+
},
138+
},
139+
},
140+
}
141+
experiments, _ := MapExperiments([]datafileEntities.Experiment{rawExperiment})
142+
assert.Equal(t, expectedExperiment.AudienceConditionTree, experiments[rawExperiment.ID].AudienceConditionTree)
143+
}

pkg/decision/evaluator/matchers/exact.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,23 @@ func (m ExactMatcher) Match(user entities.UserContext) (bool, error) {
3434
if stringValue, ok := m.Condition.Value.(string); ok {
3535
attributeValue, err := user.GetStringAttribute(m.Condition.Name)
3636
if err != nil {
37-
return false, err
37+
return false, nil
3838
}
3939
return stringValue == attributeValue, nil
4040
}
4141

4242
if boolValue, ok := m.Condition.Value.(bool); ok {
4343
attributeValue, err := user.GetBoolAttribute(m.Condition.Name)
4444
if err != nil {
45-
return false, err
45+
return false, nil
4646
}
4747
return boolValue == attributeValue, nil
4848
}
4949

5050
if floatValue, ok := utils.ToFloat(m.Condition.Value); ok {
5151
attributeValue, err := user.GetFloatAttribute(m.Condition.Name)
5252
if err != nil {
53-
return false, err
53+
return false, nil
5454
}
5555
return floatValue == attributeValue, nil
5656
}

pkg/decision/evaluator/matchers/exact_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,15 @@ func TestExactMatcherString(t *testing.T) {
5454
assert.NoError(t, err)
5555
assert.False(t, result)
5656

57-
// Test error case
57+
// Test attribute not found
5858
user = entities.UserContext{
5959
Attributes: map[string]interface{}{
6060
"string_not_foo": "foo",
6161
},
6262
}
6363

6464
_, err = matcher.Match(user)
65-
assert.Error(t, err)
65+
assert.NoError(t, err)
6666
}
6767

6868
func TestExactMatcherBool(t *testing.T) {
@@ -95,15 +95,15 @@ func TestExactMatcherBool(t *testing.T) {
9595
assert.NoError(t, err)
9696
assert.False(t, result)
9797

98-
// Test error case
98+
// Test attribute not found
9999
user = entities.UserContext{
100100
Attributes: map[string]interface{}{
101101
"not_bool_true": true,
102102
},
103103
}
104104

105105
_, err = matcher.Match(user)
106-
assert.Error(t, err)
106+
assert.NoError(t, err)
107107
}
108108

109109
func TestExactMatcherInt(t *testing.T) {
@@ -147,15 +147,15 @@ func TestExactMatcherInt(t *testing.T) {
147147
assert.NoError(t, err)
148148
assert.False(t, result)
149149

150-
// Test error case
150+
// Test attribute not found
151151
user = entities.UserContext{
152152
Attributes: map[string]interface{}{
153153
"int_43": 42,
154154
},
155155
}
156156

157157
_, err = matcher.Match(user)
158-
assert.Error(t, err)
158+
assert.NoError(t, err)
159159
}
160160

161161
func TestExactMatcherFloat(t *testing.T) {
@@ -188,13 +188,13 @@ func TestExactMatcherFloat(t *testing.T) {
188188
assert.NoError(t, err)
189189
assert.False(t, result)
190190

191-
// Test error case
191+
// Test attribute not found
192192
user = entities.UserContext{
193193
Attributes: map[string]interface{}{
194194
"float_4_3": 4.2,
195195
},
196196
}
197197

198198
_, err = matcher.Match(user)
199-
assert.Error(t, err)
199+
assert.NoError(t, err)
200200
}

pkg/decision/evaluator/matchers/gt.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func (m GtMatcher) Match(user entities.UserContext) (bool, error) {
3535
if floatValue, ok := utils.ToFloat(m.Condition.Value); ok {
3636
attributeValue, err := user.GetFloatAttribute(m.Condition.Name)
3737
if err != nil {
38-
return false, err
38+
return false, nil
3939
}
4040
return floatValue < attributeValue, nil
4141
}

pkg/decision/evaluator/matchers/gt_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,15 @@ func TestGtMatcherInt(t *testing.T) {
7676
assert.NoError(t, err)
7777
assert.False(t, result)
7878

79-
// Test error case
79+
// Test attribute not found
8080
user = entities.UserContext{
8181
Attributes: map[string]interface{}{
8282
"int_43": 42,
8383
},
8484
}
8585

8686
_, err = matcher.Match(user)
87-
assert.Error(t, err)
87+
assert.NoError(t, err)
8888
}
8989

9090
func TestGtMatcherFloat(t *testing.T) {
@@ -127,13 +127,13 @@ func TestGtMatcherFloat(t *testing.T) {
127127
assert.NoError(t, err)
128128
assert.False(t, result)
129129

130-
// Test error case
130+
// Test attribute not found
131131
user = entities.UserContext{
132132
Attributes: map[string]interface{}{
133133
"float_4_3": 4.2,
134134
},
135135
}
136136

137137
_, err = matcher.Match(user)
138-
assert.Error(t, err)
138+
assert.NoError(t, err)
139139
}

pkg/decision/evaluator/matchers/lt.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func (m LtMatcher) Match(user entities.UserContext) (bool, error) {
3535
if floatValue, ok := utils.ToFloat(m.Condition.Value); ok {
3636
attributeValue, err := user.GetFloatAttribute(m.Condition.Name)
3737
if err != nil {
38-
return false, err
38+
return false, nil
3939
}
4040
return floatValue > attributeValue, nil
4141
}

0 commit comments

Comments
 (0)