// // SQLitePreferenceStoreTests.swift // // Copyright 2026 Brendan Szymanski // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // SPDX-License-Identifier: GPL-3.0-or-later // import Foundation import Testing @testable import LuminateCore @testable import LuminateStore @Suite struct SQLitePreferenceStoreTests { @Test("A fresh database has schema version one and no preferences") func freshDatabase() throws { let (url, directory) = makeDatabaseURL() defer { try? FileManager.default.removeItem(at: directory) } let store = try SQLitePreferenceStore(url: url) #expect(store.initialSnapshot.isEmpty) let database = try SQLiteDatabase(url: url) #expect(try database.userVersion == 1) } @Test("Queued values survive flush and reopen") func persistsValue() async throws { let (url, directory) = makeDatabaseURL() defer { try? FileManager.default.removeItem(at: directory) } let store = try SQLitePreferenceStore(url: url) store.enqueue("server.url", .text("http://jellyfin.test:8096")) try await store.flush() let reopened = try SQLitePreferenceStore(url: url) #expect(reopened.initialSnapshot["server.url"] == .text("http://jellyfin.test:8096")) } @Test("A nil queued value deletes the stored row") func deletesValue() async throws { let (url, directory) = makeDatabaseURL() defer { try? FileManager.default.removeItem(at: directory) } let store = try SQLitePreferenceStore(url: url) store.enqueue("auth.accessToken", .text("secret")) store.enqueue("auth.accessToken", nil) try await store.flush() let reopened = try SQLitePreferenceStore(url: url) #expect(reopened.initialSnapshot["auth.accessToken"] == nil) } @Test("Every SQLite storage class round trips") func storageClassesRoundTrip() async throws { let (url, directory) = makeDatabaseURL() defer { try? FileManager.default.removeItem(at: directory) } let store = try SQLitePreferenceStore(url: url) let values: [String: StoredPreference] = [ "integer": .integer(42), "real": .real(3.5), "text": .text("value"), "blob": .blob(Data([1, 2, 3])), "emptyBlob": .blob(Data()), "nulText": .text("a\0b"), ] for (key, value) in values { store.enqueue(key, value) } try await store.flush() let reopened = try SQLitePreferenceStore(url: url) #expect(reopened.initialSnapshot == values) } @Test("Writes to one key are applied in submission order") func preservesOrder() async throws { let (url, directory) = makeDatabaseURL() defer { try? FileManager.default.removeItem(at: directory) } let store = try SQLitePreferenceStore(url: url) store.enqueue("server.url", .text("first")) store.enqueue("server.url", .text("second")) try await store.flush() let reopened = try SQLitePreferenceStore(url: url) #expect(reopened.initialSnapshot["server.url"] == .text("second")) } private func makeDatabaseURL() -> (URL, URL) { let directory = FileManager.default.temporaryDirectory .appending(path: "luminate-store-\(UUID().uuidString)", directoryHint: .isDirectory) return (directory.appending(path: "preferences.sqlite"), directory) } }