yorkie-ios-sdk/Tests/Unit/API/V1/ConverterTests.swift

370 lines
19 KiB
Swift

/*
* Copyright 2022 The Yorkie Authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import XCTest
@testable import Yorkie
class ConverterTests: XCTestCase {
func test_data_to_hexString() {
let array: [UInt8] = [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]
let data = Data(bytes: array, count: array.count)
XCTAssertEqual(data.toHexString, "000102030405aabbccddeeff")
let data2 = Data("Hello world".utf8)
XCTAssertEqual(data2.toHexString, "48656c6c6f20776f726c64")
}
func test_hexString_to_Data() {
let array: [UInt8] = [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]
let data = Data(bytes: array, count: array.count)
let str = "000102030405aabbccddeeff"
XCTAssertEqual(str.toData, data)
// Odd length string.
let strOddLength = "00010"
XCTAssertTrue(strOddLength.toData == nil)
// Invalid string.
let strInvalid = "Hello!"
XCTAssertTrue(strInvalid.toData == nil)
}
func test_hexString() {
let array: [UInt8] = [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]
let data = Data(bytes: array, count: array.count)
XCTAssertEqual(data, data.toHexString.toData)
let str = "000102030405aabbccddeeff"
XCTAssertEqual(str.toData?.toHexString, str)
}
func test_checkpoint() {
let checkpoint = Checkpoint.initial
let converted = Converter.fromCheckpoint(Converter.toCheckpoint(checkpoint))
XCTAssertEqual(checkpoint, converted)
}
func test_changeID() {
let changeID = ChangeID.initial
let converted = Converter.fromChangeID(Converter.toChangeID(changeID))
XCTAssertEqual(changeID.getClientSeq(), converted.getClientSeq())
XCTAssertEqual(changeID.getLamport(), converted.getLamport())
XCTAssertEqual(changeID.getActorID(), converted.getActorID())
XCTAssertEqual(changeID.structureAsString, converted.structureAsString)
XCTAssertEqual(changeID.getLamportAsString(), converted.getLamportAsString())
}
func test_timeTicket() {
let timeTicket = TimeTicket.initial
let converted = Converter.fromTimeTicket(Converter.toTimeTicket(timeTicket))
XCTAssertEqual(timeTicket, converted)
}
func test_chage() {
let addOperation = AddOperation(parentCreatedAt: TimeTicket.initial,
previousCreatedAt: TimeTicket.initial,
value: Primitive(value: .null, createdAt: TimeTicket.initial),
executedAt: TimeTicket.initial)
let change = Change(id: ChangeID.initial, operations: [addOperation], message: "AddOperation")
do {
let converted = try Converter.fromChanges([Converter.toChange(change)]).first
XCTAssertEqual(change.structureAsString, converted?.structureAsString)
} catch {
XCTFail("\(error)")
}
}
func test_chages() {
let setOperation = SetOperation(key: "key",
value: Primitive(value: .null, createdAt: TimeTicket.initial),
parentCreatedAt: TimeTicket.initial,
executedAt: TimeTicket.initial)
let addOperation = AddOperation(parentCreatedAt: TimeTicket.initial,
previousCreatedAt: TimeTicket.initial,
value: Primitive(value: .null, createdAt: TimeTicket.initial),
executedAt: TimeTicket.initial)
let setChange = Change(id: ChangeID.initial, operations: [setOperation], message: "SetOperation")
let addChange = Change(id: setChange.id.next(), operations: [addOperation], message: "AddOperation")
do {
let convertedArray = try Converter.fromChanges(Converter.toChanges([setChange, addChange]))
XCTAssertEqual(setChange.structureAsString, convertedArray[0].structureAsString)
XCTAssertEqual(addChange.structureAsString, convertedArray[1].structureAsString)
} catch {
XCTFail("\(error)")
}
}
func test_chnagePack() {
let addOperation = AddOperation(parentCreatedAt: TimeTicket.initial,
previousCreatedAt: TimeTicket.initial,
value: Primitive(value: .null, createdAt: TimeTicket.initial),
executedAt: TimeTicket.initial)
let change = Change(id: ChangeID.initial, operations: [addOperation], message: "AddOperation")
let changePack = ChangePack(key: "sample", checkpoint: Checkpoint.initial, changes: [change], isRemoved: false)
do {
let converted = try Converter.fromChangePack(Converter.toChangePack(pack: changePack))
XCTAssertEqual(changePack.getChangeSize(), converted.getChangeSize())
XCTAssertEqual(changePack.getChanges().first?.structureAsString, converted.getChanges().first?.structureAsString)
XCTAssertEqual(changePack.getCheckpoint(), converted.getCheckpoint())
XCTAssertEqual(changePack.getDocumentKey(), converted.getDocumentKey())
XCTAssertEqual(changePack.getMinSyncedTicket(), converted.getMinSyncedTicket())
} catch {
XCTFail("\(error)")
}
}
func test_operations() {
let setOperation = SetOperation(key: "key",
value: Primitive(value: .null, createdAt: TimeTicket.initial),
parentCreatedAt: TimeTicket.initial,
executedAt: TimeTicket.initial)
do {
let converted = try Converter.fromOperations([Converter.toOperation(setOperation)]).first as? SetOperation
XCTAssertEqual(setOperation.structureAsString, converted?.structureAsString)
XCTAssertEqual(setOperation.value.toJSON(), converted?.value.toJSON())
XCTAssertEqual(setOperation.key, converted?.key)
XCTAssertEqual(setOperation.effectedCreatedAt, converted?.effectedCreatedAt)
XCTAssertEqual(setOperation.executedAt, converted?.executedAt)
XCTAssertEqual(setOperation.parentCreatedAt, converted?.parentCreatedAt)
} catch {
XCTFail("\(error)")
}
let addOperation = AddOperation(parentCreatedAt: TimeTicket.initial,
previousCreatedAt: TimeTicket.initial,
value: Primitive(value: .null, createdAt: TimeTicket.initial),
executedAt: TimeTicket.initial)
do {
let converted = try Converter.fromOperations([Converter.toOperation(addOperation)]).first as? AddOperation
XCTAssertEqual(addOperation.structureAsString, converted?.structureAsString)
XCTAssertEqual(addOperation.value.toJSON(), converted?.value.toJSON())
XCTAssertEqual(addOperation.previousCreatedAt, converted?.previousCreatedAt)
XCTAssertEqual(addOperation.effectedCreatedAt, converted?.effectedCreatedAt)
XCTAssertEqual(addOperation.executedAt, converted?.executedAt)
XCTAssertEqual(addOperation.parentCreatedAt, converted?.parentCreatedAt)
} catch {
XCTFail("\(error)")
}
let moveOperation = MoveOperation(parentCreatedAt: TimeTicket.initial,
previousCreatedAt: TimeTicket.initial,
createdAt: TimeTicket.initial,
executedAt: TimeTicket.initial)
do {
let converted = try Converter.fromOperations([Converter.toOperation(moveOperation)]).first as? MoveOperation
XCTAssertEqual(moveOperation.structureAsString, converted?.structureAsString)
XCTAssertEqual(moveOperation.previousCreatedAt, converted?.previousCreatedAt)
XCTAssertEqual(moveOperation.effectedCreatedAt, converted?.effectedCreatedAt)
XCTAssertEqual(moveOperation.createdAt, converted?.createdAt)
XCTAssertEqual(moveOperation.executedAt, converted?.executedAt)
XCTAssertEqual(moveOperation.parentCreatedAt, converted?.parentCreatedAt)
} catch {
XCTFail("\(error)")
}
let removeOperation = RemoveOperation(parentCreatedAt: TimeTicket.initial,
createdAt: TimeTicket.initial,
executedAt: TimeTicket.initial)
do {
let converted = try Converter.fromOperations([Converter.toOperation(removeOperation)]).first as? RemoveOperation
XCTAssertEqual(removeOperation.structureAsString, converted?.structureAsString)
XCTAssertEqual(removeOperation.effectedCreatedAt, converted?.effectedCreatedAt)
XCTAssertEqual(removeOperation.createdAt, converted?.createdAt)
XCTAssertEqual(removeOperation.executedAt, converted?.executedAt)
XCTAssertEqual(removeOperation.parentCreatedAt, converted?.parentCreatedAt)
} catch {
XCTFail("\(error)")
}
}
func test_operations_array() {
let setOperation = SetOperation(key: "key",
value: Primitive(value: .null, createdAt: TimeTicket.initial),
parentCreatedAt: TimeTicket.initial,
executedAt: TimeTicket.initial)
let addOperation = AddOperation(parentCreatedAt: TimeTicket.initial,
previousCreatedAt: TimeTicket.initial,
value: Primitive(value: .null, createdAt: TimeTicket.initial),
executedAt: TimeTicket.initial)
let moveOperation = MoveOperation(parentCreatedAt: TimeTicket.initial,
previousCreatedAt: TimeTicket.initial,
createdAt: TimeTicket.initial,
executedAt: TimeTicket.initial)
let removeOperation = RemoveOperation(parentCreatedAt: TimeTicket.initial,
createdAt: TimeTicket.initial,
executedAt: TimeTicket.initial)
do {
let convertedArray = try Converter.fromOperations(Converter.toOperations([setOperation, addOperation, moveOperation, removeOperation]))
if let converted = convertedArray[0] as? SetOperation {
XCTAssertEqual(setOperation.structureAsString, converted.structureAsString)
XCTAssertEqual(setOperation.value.toJSON(), converted.value.toJSON())
XCTAssertEqual(setOperation.key, converted.key)
XCTAssertEqual(setOperation.effectedCreatedAt, converted.effectedCreatedAt)
XCTAssertEqual(setOperation.executedAt, converted.executedAt)
XCTAssertEqual(setOperation.parentCreatedAt, converted.parentCreatedAt)
} else {
XCTFail("Operation Type mismatch!")
}
if let converted = convertedArray[1] as? AddOperation {
XCTAssertEqual(addOperation.structureAsString, converted.structureAsString)
XCTAssertEqual(addOperation.value.toJSON(), converted.value.toJSON())
XCTAssertEqual(addOperation.previousCreatedAt, converted.previousCreatedAt)
XCTAssertEqual(addOperation.effectedCreatedAt, converted.effectedCreatedAt)
XCTAssertEqual(addOperation.executedAt, converted.executedAt)
XCTAssertEqual(addOperation.parentCreatedAt, converted.parentCreatedAt)
} else {
XCTFail("Operation Type mismatch!")
}
if let converted = convertedArray[2] as? MoveOperation {
XCTAssertEqual(moveOperation.structureAsString, converted.structureAsString)
XCTAssertEqual(moveOperation.previousCreatedAt, converted.previousCreatedAt)
XCTAssertEqual(moveOperation.effectedCreatedAt, converted.effectedCreatedAt)
XCTAssertEqual(moveOperation.createdAt, converted.createdAt)
XCTAssertEqual(moveOperation.executedAt, converted.executedAt)
XCTAssertEqual(moveOperation.parentCreatedAt, converted.parentCreatedAt)
} else {
XCTFail("Operation Type mismatch!")
}
if let converted = convertedArray[3] as? RemoveOperation {
XCTAssertEqual(removeOperation.structureAsString, converted.structureAsString)
XCTAssertEqual(removeOperation.effectedCreatedAt, converted.effectedCreatedAt)
XCTAssertEqual(removeOperation.createdAt, converted.createdAt)
XCTAssertEqual(removeOperation.executedAt, converted.executedAt)
XCTAssertEqual(removeOperation.parentCreatedAt, converted.parentCreatedAt)
} else {
XCTFail("Operation Type mismatch!")
}
} catch {
XCTFail("\(error)")
}
}
func test_element() {
// Object Test
let object = CRDTObject(createdAt: TimeTicket.initial)
// Primitive test
object.set(key: "Boolean", value: Primitive(value: PrimitiveValue.boolean(true), createdAt: TimeTicket.initial))
object.set(key: "null", value: Primitive(value: PrimitiveValue.null, createdAt: TimeTicket.initial))
object.set(key: "bytes", value: Primitive(value: PrimitiveValue.bytes(Data("Data String".utf8)), createdAt: TimeTicket.initial))
object.set(key: "int", value: Primitive(value: PrimitiveValue.integer(Int32.max), createdAt: TimeTicket.initial))
object.set(key: "long", value: Primitive(value: PrimitiveValue.long(Int64.max), createdAt: TimeTicket.initial))
object.set(key: "double", value: Primitive(value: PrimitiveValue.double(Double.pi), createdAt: TimeTicket.initial))
object.set(key: "string", value: Primitive(value: PrimitiveValue.string("Hello"), createdAt: TimeTicket.initial))
object.set(key: "date", value: Primitive(value: PrimitiveValue.date(Date()), createdAt: TimeTicket.initial))
// Array Test
let array = CRDTArray(createdAt: TimeTicket.initial)
do {
try array.insert(value: object, afterCreatedAt: TimeTicket.initial)
let converted = try Converter.fromElement(pbElement: Converter.toElement(array)) as? CRDTArray
XCTAssertEqual(try array.get(index: 0).toSortedJSON(), try converted?.get(index: 0).toSortedJSON())
} catch {
XCTFail("\(error)")
}
}
func test_element_simple() {
// Primitive test
let boolean = Primitive(value: PrimitiveValue.boolean(true), createdAt: TimeTicket.initial)
let null = Primitive(value: PrimitiveValue.null, createdAt: TimeTicket.initial)
let bytes = Primitive(value: PrimitiveValue.bytes(Data("Data String".utf8)), createdAt: TimeTicket.initial)
let intValue = Primitive(value: PrimitiveValue.integer(Int32.max), createdAt: TimeTicket.initial)
let longValue = Primitive(value: PrimitiveValue.long(Int64.max), createdAt: TimeTicket.initial)
let doubleValue = Primitive(value: PrimitiveValue.double(Double.pi), createdAt: TimeTicket.initial)
let stringValue = Primitive(value: PrimitiveValue.string("Hello"), createdAt: TimeTicket.initial)
let dateValue = Primitive(value: PrimitiveValue.date(Date()), createdAt: TimeTicket.initial)
do {
var converted = try Converter.fromElementSimple(pbElementSimple: Converter.toElementSimple(boolean))
XCTAssertEqual(boolean.toJSON(), converted.toJSON())
converted = try Converter.fromElementSimple(pbElementSimple: Converter.toElementSimple(null))
XCTAssertEqual(null.toJSON(), converted.toJSON())
converted = try Converter.fromElementSimple(pbElementSimple: Converter.toElementSimple(bytes))
XCTAssertEqual(bytes.toJSON(), converted.toJSON())
converted = try Converter.fromElementSimple(pbElementSimple: Converter.toElementSimple(intValue))
XCTAssertEqual(intValue.toJSON(), converted.toJSON())
converted = try Converter.fromElementSimple(pbElementSimple: Converter.toElementSimple(longValue))
XCTAssertEqual(longValue.toJSON(), converted.toJSON())
converted = try Converter.fromElementSimple(pbElementSimple: Converter.toElementSimple(doubleValue))
XCTAssertEqual(doubleValue.toJSON(), converted.toJSON())
converted = try Converter.fromElementSimple(pbElementSimple: Converter.toElementSimple(stringValue))
XCTAssertEqual(stringValue.toJSON(), converted.toJSON())
converted = try Converter.fromElementSimple(pbElementSimple: Converter.toElementSimple(dateValue))
XCTAssertEqual(dateValue.toJSON(), converted.toJSON())
// Object
let object = CRDTObject(createdAt: TimeTicket.initial)
converted = try Converter.fromElementSimple(pbElementSimple: Converter.toElementSimple(object))
XCTAssertEqual(object.toJSON(), converted.toJSON())
object.set(key: "boolean", value: boolean)
converted = try Converter.fromElementSimple(pbElementSimple: Converter.toElementSimple(object))
XCTAssertEqual(CRDTObject(createdAt: TimeTicket.initial).toJSON(), converted.toJSON())
// Array
let array = CRDTArray(createdAt: TimeTicket.initial)
try array.insert(value: object, afterCreatedAt: TimeTicket.initial)
converted = try Converter.fromElementSimple(pbElementSimple: Converter.toElementSimple(array))
XCTAssertEqual(CRDTArray(createdAt: TimeTicket.initial).toJSON(), converted.toJSON())
} catch {
XCTFail("\(error)")
}
}
func test_presence() {
let samplePresence: Presence = ["a": "str", "b": 10, "c": 0.5, "d": false, "e": ["a", "b", "c"], "f": ""]
let presence = PresenceInfo(clock: Int32.random(in: 0 ... Int32.max), data: samplePresence)
let converted = Converter.fromPresence(pbPresence: Converter.toClient(id: ActorIDs.initial, presence: presence).presence)
XCTAssertEqual(presence.clock, converted.clock)
// swiftlint: disable force_cast
XCTAssert((presence.data as NSDictionary).isEqual(to: (converted.data as NSDictionary) as! [AnyHashable: Any]))
}
}