Skip to content

Commit 314a201

Browse files
Alda/event tag crash (#171)
* OASIS-1606: Fixed crash with string event tags. * Fixed typo in a log string const.
1 parent c513dbe commit 314a201

File tree

4 files changed

+85
-11
lines changed

4 files changed

+85
-11
lines changed

OptimizelySDKCore/OptimizelySDKCore/OPTLYEventBuilder.m

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -121,19 +121,36 @@ - (NSDictionary *)buildEventTicket:(OPTLYProjectConfig *)config
121121

122122
// Allow only 'revenue' eventTags with integer values (max long long); otherwise the value will be cast to an integer
123123
NSMutableDictionary *mutableEventTags = [[NSMutableDictionary alloc] initWithDictionary:eventTags];
124+
124125
if ([[eventTags allKeys] containsObject:OPTLYEventMetricNameRevenue]) {
125-
if (!(strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(short)) == 0 ||
126-
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(int)) == 0 ||
127-
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(long)) == 0 ||
128-
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(long long)) == 0 ||
129-
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(unsigned short)) == 0 ||
130-
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(unsigned int)) == 0 ||
131-
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(unsigned long)) == 0 ||
132-
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(unsigned long long)) == 0)) {
133-
[config.logger logMessage:OPTLYLoggerMessagesRevenueValueInvalid withLevel:OptimizelyLogLevelWarning];
126+
127+
id revenueValue = eventTags[OPTLYEventMetricNameRevenue];
128+
129+
// if the object is an NSNumber, then char, floats, and boolean values will be cast to a long long int
130+
if ([revenueValue isKindOfClass:[NSNumber class]]) {
131+
if (!(strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(short)) == 0 ||
132+
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(int)) == 0 ||
133+
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(long)) == 0 ||
134+
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(long long)) == 0 ||
135+
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(unsigned short)) == 0 ||
136+
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(unsigned int)) == 0 ||
137+
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(unsigned long)) == 0 ||
138+
strcmp([eventTags[OPTLYEventMetricNameRevenue] objCType], @encode(unsigned long long)) == 0)) {
139+
NSNumber *revenueValue = eventTags[OPTLYEventMetricNameRevenue];
140+
long long revenueValueCast = [revenueValue longLongValue];
141+
mutableEventTags[OPTLYEventMetricNameRevenue] = [NSNumber numberWithLongLong:revenueValueCast];
142+
[config.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesReveneuValueInvalidInteger, revenueValueCast] withLevel:OptimizelyLogLevelWarning];
143+
}
144+
// cast strings to int
145+
} else if ([revenueValue isKindOfClass:[NSString class]]) {
134146
NSNumber *revenueValue = eventTags[OPTLYEventMetricNameRevenue];
135-
long long revenueValueCast = revenueValue.longLongValue;
147+
long long revenueValueCast = [revenueValue longLongValue];
148+
[config.logger logMessage:[NSString stringWithFormat:OPTLYLoggerMessagesRevenueValueString, revenueValueCast] withLevel:OptimizelyLogLevelWarning];
136149
mutableEventTags[OPTLYEventMetricNameRevenue] = [NSNumber numberWithLongLong:revenueValueCast];
150+
// all other objects can't be cast to an integer
151+
} else {
152+
[config.logger logMessage:OPTLYLoggerMessagesRevenueValueInvalid withLevel:OptimizelyLogLevelWarning];
153+
[mutableEventTags removeObjectForKey:OPTLYEventMetricNameRevenue];
137154
}
138155
}
139156

OptimizelySDKCore/OptimizelySDKCore/OPTLYLoggerMessages.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ extern NSString *const OPTLYLoggerMessagesNotBuildingDecisionEventTicket;
101101
extern NSString *const OPTLYLoggerMessagesUserIdInvalid;
102102
extern NSString *const OPTLYLoggerMessagesVariationIdInvalid;
103103
extern NSString *const OPTLYLoggerMessagesEventNotPassAudienceEvaluation;
104+
extern NSString *const OPTLYLoggerMessagesReveneuValueInvalidInteger;
105+
extern NSString *const OPTLYLoggerMessagesRevenueValueString;
104106
extern NSString *const OPTLYLoggerMessagesRevenueValueInvalid;
105107
extern NSString *const OPTLYLoggerMessagesEventTagValueInvalid;
106108

