Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pkg/config/datafileprojectconfig/mappers/experiment.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/****************************************************************************
* Copyright 2019,2021, Optimizely, Inc. and contributors *
* Copyright 2019,2021-2022, Optimizely, Inc. and contributors *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
Expand Down Expand Up @@ -83,6 +83,7 @@ func mapExperiment(rawExperiment datafileEntities.Experiment) entities.Experimen
AudienceIds: rawExperiment.AudienceIds,
AudienceConditions: rawExperiment.AudienceConditions,
ID: rawExperiment.ID,
IsExperimentRunning: rawExperiment.Status == "Running",
LayerID: rawExperiment.LayerID,
Key: rawExperiment.Key,
Variations: make(map[string]entities.Variation),
Expand Down
14 changes: 9 additions & 5 deletions pkg/config/datafileprojectconfig/mappers/experiment_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/****************************************************************************
* Copyright 2019,2021, Optimizely, Inc. and contributors *
* Copyright 2019,2021-2022, Optimizely, Inc. and contributors *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
Expand Down Expand Up @@ -29,6 +29,7 @@ func TestMapExperiments(t *testing.T) {
const testExperimentString = `{
"audienceIds": ["31111"],
"id": "11111",
"status": "Running",
"key": "test_experiment_11111",
"variations": [
{
Expand Down Expand Up @@ -70,10 +71,11 @@ func TestMapExperiments(t *testing.T) {
experimentsIDMap, experimentKeyMap := MapExperiments(rawExperiments, experimentGroupMap)
expectedExperiments := map[string]entities.Experiment{
"11111": {
AudienceIds: []string{"31111"},
ID: "11111",
GroupID: "15",
Key: "test_experiment_11111",
AudienceIds: []string{"31111"},
ID: "11111",
IsExperimentRunning: true,
GroupID: "15",
Key: "test_experiment_11111",
Variations: map[string]entities.Variation{
"21111": {
ID: "21111",
Expand Down Expand Up @@ -129,6 +131,7 @@ func TestMapExperimentsWithStringAudienceCondition(t *testing.T) {
AudienceIds: []string{"31111"},
Key: "test_experiment_11111",
AudienceConditions: "31111",
Status: "Paused",
}

rawExperiments := []datafileEntities.Experiment{rawExperiment}
Expand All @@ -139,6 +142,7 @@ func TestMapExperimentsWithStringAudienceCondition(t *testing.T) {
"11111": {
AudienceIds: []string{"31111"},
ID: "11111",
IsExperimentRunning: false,
GroupID: "15",
Key: "test_experiment_11111",
Variations: map[string]entities.Variation{},
Expand Down
12 changes: 7 additions & 5 deletions pkg/config/datafileprojectconfig/mappers/rollout_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/****************************************************************************
* Copyright 2019,2021 Optimizely, Inc. and contributors *
* Copyright 2019,2021-2022 Optimizely, Inc. and contributors *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
Expand Down Expand Up @@ -28,8 +28,9 @@ func TestMapRollouts(t *testing.T) {
const testRolloutString = `{
"id": "21111",
"experiments": [
{ "id": "11111", "key": "exp_11111" },
{ "id": "11112", "key": "exp_11112" }
{ "id": "11111", "key": "exp_11111", "status": "Running"},
{ "id": "11112", "key": "exp_11112", "status": "Paused"},
{ "id": "11113", "key": "exp_11113", "status": ""}
]
}`

Expand All @@ -42,8 +43,9 @@ func TestMapRollouts(t *testing.T) {
"21111": {
ID: "21111",
Experiments: []entities.Experiment{
{ID: "11111", Key: "exp_11111", Variations: map[string]entities.Variation{}, VariationKeyToIDMap: map[string]string{}, TrafficAllocation: []entities.Range{}},
{ID: "11112", Key: "exp_11112", Variations: map[string]entities.Variation{}, VariationKeyToIDMap: map[string]string{}, TrafficAllocation: []entities.Range{}},
{ID: "11111", Key: "exp_11111", Variations: map[string]entities.Variation{}, VariationKeyToIDMap: map[string]string{}, TrafficAllocation: []entities.Range{}, IsExperimentRunning: true},
{ID: "11112", Key: "exp_11112", Variations: map[string]entities.Variation{}, VariationKeyToIDMap: map[string]string{}, TrafficAllocation: []entities.Range{}, IsExperimentRunning: false},
{ID: "11113", Key: "exp_11113", Variations: map[string]entities.Variation{}, VariationKeyToIDMap: map[string]string{}, TrafficAllocation: []entities.Range{}, IsExperimentRunning: false},
},
},
}
Expand Down
6 changes: 5 additions & 1 deletion pkg/decision/helpers_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/****************************************************************************
* Copyright 2019-2021, Optimizely, Inc. and contributors *
* Copyright 2019-2022, Optimizely, Inc. and contributors *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
Expand Down Expand Up @@ -120,6 +120,7 @@ var testExp1111 = entities.Experiment{
TrafficAllocation: []entities.Range{
{EntityID: "2222", EndOfRange: 10000},
},
IsExperimentRunning: true,
}

// Simple feature test
Expand Down Expand Up @@ -159,6 +160,7 @@ var testExp1112 = entities.Experiment{
TrafficAllocation: []entities.Range{
{EntityID: "2222", EndOfRange: 10000},
},
IsExperimentRunning: true,
}
var testExp1117Var2223 = entities.Variation{ID: "2223", Key: "2223"}
var testAudience5556 = entities.Audience{ID: "5556"}
Expand All @@ -180,6 +182,7 @@ var testExp1117 = entities.Experiment{
TrafficAllocation: []entities.Range{
{EntityID: "2223", EndOfRange: 10000},
},
IsExperimentRunning: true,
}
var testExp1118Var2224 = entities.Variation{ID: "2224", Key: "2224"}
var testAudience5557 = entities.Audience{ID: "5557"}
Expand All @@ -201,6 +204,7 @@ var testExp1118 = entities.Experiment{
TrafficAllocation: []entities.Range{
{EntityID: "2224", EndOfRange: 10000},
},
IsExperimentRunning: true,
}

const testFeatRollout3334Key = "test_feature_rollout_3334_key"
Expand Down
7 changes: 6 additions & 1 deletion pkg/decision/rollout_service.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/****************************************************************************
* Copyright 2019-2021, Optimizely, Inc. and contributors *
* Copyright 2019-2022, Optimizely, Inc. and contributors *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
Expand Down Expand Up @@ -102,6 +102,11 @@ func (r RolloutService) GetDecision(decisionContext FeatureDecisionContext, user
loggingKey := strconv.Itoa(index + 1)
experiment := &rollout.Experiments[index]

// Only evaluate if experiment is running
if !experiment.IsExperimentRunning {
continue
}

// Checking for forced decision
if forcedDecision := checkForForcedDecision(experiment); forcedDecision != nil {
return *forcedDecision, reasons, nil
Expand Down
48 changes: 47 additions & 1 deletion pkg/decision/rollout_service_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/****************************************************************************
* Copyright 2019-2021, Optimizely, Inc. and contributors *
* Copyright 2019-2022, Optimizely, Inc. and contributors *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
Expand Down Expand Up @@ -117,6 +117,52 @@ func (s *RolloutServiceTestSuite) TestGetDecisionWithNoExperiments() {
s.Equal(expectedFeatureDecision, decision)
}

func (s *RolloutServiceTestSuite) TestGetDecisionWithPausedExperiment() {
// Test experiment passes targeting and bucketing
testExperimentBucketerDecision := ExperimentDecision{
Variation: &testExp1117Var2223,
Decision: Decision{Reason: reasons.BucketedIntoVariation},
}

// Pausing first rollout experiment
featureRollout := &testFeatRollout3334
featureRollout.Rollout.Experiments[0].IsExperimentRunning = false

s.testFeatureDecisionContext = FeatureDecisionContext{
Feature: featureRollout,
ProjectConfig: s.mockConfig,
ForcedDecisionService: NewForcedDecisionService("test_user"),
}

testExperiment1117DecisionContext := ExperimentDecisionContext{
Experiment: &testExp1117,
ProjectConfig: s.mockConfig,
}

s.mockAudienceTreeEvaluator.On("Evaluate", testExp1117.AudienceConditionTree, s.testConditionTreeParams, mock.Anything).Return(true, true, s.reasons)
s.mockExperimentService.On("GetDecision", testExperiment1117DecisionContext, s.testUserContext, s.options, mock.Anything).Return(testExperimentBucketerDecision, s.reasons, nil)

testRolloutService := RolloutService{
audienceTreeEvaluator: s.mockAudienceTreeEvaluator,
experimentBucketerService: s.mockExperimentService,
logger: s.mockLogger,
}
expectedFeatureDecision := FeatureDecision{
Experiment: testExp1117,
Variation: &testExp1117Var2223,
Source: Rollout,
Decision: Decision{Reason: reasons.BucketedIntoRollout},
}
s.mockLogger.On("Debug", fmt.Sprintf(logging.EvaluatingAudiencesForRollout.String(), "2"))
s.mockLogger.On("Debug", fmt.Sprintf(logging.RolloutAudiencesEvaluatedTo.String(), "2", true))
s.mockLogger.On("Debug", `Decision made for user "test_user" for feature rollout with key "test_feature_rollout_3334_key": Bucketed into feature rollout.`)
decision, _, _ := testRolloutService.GetDecision(s.testFeatureDecisionContext, s.testUserContext, s.options)
s.Equal(expectedFeatureDecision, decision)
s.mockAudienceTreeEvaluator.AssertExpectations(s.T())
s.mockExperimentService.AssertExpectations(s.T())
s.mockLogger.AssertExpectations(s.T())
}

func (s *RolloutServiceTestSuite) TestGetDecisionHappyPath() {
// Test experiment passes targeting and bucketing
testExperimentBucketerDecision := ExperimentDecision{
Expand Down
5 changes: 3 additions & 2 deletions pkg/entities/experiment.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/****************************************************************************
* Copyright 2019,2021, Optimizely, Inc. and contributors *
* Copyright 2019,2022, Optimizely, Inc. and contributors *
* *
* Licensed under the Apache License, Version 2.0 (the "License"); *
* you may not use this file except in compliance with the License. *
Expand Down Expand Up @@ -30,6 +30,8 @@ type Experiment struct {
AudienceIds []string
AudienceConditions interface{}
ID string
IsExperimentRunning bool
IsFeatureExperiment bool
LayerID string
Key string
Variations map[string]Variation // keyed by variation ID
Expand All @@ -38,7 +40,6 @@ type Experiment struct {
GroupID string
AudienceConditionTree *TreeNode
Whitelist map[string]string
IsFeatureExperiment bool
}

// Range represents bucketing range that the specify entityID falls into
Expand Down