Implemented the "random(upTo: )" and "random(fromExclusive: )" static function for the LoggerLevel+Helpers extension in the tests target.

This commit is contained in:
2025-09-26 01:35:53 +02:00
parent 8aa2cf0fb2
commit 386d9d8cb5
4 changed files with 99 additions and 107 deletions
@@ -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.
@@ -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
)
@@ -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.
@@ -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())
}
}