Files
UUVPN/iOS-SwiftUI-Code/GRDB.swift-6.29.3/Tests/GRDBTests/DatabaseQueueReleaseMemoryTests.swift
T

146 lines
4.8 KiB
Swift

import XCTest
@testable import GRDB
class DatabaseQueueReleaseMemoryTests: GRDBTestCase {
func testDatabaseQueueDeinitClosesConnection() throws {
let countQueue = DispatchQueue(label: "GRDB")
var openConnectionCount = 0
var totalOpenConnectionCount = 0
dbConfiguration.SQLiteConnectionDidOpen = {
countQueue.sync {
totalOpenConnectionCount += 1
openConnectionCount += 1
}
}
dbConfiguration.SQLiteConnectionDidClose = {
countQueue.sync {
openConnectionCount -= 1
}
}
do {
// Open & release connection
_ = try makeDatabaseQueue()
}
// One reader, one writer
XCTAssertEqual(totalOpenConnectionCount, 1)
// All connections are closed
XCTAssertEqual(openConnectionCount, 0)
}
func testBlocksRetainConnection() throws {
let countQueue = DispatchQueue(label: "GRDB")
var openConnectionCount = 0
var totalOpenConnectionCount = 0
dbConfiguration.SQLiteConnectionDidOpen = {
countQueue.sync {
totalOpenConnectionCount += 1
openConnectionCount += 1
}
}
dbConfiguration.SQLiteConnectionDidClose = {
countQueue.sync {
openConnectionCount -= 1
}
}
// Block 1 Block 2
// inDatabase {
// >
let s1 = DispatchSemaphore(value: 0)
// dbQueue = nil
// >
let s2 = DispatchSemaphore(value: 0)
// use database
// }
let (block1, block2) = { () -> (() -> (), () -> ()) in
var dbQueue: DatabaseQueue? = try! self.makeDatabaseQueue()
try! dbQueue!.write { db in
try db.execute(sql: "CREATE TABLE items (id INTEGER PRIMARY KEY)")
}
let block1 = { () in
_ = s1.wait(timeout: .distantFuture)
dbQueue = nil
s2.signal()
}
let block2 = { [weak dbQueue] () in
if let dbQueue {
try! dbQueue.write { db in
s1.signal()
_ = s2.wait(timeout: .distantFuture)
XCTAssertEqual(try Int.fetchOne(db, sql: "SELECT COUNT(*) FROM items"), 0)
}
} else {
XCTFail("expect non nil dbQueue")
}
}
return (block1, block2)
}()
let blocks = [block1, block2]
DispatchQueue.concurrentPerform(iterations: blocks.count) { index in
blocks[index]()
}
// one writer
XCTAssertEqual(totalOpenConnectionCount, 1)
// All connections are closed
XCTAssertEqual(openConnectionCount, 0)
}
func testStatementDoNotRetainDatabaseConnection() throws {
// Block 1 Block 2
// create statement INSERT
// >
let s1 = DispatchSemaphore(value: 0)
// dbQueue = nil
// >
let s2 = DispatchSemaphore(value: 0)
// dbQueue is nil
let (block1, block2) = { () -> (() -> (), () -> ()) in
var dbQueue: DatabaseQueue? = try! self.makeDatabaseQueue()
let block1 = { () in
_ = s1.wait(timeout: .distantFuture)
dbQueue = nil
s2.signal()
}
let block2 = { [weak dbQueue] () in
var statement: Statement? = nil
do {
if let dbQueue {
do {
try dbQueue.write { db in
statement = try db.makeStatement(sql: "CREATE TABLE items (id INTEGER PRIMARY KEY)")
s1.signal()
}
} catch {
XCTFail("error: \(error)")
}
} else {
XCTFail("expect non nil dbQueue")
}
}
_ = s2.wait(timeout: .distantFuture)
XCTAssertTrue(statement != nil)
XCTAssertTrue(dbQueue == nil)
}
return (block1, block2)
}()
let blocks = [block1, block2]
DispatchQueue.concurrentPerform(iterations: blocks.count) { index in
blocks[index]()
}
}
}