Files
swift-nio/Tests/NIOFoundationCompatTests/Codable+ByteBufferTest.swift
Franz Busch c9756e1083 Adopt swift-format (#2794)
* Apply formatting

* Apply no block comments rule

* Apply OmitExplicitReturns

* Apple OnlyOneTrailingClosureArgument

* Apply NoAssignmentInExpressions

* Fix up DontRepeatTypeInStaticProperties lint errors

* Apply `OrderedImports`

* Apply `ReplaceForEachWithForLoop`

* format file

* Enable the formatting pipeline

* Adopt `AmbiguousTrailingClosureOverload`

* Fix license header

* Fix format check

* Fix `EndOfLineComment`

* Fix CI

* Adapt CI script to check if changes when running formatting

* Separate lint and format into to steps

* Fix format

* Adopt `UseEarlyExits`

* Revert "Adopt `UseEarlyExits`"

This reverts commit d1ac5bbe12.
2024-07-19 11:48:17 +02:00

275 lines
10 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2019-2021 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import Foundation
import NIOCore
import NIOFoundationCompat
import XCTest
class CodableByteBufferTest: XCTestCase {
var buffer: ByteBuffer!
var allocator: ByteBufferAllocator!
var decoder: JSONDecoder!
var encoder: JSONEncoder!
override func setUp() {
self.allocator = ByteBufferAllocator()
self.buffer = self.allocator.buffer(capacity: 1024)
self.buffer.writeString(String(repeating: "A", count: 1024))
self.buffer.moveReaderIndex(to: 129)
self.buffer.moveWriterIndex(to: 129)
self.decoder = JSONDecoder()
self.encoder = JSONEncoder()
}
override func tearDown() {
self.encoder = nil
self.decoder = nil
self.buffer = nil
self.allocator = nil
}
func testSimpleDecode() {
self.buffer.writeString(#"{"string": "hello", "int": 42}"#)
var sAndI: StringAndInt?
XCTAssertNoThrow(sAndI = try self.decoder.decode(StringAndInt.self, from: self.buffer))
XCTAssertEqual(StringAndInt(string: "hello", int: 42), sAndI)
}
func testSimpleEncodeIntoBuffer() {
let expectedSandI = StringAndInt(string: "hello", int: 42)
XCTAssertNoThrow(try self.encoder.encode(expectedSandI, into: &self.buffer))
XCTAssertNoThrow(XCTAssertEqual(expectedSandI, try self.decoder.decode(StringAndInt.self, from: self.buffer)))
}
func testSimpleEncodeToFreshByteBuffer() {
let expectedSandI = StringAndInt(string: "hello", int: 42)
var buffer = self.allocator.buffer(capacity: 0)
XCTAssertNoThrow(buffer = try self.encoder.encodeAsByteBuffer(expectedSandI, allocator: self.allocator))
XCTAssertNoThrow(XCTAssertEqual(expectedSandI, try self.decoder.decode(StringAndInt.self, from: buffer)))
}
func testGetJSONDecodableFromBufferWorks() {
self.buffer.writeString("GARBAGE {}!!? / GARBAGE")
let beginIndex = self.buffer.writerIndex
self.buffer.writeString(#"{"string": "hello", "int": 42}"#)
let endIndex = self.buffer.writerIndex
self.buffer.writeString("GARBAGE {}!!? / GARBAGE")
let expectedSandI = StringAndInt(string: "hello", int: 42)
XCTAssertNoThrow(
XCTAssertEqual(
expectedSandI,
try self.buffer.getJSONDecodable(
StringAndInt.self,
at: beginIndex,
length: endIndex - beginIndex
)
)
)
}
func testGetJSONDecodableFromBufferFailsBecauseShort() {
self.buffer.writeString("GARBAGE {}!!? / GARBAGE")
let beginIndex = self.buffer.writerIndex
self.buffer.writeString(#"{"string": "hello", "int": 42}"#)
let endIndex = self.buffer.writerIndex
XCTAssertThrowsError(
try self.buffer.getJSONDecodable(
StringAndInt.self,
at: beginIndex,
length: endIndex - beginIndex - 1
)
) { error in
XCTAssert(error is DecodingError)
}
}
func testReadJSONDecodableFromBufferWorks() {
let beginIndex = self.buffer.writerIndex
self.buffer.writeString(#"{"string": "hello", "int": 42}"#)
let endIndex = self.buffer.writerIndex
self.buffer.writeString("GARBAGE {}!!? / GARBAGE")
let expectedSandI = StringAndInt(string: "hello", int: 42)
XCTAssertNoThrow(
XCTAssertEqual(
expectedSandI,
try self.buffer.readJSONDecodable(
StringAndInt.self,
length: endIndex - beginIndex
)
)
)
}
func testReadJSONDecodableFromBufferFailsBecauseShort() {
let beginIndex = self.buffer.writerIndex
self.buffer.writeString(#"{"string": "hello", "int": 42}"#)
let endIndex = self.buffer.writerIndex
XCTAssertThrowsError(
try self.buffer.readJSONDecodable(
StringAndInt.self,
length: endIndex - beginIndex - 1
)
) { error in
XCTAssert(error is DecodingError)
}
}
func testReadWriteJSONDecodableWorks() {
let expectedSandI = StringAndInt(string: "hello", int: 42)
self.buffer.writeString("hello")
self.buffer.moveReaderIndex(forwardBy: 5)
var writtenBytes: Int?
XCTAssertNoThrow(writtenBytes = try self.buffer.writeJSONEncodable(expectedSandI))
for _ in 0..<10 {
XCTAssertNoThrow(try self.buffer.writeJSONEncodable(expectedSandI, encoder: JSONEncoder()))
}
for _ in 0..<11 {
XCTAssertNoThrow(try self.buffer.readJSONDecodable(StringAndInt.self, length: writtenBytes ?? -1))
}
XCTAssertEqual(0, self.buffer.readableBytes)
}
func testGetSetJSONDecodableWorks() {
let expectedSandI = StringAndInt(string: "hello", int: 42)
self.buffer.writeString(String(repeating: "{", count: 1000))
var writtenBytes: Int?
XCTAssertNoThrow(
writtenBytes = try self.buffer.setJSONEncodable(
expectedSandI,
at: self.buffer.readerIndex + 123
)
)
XCTAssertNoThrow(
try self.buffer.setJSONEncodable(
expectedSandI,
encoder: JSONEncoder(),
at: self.buffer.readerIndex + 501
)
)
XCTAssertNoThrow(
XCTAssertEqual(
expectedSandI,
try self.buffer.getJSONDecodable(
StringAndInt.self,
at: self.buffer.readerIndex + 123,
length: writtenBytes ?? -1
)
)
)
XCTAssertNoThrow(
XCTAssertEqual(
expectedSandI,
try self.buffer.getJSONDecodable(
StringAndInt.self,
at: self.buffer.readerIndex + 501,
length: writtenBytes ?? -1
)
)
)
}
func testFailingReadsDoNotChangeReaderIndex() {
let expectedSandI = StringAndInt(string: "hello", int: 42)
var writtenBytes: Int?
XCTAssertNoThrow(writtenBytes = try self.buffer.writeJSONEncodable(expectedSandI))
for length in 0..<(writtenBytes ?? 0) {
XCTAssertThrowsError(
try self.buffer.readJSONDecodable(
StringAndInt.self,
length: length
)
) { error in
XCTAssert(error is DecodingError)
}
}
XCTAssertNoThrow(try self.buffer.readJSONDecodable(StringAndInt.self, length: writtenBytes ?? -1))
}
func testCustomEncoderIsRespected() {
let expectedDate = Date(timeIntervalSinceReferenceDate: 86400)
let strategyExpectation = XCTestExpectation(description: "Custom encoding strategy invoked")
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .custom({ date, encoder in
var container = encoder.singleValueContainer()
try container.encode(date.timeIntervalSinceReferenceDate)
strategyExpectation.fulfill()
})
XCTAssertNoThrow(try encoder.encode(["date": expectedDate], into: &self.buffer))
XCTAssertEqual(XCTWaiter().wait(for: [strategyExpectation], timeout: 0.0), .completed)
}
func testCustomDecoderIsRespected() {
let expectedDate = Date(timeIntervalSinceReferenceDate: 86400)
let strategyExpectation = XCTestExpectation(description: "Custom decoding strategy invoked")
let encoder = JSONEncoder()
let decoder = JSONDecoder()
encoder.dateEncodingStrategy = .custom({ date, encoder in
var container = encoder.singleValueContainer()
try container.encode(date.timeIntervalSinceReferenceDate)
})
decoder.dateDecodingStrategy = .custom({ decoder in
strategyExpectation.fulfill()
let container = try decoder.singleValueContainer()
return Date(timeIntervalSinceReferenceDate: try container.decode(Double.self))
})
XCTAssertNoThrow(try encoder.encode(["date": expectedDate], into: &self.buffer))
XCTAssertNoThrow(
XCTAssertEqual(["date": expectedDate], try decoder.decode(Dictionary<String, Date>.self, from: self.buffer))
)
XCTAssertEqual(XCTWaiter().wait(for: [strategyExpectation], timeout: 0.0), .completed)
}
func testCustomCodersAreRespectedWhenUsingReadWriteJSONDecodable() {
let expectedDate = Date(timeIntervalSinceReferenceDate: 86400)
let decoderStrategyExpectation = XCTestExpectation(description: "Custom decoding strategy invoked")
let encoderStrategyExpectation = XCTestExpectation(description: "Custom encoding strategy invoked")
let encoder = JSONEncoder()
let decoder = JSONDecoder()
encoder.dateEncodingStrategy = .custom({ date, encoder in
encoderStrategyExpectation.fulfill()
var container = encoder.singleValueContainer()
try container.encode(date.timeIntervalSinceReferenceDate)
})
decoder.dateDecodingStrategy = .custom({ decoder in
decoderStrategyExpectation.fulfill()
let container = try decoder.singleValueContainer()
return Date(timeIntervalSinceReferenceDate: try container.decode(Double.self))
})
XCTAssertNoThrow(try self.buffer.writeJSONEncodable(["date": expectedDate], encoder: encoder))
XCTAssertNoThrow(
XCTAssertEqual(
["date": expectedDate],
try self.buffer.readJSONDecodable(
Dictionary<String, Date>.self,
decoder: decoder,
length: self.buffer.readableBytes
)
)
)
XCTAssertEqual(XCTWaiter().wait(for: [decoderStrategyExpectation], timeout: 0.0), .completed)
XCTAssertEqual(XCTWaiter().wait(for: [encoderStrategyExpectation], timeout: 0.0), .completed)
}
}
struct StringAndInt: Codable, Equatable {
var string: String
var int: Int
}