From 3be85638988773ca9a8ec8617388e07c718a1aac Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Mon, 17 Dec 2018 16:35:39 -0700 Subject: [PATCH 1/7] fixup broken tests --- Signal/src/util/Backup/OWSBackupLazyRestore.swift | 3 +++ Signal/test/Models/AccountManagerTest.swift | 4 ++++ Signal/test/util/SearcherTest.swift | 7 ++++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Signal/src/util/Backup/OWSBackupLazyRestore.swift b/Signal/src/util/Backup/OWSBackupLazyRestore.swift index 76f7c2139..4b19442d6 100644 --- a/Signal/src/util/Backup/OWSBackupLazyRestore.swift +++ b/Signal/src/util/Backup/OWSBackupLazyRestore.swift @@ -77,6 +77,9 @@ public class BackupLazyRestore: NSObject { public func runIfNecessary() { AssertIsOnMainThread() + guard !CurrentAppContext().isRunningTests else { + return + } guard AppReadiness.isAppReady() else { return } diff --git a/Signal/test/Models/AccountManagerTest.swift b/Signal/test/Models/AccountManagerTest.swift index 0f22ad67d..89505fd17 100644 --- a/Signal/test/Models/AccountManagerTest.swift +++ b/Signal/test/Models/AccountManagerTest.swift @@ -47,6 +47,10 @@ class VerifyingTSAccountManager: FailingTSAccountManager { success: @escaping () -> Void, failure: @escaping (Error) -> Void) { success() } + + override func performUpdateAccountAttributes() -> AnyPromise { + return AnyPromise(Promise.value(())) + } } class TokenObtainingTSAccountManager: VerifyingTSAccountManager { diff --git a/Signal/test/util/SearcherTest.swift b/Signal/test/util/SearcherTest.swift index fcfc405aa..def8866cb 100644 --- a/Signal/test/util/SearcherTest.swift +++ b/Signal/test/util/SearcherTest.swift @@ -294,7 +294,10 @@ class ConversationSearcherTest: SignalBaseTest { XCTAssertEqual(["My fax is: 222-333-4444"], bodies(forMessageResults: resultSet.messages)) } - func bodies(forMessageResults messageResults: [ConversationSearchResult]) -> [String] { + + // MARK: Helpers + + func bodies(forMessageResults messageResults: [ConversationSearchResult]) -> [String] { var result = [String]() self.dbConnection.read { transaction in @@ -322,8 +325,6 @@ class ConversationSearcherTest: SignalBaseTest { return result.sorted() } - // MARK: Helpers - private func searchConversations(searchText: String) -> [ThreadViewModel] { let results = getResultSet(searchText: searchText) return results.conversations.map { $0.thread } From 40470ec4249e900b7ef33cc71e0f9265f9287d4b Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Mon, 17 Dec 2018 16:47:52 -0700 Subject: [PATCH 2/7] fixup test fixes --- Signal/test/util/SearcherTest.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Signal/test/util/SearcherTest.swift b/Signal/test/util/SearcherTest.swift index def8866cb..9061c1490 100644 --- a/Signal/test/util/SearcherTest.swift +++ b/Signal/test/util/SearcherTest.swift @@ -294,7 +294,6 @@ class ConversationSearcherTest: SignalBaseTest { XCTAssertEqual(["My fax is: 222-333-4444"], bodies(forMessageResults: resultSet.messages)) } - // MARK: Helpers func bodies(forMessageResults messageResults: [ConversationSearchResult]) -> [String] { From ca5b3c8ec9b6fd1e6a39c6901fefa5b53792994c Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Mon, 17 Dec 2018 16:48:15 -0700 Subject: [PATCH 3/7] make factory methods public --- .../src/TestUtils/Factories.swift | 130 +++++++++--------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/SignalServiceKit/src/TestUtils/Factories.swift b/SignalServiceKit/src/TestUtils/Factories.swift index c963360f1..34bb2cd19 100644 --- a/SignalServiceKit/src/TestUtils/Factories.swift +++ b/SignalServiceKit/src/TestUtils/Factories.swift @@ -7,7 +7,7 @@ import Foundation /// Factories for creating some default TSYapDatabaseObjects. /// /// To customize properties applied by the factory (e.g. `someProperty`) -/// the factory needs a `var somePropertyBuilder: () -> (SomePropertyType)` +/// the factory needs a `public var somePropertyBuilder: () -> (SomePropertyType)` /// which is then used in the `create` method. /// /// Examples: @@ -29,7 +29,7 @@ import Foundation /// messageFactory.threadCreator = { _ in return existingThread } /// messageFactory.create(count: 100) /// -protocol Factory { +public protocol Factory { associatedtype ObjectType: TSYapDatabaseObject var dbConnection: YapDatabaseConnection { get } @@ -44,27 +44,27 @@ protocol Factory { func create(count: UInt, transaction: YapDatabaseReadWriteTransaction) -> [ObjectType] } -extension Factory { +public extension Factory { - static var dbConnection: YapDatabaseConnection { + static public var dbConnection: YapDatabaseConnection { return OWSPrimaryStorage.shared().dbReadWriteConnection } - var dbConnection: YapDatabaseConnection { + public var dbConnection: YapDatabaseConnection { return OWSPrimaryStorage.shared().dbReadWriteConnection } - static func readWrite(block: @escaping (YapDatabaseReadWriteTransaction) -> Void) { + static public func readWrite(block: @escaping (YapDatabaseReadWriteTransaction) -> Void) { dbConnection.readWrite(block) } - func readWrite(block: @escaping (YapDatabaseReadWriteTransaction) -> Void) { + public func readWrite(block: @escaping (YapDatabaseReadWriteTransaction) -> Void) { dbConnection.readWrite(block) } // MARK: Factory Methods - func create() -> ObjectType { + public func create() -> ObjectType { var item: ObjectType! self.readWrite { transaction in item = self.create(transaction: transaction) @@ -72,7 +72,7 @@ extension Factory { return item } - func create(count: UInt) -> [ObjectType] { + public func create(count: UInt) -> [ObjectType] { var items: [ObjectType] = [] self.readWrite { transaction in items = self.create(count: count, transaction: transaction) @@ -80,20 +80,20 @@ extension Factory { return items } - func create(count: UInt, transaction: YapDatabaseReadWriteTransaction) -> [ObjectType] { + public func create(count: UInt, transaction: YapDatabaseReadWriteTransaction) -> [ObjectType] { return (0.. TSContactThread { + public func create(transaction: YapDatabaseReadWriteTransaction) -> TSContactThread { let threadId = generateContactThreadId() let thread = TSContactThread.getOrCreateThread(withContactId: threadId, transaction: transaction) @@ -116,18 +116,18 @@ class ContactThreadFactory: NSObject, Factory { // MARK: Generators - func generateContactThreadId() -> String { + public func generateContactThreadId() -> String { return CommonGenerator.contactId } } @objc -class OutgoingMessageFactory: NSObject, Factory { +public class OutgoingMessageFactory: NSObject, Factory { // MARK: Factory @objc - func build(transaction: YapDatabaseReadWriteTransaction) -> TSOutgoingMessage { + public func build(transaction: YapDatabaseReadWriteTransaction) -> TSOutgoingMessage { let item = TSOutgoingMessage(outgoingMessageWithTimestamp: timestampBuilder(), in: threadCreator(transaction), messageBody: messageBodyBuilder(), @@ -143,7 +143,7 @@ class OutgoingMessageFactory: NSObject, Factory { } @objc - func create(transaction: YapDatabaseReadWriteTransaction) -> TSOutgoingMessage { + public func create(transaction: YapDatabaseReadWriteTransaction) -> TSOutgoingMessage { let item = self.build(transaction: transaction) item.save(with: transaction) @@ -153,19 +153,19 @@ class OutgoingMessageFactory: NSObject, Factory { // MARK: Dependent Factories @objc - var threadCreator: (YapDatabaseReadWriteTransaction) -> TSThread = { transaction in + public var threadCreator: (YapDatabaseReadWriteTransaction) -> TSThread = { transaction in ContactThreadFactory().create(transaction: transaction) } // MARK: Generators @objc - var timestampBuilder: () -> UInt64 = { + public var timestampBuilder: () -> UInt64 = { return NSDate.ows_millisecondTimeStamp() } @objc - var messageBodyBuilder: () -> String = { + public var messageBodyBuilder: () -> String = { return CommonGenerator.paragraph } @@ -175,39 +175,39 @@ class OutgoingMessageFactory: NSObject, Factory { } @objc - var expiresInSecondsBuilder: () -> UInt32 = { + public var expiresInSecondsBuilder: () -> UInt32 = { return 0 } @objc - var expireStartedAtBuilder: () -> UInt64 = { + public var expireStartedAtBuilder: () -> UInt64 = { return 0 } @objc - var isVoiceMessageBuilder: () -> Bool = { + public var isVoiceMessageBuilder: () -> Bool = { return false } @objc - var groupMetaMessageBuilder: () -> TSGroupMetaMessage = { + public var groupMetaMessageBuilder: () -> TSGroupMetaMessage = { return .unspecified } @objc - var quotedMessageBuilder: () -> TSQuotedMessage? = { + public var quotedMessageBuilder: () -> TSQuotedMessage? = { return nil } @objc - var contactShareBuilder: () -> OWSContact? = { + public var contactShareBuilder: () -> OWSContact? = { return nil } // MARK: Delivery Receipts @objc - func buildDeliveryReceipt() -> OWSReceiptsForSenderMessage { + public func buildDeliveryReceipt() -> OWSReceiptsForSenderMessage { var item: OWSReceiptsForSenderMessage! self.readWrite { transaction in item = self.buildDeliveryReceipt(transaction: transaction) @@ -216,14 +216,14 @@ class OutgoingMessageFactory: NSObject, Factory { } @objc - func buildDeliveryReceipt(transaction: YapDatabaseReadWriteTransaction) -> OWSReceiptsForSenderMessage { + public func buildDeliveryReceipt(transaction: YapDatabaseReadWriteTransaction) -> OWSReceiptsForSenderMessage { let item = OWSReceiptsForSenderMessage.deliveryReceiptsForSenderMessage(with: threadCreator(transaction), messageTimestamps: messageTimestampsBuilder()) return item } @objc - var messageTimestampsBuilder: () -> [NSNumber] = { + public var messageTimestampsBuilder: () -> [NSNumber] = { return [1] } } @@ -234,7 +234,7 @@ class IncomingMessageFactory: NSObject, Factory { // MARK: Factory @objc - func create(transaction: YapDatabaseReadWriteTransaction) -> TSIncomingMessage { + public func create(transaction: YapDatabaseReadWriteTransaction) -> TSIncomingMessage { let item = TSIncomingMessage(incomingMessageWithTimestamp: timestampBuilder(), in: threadCreator(transaction), authorId: authorIdBuilder(), @@ -255,59 +255,59 @@ class IncomingMessageFactory: NSObject, Factory { // MARK: Dependent Factories @objc - var threadCreator: (YapDatabaseReadWriteTransaction) -> TSThread = { transaction in + public var threadCreator: (YapDatabaseReadWriteTransaction) -> TSThread = { transaction in ContactThreadFactory().create(transaction: transaction) } // MARK: Generators @objc - var timestampBuilder: () -> UInt64 = { + public var timestampBuilder: () -> UInt64 = { return NSDate.ows_millisecondTimeStamp() } @objc - var messageBodyBuilder: () -> String = { + public var messageBodyBuilder: () -> String = { return CommonGenerator.paragraph } @objc - var authorIdBuilder: () -> String = { + public var authorIdBuilder: () -> String = { return CommonGenerator.contactId } @objc - var sourceDeviceIdBuilder: () -> UInt32 = { + public var sourceDeviceIdBuilder: () -> UInt32 = { return 1 } @objc - var attachmentIdsBuilder: () -> [String] = { + public var attachmentIdsBuilder: () -> [String] = { return [] } @objc - var expiresInSecondsBuilder: () -> UInt32 = { + public var expiresInSecondsBuilder: () -> UInt32 = { return 0 } @objc - var quotedMessageBuilder: () -> TSQuotedMessage? = { + public var quotedMessageBuilder: () -> TSQuotedMessage? = { return nil } @objc - var contactShareBuilder: () -> OWSContact? = { + public var contactShareBuilder: () -> OWSContact? = { return nil } @objc - var serverTimestampBuilder: () -> NSNumber? = { + public var serverTimestampBuilder: () -> NSNumber? = { return nil } @objc - var wasReceivedByUDBuilder: () -> Bool = { + public var wasReceivedByUDBuilder: () -> Bool = { return false } } @@ -316,10 +316,10 @@ class IncomingMessageFactory: NSObject, Factory { class GroupThreadFactory: NSObject, Factory { @objc - var messageCount: UInt = 0 + public var messageCount: UInt = 0 @objc - func create(transaction: YapDatabaseReadWriteTransaction) -> TSGroupThread { + public func create(transaction: YapDatabaseReadWriteTransaction) -> TSGroupThread { let thread = TSGroupThread.getOrCreateThread(with: groupModelBuilder(self), transaction: transaction) thread.save(with: transaction) @@ -345,7 +345,7 @@ class GroupThreadFactory: NSObject, Factory { // MARK: Generators @objc - var groupModelBuilder: (GroupThreadFactory) -> TSGroupModel = { groupThreadFactory in + public var groupModelBuilder: (GroupThreadFactory) -> TSGroupModel = { groupThreadFactory in return TSGroupModel(title: groupThreadFactory.titleBuilder(), memberIds: groupThreadFactory.memberIdsBuilder(), image: groupThreadFactory.imageBuilder(), @@ -353,22 +353,22 @@ class GroupThreadFactory: NSObject, Factory { } @objc - var titleBuilder: () -> String? = { + public var titleBuilder: () -> String? = { return CommonGenerator.words(count: 3) } @objc - var groupIdBuilder: () -> Data = { + public var groupIdBuilder: () -> Data = { return Randomness.generateRandomBytes(Int32(kGroupIdLength))! } @objc - var imageBuilder: () -> UIImage? = { + public var imageBuilder: () -> UIImage? = { return nil } @objc - var memberIdsBuilder: () -> [RecipientIdentifier] = { + public var memberIdsBuilder: () -> [RecipientIdentifier] = { let groupSize = arc4random_uniform(10) return (0.. TSAttachmentStream { + class public func create(contentType: String, dataSource: DataSource) -> TSAttachmentStream { var item: TSAttachmentStream! readWrite { transaction in item = create(contentType: contentType, dataSource: dataSource, transaction: transaction) @@ -387,7 +387,7 @@ class AttachmentStreamFactory: NSObject, Factory { } @objc - class func create(contentType: String, dataSource: DataSource, transaction: YapDatabaseReadWriteTransaction) -> TSAttachmentStream { + class public func create(contentType: String, dataSource: DataSource, transaction: YapDatabaseReadWriteTransaction) -> TSAttachmentStream { let factory = AttachmentStreamFactory() factory.contentTypeBuilder = { return contentType } factory.byteCountBuilder = { return UInt32(dataSource.dataLength()) } @@ -403,7 +403,7 @@ class AttachmentStreamFactory: NSObject, Factory { // MARK: Factory @objc - func create(transaction: YapDatabaseReadWriteTransaction) -> TSAttachmentStream { + public func create(transaction: YapDatabaseReadWriteTransaction) -> TSAttachmentStream { let attachmentStream = build(transaction: transaction) attachmentStream.save(with: transaction) @@ -411,12 +411,12 @@ class AttachmentStreamFactory: NSObject, Factory { } @objc - func build(transaction: YapDatabaseReadTransaction) -> TSAttachmentStream { + public func build(transaction: YapDatabaseReadTransaction) -> TSAttachmentStream { return build() } @objc - func build() -> TSAttachmentStream { + public func build() -> TSAttachmentStream { let attachmentStream = TSAttachmentStream(contentType: contentTypeBuilder(), byteCount: byteCountBuilder(), sourceFilename: sourceFilenameBuilder(), @@ -429,33 +429,33 @@ class AttachmentStreamFactory: NSObject, Factory { // MARK: Properties @objc - var contentTypeBuilder: () -> String = { + public var contentTypeBuilder: () -> String = { return OWSMimeTypeApplicationOctetStream } @objc - var byteCountBuilder: () -> UInt32 = { + public var byteCountBuilder: () -> UInt32 = { return 0 } @objc - var sourceFilenameBuilder: () -> String? = { + public var sourceFilenameBuilder: () -> String? = { return "fake_file.dat" } @objc - var captionBuilder: () -> String? = { + public var captionBuilder: () -> String? = { return nil } @objc - var albumMessageIdBuilder: () -> String? = { + public var albumMessageIdBuilder: () -> String? = { return nil } } extension Array { - func ows_randomElement() -> Element? { + public func ows_randomElement() -> Element? { guard self.count > 0 else { return nil } @@ -466,7 +466,7 @@ extension Array { struct CommonGenerator { - static var contactId: String { + static public var contactId: String { let digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] let randomDigits = (0..<10).map { _ in return digits.ows_randomElement()! } @@ -499,11 +499,11 @@ struct CommonGenerator { "At one time in the world there were woods that no one owned." ] - static var word: String { + static public var word: String { return String(sentence.split(separator: " ").first!) } - static func words(count: Int) -> String { + static public func words(count: Int) -> String { var result: [String] = [] while result.count < count { @@ -514,20 +514,20 @@ struct CommonGenerator { return result.joined(separator: " ") } - static var sentence: String { + static public var sentence: String { return sentences.ows_randomElement()! } - static func sentences(count: UInt) -> [String] { + static public func sentences(count: UInt) -> [String] { return (0.. String { + static public func paragraph(sentenceCount: UInt) -> String { return sentences(count: sentenceCount).joined(separator: " ") } } From a0770c14c5bd072f1ca5e27adc76448b9c7042a7 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Mon, 17 Dec 2018 16:48:32 -0700 Subject: [PATCH 4/7] baseline perf test for migration --- Signal.xcodeproj/project.pbxproj | 4 ++ ...F29A0D38-3F89-44CA-8BDC-C99EE6C1AB81.plist | 22 +++++++ ...F934A594-2E7D-49A5-9B1B-63A05DABCE3C.plist | 22 +++++++ .../Info.plist | 62 +++++++++++++++++++ Signal/test/Models/MantlePerfTest.swift | 42 +++++++++++++ .../migrations/OWS110SortIdMigration.swift | 2 +- 6 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 Signal.xcodeproj/xcshareddata/xcbaselines/D221A0A9169C9E5F00537ABF.xcbaseline/F29A0D38-3F89-44CA-8BDC-C99EE6C1AB81.plist create mode 100644 Signal.xcodeproj/xcshareddata/xcbaselines/D221A0A9169C9E5F00537ABF.xcbaseline/F934A594-2E7D-49A5-9B1B-63A05DABCE3C.plist create mode 100644 Signal/test/Models/MantlePerfTest.swift diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 0375a76c9..5c42ef763 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -443,6 +443,7 @@ 45FBC5C81DF8575700E9B410 /* CallKitCallManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45FBC59A1DF8575700E9B410 /* CallKitCallManager.swift */; }; 45FBC5D11DF8592E00E9B410 /* SignalCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45FBC5D01DF8592E00E9B410 /* SignalCall.swift */; }; 4AC4EA13C8A444455DAB351F /* Pods_SignalMessaging.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 264242150E87D10A357DB07B /* Pods_SignalMessaging.framework */; }; + 4C04F58421C860C50090D0BB /* MantlePerfTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C04F58321C860C50090D0BB /* MantlePerfTest.swift */; }; 4C090A1B210FD9C7001FD7F9 /* HapticFeedback.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C090A1A210FD9C7001FD7F9 /* HapticFeedback.swift */; }; 4C11AA5020FD59C700351FBD /* MessageStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C11AA4F20FD59C700351FBD /* MessageStatusView.swift */; }; 4C13C9F620E57BA30089A98B /* ColorPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C13C9F520E57BA30089A98B /* ColorPickerViewController.swift */; }; @@ -1159,6 +1160,7 @@ 45F659811E1BE77000444429 /* NonCallKitCallUIAdaptee.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NonCallKitCallUIAdaptee.swift; sourceTree = ""; }; 45FBC59A1DF8575700E9B410 /* CallKitCallManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallKitCallManager.swift; sourceTree = ""; }; 45FBC5D01DF8592E00E9B410 /* SignalCall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalCall.swift; sourceTree = ""; }; + 4C04F58321C860C50090D0BB /* MantlePerfTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MantlePerfTest.swift; path = Models/MantlePerfTest.swift; sourceTree = ""; }; 4C090A1A210FD9C7001FD7F9 /* HapticFeedback.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = HapticFeedback.swift; path = UserInterface/HapticFeedback.swift; sourceTree = ""; }; 4C11AA4F20FD59C700351FBD /* MessageStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageStatusView.swift; sourceTree = ""; }; 4C13C9F520E57BA30089A98B /* ColorPickerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerViewController.swift; sourceTree = ""; }; @@ -2192,6 +2194,7 @@ 458E38381D6699110094BD24 /* Models */ = { isa = PBXGroup; children = ( + 4C04F58321C860C50090D0BB /* MantlePerfTest.swift */, 4C4BC6C22102D697004040C9 /* ContactDiscoveryOperationTest.swift */, 458E38391D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m */, 458967101DC117CC00E9DD21 /* AccountManagerTest.swift */, @@ -3626,6 +3629,7 @@ 458E383A1D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m in Sources */, 3421981C21061D2E00C57195 /* ByteParserTest.swift in Sources */, 34843B26214327C9004DED45 /* OWSOrphanDataCleanerTest.m in Sources */, + 4C04F58421C860C50090D0BB /* MantlePerfTest.swift in Sources */, 45360B901F9527DA00FA666C /* SearcherTest.swift in Sources */, 34DB0BED2011548B007B313F /* OWSDatabaseConverterTest.m in Sources */, 34843B2C214FE296004DED45 /* MockEnvironment.m in Sources */, diff --git a/Signal.xcodeproj/xcshareddata/xcbaselines/D221A0A9169C9E5F00537ABF.xcbaseline/F29A0D38-3F89-44CA-8BDC-C99EE6C1AB81.plist b/Signal.xcodeproj/xcshareddata/xcbaselines/D221A0A9169C9E5F00537ABF.xcbaseline/F29A0D38-3F89-44CA-8BDC-C99EE6C1AB81.plist new file mode 100644 index 000000000..1da1ffd17 --- /dev/null +++ b/Signal.xcodeproj/xcshareddata/xcbaselines/D221A0A9169C9E5F00537ABF.xcbaseline/F29A0D38-3F89-44CA-8BDC-C99EE6C1AB81.plist @@ -0,0 +1,22 @@ + + + + + classNames + + MantlePerfTest + + testPerformanceExample() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 3.19 + baselineIntegrationDisplayName + Local Baseline + + + + + + diff --git a/Signal.xcodeproj/xcshareddata/xcbaselines/D221A0A9169C9E5F00537ABF.xcbaseline/F934A594-2E7D-49A5-9B1B-63A05DABCE3C.plist b/Signal.xcodeproj/xcshareddata/xcbaselines/D221A0A9169C9E5F00537ABF.xcbaseline/F934A594-2E7D-49A5-9B1B-63A05DABCE3C.plist new file mode 100644 index 000000000..87aa99390 --- /dev/null +++ b/Signal.xcodeproj/xcshareddata/xcbaselines/D221A0A9169C9E5F00537ABF.xcbaseline/F934A594-2E7D-49A5-9B1B-63A05DABCE3C.plist @@ -0,0 +1,22 @@ + + + + + classNames + + MantlePerfTest + + testPerformanceExample() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.62862 + baselineIntegrationDisplayName + Local Baseline + + + + + + diff --git a/Signal.xcodeproj/xcshareddata/xcbaselines/D221A0A9169C9E5F00537ABF.xcbaseline/Info.plist b/Signal.xcodeproj/xcshareddata/xcbaselines/D221A0A9169C9E5F00537ABF.xcbaseline/Info.plist index 78d6282c7..757f83b99 100644 --- a/Signal.xcodeproj/xcshareddata/xcbaselines/D221A0A9169C9E5F00537ABF.xcbaseline/Info.plist +++ b/Signal.xcodeproj/xcshareddata/xcbaselines/D221A0A9169C9E5F00537ABF.xcbaseline/Info.plist @@ -35,6 +35,68 @@ com.apple.platform.iphonesimulator + F29A0D38-3F89-44CA-8BDC-C99EE6C1AB81 + + localComputer + + busSpeedInMHz + 100 + cpuCount + 1 + cpuKind + Intel Core i7 + cpuSpeedInMHz + 2900 + logicalCPUCoresPerPackage + 8 + modelCode + MacBookPro14,3 + physicalCPUCoresPerPackage + 4 + platformIdentifier + com.apple.platform.macosx + + targetArchitecture + x86_64 + targetDevice + + modelCode + iPhone10,6 + platformIdentifier + com.apple.platform.iphonesimulator + + + F934A594-2E7D-49A5-9B1B-63A05DABCE3C + + localComputer + + busSpeedInMHz + 100 + cpuCount + 1 + cpuKind + Intel Core i7 + cpuSpeedInMHz + 2900 + logicalCPUCoresPerPackage + 8 + modelCode + MacBookPro14,3 + physicalCPUCoresPerPackage + 4 + platformIdentifier + com.apple.platform.macosx + + targetArchitecture + x86_64 + targetDevice + + modelCode + iPhone7,2 + platformIdentifier + com.apple.platform.iphonesimulator + + diff --git a/Signal/test/Models/MantlePerfTest.swift b/Signal/test/Models/MantlePerfTest.swift new file mode 100644 index 000000000..d0e6eadaa --- /dev/null +++ b/Signal/test/Models/MantlePerfTest.swift @@ -0,0 +1,42 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +import XCTest +@testable import SignalMessaging +@testable import SignalServiceKit + +class MantlePerfTest: SignalBaseTest { + + var primaryStorage: OWSPrimaryStorage { + return SSKEnvironment.shared.primaryStorage + } + + override func setUp() { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testPerformanceExample() { + let migration = OWS110SortIdMigration() + + self.measureMetrics(XCTestCase.defaultPerformanceMetrics, automaticallyStartMeasuring: false) { + _ = OutgoingMessageFactory().create(count: 100) + + startMeasuring() + + let migrationCompleted = expectation(description: "migrationCompleted") + migration.runUp(completion: migrationCompleted.fulfill) + + self.wait(for: [migrationCompleted], timeout: 10) + + stopMeasuring() + + TSInteraction.removeAllObjectsInCollection() + } + } + +} diff --git a/SignalMessaging/environment/migrations/OWS110SortIdMigration.swift b/SignalMessaging/environment/migrations/OWS110SortIdMigration.swift index af4c2cddb..babcf9951 100644 --- a/SignalMessaging/environment/migrations/OWS110SortIdMigration.swift +++ b/SignalMessaging/environment/migrations/OWS110SortIdMigration.swift @@ -4,7 +4,7 @@ import Foundation -class OWS110SortIdMigration: OWSDatabaseMigration { +public class OWS110SortIdMigration: OWSDatabaseMigration { // increment a similar constant for each migration. @objc class func migrationId() -> String { From 0cb702b37ff22b4d800c4f65eb91d0c2a9dac44f Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Tue, 18 Dec 2018 14:54:53 -0700 Subject: [PATCH 5/7] [PERF] save 2% on large migrations --- .../Contacts/OWSDisappearingMessagesConfiguration.m | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/SignalServiceKit/src/Contacts/OWSDisappearingMessagesConfiguration.m b/SignalServiceKit/src/Contacts/OWSDisappearingMessagesConfiguration.m index c03b26b80..2f22c3f07 100644 --- a/SignalServiceKit/src/Contacts/OWSDisappearingMessagesConfiguration.m +++ b/SignalServiceKit/src/Contacts/OWSDisappearingMessagesConfiguration.m @@ -81,10 +81,14 @@ NS_ASSUME_NONNULL_BEGIN + (uint32_t)maxDurationSeconds { - uint32_t max = [[self.validDurationsSeconds valueForKeyPath:@"@max.intValue"] unsignedIntValue]; - - // It's safe to update this assert if we add a larger duration - OWSAssertDebug(max == 1 * kWeekInterval); + static uint32_t max; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + max = [[self.validDurationsSeconds valueForKeyPath:@"@max.intValue"] unsignedIntValue]; + + // It's safe to update this assert if we add a larger duration + OWSAssertDebug(max == 1 * kWeekInterval); + }); return max; } From 7bc535739751bd65ab6401441d77fe3a6d12ca95 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Tue, 18 Dec 2018 17:35:07 -0700 Subject: [PATCH 6/7] [PERF] optimize search normalization saves 2.5% on large migration --- .../src/Storage/FullTextSearchFinder.swift | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/SignalServiceKit/src/Storage/FullTextSearchFinder.swift b/SignalServiceKit/src/Storage/FullTextSearchFinder.swift index 10d0fa9a3..71b9e52cf 100644 --- a/SignalServiceKit/src/Storage/FullTextSearchFinder.swift +++ b/SignalServiceKit/src/Storage/FullTextSearchFinder.swift @@ -129,26 +129,20 @@ public class FullTextSearchFinder: NSObject { return charactersToFilter }() + // This is a hot method, especially while running large migrations. + // Changes to it should go through a profiler to make sure large migrations + // aren't adversely affected. public class func normalize(text: String) -> String { // 1. Filter out invalid characters. - let filtered = text.unicodeScalars.lazy.filter({ - !charactersToRemove.contains($0) - }) + let filtered = text.removeCharacters(characterSet: charactersToRemove) // 2. Simplify whitespace. - let simplifyingFunction: (UnicodeScalar) -> UnicodeScalar = { - if CharacterSet.whitespacesAndNewlines.contains($0) { - return UnicodeScalar(" ") - } else { - return $0 - } - } - let simplified = filtered.map(simplifyingFunction) + let simplified = filtered.replaceCharacters(characterSet: .whitespacesAndNewlines, + replacement: " ") // 3. Strip leading & trailing whitespace last, since we may replace // filtered characters with whitespace. - let result = String(String.UnicodeScalarView(simplified)) - return result.trimmingCharacters(in: .whitespacesAndNewlines) + return simplified.trimmingCharacters(in: .whitespacesAndNewlines) } // MARK: - Index Building @@ -248,9 +242,7 @@ public class FullTextSearchFinder: NSObject { let contentColumnName = "content" let handler = YapDatabaseFullTextSearchHandler.withObjectBlock { (transaction: YapDatabaseReadTransaction, dict: NSMutableDictionary, _: String, _: String, object: Any) in - if let content: String = indexContent(object: object, transaction: transaction) { - dict[contentColumnName] = content - } + dict[contentColumnName] = indexContent(object: object, transaction: transaction) } // update search index on contact name changes? @@ -262,3 +254,15 @@ public class FullTextSearchFinder: NSObject { versionTag: "1") } } + +extension String { + func replaceCharacters(characterSet: CharacterSet, replacement: String) -> String { + let components = self.components(separatedBy: characterSet) + return components.joined(separator: replacement) + } + + func removeCharacters(characterSet: CharacterSet) -> String { + let components = self.components(separatedBy: characterSet) + return components.joined() + } +} From d8fda8a7aabbf0d001d386e8392154c2d9a08c46 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 19 Dec 2018 15:31:19 -0700 Subject: [PATCH 7/7] Update pods with perf improvements --- Podfile | 45 +++++++++++++++++++++++++++++++++++++-------- Podfile.lock | 13 +++++++++---- Pods | 2 +- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/Podfile b/Podfile index 666a2f5dc..c1da5a370 100644 --- a/Podfile +++ b/Podfile @@ -4,33 +4,62 @@ source 'https://github.com/CocoaPods/Specs.git' use_frameworks! def shared_pods + + ### # OWS Pods + ### + pod 'SignalCoreKit', git: 'https://github.com/signalapp/SignalCoreKit.git', testspecs: ["Tests"] # pod 'SignalCoreKit', path: '../SignalCoreKit', testspecs: ["Tests"] - # pod 'SQLCipher', path: '../sqlcipher' - pod 'SQLCipher', :git => 'https://github.com/sqlcipher/sqlcipher.git', :commit => 'd5c2bec' - # pod 'YapDatabase/SQLCipher', path: '../YapDatabase' - pod 'YapDatabase/SQLCipher', :git => 'https://github.com/signalapp/YapDatabase.git', branch: 'signal-release' + pod 'AxolotlKit', git: 'https://github.com/signalapp/SignalProtocolKit.git', branch: 'master', testspecs: ["Tests"] # pod 'AxolotlKit', path: '../SignalProtocolKit', testspecs: ["Tests"] + pod 'HKDFKit', git: 'https://github.com/signalapp/HKDFKit.git', testspecs: ["Tests"] # pod 'HKDFKit', path: '../HKDFKit', testspecs: ["Tests"] + pod 'Curve25519Kit', git: 'https://github.com/signalapp/Curve25519Kit', testspecs: ["Tests"] # pod 'Curve25519Kit', path: '../Curve25519Kit', testspecs: ["Tests"] + pod 'SignalMetadataKit', git: 'https://github.com/signalapp/SignalMetadataKit', testspecs: ["Tests"] # pod 'SignalMetadataKit', path: '../SignalMetadataKit', testspecs: ["Tests"] + pod 'SignalServiceKit', path: '.', testspecs: ["Tests"] + + ### + # forked third party pods + ### + + # Includes some soon to be released "unencrypted header" changes required for the Share Extension + pod 'SQLCipher', :git => 'https://github.com/sqlcipher/sqlcipher.git', :commit => 'd5c2bec' + # pod 'SQLCipher', path: '../sqlcipher' + + # Forked for performance optimizations that are not likely to be upstreamed as they are specific + # to our limited use of Mantle + pod 'Mantle', git: 'https://github.com/signalapp/Mantle', branch: 'signal-master' + # pod 'Mantle', path: '../Mantle' + + # SocketRocket has some critical crash fixes on Github, but have published an official release to cocoapods in ages, so + # we were following master + # Forked and have an open PR with our changes, but they have not been merged. + # pod 'SocketRocket', :git => 'https://github.com/facebook/SocketRocket.git', inhibit_warnings: true + pod 'SocketRocket', :git => 'https://github.com/signalapp/SocketRocket.git', branch: 'mkirk/handle-sec-err', inhibit_warnings: true + + # Forked for compatibily with the ShareExtension, changes have an open PR, but have not been merged. + pod 'YapDatabase/SQLCipher', :git => 'https://github.com/signalapp/YapDatabase.git', branch: 'signal-release' + # pod 'YapDatabase/SQLCipher', path: '../YapDatabase' + + # Forked to incorporate our self-built binary artifact. pod 'GRKOpenSSLFramework', git: 'https://github.com/signalapp/GRKOpenSSLFramework' #pod 'GRKOpenSSLFramework', path: '../GRKOpenSSLFramework' + ### # third party pods + #### + pod 'AFNetworking', inhibit_warnings: true - pod 'Mantle', :inhibit_warnings => true - # pod 'YapDatabase/SQLCipher', :inhibit_warnings => true pod 'PureLayout', :inhibit_warnings => true pod 'Reachability', :inhibit_warnings => true - # pod 'SocketRocket', :git => 'https://github.com/facebook/SocketRocket.git', inhibit_warnings: true - pod 'SocketRocket', :git => 'https://github.com/signalapp/SocketRocket.git', branch: 'mkirk/handle-sec-err', inhibit_warnings: true pod 'YYImage', :inhibit_warnings => true end diff --git a/Podfile.lock b/Podfile.lock index 72fc375fa..2c25f24bf 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -196,7 +196,7 @@ DEPENDENCIES: - GRKOpenSSLFramework (from `https://github.com/signalapp/GRKOpenSSLFramework`) - HKDFKit (from `https://github.com/signalapp/HKDFKit.git`) - HKDFKit/Tests (from `https://github.com/signalapp/HKDFKit.git`) - - Mantle + - Mantle (from `https://github.com/signalapp/Mantle`, branch `signal-master`) - PureLayout - Reachability - SignalCoreKit (from `https://github.com/signalapp/SignalCoreKit.git`) @@ -216,7 +216,6 @@ SPEC REPOS: - AFNetworking - CocoaLumberjack - libPhoneNumber-iOS - - Mantle - PromiseKit - PureLayout - Reachability @@ -235,6 +234,9 @@ EXTERNAL SOURCES: :git: https://github.com/signalapp/GRKOpenSSLFramework HKDFKit: :git: https://github.com/signalapp/HKDFKit.git + Mantle: + :branch: signal-master + :git: https://github.com/signalapp/Mantle SignalCoreKit: :git: https://github.com/signalapp/SignalCoreKit.git SignalMetadataKit: @@ -264,8 +266,11 @@ CHECKOUT OPTIONS: HKDFKit: :commit: 3e0c2371d125f2d3db26daa498d5d436961b1795 :git: https://github.com/signalapp/HKDFKit.git + Mantle: + :commit: 86be6280908291114bfacca7b765fe89bd5ca6e2 + :git: https://github.com/signalapp/Mantle SignalCoreKit: - :commit: a84ec7ed6c13b079a7e03cb09c79b5452086d1e7 + :commit: b575b9ce6a670964e1624f596dbf0aebcae82046 :git: https://github.com/signalapp/SignalCoreKit.git SignalMetadataKit: :commit: 56f28fc3a6e35d548d034ef7d0009f233ca0aa62 @@ -303,6 +308,6 @@ SPEC CHECKSUMS: YapDatabase: b418a4baa6906e8028748938f9159807fd039af4 YYImage: 1e1b62a9997399593e4b9c4ecfbbabbf1d3f3b54 -PODFILE CHECKSUM: 0f765be42c3a325b23c9a59b52d35289bb6b067d +PODFILE CHECKSUM: 1d3c7b17e2ff7bab54e3551c74559c26d95d9b06 COCOAPODS: 1.5.3 diff --git a/Pods b/Pods index 96cc3c16e..80ecd8861 160000 --- a/Pods +++ b/Pods @@ -1 +1 @@ -Subproject commit 96cc3c16eb56a8bf416d91d6f06b47b06b02b9f0 +Subproject commit 80ecd88615e75d270f1aa5f5a0e8d6060cec334f