Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/groue/GRDB.swift", from: "7.1.0"),
.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.6.4"),
.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.9.0"),
.package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.3.0"),
],
targets: [
Expand Down
6 changes: 3 additions & 3 deletions SharingGRDB.xcworkspace/xcshareddata/swiftpm/Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 29 additions & 16 deletions Sources/SharingGRDB/DefaultDatabase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,8 @@ extension DependencyValues {
static var testValue: any DatabaseWriter {
var message: String {
@Dependency(\.context) var context
if context == .preview {
return """
A blank, in-memory database is being used. To set the database that is used by \
'SharingGRDB', use the 'prepareDependencies' tool as early as possible in the lifetime \
of your preview:

#Preview {
let _ = prepareDependencies {
$0.defaultDatabase = try! DatabaseQueue(/* ... */)
}

// ...
}
"""
} else {
switch context {
case .live:
return """
A blank, in-memory database is being used. To set the database that is used by \
'SharingGRDB', use the 'prepareDependencies' tool as early as possible in the lifetime \
Expand All @@ -79,9 +66,35 @@ extension DependencyValues {
// ...
}
"""

case .preview:
return #"""
A blank, in-memory database is being used. To set the database that is used by \
'SharingGRDB' in a preview, use a tool like the 'dependency' trait:

#Preview(
trait: .dependency(\.defaultDatabase, try DatabaseQueue(/* ... */)
) {
// ...
}
"""#

case .test:
return #"""
A blank, in-memory database is being used. To set the database that is used by \
'SharingGRDB' in a test, use a tool like the 'dependency' trait:

@Suite(.dependency(\.defaultDatabase, try DatabaseQueue(/* ... */)
struct MyTests {
// ...
}
"""#

}
}
reportIssue(message)
if shouldReportUnimplemented {
reportIssue(message)
}
var configuration = Configuration()
#if DEBUG
configuration.label = .defaultDatabaseLabel
Expand Down
12 changes: 6 additions & 6 deletions Tests/SharingGRDBTests/IntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@ struct IntegrationTests {
_ = try SyncUp(isActive: true, title: "Engineering")
.inserted(db)
}
try await Task.sleep(nanoseconds: 10_000_000)
try await Task.sleep(nanoseconds: 100_000_000)
#expect(syncUps == [SyncUp(id: 1, isActive: true, title: "Engineering")])
try await database.write { db in
_ = try SyncUp(id: 1, isActive: false, title: "Engineering")
.saved(db)
}
try await Task.sleep(nanoseconds: 10_000_000)
try await Task.sleep(nanoseconds: 100_000_000)
#expect(syncUps == [])
try await database.write { db in
_ = try SyncUp(id: 1, isActive: true, title: "Engineering")
.saved(db)
}
try await Task.sleep(nanoseconds: 10_000_000)
try await Task.sleep(nanoseconds: 100_000_000)
#expect(syncUps == [SyncUp(id: 1, isActive: true, title: "Engineering")])
}

Expand All @@ -45,19 +45,19 @@ struct IntegrationTests {
_ = try SyncUp(isActive: true, title: "Engineering")
.inserted(db)
}
try await Task.sleep(nanoseconds: 10_000_000)
try await Task.sleep(nanoseconds: 100_000_000)
#expect(syncUps == [SyncUp(id: 1, isActive: true, title: "Engineering")])
try await database.write { db in
_ = try SyncUp(id: 1, isActive: false, title: "Engineering")
.saved(db)
}
try await Task.sleep(nanoseconds: 10_000_000)
try await Task.sleep(nanoseconds: 100_000_000)
#expect(syncUps == [])
try await database.write { db in
_ = try SyncUp(id: 1, isActive: true, title: "Engineering")
.saved(db)
}
try await Task.sleep(nanoseconds: 10_000_000)
try await Task.sleep(nanoseconds: 100_000_000)
#expect(syncUps == [SyncUp(id: 1, isActive: true, title: "Engineering")])
}
}
Expand Down
42 changes: 23 additions & 19 deletions Tests/SharingGRDBTests/SharingGRDBTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Testing
$0.defaultDatabase = try DatabaseQueue()
} operation: {
@SharedReader(.fetchOne(sql: "SELECT 1")) var bool = false
try await Task.sleep(nanoseconds: 10_000_000)
try await Task.sleep(nanoseconds: 100_000_000)
#expect(bool)
#expect($bool.loadError == nil)
}
Expand All @@ -33,23 +33,24 @@ import Testing
} operation: {
@SharedReader(.fetchOne(sql: "SELEC 1")) var bool = false
#expect(bool == false)
try await Task.sleep(nanoseconds: 10_000_000)
try await Task.sleep(nanoseconds: 100_000_000)
#expect($bool.loadError is DatabaseError?)
let error = try #require($bool.loadError as? DatabaseError)
#expect(error.message == #"near "SELEC": syntax error"#)
}
}

@Test func fetchWithTwoDatabaseConnections() async throws {
let name = #function
try await withDependencies {
$0.defaultDatabase = try .database
$0.defaultDatabase = try .database(named: name)
} operation: {
@SharedReader(.fetchAll(sql: "SELECT * FROM records")) var records1: [Record] = []
try await Task.sleep(nanoseconds: 100_000_000)
#expect(records1.map(\.id) == [1, 2, 3])

try await withDependencies {
$0.defaultDatabase = try .database
$0.defaultDatabase = try .database(named: name)
} operation: {
@Dependency(\.defaultDatabase) var database2
@SharedReader(.fetchAll(sql: "SELECT * FROM records")) var records2: [Record] = []
Expand All @@ -68,14 +69,14 @@ import Testing
}
}

@Test(.dependency(\.defaultDatabase, try .database))
@Test(.dependency(\.defaultDatabase, try .database()))
func fetchIDHashValue() async throws {
let fetchKey1: some SharedReaderKey<Void> = .fetch(Fetch1())
let fetchKey2: some SharedReaderKey<Void> = .fetch(Fetch2())
#expect(fetchKey1.id.hashValue != fetchKey2.id.hashValue)
}

@Test(.dependency(\.defaultDatabase, try .database))
@Test(.dependency(\.defaultDatabase, try .database()))
func fetchAnimationHashValue() async throws {
let fetchKey1: some SharedReaderKey<Void> = .fetch(Fetch1())
let fetchKey2: some SharedReaderKey<Void> = .fetch(Fetch2(), animation: .default)
Expand All @@ -97,20 +98,23 @@ fileprivate struct Record: Codable, Equatable, FetchableRecord, MutablePersistab
let id: Int
}
extension DatabaseWriter where Self == DatabaseQueue {
fileprivate static var database: DatabaseQueue {
get throws {
let database = try DatabaseQueue(named: "db")
var migrator = DatabaseMigrator()
migrator.registerMigration("Up") { db in
try db.create(table: "records") { table in
table.column("id", .integer).primaryKey(autoincrement: true)
}
for index in 1...3 {
_ = try Record(id: index).inserted(db)
}
fileprivate static func database(named name: String? = nil) throws -> DatabaseQueue {
let database: DatabaseQueue
if let name {
database = try DatabaseQueue(named: name)
} else {
database = try DatabaseQueue()
}
var migrator = DatabaseMigrator()
migrator.registerMigration("Up") { db in
try db.create(table: "records") { table in
table.column("id", .integer).primaryKey(autoincrement: true)
}
for index in 1...3 {
_ = try Record(id: index).inserted(db)
}
try migrator.migrate(database)
return database
}
try migrator.migrate(database)
return database
}
}