import FluentKit import HummingbirdFluent import Logging import Testing @testable import Persistence @Suite( "Probe method", .tags(.method) ) struct ProbeTests { // MARK: Methods tests @Test func `reports a reachable database`() async throws { let service = try Service( driver: .inMemory, logger: Logger(label: "test") ) let fluent = service() let probe = Probe(fluent: fluent) let isReachable = await probe() try await fluent.shutdown() #expect(isReachable) } @Test func `reports an unreachable database`() async throws { // Port 1 on the loopback interface has nothing listening, so the connection is refused // immediately instead of timing out. let service = try Service( driver: .postgres( .init( host: "127.0.0.1", port: 1, name: "unreachable", username: "nobody", password: "nothing", tls: .off, maxConnectionsPerEventLoop: 1, poolTimeout: .seconds(10) ) ), logger: Logger(label: "test") ) let fluent = service() let probe = Probe(fluent: fluent) let isReachable = await probe() try await fluent.shutdown() #expect(!isReachable) } @Test func `reports a hanging database as unreachable within its timeout`() async throws { // The silent server accepts the TCP connection and never answers, so the probe's query can only // ever be resolved by its deadline — without one, it would wait out the driver's own connect // timeout (10 seconds) instead. let server = try await SilentPostgresServer.start() let service = try Service( driver: .postgres( .init( host: "127.0.0.1", port: server.port, name: "hanging", username: "nobody", password: "nothing", tls: .off, maxConnectionsPerEventLoop: 1, poolTimeout: .seconds(10) ) ), logger: Logger(label: "test") ) let fluent = service() let probe = Probe( fluent: fluent, timeout: .milliseconds(100) ) let clock = ContinuousClock() let start = clock.now let isReachable = await probe() let elapsed = clock.now - start try await fluent.shutdown() try await server.stop() #expect(!isReachable) // Well past the 100-millisecond deadline to absorb scheduling noise, yet far below the driver's // 10-second connect timeout — only the deadline can answer this fast. #expect(elapsed < .seconds(5)) } @Test func `reports a default database that is not an SQL database`() async throws { let fluent = Fluent(logger: Logger(label: "test")) fluent.databases.use( .init(make: { NotSQLConfiguration() }), as: .init(string: "not-sql"), isDefault: true ) let probe = Probe(fluent: fluent) let isReachable = await probe() try await fluent.shutdown() #expect(!isReachable) } }