mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-03-09 06:40:08 +01:00
importing unit tests
This commit is contained in:
@@ -8,7 +8,6 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
2F03A53619C5C6DA005002A5 /* CoreStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F03A53519C5C6DA005002A5 /* CoreStore.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
2F03A54019C5C6DA005002A5 /* CoreStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F03A53F19C5C6DA005002A5 /* CoreStoreTests.swift */; };
|
||||
2F03A54D19C5C872005002A5 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2F03A54C19C5C872005002A5 /* CoreData.framework */; };
|
||||
2F291E2719C6D3CF007AF63F /* CoreStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F291E2619C6D3CF007AF63F /* CoreStore.swift */; };
|
||||
82BA18931C4BBCBA00A0916E /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82BA18891C4BBCBA00A0916E /* CoreStore.framework */; };
|
||||
@@ -66,7 +65,6 @@
|
||||
82BA18D61C4BBD7100A0916E /* NSManagedObjectContext+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F331AFF85470064E85B /* NSManagedObjectContext+Transaction.swift */; };
|
||||
82BA18D71C4BBD7100A0916E /* NSManagedObjectModel+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */; };
|
||||
82BA18D81C4BBD7100A0916E /* WeakObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2D1AFF849C0064E85B /* WeakObject.swift */; };
|
||||
82BA18D91C4BBD9700A0916E /* CoreStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F03A53F19C5C6DA005002A5 /* CoreStoreTests.swift */; };
|
||||
82BA18DC1C4BBD9C00A0916E /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B5D372821A39CD6900F583D9 /* Model.xcdatamodeld */; };
|
||||
82BA18DD1C4BBE1400A0916E /* NSFetchedResultsController+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */; };
|
||||
82BA18DF1C4BBE2600A0916E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82BA18DE1C4BBE2600A0916E /* Foundation.framework */; };
|
||||
@@ -99,6 +97,12 @@
|
||||
B51FE5AF1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51FE5AA1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift */; };
|
||||
B5202CFA1C04688100DED140 /* NSFetchedResultsController+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */; };
|
||||
B5202CFD1C046E8400DED140 /* NSFetchedResultsController+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */; };
|
||||
B5220E081D0C5F8D009BC71E /* ObjectObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5220E071D0C5F8D009BC71E /* ObjectObserverTests.swift */; };
|
||||
B5220E091D0C5F8D009BC71E /* ObjectObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5220E071D0C5F8D009BC71E /* ObjectObserverTests.swift */; };
|
||||
B5220E0A1D0C5F8D009BC71E /* ObjectObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5220E071D0C5F8D009BC71E /* ObjectObserverTests.swift */; };
|
||||
B5220E0C1D0D0D19009BC71E /* ImportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5220E0B1D0D0D19009BC71E /* ImportTests.swift */; };
|
||||
B5220E0D1D0D0D19009BC71E /* ImportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5220E0B1D0D0D19009BC71E /* ImportTests.swift */; };
|
||||
B5220E0E1D0D0D19009BC71E /* ImportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5220E0B1D0D0D19009BC71E /* ImportTests.swift */; };
|
||||
B525576C1CFAF18F00E51965 /* IntoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B525576B1CFAF18F00E51965 /* IntoTests.swift */; };
|
||||
B525576D1CFAF18F00E51965 /* IntoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B525576B1CFAF18F00E51965 /* IntoTests.swift */; };
|
||||
B525576E1CFAF18F00E51965 /* IntoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B525576B1CFAF18F00E51965 /* IntoTests.swift */; };
|
||||
@@ -181,7 +185,6 @@
|
||||
B52DD1C91BE1F94600949AFE /* NSManagedObjectContext+Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F331AFF85470064E85B /* NSManagedObjectContext+Transaction.swift */; };
|
||||
B52DD1CA1BE1F94600949AFE /* NSManagedObjectModel+Setup.swift in Sources */ = {isa = PBXBuildFile; fileRef = B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */; };
|
||||
B52DD1CB1BE1F94600949AFE /* WeakObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E84F2D1AFF849C0064E85B /* WeakObject.swift */; };
|
||||
B52DD1CC1BE1F94D00949AFE /* CoreStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F03A53F19C5C6DA005002A5 /* CoreStoreTests.swift */; };
|
||||
B53FB9FE1CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FB9FD1CAB2D2F00F0D40A /* CSMigrationResult.swift */; };
|
||||
B53FB9FF1CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FB9FD1CAB2D2F00F0D40A /* CSMigrationResult.swift */; };
|
||||
B53FBA001CAB2D2F00F0D40A /* CSMigrationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53FB9FD1CAB2D2F00F0D40A /* CSMigrationResult.swift */; };
|
||||
@@ -660,7 +663,6 @@
|
||||
2F03A53519C5C6DA005002A5 /* CoreStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CoreStore.h; sourceTree = "<group>"; };
|
||||
2F03A53B19C5C6DA005002A5 /* CoreStoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreStoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
2F03A53E19C5C6DA005002A5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
2F03A53F19C5C6DA005002A5 /* CoreStoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CoreStoreTests.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
2F03A54C19C5C872005002A5 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
|
||||
2F291E2619C6D3CF007AF63F /* CoreStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CoreStore.swift; sourceTree = "<group>"; };
|
||||
82BA18891C4BBCBA00A0916E /* CoreStore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CoreStore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@@ -676,6 +678,8 @@
|
||||
B51BE0691B47FC4B0069F532 /* NSManagedObjectModel+Setup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSManagedObjectModel+Setup.swift"; sourceTree = "<group>"; };
|
||||
B51FE5AA1CD4D00300E54258 /* CoreStore+CustomDebugStringConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoreStore+CustomDebugStringConvertible.swift"; sourceTree = "<group>"; };
|
||||
B5202CF91C04688100DED140 /* NSFetchedResultsController+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSFetchedResultsController+Convenience.swift"; sourceTree = "<group>"; };
|
||||
B5220E071D0C5F8D009BC71E /* ObjectObserverTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectObserverTests.swift; sourceTree = "<group>"; };
|
||||
B5220E0B1D0D0D19009BC71E /* ImportTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportTests.swift; sourceTree = "<group>"; };
|
||||
B525576B1CFAF18F00E51965 /* IntoTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntoTests.swift; sourceTree = "<group>"; };
|
||||
B525576F1D02561A00E51965 /* SelectTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectTests.swift; sourceTree = "<group>"; };
|
||||
B52557731D02791400E51965 /* WhereTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WhereTests.swift; sourceTree = "<group>"; };
|
||||
@@ -954,13 +958,14 @@
|
||||
B5489F4A1CF5F743008B4978 /* BaseTests */,
|
||||
B5DBE2DD1C9939E100B5CEFA /* BridgingTests.h */,
|
||||
B5DBE2DE1C9939E100B5CEFA /* BridgingTests.m */,
|
||||
2F03A53F19C5C6DA005002A5 /* CoreStoreTests.swift */,
|
||||
B5519A3F1CA1B17B002BEF78 /* ErrorTests.swift */,
|
||||
B52557871D02DE8100E51965 /* FetchTests.swift */,
|
||||
B5489F4F1CF603D5008B4978 /* FromTests.swift */,
|
||||
B525577B1D0291FE00E51965 /* GroupByTests.swift */,
|
||||
B5220E0B1D0D0D19009BC71E /* ImportTests.swift */,
|
||||
B525576B1CFAF18F00E51965 /* IntoTests.swift */,
|
||||
B5DC47C51C93D22900FA3BF3 /* MigrationChainTests.swift */,
|
||||
B5220E071D0C5F8D009BC71E /* ObjectObserverTests.swift */,
|
||||
B52557771D02826E00E51965 /* OrderByTests.swift */,
|
||||
B57D27C11D0BC20100539C58 /* QueryTests.swift */,
|
||||
B52557831D02A07400E51965 /* SectionByTests.swift */,
|
||||
@@ -1764,13 +1769,14 @@
|
||||
B5519A401CA1B17B002BEF78 /* ErrorTests.swift in Sources */,
|
||||
B525577C1D0291FE00E51965 /* GroupByTests.swift in Sources */,
|
||||
B52557741D02791400E51965 /* WhereTests.swift in Sources */,
|
||||
2F03A54019C5C6DA005002A5 /* CoreStoreTests.swift in Sources */,
|
||||
B5DC47C61C93D22900FA3BF3 /* MigrationChainTests.swift in Sources */,
|
||||
B525576C1CFAF18F00E51965 /* IntoTests.swift in Sources */,
|
||||
B5220E0C1D0D0D19009BC71E /* ImportTests.swift in Sources */,
|
||||
B5D372841A39CD6900F583D9 /* Model.xcdatamodeld in Sources */,
|
||||
B52557881D02DE8100E51965 /* FetchTests.swift in Sources */,
|
||||
B5489F501CF603D5008B4978 /* FromTests.swift in Sources */,
|
||||
B52557781D02826E00E51965 /* OrderByTests.swift in Sources */,
|
||||
B5220E081D0C5F8D009BC71E /* ObjectObserverTests.swift in Sources */,
|
||||
B5489F421CF5EEBC008B4978 /* TestEntity2.swift in Sources */,
|
||||
B52557701D02561A00E51965 /* SelectTests.swift in Sources */,
|
||||
B5489F461CF5F017008B4978 /* TransactionTests.swift in Sources */,
|
||||
@@ -1911,16 +1917,17 @@
|
||||
B52557751D02791400E51965 /* WhereTests.swift in Sources */,
|
||||
B5DC47C71C93D22900FA3BF3 /* MigrationChainTests.swift in Sources */,
|
||||
B5DBE2E01C9939E100B5CEFA /* BridgingTests.m in Sources */,
|
||||
B5220E0D1D0D0D19009BC71E /* ImportTests.swift in Sources */,
|
||||
B525576D1CFAF18F00E51965 /* IntoTests.swift in Sources */,
|
||||
B580857B1CDF808D004C2EEB /* SetupTests.swift in Sources */,
|
||||
B52557891D02DE8100E51965 /* FetchTests.swift in Sources */,
|
||||
B5489F511CF603D5008B4978 /* FromTests.swift in Sources */,
|
||||
B5220E091D0C5F8D009BC71E /* ObjectObserverTests.swift in Sources */,
|
||||
B52557791D02826E00E51965 /* OrderByTests.swift in Sources */,
|
||||
B5489F431CF5EEBC008B4978 /* TestEntity2.swift in Sources */,
|
||||
B52557711D02561A00E51965 /* SelectTests.swift in Sources */,
|
||||
B5489F471CF5F017008B4978 /* TransactionTests.swift in Sources */,
|
||||
B52557811D029D2500E51965 /* TweakTests.swift in Sources */,
|
||||
82BA18D91C4BBD9700A0916E /* CoreStoreTests.swift in Sources */,
|
||||
B5489F4D1CF5F743008B4978 /* BaseTestCase.swift in Sources */,
|
||||
82BA18DC1C4BBD9C00A0916E /* Model.xcdatamodeld in Sources */,
|
||||
B57D27BF1D0BBE8200539C58 /* BaseTestDataTestCase.swift in Sources */,
|
||||
@@ -2037,16 +2044,17 @@
|
||||
B52557761D02791400E51965 /* WhereTests.swift in Sources */,
|
||||
B5DC47C81C93D22900FA3BF3 /* MigrationChainTests.swift in Sources */,
|
||||
B5DBE2E11C9939E100B5CEFA /* BridgingTests.m in Sources */,
|
||||
B5220E0E1D0D0D19009BC71E /* ImportTests.swift in Sources */,
|
||||
B525576E1CFAF18F00E51965 /* IntoTests.swift in Sources */,
|
||||
B580857C1CDF808F004C2EEB /* SetupTests.swift in Sources */,
|
||||
B525578A1D02DE8100E51965 /* FetchTests.swift in Sources */,
|
||||
B5489F521CF603D5008B4978 /* FromTests.swift in Sources */,
|
||||
B5220E0A1D0C5F8D009BC71E /* ObjectObserverTests.swift in Sources */,
|
||||
B525577A1D02826E00E51965 /* OrderByTests.swift in Sources */,
|
||||
B5489F441CF5EEBC008B4978 /* TestEntity2.swift in Sources */,
|
||||
B52557721D02561A00E51965 /* SelectTests.swift in Sources */,
|
||||
B5489F481CF5F017008B4978 /* TransactionTests.swift in Sources */,
|
||||
B52557821D029D2500E51965 /* TweakTests.swift in Sources */,
|
||||
B52DD1CC1BE1F94D00949AFE /* CoreStoreTests.swift in Sources */,
|
||||
B5489F4E1CF5F743008B4978 /* BaseTestCase.swift in Sources */,
|
||||
B5598BCC1BE2093D0092EFCE /* Model.xcdatamodeld in Sources */,
|
||||
B57D27C01D0BBE8200539C58 /* BaseTestDataTestCase.swift in Sources */,
|
||||
|
||||
@@ -70,7 +70,7 @@ class BaseTestCase: XCTestCase {
|
||||
CoreStore.logger = TestLogger(self.prepareLoggerExpectations(expectations))
|
||||
defer {
|
||||
|
||||
self.waitForExpectationsWithTimeout(0, handler: nil)
|
||||
self.checkExpectationsImmediately()
|
||||
CoreStore.logger = TestLogger([:])
|
||||
}
|
||||
return closure()
|
||||
@@ -93,6 +93,17 @@ class BaseTestCase: XCTestCase {
|
||||
return testExpectations
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
func checkExpectationsImmediately() {
|
||||
|
||||
self.waitForExpectationsWithTimeout(0, handler: nil)
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
func waitAndCheckExpectations() {
|
||||
|
||||
self.waitForExpectationsWithTimeout(10, handler: nil)
|
||||
}
|
||||
|
||||
// MARK: XCTestCase
|
||||
|
||||
@@ -165,10 +176,9 @@ class TestLogger: CoreStoreLogger {
|
||||
self.fulfill(.AssertionFailure)
|
||||
}
|
||||
|
||||
@noreturn func fatalError(message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
|
||||
func abort(message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
|
||||
|
||||
self.fulfill(.FatalError)
|
||||
Swift.fatalError()
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,364 +0,0 @@
|
||||
//
|
||||
// CoreStoreTests.swift
|
||||
// CoreStoreTests
|
||||
//
|
||||
// Copyright © 2014 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
@testable
|
||||
import CoreStore
|
||||
|
||||
class CoreStoreTests: XCTestCase {
|
||||
|
||||
override func setUp() {
|
||||
|
||||
super.setUp()
|
||||
self.deleteStores()
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
|
||||
self.deleteStores()
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testExample() {
|
||||
|
||||
let stack = DataStack(
|
||||
modelName: "Model",
|
||||
bundle: NSBundle(forClass: self.dynamicType)
|
||||
)
|
||||
CoreStore.defaultStack = stack
|
||||
XCTAssert(CoreStore.defaultStack === stack, "CoreStore.defaultStack === stack")
|
||||
|
||||
do {
|
||||
|
||||
try stack.addStorageAndWait(
|
||||
SQLiteStore(
|
||||
fileName: "ConfigStore1.sqlite",
|
||||
configuration: "Config1",
|
||||
localStorageOptions: .RecreateStoreOnModelMismatch
|
||||
)
|
||||
)
|
||||
}
|
||||
catch let error as NSError {
|
||||
|
||||
XCTFail(error.description)
|
||||
}
|
||||
|
||||
do {
|
||||
|
||||
try stack.addStorageAndWait(
|
||||
SQLiteStore(
|
||||
fileName: "ConfigStore2.sqlite",
|
||||
configuration: "Config2",
|
||||
localStorageOptions: .RecreateStoreOnModelMismatch
|
||||
)
|
||||
)
|
||||
}
|
||||
catch let error as NSError {
|
||||
|
||||
XCTFail(error.description)
|
||||
}
|
||||
|
||||
let unsafeTransaction = CoreStore.beginUnsafe()
|
||||
|
||||
let createExpectation = self.expectationWithDescription("Entity creation")
|
||||
CoreStore.beginAsynchronous { (transaction) -> Void in
|
||||
|
||||
let obj1 = transaction.create(Into(TestEntity1))
|
||||
obj1.testEntityID = 1
|
||||
obj1.testString = "lololol"
|
||||
obj1.testNumber = 42
|
||||
obj1.testDate = NSDate()
|
||||
|
||||
let count = transaction.queryValue(
|
||||
From<TestEntity1>(),
|
||||
Select<Int>(.Count("testNumber"))
|
||||
)
|
||||
XCTAssertTrue(count == 0, "count == 0 (actual: \(count))") // counts only objects in store
|
||||
|
||||
let obj2 = transaction.create(Into<TestEntity2>())
|
||||
obj2.testEntityID = 2
|
||||
obj2.testString = "hahaha"
|
||||
obj2.testNumber = 100
|
||||
obj2.testDate = NSDate()
|
||||
|
||||
let obj3 = transaction.create(Into<TestEntity2>("Config2"))
|
||||
obj3.testEntityID = 3
|
||||
obj3.testString = "hahaha"
|
||||
obj3.testNumber = 90
|
||||
obj3.testDate = NSDate()
|
||||
|
||||
let obj4 = transaction.create(Into(TestEntity2.self, "Config2"))
|
||||
obj4.testEntityID = 5
|
||||
obj4.testString = "hohoho"
|
||||
obj4.testNumber = 80
|
||||
obj4.testDate = NSDate()
|
||||
|
||||
|
||||
transaction.beginSynchronous { (transaction) -> Void in
|
||||
|
||||
let obj4 = transaction.create(Into<TestEntity2>())
|
||||
obj4.testEntityID = 4
|
||||
obj4.testString = "hehehehe"
|
||||
obj4.testNumber = 80
|
||||
obj4.testDate = NSDate()
|
||||
|
||||
let objs4test = transaction.fetchOne(
|
||||
From<TestEntity2>("Config2"),
|
||||
Where("testEntityID", isEqualTo: 4),
|
||||
Tweak { (fetchRequest) -> Void in
|
||||
|
||||
fetchRequest.includesPendingChanges = true
|
||||
}
|
||||
)
|
||||
XCTAssertNotNil(objs4test, "objs4test != nil")
|
||||
|
||||
let objs5test = transaction.fetchOne(
|
||||
From(TestEntity2),
|
||||
Where("testEntityID", isEqualTo: 4),
|
||||
Tweak { (fetchRequest) -> Void in
|
||||
|
||||
fetchRequest.includesPendingChanges = false
|
||||
}
|
||||
)
|
||||
XCTAssertNil(objs5test, "objs5test == nil")
|
||||
|
||||
// Dont commit1
|
||||
}
|
||||
|
||||
transaction.commit { (result) -> Void in
|
||||
|
||||
let objs4test = CoreStore.fetchOne(
|
||||
From(TestEntity2),
|
||||
Where("testEntityID", isEqualTo: 4),
|
||||
Tweak { (fetchRequest) -> Void in
|
||||
|
||||
fetchRequest.includesPendingChanges = false
|
||||
}
|
||||
)
|
||||
XCTAssertNil(objs4test, "objs4test == nil")
|
||||
|
||||
let objs5test = unsafeTransaction.fetchCount(From(TestEntity2))
|
||||
XCTAssertTrue(objs5test == 3, "objs5test == 3")
|
||||
|
||||
XCTAssertTrue(NSThread.isMainThread(), "NSThread.isMainThread()")
|
||||
switch result {
|
||||
|
||||
case .Success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges, "hasChanges == true")
|
||||
createExpectation.fulfill()
|
||||
|
||||
case .Failure(let error):
|
||||
XCTFail("\(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let queryExpectation = self.expectationWithDescription("Query creation")
|
||||
CoreStore.beginAsynchronous { (transaction) -> Void in
|
||||
|
||||
let obj1 = transaction.fetchOne(From(TestEntity1))
|
||||
XCTAssertNotNil(obj1, "obj1 != nil")
|
||||
|
||||
var orderBy = OrderBy(.Ascending("testEntityID"))
|
||||
orderBy += OrderBy(.Descending("testString"))
|
||||
let objs2 = transaction.fetchAll(
|
||||
From(TestEntity2),
|
||||
Where("testNumber", isEqualTo: 100) || Where("%K == %@", "testNumber", 90),
|
||||
orderBy,
|
||||
Tweak { (fetchRequest) -> Void in
|
||||
|
||||
fetchRequest.includesPendingChanges = true
|
||||
}
|
||||
)
|
||||
XCTAssertNotNil(objs2, "objs2 != nil")
|
||||
XCTAssertTrue(objs2?.count == 2, "objs2?.count == 2")
|
||||
|
||||
transaction.commit { (result) -> Void in
|
||||
|
||||
let counts = CoreStore.queryAttributes(
|
||||
From(TestEntity2),
|
||||
Select("testString", .Count("testString", As: "count")),
|
||||
GroupBy("testString")
|
||||
)
|
||||
|
||||
XCTAssertTrue(NSThread.isMainThread(), "NSThread.isMainThread()")
|
||||
switch result {
|
||||
|
||||
case .Success(let hasChanges):
|
||||
XCTAssertFalse(hasChanges, "hasChanges == false")
|
||||
queryExpectation.fulfill()
|
||||
|
||||
case .Failure(let error):
|
||||
XCTFail("\(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.waitForExpectationsWithTimeout(100, handler: nil)
|
||||
|
||||
let max1 = CoreStore.queryValue(
|
||||
From(TestEntity2),
|
||||
Select<Int>(.Maximum("testNumber"))
|
||||
)
|
||||
XCTAssertTrue(max1 == 100, "max == 100 (actual: \(max1))")
|
||||
|
||||
let max2 = CoreStore.queryValue(
|
||||
From(TestEntity2),
|
||||
Select<NSNumber>(.Maximum("testNumber")),
|
||||
Where("%K > %@", "testEntityID", 2)
|
||||
)
|
||||
XCTAssertTrue(max2 == 90, "max == 90 (actual: \(max2))")
|
||||
|
||||
CoreStore.beginSynchronous { (transaction) -> Void in
|
||||
|
||||
let numberOfDeletedObjects1 = transaction.deleteAll(From(TestEntity1))
|
||||
XCTAssertTrue(numberOfDeletedObjects1 == 1, "numberOfDeletedObjects1 == 1 (actual: \(numberOfDeletedObjects1))")
|
||||
|
||||
let numberOfDeletedObjects2 = transaction.deleteAll(
|
||||
From(TestEntity2),
|
||||
Where("%K > %@", "testEntityID", 2)
|
||||
)
|
||||
XCTAssertTrue(numberOfDeletedObjects2 == 2, "numberOfDeletedObjects2 == 2 (actual: \(numberOfDeletedObjects2))")
|
||||
|
||||
transaction.commitAndWait()
|
||||
}
|
||||
|
||||
CoreStore.beginSynchronous({ (transaction) -> Void in
|
||||
|
||||
if let obj = CoreStore.fetchOne(From(TestEntity2)) {
|
||||
|
||||
let oldID = obj.testEntityID
|
||||
obj.testEntityID = 0
|
||||
obj.testEntityID = oldID
|
||||
}
|
||||
|
||||
transaction.commitAndWait()
|
||||
})
|
||||
|
||||
let objs1 = CoreStore.fetchAll(From(TestEntity1))
|
||||
XCTAssertNotNil(objs1, "objs1 != nil")
|
||||
XCTAssertTrue(objs1?.count == 0, "objs1?.count == 0")
|
||||
|
||||
let objs2 = CoreStore.fetchAll(From(TestEntity2))
|
||||
XCTAssertNotNil(objs2, "objs2 != nil")
|
||||
XCTAssertTrue(objs2?.count == 1, "objs2?.count == 1")
|
||||
|
||||
let unsafeExpectation = self.expectationWithDescription("Query creation")
|
||||
|
||||
let obj5 = unsafeTransaction.create(Into<TestEntity1>("Config1"))
|
||||
obj5.testEntityID = 5
|
||||
obj5.testString = "hihihi"
|
||||
obj5.testNumber = 70
|
||||
obj5.testDate = NSDate()
|
||||
XCTAssert(unsafeTransaction === obj5.unsafeDataTransaction, "unsafeTransaction === obj5.unsafeDataTransaction")
|
||||
|
||||
unsafeTransaction.commit { (result) -> Void in
|
||||
|
||||
XCTAssertTrue(NSThread.isMainThread(), "NSThread.isMainThread()")
|
||||
switch result {
|
||||
|
||||
case .Success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges, "hasChanges == true")
|
||||
|
||||
CoreStore.beginSynchronous { (transaction) -> Void in
|
||||
|
||||
let obj5Copy1 = transaction.edit(obj5)
|
||||
XCTAssertTrue(obj5.objectID == obj5Copy1?.objectID, "obj5.objectID == obj5Copy1?.objectID")
|
||||
XCTAssertFalse(obj5 == obj5Copy1, "obj5 == obj5Copy1")
|
||||
XCTAssertNil(obj5Copy1?.unsafeDataTransaction)
|
||||
|
||||
let obj5Copy2 = transaction.edit(Into(TestEntity1), obj5.objectID)
|
||||
XCTAssertTrue(obj5.objectID == obj5Copy2?.objectID, "obj5.objectID == obj5Copy2?.objectID")
|
||||
XCTAssertFalse(obj5 == obj5Copy2, "obj5 == obj5Copy2")
|
||||
}
|
||||
|
||||
let count: Int? = CoreStore.queryValue(
|
||||
From(TestEntity1),
|
||||
Select(.Count("testNumber"))
|
||||
)
|
||||
XCTAssertTrue(count == 1, "count == 1 (actual: \(count))")
|
||||
|
||||
let obj6 = unsafeTransaction.create(Into<TestEntity1>())
|
||||
obj6.testEntityID = 6
|
||||
obj6.testString = "huehuehue"
|
||||
obj6.testNumber = 130
|
||||
obj6.testDate = NSDate()
|
||||
XCTAssert(unsafeTransaction === obj6.unsafeDataTransaction, "unsafeTransaction === obj6.unsafeDataTransaction")
|
||||
|
||||
unsafeTransaction.commit { (result) -> Void in
|
||||
|
||||
XCTAssertTrue(NSThread.isMainThread(), "NSThread.isMainThread()")
|
||||
switch result {
|
||||
|
||||
case .Success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges, "hasChanges == true")
|
||||
|
||||
let count = CoreStore.queryValue(
|
||||
From(TestEntity1),
|
||||
Select<Int>(.Count("testNumber"))
|
||||
)
|
||||
XCTAssertTrue(count == 2, "count == 2 (actual: \(count))")
|
||||
|
||||
|
||||
CoreStore.beginSynchronous { (transaction) -> Void in
|
||||
|
||||
let obj6 = transaction.edit(obj6)
|
||||
let obj5 = transaction.edit(obj5)
|
||||
transaction.delete(obj5, obj6)
|
||||
|
||||
transaction.commitAndWait()
|
||||
}
|
||||
|
||||
let count2 = CoreStore.queryValue(
|
||||
From(TestEntity1),
|
||||
Select<Int>(.Count("testNumber"))
|
||||
)
|
||||
XCTAssertTrue(count2 == 0, "count == 0 (actual: \(count2))")
|
||||
|
||||
unsafeExpectation.fulfill()
|
||||
|
||||
case .Failure(let error):
|
||||
XCTFail("\(error)")
|
||||
}
|
||||
}
|
||||
|
||||
case .Failure(let error):
|
||||
XCTFail("\(error)")
|
||||
}
|
||||
}
|
||||
|
||||
self.waitForExpectationsWithTimeout(100, handler: nil)
|
||||
}
|
||||
|
||||
private func deleteStores() {
|
||||
|
||||
do {
|
||||
|
||||
try NSFileManager.defaultManager().removeItemAtURL(SQLiteStore.defaultRootDirectory)
|
||||
}
|
||||
catch _ { }
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import GCDKit
|
||||
|
||||
@testable
|
||||
import CoreStore
|
||||
@@ -33,6 +34,195 @@ import CoreStore
|
||||
|
||||
final class FetchTests: BaseTestDataTestCase {
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatDataStacksAndTransactions_CanFetchOneExisting() {
|
||||
|
||||
let configurations: [String?] = ["Config1"]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
|
||||
let from = From(TestEntity1)
|
||||
let fetchClauses: [FetchClause] = [
|
||||
OrderBy(.Ascending("testEntityID"))
|
||||
]
|
||||
let object = stack.fetchOne(from, fetchClauses)!
|
||||
do {
|
||||
|
||||
let existing = stack.fetchExisting(object)
|
||||
XCTAssertNotNil(existing)
|
||||
XCTAssertEqual(existing!.objectID, object.objectID)
|
||||
XCTAssertEqual(existing!.managedObjectContext, stack.mainContext)
|
||||
}
|
||||
do {
|
||||
|
||||
let transaction = stack.beginUnsafe()
|
||||
|
||||
let existing1 = transaction.fetchExisting(object)
|
||||
XCTAssertNotNil(existing1)
|
||||
XCTAssertEqual(existing1!.objectID, object.objectID)
|
||||
XCTAssertEqual(existing1!.managedObjectContext, transaction.context)
|
||||
|
||||
let existing2 = stack.fetchExisting(existing1!)
|
||||
XCTAssertNotNil(existing2)
|
||||
XCTAssertEqual(existing2!.objectID, object.objectID)
|
||||
XCTAssertEqual(existing2!.managedObjectContext, stack.mainContext)
|
||||
}
|
||||
do {
|
||||
|
||||
let fetchExpectation = self.expectationWithDescription("fetch")
|
||||
|
||||
var existing1: TestEntity1?
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
existing1 = transaction.fetchExisting(object)
|
||||
XCTAssertNotNil(existing1)
|
||||
XCTAssertEqual(existing1!.objectID, object.objectID)
|
||||
XCTAssertEqual(existing1!.managedObjectContext, transaction.context)
|
||||
|
||||
fetchExpectation.fulfill()
|
||||
}
|
||||
let existing2 = stack.fetchExisting(existing1!)
|
||||
XCTAssertNotNil(existing2)
|
||||
XCTAssertEqual(existing2!.objectID, object.objectID)
|
||||
XCTAssertEqual(existing2!.managedObjectContext, stack.mainContext)
|
||||
}
|
||||
do {
|
||||
|
||||
let fetchExpectation = self.expectationWithDescription("fetch")
|
||||
stack.beginAsynchronous { (transaction) in
|
||||
|
||||
let existing1 = transaction.fetchExisting(object)
|
||||
XCTAssertNotNil(existing1)
|
||||
XCTAssertEqual(existing1!.objectID, object.objectID)
|
||||
XCTAssertEqual(existing1!.managedObjectContext, transaction.context)
|
||||
|
||||
GCDQueue.Main.async {
|
||||
|
||||
let existing2 = stack.fetchExisting(existing1!)
|
||||
XCTAssertNotNil(existing2)
|
||||
XCTAssertEqual(existing2!.objectID, object.objectID)
|
||||
XCTAssertEqual(existing2!.managedObjectContext, stack.mainContext)
|
||||
|
||||
fetchExpectation.fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.waitAndCheckExpectations()
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatDataStacksAndTransactions_CanFetchAllExisting() {
|
||||
|
||||
let configurations: [String?] = ["Config1"]
|
||||
self.prepareStack(configurations: configurations) { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: configurations)
|
||||
|
||||
let from = From(TestEntity1)
|
||||
let fetchClauses: [FetchClause] = [
|
||||
OrderBy(.Ascending("testEntityID"))
|
||||
]
|
||||
let objects = stack.fetchAll(from, fetchClauses)!
|
||||
do {
|
||||
|
||||
let existing = stack.fetchExisting(objects)
|
||||
XCTAssertEqual(
|
||||
existing.map { $0.objectID },
|
||||
objects.map { $0.objectID }
|
||||
)
|
||||
for object in existing {
|
||||
|
||||
XCTAssertEqual(object.managedObjectContext, stack.mainContext)
|
||||
}
|
||||
}
|
||||
do {
|
||||
|
||||
let transaction = stack.beginUnsafe()
|
||||
|
||||
let existing1 = transaction.fetchExisting(objects)
|
||||
XCTAssertEqual(
|
||||
existing1.map { $0.objectID },
|
||||
objects.map { $0.objectID }
|
||||
)
|
||||
for object in existing1 {
|
||||
|
||||
XCTAssertEqual(object.managedObjectContext, transaction.context)
|
||||
}
|
||||
|
||||
let existing2 = stack.fetchExisting(existing1)
|
||||
XCTAssertEqual(
|
||||
existing2.map { $0.objectID },
|
||||
objects.map { $0.objectID }
|
||||
)
|
||||
for object in existing2 {
|
||||
|
||||
XCTAssertEqual(object.managedObjectContext, stack.mainContext)
|
||||
}
|
||||
}
|
||||
do {
|
||||
|
||||
let fetchExpectation = self.expectationWithDescription("fetch")
|
||||
|
||||
var existing1 = [TestEntity1]()
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
existing1 = transaction.fetchExisting(objects)
|
||||
XCTAssertEqual(
|
||||
existing1.map { $0.objectID },
|
||||
objects.map { $0.objectID }
|
||||
)
|
||||
for object in existing1 {
|
||||
|
||||
XCTAssertEqual(object.managedObjectContext, transaction.context)
|
||||
}
|
||||
|
||||
fetchExpectation.fulfill()
|
||||
}
|
||||
let existing2 = stack.fetchExisting(existing1)
|
||||
XCTAssertEqual(
|
||||
existing2.map { $0.objectID },
|
||||
objects.map { $0.objectID }
|
||||
)
|
||||
for object in existing2 {
|
||||
|
||||
XCTAssertEqual(object.managedObjectContext, stack.mainContext)
|
||||
}
|
||||
}
|
||||
do {
|
||||
|
||||
let fetchExpectation = self.expectationWithDescription("fetch")
|
||||
stack.beginAsynchronous { (transaction) in
|
||||
|
||||
let existing1 = transaction.fetchExisting(objects)
|
||||
XCTAssertEqual(
|
||||
existing1.map { $0.objectID },
|
||||
objects.map { $0.objectID }
|
||||
)
|
||||
for object in existing1 {
|
||||
|
||||
XCTAssertEqual(object.managedObjectContext, transaction.context)
|
||||
}
|
||||
GCDQueue.Main.async {
|
||||
|
||||
let existing2 = stack.fetchExisting(existing1)
|
||||
XCTAssertEqual(
|
||||
existing2.map { $0.objectID },
|
||||
objects.map { $0.objectID }
|
||||
)
|
||||
for object in existing2 {
|
||||
|
||||
XCTAssertEqual(object.managedObjectContext, stack.mainContext)
|
||||
}
|
||||
fetchExpectation.fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.waitAndCheckExpectations()
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatDataStacks_CanFetchOneFromDefaultConfiguration() {
|
||||
|
||||
|
||||
983
CoreStoreTests/ImportTests.swift
Normal file
983
CoreStoreTests/ImportTests.swift
Normal file
@@ -0,0 +1,983 @@
|
||||
//
|
||||
// ImportTests.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2016 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
@testable
|
||||
import CoreStore
|
||||
|
||||
|
||||
// MARK: - ImportTests
|
||||
|
||||
class ImportTests: BaseTestDataTestCase {
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatImportObject_CanSkipImport() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
do {
|
||||
|
||||
let object = try transaction.importObject(
|
||||
Into(TestEntity1),
|
||||
source: [
|
||||
"testBoolean": NSNumber(bool: true),
|
||||
"testNumber": NSNumber(integer: 1),
|
||||
"testDecimal": NSDecimalNumber(string: "1"),
|
||||
"testString": "nil:TestEntity1:1",
|
||||
"testData": ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")!,
|
||||
"skip_insert": ""
|
||||
]
|
||||
)
|
||||
XCTAssertNil(object)
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 0)
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatImportObject_CanThrowError() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
let errorExpectation = self.expectationWithDescription("error")
|
||||
do {
|
||||
|
||||
let _ = try transaction.importObject(
|
||||
Into(TestEntity1),
|
||||
source: [
|
||||
"testBoolean": NSNumber(bool: true),
|
||||
"testNumber": NSNumber(integer: 1),
|
||||
"testDecimal": NSDecimalNumber(string: "1"),
|
||||
"testString": "nil:TestEntity1:1",
|
||||
"testData": ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")!,
|
||||
"throw_on_insert": ""
|
||||
]
|
||||
)
|
||||
XCTFail()
|
||||
}
|
||||
catch _ as TestInsertError {
|
||||
|
||||
errorExpectation.fulfill()
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 1)
|
||||
|
||||
let object = transaction.fetchOne(From(TestEntity1))
|
||||
XCTAssertNotNil(object)
|
||||
XCTAssertNil(object?.testEntityID)
|
||||
XCTAssertNil(object?.testBoolean)
|
||||
XCTAssertNil(object?.testNumber)
|
||||
XCTAssertNil(object?.testDecimal)
|
||||
XCTAssertNil(object?.testString)
|
||||
XCTAssertNil(object?.testData)
|
||||
XCTAssertNil(object?.testDate)
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
self.checkExpectationsImmediately()
|
||||
transaction.context.reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatImportObject_CanImportCorrectly() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
do {
|
||||
|
||||
let object = try transaction.importObject(
|
||||
Into(TestEntity1),
|
||||
source: [
|
||||
"testBoolean": NSNumber(bool: true),
|
||||
"testNumber": NSNumber(integer: 1),
|
||||
"testDecimal": NSDecimalNumber(string: "1"),
|
||||
"testString": "nil:TestEntity1:1",
|
||||
"testData": ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")!
|
||||
]
|
||||
)
|
||||
XCTAssertNotNil(object)
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 1)
|
||||
XCTAssertNil(object?.testEntityID)
|
||||
XCTAssertEqual(object?.testBoolean, NSNumber(bool: true))
|
||||
XCTAssertEqual(object?.testNumber, NSNumber(integer: 1))
|
||||
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "1"))
|
||||
XCTAssertEqual(object?.testString, "nil:TestEntity1:1")
|
||||
XCTAssertEqual(object?.testData, ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!)
|
||||
XCTAssertEqual(object?.testDate, self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")!)
|
||||
|
||||
try transaction.importObject(
|
||||
object!,
|
||||
source: [
|
||||
"testBoolean": NSNumber(bool: false),
|
||||
"testNumber": NSNumber(integer: 2),
|
||||
"testDecimal": NSDecimalNumber(string: "2"),
|
||||
"testString": "nil:TestEntity1:2",
|
||||
"testData": ("nil:TestEntity1:2" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-02T00:00:00Z")!
|
||||
]
|
||||
)
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 1)
|
||||
XCTAssertNil(object?.testEntityID)
|
||||
XCTAssertEqual(object?.testBoolean, NSNumber(bool: false))
|
||||
XCTAssertEqual(object?.testNumber, NSNumber(integer: 2))
|
||||
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "2"))
|
||||
XCTAssertEqual(object?.testString, "nil:TestEntity1:2")
|
||||
XCTAssertEqual(object?.testData, ("nil:TestEntity1:2" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!)
|
||||
XCTAssertEqual(object?.testDate, self.dateFormatter.dateFromString("2000-01-02T00:00:00Z")!)
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
transaction.context.reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatImportObjects_CanSkipImport() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
do {
|
||||
|
||||
let sourceArray: [TestEntity1.ImportSource] = [
|
||||
[
|
||||
"testBoolean": NSNumber(bool: true),
|
||||
"testNumber": NSNumber(integer: 1),
|
||||
"testDecimal": NSDecimalNumber(string: "1"),
|
||||
"testString": "nil:TestEntity1:1",
|
||||
"testData": ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")!,
|
||||
"skip_insert": ""
|
||||
],
|
||||
[
|
||||
"testBoolean": NSNumber(bool: false),
|
||||
"testNumber": NSNumber(integer: 2),
|
||||
"testDecimal": NSDecimalNumber(string: "2"),
|
||||
"testString": "nil:TestEntity1:2",
|
||||
"testData": ("nil:TestEntity1:2" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-02T00:00:00Z")!
|
||||
]
|
||||
]
|
||||
let objects = try transaction.importObjects(
|
||||
Into(TestEntity1),
|
||||
sourceArray: sourceArray
|
||||
)
|
||||
XCTAssertEqual(objects.count, 1)
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 1)
|
||||
|
||||
let object = objects[0]
|
||||
let dictionary = sourceArray[1]
|
||||
XCTAssertNil(object.testEntityID)
|
||||
XCTAssertEqual(object.testBoolean, dictionary["testBoolean"] as? NSNumber)
|
||||
XCTAssertEqual(object.testNumber, dictionary["testNumber"] as? NSNumber)
|
||||
XCTAssertEqual(object.testDecimal, dictionary["testDecimal"] as? NSDecimalNumber)
|
||||
XCTAssertEqual(object.testString, dictionary["testString"] as? String)
|
||||
XCTAssertEqual(object.testData, dictionary["testData"] as? NSData)
|
||||
XCTAssertEqual(object.testDate, dictionary["testDate"] as? NSDate)
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
transaction.context.reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatImportObjects_CanThrowError() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
let errorExpectation = self.expectationWithDescription("error")
|
||||
do {
|
||||
|
||||
let sourceArray: [TestEntity1.ImportSource] = [
|
||||
[
|
||||
"testBoolean": NSNumber(bool: true),
|
||||
"testNumber": NSNumber(integer: 1),
|
||||
"testDecimal": NSDecimalNumber(string: "1"),
|
||||
"testString": "nil:TestEntity1:1",
|
||||
"testData": ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")!,
|
||||
"throw_on_insert": ""
|
||||
],
|
||||
[
|
||||
"testBoolean": NSNumber(bool: false),
|
||||
"testNumber": NSNumber(integer: 2),
|
||||
"testDecimal": NSDecimalNumber(string: "2"),
|
||||
"testString": "nil:TestEntity1:2",
|
||||
"testData": ("nil:TestEntity1:2" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-02T00:00:00Z")!
|
||||
]
|
||||
]
|
||||
let _ = try transaction.importObjects(
|
||||
Into(TestEntity1),
|
||||
sourceArray: sourceArray
|
||||
)
|
||||
XCTFail()
|
||||
}
|
||||
catch _ as TestInsertError {
|
||||
|
||||
errorExpectation.fulfill()
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 1)
|
||||
|
||||
let object = transaction.fetchOne(From(TestEntity1))
|
||||
XCTAssertNotNil(object)
|
||||
XCTAssertNil(object?.testEntityID)
|
||||
XCTAssertNil(object?.testBoolean)
|
||||
XCTAssertNil(object?.testNumber)
|
||||
XCTAssertNil(object?.testDecimal)
|
||||
XCTAssertNil(object?.testString)
|
||||
XCTAssertNil(object?.testData)
|
||||
XCTAssertNil(object?.testDate)
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
self.checkExpectationsImmediately()
|
||||
transaction.context.reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatImportObjects_CanImportCorrectly() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
do {
|
||||
|
||||
let sourceArray: [TestEntity1.ImportSource] = [
|
||||
[
|
||||
"testBoolean": NSNumber(bool: true),
|
||||
"testNumber": NSNumber(integer: 1),
|
||||
"testDecimal": NSDecimalNumber(string: "1"),
|
||||
"testString": "nil:TestEntity1:1",
|
||||
"testData": ("nil:TestEntity1:1" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-01T00:00:00Z")!
|
||||
],
|
||||
[
|
||||
"testBoolean": NSNumber(bool: false),
|
||||
"testNumber": NSNumber(integer: 2),
|
||||
"testDecimal": NSDecimalNumber(string: "2"),
|
||||
"testString": "nil:TestEntity1:2",
|
||||
"testData": ("nil:TestEntity1:2" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-02T00:00:00Z")!
|
||||
]
|
||||
]
|
||||
let objects = try transaction.importObjects(
|
||||
Into(TestEntity1),
|
||||
sourceArray: sourceArray
|
||||
)
|
||||
XCTAssertEqual(objects.count, sourceArray.count)
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 2)
|
||||
|
||||
for i in 0 ..< sourceArray.count {
|
||||
|
||||
let object = objects[i]
|
||||
let dictionary = sourceArray[i]
|
||||
|
||||
XCTAssertNil(object.testEntityID)
|
||||
XCTAssertEqual(object.testBoolean, dictionary["testBoolean"] as? NSNumber)
|
||||
XCTAssertEqual(object.testNumber, dictionary["testNumber"] as? NSNumber)
|
||||
XCTAssertEqual(object.testDecimal, dictionary["testDecimal"] as? NSDecimalNumber)
|
||||
XCTAssertEqual(object.testString, dictionary["testString"] as? String)
|
||||
XCTAssertEqual(object.testData, dictionary["testData"] as? NSData)
|
||||
XCTAssertEqual(object.testDate, dictionary["testDate"] as? NSDate)
|
||||
}
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
transaction.context.reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatImportUniqueObject_CanSkipImport() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: [nil])
|
||||
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
do {
|
||||
|
||||
let object = try transaction.importUniqueObject(
|
||||
Into(TestEntity1),
|
||||
source: [
|
||||
"testEntityID": NSNumber(integer: 106),
|
||||
"testBoolean": NSNumber(bool: true),
|
||||
"testNumber": NSNumber(integer: 6),
|
||||
"testDecimal": NSDecimalNumber(string: "6"),
|
||||
"testString": "nil:TestEntity1:6",
|
||||
"testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!,
|
||||
"skip_insert": ""
|
||||
]
|
||||
)
|
||||
XCTAssertNil(object)
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 5)
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
do {
|
||||
|
||||
let object = try transaction.importUniqueObject(
|
||||
Into(TestEntity1),
|
||||
source: [
|
||||
"testEntityID": NSNumber(integer: 105),
|
||||
"testBoolean": NSNumber(bool: false),
|
||||
"testNumber": NSNumber(integer: 6),
|
||||
"testDecimal": NSDecimalNumber(string: "6"),
|
||||
"testString": "nil:TestEntity1:6",
|
||||
"testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!,
|
||||
"skip_update": ""
|
||||
]
|
||||
)
|
||||
XCTAssertNil(object)
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 5)
|
||||
|
||||
let existingObjects = transaction.fetchAll(From(TestEntity1), Where("testEntityID", isEqualTo: 105))
|
||||
XCTAssertNotNil(existingObjects)
|
||||
XCTAssertEqual(existingObjects?.count, 1)
|
||||
|
||||
let existingObject = existingObjects?[0]
|
||||
XCTAssertEqual(existingObject?.testEntityID, NSNumber(integer: 105))
|
||||
XCTAssertEqual(existingObject?.testBoolean, NSNumber(bool: true))
|
||||
XCTAssertEqual(existingObject?.testNumber, NSNumber(integer: 5))
|
||||
XCTAssertEqual(existingObject?.testDecimal, NSDecimalNumber(string: "5"))
|
||||
XCTAssertEqual(existingObject?.testString, "nil:TestEntity1:5")
|
||||
XCTAssertEqual(existingObject?.testData, ("nil:TestEntity1:5" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!)
|
||||
XCTAssertEqual(existingObject?.testDate, self.dateFormatter.dateFromString("2000-01-05T00:00:00Z")!)
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatImportUniqueObject_CanThrowError() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: [nil])
|
||||
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
do {
|
||||
|
||||
let errorExpectation = self.expectationWithDescription("error")
|
||||
do {
|
||||
|
||||
let _ = try transaction.importUniqueObject(
|
||||
Into(TestEntity1),
|
||||
source: [
|
||||
"testEntityID": NSNumber(integer: 106),
|
||||
"testBoolean": NSNumber(bool: true),
|
||||
"testNumber": NSNumber(integer: 6),
|
||||
"testDecimal": NSDecimalNumber(string: "6"),
|
||||
"testString": "nil:TestEntity1:6",
|
||||
"testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!,
|
||||
"throw_on_insert": ""
|
||||
]
|
||||
)
|
||||
XCTFail()
|
||||
}
|
||||
catch _ as TestInsertError {
|
||||
|
||||
errorExpectation.fulfill()
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 6)
|
||||
|
||||
let object = transaction.fetchOne(From(TestEntity1), Where("testEntityID", isEqualTo: 106))
|
||||
XCTAssertNotNil(object)
|
||||
XCTAssertEqual(object?.testEntityID, NSNumber(integer: 106))
|
||||
XCTAssertNil(object?.testBoolean)
|
||||
XCTAssertNil(object?.testNumber)
|
||||
XCTAssertNil(object?.testDecimal)
|
||||
XCTAssertNil(object?.testString)
|
||||
XCTAssertNil(object?.testData)
|
||||
XCTAssertNil(object?.testDate)
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
self.checkExpectationsImmediately()
|
||||
}
|
||||
do {
|
||||
|
||||
let errorExpectation = self.expectationWithDescription("error")
|
||||
do {
|
||||
|
||||
let _ = try transaction.importUniqueObject(
|
||||
Into(TestEntity1),
|
||||
source: [
|
||||
"testEntityID": NSNumber(integer: 105),
|
||||
"testBoolean": NSNumber(bool: false),
|
||||
"testNumber": NSNumber(integer: 6),
|
||||
"testDecimal": NSDecimalNumber(string: "6"),
|
||||
"testString": "nil:TestEntity1:6",
|
||||
"testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!,
|
||||
"throw_on_update": ""
|
||||
]
|
||||
)
|
||||
XCTFail()
|
||||
}
|
||||
catch _ as TestUpdateError {
|
||||
|
||||
errorExpectation.fulfill()
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 6)
|
||||
|
||||
let existingObjects = transaction.fetchAll(From(TestEntity1), Where("testEntityID", isEqualTo: 105))
|
||||
XCTAssertNotNil(existingObjects)
|
||||
XCTAssertEqual(existingObjects?.count, 1)
|
||||
|
||||
let existingObject = existingObjects?[0]
|
||||
XCTAssertNotNil(existingObject)
|
||||
XCTAssertEqual(existingObject?.testEntityID, NSNumber(integer: 105))
|
||||
XCTAssertEqual(existingObject?.testBoolean, NSNumber(bool: true))
|
||||
XCTAssertEqual(existingObject?.testNumber, NSNumber(integer: 5))
|
||||
XCTAssertEqual(existingObject?.testDecimal, NSDecimalNumber(string: "5"))
|
||||
XCTAssertEqual(existingObject?.testString, "nil:TestEntity1:5")
|
||||
XCTAssertEqual(existingObject?.testData, ("nil:TestEntity1:5" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!)
|
||||
XCTAssertEqual(existingObject?.testDate, self.dateFormatter.dateFromString("2000-01-05T00:00:00Z")!)
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
self.checkExpectationsImmediately()
|
||||
}
|
||||
transaction.context.reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatImportUniqueObject_CanImportCorrectly() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: [nil])
|
||||
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
do {
|
||||
|
||||
let object = try transaction.importUniqueObject(
|
||||
Into(TestEntity1),
|
||||
source: [
|
||||
"testEntityID": NSNumber(integer: 106),
|
||||
"testBoolean": NSNumber(bool: true),
|
||||
"testNumber": NSNumber(integer: 6),
|
||||
"testDecimal": NSDecimalNumber(string: "6"),
|
||||
"testString": "nil:TestEntity1:6",
|
||||
"testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!
|
||||
]
|
||||
)
|
||||
XCTAssertNotNil(object)
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 6)
|
||||
|
||||
XCTAssertEqual(object?.testEntityID, NSNumber(integer: 106))
|
||||
XCTAssertEqual(object?.testBoolean, NSNumber(bool: true))
|
||||
XCTAssertEqual(object?.testNumber, NSNumber(integer: 6))
|
||||
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "6"))
|
||||
XCTAssertEqual(object?.testString, "nil:TestEntity1:6")
|
||||
XCTAssertEqual(object?.testData, ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!)
|
||||
XCTAssertEqual(object?.testDate, self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!)
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
do {
|
||||
|
||||
let object = try transaction.importUniqueObject(
|
||||
Into(TestEntity1),
|
||||
source: [
|
||||
"testEntityID": NSNumber(integer: 106),
|
||||
"testBoolean": NSNumber(bool: false),
|
||||
"testNumber": NSNumber(integer: 7),
|
||||
"testDecimal": NSDecimalNumber(string: "7"),
|
||||
"testString": "nil:TestEntity1:7",
|
||||
"testData": ("nil:TestEntity1:7" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-07T00:00:00Z")!,
|
||||
]
|
||||
)
|
||||
XCTAssertNotNil(object)
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 6)
|
||||
|
||||
XCTAssertEqual(object?.testEntityID, NSNumber(integer: 106))
|
||||
XCTAssertEqual(object?.testBoolean, NSNumber(bool: false))
|
||||
XCTAssertEqual(object?.testNumber, NSNumber(integer: 7))
|
||||
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "7"))
|
||||
XCTAssertEqual(object?.testString, "nil:TestEntity1:7")
|
||||
XCTAssertEqual(object?.testData, ("nil:TestEntity1:7" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!)
|
||||
XCTAssertEqual(object?.testDate, self.dateFormatter.dateFromString("2000-01-07T00:00:00Z")!)
|
||||
|
||||
let existingObjects = transaction.fetchAll(From(TestEntity1), Where("testEntityID", isEqualTo: 106))
|
||||
XCTAssertNotNil(existingObjects)
|
||||
XCTAssertEqual(existingObjects?.count, 1)
|
||||
|
||||
let existingObject = existingObjects?[0]
|
||||
XCTAssertEqual(existingObject, object)
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
transaction.context.reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatImportUniqueObjects_CanSkipImport() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: [nil])
|
||||
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
do {
|
||||
|
||||
let sourceArray: [TestEntity1.ImportSource] = [
|
||||
[
|
||||
"testEntityID": NSNumber(integer: 106),
|
||||
"testBoolean": NSNumber(bool: true),
|
||||
"testNumber": NSNumber(integer: 6),
|
||||
"testDecimal": NSDecimalNumber(string: "6"),
|
||||
"testString": "nil:TestEntity1:6",
|
||||
"testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!,
|
||||
"skip_insert": ""
|
||||
],
|
||||
[
|
||||
"testEntityID": NSNumber(integer: 107),
|
||||
"testBoolean": NSNumber(bool: false),
|
||||
"testNumber": NSNumber(integer: 7),
|
||||
"testDecimal": NSDecimalNumber(string: "7"),
|
||||
"testString": "nil:TestEntity1:7",
|
||||
"testData": ("nil:TestEntity1:7" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-07T00:00:00Z")!
|
||||
]
|
||||
]
|
||||
let objects = try transaction.importUniqueObjects(
|
||||
Into(TestEntity1),
|
||||
sourceArray: sourceArray
|
||||
)
|
||||
XCTAssertEqual(objects.count, 1)
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 6)
|
||||
|
||||
let object = objects[0]
|
||||
let dictionary = sourceArray[1]
|
||||
XCTAssertEqual(object.testEntityID, dictionary["testEntityID"] as? NSNumber)
|
||||
XCTAssertEqual(object.testBoolean, dictionary["testBoolean"] as? NSNumber)
|
||||
XCTAssertEqual(object.testNumber, dictionary["testNumber"] as? NSNumber)
|
||||
XCTAssertEqual(object.testDecimal, dictionary["testDecimal"] as? NSDecimalNumber)
|
||||
XCTAssertEqual(object.testString, dictionary["testString"] as? String)
|
||||
XCTAssertEqual(object.testData, dictionary["testData"] as? NSData)
|
||||
XCTAssertEqual(object.testDate, dictionary["testDate"] as? NSDate)
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
transaction.context.reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatImportUniqueObjects_CanThrowError() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: [nil])
|
||||
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
let errorExpectation = self.expectationWithDescription("error")
|
||||
do {
|
||||
|
||||
let sourceArray: [TestEntity1.ImportSource] = [
|
||||
[
|
||||
"testEntityID": NSNumber(integer: 106),
|
||||
"testBoolean": NSNumber(bool: true),
|
||||
"testNumber": NSNumber(integer: 6),
|
||||
"testDecimal": NSDecimalNumber(string: "6"),
|
||||
"testString": "nil:TestEntity1:6",
|
||||
"testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!,
|
||||
"throw_on_id": ""
|
||||
],
|
||||
[
|
||||
"testEntityID": NSNumber(integer: 107),
|
||||
"testBoolean": NSNumber(bool: false),
|
||||
"testNumber": NSNumber(integer: 7),
|
||||
"testDecimal": NSDecimalNumber(string: "7"),
|
||||
"testString": "nil:TestEntity1:7",
|
||||
"testData": ("nil:TestEntity1:7" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-07T00:00:00Z")!
|
||||
]
|
||||
]
|
||||
let _ = try transaction.importUniqueObjects(
|
||||
Into(TestEntity1),
|
||||
sourceArray: sourceArray
|
||||
)
|
||||
XCTFail()
|
||||
}
|
||||
catch _ as TestIDError {
|
||||
|
||||
errorExpectation.fulfill()
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 5)
|
||||
|
||||
XCTAssertNil(transaction.fetchOne(From(TestEntity1), Where("testEntityID", isEqualTo: 106)))
|
||||
XCTAssertNil(transaction.fetchOne(From(TestEntity1), Where("testEntityID", isEqualTo: 107)))
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
self.checkExpectationsImmediately()
|
||||
transaction.context.reset()
|
||||
}
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
let errorExpectation = self.expectationWithDescription("error")
|
||||
do {
|
||||
|
||||
let sourceArray: [TestEntity1.ImportSource] = [
|
||||
[
|
||||
"testEntityID": NSNumber(integer: 106),
|
||||
"testBoolean": NSNumber(bool: true),
|
||||
"testNumber": NSNumber(integer: 6),
|
||||
"testDecimal": NSDecimalNumber(string: "6"),
|
||||
"testString": "nil:TestEntity1:6",
|
||||
"testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!,
|
||||
"throw_on_insert": ""
|
||||
],
|
||||
[
|
||||
"testEntityID": NSNumber(integer: 107),
|
||||
"testBoolean": NSNumber(bool: false),
|
||||
"testNumber": NSNumber(integer: 7),
|
||||
"testDecimal": NSDecimalNumber(string: "7"),
|
||||
"testString": "nil:TestEntity1:7",
|
||||
"testData": ("nil:TestEntity1:7" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-07T00:00:00Z")!
|
||||
]
|
||||
]
|
||||
let _ = try transaction.importUniqueObjects(
|
||||
Into(TestEntity1),
|
||||
sourceArray: sourceArray
|
||||
)
|
||||
XCTFail()
|
||||
}
|
||||
catch _ as TestInsertError {
|
||||
|
||||
errorExpectation.fulfill()
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 7)
|
||||
|
||||
let object = transaction.fetchOne(From(TestEntity1), Where("testEntityID", isEqualTo: 106))
|
||||
XCTAssertNotNil(object)
|
||||
XCTAssertEqual(object?.testEntityID, NSNumber(integer: 106))
|
||||
XCTAssertNil(object?.testBoolean)
|
||||
XCTAssertNil(object?.testNumber)
|
||||
XCTAssertNil(object?.testDecimal)
|
||||
XCTAssertNil(object?.testString)
|
||||
XCTAssertNil(object?.testData)
|
||||
XCTAssertNil(object?.testDate)
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
self.checkExpectationsImmediately()
|
||||
transaction.context.reset()
|
||||
}
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
let errorExpectation = self.expectationWithDescription("error")
|
||||
do {
|
||||
|
||||
let sourceArray: [TestEntity1.ImportSource] = [
|
||||
[
|
||||
"testEntityID": NSNumber(integer: 105),
|
||||
"testBoolean": NSNumber(bool: false),
|
||||
"testNumber": NSNumber(integer: 6),
|
||||
"testDecimal": NSDecimalNumber(string: "6"),
|
||||
"testString": "nil:TestEntity1:6",
|
||||
"testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!,
|
||||
"throw_on_update": ""
|
||||
]
|
||||
]
|
||||
let _ = try transaction.importUniqueObjects(
|
||||
Into(TestEntity1),
|
||||
sourceArray: sourceArray
|
||||
)
|
||||
XCTFail()
|
||||
}
|
||||
catch _ as TestUpdateError {
|
||||
|
||||
errorExpectation.fulfill()
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 5)
|
||||
|
||||
let object = transaction.fetchOne(From(TestEntity1), Where("testEntityID", isEqualTo: 105))
|
||||
XCTAssertNotNil(object)
|
||||
XCTAssertEqual(object?.testEntityID, NSNumber(integer: 105))
|
||||
XCTAssertEqual(object?.testBoolean, NSNumber(bool: true))
|
||||
XCTAssertEqual(object?.testNumber, NSNumber(integer: 5))
|
||||
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "5"))
|
||||
XCTAssertEqual(object?.testString, "nil:TestEntity1:5")
|
||||
XCTAssertEqual(object?.testData, ("nil:TestEntity1:5" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!)
|
||||
XCTAssertEqual(object?.testDate, self.dateFormatter.dateFromString("2000-01-05T00:00:00Z")!)
|
||||
|
||||
let existingObjects = transaction.fetchAll(From(TestEntity1), Where("testEntityID", isEqualTo: 105))
|
||||
XCTAssertNotNil(existingObjects)
|
||||
XCTAssertEqual(existingObjects?.count, 1)
|
||||
|
||||
let existingObject = existingObjects?[0]
|
||||
XCTAssertEqual(existingObject, object)
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
self.checkExpectationsImmediately()
|
||||
transaction.context.reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatImportUniqueObjects_CanImportCorrectly() {
|
||||
|
||||
self.prepareStack { (stack) in
|
||||
|
||||
self.prepareTestDataForStack(stack, configurations: [nil])
|
||||
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
do {
|
||||
|
||||
let sourceArray: [TestEntity1.ImportSource] = [
|
||||
[
|
||||
"testEntityID": NSNumber(integer: 105),
|
||||
"testBoolean": NSNumber(bool: false),
|
||||
"testNumber": NSNumber(integer: 15),
|
||||
"testDecimal": NSDecimalNumber(string: "15"),
|
||||
"testString": "nil:TestEntity1:15",
|
||||
"testData": ("nil:TestEntity1:15" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-15T00:00:00Z")!
|
||||
],
|
||||
[
|
||||
"testEntityID": NSNumber(integer: 106),
|
||||
"testBoolean": NSNumber(bool: false),
|
||||
"testNumber": NSNumber(integer: 6),
|
||||
"testDecimal": NSDecimalNumber(string: "6"),
|
||||
"testString": "nil:TestEntity1:6",
|
||||
"testData": ("nil:TestEntity1:6" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!,
|
||||
"testDate": self.dateFormatter.dateFromString("2000-01-06T00:00:00Z")!
|
||||
]
|
||||
]
|
||||
let objects = try transaction.importUniqueObjects(
|
||||
Into(TestEntity1),
|
||||
sourceArray: sourceArray
|
||||
)
|
||||
XCTAssertEqual(objects.count, sourceArray.count)
|
||||
XCTAssertEqual(transaction.fetchCount(From(TestEntity1)), 6)
|
||||
for i in 0 ..< sourceArray.count {
|
||||
|
||||
let object = objects[i]
|
||||
let dictionary = sourceArray[i]
|
||||
|
||||
XCTAssertEqual(object.testEntityID, dictionary["testEntityID"] as? NSNumber)
|
||||
XCTAssertEqual(object.testBoolean, dictionary["testBoolean"] as? NSNumber)
|
||||
XCTAssertEqual(object.testNumber, dictionary["testNumber"] as? NSNumber)
|
||||
XCTAssertEqual(object.testDecimal, dictionary["testDecimal"] as? NSDecimalNumber)
|
||||
XCTAssertEqual(object.testString, dictionary["testString"] as? String)
|
||||
XCTAssertEqual(object.testData, dictionary["testData"] as? NSData)
|
||||
XCTAssertEqual(object.testDate, dictionary["testDate"] as? NSDate)
|
||||
}
|
||||
let existingObjects = transaction.fetchAll(From(TestEntity1), Where("testEntityID", isEqualTo: 105))
|
||||
XCTAssertNotNil(existingObjects)
|
||||
XCTAssertEqual(existingObjects?.count, 1)
|
||||
|
||||
let existingObject = existingObjects?[0]
|
||||
XCTAssertEqual(existingObject, objects[0])
|
||||
}
|
||||
catch {
|
||||
|
||||
XCTFail()
|
||||
}
|
||||
transaction.context.reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - TestInsertError
|
||||
|
||||
private struct TestInsertError: ErrorType {}
|
||||
|
||||
|
||||
// MARK: - TestUpdateError
|
||||
|
||||
private struct TestUpdateError: ErrorType {}
|
||||
|
||||
|
||||
// MARK: - TestIDError
|
||||
|
||||
private struct TestIDError: ErrorType {}
|
||||
|
||||
|
||||
// MARK: - TestEntity1
|
||||
|
||||
extension TestEntity1: ImportableUniqueObject {
|
||||
|
||||
// MARK: ImportableObject
|
||||
|
||||
typealias ImportSource = [String: AnyObject]
|
||||
|
||||
static func shouldInsertFromImportSource(source: [String: AnyObject], inTransaction transaction: BaseDataTransaction) -> Bool {
|
||||
|
||||
return source["skip_insert"] == nil
|
||||
}
|
||||
|
||||
func didInsertFromImportSource(source: [String: AnyObject], inTransaction transaction: BaseDataTransaction) throws {
|
||||
|
||||
if let _ = source["throw_on_insert"] {
|
||||
|
||||
throw TestInsertError()
|
||||
}
|
||||
self.testBoolean = source["testBoolean"] as? NSNumber
|
||||
self.testNumber = source["testNumber"] as? NSNumber
|
||||
self.testDecimal = source["testDecimal"] as? NSDecimalNumber
|
||||
self.testString = source["testString"] as? String
|
||||
self.testData = source["testData"] as? NSData
|
||||
self.testDate = source["testDate"] as? NSDate
|
||||
self.testNil = nil
|
||||
}
|
||||
|
||||
|
||||
// MARK: ImportableUniqueObject
|
||||
|
||||
typealias UniqueIDType = NSNumber
|
||||
|
||||
static var uniqueIDKeyPath: String {
|
||||
|
||||
return "testEntityID"
|
||||
}
|
||||
|
||||
var uniqueIDValue: NSNumber {
|
||||
|
||||
get {
|
||||
|
||||
guard let ID = self.testEntityID else {
|
||||
|
||||
XCTFail()
|
||||
return 0
|
||||
}
|
||||
return ID
|
||||
}
|
||||
set {
|
||||
|
||||
self.testEntityID = newValue
|
||||
}
|
||||
}
|
||||
|
||||
static func shouldUpdateFromImportSource(source: [String: AnyObject], inTransaction transaction: BaseDataTransaction) -> Bool {
|
||||
|
||||
return source["skip_update"] == nil
|
||||
}
|
||||
|
||||
static func uniqueIDFromImportSource(source: [String: AnyObject], inTransaction transaction: BaseDataTransaction) throws -> NSNumber? {
|
||||
|
||||
if let _ = source["throw_on_id"] {
|
||||
|
||||
throw TestIDError()
|
||||
}
|
||||
return source["testEntityID"] as? NSNumber
|
||||
}
|
||||
|
||||
func updateFromImportSource(source: [String: AnyObject], inTransaction transaction: BaseDataTransaction) throws {
|
||||
|
||||
if let _ = source["throw_on_update"] {
|
||||
|
||||
throw TestUpdateError()
|
||||
}
|
||||
self.testBoolean = source["testBoolean"] as? NSNumber
|
||||
self.testNumber = source["testNumber"] as? NSNumber
|
||||
self.testDecimal = source["testDecimal"] as? NSDecimalNumber
|
||||
self.testString = source["testString"] as? String
|
||||
self.testData = source["testData"] as? NSData
|
||||
self.testDate = source["testDate"] as? NSDate
|
||||
self.testNil = nil
|
||||
}
|
||||
}
|
||||
@@ -4,20 +4,20 @@
|
||||
<attribute name="testBoolean" optional="YES" attributeType="Boolean" syncable="YES"/>
|
||||
<attribute name="testData" optional="YES" attributeType="Binary" syncable="YES"/>
|
||||
<attribute name="testDate" optional="YES" attributeType="Date" syncable="YES"/>
|
||||
<attribute name="testDecimal" optional="YES" attributeType="Decimal" defaultValueString="0.0" syncable="YES"/>
|
||||
<attribute name="testEntityID" attributeType="Integer 64" syncable="YES"/>
|
||||
<attribute name="testDecimal" optional="YES" attributeType="Decimal" syncable="YES"/>
|
||||
<attribute name="testEntityID" optional="YES" attributeType="Integer 64" syncable="YES"/>
|
||||
<attribute name="testNil" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="testNumber" optional="YES" attributeType="Integer 32" defaultValueString="0" syncable="YES"/>
|
||||
<attribute name="testNumber" optional="YES" attributeType="Integer 32" syncable="YES"/>
|
||||
<attribute name="testString" optional="YES" attributeType="String" syncable="YES"/>
|
||||
</entity>
|
||||
<entity name="TestEntity2" representedClassName="CoreStoreTests.TestEntity2" syncable="YES">
|
||||
<attribute name="testBoolean" optional="YES" attributeType="Boolean" syncable="YES"/>
|
||||
<attribute name="testData" optional="YES" attributeType="Binary" syncable="YES"/>
|
||||
<attribute name="testDate" optional="YES" attributeType="Date" syncable="YES"/>
|
||||
<attribute name="testDecimal" optional="YES" attributeType="Decimal" defaultValueString="0.0" syncable="YES"/>
|
||||
<attribute name="testEntityID" attributeType="Integer 64" syncable="YES"/>
|
||||
<attribute name="testDecimal" optional="YES" attributeType="Decimal" syncable="YES"/>
|
||||
<attribute name="testEntityID" optional="YES" attributeType="Integer 64" syncable="YES"/>
|
||||
<attribute name="testNil" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="testNumber" optional="YES" attributeType="Integer 32" defaultValueString="0" syncable="YES"/>
|
||||
<attribute name="testNumber" optional="YES" attributeType="Integer 32" syncable="YES"/>
|
||||
<attribute name="testString" optional="YES" attributeType="String" syncable="YES"/>
|
||||
</entity>
|
||||
<configuration name="Config1">
|
||||
|
||||
37
CoreStoreTests/ObjectObserverTests.swift
Normal file
37
CoreStoreTests/ObjectObserverTests.swift
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// ObjectObserverTests.swift
|
||||
// CoreStore
|
||||
//
|
||||
// Copyright © 2016 John Rommel Estropia
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
@testable
|
||||
import CoreStore
|
||||
|
||||
|
||||
// MARK: - ObjectObserverTests
|
||||
|
||||
class ObjectObserverTests: BaseTestDataTestCase {
|
||||
|
||||
|
||||
}
|
||||
@@ -24,11 +24,10 @@
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import GCDKit
|
||||
|
||||
@testable
|
||||
import CoreStore
|
||||
@testable
|
||||
import GCDKit
|
||||
|
||||
|
||||
//MARK: - TransactionTests
|
||||
@@ -62,7 +61,7 @@ final class TransactionTests: BaseTestCase {
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
self.waitForExpectationsWithTimeout(0, handler: nil)
|
||||
self.checkExpectationsImmediately()
|
||||
|
||||
XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 1)
|
||||
|
||||
@@ -97,7 +96,7 @@ final class TransactionTests: BaseTestCase {
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
self.waitForExpectationsWithTimeout(0, handler: nil)
|
||||
self.checkExpectationsImmediately()
|
||||
|
||||
XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 1)
|
||||
|
||||
@@ -126,7 +125,7 @@ final class TransactionTests: BaseTestCase {
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
self.waitForExpectationsWithTimeout(0, handler: nil)
|
||||
self.checkExpectationsImmediately()
|
||||
|
||||
XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 0)
|
||||
|
||||
@@ -136,6 +135,107 @@ final class TransactionTests: BaseTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatSynchronousTransactions_CanPerformCRUDsInCorrectConfiguration() {
|
||||
|
||||
self.prepareStack(configurations: [nil, "Config1"]) { (stack) in
|
||||
|
||||
let testDate = NSDate()
|
||||
do {
|
||||
|
||||
let createExpectation = self.expectationWithDescription("create")
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
let object = transaction.create(Into<TestEntity1>("Config1"))
|
||||
object.testEntityID = NSNumber(integer: 1)
|
||||
object.testString = "string1"
|
||||
object.testNumber = 100
|
||||
object.testDate = testDate
|
||||
|
||||
switch transaction.commitAndWait() {
|
||||
|
||||
case .Success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges)
|
||||
createExpectation.fulfill()
|
||||
|
||||
default:
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
self.checkExpectationsImmediately()
|
||||
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>("Config1")), 1)
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>(nil)), 0)
|
||||
|
||||
let object = stack.fetchOne(From<TestEntity1>("Config1"))
|
||||
XCTAssertNotNil(object)
|
||||
XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1))
|
||||
XCTAssertEqual(object?.testString, "string1")
|
||||
XCTAssertEqual(object?.testNumber, 100)
|
||||
XCTAssertEqual(object?.testDate, testDate)
|
||||
}
|
||||
do {
|
||||
|
||||
let updateExpectation = self.expectationWithDescription("update")
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
guard let object = transaction.fetchOne(From<TestEntity1>("Config1")) else {
|
||||
|
||||
XCTFail()
|
||||
return
|
||||
}
|
||||
object.testString = "string1_edit"
|
||||
object.testNumber = 200
|
||||
object.testDate = NSDate.distantFuture()
|
||||
|
||||
switch transaction.commitAndWait() {
|
||||
|
||||
case .Success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges)
|
||||
updateExpectation.fulfill()
|
||||
|
||||
default:
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
self.checkExpectationsImmediately()
|
||||
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>("Config1")), 1)
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>(nil)), 0)
|
||||
|
||||
let object = stack.fetchOne(From<TestEntity1>("Config1"))
|
||||
XCTAssertNotNil(object)
|
||||
XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1))
|
||||
XCTAssertEqual(object?.testString, "string1_edit")
|
||||
XCTAssertEqual(object?.testNumber, 200)
|
||||
XCTAssertEqual(object?.testDate, NSDate.distantFuture())
|
||||
}
|
||||
do {
|
||||
|
||||
let deleteExpectation = self.expectationWithDescription("delete")
|
||||
stack.beginSynchronous { (transaction) in
|
||||
|
||||
let object = transaction.fetchOne(From<TestEntity1>("Config1"))
|
||||
transaction.delete(object)
|
||||
|
||||
switch transaction.commitAndWait() {
|
||||
|
||||
case .Success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges)
|
||||
deleteExpectation.fulfill()
|
||||
|
||||
default:
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
self.checkExpectationsImmediately()
|
||||
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>("Config1")), 0)
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>(nil)), 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatSynchronousTransactions_CanDiscardUncommittedChanges() {
|
||||
|
||||
@@ -156,7 +256,7 @@ final class TransactionTests: BaseTestCase {
|
||||
createDiscardExpectation.fulfill()
|
||||
self.expectLogger(loggerExpectations)
|
||||
}
|
||||
self.waitForExpectationsWithTimeout(0, handler: nil)
|
||||
self.checkExpectationsImmediately()
|
||||
|
||||
XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 0)
|
||||
|
||||
@@ -184,7 +284,7 @@ final class TransactionTests: BaseTestCase {
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
self.waitForExpectationsWithTimeout(0, handler: nil)
|
||||
self.checkExpectationsImmediately()
|
||||
}
|
||||
do {
|
||||
|
||||
@@ -204,7 +304,7 @@ final class TransactionTests: BaseTestCase {
|
||||
updateDiscardExpectation.fulfill()
|
||||
self.expectLogger(loggerExpectations)
|
||||
}
|
||||
self.waitForExpectationsWithTimeout(0, handler: nil)
|
||||
self.checkExpectationsImmediately()
|
||||
|
||||
XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 1)
|
||||
|
||||
@@ -231,7 +331,7 @@ final class TransactionTests: BaseTestCase {
|
||||
deleteDiscardExpectation.fulfill()
|
||||
self.expectLogger(loggerExpectations)
|
||||
}
|
||||
self.waitForExpectationsWithTimeout(0, handler: nil)
|
||||
self.checkExpectationsImmediately()
|
||||
|
||||
XCTAssertEqual(stack.fetchCount(From(TestEntity1)), 1)
|
||||
|
||||
@@ -350,7 +450,116 @@ final class TransactionTests: BaseTestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
self.waitForExpectationsWithTimeout(NSTimeInterval(Int8.max), handler: nil)
|
||||
self.waitAndCheckExpectations()
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatAsynchronousTransactions_CanPerformCRUDsInCorrectConfiguration() {
|
||||
|
||||
self.prepareStack(configurations: [nil, "Config1"]) { (stack) in
|
||||
|
||||
let testDate = NSDate()
|
||||
do {
|
||||
|
||||
let createExpectation = self.expectationWithDescription("create")
|
||||
stack.beginAsynchronous { (transaction) in
|
||||
|
||||
let object = transaction.create(Into<TestEntity1>("Config1"))
|
||||
object.testEntityID = NSNumber(integer: 1)
|
||||
object.testString = "string1"
|
||||
object.testNumber = 100
|
||||
object.testDate = testDate
|
||||
|
||||
transaction.commit { (result) in
|
||||
|
||||
switch result {
|
||||
|
||||
case .Success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges)
|
||||
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>("Config1")), 1)
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>(nil)), 0)
|
||||
|
||||
let object = stack.fetchOne(From<TestEntity1>("Config1"))
|
||||
XCTAssertNotNil(object)
|
||||
XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1))
|
||||
XCTAssertEqual(object?.testString, "string1")
|
||||
XCTAssertEqual(object?.testNumber, 100)
|
||||
XCTAssertEqual(object?.testDate, testDate)
|
||||
createExpectation.fulfill()
|
||||
|
||||
default:
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
do {
|
||||
|
||||
let updateExpectation = self.expectationWithDescription("update")
|
||||
stack.beginAsynchronous { (transaction) in
|
||||
|
||||
guard let object = transaction.fetchOne(From<TestEntity1>("Config1")) else {
|
||||
|
||||
XCTFail()
|
||||
return
|
||||
}
|
||||
object.testString = "string1_edit"
|
||||
object.testNumber = 200
|
||||
object.testDate = NSDate.distantFuture()
|
||||
|
||||
transaction.commit { (result) in
|
||||
|
||||
switch result {
|
||||
|
||||
case .Success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges)
|
||||
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>("Config1")), 1)
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>(nil)), 0)
|
||||
|
||||
let object = stack.fetchOne(From<TestEntity1>("Config1"))
|
||||
XCTAssertNotNil(object)
|
||||
XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1))
|
||||
XCTAssertEqual(object?.testString, "string1_edit")
|
||||
XCTAssertEqual(object?.testNumber, 200)
|
||||
XCTAssertEqual(object?.testDate, NSDate.distantFuture())
|
||||
updateExpectation.fulfill()
|
||||
|
||||
default:
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
do {
|
||||
|
||||
let deleteExpectation = self.expectationWithDescription("delete")
|
||||
stack.beginAsynchronous { (transaction) in
|
||||
|
||||
let object = transaction.fetchOne(From<TestEntity1>("Config1"))
|
||||
transaction.delete(object)
|
||||
|
||||
transaction.commit { (result) in
|
||||
|
||||
switch result {
|
||||
|
||||
case .Success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges)
|
||||
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>("Config1")), 0)
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>(nil)), 0)
|
||||
|
||||
deleteExpectation.fulfill()
|
||||
|
||||
default:
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.waitAndCheckExpectations()
|
||||
}
|
||||
|
||||
@objc
|
||||
@@ -458,7 +667,7 @@ final class TransactionTests: BaseTestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
self.waitForExpectationsWithTimeout(NSTimeInterval(Int8.max), handler: nil)
|
||||
self.waitAndCheckExpectations()
|
||||
}
|
||||
|
||||
@objc
|
||||
@@ -542,6 +751,89 @@ final class TransactionTests: BaseTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatUnsafeTransactions_CanPerformCRUDsInCorrectConfiguration() {
|
||||
|
||||
self.prepareStack(configurations: [nil, "Config1"]) { (stack) in
|
||||
|
||||
let transaction = stack.beginUnsafe()
|
||||
|
||||
let testDate = NSDate()
|
||||
do {
|
||||
|
||||
let object = transaction.create(Into<TestEntity1>("Config1"))
|
||||
object.testEntityID = NSNumber(integer: 1)
|
||||
object.testString = "string1"
|
||||
object.testNumber = 100
|
||||
object.testDate = testDate
|
||||
|
||||
switch transaction.commitAndWait() {
|
||||
|
||||
case .Success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges)
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>("Config1")), 1)
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>(nil)), 0)
|
||||
|
||||
let object = stack.fetchOne(From<TestEntity1>("Config1"))
|
||||
XCTAssertNotNil(object)
|
||||
XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1))
|
||||
XCTAssertEqual(object?.testString, "string1")
|
||||
XCTAssertEqual(object?.testNumber, 100)
|
||||
XCTAssertEqual(object?.testDate, testDate)
|
||||
|
||||
default:
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
do {
|
||||
|
||||
guard let object = transaction.fetchOne(From<TestEntity1>("Config1")) else {
|
||||
|
||||
XCTFail()
|
||||
return
|
||||
}
|
||||
object.testString = "string1_edit"
|
||||
object.testNumber = 200
|
||||
object.testDate = NSDate.distantFuture()
|
||||
|
||||
switch transaction.commitAndWait() {
|
||||
|
||||
case .Success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges)
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>("Config1")), 1)
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>(nil)), 0)
|
||||
|
||||
let object = stack.fetchOne(From<TestEntity1>("Config1"))
|
||||
XCTAssertNotNil(object)
|
||||
XCTAssertEqual(object?.testEntityID, NSNumber(integer: 1))
|
||||
XCTAssertEqual(object?.testString, "string1_edit")
|
||||
XCTAssertEqual(object?.testNumber, 200)
|
||||
XCTAssertEqual(object?.testDate, NSDate.distantFuture())
|
||||
|
||||
default:
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
do {
|
||||
|
||||
let object = transaction.fetchOne(From<TestEntity1>("Config1"))
|
||||
transaction.delete(object)
|
||||
|
||||
switch transaction.commitAndWait() {
|
||||
|
||||
case .Success(let hasChanges):
|
||||
XCTAssertTrue(hasChanges)
|
||||
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>("Config1")), 0)
|
||||
XCTAssertEqual(stack.fetchCount(From<TestEntity1>(nil)), 0)
|
||||
|
||||
default:
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
dynamic func test_ThatUnsafeTransactions_CanRollbackChanges() {
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@ public extension BaseDataTransaction {
|
||||
mapping = try cs_autoreleasepool { try preProcess(mapping: mapping) }
|
||||
|
||||
var objects = Dictionary<T.UniqueIDType, T>()
|
||||
for object in self.fetchAll(From(T), Where(T.uniqueIDKeyPath, isMemberOf: mapping.keys)) ?? [] {
|
||||
for object in self.fetchAll(From(T), Where(T.uniqueIDKeyPath, isMemberOf: sortedIDs)) ?? [] {
|
||||
|
||||
try cs_autoreleasepool {
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ internal final class CoreStoreFetchedResultsController: NSFetchedResultsControll
|
||||
|
||||
guard let from = (fetchRequest.entity.flatMap { $0.managedObjectClassName }).flatMap(NSClassFromString).flatMap(From.init) else {
|
||||
|
||||
fatalError("Attempted to create an \(cs_typeName(NSFetchedResultsController)) without a \(cs_typeName(From)) clause or an \(cs_typeName(NSEntityDescription)).")
|
||||
CoreStore.abort("Attempted to create an \(cs_typeName(NSFetchedResultsController)) without a \(cs_typeName(From)) clause or an \(cs_typeName(NSEntityDescription)).")
|
||||
}
|
||||
|
||||
self.reapplyAffectedStores = { fetchRequest, context in
|
||||
|
||||
@@ -38,7 +38,7 @@ internal extension NSManagedObjectModel {
|
||||
|
||||
guard let modelFilePath = bundle.pathForResource(modelName, ofType: "momd") else {
|
||||
|
||||
fatalError("Could not find \"\(modelName).momd\" from the bundle. \(bundle)")
|
||||
CoreStore.abort("Could not find \"\(modelName).momd\" from the bundle. \(bundle)")
|
||||
}
|
||||
|
||||
let modelFileURL = NSURL(fileURLWithPath: modelFilePath)
|
||||
@@ -47,7 +47,7 @@ internal extension NSManagedObjectModel {
|
||||
guard let versionInfo = NSDictionary(contentsOfURL: versionInfoPlistURL),
|
||||
let versionHashes = versionInfo["NSManagedObjectModel_VersionHashes"] as? [String: AnyObject] else {
|
||||
|
||||
fatalError("Could not load \(cs_typeName(NSManagedObjectModel)) metadata from path \"\(versionInfoPlistURL)\".")
|
||||
CoreStore.abort("Could not load \(cs_typeName(NSManagedObjectModel)) metadata from path \"\(versionInfoPlistURL)\".")
|
||||
}
|
||||
|
||||
let modelVersions = Set(versionHashes.keys)
|
||||
@@ -77,7 +77,7 @@ internal extension NSManagedObjectModel {
|
||||
}
|
||||
else {
|
||||
|
||||
fatalError("No model files were found in URL \"\(modelFileURL)\".")
|
||||
CoreStore.abort("No model files were found in URL \"\(modelFileURL)\".")
|
||||
}
|
||||
|
||||
var modelVersionFileURL: NSURL?
|
||||
@@ -106,7 +106,7 @@ internal extension NSManagedObjectModel {
|
||||
return rootModel
|
||||
}
|
||||
|
||||
fatalError("Could not create an \(cs_typeName(NSManagedObjectModel)) from the model at URL \"\(modelFileURL)\".")
|
||||
CoreStore.abort("Could not create an \(cs_typeName(NSManagedObjectModel)) from the model at URL \"\(modelFileURL)\".")
|
||||
}
|
||||
|
||||
@nonobjc
|
||||
|
||||
@@ -70,4 +70,16 @@ public extension CoreStore {
|
||||
functionName: functionName
|
||||
)
|
||||
}
|
||||
|
||||
@noreturn
|
||||
internal static func abort(message: String, fileName: StaticString = #file, lineNumber: Int = #line, functionName: StaticString = #function) {
|
||||
|
||||
self.logger.abort(
|
||||
message,
|
||||
fileName: fileName,
|
||||
lineNumber: lineNumber,
|
||||
functionName: functionName
|
||||
)
|
||||
Swift.fatalError(message, file: fileName, line: UInt(lineNumber))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,17 @@ public protocol CoreStoreLogger {
|
||||
*/
|
||||
func assert(@autoclosure condition: () -> Bool, @autoclosure message: () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
|
||||
|
||||
/**
|
||||
Handles fatal errors made throughout the `CoreStore` framework. The app wil terminate after this method is called.
|
||||
- Important: Implementers may guarantee that the function doesn't return, either by calling another `@noreturn` function such as `fatalError()` or `abort()`, or by raising an exception. If the implementation does not terminate the app, CoreStore will call an internal `fatalError()` to do so.
|
||||
|
||||
- parameter message: the fatal error message
|
||||
- parameter fileName: the source file name
|
||||
- parameter lineNumber: the source line number
|
||||
- parameter functionName: the source function name
|
||||
*/
|
||||
func abort(message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString)
|
||||
|
||||
|
||||
// MARK: Deprecated
|
||||
|
||||
@@ -100,4 +111,9 @@ extension CoreStoreLogger {
|
||||
|
||||
self.log(error: error.bridgeToSwift, message: message, fileName: fileName, lineNumber: lineNumber, functionName: functionName)
|
||||
}
|
||||
|
||||
public func abort(message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
|
||||
|
||||
Swift.fatalError(message, file: fileName, line: UInt(lineNumber))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,22 @@ public final class DefaultLogger: CoreStoreLogger {
|
||||
return
|
||||
}
|
||||
Swift.print("❗ [CoreStore: Assertion Failure] \((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ \(message())\n")
|
||||
Swift.fatalError()
|
||||
Swift.fatalError(file: fileName, line: UInt(lineNumber))
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
Handles fatal errors made throughout the `CoreStore` framework.
|
||||
- Important: This method should be marked `@noreturn` and implementers should guarantee that the function doesn't, either by calling another `@noreturn` function such as `fatalError()` or `abort()`, or by raising an exception.
|
||||
|
||||
- parameter message: the fatal error message
|
||||
- parameter fileName: the source file name
|
||||
- parameter lineNumber: the source line number
|
||||
- parameter functionName: the source function name
|
||||
*/
|
||||
public func abort(message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
|
||||
|
||||
Swift.print("❗ [CoreStore: Fatal Error] \((fileName.stringValue as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ \(message)\n")
|
||||
Swift.fatalError(file: fileName, line: UInt(lineNumber))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,10 +76,10 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
return object
|
||||
|
||||
case (nil, true):
|
||||
fatalError("Attempted to create an entity of type \(cs_typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.")
|
||||
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.")
|
||||
|
||||
default:
|
||||
fatalError("Attempted to create an entity of type \(cs_typeName(entityClass)), but a destination persistent store containing the entity type could not be found.")
|
||||
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)), but a destination persistent store containing the entity type could not be found.")
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -97,16 +97,16 @@ public /*abstract*/ class BaseDataTransaction {
|
||||
return object
|
||||
|
||||
case (nil, true):
|
||||
fatalError("Attempted to create an entity of type \(cs_typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.")
|
||||
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) with ambiguous destination persistent store, but the configuration name was not specified.")
|
||||
|
||||
default:
|
||||
if let configuration = into.configuration {
|
||||
|
||||
fatalError("Attempted to create an entity of type \(cs_typeName(entityClass)) into the configuration \"\(configuration)\", which it doesn't belong to.")
|
||||
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) into the configuration \"\(configuration)\", which it doesn't belong to.")
|
||||
}
|
||||
else {
|
||||
|
||||
fatalError("Attempted to create an entity of type \(cs_typeName(entityClass)) into the default configuration, which it doesn't belong to.")
|
||||
CoreStore.abort("Attempted to create an entity of type \(cs_typeName(entityClass)) into the default configuration, which it doesn't belong to.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user