Skip to content

Commit

Permalink
update Codec test
Browse files Browse the repository at this point in the history
  • Loading branch information
MacOMNI committed Dec 4, 2024
1 parent 29b9367 commit 136cf6b
Show file tree
Hide file tree
Showing 5 changed files with 283 additions and 4 deletions.
12 changes: 12 additions & 0 deletions Codec/Sources/Codec/JamEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,16 @@ private class EncodeContext: Encoder {
}
}

fileprivate func encodeOptional(_ value: Encodable) throws {
let mirror = Mirror(reflecting: value)
if let someValue = mirror.children.first?.value as? Encodable {
data.append(UInt8(1)) // Encode presence flag
try encode(someValue) // Encode the unwrapped value
} else {
data.append(UInt8(0)) // Encode absence flag
}
}

fileprivate func encode(_ value: some Encodable) throws {
if let value = value as? Data {
encodeData(value, lengthPrefix: true)
Expand All @@ -94,6 +104,8 @@ private class EncodeContext: Encoder {
encodeData(value.data, lengthPrefix: false)
} else if let value = value as? [Encodable] {
try encodeArray(value)
} else if Mirror(reflecting: value).displayStyle == .optional {
try encodeOptional(value)
} else {
try value.encode(to: self)
}
Expand Down
74 changes: 74 additions & 0 deletions Codec/Tests/CodecTests/DecoderTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import Foundation
import Testing

@testable import Codec

struct DecoderTests {
@Test func decodeData() throws {
let encodedData = Data([3, 0, 1, 2])
let decoded = try JamDecoder.decode(Data.self, from: encodedData)

#expect(decoded == Data([0, 1, 2]))
}

@Test func decodeBool() throws {
let encodedTrue = Data([1])
let encodedFalse = Data([0])

let decodedTrue = try JamDecoder.decode(Bool.self, from: encodedTrue)
let decodedFalse = try JamDecoder.decode(Bool.self, from: encodedFalse)

#expect(decodedTrue == true)
#expect(decodedFalse == false)
}

@Test func decodeString() throws {
let encoded = Data([5, 104, 101, 108, 108, 111])
let decoded = try JamDecoder.decode(String.self, from: encoded)

#expect(decoded == "hello")
}

@Test func decodeArray() throws {
let encoded = Data([3, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0])
let decoded = try JamDecoder.decode([Int].self, from: encoded)

#expect(decoded == [1, 2, 3])
}

@Test func decodeInt() throws {
let encoded = Data([1, 0, 0, 0, 0, 0, 0, 0])
let decoded = try JamDecoder.decode(Int.self, from: encoded)

#expect(decoded == 1)
}

@Test func decodeOptional() throws {
let encodedSome = Data([1, 1, 0, 0, 0, 0, 0, 0, 0])
let encodedNone = Data([0])

let decodedSome = try JamDecoder.decode(Int?.self, from: encodedSome)
let decodedNone = try JamDecoder.decode(Int?.self, from: encodedNone)

#expect(decodedSome == .some(1))
#expect(decodedNone == .none)
}

@Test func decodeFixedWidthInteger() throws {
let encodedInt8 = Data([251])
let encodedUInt64 = Data([21, 205, 91, 7, 0, 0, 0, 0])

let decodedInt8 = try JamDecoder.decode(Int8.self, from: encodedInt8)
let decodedUInt64 = try JamDecoder.decode(UInt64.self, from: encodedUInt64)

#expect(decodedInt8 == -5)
#expect(decodedUInt64 == 123_456_789)
}

@Test func decodeInvalidData() throws {
let invalidEncodedData = Data([0, 0, 0, 123])
#expect(throws: Error.self) {
_ = try JamDecoder.decode(Int8.self, from: invalidEncodedData)
}
}
}
92 changes: 92 additions & 0 deletions Codec/Tests/CodecTests/EncodeSizeTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import Foundation
import Testing

@testable import Codec

extension Int: EncodedSize, @retroactive Error {
public var encodedSize: Int {
MemoryLayout<Int>.size
}

public static var encodeedSizeHint: Int? {
MemoryLayout<Int>.size
}
}

struct EncodeSizeTests {
@Test
func encodeFixedWidthInteger() throws {
#expect(Int(42).encodedSize == MemoryLayout<Int>.size)
#expect(Int8(-5).encodedSize == MemoryLayout<Int8>.size)
#expect(UInt32(123_456).encodedSize == MemoryLayout<UInt32>.size)
#expect(Int.encodeedSizeHint == MemoryLayout<Int>.size)
#expect(Int8.encodeedSizeHint == MemoryLayout<Int8>.size)
#expect(UInt32.encodeedSizeHint == MemoryLayout<UInt32>.size)
}

@Test
func encodeBool() throws {
#expect(true.encodedSize == 1)
#expect(false.encodedSize == 1)
#expect(Bool.encodeedSizeHint == 1)
}

@Test
func encodeStringAndData() throws {
#expect("test".encodedSize == 4)
#expect("".encodedSize == 0)
#expect(Data([0x01, 0x02, 0x03]).encodedSize == 4)
#expect(Data().encodedSize == 1)
#expect(String.encodeedSizeHint == nil)
#expect(Data.encodeedSizeHint == nil)
}

@Test
func encodeArrayAndSet() throws {
let intArray = [1, 2, 3]
let emptyArray: [Int] = []
let intSet: Set<Int> = [4, 5, 6]
let emptySet: Set<Int> = []

#expect(intArray.encodedSize == UInt32(3).variableEncodingLength() + 3 * MemoryLayout<Int>.size)
#expect(emptyArray.encodedSize == UInt32(0).variableEncodingLength())
#expect(intSet.encodedSize >= UInt32(3).variableEncodingLength())
#expect(emptySet.encodedSize == UInt32(0).variableEncodingLength())
#expect([Int].encodeedSizeHint == nil)
#expect(Set<Int>.encodeedSizeHint == nil)
}

@Test
func encodeDictionary() throws {
let dict: [Int: String] = [1: "one", 2: "two"]
let emptyDict: [Int: String] = [:]

let expectedSize = UInt32(2).variableEncodingLength() +
1.encodedSize + "one".encodedSize +
1.encodedSize + "two".encodedSize

#expect(dict.encodedSize == expectedSize)
#expect(emptyDict.encodedSize == UInt32(0).variableEncodingLength())
#expect([Int: String].encodeedSizeHint == nil)
}

@Test
func encodeOptional() throws {
let someValue: Int? = 42
let noneValue: Int? = nil

#expect(someValue.encodedSize == 1 + MemoryLayout<Int>.size)
#expect(noneValue.encodedSize == 1)
#expect(Int?.encodeedSizeHint == nil)
}

@Test
func encodeResult() throws {
let successResult: Result<String, Int> = .success("OK")
let failureResult: Result<String, Int> = .failure(404)

#expect(successResult.encodedSize == 1 + "OK".encodedSize)
#expect(failureResult.encodedSize == 1 + MemoryLayout<Int>.size)
#expect(Result<String, Int>.encodeedSizeHint == nil)
}
}
87 changes: 85 additions & 2 deletions Codec/Tests/CodecTests/EncoderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,94 @@ import Testing

@testable import Codec

// TODO: add more tests
extension Data {
public func toHexString() -> String {
map { String(format: "%02x", $0) }.joined()
}
}

struct EncoderTests {
@Test func encodeData() throws {
let data = Data([0, 1, 2])
let encoded = try JamEncoder.encode(data)
#expect(encoded == Data([3, 0, 1, 2]))
#expect(encoded == Data([3, 0, 1, 2])) // Length prefix of 3 bytes
}

@Test func encodeBool() throws {
let trueValue = true
let falseValue = false

let encodedTrue = try JamEncoder.encode(trueValue)
let encodedFalse = try JamEncoder.encode(falseValue)

#expect(encodedTrue == Data([1])) // True encoded as 1 byte
#expect(encodedFalse == Data([0])) // False encoded as 1 byte
}

@Test func encodeString() throws {
let stringValue = "hello"
let encoded = try JamEncoder.encode(stringValue)

#expect(encoded == Data([5, 104, 101, 108, 108, 111])) // Length prefix of 5 bytes and UTF-8 encoding of "hello"
}

@Test func encodeArray() throws {
let arrayValue: [Int] = [1, 2, 3]
let encoded = try JamEncoder.encode(arrayValue)
#expect(encoded == Data([
3,
1,
0,
0,
0,
0,
0,
0,
0,
2,
0,
0,
0,
0,
0,
0,
0,
3,
0,
0,
0,
0,
0,
0,
0,
])) // Array with length prefix and encoded integers
}

@Test func encodeOptional() throws {
let optionalValue: Int? = 1
let encodedSome = try JamEncoder.encode(optionalValue)

let encodedNone = try JamEncoder.encode(Int?.none)

#expect(encodedSome == Data([1, 1, 0, 0, 0, 0, 0, 0, 0])) // Optional with value encoded
#expect(encodedNone == Data([0])) // None encoded as 1 byte (0)
}

@Test func encodeInt() throws {
let intValue = 123_456_789
let encoded = try JamEncoder.encode(intValue)

#expect(encoded == Data([21, 205, 91, 7, 0, 0, 0, 0])) // Integer with encoded size
}

@Test func encodeFixedWidthInteger() throws {
let int8Value: Int8 = -5
let uint64Value: UInt64 = 123_456_789

let encodedInt8 = try JamEncoder.encode(int8Value)
let encodedUInt64 = try JamEncoder.encode(uint64Value)

#expect(encodedInt8 == Data([251])) // Int8 encoding (signed byte)
#expect(encodedUInt64 == Data([21, 205, 91, 7, 0, 0, 0, 0])) // UInt64 encoding
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 136cf6b

Please sign in to comment.