diff --git a/.swiftlint.yml b/.swiftlint.yml index 48c176560b7e49dcb37e4b352d23681600bab06a..c6574dc8868b8da11f74427cd5a1c3a28fc2290c 100755 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -16,7 +16,6 @@ included: - Tools/Scripts/Templates excluded: - "*/Sources/Generated/*" - - IntegrationTests # prints to stdout for performance tests. - Tools/Sources # Our command-line tools use a lot of print commands. line_length: diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 9600ff97ac2597d559a54b3206dd8d8fc6ff23b2..7a1b512c49f2b192091cba0119b7d4400b081465 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -212,7 +212,6 @@ 281BED345D59A9A6A99E9D98 /* UNNotificationContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE148A4FFEE853C5A281500C /* UNNotificationContent.swift */; }; 2835FD52F3F618D07F799B3D /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7310D8DFE01AF45F0689C3AA /* Publisher.swift */; }; 28AB1614E749D1147A2AC6C2 /* CreateRoomScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2214C32EA81FA9168D923D4C /* CreateRoomScreenTests.swift */; }; - 290FDB0FFDC2F1DDF660343E /* TestMeasurementParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4048041C1A6B20CB97FD18 /* TestMeasurementParser.swift */; }; 292827744227DF61C930BDDB /* CreateRoomScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB0D6CB491777E7FC6B5BA12 /* CreateRoomScreen.swift */; }; 29491EE7AE37E239E839C5A3 /* LocationSharingScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BEBF0E59F25E842EDB6FD11 /* LocationSharingScreenModels.swift */; }; 2955F4C160CFD7794D819C64 /* EffectsScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 024F7398C5FC12586FB10E9D /* EffectsScene.swift */; }; @@ -2095,7 +2094,6 @@ 9B67DF223EEB8DCAF178A1D4 /* AnalyticsPromptScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsPromptScreenCoordinator.swift; sourceTree = "<group>"; }; 9B7D8D3638864B7482E148CC /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 9C3ACC093F88FD9888518561 /* AuthenticationStartScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenViewModel.swift; sourceTree = "<group>"; }; - 9C4048041C1A6B20CB97FD18 /* TestMeasurementParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestMeasurementParser.swift; sourceTree = "<group>"; }; 9C5E81214D27A6B898FC397D /* ElementX.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ElementX.entitlements; sourceTree = "<group>"; }; 9C6624240FFD32B7F0834229 /* IdentityConfirmedScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityConfirmedScreenViewModel.swift; sourceTree = "<group>"; }; 9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationStackCoordinatorTests.swift; sourceTree = "<group>"; }; @@ -3772,7 +3770,6 @@ children = ( D33116993D54FADC0C721C1F /* Application.swift */, D1BC84BA0AF11C2128D58ABD /* Common.swift */, - 9C4048041C1A6B20CB97FD18 /* TestMeasurementParser.swift */, 21DD8599815136EFF5B73F38 /* UserFlowTests.swift */, ); path = Sources; @@ -7772,7 +7769,6 @@ 388D39ED9FE1122EA6D76BF2 /* Common.swift in Sources */, A439B456D0761D6541745CC3 /* NSRegularExpresion.swift in Sources */, 88356DE7F2AD243AB10C7B7A /* Signposter.swift in Sources */, - 290FDB0FFDC2F1DDF660343E /* TestMeasurementParser.swift in Sources */, 32B7891D937377A59606EDFC /* UserFlowTests.swift in Sources */, B444F9C184A377C1B481F07F /* XCUIElement.swift in Sources */, ); diff --git a/IntegrationTests/Sources/TestMeasurementParser.swift b/IntegrationTests/Sources/TestMeasurementParser.swift deleted file mode 100644 index 3fcad1fcd12e7d4756581a8063d324bad0d208de..0000000000000000000000000000000000000000 --- a/IntegrationTests/Sources/TestMeasurementParser.swift +++ /dev/null @@ -1,112 +0,0 @@ -// -// Copyright 2022-2024 New Vector Ltd. -// -// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -// Please see LICENSE files in the repository root for full details. -// - -import Foundation -import XCTest - -enum TestMeasurementParserMetric: String { - case appLaunch = "Duration (AppLaunch)" - case clockMonotonicTime = "Clock Monotonic Time" - case cpuTime = "CPU Time" - case memoryPeakPhysical = "Memory Peak Physical" - case memoryPhysical = "Memory Physical" - case cpuInstructionsRetired = "CPU Instructions Retired" - case diskLogicalWrites = "Disk Logical Writes" - case cpuCycles = "CPU Cycles" - - var regexValue: String { - switch self { - case .appLaunch: - return rawValue.replacingOccurrences(of: "(", with: "\\(").replacingOccurrences(of: ")", with: "\\)") - default: - return rawValue - } - } -} - -/// This class is responsible for extracting XCTest measurement run results from stderr in lieu of an official API -/// Heavily inspired by https://stackoverflow.com/questions/54814422/how-to-extract-performance-metrics-measured-by-measureblock-in-xctest -final class TestMeasurementParser { - private let pipe = Pipe() - private let regex: NSRegularExpression - private var results = [String: Double]() - - init() { - do { - let pattern = """ - \\[(\ - \(TestMeasurementParserMetric.appLaunch.regexValue)|\ - \(TestMeasurementParserMetric.clockMonotonicTime.regexValue)|\ - \(TestMeasurementParserMetric.cpuTime.regexValue)|\ - \(TestMeasurementParserMetric.memoryPeakPhysical.regexValue)|\ - \(TestMeasurementParserMetric.memoryPhysical.regexValue)|\ - \(TestMeasurementParserMetric.cpuInstructionsRetired.regexValue)|\ - \(TestMeasurementParserMetric.diskLogicalWrites.regexValue)|\ - \(TestMeasurementParserMetric.cpuCycles.regexValue)\ - ), \ - (s|kB|kI|kC)\\] \ - average: ([0-9\\.]*), - """ - - regex = try NSRegularExpression(pattern: pattern, - options: .caseInsensitive) - } catch { - fatalError("Invalid regular expression") - } - } - - /// Running an XCTest measure block within this will enable the `XCTestMeasurementParser` to read resulting values from stderr and store them locally - /// - Parameters: - /// - testCase: we need the test case so that we can add and wait for an expectation on it, allowing the capturing to finish - /// - block: should contain the normal test steps and measure block - func capture(testCase: XCTestCase, block: @escaping () -> Void) { - results.removeAll() - - // Save original output - let original = dup(STDERR_FILENO) - - // Configure `stderr` so that it's not buffered - setvbuf(stderr, nil, _IONBF, 0) - - dup2(pipe.fileHandleForWriting.fileDescriptor, STDERR_FILENO) - - pipe.fileHandleForReading.readabilityHandler = { [weak self] handle in - guard let self else { - return - } - - let string = String(data: handle.availableData, encoding: .utf8) ?? "<Non-ascii data of size\(handle.availableData.count)>\n" - self.regex.matches(in: string, options: .reportCompletion).forEach { - if let nameIndex = Range($0.range(at: 1), in: string), - let averageIndex = Range($0.range(at: 3), in: string) { - let name = String(string[nameIndex]) - let average = Double(string[averageIndex]) - - self.results[name] = average - } - } - - // Print to stdout because stderr is piped - print("\(string)") - } - - block() - - // Revert - fflush(stderr) - dup2(original, STDERR_FILENO) - close(original) - - // Allow the parser to finish - let expectation = testCase.expectation(description: "Wait for the results to be gathered") - DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { - expectation.fulfill() - } - - testCase.waitForExpectations(timeout: 10.0) - } -}