195 lines
7.8 KiB
Swift
195 lines
7.8 KiB
Swift
import XCTest
|
|
import GRDB
|
|
|
|
class FoundationNSNumberTests: GRDBTestCase {
|
|
|
|
func testNSNumberDatabaseValueToSwiftType() {
|
|
enum Storage {
|
|
case integer
|
|
case double
|
|
}
|
|
|
|
func storage(_ n: NSNumber) -> Storage? {
|
|
switch n.databaseValue.storage {
|
|
case .int64:
|
|
return .integer
|
|
case .double:
|
|
return .double
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// case "c":
|
|
do {
|
|
let number = NSNumber(value: Int8.min + 1)
|
|
XCTAssertEqual(String(cString: number.objCType), "c")
|
|
XCTAssertEqual(storage(number), .integer)
|
|
XCTAssertEqual(Int64.fromDatabaseValue(number.databaseValue), Int64(Int8.min + 1))
|
|
}
|
|
|
|
// case "C":
|
|
do {
|
|
let number = NSNumber(value: UInt8.max - 1)
|
|
// XCTAssertEqual(String(cString: number.objCType), "C") // get "s" instead of "C"
|
|
XCTAssertEqual(storage(number), .integer)
|
|
XCTAssertEqual(Int64.fromDatabaseValue(number.databaseValue), Int64(UInt8.max - 1))
|
|
}
|
|
|
|
// case "s":
|
|
do {
|
|
let number = NSNumber(value: Int16.min + 1)
|
|
XCTAssertEqual(String(cString: number.objCType), "s")
|
|
XCTAssertEqual(storage(number), .integer)
|
|
XCTAssertEqual(Int64.fromDatabaseValue(number.databaseValue), Int64(Int16.min + 1))
|
|
}
|
|
|
|
// case "S":
|
|
do {
|
|
let number = NSNumber(value: UInt16.max - 1)
|
|
// XCTAssertEqual(String(cString: number.objCType), "S") // get "i" instead of "S"
|
|
XCTAssertEqual(storage(number), .integer)
|
|
XCTAssertEqual(Int64.fromDatabaseValue(number.databaseValue), Int64(UInt16.max - 1))
|
|
}
|
|
|
|
// case "i":
|
|
do {
|
|
let number = NSNumber(value: Int32.min + 1)
|
|
XCTAssertEqual(String(cString: number.objCType), "i")
|
|
XCTAssertEqual(storage(number), .integer)
|
|
XCTAssertEqual(Int64.fromDatabaseValue(number.databaseValue), Int64(Int32.min + 1))
|
|
}
|
|
|
|
// case "I":
|
|
do {
|
|
let number = NSNumber(value: UInt32.max - 1)
|
|
// XCTAssertEqual(String(cString: number.objCType), "I") // get "q" instead of "I"
|
|
XCTAssertEqual(storage(number), .integer)
|
|
XCTAssertEqual(Int64.fromDatabaseValue(number.databaseValue), Int64(UInt32.max - 1))
|
|
}
|
|
|
|
// case "l":
|
|
do {
|
|
let number = NSNumber(value: Int.min + 1)
|
|
// XCTAssertEqual(String(cString: number.objCType), "l") // get "q" instead of "l"
|
|
XCTAssertEqual(storage(number), .integer)
|
|
XCTAssertEqual(Int64.fromDatabaseValue(number.databaseValue), Int64(Int.min + 1))
|
|
}
|
|
|
|
// case "L":
|
|
do {
|
|
let number = NSNumber(value: UInt(UInt32.max))
|
|
// XCTAssertEqual(String(cString: number.objCType), "L") // get "q" instead of "L"
|
|
XCTAssertEqual(storage(number), .integer)
|
|
XCTAssertEqual(Int64.fromDatabaseValue(number.databaseValue), Int64(UInt32.max))
|
|
}
|
|
|
|
// case "q":
|
|
do {
|
|
let number = NSNumber(value: Int64.min + 1)
|
|
XCTAssertEqual(String(cString: number.objCType), "q")
|
|
XCTAssertEqual(storage(number), .integer)
|
|
XCTAssertEqual(Int64.fromDatabaseValue(number.databaseValue), Int64(Int64.min + 1))
|
|
}
|
|
|
|
// case "Q":
|
|
do {
|
|
let number = NSNumber(value: UInt64(Int64.max))
|
|
// XCTAssertEqual(String(cString: number.objCType), "Q") // get "q" instead of "Q"
|
|
XCTAssertEqual(storage(number), .integer)
|
|
XCTAssertEqual(Int64.fromDatabaseValue(number.databaseValue), Int64.max)
|
|
}
|
|
|
|
// case "f":
|
|
do {
|
|
let number = NSNumber(value: Float(3))
|
|
XCTAssertEqual(String(cString: number.objCType), "f")
|
|
XCTAssertEqual(storage(number), .double)
|
|
XCTAssertEqual(Float.fromDatabaseValue(number.databaseValue), Float(3))
|
|
}
|
|
|
|
// case "d":
|
|
do {
|
|
let number = NSNumber(value: 10.0)
|
|
XCTAssertEqual(String(cString: number.objCType), "d")
|
|
XCTAssertEqual(storage(number), .double)
|
|
XCTAssertEqual(Double.fromDatabaseValue(number.databaseValue), 10.0)
|
|
}
|
|
|
|
// case "B":
|
|
do {
|
|
let number = NSNumber(value: true)
|
|
XCTAssertEqual(String(cString: number.objCType), "c")
|
|
XCTAssertEqual(storage(number), .integer)
|
|
XCTAssertEqual(Bool.fromDatabaseValue(number.databaseValue), true)
|
|
}
|
|
|
|
do {
|
|
let number = NSNumber(value: false)
|
|
XCTAssertEqual(String(cString: number.objCType), "c")
|
|
XCTAssertEqual(storage(number), .integer)
|
|
XCTAssertEqual(Bool.fromDatabaseValue(number.databaseValue), false)
|
|
}
|
|
}
|
|
|
|
func testNSNumberDatabaseRoundTrip() throws {
|
|
let dbQueue = try makeDatabaseQueue()
|
|
func roundTrip(_ value: NSNumber) throws -> Bool {
|
|
guard let back = try dbQueue.inDatabase({ try NSNumber.fetchOne($0, sql: "SELECT ?", arguments: [value]) }) else {
|
|
XCTFail()
|
|
return false
|
|
}
|
|
return back == value
|
|
}
|
|
|
|
XCTAssertTrue(try roundTrip(NSNumber(value: Int32.min + 1)))
|
|
XCTAssertTrue(try roundTrip(NSNumber(value: Double(10000000.01))))
|
|
}
|
|
|
|
func testNSNumberDatabaseValueRoundTrip() {
|
|
func roundTrip(_ value: NSNumber) -> Bool
|
|
{
|
|
let dbValue = value.databaseValue
|
|
guard let back = NSNumber.fromDatabaseValue(dbValue) else
|
|
{
|
|
XCTFail("Failed to convert from DatabaseValue to NSNumber")
|
|
return false
|
|
}
|
|
return back.isEqual(to: value)
|
|
}
|
|
|
|
XCTAssertTrue(roundTrip(NSNumber(value: Int32.min + 1)))
|
|
XCTAssertTrue(roundTrip(NSNumber(value: Double(10000000.01))))
|
|
}
|
|
|
|
func testNSNumberFromDatabaseValueFailure() {
|
|
let databaseValue_Null = DatabaseValue.null
|
|
let databaseValue_String = "foo".databaseValue
|
|
let databaseValue_Blob = "bar".data(using: .utf8)!.databaseValue
|
|
XCTAssertNil(NSNumber.fromDatabaseValue(databaseValue_Null))
|
|
XCTAssertNil(NSNumber.fromDatabaseValue(databaseValue_String))
|
|
XCTAssertNil(NSNumber.fromDatabaseValue(databaseValue_Blob))
|
|
}
|
|
|
|
func testNSNumberDecodingFromText() throws {
|
|
func test(_ value: String, isDecodedAs number: NSDecimalNumber) throws {
|
|
let decodedFromDatabaseValue = NSNumber.fromDatabaseValue(value.databaseValue) as? NSDecimalNumber
|
|
XCTAssertEqual(decodedFromDatabaseValue, number)
|
|
|
|
let decodedFromDatabase = try DatabaseQueue().read { db in
|
|
try NSNumber.fetchOne(db, sql: "SELECT ?", arguments: [value]) as? NSDecimalNumber
|
|
}
|
|
XCTAssertEqual(decodedFromDatabase, number)
|
|
}
|
|
try test("0", isDecodedAs: NSDecimalNumber(value: 0))
|
|
try test("0.25", isDecodedAs: NSDecimalNumber(value: 0.25))
|
|
try test("1", isDecodedAs: NSDecimalNumber(value: 1))
|
|
try test("-1", isDecodedAs: NSDecimalNumber(value: -1))
|
|
try test("9223372036854775807", isDecodedAs: NSDecimalNumber(value: 9223372036854775807))
|
|
try test("9223372036854775806", isDecodedAs: NSDecimalNumber(value: 9223372036854775806))
|
|
try test("-9223372036854775807", isDecodedAs: NSDecimalNumber(value: -9223372036854775807))
|
|
try test("-9223372036854775808", isDecodedAs: NSDecimalNumber(value: -9223372036854775808))
|
|
try test("18446744073709551615", isDecodedAs: NSDecimalNumber(value: UInt64(18446744073709551615)))
|
|
}
|
|
}
|