From 7a2fd20fdc551520f019a9acc1c10554739c462a Mon Sep 17 00:00:00 2001 From: Mike Chu Date: Tue, 25 Jul 2023 10:08:05 -0400 Subject: [PATCH 01/12] Add early check for eventKey being null/empty --- OptimizelySDK/Optimizely.cs | 42 ++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/OptimizelySDK/Optimizely.cs b/OptimizelySDK/Optimizely.cs index 9da300f8..0963fbf4 100644 --- a/OptimizelySDK/Optimizely.cs +++ b/OptimizelySDK/Optimizely.cs @@ -87,7 +87,7 @@ public static String SDK_VERSION { get { - // Example output: "2.1.0" . Should be kept in synch with NuGet package version. + // Example output: "2.1.0". Should be kept in sync with NuGet package version. #if NET35 || NET40 var assembly = Assembly.GetExecutingAssembly(); #else @@ -346,46 +346,52 @@ public void Track(string eventKey, string userId, UserAttributes userAttributes EventTags eventTags = null ) { - var config = ProjectConfigManager?.GetConfig(); - - if (config == null) + if (string.IsNullOrEmpty(eventKey)) { - Logger.Log(LogLevel.ERROR, "Datafile has invalid format. Failing 'Track'."); + Logger.Log(LogLevel.ERROR, + "Event key cannot be null or empty string. Failing 'Track'."); return; } var inputValues = new Dictionary - { { USER_ID, userId }, { EVENT_KEY, eventKey } }; + { + { USER_ID, userId }, + { EVENT_KEY, eventKey }, + }; if (!ValidateStringInputs(inputValues)) { return; } - var eevent = config.GetEvent(eventKey); - - if (eevent.Key == null) + var config = ProjectConfigManager?.GetConfig(); + if (config == null) { - Logger.Log(LogLevel.INFO, - string.Format("Not tracking user {0} for event {1}.", userId, eventKey)); + Logger.Log(LogLevel.ERROR, "Datafile has invalid format. Failing 'Track'."); return; } - if (eventTags != null) + var eventToTrack = config.GetEvent(eventKey); + if (eventToTrack.Key == null) { - eventTags = eventTags.FilterNullValues(Logger); + Logger.Log(LogLevel.INFO, $"Not tracking user {userId} for event {eventKey}."); + return; } + eventTags = eventTags?.FilterNullValues(Logger); + var userEvent = UserEventFactory.CreateConversionEvent(config, eventKey, userId, userAttributes, eventTags); + EventProcessor.Process(userEvent); - Logger.Log(LogLevel.INFO, - string.Format("Tracking event {0} for user {1}.", eventKey, userId)); + + Logger.Log(LogLevel.INFO, $"Tracking event {eventKey} for user {userId}."); if (NotificationCenter.GetNotificationCount(NotificationCenter.NotificationType.Track) > 0) { var conversionEvent = EventFactory.CreateLogEvent(userEvent, Logger); + NotificationCenter.SendNotifications(NotificationCenter.NotificationType.Track, eventKey, userId, userAttributes, eventTags, conversionEvent); @@ -1347,7 +1353,8 @@ List segmentOptions if (config == null) { - Logger.Log(LogLevel.ERROR, "Datafile has invalid format. Failing 'FetchQualifiedSegments'."); + Logger.Log(LogLevel.ERROR, + "Datafile has invalid format. Failing 'FetchQualifiedSegments'."); return null; } @@ -1378,7 +1385,8 @@ internal void IdentifyUser(string userId) /// Dictionary for identifiers. The caller must provide at least one key-value pair. /// Type of event (defaults to `fullstack`) /// Optional event data in a key-value pair format - public void SendOdpEvent(string action, Dictionary identifiers, string type = Constants.ODP_EVENT_TYPE, + public void SendOdpEvent(string action, Dictionary identifiers, string type + = Constants.ODP_EVENT_TYPE, Dictionary data = null ) { From aa6e2131a081a5829b2a5e859a17b4cc91c562ba Mon Sep 17 00:00:00 2001 From: Mike Chu Date: Tue, 25 Jul 2023 10:28:20 -0400 Subject: [PATCH 02/12] Adjust Track tests for null/empty event key --- OptimizelySDK.Tests/OptimizelyTest.cs | 41 ++++++++++++++++++--------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/OptimizelySDK.Tests/OptimizelyTest.cs b/OptimizelySDK.Tests/OptimizelyTest.cs index 5dab3aec..c7c692ec 100644 --- a/OptimizelySDK.Tests/OptimizelyTest.cs +++ b/OptimizelySDK.Tests/OptimizelyTest.cs @@ -624,7 +624,7 @@ public void TestInvalidInstanceLogMessages() Times.Once); LoggerMock.Verify( log => log.Log(LogLevel.ERROR, "Datafile has invalid format. Failing 'Track'."), - Times.Once); + Times.Never); // Erroring on null or empty event key takes priority over invalid datafile. LoggerMock.Verify( log => log.Log(LogLevel.ERROR, "Datafile has invalid format. Failing 'IsFeatureEnabled'."), Times.Once); @@ -5673,15 +5673,20 @@ public void TestTrackValidateInputValues() LoggerMock.Verify(l => l.Log(LogLevel.ERROR, "Provided User Id is in invalid format."), Times.Never); LoggerMock.Verify( - l => l.Log(LogLevel.ERROR, "Provided Event Key is in invalid format."), + l => l.Log(LogLevel.ERROR, "Event key cannot be null or empty string. Failing 'Track'."), Times.Never); - // Verify that ValidateStringInputs logs error for invalid values. - Optimizely.Track("", null); + // Verify that ValidateStringInputs logs error for invalid event key. + Optimizely.Track("", "test_user"); + LoggerMock.Verify( + l => l.Log(LogLevel.ERROR, + "Event key cannot be null or empty string. Failing 'Track'."), + Times.Once); + + // Verify that ValidateStringInputs logs error for invalid user id. + Optimizely.Track("purchase", null); LoggerMock.Verify(l => l.Log(LogLevel.ERROR, "Provided User Id is in invalid format."), Times.Once); - LoggerMock.Verify( - l => l.Log(LogLevel.ERROR, "Provided Event Key is in invalid format."), Times.Once); } #endregion Test ValidateStringInputs @@ -6139,8 +6144,10 @@ public static void SetCulture(string culture) [Test] public void TestSendOdpEventNullAction() { - var optly = new Optimizely(TestData.OdpIntegrationDatafile, logger: LoggerMock.Object, odpManager: OdpManagerMock.Object); - optly.SendOdpEvent(action: null, identifiers: new Dictionary(), type: "type"); + var optly = new Optimizely(TestData.OdpIntegrationDatafile, logger: LoggerMock.Object, + odpManager: OdpManagerMock.Object); + optly.SendOdpEvent(action: null, identifiers: new Dictionary(), + type: "type"); LoggerMock.Verify(l => l.Log(LogLevel.ERROR, Constants.ODP_INVALID_ACTION_MESSAGE), Times.Exactly(1)); @@ -6151,7 +6158,8 @@ public void TestSendOdpEventNullAction() public void TestSendOdpEventInvalidOptimizelyObject() { var optly = new Optimizely("Random datafile", null, LoggerMock.Object); - optly.SendOdpEvent("some_action", new Dictionary() { { "some_key", "some_value" } }, "some_event"); + optly.SendOdpEvent("some_action", + new Dictionary() { { "some_key", "some_value" } }, "some_event"); LoggerMock.Verify( l => l.Log(LogLevel.ERROR, "Datafile has invalid format. Failing 'SendOdpEvent'."), Times.Once); @@ -6160,8 +6168,10 @@ public void TestSendOdpEventInvalidOptimizelyObject() [Test] public void TestSendOdpEventEmptyStringAction() { - var optly = new Optimizely(TestData.OdpIntegrationDatafile, logger: LoggerMock.Object, odpManager: OdpManagerMock.Object); - optly.SendOdpEvent(action: "", identifiers: new Dictionary(), type: "type"); + var optly = new Optimizely(TestData.OdpIntegrationDatafile, logger: LoggerMock.Object, + odpManager: OdpManagerMock.Object); + optly.SendOdpEvent(action: "", identifiers: new Dictionary(), + type: "type"); LoggerMock.Verify(l => l.Log(LogLevel.ERROR, Constants.ODP_INVALID_ACTION_MESSAGE), Times.Exactly(1)); @@ -6172,7 +6182,8 @@ public void TestSendOdpEventEmptyStringAction() public void TestSendOdpEventNullType() { var identifiers = new Dictionary(); - var optly = new Optimizely(TestData.OdpIntegrationDatafile, logger: LoggerMock.Object, odpManager: OdpManagerMock.Object); + var optly = new Optimizely(TestData.OdpIntegrationDatafile, logger: LoggerMock.Object, + odpManager: OdpManagerMock.Object); optly.SendOdpEvent(action: "action", identifiers: identifiers, type: null); @@ -6188,7 +6199,8 @@ public void TestSendOdpEventNullType() public void TestSendOdpEventEmptyStringType() { var identifiers = new Dictionary(); - var optly = new Optimizely(TestData.OdpIntegrationDatafile, logger: LoggerMock.Object, odpManager: OdpManagerMock.Object); + var optly = new Optimizely(TestData.OdpIntegrationDatafile, logger: LoggerMock.Object, + odpManager: OdpManagerMock.Object); optly.SendOdpEvent(action: "action", identifiers: identifiers, type: ""); @@ -6210,7 +6222,8 @@ public void TestFetchQualifiedSegmentsInvalidOptimizelyObject() var optly = new Optimizely("Random datafile", null, LoggerMock.Object); optly.FetchQualifiedSegments("some_user", null); LoggerMock.Verify( - l => l.Log(LogLevel.ERROR, "Datafile has invalid format. Failing 'FetchQualifiedSegments'."), + l => l.Log(LogLevel.ERROR, + "Datafile has invalid format. Failing 'FetchQualifiedSegments'."), Times.Once); } From 7a6cbb3bf7af7d8ad23d84013603a545ce585ecd Mon Sep 17 00:00:00 2001 From: Mike Chu Date: Tue, 25 Jul 2023 11:06:58 -0400 Subject: [PATCH 03/12] Update method docs --- OptimizelySDK/Optimizely.cs | 2 +- OptimizelySDK/OptimizelyUserContext.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OptimizelySDK/Optimizely.cs b/OptimizelySDK/Optimizely.cs index 0963fbf4..04610962 100644 --- a/OptimizelySDK/Optimizely.cs +++ b/OptimizelySDK/Optimizely.cs @@ -338,7 +338,7 @@ private bool ValidateInputs(string datafile, bool skipJsonValidation) /// /// Sends conversion event to Optimizely. /// - /// Event key representing the event which needs to be recorded + /// Event key representing the event (must not be null or empty) /// ID for user /// Attributes of the user /// eventTags array Hash representing metadata associated with the event. diff --git a/OptimizelySDK/OptimizelyUserContext.cs b/OptimizelySDK/OptimizelyUserContext.cs index f7b37dac..9649e404 100644 --- a/OptimizelySDK/OptimizelyUserContext.cs +++ b/OptimizelySDK/OptimizelyUserContext.cs @@ -348,7 +348,7 @@ OptimizelyDecideOption[] options /// /// Track an event. /// - /// The event name. + /// The event name (must not be null or empty). public virtual void TrackEvent(string eventName) { TrackEvent(eventName, new EventTags()); @@ -357,7 +357,7 @@ public virtual void TrackEvent(string eventName) /// /// Track an event. /// - /// The event name. + /// The event name (must not be null or empty). /// A map of event tag names to event tag values. public virtual void TrackEvent(string eventName, EventTags eventTags From 0251e5a0a1ce76a30f68b6e386039ae9b99f47cf Mon Sep 17 00:00:00 2001 From: Mike Chu Date: Tue, 25 Jul 2023 11:08:44 -0400 Subject: [PATCH 04/12] Use IsNullOrWhiteSpace for eventKey --- OptimizelySDK/Optimizely.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OptimizelySDK/Optimizely.cs b/OptimizelySDK/Optimizely.cs index 04610962..ad6952ca 100644 --- a/OptimizelySDK/Optimizely.cs +++ b/OptimizelySDK/Optimizely.cs @@ -346,7 +346,7 @@ public void Track(string eventKey, string userId, UserAttributes userAttributes EventTags eventTags = null ) { - if (string.IsNullOrEmpty(eventKey)) + if (string.IsNullOrWhiteSpace(eventKey)) { Logger.Log(LogLevel.ERROR, "Event key cannot be null or empty string. Failing 'Track'."); From 0a265c97b74d575e77ee8523db63c4f102b5b9ef Mon Sep 17 00:00:00 2001 From: Mike Chu Date: Tue, 25 Jul 2023 11:10:37 -0400 Subject: [PATCH 05/12] Add doc about no whitespace --- OptimizelySDK/Optimizely.cs | 2 +- OptimizelySDK/OptimizelyUserContext.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OptimizelySDK/Optimizely.cs b/OptimizelySDK/Optimizely.cs index ad6952ca..664471fa 100644 --- a/OptimizelySDK/Optimizely.cs +++ b/OptimizelySDK/Optimizely.cs @@ -338,7 +338,7 @@ private bool ValidateInputs(string datafile, bool skipJsonValidation) /// /// Sends conversion event to Optimizely. /// - /// Event key representing the event (must not be null or empty) + /// Event key representing the event (must not be null, empty, or whitespace) /// ID for user /// Attributes of the user /// eventTags array Hash representing metadata associated with the event. diff --git a/OptimizelySDK/OptimizelyUserContext.cs b/OptimizelySDK/OptimizelyUserContext.cs index 9649e404..0f095976 100644 --- a/OptimizelySDK/OptimizelyUserContext.cs +++ b/OptimizelySDK/OptimizelyUserContext.cs @@ -348,7 +348,7 @@ OptimizelyDecideOption[] options /// /// Track an event. /// - /// The event name (must not be null or empty). + /// The event name (must not be null, empty, or whitespace). public virtual void TrackEvent(string eventName) { TrackEvent(eventName, new EventTags()); @@ -357,7 +357,7 @@ public virtual void TrackEvent(string eventName) /// /// Track an event. /// - /// The event name (must not be null or empty). + /// The event name (must not be null, empty, or whitespace). /// A map of event tag names to event tag values. public virtual void TrackEvent(string eventName, EventTags eventTags From dcbedf4b43432601a6c6429a93586d551fe15bfd Mon Sep 17 00:00:00 2001 From: Mike Chu Date: Tue, 25 Jul 2023 11:14:52 -0400 Subject: [PATCH 06/12] Refactor code; Update logged error message --- OptimizelySDK.Tests/OptimizelyTest.cs | 20 +++++++++++++++----- OptimizelySDK/Optimizely.cs | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/OptimizelySDK.Tests/OptimizelyTest.cs b/OptimizelySDK.Tests/OptimizelyTest.cs index c7c692ec..7b45a8f9 100644 --- a/OptimizelySDK.Tests/OptimizelyTest.cs +++ b/OptimizelySDK.Tests/OptimizelyTest.cs @@ -5668,23 +5668,33 @@ public void TestGetVariationValidateInputValues() [Test] public void TestTrackValidateInputValues() { + const string GOOD_EVENT_KEY = "purchase"; + const string GOOD_USER = "test_user"; + // Verify that ValidateStringInputs does not log error for valid values. - Optimizely.Track("purchase", "test_user"); + Optimizely.Track(GOOD_EVENT_KEY, GOOD_USER); LoggerMock.Verify(l => l.Log(LogLevel.ERROR, "Provided User Id is in invalid format."), Times.Never); LoggerMock.Verify( l => l.Log(LogLevel.ERROR, "Event key cannot be null or empty string. Failing 'Track'."), Times.Never); - // Verify that ValidateStringInputs logs error for invalid event key. - Optimizely.Track("", "test_user"); + // Verify logs error for invalid empty string event key. + Optimizely.Track(GOOD_EVENT_KEY, GOOD_USER); + LoggerMock.Verify( + l => l.Log(LogLevel.ERROR, + "Event key cannot be null, empty or whitespace string. Failing 'Track'."), + Times.Once); + + // Verify logs error for invalid whitespace string event key. + Optimizely.Track(" ", GOOD_USER); LoggerMock.Verify( l => l.Log(LogLevel.ERROR, - "Event key cannot be null or empty string. Failing 'Track'."), + "Event key cannot be null, empty or whitespace string. Failing 'Track'."), Times.Once); // Verify that ValidateStringInputs logs error for invalid user id. - Optimizely.Track("purchase", null); + Optimizely.Track(GOOD_EVENT_KEY, null); LoggerMock.Verify(l => l.Log(LogLevel.ERROR, "Provided User Id is in invalid format."), Times.Once); } diff --git a/OptimizelySDK/Optimizely.cs b/OptimizelySDK/Optimizely.cs index 664471fa..d58a4642 100644 --- a/OptimizelySDK/Optimizely.cs +++ b/OptimizelySDK/Optimizely.cs @@ -349,7 +349,7 @@ public void Track(string eventKey, string userId, UserAttributes userAttributes if (string.IsNullOrWhiteSpace(eventKey)) { Logger.Log(LogLevel.ERROR, - "Event key cannot be null or empty string. Failing 'Track'."); + "Event key cannot be null, empty or whitespace string. Failing 'Track'."); return; } From 1ab6c5582b2b291922e596e80a2bbef267408156 Mon Sep 17 00:00:00 2001 From: Mike Chu Date: Tue, 25 Jul 2023 11:24:48 -0400 Subject: [PATCH 07/12] Further refactors --- OptimizelySDK.Tests/OptimizelyTest.cs | 30 ++++++++++++++++----------- OptimizelySDK/Optimizely.cs | 2 +- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/OptimizelySDK.Tests/OptimizelyTest.cs b/OptimizelySDK.Tests/OptimizelyTest.cs index 7b45a8f9..5251c61d 100644 --- a/OptimizelySDK.Tests/OptimizelyTest.cs +++ b/OptimizelySDK.Tests/OptimizelyTest.cs @@ -5669,33 +5669,39 @@ public void TestGetVariationValidateInputValues() public void TestTrackValidateInputValues() { const string GOOD_EVENT_KEY = "purchase"; + const string EXPECTED_EVENT_KEY_ERROR_MESSAGE = + "Event key cannot be null, empty, or whitespace string. Failing 'Track'."; const string GOOD_USER = "test_user"; + const string EXPECTED_USER_ID_ERROR_MESSAGE = "Provided User Id is in invalid format."; - // Verify that ValidateStringInputs does not log error for valid values. Optimizely.Track(GOOD_EVENT_KEY, GOOD_USER); - LoggerMock.Verify(l => l.Log(LogLevel.ERROR, "Provided User Id is in invalid format."), + LoggerMock.Verify(l => l.Log(LogLevel.ERROR, EXPECTED_USER_ID_ERROR_MESSAGE), Times.Never); LoggerMock.Verify( - l => l.Log(LogLevel.ERROR, "Event key cannot be null or empty string. Failing 'Track'."), + l => l.Log(LogLevel.ERROR, EXPECTED_EVENT_KEY_ERROR_MESSAGE), Times.Never); + LoggerMock.ResetCalls(); - // Verify logs error for invalid empty string event key. - Optimizely.Track(GOOD_EVENT_KEY, GOOD_USER); + Optimizely.Track("", GOOD_USER); LoggerMock.Verify( - l => l.Log(LogLevel.ERROR, - "Event key cannot be null, empty or whitespace string. Failing 'Track'."), + l => l.Log(LogLevel.ERROR, EXPECTED_EVENT_KEY_ERROR_MESSAGE), Times.Once); + LoggerMock.ResetCalls(); - // Verify logs error for invalid whitespace string event key. Optimizely.Track(" ", GOOD_USER); LoggerMock.Verify( - l => l.Log(LogLevel.ERROR, - "Event key cannot be null, empty or whitespace string. Failing 'Track'."), + l => l.Log(LogLevel.ERROR, EXPECTED_EVENT_KEY_ERROR_MESSAGE), Times.Once); + LoggerMock.ResetCalls(); + + Optimizely.Track(null, GOOD_USER); + LoggerMock.Verify( + l => l.Log(LogLevel.ERROR, EXPECTED_EVENT_KEY_ERROR_MESSAGE), + Times.Once); + LoggerMock.ResetCalls(); - // Verify that ValidateStringInputs logs error for invalid user id. Optimizely.Track(GOOD_EVENT_KEY, null); - LoggerMock.Verify(l => l.Log(LogLevel.ERROR, "Provided User Id is in invalid format."), + LoggerMock.Verify(l => l.Log(LogLevel.ERROR, EXPECTED_USER_ID_ERROR_MESSAGE), Times.Once); } diff --git a/OptimizelySDK/Optimizely.cs b/OptimizelySDK/Optimizely.cs index d58a4642..e24a8d6a 100644 --- a/OptimizelySDK/Optimizely.cs +++ b/OptimizelySDK/Optimizely.cs @@ -349,7 +349,7 @@ public void Track(string eventKey, string userId, UserAttributes userAttributes if (string.IsNullOrWhiteSpace(eventKey)) { Logger.Log(LogLevel.ERROR, - "Event key cannot be null, empty or whitespace string. Failing 'Track'."); + "Event key cannot be null, empty, or whitespace string. Failing 'Track'."); return; } From 0b6f70a4756c1192fa22b05bca04531a9546a4da Mon Sep 17 00:00:00 2001 From: Mike Chu Date: Tue, 25 Jul 2023 11:28:34 -0400 Subject: [PATCH 08/12] Lint fixes --- OptimizelySDK.Tests/OptimizelyTest.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OptimizelySDK.Tests/OptimizelyTest.cs b/OptimizelySDK.Tests/OptimizelyTest.cs index 5251c61d..a0cca1d0 100644 --- a/OptimizelySDK.Tests/OptimizelyTest.cs +++ b/OptimizelySDK.Tests/OptimizelyTest.cs @@ -5673,7 +5673,7 @@ public void TestTrackValidateInputValues() "Event key cannot be null, empty, or whitespace string. Failing 'Track'."; const string GOOD_USER = "test_user"; const string EXPECTED_USER_ID_ERROR_MESSAGE = "Provided User Id is in invalid format."; - + Optimizely.Track(GOOD_EVENT_KEY, GOOD_USER); LoggerMock.Verify(l => l.Log(LogLevel.ERROR, EXPECTED_USER_ID_ERROR_MESSAGE), Times.Never); @@ -5693,13 +5693,13 @@ public void TestTrackValidateInputValues() l => l.Log(LogLevel.ERROR, EXPECTED_EVENT_KEY_ERROR_MESSAGE), Times.Once); LoggerMock.ResetCalls(); - + Optimizely.Track(null, GOOD_USER); LoggerMock.Verify( l => l.Log(LogLevel.ERROR, EXPECTED_EVENT_KEY_ERROR_MESSAGE), Times.Once); LoggerMock.ResetCalls(); - + Optimizely.Track(GOOD_EVENT_KEY, null); LoggerMock.Verify(l => l.Log(LogLevel.ERROR, EXPECTED_USER_ID_ERROR_MESSAGE), Times.Once); From 9bf7230f9c72c274064c5862c69bb7289f9f95e4 Mon Sep 17 00:00:00 2001 From: Mike Chu Date: Tue, 25 Jul 2023 11:39:11 -0400 Subject: [PATCH 09/12] Fixing whitespace lints --- OptimizelySDK.Tests/OptimizelyTest.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/OptimizelySDK.Tests/OptimizelyTest.cs b/OptimizelySDK.Tests/OptimizelyTest.cs index a0cca1d0..ee980c97 100644 --- a/OptimizelySDK.Tests/OptimizelyTest.cs +++ b/OptimizelySDK.Tests/OptimizelyTest.cs @@ -5673,7 +5673,7 @@ public void TestTrackValidateInputValues() "Event key cannot be null, empty, or whitespace string. Failing 'Track'."; const string GOOD_USER = "test_user"; const string EXPECTED_USER_ID_ERROR_MESSAGE = "Provided User Id is in invalid format."; - + Optimizely.Track(GOOD_EVENT_KEY, GOOD_USER); LoggerMock.Verify(l => l.Log(LogLevel.ERROR, EXPECTED_USER_ID_ERROR_MESSAGE), Times.Never); @@ -5681,25 +5681,25 @@ public void TestTrackValidateInputValues() l => l.Log(LogLevel.ERROR, EXPECTED_EVENT_KEY_ERROR_MESSAGE), Times.Never); LoggerMock.ResetCalls(); - + Optimizely.Track("", GOOD_USER); LoggerMock.Verify( l => l.Log(LogLevel.ERROR, EXPECTED_EVENT_KEY_ERROR_MESSAGE), Times.Once); LoggerMock.ResetCalls(); - + Optimizely.Track(" ", GOOD_USER); LoggerMock.Verify( l => l.Log(LogLevel.ERROR, EXPECTED_EVENT_KEY_ERROR_MESSAGE), Times.Once); LoggerMock.ResetCalls(); - + Optimizely.Track(null, GOOD_USER); LoggerMock.Verify( l => l.Log(LogLevel.ERROR, EXPECTED_EVENT_KEY_ERROR_MESSAGE), Times.Once); LoggerMock.ResetCalls(); - + Optimizely.Track(GOOD_EVENT_KEY, null); LoggerMock.Verify(l => l.Log(LogLevel.ERROR, EXPECTED_USER_ID_ERROR_MESSAGE), Times.Once); From 259709801717d7119de5dece0fb79d19a625db41 Mon Sep 17 00:00:00 2001 From: Mike Chu Date: Tue, 25 Jul 2023 12:01:03 -0400 Subject: [PATCH 10/12] Fix lints ... Tested locally --- OptimizelySDK.Tests/OptimizelyTest.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/OptimizelySDK.Tests/OptimizelyTest.cs b/OptimizelySDK.Tests/OptimizelyTest.cs index ee980c97..a0cca1d0 100644 --- a/OptimizelySDK.Tests/OptimizelyTest.cs +++ b/OptimizelySDK.Tests/OptimizelyTest.cs @@ -5673,7 +5673,7 @@ public void TestTrackValidateInputValues() "Event key cannot be null, empty, or whitespace string. Failing 'Track'."; const string GOOD_USER = "test_user"; const string EXPECTED_USER_ID_ERROR_MESSAGE = "Provided User Id is in invalid format."; - + Optimizely.Track(GOOD_EVENT_KEY, GOOD_USER); LoggerMock.Verify(l => l.Log(LogLevel.ERROR, EXPECTED_USER_ID_ERROR_MESSAGE), Times.Never); @@ -5681,25 +5681,25 @@ public void TestTrackValidateInputValues() l => l.Log(LogLevel.ERROR, EXPECTED_EVENT_KEY_ERROR_MESSAGE), Times.Never); LoggerMock.ResetCalls(); - + Optimizely.Track("", GOOD_USER); LoggerMock.Verify( l => l.Log(LogLevel.ERROR, EXPECTED_EVENT_KEY_ERROR_MESSAGE), Times.Once); LoggerMock.ResetCalls(); - + Optimizely.Track(" ", GOOD_USER); LoggerMock.Verify( l => l.Log(LogLevel.ERROR, EXPECTED_EVENT_KEY_ERROR_MESSAGE), Times.Once); LoggerMock.ResetCalls(); - + Optimizely.Track(null, GOOD_USER); LoggerMock.Verify( l => l.Log(LogLevel.ERROR, EXPECTED_EVENT_KEY_ERROR_MESSAGE), Times.Once); LoggerMock.ResetCalls(); - + Optimizely.Track(GOOD_EVENT_KEY, null); LoggerMock.Verify(l => l.Log(LogLevel.ERROR, EXPECTED_USER_ID_ERROR_MESSAGE), Times.Once); From a2b8d54fedce39507d6ac85e3544f5c2d483759c Mon Sep 17 00:00:00 2001 From: Mike Chu Date: Tue, 25 Jul 2023 13:23:22 -0400 Subject: [PATCH 11/12] Put back needed Linq import --- OptimizelySDK/Config/HttpProjectConfigManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OptimizelySDK/Config/HttpProjectConfigManager.cs b/OptimizelySDK/Config/HttpProjectConfigManager.cs index 6a73e2ec..2ae478a7 100644 --- a/OptimizelySDK/Config/HttpProjectConfigManager.cs +++ b/OptimizelySDK/Config/HttpProjectConfigManager.cs @@ -19,6 +19,7 @@ #endif using System; +using System.Linq; using System.Net; using System.Threading.Tasks; using OptimizelySDK.ErrorHandler; From aad09e1dee030c28db851bbe0df4a96a2f2e782c Mon Sep 17 00:00:00 2001 From: Mike Chu Date: Tue, 25 Jul 2023 13:23:56 -0400 Subject: [PATCH 12/12] Fix for .NET 3.5 lacking IsNullOrWhiteSpace() --- OptimizelySDK/Optimizely.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OptimizelySDK/Optimizely.cs b/OptimizelySDK/Optimizely.cs index e24a8d6a..91503e03 100644 --- a/OptimizelySDK/Optimizely.cs +++ b/OptimizelySDK/Optimizely.cs @@ -35,6 +35,7 @@ using OptimizelySDK.OptlyConfig; using OptimizelySDK.OptimizelyDecisions; using System.Linq; +using System.Text.RegularExpressions; #if USE_ODP using OptimizelySDK.Odp; @@ -346,7 +347,7 @@ public void Track(string eventKey, string userId, UserAttributes userAttributes EventTags eventTags = null ) { - if (string.IsNullOrWhiteSpace(eventKey)) + if (eventKey == null || Regex.IsMatch(eventKey, @"^\s*$")) { Logger.Log(LogLevel.ERROR, "Event key cannot be null, empty, or whitespace string. Failing 'Track'.");