From 4e4244eadf14075b2f3d6fd7ca8e61b37909e0c5 Mon Sep 17 00:00:00 2001 From: Frank Rotermund Date: Tue, 17 Oct 2023 10:12:31 +0000 Subject: [PATCH] Feature/5031 maintenance error handling --- Gemfile | 3 +- Riot/target-bum-open.yml | 14 -- Riot/target-messenger.yml | 14 -- Riot/target.yml | 9 - RiotTests/RiotTests-Bridging-Header.h | 2 - RiotTests/target.yml | 39 ++-- .../ServerDownTimeService.swift | 1 + bwi/ServerMaintenance/ServerDowntime.swift | 2 +- .../ServerDowntimeDefaultService.swift | 51 ++++- bwi/Tests/BWIAnalyticsTests.swift | 2 +- bwi/Tests/LoginProtectionTests.swift | 1 + bwi/Tests/ServerDownTimeTests.swift | 211 ++++++++++++++++++ 12 files changed, 281 insertions(+), 68 deletions(-) create mode 100644 bwi/Tests/ServerDownTimeTests.swift diff --git a/Gemfile b/Gemfile index 6ae494528..32e7a088a 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,8 @@ source "https://rubygems.org" gem "xcode-install" gem "fastlane" -gem "cocoapods", '~>1.11.2' +gem "cocoapods", '~>1.13.0' +gem 'activesupport', '~> 7.0.8' gem "slather" plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') diff --git a/Riot/target-bum-open.yml b/Riot/target-bum-open.yml index 344536c2d..25f58e963 100644 --- a/Riot/target-bum-open.yml +++ b/Riot/target-bum-open.yml @@ -10,7 +10,6 @@ schemes: targets: BuM-Open: - running - - testing - profiling - analyzing - archiving @@ -19,19 +18,6 @@ schemes: run: config: Debug disableMainThreadChecker: true - test: - config: Debug - disableMainThreadChecker: true - gatherCoverageData: true - language: "de" - region: "DE" - environmentVariables: - username: - defaultpin: - defaultpassphrase: - defaultpassword: - targets: - - RiotTests targets: BuM-Open: diff --git a/Riot/target-messenger.yml b/Riot/target-messenger.yml index 1453c1edc..723620028 100644 --- a/Riot/target-messenger.yml +++ b/Riot/target-messenger.yml @@ -10,7 +10,6 @@ schemes: targets: BundesMessenger: - running - - testing - profiling - analyzing - archiving @@ -19,19 +18,6 @@ schemes: run: config: Debug disableMainThreadChecker: true - test: - config: Debug - disableMainThreadChecker: true - gatherCoverageData: true - language: "de" - region: "DE" - environmentVariables: - username: - defaultpin: - defaultpassphrase: - defaultpassword: - targets: - - RiotTests targets: BundesMessenger: diff --git a/Riot/target.yml b/Riot/target.yml index 7ecc5fd7e..eaaef3240 100644 --- a/Riot/target.yml +++ b/Riot/target.yml @@ -10,7 +10,6 @@ schemes: targets: Riot: - running - - testing - profiling - analyzing - archiving @@ -19,14 +18,6 @@ schemes: run: config: Debug disableMainThreadChecker: true - test: - config: Debug - disableMainThreadChecker: true - targets: - - RiotTests - gatherCoverageData: true - coverageTargets: - - Riot targets: Riot: diff --git a/RiotTests/RiotTests-Bridging-Header.h b/RiotTests/RiotTests-Bridging-Header.h index 96b1212d8..1b2cb5d6d 100644 --- a/RiotTests/RiotTests-Bridging-Header.h +++ b/RiotTests/RiotTests-Bridging-Header.h @@ -2,5 +2,3 @@ // Use this file to import your target's public headers that you would like to expose to Swift. // -#import "Riot-Bridging-Header.h" -#import "MatrixKitTests-Bridging-Header.h" diff --git a/RiotTests/target.yml b/RiotTests/target.yml index 01ba2d891..4d26d25d0 100644 --- a/RiotTests/target.yml +++ b/RiotTests/target.yml @@ -58,23 +58,22 @@ targets: PROVISIONING_PROFILE_SPECIFIER: $(RIOT_PROVISIONING_PROFILE_SPECIFIER) sources: - - path: . - - path: ../Config/Configurable.swift - - path: ../Config/BuildSettings.swift - - path: ../Config/BWIBuildSettings.swift - - path: ../Config/BuM/BWIBuildSettings+BuM.swift - - path: ../Config/AppConfiguration.swift - - path: ../Config/CommonConfiguration.swift - - path: ../Config/MDMSettings.swift - - path: ../Riot/Categories/Bundle.swift - - path: ../Riot/Managers/AppInfo/AppInfo.swift - - path: ../Riot/Managers/AppInfo/AppVersion.swift - - path: ../Riot/Managers/Settings/RiotSettings.swift - - path: ../Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift - - path: ../bwi/SecureStorage/ - - path: ../Riot/PropertyWrappers/UserDefaultsBackedPropertyWrapper.swift - - path: ../bwi/Tests/BWIAnalyticsTests.swift - - path: ../Riot/Modules/Room/TimelineCells/Styles/RoomTimelineStyleIdentifier.swift - - path: ../Riot/Modules/Room/EventMenu/EventMenuBuilder.swift - - path: ../Riot/Modules/Room/EventMenu/EventMenuItemType.swift - - path: ../Riot/Modules/VoiceBroadcast/VoiceBroadcastSDK/MatrixSDK/VoiceBroadcastSettings.swift + - path: target.yml + # - path: ../Config/Configurable.swift + # - path: ../Config/BuildSettings.swift + # - path: ../Config/BWIBuildSettings.swift + # - path: ../Config/BuM/BWIBuildSettings+BuM.swift + # - path: ../Config/AppConfiguration.swift + # - path: ../Config/CommonConfiguration.swift + # - path: ../Riot/Categories/Bundle.swift + # - path: ../Riot/Managers/AppInfo/AppInfo.swift + # - path: ../Riot/Managers/AppInfo/AppVersion.swift + # - path: ../Riot/Managers/Settings/RiotSettings.swift + # - path: ../Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift + # - path: ../bwi/SecureStorage/ + # - path: ../Riot/PropertyWrappers/UserDefaultsBackedPropertyWrapper.swift + - path: ../bwi/Tests +# - path: ../Riot/Modules/Room/TimelineCells/Styles/RoomTimelineStyleIdentifier.swift +# - path: ../Riot/Modules/Room/EventMenu/EventMenuBuilder.swift +# - path: ../Riot/Modules/Room/EventMenu/EventMenuItemType.swift +# - path: ../Riot/Modules/VoiceBroadcast/VoiceBroadcastSDK/MatrixSDK/VoiceBroadcastSettings.swift \ No newline at end of file diff --git a/bwi/ServerMaintenance/ServerDownTimeService.swift b/bwi/ServerMaintenance/ServerDownTimeService.swift index 5ae327438..6341d7eea 100644 --- a/bwi/ServerMaintenance/ServerDownTimeService.swift +++ b/bwi/ServerMaintenance/ServerDownTimeService.swift @@ -35,6 +35,7 @@ enum ServerDowntimeType: String { protocol ServerDowntimeService { func fetchDowntimes(session: MXSession, completion: @escaping () -> Void) + func loadDowntimes(downtimes: [[String: Any]]) throws func isDowntimePresentable() -> Bool func downtimeText() -> String func downtimeColor() -> UIColor diff --git a/bwi/ServerMaintenance/ServerDowntime.swift b/bwi/ServerMaintenance/ServerDowntime.swift index 254284e8a..70a05ef70 100644 --- a/bwi/ServerMaintenance/ServerDowntime.swift +++ b/bwi/ServerMaintenance/ServerDowntime.swift @@ -22,7 +22,7 @@ struct ServerDowntime : Codable { let startTime: String let endTime: String let type: String - let description: String + let description: String? let blocking: Bool? private enum CodingKeys: String, CodingKey { diff --git a/bwi/ServerMaintenance/ServerDowntimeDefaultService.swift b/bwi/ServerMaintenance/ServerDowntimeDefaultService.swift index 919e0071b..ea10bd302 100644 --- a/bwi/ServerMaintenance/ServerDowntimeDefaultService.swift +++ b/bwi/ServerMaintenance/ServerDowntimeDefaultService.swift @@ -39,8 +39,18 @@ fileprivate let maintenanceURL = "/_matrix/cmaintenance" return nil } - let serverDowntimes = encodedDowntimes + // needs to split up because compiler gets confused + var serverDowntimes = encodedDowntimes .compactMap { try? JSONDecoder().decode(ServerDowntime.self, from: $0) } + + serverDowntimes = serverDowntimes + .filter { + // remove downtimes with invalid values + return ($0.type.elementsEqual(ServerDowntimeType.adhocMessage.rawValue) || $0.type.elementsEqual(ServerDowntimeType.maintenance.rawValue)) && + $0.startTime.iso8601Date != nil && + $0.endTime.iso8601Date != nil && + $0.warningStartTime.iso8601Date != nil + } .filter { // remove downtimes that are already done guard let downtimeEndDate = $0.endTime.iso8601Date else { @@ -55,10 +65,32 @@ fileprivate let maintenanceURL = "/_matrix/cmaintenance" } return warningStartDate.timeIntervalSinceNow <= 0 } + + // filter Maintenance with wrong date order + serverDowntimes = serverDowntimes .filter { - // remove downtimes with invalid formed start or end times - return $0.startTime.iso8601Date != nil && $0.endTime.iso8601Date != nil + guard let startDate = $0.startTime.iso8601Date, let endDate = $0.endTime.iso8601Date, let warningDate = $0.warningStartTime.iso8601Date else { + return false + } + + return (warningDate <= startDate) && (startDate <= endDate) } + + // filter empty messages on ADMHOCMESSAGE type + + serverDowntimes = serverDowntimes + .filter { + if $0.type.elementsEqual(ServerDowntimeType.adhocMessage.rawValue) { + if let description = $0.description, description.count > 0 { + return true + } else { + return false + } + } + return true + } + + serverDowntimes = serverDowntimes .sorted { // sort downtimes be startTime guard let downtimeStartDate1 = $0.startTime.iso8601Date, let downtimeStartDate2 = $1.startTime.iso8601Date else { @@ -238,6 +270,10 @@ extension ServerDowntimeDefaultService : ServerDowntimeService { }) } + func loadDowntimes(downtimes: [[String : Any]]) throws { + try copyServerDowntimesToUserDefaults(downtimes: downtimes) + } + func fetchDowntimesWithDirectRequest(localUrlString: String? = nil, completion: @escaping (Bool) -> Void) { var urlString = AppConfigService.shared.serverUrl() @@ -286,7 +322,10 @@ extension ServerDowntimeDefaultService : ServerDowntimeService { } switch downtimeType() { case .adhocMessage: - return downTime.description + guard let description = downTime.description else { + return "" + } + return description case .maintenance: guard let startDate = downTime.startTime.iso8601Date, let endDate = downTime.endTime.iso8601Date else { return "" @@ -323,7 +362,7 @@ extension ServerDowntimeDefaultService : ServerDowntimeService { dateFormatter.string(from: startDate), timeFormatter.string(from: startDate), timeFormatter.string(from: endDate), - utcFormatter.string(from: startDate)).appending(BWIBuildSettings.shared.showMaintenanceInfoMessageType ? "\n\n\(downTime.description)" : "") + utcFormatter.string(from: startDate)).appending(BWIBuildSettings.shared.showMaintenanceInfoMessageType ? "\n\n\(downTime.description ?? "")" : "") } else { return BWIL10n.settingsDowntimeMessageDifferentDays(AppInfo.current.displayName, dayOfWeekFormatter.string(from: startDate), @@ -331,7 +370,7 @@ extension ServerDowntimeDefaultService : ServerDowntimeService { utcFormatter.string(from: startDate), dayOfWeekFormatter.string(from: endDate), dateTimeFormatter.string(from: endDate), - utcFormatter.string(from: endDate)).appending(BWIBuildSettings.shared.showMaintenanceInfoMessageType ? "\n\n\(downTime.description)" : "") + utcFormatter.string(from: endDate)).appending(BWIBuildSettings.shared.showMaintenanceInfoMessageType ? "\n\n\(downTime.description ?? "")" : "") } } } diff --git a/bwi/Tests/BWIAnalyticsTests.swift b/bwi/Tests/BWIAnalyticsTests.swift index bf7b8cb8c..f5f19ac68 100644 --- a/bwi/Tests/BWIAnalyticsTests.swift +++ b/bwi/Tests/BWIAnalyticsTests.swift @@ -16,7 +16,7 @@ */ import XCTest -@testable import Riot +@testable import Element class BWIAnalyticsTests: XCTestCase { diff --git a/bwi/Tests/LoginProtectionTests.swift b/bwi/Tests/LoginProtectionTests.swift index 0dc0ca915..464136244 100644 --- a/bwi/Tests/LoginProtectionTests.swift +++ b/bwi/Tests/LoginProtectionTests.swift @@ -16,6 +16,7 @@ */ import XCTest +@testable import Element class LoginProtectionTests: XCTestCase { diff --git a/bwi/Tests/ServerDownTimeTests.swift b/bwi/Tests/ServerDownTimeTests.swift new file mode 100644 index 000000000..fd3240016 --- /dev/null +++ b/bwi/Tests/ServerDownTimeTests.swift @@ -0,0 +1,211 @@ +// +/* + * Copyright (c) 2022 BWI GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import XCTest +@testable import Element + +final class ServerDownTimeTests: XCTestCase { + + private let typeMain = "MAINTENANCE" + private let typeAdhoc = "ADHOC_MESSAGE" + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testWarningTimeMaintenance() throws { + let service = ServerDowntimeDefaultService() + + let downtimes = [["warning_start_time": isoDate(-2), + "start_time": isoDate(2), + "end_time": isoDate(4), + "type": typeMain, + "description": "", + "blocking": true]] + + + try service.loadDowntimes(downtimes: downtimes) + + XCTAssert(service.nextDowntimeStatus() == .warning) + } + + func testRunningMaintenance() throws { + let service = ServerDowntimeDefaultService() + + let downtimes = [["warning_start_time": isoDate(-4), + "start_time": isoDate(-2), + "end_time": isoDate(4), + "type": typeMain, + "description": "", + "blocking": true]] + + + try service.loadDowntimes(downtimes: downtimes) + + XCTAssert(service.nextDowntimeStatus() == .ongoing) + } + + func testRunningBlockingMaintenance() throws { + let service = ServerDowntimeDefaultService() + + let downtimes = [["warning_start_time": isoDate(-4), + "start_time": isoDate(-2), + "end_time": isoDate(4), + "type": typeMain, + "description": "", + "blocking": true]] + + + try service.loadDowntimes(downtimes: downtimes) + + XCTAssert(service.nextDowntimeStatus() == .ongoing) + XCTAssert(service.isBlocking()) + } + + func testRunningNoneBlockingMaintenance() throws { + let service = ServerDowntimeDefaultService() + + let downtimes = [["warning_start_time": isoDate(-4), + "start_time": isoDate(-2), + "end_time": isoDate(4), + "type": typeMain, + "description": "", + "blocking": false]] + + + try service.loadDowntimes(downtimes: downtimes) + + XCTAssert(service.nextDowntimeStatus() == .ongoing) + XCTAssert(service.isBlocking() == false) + } + + func testRunningBlockingDefaultMaintenance() throws { + let service = ServerDowntimeDefaultService() + + let downtimes = [["warning_start_time": isoDate(-4), + "start_time": isoDate(-2), + "end_time": isoDate(4), + "type": typeMain, + "description": ""]] + + + try service.loadDowntimes(downtimes: downtimes) + + XCTAssert(service.nextDowntimeStatus() == .ongoing) + XCTAssert(service.isBlocking() == false) + } + + func testAdhocMessage() throws { + let service = ServerDowntimeDefaultService() + + let downtimes = [["warning_start_time": isoDate(-4), + "start_time": isoDate(-2), + "end_time": isoDate(4), + "type": typeAdhoc, + "description": "Text"]] + + + try service.loadDowntimes(downtimes: downtimes) + + XCTAssert(service.nextDowntimeStatus() == .ongoing) + XCTAssert(service.downtimeText() == "Text") + } + + func testAdhocMessageWithoutDescription() throws { + let service = ServerDowntimeDefaultService() + + let downtimes = [["warning_start_time": isoDate(-4), + "start_time": isoDate(-2), + "end_time": isoDate(4), + "type": typeAdhoc + ]] + + + try service.loadDowntimes(downtimes: downtimes) + + XCTAssert(service.nextDowntimeStatus() == .none) + } + + func testToBigWarningDate() throws { + let service = ServerDowntimeDefaultService() + + let downtimes = [["warning_start_time": isoDate(2), + "start_time": isoDate(-2), + "end_time": isoDate(4), + "type": typeAdhoc, + "description": "Text"]] + + + try service.loadDowntimes(downtimes: downtimes) + + XCTAssert(service.nextDowntimeStatus() == .none) + } + + func testToBigStartDate() throws { + let service = ServerDowntimeDefaultService() + + let downtimes = [["warning_start_time": isoDate(-2), + "start_time": isoDate(4), + "end_time": isoDate(2), + "type": typeAdhoc, + "description": "Text"]] + + + try service.loadDowntimes(downtimes: downtimes) + + XCTAssert(service.nextDowntimeStatus() == .none) + } + + func testWrongType() throws { + let service = ServerDowntimeDefaultService() + + let downtimes = [["warning_start_time": isoDate(-4), + "start_time": isoDate(-2), + "end_time": isoDate(2), + "type": "TYPPP", + "description": "Text"]] + + + try service.loadDowntimes(downtimes: downtimes) + + XCTAssert(service.nextDowntimeStatus() == .none) + } + + func testDateFormatType() throws { + let service = ServerDowntimeDefaultService() + + let downtimes = [["warning_start_time": "2023-0100:00:00", + "start_time": isoDate(-2), + "end_time": isoDate(2), + "type": typeMain, + "description": "Text"]] + + + try service.loadDowntimes(downtimes: downtimes) + + XCTAssert(service.nextDowntimeStatus() == .none) + } + + private func isoDate(_ hours: Int) -> String { + let dateFormatter = ISO8601DateFormatter() + return dateFormatter.string(from: Calendar.current.date(byAdding: .hour, value:hours, to: Date())!) + } +}