Refactor entire codebase and rewrite documentation

This commit is contained in:
2025-10-10 18:06:34 +03:00
parent b4e9755c15
commit 8e471f2b9f
74 changed files with 3405 additions and 4149 deletions

View File

@@ -17,15 +17,4 @@ struct ConnectionLocationTests {
let temporaryLocation = Connection.Location.temporary
#expect(temporaryLocation.path == "")
}
@Test func testFileLocationInitialization() {
let filePath = "/path/to/database.db"
let location = Connection.Location.file(path: filePath)
switch location {
case .file(let path):
#expect(path == filePath)
default:
Issue.record("Expected `.file` case but got \(location)")
}
}
}

View File

@@ -101,7 +101,7 @@ struct ConnectionTests {
""")
#expect(
throws: Connection.Error(
throws: SQLiteError(
code: SQLITE_BUSY,
message: "database is locked"
),
@@ -229,7 +229,7 @@ struct ConnectionTests {
try connection.add(function: function)
try connection.remove(function: function)
#expect(
throws: Connection.Error(
throws: SQLiteError(
code: SQLITE_ERROR,
message: "no such function: \(name)"
),
@@ -250,7 +250,7 @@ private extension ConnectionTests {
[.deterministic, .innocuous]
}
override class func invoke(args: Arguments) throws -> SQLiteRawRepresentable? {
override class func invoke(args: any ArgumentsProtocol) throws -> SQLiteRepresentable? {
args[0].description
}
}
@@ -264,13 +264,13 @@ private extension ConnectionTests {
private var count: Int = 0
override func step(args: Arguments) throws {
override func step(args: any ArgumentsProtocol) throws {
if args[0] != .null {
count += 1
}
}
override func finalize() throws -> SQLiteRawRepresentable? {
override func finalize() throws -> SQLiteRepresentable? {
count
}
}

View File

@@ -1,45 +1,41 @@
import Foundation
import Testing
import DataLiteCore
import DataLiteC
import DataLiteCore
struct StatementOptionsTests {
@Test func testOptionsInitialization() {
let options: Statement.Options = [.persistent]
#expect(options.contains(.persistent))
#expect(options.contains(.noVtab) == false)
}
@Test func testOptionsCombination() {
var options: Statement.Options = [.persistent]
#expect(options.contains(.persistent))
#expect(options.contains(.noVtab) == false)
options.insert(.noVtab)
#expect(options.contains(.persistent))
#expect(options.contains(.noVtab))
}
@Test func testOptionsRemoval() {
var options: Statement.Options = [.persistent, .noVtab]
#expect(options.contains(.persistent))
#expect(options.contains(.noVtab))
options.remove(.noVtab)
#expect(options.contains(.persistent))
#expect(options.contains(.noVtab) == false)
}
@Test func testOptionsRawValue() {
let options: Statement.Options = [.persistent, .noVtab]
let rawOpts = UInt32(SQLITE_PREPARE_PERSISTENT | SQLITE_PREPARE_NO_VTAB)
#expect(options.rawValue == rawOpts)
@Test func testPersistentOptions() {
#expect(Statement.Options.persistent.rawValue == UInt32(SQLITE_PREPARE_PERSISTENT))
}
@Test func testNoVtabOptions() {
#expect(Statement.Options.noVtab.rawValue == UInt32(SQLITE_PREPARE_NO_VTAB))
}
@Test func testCombineOptions() {
let options: Statement.Options = [.persistent, .noVtab]
let expected = UInt32(SQLITE_PREPARE_PERSISTENT | SQLITE_PREPARE_NO_VTAB)
#expect(options.contains(.persistent))
#expect(options.contains(.noVtab))
#expect(options.rawValue == expected)
}
@Test func testInitWithUInt32RawValue() {
let raw = UInt32(SQLITE_PREPARE_PERSISTENT)
let options = Statement.Options(rawValue: raw)
#expect(options == .persistent)
}
@Test func testInitWithInt32RawValue() {
let raw = Int32(SQLITE_PREPARE_NO_VTAB)
let options = Statement.Options(rawValue: raw)
#expect(options == .noVtab)
}
@Test func testEmptySetRawValueIsZero() {
let empty: Statement.Options = []
#expect(empty.rawValue == 0)
#expect(!empty.contains(.persistent))
#expect(!empty.contains(.noVtab))
}
}

View File

@@ -1,135 +1,240 @@
import XCTest
import Foundation
import Testing
import DataLiteC
@testable import DataLiteCore
final class StatementTests: XCTestCase {
private let databasePath = FileManager.default.temporaryDirectory.appendingPathComponent("test.db").path
private var connection: OpaquePointer!
final class StatementTests {
let connection: OpaquePointer
override func setUpWithError() throws {
try super.setUpWithError()
XCTAssertEqual(
sqlite3_open(databasePath, &connection),
SQLITE_OK,
"Failed to open database"
init() {
var connection: OpaquePointer! = nil
let opts = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE
sqlite3_open_v2(":memory:", &connection, opts, nil)
sqlite3_exec(
connection,
"""
CREATE TABLE t(
id INTEGER PRIMARY KEY,
n INTEGER,
r REAL,
s TEXT,
b BLOB
);
""", nil, nil, nil
)
XCTAssertEqual(
sqlite3_exec(
connection,
"""
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT,
age INTEGER
);
""",
nil, nil, nil
self.connection = connection
}
deinit {
sqlite3_close_v2(connection)
}
@Test func testInitWithError() throws {
#expect(
throws: SQLiteError(
code: SQLITE_ERROR,
message: "no such table: invalid"
),
SQLITE_OK,
"Failed to create table"
performing: {
try Statement(
db: connection,
sql: "SELECT * FROM invalid",
options: []
)
}
)
}
override func tearDownWithError() throws {
sqlite3_close(connection)
try FileManager.default.removeItem(atPath: databasePath)
try super.tearDownWithError()
@Test func testParameterCount() throws {
let sql = "SELECT * FROM t WHERE id = ? AND s = ?"
let stmt = try Statement(db: connection, sql: sql, options: [])
#expect(stmt.parameterCount() == 2)
}
func testMixBindings() throws {
do {
let sql = "INSERT INTO users (name, age) VALUES (?, ?)"
let stmt = try Statement(db: connection, sql: sql, options: [])
try stmt.bind("Alice", at: 1)
try stmt.bind(88, at: 2)
XCTAssertFalse(try stmt.step())
}
do {
let sql = "SELECT * FROM users WHERE age = ? AND name = $name"
let stmt = try Statement(db: connection, sql: sql, options: [])
try stmt.bind(88, at: 1)
try stmt.bind("Alice", at: stmt.bind(parameterIndexBy: "$name"))
XCTAssertTrue(try stmt.step())
XCTAssertEqual(stmt.columnValue(at: 1), "Alice")
XCTAssertEqual(stmt.columnValue(at: 2), 88)
}
@Test func testZeroParameterCount() throws {
let sql = "SELECT * FROM t"
let stmt = try Statement(db: connection, sql: sql, options: [])
#expect(stmt.parameterCount() == 0)
}
func testStatementInitialization() throws {
let sql = "INSERT INTO users (name, age) VALUES (?, ?)"
let statement = try Statement(db: connection, sql: sql, options: [.persistent])
XCTAssertNotNil(statement, "Statement should not be nil")
@Test func testParameterIndexByName() throws {
let sql = "SELECT * FROM t WHERE id = :id AND s = :s"
let stmt = try Statement(db: connection, sql: sql, options: [])
#expect(stmt.parameterIndexBy(":id") == 1)
#expect(stmt.parameterIndexBy(":s") == 2)
#expect(stmt.parameterIndexBy(":invalid") == 0)
}
func testBindAndExecute() throws {
let sql = "INSERT INTO users (name, age) VALUES (?, ?)"
let statement = try Statement(db: connection, sql: sql, options: [.persistent])
try statement.bind("Alice", at: 1)
try statement.bind(30, at: 2)
XCTAssertEqual(statement.bindParameterCount(), 2)
XCTAssertFalse(try statement.step())
let query = "SELECT * FROM users WHERE name = ?"
let queryStatement = try Statement(db: connection, sql: query, options: [.persistent])
try queryStatement.bind("Alice", at: 1)
XCTAssertTrue(try queryStatement.step(), "Failed to execute SELECT query")
XCTAssertEqual(queryStatement.columnValue(at: 1), "Alice")
XCTAssertEqual(queryStatement.columnValue(at: 2), 30)
@Test func testParameterNameByIndex() throws {
let sql = "SELECT * FROM t WHERE id = :id AND s = :s"
let stmt = try Statement(db: connection, sql: sql, options: [])
#expect(stmt.parameterNameBy(1) == ":id")
#expect(stmt.parameterNameBy(2) == ":s")
#expect(stmt.parameterNameBy(3) == nil)
}
func testClearBindings() throws {
let sql = "INSERT INTO users (name, age) VALUES (?, ?)"
let statement = try Statement(db: connection, sql: sql, options: [.persistent])
try statement.bind("Bob", at: 1)
try statement.bind(25, at: 2)
try statement.clearBindings()
XCTAssertFalse(try statement.step())
@Test func testBindValueAtIndex() throws {
let sql = "SELECT * FROM t where id = ?"
let stmt = try Statement(db: connection, sql: sql, options: [])
try stmt.bind(.int(42), at: 1)
try stmt.bind(.real(42), at: 1)
try stmt.bind(.text("42"), at: 1)
try stmt.bind(.blob(Data([0x42])), at: 1)
try stmt.bind(.null, at: 1)
try stmt.bind(TestValue(value: 42), at: 1)
try stmt.bind(TestValue?.none, at: 1)
}
func testResetStatement() throws {
let sql = "INSERT INTO users (name, age) VALUES (?, ?)"
let statement = try Statement(db: connection, sql: sql, options: [.persistent])
try statement.bind("Charlie", at: 1)
try statement.bind(40, at: 2)
try statement.step()
// Reset the statement and try executing it again with new values
try statement.reset()
try statement.bind("Dave", at: 1)
try statement.bind(45, at: 2)
XCTAssertEqual(statement.bindParameterCount(), 2)
XCTAssertFalse(try statement.step())
// Check if the record was actually inserted
let query = "SELECT * FROM users WHERE name = ?"
let queryStatement = try Statement(db: connection, sql: query, options: [.persistent])
try queryStatement.bind("Dave", at: 1)
XCTAssertTrue(try queryStatement.step(), "Failed to execute SELECT query")
XCTAssertEqual(queryStatement.columnValue(at: 1), "Dave")
XCTAssertEqual(queryStatement.columnValue(at: 2), 45)
@Test func testErrorBindValueAtIndex() throws {
let sql = "SELECT * FROM t where id = ?"
let stmt = try Statement(db: connection, sql: sql, options: [])
#expect(
throws: SQLiteError(
code: SQLITE_RANGE,
message: "column index out of range"
),
performing: {
try stmt.bind(.null, at: 0)
}
)
}
func testColumnValues() throws {
let sql = "INSERT INTO users (name, age) VALUES (?, ?)"
let statement = try Statement(db: connection, sql: sql, options: [.persistent])
try statement.bind("Eve", at: 1)
try statement.bind(28, at: 2)
try statement.step()
@Test func testBindValueByName() throws {
let sql = "SELECT * FROM t where id = :id"
let stmt = try Statement(db: connection, sql: sql, options: [])
try stmt.bind(.int(42), by: ":id")
try stmt.bind(.real(42), by: ":id")
try stmt.bind(.text("42"), by: ":id")
try stmt.bind(.blob(Data([0x42])), by: ":id")
try stmt.bind(.null, by: ":id")
try stmt.bind(TestValue(value: 42), by: ":id")
try stmt.bind(TestValue?.none, by: ":id")
}
@Test func testErrorBindValueByName() throws {
let sql = "SELECT * FROM t where id = :id"
let stmt = try Statement(db: connection, sql: sql, options: [])
#expect(
throws: SQLiteError(
code: SQLITE_RANGE,
message: "column index out of range"
),
performing: {
try stmt.bind(.null, by: ":invalid")
}
)
}
@Test func testStepOneRow() throws {
let sql = "SELECT 1 where 1"
let stmt = try Statement(db: connection, sql: sql, options: [])
#expect(try stmt.step())
#expect(try stmt.step() == false)
}
@Test func testStepMultipleRows() throws {
sqlite3_exec(connection, "INSERT INTO t(n) VALUES (1),(2),(3)", nil, nil, nil)
let sql = "SELECT id FROM t ORDER BY id"
let stmt = try Statement(db: connection, sql: sql, options: [])
#expect(try stmt.step())
#expect(try stmt.step())
#expect(try stmt.step())
#expect(try stmt.step() == false)
}
@Test func testStepNoRows() throws {
let sql = "SELECT 1 WHERE 0"
let stmt = try Statement(db: connection, sql: sql, options: [])
#expect(try stmt.step() == false)
}
@Test func testStepWithError() throws {
sqlite3_exec(connection, "INSERT INTO t(id, n) VALUES (1, 10)", nil, nil, nil)
let sql = "INSERT INTO t(id, n) VALUES (?, ?)"
let stmt = try Statement(db: connection, sql: sql, options: [])
try stmt.bind(.int(1), at: 1)
try stmt.bind(.int(20), at: 2)
#expect(
throws: SQLiteError(
code: 1555,
message: "UNIQUE constraint failed: t.id"
),
performing: {
try stmt.step()
}
)
}
@Test func testColumnCount() throws {
let sql = "SELECT * FROM t"
let stmt = try Statement(db: connection, sql: sql, options: [])
#expect(stmt.columnCount() == 5)
}
@Test func testColumnName() throws {
let sql = "SELECT * FROM t"
let stmt = try Statement(db: connection, sql: sql, options: [])
#expect(stmt.columnName(at: 0) == "id")
#expect(stmt.columnName(at: 1) == "n")
#expect(stmt.columnName(at: 2) == "r")
#expect(stmt.columnName(at: 3) == "s")
#expect(stmt.columnName(at: 4) == "b")
}
@Test func testColumnValueAtIndex() throws {
sqlite3_exec(connection, """
INSERT INTO t (id, n, r, s, b)
VALUES (10, 42, 3.5, 'hello', x'DEADBEEF')
""", nil, nil, nil
)
// Perform a SELECT query and check column data types
let query = "SELECT * FROM users WHERE name = ?"
let queryStatement = try Statement(db: connection, sql: query, options: [.persistent])
try queryStatement.bind("Eve", at: 1)
let sql = "SELECT * FROM t WHERE id = 10"
let stmt = try Statement(db: connection, sql: sql, options: [])
XCTAssertTrue(try queryStatement.step(), "Failed to execute SELECT query")
XCTAssertEqual(queryStatement.columnType(at: 1), .text)
XCTAssertEqual(queryStatement.columnType(at: 2), .int)
XCTAssertEqual(queryStatement.columnValue(at: 1), "Eve")
XCTAssertEqual(queryStatement.columnValue(at: 2), 28)
#expect(try stmt.step())
#expect(stmt.columnValue(at: 0) == .int(10))
#expect(stmt.columnValue(at: 1) == .int(42))
#expect(stmt.columnValue(at: 1) == TestValue(value: 42))
#expect(stmt.columnValue(at: 2) == .real(3.5))
#expect(stmt.columnValue(at: 3) == .text("hello"))
#expect(stmt.columnValue(at: 4) == .blob(Data([0xDE, 0xAD, 0xBE, 0xEF])))
}
@Test func testColumnNullValueAtIndex() throws {
sqlite3_exec(connection, """
INSERT INTO t (id) VALUES (10)
""", nil, nil, nil
)
let sql = "SELECT * FROM t WHERE id = 10"
let stmt = try Statement(db: connection, sql: sql, options: [])
#expect(try stmt.step())
#expect(stmt.columnValue(at: 0) == .int(10))
#expect(stmt.columnValue(at: 1) == .null)
#expect(stmt.columnValue(at: 1) == TestValue?.none)
}
}
private extension StatementTests {
struct TestValue: SQLiteRepresentable, Equatable {
let value: Int
var sqliteValue: SQLiteValue {
.int(Int64(value))
}
init(value: Int) {
self.value = value
}
init?(_ value: SQLiteValue) {
if case .int(let intValue) = value {
self.value = Int(intValue)
} else {
return nil
}
}
}
}

View File

@@ -1,27 +0,0 @@
import Testing
import DataLiteC
import DataLiteCore
struct SQLiteRawTypeTests {
@Test func testInitializationFromRawValue() {
#expect(SQLiteRawType(rawValue: SQLITE_INTEGER) == .int)
#expect(SQLiteRawType(rawValue: SQLITE_FLOAT) == .real)
#expect(SQLiteRawType(rawValue: SQLITE_TEXT) == .text)
#expect(SQLiteRawType(rawValue: SQLITE_BLOB) == .blob)
#expect(SQLiteRawType(rawValue: SQLITE_NULL) == .null)
#expect(SQLiteRawType(rawValue: -1) == nil)
}
@Test func testRawValue() {
#expect(SQLiteRawType.int.rawValue == SQLITE_INTEGER)
#expect(SQLiteRawType.real.rawValue == SQLITE_FLOAT)
#expect(SQLiteRawType.text.rawValue == SQLITE_TEXT)
#expect(SQLiteRawType.blob.rawValue == SQLITE_BLOB)
#expect(SQLiteRawType.null.rawValue == SQLITE_NULL)
}
@Test func testInvalidRawValue() {
let invalidRawValue: Int32 = 9999
#expect(SQLiteRawType(rawValue: invalidRawValue) == nil)
}
}

View File

@@ -1,36 +0,0 @@
import Testing
import Foundation
import DataLiteCore
struct SQLiteRawValueTests {
@Test func testIntValue() {
let value = SQLiteRawValue.int(42)
#expect(value.description == "42")
}
@Test func testRealValue() {
let value = SQLiteRawValue.real(3.14)
#expect(value.description == "3.14")
}
@Test func testTextValue() {
let value = SQLiteRawValue.text("Hello, World!")
#expect(value.description == "'Hello, World!'")
}
@Test func testTextValueWithSingleQuote() {
let value = SQLiteRawValue.text("O'Reilly")
#expect(value.description == "'O''Reilly'") // Escaped single quote
}
@Test func testBlobValue() {
let data = Data([0xDE, 0xAD, 0xBE, 0xEF])
let value = SQLiteRawValue.blob(data)
#expect(value.description == "X'DEADBEEF'")
}
@Test func testNullValue() {
let value = SQLiteRawValue.null
#expect(value.description == "NULL")
}
}

View File

@@ -0,0 +1,49 @@
import Foundation
import Testing
import DataLiteCore
struct SQLiteValueTests {
@Test(arguments: [1, 42, 1234])
func testSQLiteIntValue(_ value: Int64) {
let value = SQLiteValue.int(value)
#expect(value.sqliteLiteral == "\(value)")
#expect(value.description == value.sqliteLiteral)
}
@Test(arguments: [12, 0.5, 123.99])
func testSQLiteRealValue(_ value: Double) {
let value = SQLiteValue.real(value)
#expect(value.sqliteLiteral == "\(value)")
#expect(value.description == value.sqliteLiteral)
}
@Test(arguments: [
("", "''"),
("'hello'", "'''hello'''"),
("hello", "'hello'"),
("O'Reilly", "'O''Reilly'"),
("It's John's \"book\"", "'It''s John''s \"book\"'")
])
func testSQLiteTextValue(_ value: String, _ expected: String) {
let value = SQLiteValue.text(value)
#expect(value.sqliteLiteral == expected)
#expect(value.description == value.sqliteLiteral)
}
@Test(arguments: [
(Data(), "X''"),
(Data([0x00]), "X'00'"),
(Data([0x00, 0xAB, 0xCD]), "X'00ABCD'")
])
func testSQLiteBlobValue(_ value: Data, _ expected: String) {
let value = SQLiteValue.blob(value)
#expect(value.sqliteLiteral == expected)
#expect(value.description == value.sqliteLiteral)
}
@Test func testSQLiteNullValue() {
let value = SQLiteValue.null
#expect(value.sqliteLiteral == "NULL")
#expect(value.description == value.sqliteLiteral)
}
}

View File

@@ -4,46 +4,46 @@ import DataLiteCore
struct BinaryFloatingPointTests {
@Test func testFloatToSQLiteRawValue() {
let floatValue: Float = 3.14
let rawValue = floatValue.sqliteRawValue
let rawValue = floatValue.sqliteValue
#expect(rawValue == .real(Double(floatValue)))
}
@Test func testDoubleToSQLiteRawValue() {
let doubleValue: Double = 3.14
let rawValue = doubleValue.sqliteRawValue
let rawValue = doubleValue.sqliteValue
#expect(rawValue == .real(doubleValue))
}
@Test func testFloatInitializationFromSQLiteRawValue() {
let realValue: SQLiteRawValue = .real(3.14)
let realValue: SQLiteValue = .real(3.14)
let floatValue = Float(realValue)
#expect(floatValue != nil)
#expect(floatValue == 3.14)
let intValue: SQLiteRawValue = .int(42)
let intValue: SQLiteValue = .int(42)
let floatFromInt = Float(intValue)
#expect(floatFromInt != nil)
#expect(floatFromInt == 42.0)
}
@Test func testDoubleInitializationFromSQLiteRawValue() {
let realValue: SQLiteRawValue = .real(3.14)
let realValue: SQLiteValue = .real(3.14)
let doubleValue = Double(realValue)
#expect(doubleValue != nil)
#expect(doubleValue == 3.14)
let intValue: SQLiteRawValue = .int(42)
let intValue: SQLiteValue = .int(42)
let doubleFromInt = Double(intValue)
#expect(doubleFromInt != nil)
#expect(doubleFromInt == 42.0)
}
@Test func testInitializationFailureFromInvalidSQLiteRawValue() {
let nullValue: SQLiteRawValue = .null
let nullValue: SQLiteValue = .null
#expect(Float(nullValue) == nil)
#expect(Double(nullValue) == nil)
let textValue: SQLiteRawValue = .text("Invalid")
let textValue: SQLiteValue = .text("Invalid")
#expect(Float(textValue) == nil)
#expect(Double(textValue) == nil)
}

View File

@@ -3,38 +3,38 @@ import Foundation
import DataLiteCore
struct BinaryIntegerTests {
@Test func testIntegerToSQLiteRawValue() {
#expect(Int(42).sqliteRawValue == .int(42))
#expect(Int8(42).sqliteRawValue == .int(42))
#expect(Int16(42).sqliteRawValue == .int(42))
#expect(Int32(42).sqliteRawValue == .int(42))
#expect(Int64(42).sqliteRawValue == .int(42))
@Test func testIntegerToSQLiteValue() {
#expect(Int(42).sqliteValue == .int(42))
#expect(Int8(42).sqliteValue == .int(42))
#expect(Int16(42).sqliteValue == .int(42))
#expect(Int32(42).sqliteValue == .int(42))
#expect(Int64(42).sqliteValue == .int(42))
#expect(UInt(42).sqliteRawValue == .int(42))
#expect(UInt8(42).sqliteRawValue == .int(42))
#expect(UInt16(42).sqliteRawValue == .int(42))
#expect(UInt32(42).sqliteRawValue == .int(42))
#expect(UInt64(42).sqliteRawValue == .int(42))
#expect(UInt(42).sqliteValue == .int(42))
#expect(UInt8(42).sqliteValue == .int(42))
#expect(UInt16(42).sqliteValue == .int(42))
#expect(UInt32(42).sqliteValue == .int(42))
#expect(UInt64(42).sqliteValue == .int(42))
}
@Test func testIntegerInitializationFromSQLiteRawValue() {
#expect(Int(SQLiteRawValue.int(42)) == 42)
#expect(Int8(SQLiteRawValue.int(42)) == 42)
#expect(Int16(SQLiteRawValue.int(42)) == 42)
#expect(Int32(SQLiteRawValue.int(42)) == 42)
#expect(Int64(SQLiteRawValue.int(42)) == 42)
@Test func testIntegerInitializationFromSQLiteValue() {
#expect(Int(SQLiteValue.int(42)) == 42)
#expect(Int8(SQLiteValue.int(42)) == 42)
#expect(Int16(SQLiteValue.int(42)) == 42)
#expect(Int32(SQLiteValue.int(42)) == 42)
#expect(Int64(SQLiteValue.int(42)) == 42)
#expect(UInt(SQLiteRawValue.int(42)) == 42)
#expect(UInt8(SQLiteRawValue.int(42)) == 42)
#expect(UInt16(SQLiteRawValue.int(42)) == 42)
#expect(UInt32(SQLiteRawValue.int(42)) == 42)
#expect(UInt64(SQLiteRawValue.int(42)) == 42)
#expect(UInt(SQLiteValue.int(42)) == 42)
#expect(UInt8(SQLiteValue.int(42)) == 42)
#expect(UInt16(SQLiteValue.int(42)) == 42)
#expect(UInt32(SQLiteValue.int(42)) == 42)
#expect(UInt64(SQLiteValue.int(42)) == 42)
}
@Test func testInvalidIntegerInitialization() {
#expect(Int(SQLiteRawValue.real(3.14)) == nil)
#expect(Int8(SQLiteRawValue.text("test")) == nil)
#expect(UInt32(SQLiteRawValue.blob(Data([0x01, 0x02]))) == nil)
#expect(Int(SQLiteValue.real(3.14)) == nil)
#expect(Int8(SQLiteValue.text("test")) == nil)
#expect(UInt32(SQLiteValue.blob(Data([0x01, 0x02]))) == nil)
// Out-of-range conversion
let largeValue = Int64.max

View File

@@ -4,8 +4,8 @@ import DataLiteCore
struct BoolTests {
@Test func testBoolToSQLiteRawValue() {
#expect(true.sqliteRawValue == .int(1))
#expect(false.sqliteRawValue == .int(0))
#expect(true.sqliteValue == .int(1))
#expect(false.sqliteValue == .int(0))
}
@Test func testSQLiteRawValueToBool() {

View File

@@ -5,12 +5,12 @@ import DataLiteCore
struct DataSQLiteRawRepresentableTests {
@Test func testDataToSQLiteRawValue() {
let data = Data([0x01, 0x02, 0x03])
#expect(data.sqliteRawValue == .blob(data))
#expect(data.sqliteValue == .blob(data))
}
@Test func testSQLiteRawValueToData() {
let data = Data([0x01, 0x02, 0x03])
let rawValue = SQLiteRawValue.blob(data)
let rawValue = SQLiteValue.blob(data)
#expect(Data(rawValue) == data)

View File

@@ -8,7 +8,7 @@ struct DateSQLiteRawRepresentableTests {
let formatter = ISO8601DateFormatter()
let dateString = formatter.string(from: date)
#expect(date.sqliteRawValue == .text(dateString))
#expect(date.sqliteValue == .text(dateString))
}
@Test func testSQLiteRawValueToDate() {
@@ -16,13 +16,13 @@ struct DateSQLiteRawRepresentableTests {
let formatter = ISO8601DateFormatter()
let dateString = formatter.string(from: date)
let rawText = SQLiteRawValue.text(dateString)
let rawText = SQLiteValue.text(dateString)
#expect(Date(rawText) == date)
let rawInt = SQLiteRawValue.int(1609459200)
let rawInt = SQLiteValue.int(1609459200)
#expect(Date(rawInt) == date)
let rawReal = SQLiteRawValue.real(1609459200)
let rawReal = SQLiteValue.real(1609459200)
#expect(Date(rawReal) == date)
#expect(Date(.blob(Data([0x01, 0x02, 0x03]))) == nil)

View File

@@ -5,7 +5,7 @@ import DataLiteCore
struct RawRepresentableTests {
@Test func testRawRepresentableToSQLiteRawValue() {
let color: Color = .green
#expect(color.sqliteRawValue == .int(1))
#expect(color.sqliteValue == .int(1))
}
@Test func testSQLiteRawValueToRawRepresentable() {
@@ -19,7 +19,7 @@ struct RawRepresentableTests {
}
private extension RawRepresentableTests {
enum Color: Int, SQLiteRawRepresentable {
enum Color: Int, SQLiteRepresentable {
case red
case green
case blue

View File

@@ -4,14 +4,14 @@ import DataLiteCore
struct StringTests {
@Test func testStringToSQLiteRawValue() {
#expect("Hello, SQLite!".sqliteRawValue == .text("Hello, SQLite!"))
#expect("Hello, SQLite!".sqliteValue == .text("Hello, SQLite!"))
}
@Test func testSQLiteRawValueToString() {
#expect(String(SQLiteRawValue.text("Hello, SQLite!")) == "Hello, SQLite!")
#expect(String(SQLiteValue.text("Hello, SQLite!")) == "Hello, SQLite!")
#expect(String(SQLiteRawValue.int(42)) == nil)
#expect(String(SQLiteRawValue.blob(Data([0x01, 0x02]))) == nil)
#expect(String(SQLiteRawValue.null) == nil)
#expect(String(SQLiteValue.int(42)) == nil)
#expect(String(SQLiteValue.blob(Data([0x01, 0x02]))) == nil)
#expect(String(SQLiteValue.null) == nil)
}
}

View File

@@ -5,11 +5,11 @@ import DataLiteCore
struct UUIDTests {
@Test func testUUIDToSQLiteRawValue() {
let uuid = UUID(uuidString: "123e4567-e89b-12d3-a456-426614174000")!
#expect(uuid.sqliteRawValue == .text("123E4567-E89B-12D3-A456-426614174000"))
#expect(uuid.sqliteValue == .text("123E4567-E89B-12D3-A456-426614174000"))
}
@Test func testSQLiteRawValueToUUID() {
let raw = SQLiteRawValue.text("123e4567-e89b-12d3-a456-426614174000")
let raw = SQLiteValue.text("123e4567-e89b-12d3-a456-426614174000")
#expect(UUID(raw) == UUID(uuidString: "123e4567-e89b-12d3-a456-426614174000"))
#expect(UUID(.text("invalid-uuid-string")) == nil)

View File

@@ -0,0 +1,22 @@
import Foundation
import Testing
import DataLiteCore
private struct BindableStub: SQLiteBindable {
let value: SQLiteValue
var sqliteValue: SQLiteValue { value }
}
struct SQLiteBindableTests {
@Test(arguments: [
SQLiteValue.int(42),
SQLiteValue.real(0.5),
SQLiteValue.text("O'Reilly"),
SQLiteValue.blob(Data([0x00, 0xAB])),
SQLiteValue.null
])
func testDefaultSqliteLiteralPassThrough(_ value: SQLiteValue) {
let stub = BindableStub(value: value)
#expect(stub.sqliteLiteral == value.sqliteLiteral)
}
}

View File

@@ -3,26 +3,26 @@ import Testing
import DataLiteC
@testable import DataLiteCore
struct ConnectionErrorTests {
struct SQLiteErrorTests {
@Test func testInitWithConnection() {
var db: OpaquePointer? = nil
defer { sqlite3_close(db) }
sqlite3_open(":memory:", &db)
sqlite3_exec(db, "INVALID SQL", nil, nil, nil)
let error = Connection.Error(db!)
let error = SQLiteError(db!)
#expect(error.code == SQLITE_ERROR)
#expect(error.message == "near \"INVALID\": syntax error")
}
@Test func testInitWithCodeAndMessage() {
let error = Connection.Error(code: 1, message: "Test Error Message")
let error = SQLiteError(code: 1, message: "Test Error Message")
#expect(error.code == 1)
#expect(error.message == "Test Error Message")
}
@Test func testDescription() {
let error = Connection.Error(code: 1, message: "Test Error Message")
#expect(error.description == "Connection.Error code: 1 message: Test Error Message")
let error = SQLiteError(code: 1, message: "Test Error Message")
#expect(error.description == "SQLiteError code: 1 message: Test Error Message")
}
}

View File

@@ -26,7 +26,7 @@ final class SQLiteRowTests: XCTestCase {
XCTAssertEqual(row["name"], .text("Alice"))
XCTAssertNil(row["age"])
row["age"] = SQLiteRawValue.int(30)
row["age"] = SQLiteValue.int(30)
XCTAssertEqual(row["age"], .int(30))
}