OptimizelySDKCore/OptimizelySDKCore/OPTLYLoggerMessages.m

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@
9797
NSString *const OPTLYLoggerMessagesUserIdInvalid = @"[EVENT BUILDER] User ID cannot be an empty string.";
9898
NSString *const OPTLYLoggerMessagesVariationIdInvalid = @"[EVENT BUILDER] Variation ID cannot be an empty string.";
9999
NSString *const OPTLYLoggerMessagesEventNotPassAudienceEvaluation = @"[EVENT BUILDER] None of the experiments of %@ pass audience evaluation.";
100-
NSString *const OPTLYLoggerMessagesRevenueValueInvalid = @"[EVENT BUILDER] Provided revenue value is not an integer.";
100+
NSString *const OPTLYLoggerMessagesReveneuValueInvalidInteger = @"[EVENT BUILDER] Provided revenue value is an invalid integer type and will be cast to the integer: %llu.";
101+
NSString *const OPTLYLoggerMessagesRevenueValueString = @"[EVENT BUILDER] Provided revenue value is a string and will be cast to the integer: %llu.";
102+
NSString *const OPTLYLoggerMessagesRevenueValueInvalid = @"[EVENT BUILDER] Provided revenue value is in an invalid format and will not be sent to results.";
101103
NSString *const OPTLYLoggerMessagesEventTagValueInvalid = @"[EVENT BUILDER] Provided event tag %@ is neither an integer nor a string; skipping.";
102104

103105

OptimizelySDKCore/OptimizelySDKCoreTests/OPTLYEventBuilderTest.m

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,59 @@ - (void)testBuildEventTicketWithInvalidBooleanRevenue
261261
experimentIds:@[kExperimentWithAudienceId]];
262262
}
263263

264+
- (void)testBuildEventTicketWithInvalidStringRevenue
265+
{
266+
NSString *stringRevenue = @"8.234";
267+
long long int castStringRevenue = [stringRevenue longLongValue];
268+
269+
NSDictionary *attributes = @{kAttributeKeyBrowserType : kAttributeValueFirefox};
270+
271+
NSDictionary *params = [self.eventBuilder buildEventTicket:self.config
272+
bucketer:self.bucketer
273+
userId:kUserId
274+
eventName:kEventWithAudienceName
275+
eventTags:@{ OPTLYEventMetricNameRevenue : stringRevenue,
276+
kAttributeKeyBrowserType : kAttributeValueChrome }
277+
attributes:attributes];
278+
[self checkCommonParams:params withAttributes:attributes];
279+
280+
// the revenue value should be cast to an int
281+
[self checkEventTicket:params
282+
config:self.config
283+
eventId:kEventWithAudienceId
284+
eventName:kEventWithAudienceName
285+
eventTags:@{ OPTLYEventMetricNameRevenue : [NSNumber numberWithInteger:castStringRevenue],
286+
kAttributeKeyBrowserType : kAttributeValueChrome}
287+
attributes:attributes
288+
userId:kUserId
289+
experimentIds:@[kExperimentWithAudienceId]];
290+
}
291+
292+
- (void)testBuildEventTicketWithInvalidObjectRevenue
293+
{
294+
NSDictionary *attributes = @{kAttributeKeyBrowserType : kAttributeValueFirefox};
295+
296+
NSDictionary *params = [self.eventBuilder buildEventTicket:self.config
297+
bucketer:self.bucketer
298+
userId:kUserId
299+
eventName:kEventWithAudienceName
300+
eventTags:@{ OPTLYEventMetricNameRevenue : attributes,
301+
kAttributeKeyBrowserType : kAttributeValueChrome }
302+
attributes:attributes];
303+
[self checkCommonParams:params withAttributes:attributes];
304+
305+
// no revenue value should be included
306+
[self checkEventTicket:params
307+
config:self.config
308+
eventId:kEventWithAudienceId
309+
eventName:kEventWithAudienceName
310+
eventTags:@{ kAttributeKeyBrowserType : kAttributeValueChrome }
311+
attributes:attributes
312+
userId:kUserId
313+
experimentIds:@[kExperimentWithAudienceId]];
314+
}
315+
316+
264317
- (void)testBuildEventTicketWithEventTags
265318
{
266319
NSDictionary *attributes = @{kAttributeKeyBrowserType : kAttributeValueFirefox};

0 commit comments

Comments
 (0)