Files
SwiftCBOR/Tests/CodableCBOREncoderTests.swift

142 lines
6.8 KiB
Swift

import XCTest
@testable import SwiftCBOR
class CodableCBOREncoderTests: XCTestCase {
func testEncodeNull() {
let encoded = try! CodableCBOREncoder().encode(Optional<String>(nil))
XCTAssertEqual(encoded, Data([0xf6]))
}
func testEncodeBools() {
let falseVal = try! CodableCBOREncoder().encode(false)
XCTAssertEqual(falseVal, Data([0xf4]))
let trueVal = try! CodableCBOREncoder().encode(true)
XCTAssertEqual(trueVal, Data([0xf5]))
}
func testEncodeInts() {
// Less than 24
let zero = try! CodableCBOREncoder().encode(0)
XCTAssertEqual(zero, Data([0x00]))
let eight = try! CodableCBOREncoder().encode(8)
XCTAssertEqual(eight, Data([0x08]))
let ten = try! CodableCBOREncoder().encode(10)
XCTAssertEqual(ten, Data([0x0a]))
let twentyThree = try! CodableCBOREncoder().encode(23)
XCTAssertEqual(twentyThree, Data([0x17]))
// Just bigger than 23
let twentyFour = try! CodableCBOREncoder().encode(24)
XCTAssertEqual(twentyFour, Data([0x18, 0x18]))
let twentyFive = try! CodableCBOREncoder().encode(25)
XCTAssertEqual(twentyFive, Data([0x18, 0x19]))
// Bigger
let hundred = try! CodableCBOREncoder().encode(100)
XCTAssertEqual(hundred, Data([0x18, 0x64]))
let thousand = try! CodableCBOREncoder().encode(1_000)
XCTAssertEqual(thousand, Data([0x19, 0x03, 0xe8]))
let million = try! CodableCBOREncoder().encode(1_000_000)
XCTAssertEqual(million, Data([0x1a, 0x00, 0x0f, 0x42, 0x40]))
let trillion = try! CodableCBOREncoder().encode(1_000_000_000_000)
XCTAssertEqual(trillion, Data([0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00]))
// TODO: Tagged byte strings for big numbers
// let bigNum = try! CodableCBORDecoder().decode(Int.self, from: Data([0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]))
// XCTAssertEqual(bigNum, 18_446_744_073_709_551_615)
// let biggerNum = try! CodableCBORDecoder().decode(Int.self, from: Data([0x2c, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,]))
// XCTAssertEqual(biggerNum, 18_446_744_073_709_551_616)
}
func testEncodeNegativeInts() {
// Less than 24
let minusOne = try! CodableCBOREncoder().encode(-1)
XCTAssertEqual(minusOne, Data([0x20]))
let minusTen = try! CodableCBOREncoder().encode(-10)
XCTAssertEqual(minusTen, Data([0x29]))
// Bigger
let minusHundred = try! CodableCBOREncoder().encode(-100)
XCTAssertEqual(minusHundred, Data([0x38, 0x63]))
let minusThousand = try! CodableCBOREncoder().encode(-1_000)
XCTAssertEqual(minusThousand, Data([0x39, 0x03, 0xe7]))
// TODO: Tagged byte strings for big negative numbers
// let bigNum = try! CodableCBORDecoder().decode(Int.self, from: Data([0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]))
// XCTAssertEqual(bigNum, 18_446_744_073_709_551_615)
// let biggerNum = try! CodableCBORDecoder().decode(Int.self, from: Data([0x2c, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,]))
// XCTAssertEqual(biggerNum, 18_446_744_073_709_551_616)
}
func testEncodeStrings() {
let empty = try! CodableCBOREncoder().encode("")
XCTAssertEqual(empty, Data([0x60]))
let a = try! CodableCBOREncoder().encode("a")
XCTAssertEqual(a, Data([0x61, 0x61]))
let IETF = try! CodableCBOREncoder().encode("IETF")
XCTAssertEqual(IETF, Data([0x64, 0x49, 0x45, 0x54, 0x46]))
let quoteSlash = try! CodableCBOREncoder().encode("\"\\")
XCTAssertEqual(quoteSlash, Data([0x62, 0x22, 0x5c]))
let littleUWithDiaeresis = try! CodableCBOREncoder().encode("\u{00FC}")
XCTAssertEqual(littleUWithDiaeresis, Data([0x62, 0xc3, 0xbc]))
}
func testEncodeByteStrings() {
let fourByteByteString = try! CodableCBOREncoder().encode(Data([0x01, 0x02, 0x03, 0x04]))
XCTAssertEqual(fourByteByteString, Data([0x44, 0x01, 0x02, 0x03, 0x04]))
}
func testEncodeArrays() {
let empty = try! CodableCBOREncoder().encode([String]())
XCTAssertEqual(empty, Data([0x80]))
let oneTwoThree = try! CodableCBOREncoder().encode([1, 2, 3])
XCTAssertEqual(oneTwoThree, Data([0x83, 0x01, 0x02, 0x03]))
let lotsOfInts = try! CodableCBOREncoder().encode([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25])
XCTAssertEqual(lotsOfInts, Data([0x98, 0x19, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19]))
let nestedSimple = try! CodableCBOREncoder().encode([[1], [2, 3], [4, 5]])
XCTAssertEqual(nestedSimple, Data([0x83, 0x81, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05]))
}
func testEncodeMaps() {
let empty = try! CodableCBOREncoder().encode([String: String]())
XCTAssertEqual(empty, Data([0xa0]))
let stringToString = try! CodableCBOREncoder().encode(["a": "A", "b": "B", "c": "C", "d": "D", "e": "E"])
XCTAssertEqual(stringToString.first!, 0xa5)
let dataMinusFirstByte = stringToString[1...].map { $0 }.chunked(into: 4).sorted(by: { $0.lexicographicallyPrecedes($1) })
let dataForKeyValuePairs: [[UInt8]] = [[0x61, 0x61, 0x61, 0x41], [0x61, 0x62, 0x61, 0x42], [0x61, 0x63, 0x61, 0x43], [0x61, 0x64, 0x61, 0x44], [0x61, 0x65, 0x61, 0x45]]
XCTAssertEqual(dataMinusFirstByte, dataForKeyValuePairs)
let oneTwoThreeFour = try! CodableCBOREncoder().encode([1: 2, 3: 4])
XCTAssert(
oneTwoThreeFour == Data([0xa2, 0x01, 0x02, 0x03, 0x04])
|| oneTwoThreeFour == Data([0xa2, 0x03, 0x04, 0x01, 0x02])
)
let encoder = CodableCBOREncoder()
encoder.useStringKeys = true
let encodedWithStringKeys = try! encoder.encode([1: 2, 3: 4])
XCTAssert(encodedWithStringKeys == Data([0xa2, 0x61, 0x31, 0x02, 0x61, 0x33, 0x04]) || encodedWithStringKeys == Data([0xa2, 0x61, 0x33, 0x04, 0x61, 0x31, 0x02]))
}
func testEncodeSimpleStructs() {
struct MyStruct: Codable {
let age: Int
let name: String
}
let encoded = try! CodableCBOREncoder().encode(MyStruct(age: 27, name: "Ham")).map { $0 }
XCTAssert(
encoded == [0xa2, 0x63, 0x61, 0x67, 0x65, 0x18, 0x1b, 0x64, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x48, 0x61, 0x6d]
|| encoded == [0xa2, 0x64, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x48, 0x61, 0x6d, 0x63, 0x61, 0x67, 0x65, 0x18, 0x1b]
)
}
}
extension Array {
func chunked(into size: Int) -> [[Element]] {
return stride(from: 0, to: count, by: size).map {
Array(self[$0 ..< Swift.min($0 + size, count)])
}
}
}