Skip to content

Commit 586b82d

Browse files
yasirfolio3Michael Ng
authored andcommitted
fix(mutual-exclusion-groups): Added missing groupMap implementation and GroupId to Experiment. (#157)
1 parent 903624b commit 586b82d

File tree

6 files changed

+175
-7
lines changed

6 files changed

+175
-7
lines changed

pkg/config/datafileprojectconfig/config.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,10 @@ func NewDatafileProjectConfig(jsonDatafile []byte) (*DatafileProjectConfig, erro
170170
}
171171

172172
attributeMap, attributeKeyToIDMap := mappers.MapAttributes(datafile.Attributes)
173-
experimentMap, experimentKeyMap := mappers.MapExperiments(datafile.Experiments)
173+
allExperiments := mappers.MergeExperiments(datafile.Experiments, datafile.Groups)
174+
groupMap, experimentGroupMap := mappers.MapGroups(datafile.Groups)
175+
experimentMap, experimentKeyMap := mappers.MapExperiments(allExperiments, experimentGroupMap)
176+
174177
rolloutMap := mappers.MapRollouts(datafile.Rollouts)
175178
eventMap := mappers.MapEvents(datafile.Events)
176179
mergedAudiences := append(datafile.TypedAudiences, datafile.Audiences...)
@@ -183,6 +186,7 @@ func NewDatafileProjectConfig(jsonDatafile []byte) (*DatafileProjectConfig, erro
183186
botFiltering: datafile.BotFiltering,
184187
experimentKeyToIDMap: experimentKeyMap,
185188
experimentMap: experimentMap,
189+
groupMap: groupMap,
186190
eventMap: eventMap,
187191
featureMap: mappers.MapFeatures(datafile.FeatureFlags, rolloutMap, experimentMap),
188192
projectID: datafile.ProjectID,

pkg/config/datafileprojectconfig/entities/entities.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,20 @@ type Experiment struct {
3939
LayerID string `json:"layerId"`
4040
Status string `json:"status"`
4141
Variations []Variation `json:"variations"`
42-
TrafficAllocation []trafficAllocation `json:"trafficAllocation"`
42+
TrafficAllocation []TrafficAllocation `json:"trafficAllocation"`
4343
AudienceIds []string `json:"audienceIds"`
4444
ForcedVariations map[string]string `json:"forcedVariations"`
4545
AudienceConditions []interface{} `json:"audienceConditions"`
4646
}
4747

48+
// Group represents an Group object from the Optimizely datafile
49+
type Group struct {
50+
ID string `json:"id"`
51+
Policy string `json:"policy"`
52+
TrafficAllocation []TrafficAllocation `json:"trafficAllocation"`
53+
Experiments []Experiment `json:"experiments"`
54+
}
55+
4856
// FeatureFlag represents a FeatureFlag object from the Optimizely datafile
4957
type FeatureFlag struct {
5058
ID string `json:"id"`
@@ -62,8 +70,8 @@ type Variable struct {
6270
Type entities.VariableType `json:"type"`
6371
}
6472

65-
// trafficAllocation represents a traffic allocation range from the Optimizely datafile
66-
type trafficAllocation struct {
73+
// TrafficAllocation represents a traffic allocation range from the Optimizely datafile
74+
type TrafficAllocation struct {
6775
EntityID string `json:"entityId"`
6876
EndOfRange int `json:"endOfRange"`
6977
}
@@ -100,6 +108,7 @@ type Datafile struct {
100108
Attributes []Attribute `json:"attributes"`
101109
Audiences []Audience `json:"audiences"`
102110
Experiments []Experiment `json:"experiments"`
111+
Groups []Group `json:"groups"`
103112
FeatureFlags []FeatureFlag `json:"featureFlags"`
104113
Events []Event `json:"events"`
105114
Rollouts []Rollout `json:"rollouts"`

pkg/config/datafileprojectconfig/mappers/experiment.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@ import (
2323
)
2424

2525
// MapExperiments maps the raw experiments entities from the datafile to SDK Experiment entities and also returns a map of experiment key to experiment ID
26-
func MapExperiments(rawExperiments []datafileEntities.Experiment) (experimentMap map[string]entities.Experiment, experimentKeyMap map[string]string) {
26+
func MapExperiments(rawExperiments []datafileEntities.Experiment, experimentGroupMap map[string]string) (experimentMap map[string]entities.Experiment, experimentKeyMap map[string]string) {
2727

2828
experimentMap = make(map[string]entities.Experiment)
2929
experimentKeyMap = make(map[string]string)
3030
for _, rawExperiment := range rawExperiments {
3131

3232
experiment := mapExperiment(rawExperiment)
33+
experiment.GroupID = experimentGroupMap[experiment.ID]
3334
experimentMap[experiment.ID] = experiment
3435
experimentKeyMap[experiment.Key] = experiment.ID
3536
}
@@ -89,3 +90,12 @@ func mapExperiment(rawExperiment datafileEntities.Experiment) entities.Experimen
8990

9091
return experiment
9192
}
93+
94+
// MergeExperiments combines raw experiments and experiments inside groups and returns the array
95+
func MergeExperiments(rawExperiments []datafileEntities.Experiment, rawGroups []datafileEntities.Group) (mergedExperiments []datafileEntities.Experiment) {
96+
mergedExperiments = rawExperiments
97+
for _, group := range rawGroups {
98+
mergedExperiments = append(mergedExperiments, group.Experiments...)
99+
}
100+
return mergedExperiments
101+
}

pkg/config/datafileprojectconfig/mappers/experiment_test.go

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,14 @@ func TestMapExperiments(t *testing.T) {
6565
json.Unmarshal([]byte(testExperimentString), &rawExperiment)
6666

6767
rawExperiments := []datafileEntities.Experiment{rawExperiment}
68-
experiments, experimentKeyMap := MapExperiments(rawExperiments)
68+
experimentGroupMap := map[string]string{"11111": "15"}
69+
70+
experiments, experimentKeyMap := MapExperiments(rawExperiments, experimentGroupMap)
6971
expectedExperiments := map[string]entities.Experiment{
7072
"11111": {
7173
AudienceIds: []string{"31111"},
7274
ID: "11111",
75+
GroupID: "15",
7376
Key: "test_experiment_11111",
7477
Variations: map[string]entities.Variation{
7578
"21111": {
@@ -114,6 +117,47 @@ func TestMapExperiments(t *testing.T) {
114117
assert.Equal(t, expectedExperimentKeyMap, experimentKeyMap)
115118
}
116119

120+
func TestMergeExperiments(t *testing.T) {
121+
122+
rawExperiment := datafileEntities.Experiment{
123+
ID: "11111",
124+
}
125+
rawGroup := datafileEntities.Group{
126+
Policy: "random",
127+
ID: "11112",
128+
TrafficAllocation: []datafileEntities.TrafficAllocation{
129+
datafileEntities.TrafficAllocation{
130+
EntityID: "21113",
131+
EndOfRange: 7000,
132+
},
133+
datafileEntities.TrafficAllocation{
134+
EntityID: "21114",
135+
EndOfRange: 10000,
136+
},
137+
},
138+
Experiments: []datafileEntities.Experiment{
139+
datafileEntities.Experiment{
140+
ID: "11112",
141+
},
142+
},
143+
}
144+
145+
rawExperiments := []datafileEntities.Experiment{rawExperiment}
146+
rawGroups := []datafileEntities.Group{rawGroup}
147+
mergedExperiments := MergeExperiments(rawExperiments, rawGroups)
148+
149+
expectedExperiments := []datafileEntities.Experiment{
150+
{
151+
ID: "11111",
152+
},
153+
{
154+
ID: "11112",
155+
},
156+
}
157+
158+
assert.Equal(t, expectedExperiments, mergedExperiments)
159+
}
160+
117161
func TestMapExperimentsAudienceIdsOnly(t *testing.T) {
118162
var rawExperiment datafileEntities.Experiment
119163
rawExperiment.AudienceIds = []string{"11111", "11112"}
@@ -138,6 +182,7 @@ func TestMapExperimentsAudienceIdsOnly(t *testing.T) {
138182
},
139183
},
140184
}
141-
experiments, _ := MapExperiments([]datafileEntities.Experiment{rawExperiment})
185+
186+
experiments, _ := MapExperiments([]datafileEntities.Experiment{rawExperiment}, map[string]string{})
142187
assert.Equal(t, expectedExperiment.AudienceConditionTree, experiments[rawExperiment.ID].AudienceConditionTree)
143188
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/****************************************************************************
2+
* Copyright 2019, Optimizely, Inc. and contributors *
3+
* *
4+
* Licensed under the Apache License, Version 2.0 (the "License"); *
5+
* you may not use this file except in compliance with the License. *
6+
* You may obtain a copy of the License at *
7+
* *
8+
* http://www.apache.org/licenses/LICENSE-2.0 *
9+
* *
10+
* Unless required by applicable law or agreed to in writing, software *
11+
* distributed under the License is distributed on an "AS IS" BASIS, *
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13+
* See the License for the specific language governing permissions and *
14+
* limitations under the License. *
15+
***************************************************************************/
16+
17+
// Package mappers ...
18+
package mappers
19+
20+
import (
21+
datafileEntities "github.com/optimizely/go-sdk/pkg/config/datafileprojectconfig/entities"
22+
"github.com/optimizely/go-sdk/pkg/entities"
23+
)
24+
25+
// MapGroups maps the raw group entity from the datafile to an SDK Group entity
26+
func MapGroups(rawGroups []datafileEntities.Group) (groupMap map[string]entities.Group, experimentGroupMap map[string]string) {
27+
groupMap = make(map[string]entities.Group)
28+
experimentGroupMap = make(map[string]string)
29+
for _, group := range rawGroups {
30+
groupEntity := entities.Group{
31+
ID: group.ID,
32+
Policy: group.Policy,
33+
}
34+
for _, allocation := range group.TrafficAllocation {
35+
groupEntity.TrafficAllocation = append(groupEntity.TrafficAllocation, entities.Range(allocation))
36+
}
37+
groupMap[group.ID] = groupEntity
38+
for _, experiment := range group.Experiments {
39+
experimentGroupMap[experiment.ID] = group.ID
40+
}
41+
}
42+
return groupMap, experimentGroupMap
43+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/****************************************************************************
2+
* Copyright 2019, Optimizely, Inc. and contributors *
3+
* *
4+
* Licensed under the Apache License, Version 2.0 (the "License"); *
5+
* you may not use this file except in compliance with the License. *
6+
* You may obtain a copy of the License at *
7+
* *
8+
* http://www.apache.org/licenses/LICENSE-2.0 *
9+
* *
10+
* Unless required by applicable law or agreed to in writing, software *
11+
* distributed under the License is distributed on an "AS IS" BASIS, *
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13+
* See the License for the specific language governing permissions and *
14+
* limitations under the License. *
15+
***************************************************************************/
16+
17+
package mappers
18+
19+
import (
20+
"testing"
21+
22+
datafileEntities "github.com/optimizely/go-sdk/pkg/config/datafileprojectconfig/entities"
23+
"github.com/optimizely/go-sdk/pkg/entities"
24+
"github.com/stretchr/testify/assert"
25+
)
26+
27+
func TestMapGroups(t *testing.T) {
28+
29+
rawGroup := datafileEntities.Group{
30+
Policy: "random",
31+
ID: "14",
32+
TrafficAllocation: []datafileEntities.TrafficAllocation{
33+
datafileEntities.TrafficAllocation{
34+
EntityID: "13",
35+
EndOfRange: 4000,
36+
},
37+
},
38+
}
39+
40+
rawGroups := []datafileEntities.Group{rawGroup}
41+
groupMap, _ := MapGroups(rawGroups)
42+
43+
expectedGroupsMap := map[string]entities.Group{
44+
"14": entities.Group{
45+
ID: "14",
46+
Policy: "random",
47+
TrafficAllocation: []entities.Range{
48+
entities.Range{
49+
EntityID: "13",
50+
EndOfRange: 4000,
51+
},
52+
},
53+
},
54+
}
55+
56+
assert.Equal(t, expectedGroupsMap, groupMap)
57+
}

0 commit comments

Comments
 (0)