PromtGarageMac / Tests /PromptGarageCoreTests /DatabaseSchemaTests.swift
smlflg's picture
Initial public upload from Projekte/PromtGarageMac
4977db2 verified
Raw History Blame Contribute Delete
4.63 kB
import Foundation
import GRDB
import XCTest
@testable import PromptGarageCore
final class DatabaseSchemaTests: XCTestCase {
private func makeDatabaseQueue() throws -> DatabaseQueue {
let directory = FileManager.default.temporaryDirectory
.appendingPathComponent("PromptGarageTests-\(UUID().uuidString)", isDirectory: true)
try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
addTeardownBlock {
try? FileManager.default.removeItem(at: directory)
}
return try DatabaseQueue(path: directory.appendingPathComponent("prompts.db").path)
}
func testSchemaCreationAndValidationAreIdempotent() throws {
let queue = try makeDatabaseQueue()
try queue.write { db in
try DatabaseSchema.createIfNeeded(in: db)
try DatabaseSchema.createIfNeeded(in: db)
}
let report = try DatabaseSchema.validate(queue)
XCTAssertEqual(report.integrity, "ok")
XCTAssertEqual(report.promptCount, 0)
XCTAssertEqual(report.ftsCount, 0)
}
func testFTSTriggersFollowInsertUpdateAndDelete() throws {
let queue = try makeDatabaseQueue()
try queue.write { db in
try DatabaseSchema.createIfNeeded(in: db)
try db.execute(
sql: "INSERT INTO prompts (title, content, tags) VALUES (?, ?, ?)",
arguments: ["Swift Search", "prefix matching with SQLite", "swift,search"]
)
}
var counts = try queue.read { db in
(
try Int.fetchOne(db, sql: "SELECT COUNT(*) FROM prompts") ?? -1,
try Int.fetchOne(db, sql: "SELECT COUNT(*) FROM prompts_fts") ?? -1
)
}
XCTAssertEqual(counts.0, 1)
XCTAssertEqual(counts.1, 1)
try queue.write { db in
try db.execute(sql: "UPDATE prompts SET content = ? WHERE id = 1", arguments: ["updated text"])
}
let updatedContent = try queue.read { db in
try String.fetchOne(db, sql: "SELECT content FROM prompts_fts WHERE rowid = 1")
}
XCTAssertEqual(updatedContent, "updated text")
try queue.write { db in
try db.execute(sql: "DELETE FROM prompts WHERE id = 1")
}
counts = try queue.read { db in
(
try Int.fetchOne(db, sql: "SELECT COUNT(*) FROM prompts") ?? -1,
try Int.fetchOne(db, sql: "SELECT COUNT(*) FROM prompts_fts") ?? -1
)
}
XCTAssertEqual(counts.0, 0)
XCTAssertEqual(counts.1, 0)
}
func testValidationRejectsDatabaseWithoutPromptSchema() throws {
let queue = try makeDatabaseQueue()
try queue.write { db in
try db.execute(sql: "CREATE TABLE unrelated (id INTEGER PRIMARY KEY)")
}
XCTAssertThrowsError(try DatabaseSchema.validate(queue)) { error in
XCTAssertEqual(error as? DatabaseValidationError, .missingTables)
}
}
func testRepairRebuildsStaleExternalContentFTSIndex() throws {
let queue = try makeDatabaseQueue()
try queue.write { db in
try DatabaseSchema.createIfNeeded(in: db)
try db.execute(
sql: "INSERT INTO prompts (title, content, tags) VALUES (?, ?, ?)",
arguments: ["Swift title", "native search", "swift"]
)
try db.execute(
sql: """
INSERT INTO prompts_fts(prompts_fts, rowid, title, content, tags)
VALUES('delete', 1, 'Swift title', 'native search', 'swift')
"""
)
}
// External-content FTS count mirrors `prompts`, even though MATCH is
// stale. This is the exact failure that plain row parity misses.
let before = try queue.read { db in
(
try Int.fetchOne(db, sql: "SELECT COUNT(*) FROM prompts_fts") ?? -1,
try Int.fetchOne(
db,
sql: "SELECT COUNT(*) FROM prompts_fts WHERE prompts_fts MATCH 'swift'"
) ?? -1
)
}
XCTAssertEqual(before.0, 1)
XCTAssertEqual(before.1, 0)
try queue.write { db in
try DatabaseSchema.repairSearchIndexIfNeeded(in: db)
}
let matches = try queue.read { db in
try Int.fetchOne(
db,
sql: "SELECT COUNT(*) FROM prompts_fts WHERE prompts_fts MATCH 'swift'"
)
}
XCTAssertEqual(matches, 1)
}
}