Skip to content
Merged
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
97 changes: 97 additions & 0 deletions Branch-TestBed/Branch-SDK-Tests/BranchClassTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -261,5 +261,102 @@ - (void)testSetConsumerProtectionAttributionLevel {

}

- (void)testSetAnonID {
NSString *expectedAnonID = @"static-test-anon-id-12345";

[Branch setAnonID:expectedAnonID];

NSString *actualAnonID = [BNCPreferenceHelper sharedInstance].anonID;
XCTAssertEqualObjects(actualAnonID, expectedAnonID, @"setAnonID should set valid string");
}

- (void)testSetAnonID_UpdateExistingValue {
NSString *initialAnonID = @"initial-anon-id";
NSString *updatedAnonID = @"updated-anon-id";

[Branch setAnonID:initialAnonID];
XCTAssertEqualObjects([BNCPreferenceHelper sharedInstance].anonID, initialAnonID);

[Branch setAnonID:updatedAnonID];
XCTAssertEqualObjects([BNCPreferenceHelper sharedInstance].anonID, updatedAnonID);
}

- (void)testSetAnonID_NilValue {
NSString *initialAnonID = @"initial-anon-id";

[Branch setAnonID:initialAnonID];
XCTAssertEqualObjects([BNCPreferenceHelper sharedInstance].anonID, initialAnonID);

[Branch setAnonID:nil];
XCTAssertEqualObjects([BNCPreferenceHelper sharedInstance].anonID, initialAnonID);
}

- (void)testSetAnonID_EmptyString {
NSString *emptyAnonID = @"";

[Branch setAnonID:emptyAnonID];

NSString *actualAnonID = [BNCPreferenceHelper sharedInstance].anonID;
XCTAssertEqualObjects(actualAnonID, emptyAnonID, @"Static setAnonID should accept empty string");
}

- (void)testSetAnonID_NonStringObject {
NSString *initialAnonID = @"initial-anon-id";

[Branch setAnonID:initialAnonID];
XCTAssertEqualObjects([BNCPreferenceHelper sharedInstance].anonID, initialAnonID);

// Try to set with a non-string object (NSNumber)
NSNumber *nonStringValue = @123;
[Branch setAnonID:(NSString *)nonStringValue];
Comment on lines +309 to +311
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Bug Fix

Issue: Unsafe type casting of NSNumber to NSString will cause runtime crash when the method tries to validate the parameter type
Fix: Remove the explicit cast to let the method handle type validation naturally
Impact: Prevents potential crash and allows proper testing of type validation logic

Suggested change
// Try to set with a non-string object (NSNumber)
NSNumber *nonStringValue = @123;
[Branch setAnonID:(NSString *)nonStringValue];
// Try to set with a non-string object (NSNumber)
NSNumber *nonStringValue = @123;
[Branch setAnonID:nonStringValue];


XCTAssertEqualObjects([BNCPreferenceHelper sharedInstance].anonID, initialAnonID);
}

- (void)testSetAnonID_LongString {
NSString *longAnonID = @"very-long-anon-id-with-many-characters-to-test-string-handling-1234567890-abcdefghijklmnopqrstuvwxyz";

[Branch setAnonID:longAnonID];

NSString *actualAnonID = [BNCPreferenceHelper sharedInstance].anonID;
XCTAssertEqualObjects(actualAnonID, longAnonID, @"setAnonID should handle long strings");
}

- (void)testSetAnonID_SpecialCharacters {
NSString *specialCharAnonID = @"static-anon-id-with-special-chars-!@#$%^&*()_+-=[]{}|;:,.<>?";

[Branch setAnonID:specialCharAnonID];

NSString *actualAnonID = [BNCPreferenceHelper sharedInstance].anonID;
XCTAssertEqualObjects(actualAnonID, specialCharAnonID, @"setAnonID should handle special characters");
}

- (void)testSetAnonID_ThreadSafety {
NSString *anonID1 = @"thread-test-anon-id-1";
NSString *anonID2 = @"thread-test-anon-id-2";

// Test that the method is thread-safe by calling it from different queues
dispatch_group_t group = dispatch_group_create();

dispatch_group_enter(group);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[Branch setAnonID:anonID1];
dispatch_group_leave(group);
});

dispatch_group_enter(group);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[Branch setAnonID:anonID2];
dispatch_group_leave(group);
});

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

// Verify that one of the values was set (we can't predict which due to concurrency)
NSString *finalAnonID = [BNCPreferenceHelper sharedInstance].anonID;
XCTAssertTrue([finalAnonID isEqualToString:anonID1] || [finalAnonID isEqualToString:anonID2],
@"One of the anonID values should be set");
}


@end
10 changes: 10 additions & 0 deletions Sources/BranchSDK/Branch.m
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,16 @@ + (void)setODMInfo:(NSString *)odmInfo andFirstOpenTimestamp:(NSDate *) firstOpe

}

+ (void)setAnonID:(NSString *)anonID {
@synchronized (self) {
if (anonID && [anonID isKindOfClass:[NSString class]]) {
[BNCPreferenceHelper sharedInstance].anonID = anonID;
} else {
[[BranchLogger shared] logWarning:@"Invalid anonID provided. Must be a non-nil NSString." error:nil];
}
}
}

- (void)setConsumerProtectionAttributionLevel:(BranchAttributionLevel)level {
self.preferenceHelper.attributionLevel = level;

Expand Down
6 changes: 6 additions & 0 deletions Sources/BranchSDK/Public/Branch.h
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,12 @@ Sets a custom base safetrack URL for non-linking calls to the Branch API.

+ (void)setODMInfo:(NSString *)odmInfo andFirstOpenTimestamp:(NSDate *) firstOpenTimestamp;

/**
Sets a custom Meta Anon ID for the current user.
@param anonID The custom Meta Anon ID to be used by Branch.
*/
+ (void)setAnonID:(NSString *)anonID;

/**
* Enumeration representing different levels of consumer protection attribution levels
*/
Expand Down
Loading