swift-nio/Tests/NIOPosixTests/SystemTest.swift

177 lines
8.7 KiB
Swift
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-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 XCTest
import NIOCore
@testable import NIOPosix
class SystemTest: XCTestCase {
func testSystemCallWrapperPerformance() throws {
try runSystemCallWrapperPerformanceTest(testAssertFunction: XCTAssert,
debugModeAllowed: true)
}
func testErrorsWorkCorrectly() throws {
try withPipe { readFD, writeFD in
var randomBytes: UInt8 = 42
do {
_ = try withUnsafePointer(to: &randomBytes) { ptr in
try readFD.withUnsafeFileDescriptor { readFD in
try NIOBSDSocket.setsockopt(socket: readFD,
level: NIOBSDSocket.OptionLevel(rawValue: -1),
option_name: NIOBSDSocket.Option(rawValue: -1),
option_value: ptr,
option_len: 0)
}
}
XCTFail("success even though the call was invalid")
} catch let e as IOError {
XCTAssert([ENOTSOCK /* almost everything */, ENOPROTOOPT /* in Qemu */].contains(e.errnoCode))
XCTAssert(e.description.contains("setsockopt"))
XCTAssert(e.description.contains("\(ENOTSOCK)") || e.description.contains("\(ENOPROTOOPT)"))
} catch let e {
XCTFail("wrong error thrown: \(e)")
}
return [readFD, writeFD]
}
}
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
// Example twin data options captured on macOS
private static let cmsghdrExample: [UInt8] = [0x10, 0x00, 0x00, 0x00, // Length 16 including header
0x00, 0x00, 0x00, 0x00, // IPPROTO_IP
0x07, 0x00, 0x00, 0x00, // IP_RECVDSTADDR
0x7F, 0x00, 0x00, 0x01, // 127.0.0.1
0x0D, 0x00, 0x00, 0x00, // Length 13 including header
0x00, 0x00, 0x00, 0x00, // IPPROTO_IP
0x1B, 0x00, 0x00, 0x00, // IP_RECVTOS
0x01, 0x00, 0x00, 0x00] // ECT-1 (1 byte)
private static let cmsghdr_secondStartPosition = 16
private static let cmsghdr_firstDataStart = 12
private static let cmsghdr_firstDataCount = 4
private static let cmsghdr_secondDataCount = 1
private static let cmsghdr_firstType = IP_RECVDSTADDR
private static let cmsghdr_secondType = IP_RECVTOS
#elseif os(Android) && arch(arm)
private static let cmsghdrExample: [UInt8] = [0x10, 0x00, 0x00, 0x00, // Length 16 including header
0x00, 0x00, 0x00, 0x00, // IPPROTO_IP
0x08, 0x00, 0x00, 0x00, // IP_PKTINFO
0x7F, 0x00, 0x00, 0x01, // 127.0.0.1
0x0D, 0x00, 0x00, 0x00, // Length 13 including header
0x00, 0x00, 0x00, 0x00, // IPPROTO_IP
0x01, 0x00, 0x00, 0x00, // IP_TOS
0x01, 0x00, 0x00, 0x00] // ECT-1 (1 byte)
private static let cmsghdr_secondStartPosition = 16
private static let cmsghdr_firstDataStart = 12
private static let cmsghdr_firstDataCount = 4
private static let cmsghdr_secondDataCount = 1
private static let cmsghdr_firstType = IP_PKTINFO
private static let cmsghdr_secondType = IP_TOS
#elseif os(Linux) || os(Android)
// Example twin data options captured on Linux
private static let cmsghdrExample: [UInt8] = [
0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Length 28 including header.
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // IPPROTO_IP, IP_PKTINFO
0x01, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x01, // interface number, 127.0.0.1 (local)
0x7F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, // 127.0.0.1 (destination), 4 bytes to align length
0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Length 17
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // IPPROTO_IP, IP_TOS
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // ECT-1 (1 byte)
]
private static let cmsghdr_secondStartPosition = 32
private static let cmsghdr_firstDataStart = 16
private static let cmsghdr_firstDataCount = 12
private static let cmsghdr_secondDataCount = 1
private static let cmsghdr_firstType = IP_PKTINFO
private static let cmsghdr_secondType = IP_TOS
#else
#error("No cmsg support on this platform.")
#endif
func testCmsgFirstHeader() {
var exampleCmsgHdr = SystemTest.cmsghdrExample
exampleCmsgHdr.withUnsafeMutableBytes { pCmsgHdr in
var msgHdr = msghdr()
msgHdr.msg_control = pCmsgHdr.baseAddress
msgHdr.msg_controllen = .init(pCmsgHdr.count)
withUnsafePointer(to: msgHdr) { pMsgHdr in
let result = NIOBSDSocketControlMessage.firstHeader(inside: pMsgHdr)
XCTAssertEqual(pCmsgHdr.baseAddress, result)
}
}
}
func testCMsgNextHeader() {
var exampleCmsgHdr = SystemTest.cmsghdrExample
exampleCmsgHdr.withUnsafeMutableBytes { pCmsgHdr in
var msgHdr = msghdr()
msgHdr.msg_control = pCmsgHdr.baseAddress
msgHdr.msg_controllen = .init(pCmsgHdr.count)
withUnsafeMutablePointer(to: &msgHdr) { pMsgHdr in
let first = NIOBSDSocketControlMessage.firstHeader(inside: pMsgHdr)
let second = NIOBSDSocketControlMessage.nextHeader(inside: pMsgHdr, after: first!)
let expectedSecondStart = pCmsgHdr.baseAddress! + SystemTest.cmsghdr_secondStartPosition
XCTAssertEqual(expectedSecondStart, second!)
let third = NIOBSDSocketControlMessage.nextHeader(inside: pMsgHdr, after: second!)
XCTAssertEqual(third, nil)
}
}
}
func testCMsgData() {
var exampleCmsgHrd = SystemTest.cmsghdrExample
exampleCmsgHrd.withUnsafeMutableBytes { pCmsgHdr in
var msgHdr = msghdr()
msgHdr.msg_control = pCmsgHdr.baseAddress
msgHdr.msg_controllen = .init(pCmsgHdr.count)
withUnsafePointer(to: msgHdr) { pMsgHdr in
let first = NIOBSDSocketControlMessage.firstHeader(inside: pMsgHdr)
let firstData = NIOBSDSocketControlMessage.data(for: first!)
let expecedFirstData = UnsafeRawBufferPointer(
rebasing: pCmsgHdr[SystemTest.cmsghdr_firstDataStart..<(
SystemTest.cmsghdr_firstDataStart + SystemTest.cmsghdr_firstDataCount)])
XCTAssertEqual(expecedFirstData.baseAddress, firstData?.baseAddress)
XCTAssertEqual(expecedFirstData.count, firstData?.count)
}
}
}
func testCMsgCollection() {
var exampleCmsgHrd = SystemTest.cmsghdrExample
exampleCmsgHrd.withUnsafeMutableBytes { pCmsgHdr in
var msgHdr = msghdr()
msgHdr.msg_control = pCmsgHdr.baseAddress
msgHdr.msg_controllen = .init(pCmsgHdr.count)
let collection = UnsafeControlMessageCollection(messageHeader: msgHdr)
var msgNum = 0
for cmsg in collection {
if msgNum == 0 {
XCTAssertEqual(cmsg.level, .init(IPPROTO_IP))
XCTAssertEqual(cmsg.type, .init(SystemTest.cmsghdr_firstType))
XCTAssertEqual(cmsg.data?.count, SystemTest.cmsghdr_firstDataCount)
} else if msgNum == 1 {
XCTAssertEqual(cmsg.level, .init(IPPROTO_IP))
XCTAssertEqual(cmsg.type, .init(SystemTest.cmsghdr_secondType))
XCTAssertEqual(cmsg.data?.count, SystemTest.cmsghdr_secondDataCount)
}
msgNum += 1
}
XCTAssertEqual(msgNum, 2)
}
}
}