From 386d9d8cb55b7408343f4b70322ccaab38f37ca6 Mon Sep 17 00:00:00 2001 From: Javier Cicchelli Date: Fri, 26 Sep 2025 01:35:53 +0200 Subject: [PATCH] Implemented the "random(upTo: )" and "random(fromExclusive: )" static function for the LoggerLevel+Helpers extension in the tests target. --- .../Use Cases/RedirectURIUseCaseTests.swift | 24 +---- .../Use Cases/ServeURIUseCaseTests.swift | 20 ++-- .../Middlewares/DocCMiddlewareTests.swift | 101 +++++------------- .../Extensions/LoggerLevel+Helpers.swift | 61 +++++++++++ 4 files changed, 99 insertions(+), 107 deletions(-) create mode 100644 Tests/DocCMiddleware/Types/Extensions/LoggerLevel+Helpers.swift diff --git a/Tests/DocCMiddleware/Tests/Internal/Use Cases/RedirectURIUseCaseTests.swift b/Tests/DocCMiddleware/Tests/Internal/Use Cases/RedirectURIUseCaseTests.swift index 6f8fea9..29953a9 100644 --- a/Tests/DocCMiddleware/Tests/Internal/Use Cases/RedirectURIUseCaseTests.swift +++ b/Tests/DocCMiddleware/Tests/Internal/Use Cases/RedirectURIUseCaseTests.swift @@ -29,7 +29,7 @@ struct RedirectURIUseCaseTests { @Test func `response when logging event triggered`() async throws { try await assertResponse( - logLevel: try randomLogLevelWithEvent, + logLevel: try .random(upTo: .debug), uriRedirection: .Sample.uriRedirection, expects: .movedPermanently ) @@ -38,7 +38,7 @@ struct RedirectURIUseCaseTests { @Test func `response when logging event not triggered`() async throws { try await assertResponse( - logLevel: try randomLogLevelWithNoEvent, + logLevel: try .random(fromExclusive: .debug), uriRedirection: .Sample.uriRedirection, expects: .movedPermanently ) @@ -47,7 +47,7 @@ struct RedirectURIUseCaseTests { @Test("response when logging event triggered") func response_whenEventTriggered() async throws { try await assertResponse( - logLevel: try randomLogLevelWithEvent, + logLevel: try .random(upTo: .debug), uriRedirection: .uriRedirection, expects: .movedPermanently ) @@ -137,23 +137,7 @@ private extension RedirectURIUseCaseTests { // MARK: - Helpers private extension RedirectURIUseCaseTests { - - // MARK: Computed - - /// Extracts a random logging level that support event logging for the use case. - var randomLogLevelWithEvent: Logger.Level { - get throws { - try #require([.debug, .trace].randomElement()) - } - } - - /// Extracts a random logging level that does not support event logging for the use case. - var randomLogLevelWithNoEvent: Logger.Level { - get throws { - try #require([.critical, .error, .info, .notice, .warning].randomElement()) - } - } - + // MARK: Functions /// Checks whether a logging event should be logged or not. diff --git a/Tests/DocCMiddleware/Tests/Internal/Use Cases/ServeURIUseCaseTests.swift b/Tests/DocCMiddleware/Tests/Internal/Use Cases/ServeURIUseCaseTests.swift index 6c36e7f..bf5d27e 100644 --- a/Tests/DocCMiddleware/Tests/Internal/Use Cases/ServeURIUseCaseTests.swift +++ b/Tests/DocCMiddleware/Tests/Internal/Use Cases/ServeURIUseCaseTests.swift @@ -29,7 +29,7 @@ struct ServeURIUseCaseTests { @Test func `response when resource served and logging event triggered`() async throws { try await assertResponse( - logLevel: .debug, + logLevel: try .random(upTo: .debug), uriPath: .Sample.uriResource, folderPath: .Sample.uriFolder, expects: .ok @@ -39,7 +39,7 @@ struct ServeURIUseCaseTests { @Test func `response when resource served and logging event not triggered`() async throws { try await assertResponse( - logLevel: .info, + logLevel: try .random(fromExclusive: .debug), uriPath: .Sample.uriResource, folderPath: .Sample.uriFolder, expects: .ok @@ -49,7 +49,7 @@ struct ServeURIUseCaseTests { @Test func `response when resource not found and logging event triggered`() async throws { try await assertResponse( - logLevel: .error, + logLevel: try .random(upTo: .error), uriPath: .Sample.uriResource, folderPath: .Sample.uriFolder, expects: .notFound @@ -59,7 +59,7 @@ struct ServeURIUseCaseTests { @Test func `response when resource not found and logging event not triggered`() async throws { try await assertResponse( - logLevel: .critical, + logLevel: try .random(fromExclusive: .error), uriPath: .Sample.uriResource, folderPath: .Sample.uriFolder, expects: .notFound @@ -69,7 +69,7 @@ struct ServeURIUseCaseTests { @Test func `response throws error when loading resource`() async throws { try await assertResponse( - logLevel: .warning, + logLevel: try .random(), uriPath: .Sample.uriResource, folderPath: .Sample.uriFolder ) @@ -78,7 +78,7 @@ struct ServeURIUseCaseTests { @Test("response when resource served and logging event triggered") func response_whenResourceServed_andEventTriggered() async throws { try await assertResponse( - logLevel: .debug, + logLevel: try .random(upTo: .debug), uriPath: .Sample.uriResource, folderPath: .Sample.uriFolder, expects: .ok @@ -88,7 +88,7 @@ struct ServeURIUseCaseTests { @Test("response when resource served and logging event not triggered") func response_whenResourceServed_andEventNotTriggered() async throws { try await assertResponse( - logLevel: .info, + logLevel: try .random(fromExclusive: .debug), uriPath: .Sample.uriResource, folderPath: .Sample.uriFolder, expects: .ok @@ -98,7 +98,7 @@ struct ServeURIUseCaseTests { @Test("response when resource not found and logging event triggered") func resource_whenResourceNotFound_andEventTriggered() async throws { try await assertResponse( - logLevel: .error, + logLevel: try .random(upTo: .error), uriPath: .Sample.uriResource, folderPath: .Sample.uriFolder, expects: .notFound @@ -108,7 +108,7 @@ struct ServeURIUseCaseTests { @Test("response when resource not found and logging event not triggered") func resource_whenResourceNotFound_andEventNotTriggered() async throws { try await assertResponse( - logLevel: .critical, + logLevel: try .random(fromExclusive: .error), uriPath: .Sample.uriResource, folderPath: .Sample.uriFolder, expects: .notFound @@ -118,7 +118,7 @@ struct ServeURIUseCaseTests { @Test("response throws error when loading resource") func resource_throwsError_whenLoadingResource() async throws { try await assertResponse( - logLevel: .warning, + logLevel: try .random(), uriPath: .Sample.uriResource, folderPath: .Sample.uriFolder ) diff --git a/Tests/DocCMiddleware/Tests/Public/Middlewares/DocCMiddlewareTests.swift b/Tests/DocCMiddleware/Tests/Public/Middlewares/DocCMiddlewareTests.swift index 8334415..3eec0dd 100644 --- a/Tests/DocCMiddleware/Tests/Public/Middlewares/DocCMiddlewareTests.swift +++ b/Tests/DocCMiddleware/Tests/Public/Middlewares/DocCMiddlewareTests.swift @@ -79,7 +79,7 @@ struct DocCMiddlewareTests { expects uriRedirect: String ) async throws { try await assertRedirect( - logLevel: try randomLogLevelForRedirectWithEvent, + logLevel: try .random(upTo: .debug), uriPath: .Sample.uriDocument + uriPath, to: .Sample.uriDocument + uriRedirect ) @@ -94,7 +94,7 @@ struct DocCMiddlewareTests { expects uriRedirect: String ) async throws { try await assertRedirect( - logLevel: try randomLogLevelForRedirectWithNoEvent, + logLevel: try .random(fromExclusive: .debug), uriPath: .Sample.uriDocument + uriPath, to: .Sample.uriDocument + uriRedirect ) @@ -103,8 +103,8 @@ struct DocCMiddlewareTests { @Test(arguments: Input.redirectURIPaths) func `redirect a URI path not prefixed with root URI path`(uriPath: String) async throws { try await assertRedirect( - logLevel: try randomLogLevel, - uriPath: .Sample.uriDocument + uriPath, + logLevel: try .random(), + uriPath: uriPath, expects: .ok ) } @@ -118,7 +118,7 @@ struct DocCMiddlewareTests { uriFile: String ) async throws { try await assertServe( - logLevel: try randomLogLevelForServeOKWithEvent, + logLevel: try .random(upTo: .debug), uriPath: .Sample.uriDocument + uriPath, uriFile: uriFile, statusCode: .ok @@ -130,7 +130,7 @@ struct DocCMiddlewareTests { uriPath: String ) async throws { try await assertServe( - logLevel: try randomLogLevelForServeOKWithNoEvent, + logLevel: try .random(fromExclusive: .debug), uriPath: .Sample.uriDocument + uriPath, statusCode: .ok ) @@ -145,7 +145,7 @@ struct DocCMiddlewareTests { uriFile: String ) async throws { try await assertServe( - logLevel: try randomLogLevelForServeNotFoundWithEvent, + logLevel: try .random(upTo: .error), uriPath: .Sample.uriDocument + uriPath, uriFile: uriFile, statusCode: .notFound @@ -157,7 +157,7 @@ struct DocCMiddlewareTests { uriPath: String ) async throws { try await assertServe( - logLevel: try randomLogLevelForServeNotFoundWithNoEvent, + logLevel: try .random(fromExclusive: .error), uriPath: .Sample.uriDocument + uriPath, statusCode: .notFound ) @@ -168,7 +168,7 @@ struct DocCMiddlewareTests { uriPath: String ) async throws { try await assertServe( - logLevel: try randomLogLevel, + logLevel: try .random(), uriPath: uriPath ) } @@ -182,7 +182,7 @@ struct DocCMiddlewareTests { expects uriRedirect: String ) async throws { try await assertRedirect( - logLevel: try randomLogLevelForRedirectWithEvent, + logLevel: try .random(upTo: .debug), uriPath: .Sample.uriRoot + uriPath, to: .Sample.uriRoot + uriRedirect ) @@ -197,7 +197,7 @@ struct DocCMiddlewareTests { expects uriRedirect: String ) async throws { try await assertRedirect( - logLevel: try randomLogLevelForRedirectWithNoEvent, + logLevel: try .random(fromExclusive: .debug), uriPath: .Sample.uriRoot + uriPath, to: .Sample.uriRoot + uriRedirect ) @@ -206,7 +206,7 @@ struct DocCMiddlewareTests { @Test("redirect a URI path not prefixed with root URI path", arguments: Input.redirectURIPaths) func redirect_aURIPath_notPrefixedURIRoot(uriPath: String) async throws { try await assertRedirect( - logLevel: try randomLogLevel, + logLevel: try .random(), uriPath: .Sample.uriResource + uriPath, expects: .ok ) @@ -221,7 +221,7 @@ struct DocCMiddlewareTests { uriFile: String ) async throws { try await assertServe( - logLevel: try randomLogLevelForServeOKWithEvent, + logLevel: try .random(upTo: .debug), uriPath: .Sample.uriDocument + uriPath, uriFile: uriFile, statusCode: .ok @@ -233,7 +233,7 @@ struct DocCMiddlewareTests { uriPath: String ) async throws { try await assertServe( - logLevel: try randomLogLevelForServeOKWithNoEvent, + logLevel: try .random(fromExclusive: .debug), uriPath: .Sample.uriDocument + uriPath, statusCode: .ok ) @@ -248,7 +248,7 @@ struct DocCMiddlewareTests { uriFile: String ) async throws { try await assertServe( - logLevel: try randomLogLevelForServeNotFoundWithEvent, + logLevel: try .random(upTo: .error), uriPath: .Sample.uriDocument + uriPath, uriFile: uriFile, statusCode: .notFound @@ -260,7 +260,7 @@ struct DocCMiddlewareTests { uriPath: String ) async throws { try await assertServe( - logLevel: try randomLogLevelForServeNotFoundWithNoEvent, + logLevel: try .random(fromExclusive: .error), uriPath: .Sample.uriDocument + uriPath, statusCode: .notFound ) @@ -271,7 +271,7 @@ struct DocCMiddlewareTests { uriPath: String ) async throws { try await assertServe( - logLevel: try randomLogLevel, + logLevel: try .random(), uriPath: uriPath ) } @@ -342,7 +342,7 @@ private extension DocCMiddlewareTests { #expect(type(of:middleware.fileProvider) == FileSystemProvider.self) } - /// Asserts an URI path redirection done by the middleware. + /// Asserts a URI path redirection done by the middleware. /// - Parameters: /// - logLevel: A representation of the logging level to set in the `Logger` instance. /// - uriPath: A URI path to a resource. @@ -423,19 +423,17 @@ private extension DocCMiddlewareTests { } } - /// <#Description#> + /// Asserts a URI resource serving done by the middleware. /// - Parameters: - /// - logLevel: <#logLevel description#> - /// - uriPath: <#uriPath description#> - /// - uriFile: <#uriFile description#> - /// - folderPath: <#folderPath description#> - /// - statusCode: <#statusCode description#> + /// - logLevel: A representation of the logging level to set in the `Logger` instance. + /// - uriPath: A URI path for a resource. + /// - uriFile: A URI path for a file in the local file system. + /// - statusCode: An expected status code from the response coming out of the use case, if any. /// - Throws: An error in case an issue is encountered while asserting URI path servings by the middleware. func assertServe( logLevel: Logger.Level, uriPath: String, uriFile: String? = nil, - folderPath: String = .Sample.uriFolder, statusCode: HTTPResponse.Status? = nil ) async throws { // GIVEN @@ -527,58 +525,7 @@ private extension DocCMiddlewareTests { // MARK: - Helpers private extension DocCMiddlewareTests { - - // MARK: Computed - - /// Extracts a random logging level. - var randomLogLevel: Logger.Level { - get throws { - try #require(Logger.Level.allCases.randomElement()) - } - } - - /// Extracts a random logging level for redirection assertions that support event logging for the use case. - var randomLogLevelForRedirectWithEvent: Logger.Level { - get throws { - try #require([.debug, .trace].randomElement()) - } - } - - /// Extracts a random logging level for redirection assertions that does not support event logging for the use case. - var randomLogLevelForRedirectWithNoEvent: Logger.Level { - get throws { - try #require([.critical, .error, .info, .notice, .warning].randomElement()) - } - } - - /// Extracts a random logging level for OK serve assertions that support event logging for the use case. - var randomLogLevelForServeOKWithEvent: Logger.Level { - get throws { - try #require([.debug, .trace].randomElement()) - } - } - - /// Extracts a random logging level for OK serve assertions that does not support event logging for the use case. - var randomLogLevelForServeOKWithNoEvent: Logger.Level { - get throws { - try #require([.critical, .error, .info, .notice, .warning].randomElement()) - } - } - - /// Extracts a random logging level for Not Found serve assertions that support event logging for the use case. - var randomLogLevelForServeNotFoundWithEvent: Logger.Level { - get throws { - try #require([.debug, .error, .info, .notice, .trace, .warning].randomElement()) - } - } - - /// Extracts a random logging level for Not Found serve assertions that does not support event logging for the use case. - var randomLogLevelForServeNotFoundWithNoEvent: Logger.Level { - get throws { - try #require([.critical].randomElement()) - } - } - + // MARK: Functions /// Checks whether a logging event should be logged or not, based on a given logging level. diff --git a/Tests/DocCMiddleware/Types/Extensions/LoggerLevel+Helpers.swift b/Tests/DocCMiddleware/Types/Extensions/LoggerLevel+Helpers.swift new file mode 100644 index 0000000..680ca8d --- /dev/null +++ b/Tests/DocCMiddleware/Types/Extensions/LoggerLevel+Helpers.swift @@ -0,0 +1,61 @@ +// ===----------------------------------------------------------------------=== +// +// This source file is part of the Hummingbird DocC Middleware open source project +// +// Copyright (c) 2025 Röck+Cöde VoF. and the Hummingbird DocC Middleware project authors +// Licensed under the EUPL 1.2 or later. +// +// See LICENSE for license information +// See CONTRIBUTORS for the list of Hummingbird DocC Middleware project authors +// +// ===----------------------------------------------------------------------=== + +import Testing + +import struct Logging.Logger + +extension Logger.Level { + + // MARK: Functions + + /// Extracts a random logging level value out of an inclusive subset of logging levels, arranged by severity. + /// - Parameter level: A representation of a logging level that defines a subset of values to choose from, if any. + /// - Returns: A randomized logging value. + /// - Throws: An error thrown in case an issue is encountered when deciding for a random value. + static func random(upTo level: Self? = nil) throws -> Self { + guard let level else { + return try #require(Self.allCases.randomElement()) + } + + let levels: [Self] = switch level { + case .trace: [.trace] + case .debug: [.debug, .trace] + case .info: [.debug, .info, .trace] + case .notice: [.debug, .info, .notice, .trace] + case .warning: [.debug, .info, .notice, .trace, .warning] + case .error: [.debug, .error, .info, .notice, .trace, .warning] + case .critical: Self.allCases + } + + return try #require(levels.randomElement()) + } + + /// /// Extracts a random logging level value out of an exclusive subset of logging levels, arranged by severity. + /// - Parameter level: A representation of a logging level that defines a subset of values to choose from. + /// - Returns: A randomized logging value. + /// - Throws: An error thrown in case an issue is encountered when deciding for a random value. + static func random(fromExclusive level: Self) throws -> Self { + let levels: [Self] = switch level { + case .trace: [.critical, .debug, .error, .info, .notice, .warning] + case .debug: [.critical, .error, .info, .notice, .warning] + case .info: [.critical, .error, .notice, .warning] + case .notice: [.critical, .error, .warning] + case .warning: [.critical, .error] + case .error: [.critical] + case .critical: [] + } + + return try #require(levels.randomElement()) + } + +}