// // Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSScrubbingLogFormatter.h" #import "SignalBaseTest.h" NS_ASSUME_NONNULL_BEGIN @interface OWSScrubbingLogFormatterTest : SignalBaseTest @property (nonatomic) NSDate *testDate; @end @implementation OWSScrubbingLogFormatterTest - (void)setUp { [super setUp]; self.testDate = [NSDate new]; } - (void)tearDown { [super tearDown]; } - (DDLogMessage *)messageWithString:(NSString *)string { return [[DDLogMessage alloc] initWithMessage:string level:DDLogLevelInfo flag:0 context:0 file:@"mock file name" function:@"mock function name" line:0 tag:nil options:0 timestamp:self.testDate]; } - (void)testDataScrubbed { NSDictionary *expectedOutputs = @{ @"<01234567 89a23def 23234567 89ab1234>" : @"[ REDACTED_DATA:01... ]", @"My data is: <01234567 89a23def 23234567 89ab1223>" : @"My data is: [ REDACTED_DATA:01... ]", @"My data is <12345670 89a23def 23234567 89ab1223> their data is <87654321 89ab1234>" : @"My data is [ REDACTED_DATA:12... ] their data is [ REDACTED_DATA:87... ]" }; OWSScrubbingLogFormatter *formatter = [OWSScrubbingLogFormatter new]; // Other formatters add a dynamic date prefix to log lines. We truncate that when comparing our expected output. NSUInteger datePrefixLength = [formatter formatLogMessage:[self messageWithString:@""]].length; for (NSString *input in expectedOutputs) { NSString *rawActual = [formatter formatLogMessage:[self messageWithString:input]]; // strip out dynamic date portion of log line NSString *actual = [rawActual substringWithRange:NSMakeRange(datePrefixLength, rawActual.length - datePrefixLength)]; NSString *expected = expectedOutputs[input]; XCTAssertEqualObjects(expected, actual); } } - (void)testPhoneNumbersScrubbed { NSArray *phoneStrings = @[ @"+13331231234 ", @"+4113331231234", @"+13331231234 something something +13331231234", ]; for (NSString *phoneString in phoneStrings) { OWSScrubbingLogFormatter *formatter = [OWSScrubbingLogFormatter new]; NSString *messageText = [NSString stringWithFormat:@"My phone number is %@", phoneString]; NSString *actual = [formatter formatLogMessage:[self messageWithString:messageText]]; NSRange redactedRange = [actual rangeOfString:@"My phone number is [ REDACTED_PHONE_NUMBER:xxx234 ]"]; XCTAssertNotEqual(NSNotFound, redactedRange.location, "Failed to redact phone string: %@", phoneString); NSRange phoneNumberRange = [actual rangeOfString:phoneString]; XCTAssertEqual(NSNotFound, phoneNumberRange.location, "Failed to redact phone string: %@", phoneString); } } - (void)testNonPhoneNumberNotScrubbed { OWSScrubbingLogFormatter *formatter = [OWSScrubbingLogFormatter new]; NSString *actual = [formatter formatLogMessage:[self messageWithString:[NSString stringWithFormat:@"Some unfiltered string"]]]; NSRange redactedRange = [actual rangeOfString:@"Some unfiltered string"]; XCTAssertNotEqual(NSNotFound, redactedRange.location, "Shouldn't touch non phone string."); } - (void)testIPAddressesScrubbed { id scrubbingFormatter = [OWSScrubbingLogFormatter new]; id defaultFormatter = [DDLogFileFormatterDefault new]; NSDictionary *valueMap = @{ @"0.0.0.0" : @"[ REDACTED_IPV4_ADDRESS:...0 ]", @"127.0.0.1" : @"[ REDACTED_IPV4_ADDRESS:...1 ]", @"255.255.255.255" : @"[ REDACTED_IPV4_ADDRESS:...255 ]", @"1.2.3.4" : @"[ REDACTED_IPV4_ADDRESS:...4 ]", }; NSArray *messageFormats = @[ @"a%@b", @"http://%@", @"http://%@/", @"%@ and %@ and %@", @"%@", @"%@ %@", @"no ip address!", @"", ]; for (NSString *ipAddress in valueMap) { NSString *redactedIPAddress = valueMap[ipAddress]; for (NSString *messageFormat in messageFormats) { NSString *message = [messageFormat stringByReplacingOccurrencesOfString:@"%@" withString:ipAddress]; NSString *unredactedMessage = [defaultFormatter formatLogMessage:[self messageWithString:messageFormat]]; NSString *expectedRedactedMessage = [defaultFormatter formatLogMessage:[self messageWithString:[messageFormat stringByReplacingOccurrencesOfString:@"%@" withString:redactedIPAddress]]]; NSString *redactedMessage = [scrubbingFormatter formatLogMessage:[self messageWithString:message]]; XCTAssertEqualObjects( expectedRedactedMessage, redactedMessage, @"Scrubbing failed for message: %@", unredactedMessage); NSRange ipAddressRange = [redactedMessage rangeOfString:ipAddress]; XCTAssertEqual(NSNotFound, ipAddressRange.location, "Failed to redact IP address: %@", unredactedMessage); } } } @end NS_ASSUME_NONNULL_END