174 lines
4.8 KiB
Swift
174 lines
4.8 KiB
Swift
import Foundation
|
|
import Logging
|
|
import SQLKit
|
|
import Testing
|
|
|
|
@testable import Persistence
|
|
|
|
@Suite(
|
|
"Service method",
|
|
.tags(.method)
|
|
)
|
|
struct ServiceTests {
|
|
|
|
// MARK: Methods tests
|
|
|
|
@Test
|
|
func `registers an SQLite database as the default for the in-memory driver`() async throws {
|
|
let service = try Service(
|
|
driver: .inMemory,
|
|
logger: Logger(label: "test")
|
|
)
|
|
|
|
let fluent = service()
|
|
let database = fluent.db() as? any SQLDatabase
|
|
|
|
try await fluent.shutdown()
|
|
|
|
let dialect = try #require(database?.dialect)
|
|
|
|
#expect(dialect.name == "sqlite")
|
|
}
|
|
|
|
@Test
|
|
func `registers a PostgreSQL database as the default for the postgres driver`() async throws {
|
|
// Resolving the default database opens no connection — pooling is lazy — so no server
|
|
// needs to be listening on the configured host and port.
|
|
let service = try Service(
|
|
driver: .postgres(
|
|
.init(
|
|
host: "127.0.0.1",
|
|
port: 5432,
|
|
name: "site",
|
|
username: "site",
|
|
password: "site",
|
|
tls: .off,
|
|
maxConnectionsPerEventLoop: 1,
|
|
poolTimeout: .seconds(10)
|
|
)
|
|
),
|
|
logger: Logger(label: "test")
|
|
)
|
|
|
|
let fluent = service()
|
|
let database = fluent.db() as? any SQLDatabase
|
|
|
|
try await fluent.shutdown()
|
|
|
|
let dialect = try #require(database?.dialect)
|
|
|
|
#expect(dialect.name == "postgresql")
|
|
}
|
|
|
|
@Test
|
|
func `builds a usable in-memory database`() async throws {
|
|
let service = try Service(
|
|
driver: .inMemory,
|
|
logger: Logger(label: "test")
|
|
)
|
|
|
|
let fluent = service()
|
|
|
|
do {
|
|
let database = try #require(fluent.db() as? any SQLDatabase)
|
|
|
|
try await database.raw("SELECT 1").run()
|
|
} catch {
|
|
try? await fluent.shutdown()
|
|
|
|
throw error
|
|
}
|
|
|
|
try await fluent.shutdown()
|
|
}
|
|
|
|
@Test("in-memory: migrate, insert, read back")
|
|
func inMemoryRoundTrip() async throws {
|
|
try await roundTrip(driver: .inMemory)
|
|
}
|
|
|
|
@Test(
|
|
"postgres: migrate, insert, read back",
|
|
.enabled(if: postgresDriver != nil)
|
|
)
|
|
func postgresRoundTrip() async throws {
|
|
try await roundTrip(
|
|
driver: postgresDriver!,
|
|
revertAfter: true
|
|
)
|
|
}
|
|
|
|
}
|
|
|
|
// MARK: - Helpers
|
|
|
|
private extension ServiceTests {
|
|
|
|
/// Migrates, inserts, and reads back a record against the given driver, shutting the pool down after.
|
|
///
|
|
/// The `Fluent` service normally owns pool shutdown via its `run()` in the service group; outside that,
|
|
/// the test must shut it down explicitly — even on failure — or the pool asserts on `deinit`.
|
|
/// - Parameters:
|
|
/// - driver: the persistence backend to exercise.
|
|
/// - revertAfter: whether to revert the migrations afterwards; set for a shared database (the
|
|
/// in-memory database is discarded on shutdown, so it needs no revert).
|
|
func roundTrip(
|
|
driver: Persistence.Driver,
|
|
revertAfter: Bool = false
|
|
) async throws {
|
|
let prepareDB = PrepareDB()
|
|
let service = try Service(
|
|
driver: driver,
|
|
logger: Logger(label: "test")
|
|
)
|
|
|
|
let fluent = service()
|
|
|
|
do {
|
|
await prepareDB(for: fluent)
|
|
|
|
try await fluent.migrate()
|
|
|
|
let repository = ExampleRepository(fluent: fluent)
|
|
let created = try await repository.create(name: "site")
|
|
|
|
#expect(try await repository.all().contains(created))
|
|
|
|
if revertAfter {
|
|
try await fluent.revert()
|
|
}
|
|
} catch {
|
|
try? await fluent.shutdown()
|
|
|
|
throw error
|
|
}
|
|
|
|
try await fluent.shutdown()
|
|
}
|
|
|
|
}
|
|
|
|
/// The PostgreSQL driver built from the `POSTGRES_TEST_*` environment variables, or `nil` when the gate
|
|
/// variable `POSTGRES_TEST_HOST` is unset — in which case the PostgreSQL integration test is skipped, so
|
|
/// the suite stays runnable with no database available.
|
|
private let postgresDriver: Persistence.Driver? = {
|
|
let environment = ProcessInfo.processInfo.environment
|
|
|
|
guard let host = environment["POSTGRES_TEST_HOST"] else {
|
|
return nil
|
|
}
|
|
|
|
return .postgres(
|
|
.init(
|
|
host: host,
|
|
port: environment["POSTGRES_TEST_PORT"].flatMap(Int.init) ?? 5432,
|
|
name: environment["POSTGRES_TEST_NAME"] ?? "site",
|
|
username: environment["POSTGRES_TEST_USERNAME"] ?? "site",
|
|
password: environment["POSTGRES_TEST_PASSWORD"] ?? "site",
|
|
tls: .off,
|
|
maxConnectionsPerEventLoop: 2,
|
|
poolTimeout: .seconds(10)
|
|
)
|
|
)
|
|
}()
|