Skip to content

Commit c6213a9

Browse files
[FSSDK-9783] Return Latest Experiment When Duplicate Keys in Config (#370)
* feat: log duplicate experiment keys Also refactored private fields to readonly & standard names * test: updated existing dupe exp keys test Also refactored private fields to readonly & names * fix: remove `readonly` from fields that aren't mine
1 parent d1ebc8e commit c6213a9

File tree

2 files changed

+42
-26
lines changed

2 files changed

+42
-26
lines changed

OptimizelySDK.Tests/OptimizelyConfigTests/OptimizelyConfigTest.cs

+22-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2022, Optimizely
2+
* Copyright 2020-2023, Optimizely
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,28 +29,30 @@ namespace OptimizelySDK.Tests.OptimizelyConfigTests
2929
[TestFixture]
3030
public class OptimizelyConfigTest
3131
{
32-
private Mock<ILogger> LoggerMock;
32+
private Mock<ILogger> _loggerMock;
3333

3434
[SetUp]
3535
public void Setup()
3636
{
37-
LoggerMock = new Mock<ILogger>();
38-
LoggerMock.Setup(l => l.Log(It.IsAny<LogLevel>(), It.IsAny<string>()));
37+
_loggerMock = new Mock<ILogger>();
38+
_loggerMock.Setup(l => l.Log(It.IsAny<LogLevel>(), It.IsAny<string>()));
3939
}
4040

4141
#region Test OptimizelyConfigService
4242

43-
private static Type[] ParameterTypes =
43+
private static readonly Type[] parameterTypes =
4444
{
4545
typeof(ProjectConfig),
46+
typeof(ILogger),
4647
};
4748

4849
private PrivateObject CreatePrivateOptimizelyConfigService(ProjectConfig projectConfig)
4950
{
50-
return new PrivateObject(typeof(OptimizelyConfigService), ParameterTypes,
51+
return new PrivateObject(typeof(OptimizelyConfigService), parameterTypes,
5152
new object[]
5253
{
5354
projectConfig,
55+
new NoOpLogger(),
5456
});
5557
}
5658

@@ -144,22 +146,26 @@ public void TestGetOptimizelyConfigServiceNullConfig()
144146
}
145147

146148
[Test]
147-
[Obsolete]
148149
public void TestGetOptimizelyConfigWithDuplicateExperimentKeys()
149150
{
151+
// OptimizelySDK.Tests/similar_exp_keys.json has DUPLICATED_EXPERIMENT_KEY
152+
const string DUPLICATED_EXPERIMENT_KEY = "targeted_delivery";
153+
const string SECOND_DUPLICATED_EXPERIMENT_ID = "9300000007573";
150154
var datafileProjectConfig = DatafileProjectConfig.Create(
151-
TestData.DuplicateExpKeysDatafile, new NoOpLogger(),
155+
TestData.DuplicateExpKeysDatafile,
156+
new NoOpLogger(),
152157
new ErrorHandler.NoOpErrorHandler());
153-
var optimizelyConfigService = new OptimizelyConfigService(datafileProjectConfig);
158+
var optimizelyConfigService =
159+
new OptimizelyConfigService(datafileProjectConfig, _loggerMock.Object);
160+
154161
var optimizelyConfig = optimizelyConfigService.GetOptimizelyConfig();
155-
Assert.AreEqual(optimizelyConfig.ExperimentsMap.Count, 1);
156162

157-
var experimentMapFlag1 =
158-
optimizelyConfig.FeaturesMap["flag1"].ExperimentsMap; //9300000007569
159-
var experimentMapFlag2 =
160-
optimizelyConfig.FeaturesMap["flag2"].ExperimentsMap; // 9300000007573
161-
Assert.AreEqual(experimentMapFlag1["targeted_delivery"].Id, "9300000007569");
162-
Assert.AreEqual(experimentMapFlag2["targeted_delivery"].Id, "9300000007573");
163+
Assert.AreEqual(optimizelyConfig.ExperimentsMap.Count, 1);
164+
Assert.AreEqual(optimizelyConfig.ExperimentsMap[DUPLICATED_EXPERIMENT_KEY].Id,
165+
SECOND_DUPLICATED_EXPERIMENT_ID);
166+
_loggerMock.Verify(
167+
l => l.Log(LogLevel.WARN,
168+
"Duplicate experiment keys found in datafile: targeted_delivery"), Times.Once);
163169
}
164170

165171
[Test]

OptimizelySDK/OptlyConfig/OptimizelyConfigService.cs

+20-10
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/*
2-
* Copyright 2019-2021, Optimizely
2+
* Copyright 2019-2021, 2023, Optimizely
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
66
* You may obtain a copy of the License at
77
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
8+
* https://www.apache.org/licenses/LICENSE-2.0
99
*
1010
* Unless required by applicable law or agreed to in writing, software
1111
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -15,30 +15,34 @@
1515
*/
1616

1717
using System;
18-
using System.Collections;
1918
using System.Collections.Generic;
2019
using System.Linq;
2120
using System.Text;
2221
using Newtonsoft.Json;
2322
using Newtonsoft.Json.Linq;
2423
using OptimizelySDK.Entity;
24+
using OptimizelySDK.Logger;
2525

2626
namespace OptimizelySDK.OptlyConfig
2727
{
2828
public class OptimizelyConfigService
2929
{
30-
private OptimizelyConfig OptimizelyConfig;
30+
private OptimizelyConfig _optimizelyConfig;
3131

32-
private IDictionary<string, List<FeatureVariable>> featureIdVariablesMap;
32+
private IDictionary<string, List<FeatureVariable>> _featureIdVariablesMap;
3333

34-
public OptimizelyConfigService(ProjectConfig projectConfig)
34+
private readonly ILogger _logger;
35+
36+
public OptimizelyConfigService(ProjectConfig projectConfig, ILogger logger = null)
3537
{
3638
if (projectConfig == null)
3739
{
3840
return;
3941
}
4042

41-
featureIdVariablesMap = GetFeatureVariablesByIdMap(projectConfig);
43+
_logger = logger ?? new DefaultLogger();
44+
45+
_featureIdVariablesMap = GetFeatureVariablesByIdMap(projectConfig);
4246
var attributes = GetAttributes(projectConfig);
4347
var audiences = GetAudiences(projectConfig);
4448
var experimentsMapById = GetExperimentsMapById(projectConfig);
@@ -47,7 +51,7 @@ public OptimizelyConfigService(ProjectConfig projectConfig)
4751
var featureMap = GetFeaturesMap(projectConfig, experimentsMapById);
4852
var events = GetEvents(projectConfig);
4953

50-
OptimizelyConfig = new OptimizelyConfig(projectConfig.Revision,
54+
_optimizelyConfig = new OptimizelyConfig(projectConfig.Revision,
5155
projectConfig.SDKKey,
5256
projectConfig.EnvironmentKey,
5357
attributes,
@@ -118,6 +122,12 @@ IDictionary<string, OptimizelyExperiment> experimentsMapById
118122

119123
foreach (var experiment in experimentsMapById.Values)
120124
{
125+
if (experimentKeyMaps.ContainsKey(experiment.Key))
126+
{
127+
_logger.Log(LogLevel.WARN,
128+
$"Duplicate experiment keys found in datafile: {experiment.Key}");
129+
}
130+
121131
experimentKeyMaps[experiment.Key] = experiment;
122132
}
123133

@@ -210,7 +220,7 @@ bool isFeatureEnabled
210220

211221
if (!string.IsNullOrEmpty(featureId))
212222
{
213-
variablesMap = featureIdVariablesMap[featureId]?.
223+
variablesMap = _featureIdVariablesMap[featureId]?.
214224
Select(f => new OptimizelyVariable(f.Id,
215225
f.Key,
216226
f.Type.ToString().ToLower(),
@@ -451,7 +461,7 @@ private IDictionary<string, FeatureVariable> GetVariableIdMap(ProjectConfig proj
451461

452462
public OptimizelyConfig GetOptimizelyConfig()
453463
{
454-
return OptimizelyConfig;
464+
return _optimizelyConfig;
455465
}
456466
}
457467
}

0 commit comments

Comments
 (0)