diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index e446a5da9..a88417249 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -30,8 +30,8 @@ jobs: run: source ci_scripts/ci_common.sh && setup_github_actions_environment - - name: Reset simulators - run: SNAPSHOT_FORCE_DELETE=1 bundle exec fastlane snapshot reset_simulators + - name: Delete old log files + run: find '/Users/Shared' -name 'console*' -delete - name: Run tests run: bundle exec fastlane integration_tests @@ -44,7 +44,7 @@ jobs: run: (grep ' TRACE ' /Users/Shared -qR) - name: Check logs don't contain private messages - run: (! grep 'Go down in flames' /Users/Shared -qR) + run: "! grep 'Go down in flames' /Users/Shared -R" - name: Zip results # for faster upload if: failure() diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 1d6206923..63fa5e54e 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -35,9 +35,6 @@ jobs: - name: SwiftFormat run: swiftformat --lint . - - - name: Reset simulators - run: SNAPSHOT_FORCE_DELETE=1 bundle exec fastlane snapshot reset_simulators - name: Run tests run: bundle exec fastlane unit_tests diff --git a/.github/workflows/unit_tests_enterprise.yml b/.github/workflows/unit_tests_enterprise.yml index 8df5b704c..5bc8baac3 100644 --- a/.github/workflows/unit_tests_enterprise.yml +++ b/.github/workflows/unit_tests_enterprise.yml @@ -45,9 +45,6 @@ jobs: - name: SwiftFormat run: swiftformat --lint . - - name: Reset simulators - run: SNAPSHOT_FORCE_DELETE=1 bundle exec fastlane snapshot reset_simulators - - name: Run tests run: bundle exec fastlane unit_tests skip_previews:true diff --git a/ElementX/Sources/Application/AppCoordinator.swift b/ElementX/Sources/Application/AppCoordinator.swift index 18f366bea..5652a91f2 100644 --- a/ElementX/Sources/Application/AppCoordinator.swift +++ b/ElementX/Sources/Application/AppCoordinator.swift @@ -70,7 +70,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg let appSettings = appHooks.appSettingsHook.configure(AppSettings()) - MXLog.configure(logLevel: appSettings.logLevel) + MXLog.configure(currentTarget: "elementx", filePrefix: nil, logLevel: appSettings.logLevel) let appName = InfoPlistReader.main.bundleDisplayName let appVersion = InfoPlistReader.main.bundleShortVersionString diff --git a/ElementX/Sources/Other/Extensions/XCUIElement.swift b/ElementX/Sources/Other/Extensions/XCUIElement.swift index bb345b3c0..83c26a615 100644 --- a/ElementX/Sources/Other/Extensions/XCUIElement.swift +++ b/ElementX/Sources/Other/Extensions/XCUIElement.swift @@ -9,7 +9,7 @@ import XCTest extension XCUIElement { func clearAndTypeText(_ text: String) { - forceTap() + tapCenter() guard let currentValue = value as? String else { XCTFail("Tried to clear and type text into a non string value") @@ -24,7 +24,7 @@ extension XCUIElement { } } - func forceTap() { + func tapCenter() { let coordinate: XCUICoordinate = coordinate(withNormalizedOffset: .init(dx: 0.5, dy: 0.5)) coordinate.tap() } diff --git a/ElementX/Sources/Other/Logging/MXLog.swift b/ElementX/Sources/Other/Logging/MXLog.swift index 652c257f0..974b02f59 100644 --- a/ElementX/Sources/Other/Logging/MXLog.swift +++ b/ElementX/Sources/Other/Logging/MXLog.swift @@ -22,21 +22,18 @@ enum MXLog { private static var didConfigureOnce = false private static var rootSpan: Span! - private static var target: String! + private static var currentTarget: String! - static func configure(target: String? = nil, + static func configure(currentTarget: String, + filePrefix: String?, logLevel: TracingConfiguration.LogLevel) { guard !didConfigureOnce else { return } - RustTracing.setup(configuration: .init(logLevel: logLevel, target: target)) + RustTracing.setup(configuration: .init(logLevel: logLevel, currentTarget: currentTarget, filePrefix: filePrefix)) - if let target { - self.target = target - } else { - self.target = Constants.target - } + self.currentTarget = currentTarget - rootSpan = Span(file: #file, line: #line, level: .info, target: self.target, name: "root") + rootSpan = Span(file: #file, line: #line, level: .info, target: self.currentTarget, name: "root") rootSpan.enter() didConfigureOnce = true @@ -138,7 +135,7 @@ enum MXLog { rootSpan.enter() } - return Span(file: file, line: UInt32(line), level: level, target: target, name: name) + return Span(file: file, line: UInt32(line), level: level, target: currentTarget, name: name) } // periphery:ignore:parameters function,column,context @@ -157,6 +154,6 @@ enum MXLog { rootSpan.enter() } - logEvent(file: (file as NSString).lastPathComponent, line: UInt32(line), level: level, target: target, message: "\(message)") + logEvent(file: (file as NSString).lastPathComponent, line: UInt32(line), level: level, target: currentTarget, message: "\(message)") } } diff --git a/ElementX/Sources/Other/Logging/RustTracing.swift b/ElementX/Sources/Other/Logging/RustTracing.swift index 8e4c0b9b3..35f55000b 100644 --- a/ElementX/Sources/Other/Logging/RustTracing.swift +++ b/ElementX/Sources/Other/Logging/RustTracing.swift @@ -32,7 +32,7 @@ enum RustTracing { // Log everything on integration tests to check whether // the logs contain any sensitive data. See `UserFlowTests.swift` let filter = if ProcessInfo.isRunningIntegrationTests { - TracingConfiguration(logLevel: .trace, target: nil).filter + TracingConfiguration(logLevel: .trace, currentTarget: "integrationtests", filePrefix: nil).filter } else { configuration.filter } diff --git a/ElementX/Sources/Other/Logging/TracingConfiguration.swift b/ElementX/Sources/Other/Logging/TracingConfiguration.swift index 3ff5250de..a8d0a061c 100644 --- a/ElementX/Sources/Other/Logging/TracingConfiguration.swift +++ b/ElementX/Sources/Other/Logging/TracingConfiguration.swift @@ -11,9 +11,8 @@ import Collections // We can filter by level, crate and even file. See more details here: // https://docs.rs/tracing-subscriber/0.2.7/tracing_subscriber/filter/struct.EnvFilter.html#examples struct TracingConfiguration { - enum LogLevel: Codable, Hashable { + enum LogLevel: String, Codable, Hashable, Comparable { case error, warn, info, debug, trace - case custom(String) var title: String { switch self { @@ -27,34 +26,32 @@ struct TracingConfiguration { return "Debug" case .trace: return "Trace" - case .custom: - return "Custom" } } - fileprivate var rawValue: String { - switch self { - case .error: - return "error" - case .warn: - return "warn" - case .info: - return "info" - case .debug: - return "debug" - case .trace: - return "trace" - case .custom(let filter): - return filter + static func < (lhs: TracingConfiguration.LogLevel, rhs: TracingConfiguration.LogLevel) -> Bool { + switch (lhs, rhs) { + case (.error, _): + true + case (.warn, .error): + false + case (.warn, _): + true + case (.info, .error), (.info, .warn): + false + case (.info, _): + true + case (.debug, .error), (.debug, .warn), (.debug, .info): + false + case (.debug, _): + true + case (.trace, _): + false } } } enum Target: String { - case common = "" - - case elementx - case hyper, matrix_sdk_ffi, matrix_sdk_crypto case matrix_sdk_client = "matrix_sdk::client" @@ -66,9 +63,8 @@ struct TracingConfiguration { case matrix_sdk_ui_timeline = "matrix_sdk_ui::timeline" } + // The `common` target is excluded because 3rd-party crates might end up logging user data. static let targets: OrderedDictionary = [ - .common: .info, // Never set this lower than info - 3rd-party crates may start logging user data. - .elementx: .info, .hyper: .warn, .matrix_sdk_ffi: .info, .matrix_sdk_client: .trace, @@ -92,33 +88,30 @@ struct TracingConfiguration { /// - Parameter logLevel: the desired log level /// - Parameter target: the name of the target being configured /// - Returns: a custom tracing configuration - init(logLevel: LogLevel, target: String?) { - fileName = if let target { - "\(RustTracing.filePrefix)-\(target)" + init(logLevel: LogLevel, currentTarget: String, filePrefix: String?) { + fileName = if let filePrefix { + "\(RustTracing.filePrefix)-\(filePrefix)" } else { RustTracing.filePrefix } - - if case let .custom(filter) = logLevel { - self.filter = filter - return - } - + let overrides = Self.targets.keys.reduce(into: [Target: LogLevel]()) { partialResult, target in // Keep the defaults here - let ignoredTargets: [Target] = [.common, // Never remove common from the ignored targets (see above for more info). - .hyper, - .matrix_sdk_ffi, - .matrix_sdk_oidc, - .matrix_sdk_client, - .matrix_sdk_crypto, - .matrix_sdk_crypto_account, - .matrix_sdk_http_client] + let ignoredTargets: [Target] = [.hyper] + if ignoredTargets.contains(target) { return } - partialResult[target] = logLevel + guard let defaultTargetLogLevel = Self.targets[target] else { + return + } + + // Only change the targets that have default values + // smaller than the desired log level + if defaultTargetLogLevel < logLevel { + partialResult[target] = logLevel + } } var newTargets = Self.targets @@ -126,7 +119,7 @@ struct TracingConfiguration { newTargets.updateValue(logLevel, forKey: target) } - let components = newTargets.map { (target: Target, logLevel: LogLevel) in + var components = newTargets.map { (target: Target, logLevel: LogLevel) in guard !target.rawValue.isEmpty else { return logLevel.rawValue } @@ -134,6 +127,10 @@ struct TracingConfiguration { return "\(target.rawValue)=\(logLevel.rawValue)" } + // With `common` not being used we manually need to specify the log + // level for passed in targets + components.append("\(currentTarget)=\(logLevel.rawValue)") + filter = components.joined(separator: ",") } } diff --git a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift index 24152f5be..30f6e8ec8 100644 --- a/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift +++ b/ElementX/Sources/Screens/Settings/DeveloperOptionsScreen/View/DeveloperOptionsScreen.swift @@ -135,18 +135,6 @@ struct DeveloperOptionsScreen: View { private struct LogLevelConfigurationView: View { @Binding var logLevel: TracingConfiguration.LogLevel - @State private var customTracingConfiguration: String - - init(logLevel: Binding) { - _logLevel = logLevel - - if case .custom(let configuration) = logLevel.wrappedValue { - customTracingConfiguration = configuration - } else { - customTracingConfiguration = TracingConfiguration(logLevel: .info, target: nil).filter - } - } - var body: some View { Picker(selection: $logLevel) { ForEach(logLevels, id: \.self) { logLevel in @@ -156,24 +144,11 @@ private struct LogLevelConfigurationView: View { Text("Log level") Text("Requires app reboot") } - - if case .custom = logLevel { - TextEditor(text: $customTracingConfiguration) - .textInputAutocapitalization(.never) - .autocorrectionDisabled() - .onChange(of: customTracingConfiguration) { newValue in - logLevel = .custom(newValue) - } - } } /// Allows the picker to work with associated values private var logLevels: [TracingConfiguration.LogLevel] { - if case let .custom(filter) = logLevel { - return [.error, .warn, .info, .debug, .trace, .custom(filter)] - } else { - return [.error, .warn, .info, .debug, .trace, .custom("")] - } + [.error, .warn, .info, .debug, .trace] } } diff --git a/ElementX/Sources/UITests/UITestsAppCoordinator.swift b/ElementX/Sources/UITests/UITestsAppCoordinator.swift index 2af7f39bc..030e58bc3 100644 --- a/ElementX/Sources/UITests/UITestsAppCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsAppCoordinator.swift @@ -30,7 +30,7 @@ class UITestsAppCoordinator: AppCoordinatorProtocol, SecureWindowManagerDelegate windowManager.delegate = self - MXLog.configure(logLevel: .debug) + MXLog.configure(currentTarget: "uitests", filePrefix: nil, logLevel: .debug) ServiceLocator.shared.register(userIndicatorController: UserIndicatorController()) diff --git a/IntegrationTests/Sources/Common.swift b/IntegrationTests/Sources/Common.swift index 51c334cd3..e79483605 100644 --- a/IntegrationTests/Sources/Common.swift +++ b/IntegrationTests/Sources/Common.swift @@ -12,12 +12,11 @@ extension XCUIApplication { let getStartedButton = buttons[A11yIdentifiers.authenticationStartScreen.signIn] XCTAssertTrue(getStartedButton.waitForExistence(timeout: 10.0)) - getStartedButton.tap() + getStartedButton.tapCenter() - // Get started is network bound, wait for the change homeserver button for longer let changeHomeserverButton = buttons[A11yIdentifiers.serverConfirmationScreen.changeServer] - XCTAssertTrue(changeHomeserverButton.waitForExistence(timeout: 30.0)) - changeHomeserverButton.tap() + XCTAssertTrue(changeHomeserverButton.waitForExistence(timeout: 10.0)) + changeHomeserverButton.tapCenter() let homeserverTextField = textFields[A11yIdentifiers.changeServerScreen.server] XCTAssertTrue(homeserverTextField.waitForExistence(timeout: 10.0)) @@ -26,7 +25,7 @@ extension XCUIApplication { let confirmButton = buttons[A11yIdentifiers.changeServerScreen.continue] XCTAssertTrue(confirmButton.waitForExistence(timeout: 10.0)) - confirmButton.tap() + confirmButton.tapCenter() // Wait for server confirmation to finish let doesNotExistPredicate = NSPredicate(format: "exists == 0") @@ -35,7 +34,7 @@ extension XCUIApplication { let continueButton = buttons[A11yIdentifiers.serverConfirmationScreen.continue] XCTAssertTrue(continueButton.waitForExistence(timeout: 30.0)) - continueButton.tap() + continueButton.tapCenter() let usernameTextField = textFields[A11yIdentifiers.loginScreen.emailUsername] XCTAssertTrue(usernameTextField.waitForExistence(timeout: 10.0)) @@ -51,7 +50,7 @@ extension XCUIApplication { XCTAssertTrue(nextButton.waitForExistence(timeout: 10.0)) XCTAssertTrue(nextButton.isEnabled) - nextButton.tap() + nextButton.tapCenter() // Wait for login to finish currentTestCase.expectation(for: doesNotExistPredicate, evaluatedWith: usernameTextField) @@ -63,7 +62,7 @@ extension XCUIApplication { // Tapping the sheet button while animating upwards fails. Wait for it to settle sleep(1) - savePasswordButton.tap() + savePasswordButton.tapCenter() } // Wait for the home screen to become visible. @@ -80,17 +79,17 @@ extension XCUIApplication { let profileButton = buttons[A11yIdentifiers.homeScreen.userAvatar] // `Failed to scroll to visible (by AX action) Button` https://stackoverflow.com/a/33534187/730924 - profileButton.forceTap() + profileButton.tapCenter() // Logout let logoutButton = buttons[A11yIdentifiers.settingsScreen.logout] XCTAssertTrue(logoutButton.waitForExistence(timeout: 10.0)) - logoutButton.tap() + logoutButton.tapCenter() // Confirm logout let alertLogoutButton = alerts.firstMatch.buttons["Sign out"] XCTAssertTrue(alertLogoutButton.waitForExistence(timeout: 10.0)) - alertLogoutButton.tap() + alertLogoutButton.tapCenter() // Check that we're back on the login screen let getStartedButton = buttons[A11yIdentifiers.authenticationStartScreen.signIn] diff --git a/IntegrationTests/Sources/UserFlowTests.swift b/IntegrationTests/Sources/UserFlowTests.swift index a5f78038d..bd0be27d6 100644 --- a/IntegrationTests/Sources/UserFlowTests.swift +++ b/IntegrationTests/Sources/UserFlowTests.swift @@ -37,13 +37,13 @@ class UserFlowTests: XCTestCase { // And open it let firstRoom = app.buttons.matching(NSPredicate(format: "identifier CONTAINS %@", Self.integrationTestsRoomName)).firstMatch XCTAssertTrue(firstRoom.waitForExistence(timeout: 10.0)) - firstRoom.tap() + firstRoom.tapCenter() sendMessages() - checkPhotoSharing() - - checkDocumentSharing() + // Intentionally disabled as they're super flakey on iOS 18 simulators + // checkPhotoSharing() + // checkDocumentSharing() checkLocationSharing() @@ -57,7 +57,7 @@ class UserFlowTests: XCTestCase { // Cancel initial the room search let searchCancelButton = app.buttons["Cancel"].firstMatch XCTAssertTrue(searchCancelButton.waitForExistence(timeout: 10.0)) - searchCancelButton.forceTap() + searchCancelButton.tapCenter() } private func sendMessages() { @@ -67,7 +67,7 @@ class UserFlowTests: XCTestCase { var sendButton = app.buttons[A11yIdentifiers.roomScreen.sendButton].firstMatch XCTAssertTrue(sendButton.waitForExistence(timeout: 10.0)) - sendButton.tap() + sendButton.tapCenter() sleep(10) // Wait for the message to be sent @@ -81,12 +81,12 @@ class UserFlowTests: XCTestCase { sendButton = app.buttons[A11yIdentifiers.roomScreen.sendButton].firstMatch XCTAssertTrue(sendButton.waitForExistence(timeout: 10.0)) - sendButton.tap() + sendButton.tapCenter() sleep(5) // Wait for the message to be sent // Close the formatting options - app.buttons[A11yIdentifiers.roomScreen.composerToolbar.closeFormattingOptions].tap() + app.buttons[A11yIdentifiers.roomScreen.composerToolbar.closeFormattingOptions].tapCenter() } private func checkPhotoSharing() { @@ -98,7 +98,7 @@ class UserFlowTests: XCTestCase { // Tap on the second image. First one is always broken on simulators. let secondImage = app.scrollViews.images.element(boundBy: 1) XCTAssertTrue(secondImage.waitForExistence(timeout: 20.0)) // Photo library takes a bit to load - secondImage.tap() + secondImage.tapCenter() // Wait for the image to be processed and the new screen to appear sleep(10) @@ -129,7 +129,7 @@ class UserFlowTests: XCTestCase { // Handle map loading errors (missing credentials) let alertOkButton = app.alerts.firstMatch.buttons["OK"].firstMatch if alertOkButton.waitForExistence(timeout: 10.0) { - alertOkButton.tap() + alertOkButton.tapCenter() } allowLocationPermissionOnce() @@ -141,7 +141,7 @@ class UserFlowTests: XCTestCase { let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") let notificationAlertAllowButton = springboard.buttons["Allow Once"].firstMatch if notificationAlertAllowButton.waitForExistence(timeout: 10.0) { - notificationAlertAllowButton.tap() + notificationAlertAllowButton.tapCenter() } } @@ -178,7 +178,7 @@ class UserFlowTests: XCTestCase { // Open the room details let roomHeader = app.staticTexts[A11yIdentifiers.roomScreen.name] XCTAssertTrue(roomHeader.waitForExistence(timeout: 10.0)) - roomHeader.tap() + roomHeader.tapCenter() // Open the room member details tapOnButton(A11yIdentifiers.roomDetailsScreen.people) @@ -186,7 +186,7 @@ class UserFlowTests: XCTestCase { // Open the first member's details. Loading members for big rooms can take a while. let firstRoomMember = app.scrollViews.buttons.firstMatch XCTAssertTrue(firstRoomMember.waitForExistence(timeout: 1000.0)) - firstRoomMember.tap() + firstRoomMember.tapCenter() // Go back to the room member details tapOnBackButton("People") @@ -206,7 +206,7 @@ class UserFlowTests: XCTestCase { let profileButton = app.buttons[A11yIdentifiers.homeScreen.userAvatar] // `Failed to scroll to visible (by AX action) Button` https://stackoverflow.com/a/33534187/730924 - profileButton.forceTap() + profileButton.tapCenter() // Open analytics tapOnButton(A11yIdentifiers.settingsScreen.analytics) @@ -233,7 +233,7 @@ class UserFlowTests: XCTestCase { private func tapOnButton(_ identifier: String, waitForDisappearance: Bool = false) { let button = app.buttons[identifier] XCTAssertTrue(button.waitForExistence(timeout: 10.0)) - button.tap() + button.tapCenter() if waitForDisappearance { let doesNotExistPredicate = NSPredicate(format: "exists == 0") @@ -245,7 +245,7 @@ class UserFlowTests: XCTestCase { private func tapOnMenu(_ identifier: String) { let button = app.buttons[identifier] XCTAssertTrue(button.waitForExistence(timeout: 10.0)) - button.forceTap() + button.tapCenter() } /// Taps on a back button that the system configured with a label but no identifier. @@ -255,6 +255,6 @@ class UserFlowTests: XCTestCase { private func tapOnBackButton(_ label: String = "Back") { let button = app.buttons.matching(NSPredicate(format: "label == %@ && identifier == ''", label)).firstMatch XCTAssertTrue(button.waitForExistence(timeout: 10.0)) - button.tap() + button.tapCenter() } } diff --git a/NSE/Sources/Other/NSELogger.swift b/NSE/Sources/Other/NSELogger.swift index c0f7cc4f2..985038136 100644 --- a/NSE/Sources/Other/NSELogger.swift +++ b/NSE/Sources/Other/NSELogger.swift @@ -72,7 +72,7 @@ enum NSELogger { } isConfigured = true - MXLog.configure(target: "nse", logLevel: logLevel) + MXLog.configure(currentTarget: "nse", filePrefix: "nse", logLevel: logLevel) } static func logMemory(with tag: String) { diff --git a/UnitTests/Sources/LoggingTests.swift b/UnitTests/Sources/LoggingTests.swift index 56d34ed35..df701300a 100644 --- a/UnitTests/Sources/LoggingTests.swift +++ b/UnitTests/Sources/LoggingTests.swift @@ -22,7 +22,7 @@ class LoggingTests: XCTestCase { let target = "tests" XCTAssertTrue(RustTracing.logFiles.isEmpty) - MXLog.configure(target: target, logLevel: .info) + MXLog.configure(currentTarget: target, filePrefix: target, logLevel: .info) // There is something weird with Rust logging where the file writing handle doesn't // notice that the file it is writing to was deleted, so we can't run these checks @@ -168,7 +168,7 @@ class LoggingTests: XCTestCase { content: .init(body: "FileString", source: nil, thumbnailSource: nil, contentType: nil)) // When logging that value - MXLog.configure(logLevel: .info) + MXLog.configure(currentTarget: "tests", filePrefix: nil, logLevel: .info) MXLog.info(textMessage) MXLog.info(noticeMessage) diff --git a/UnitTests/Sources/TracingConfigurationTests.swift b/UnitTests/Sources/TracingConfigurationTests.swift index 864c8898f..2150be85b 100644 --- a/UnitTests/Sources/TracingConfigurationTests.swift +++ b/UnitTests/Sources/TracingConfigurationTests.swift @@ -10,14 +10,35 @@ import XCTest @testable import ElementX class TracingConfigurationTests: XCTestCase { - func testConfiguration() { - let configuration = TracingConfiguration(logLevel: .trace, target: nil) + func testConfiguration() { // swiftlint:disable line_length + var filter = TracingConfiguration(logLevel: .error, currentTarget: "tests", filePrefix: nil).filter - let filterComponents = configuration.filter.components(separatedBy: ",") - XCTAssertEqual(filterComponents.first, "info") - XCTAssertTrue(filterComponents.contains("matrix_sdk_base::sliding_sync=trace")) - XCTAssertTrue(filterComponents.contains("matrix_sdk::http_client=debug")) - XCTAssertTrue(filterComponents.contains("matrix_sdk_crypto=debug")) - XCTAssertTrue(filterComponents.contains("hyper=warn")) + XCTAssertEqual(filter, "hyper=warn,matrix_sdk_ffi=info,matrix_sdk::client=trace,matrix_sdk_crypto=debug,matrix_sdk_crypto::olm::account=trace,matrix_sdk::oidc=trace,matrix_sdk::http_client=debug,matrix_sdk::sliding_sync=info,matrix_sdk_base::sliding_sync=info,matrix_sdk_ui::timeline=info,tests=error") + + filter = TracingConfiguration(logLevel: .warn, currentTarget: "tests", filePrefix: nil).filter + + XCTAssertEqual(filter, "hyper=warn,matrix_sdk_ffi=info,matrix_sdk::client=trace,matrix_sdk_crypto=debug,matrix_sdk_crypto::olm::account=trace,matrix_sdk::oidc=trace,matrix_sdk::http_client=debug,matrix_sdk::sliding_sync=info,matrix_sdk_base::sliding_sync=info,matrix_sdk_ui::timeline=info,tests=warn") + + filter = TracingConfiguration(logLevel: .info, currentTarget: "tests", filePrefix: nil).filter + + XCTAssertEqual(filter, "hyper=warn,matrix_sdk_ffi=info,matrix_sdk::client=trace,matrix_sdk_crypto=debug,matrix_sdk_crypto::olm::account=trace,matrix_sdk::oidc=trace,matrix_sdk::http_client=debug,matrix_sdk::sliding_sync=info,matrix_sdk_base::sliding_sync=info,matrix_sdk_ui::timeline=info,tests=info") + + filter = TracingConfiguration(logLevel: .debug, currentTarget: "tests", filePrefix: nil).filter + + XCTAssertEqual(filter, "hyper=warn,matrix_sdk_ffi=debug,matrix_sdk::client=trace,matrix_sdk_crypto=debug,matrix_sdk_crypto::olm::account=trace,matrix_sdk::oidc=trace,matrix_sdk::http_client=debug,matrix_sdk::sliding_sync=debug,matrix_sdk_base::sliding_sync=debug,matrix_sdk_ui::timeline=debug,tests=debug") + + filter = TracingConfiguration(logLevel: .trace, currentTarget: "tests", filePrefix: nil).filter + + XCTAssertEqual(filter, "hyper=warn,matrix_sdk_ffi=trace,matrix_sdk::client=trace,matrix_sdk_crypto=trace,matrix_sdk_crypto::olm::account=trace,matrix_sdk::oidc=trace,matrix_sdk::http_client=trace,matrix_sdk::sliding_sync=trace,matrix_sdk_base::sliding_sync=trace,matrix_sdk_ui::timeline=trace,tests=trace") + } // swiftlint:enable line_length + + func testLevelOrdering() { + var logLevels: [TracingConfiguration.LogLevel] = [.info, .error, .trace, .debug, .warn] + + XCTAssertEqual(logLevels.sorted(), [.error, .warn, .info, .debug, .trace]) + + logLevels = [.warn, .error, .debug, .trace, .info, .error] + + XCTAssertEqual(logLevels.sorted(), [.error, .error, .warn, .info, .debug, .trace]) } } diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 05ea80f62..881b9cf95 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -80,12 +80,15 @@ lane :alpha do end lane :unit_tests do |options| + reset_simulator = ENV.key?('CI') + run_tests( scheme: "UnitTests", destination: "platform=iOS Simulator,name=iPhone 16,OS=18.0", ensure_devices_found: true, result_bundle: true, number_of_retries: 3, + reset_simulator: reset_simulator ) if !options[:skip_previews] @@ -95,6 +98,7 @@ lane :unit_tests do |options| ensure_devices_found: true, result_bundle: true, number_of_retries: 3, + reset_simulator: reset_simulator ) end @@ -102,10 +106,6 @@ lane :unit_tests do |options| end lane :ui_tests do |options| - # Use a fresh simulator state to ensure hardware keyboard isn't attached. - # Not necessary when running on GitHub. - # reset_simulator_contents() - create_simulator_if_necessary( name: "iPhone 16", type: "com.apple.CoreSimulator.SimDeviceType.iPhone-16", @@ -124,6 +124,8 @@ lane :ui_tests do |options| test_to_run = nil end + reset_simulator = ENV.key?('CI') + run_tests( scheme: "UITests", devices: ["iPhone 16", "iPad (10th generation)"], @@ -132,6 +134,7 @@ lane :ui_tests do |options| result_bundle: true, only_testing: test_to_run, number_of_retries: 3, + reset_simulator: reset_simulator ) end @@ -145,12 +148,14 @@ lane :integration_tests do runtime: "com.apple.CoreSimulator.SimRuntime.iOS-18-0" ) + reset_simulator = ENV.key?('CI') + run_tests( scheme: "IntegrationTests", destination: "platform=iOS Simulator,name=iPhone 16 Pro,OS=18.0", ensure_devices_found: true, result_bundle: true, - reset_simulator: true + reset_simulator: reset_simulator ) end