AgileDB/Tests/AgileDBTests/SyncTests.swift

247 lines
9.5 KiB
Swift

//
// AgileDBSyncTests.swift
// AgileDB
//
// Created by Aaron Bratcher on 1/15/15.
// Copyright (c) 2015 Aaron Bratcher. All rights reserved.
//
import Foundation
import XCTest
@testable import AgileDB
func dbForTestClass(className: String) -> AgileDB {
let pathURL = URL(fileURLWithPath: pathForDB(className: className))
print(pathURL)
let db = AgileDB(fileLocation: pathURL)
return db
}
func pathForDB(className: String) -> String {
let searchPaths = NSSearchPathForDirectoriesInDomains(.downloadsDirectory, .userDomainMask, true)
let documentFolderPath = searchPaths[0]
let dbFilePath = documentFolderPath + "/\(className).db"
return dbFilePath
}
func removeDB(for className: String) {
let path = pathForDB(className: className)
let fileExists = FileManager.default.fileExists(atPath: path)
if fileExists {
try? FileManager.default.removeItem(atPath: path)
}
}
class SyncTests: XCTestCase {
lazy var db: AgileDB = {
return dbForTestClass(className: String(describing: type(of: self)))
}()
override func setUpWithError() throws {
super.setUp()
db.dropAllTables()
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
db.close()
removeDB(for: String(describing: type(of: self)))
}
func testEnableSyncing() {
XCTAssert(db.enableSyncing(), "Could not enable syncing")
}
func testDisableSyncing() {
if !db.enableSyncing() { return }
XCTAssert(db.disableSyncing(), "Could not disable syncing")
}
func testCreateSyncFile() {
_ = db.disableSyncing()
db.dropAllTables()
_ = db.enableSyncing()
db.setValueInTable(DBTable(name: "table8"), for: "testKey1", to: "{\"numValue\":1,\"account\":\"ACCT1\",\"dateValue\":\"2014-8-19T18:23:42.434-05:00\",\"arrayValue\":[1,2,3,4,5]}", autoDeleteAfter: nil)
db.deleteFromTable(DBTable(name: "table8"), for: "testKey1")
db.setValueInTable(DBTable(name: "table9"), for: "testKey2", to: "{\"numValue\":2,\"account\":\"TEST1\",\"dateValue\":\"2014-9-19T18:23:42.434-05:00\",\"arrayValue\":[6,7,8,9,10]}", autoDeleteAfter: nil)
db.setValueInTable(DBTable(name: "table9"), for: "testKey1", to: "{\"numValue\":1,\"account\":\"ACCT1\",\"dateValue\":\"2014-8-19T18:23:42.434-05:00\"}", autoDeleteAfter: nil)
db.setValueInTable(DBTable(name: "table10"), for: "testKey3", to: "{\"numValue\":3,\"account\":\"TEST2\",\"dateValue\":\"2014-10-19T18:23:42.434-05:00\",\"arrayValue\":[11,12,13,14,15]}", autoDeleteAfter: nil)
db.setValueInTable(DBTable(name: "table10"), for: "testKey3", to: "{\"numValue\":3,\"dateValue\":\"2014-10-19T18:23:42.434-05:00\",\"arrayValue\":[11,12]}", autoDeleteAfter: nil)
db.setValueInTable(DBTable(name: "table11"), for: "testKey4", to: "{\"numValue\":4,\"account\":\"TEST3\",\"dateValue\":\"2014-11-19T18:23:42.434-05:00\",\"arrayValue\":[16,17,18,19,20]}", autoDeleteAfter: nil)
db.deleteFromTable(DBTable(name: "table11"), for: "testKey4")
db.setValueInTable(DBTable(name: "table12"), for: "testKey5", to: "{\"numValue\":5,\"account\":\"ACCT3\",\"dateValue\":\"2014-12-19T18:23:42.434-05:00\",\"arrayValue\":[21,22,23,24,25]}", autoDeleteAfter: nil)
db.dropTable("table9")
let searchPaths = NSSearchPathForDirectoriesInDomains(.downloadsDirectory, .userDomainMask, true)
let documentFolderPath = searchPaths[0]
let logFilePath = documentFolderPath + "/testSyncLog.txt"
print(logFilePath)
let fileURL = URL(fileURLWithPath: logFilePath)
let (complete, lastSequence) = db.createSyncFileAtURL(fileURL, lastSequence: 0, targetDBInstanceKey: "TEST-DB-INSTANCE")
XCTAssert(complete, "sync file not completed")
XCTAssert(lastSequence == 10, "lastSequence is incorrect")
// read in file and make sure it is valid JSON
if let fileHandle = FileHandle(forReadingAtPath: logFilePath) {
let dataValue = fileHandle.readDataToEndOfFile()
if let _ = (try? JSONSerialization.jsonObject(with: dataValue, options: .mutableContainers)) as? [String: AnyObject] {
// conversion successful
} else {
XCTAssert(false, "invalid sync file format")
}
} else {
XCTAssert(false, "cannot open file")
}
}
func testProcessSyncFile() {
if !db.disableSyncing() {
XCTFail()
}
if !db.dropAllTables() {
XCTFail()
}
if !db.enableSyncing() {
XCTFail()
}
let table11: DBTable = "table11"
db.setUnsyncedTables([table11])
db.close()
db.open()
XCTAssert(db.unsyncedTables.count == 1)
// will be deleted
db.setValueInTable(DBTable(name: "table8"), for: "testKey1", to: "{\"numValue\":10,\"account\":\"ACCT1\",\"dateValue\":\"2014-8-19T18:23:42.434-05:00\",\"arrayValue\":[1,2,3,4,5]}", autoDeleteAfter: nil)
// these entries will be deleted because of a drop table
db.setValueInTable(DBTable(name: "table9"), for: "testKey2", to: "{\"numValue\":2,\"account\":\"TEST1\",\"dateValue\":\"2014-9-19T18:23:42.434-05:00\",\"arrayValue\":[6,7,8,9,10]}", autoDeleteAfter: nil)
db.setValueInTable(DBTable(name: "table9"), for: "testKey3", to: "{\"numValue\":2,\"account\":\"TEST1\",\"dateValue\":\"2014-9-19T18:23:42.434-05:00\",\"arrayValue\":[6,7,8,9,10]}", autoDeleteAfter: nil)
db.setValueInTable(DBTable(name: "table9"), for: "testKey4", to: "{\"numValue\":2,\"account\":\"TEST1\",\"dateValue\":\"2014-9-19T18:23:42.434-05:00\",\"arrayValue\":[6,7,8,9,10]}", autoDeleteAfter: nil)
db.setValueInTable(DBTable(name: "table9"), for: "testKey5", to: "{\"numValue\":2,\"account\":\"TEST1\",\"dateValue\":\"2014-9-19T18:23:42.434-05:00\",\"arrayValue\":[6,7,8,9,10]}", autoDeleteAfter: nil)
// this value will be unchanged due to timeStamp
db.setValueInTable(DBTable(name: "table10"), for: "testKey3", to: "{\"numValue\":13,\"account\":\"TEST2\",\"dateValue\":\"2014-10-19T18:23:42.434-05:00\",\"arrayValue\":[11,12,13,14,15]}", autoDeleteAfter: nil)
// this value will be updated
db.setValueInTable(DBTable(name: "table12"), for: "testKey5", to: "{\"numValue\":15,\"account\":\"ACCT3\",\"dateValue\":\"2014-12-19T18:23:42.434-05:00\",\"arrayValue\":[21,22,23,24,25]}", autoDeleteAfter: nil)
let syncFileContents = """
{
"sourceDB": "58D200A048F9",
"lastSequence": 1000,
"logEntries": [
{
"timeStamp": "\(AgileDB.stringValueForDate(Date()))",
"key": "testKey1",
"activity": "D",
"tableName": "table8"
},
{
"timeStamp": "2010-01-15T16:22:55.262-05:00",
"value": {
"addedDateTime": "2015-01-15T16:22:55.246-05:00",
"dateValue": "2014-10-19T18:23:42.434-05:00",
"numValue": 3,
"updatedDateTime": "2015-01-15T16:22:55.258-05:00",
"arrayValue": [11,12]
},
"key": "testKey3",
"activity": "U",
"tableName": "table10"
},
{
"timeStamp": "2015-01-15T16:22:55.276-05:00",
"key": "testKey4",
"activity": "D",
"tableName": "table11"
},
{
"timeStamp": "\(AgileDB.stringValueForDate(Date()))",
"value": {
"addedDateTime": "2015-01-15T16:22:55.277-05:00",
"account": "ACCT3",
"dateValue": "2014-12-19T18:23:42.434-05:00",
"numValue": 5,
"updatedDateTime": "2015-01-15T16:22:55.277-05:00",
"arrayValue": [21,22,23,24,25]
},
"key": "testKey5",
"activity": "U",
"tableName": "table12"
},
{
"tableName": "table9",
"activity": "X",
"timeStamp": "\(AgileDB.stringValueForDate(Date()))"
}
]
}
"""
let searchPaths = NSSearchPathForDirectoriesInDomains(.downloadsDirectory, .userDomainMask, true)
let documentFolderPath = searchPaths[0]
let logFilePath = documentFolderPath + "/testSyncLog2.txt"
FileManager.default.createFile(atPath: logFilePath, contents: nil, attributes: nil)
if let fileHandle = FileHandle(forWritingAtPath: logFilePath) {
fileHandle.write(syncFileContents.dataValue() as Data)
fileHandle.closeFile()
let fileURL = URL(fileURLWithPath: logFilePath)
let (results, _, _) = db.processSyncFileAtURL(fileURL, syncProgress: nil)
XCTAssert(results, "sync log not processed")
// check for proper changes
XCTAssert(!db.tableHasKey(table: DBTable(name: "table8"), key: "testKey1")!, "table8 still has entry")
XCTAssert(!db.tableHasKey(table: DBTable(name: "table9"), key: "testKey2")!, "drop table 9 failed")
XCTAssert(!db.tableHasKey(table: DBTable(name: "table9"), key: "testKey3")!, "drop table 9 failed")
XCTAssert(!db.tableHasKey(table: DBTable(name: "table9"), key: "testKey4")!, "drop table 9 failed")
XCTAssert(!db.tableHasKey(table: DBTable(name: "table9"), key: "testKey5")!, "drop table 9 failed")
var jsonValue = db.valueFromTable(DBTable(name: "table10"), for: "testKey3")
// compare dict values
if let jsonValue = jsonValue {
let dataValue = jsonValue.data(using: String.Encoding.utf8, allowLossyConversion: false)!
let objectValues = (try? JSONSerialization.jsonObject(with: dataValue, options: .mutableContainers)) as? [String: AnyObject]
let numValue = objectValues!["numValue"] as! Int
XCTAssert(numValue == 13, "number unexpectedly got changed")
}
jsonValue = db.valueFromTable(DBTable(name: "table12"), for: "testKey5")
// compare dict values
if let jsonValue = jsonValue {
let dataValue = jsonValue.data(using: String.Encoding.utf8, allowLossyConversion: false)!
let objectValues = (try? JSONSerialization.jsonObject(with: dataValue, options: .mutableContainers)) as? [String: AnyObject]
let numValue = objectValues!["numValue"] as! Int
XCTAssert(numValue == 5, "number was not changed")
}
} else {
XCTAssert(false, "unable to create log file")
}
}
}
extension String {
func dataValue() -> Data {
return data(using: .utf8, allowLossyConversion: false)!
}
}