Skip to content

Commit

Permalink
Hook PipeChannel creation
Browse files Browse the repository at this point in the history
  • Loading branch information
PeterAdams-A committed May 20, 2024
2 parents 2abc803 + cf91b1d commit e5a1255
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 1 deletion.
30 changes: 29 additions & 1 deletion Sources/NIOPosix/Bootstrap.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1926,6 +1926,7 @@ public final class NIOPipeBootstrap {
private var channelInitializer: Optional<ChannelInitializerCallback>
@usableFromInline
internal var _channelOptions: ChannelOptions.Storage
private let hooks: any NIOPipeBootstrapHooks

/// Create a `NIOPipeBootstrap` on the `EventLoopGroup` `group`.
///
Expand Down Expand Up @@ -1956,6 +1957,19 @@ public final class NIOPipeBootstrap {
self._channelOptions = ChannelOptions.Storage()
self.group = group
self.channelInitializer = nil
self.hooks = DefaultNIOPipeBootstrapHooks()
}

/// Initialiser for hooked testing
init?(validatingGroup group: EventLoopGroup, hooks: any NIOPipeBootstrapHooks) {
guard NIOOnSocketsBootstraps.isCompatible(group: group) else {
return nil
}

self._channelOptions = ChannelOptions.Storage()
self.group = group
self.channelInitializer = nil
self.hooks = hooks
}

/// Initialize the connected `PipeChannel` with `initializer`. The most common task in initializer is to add
Expand Down Expand Up @@ -2282,7 +2296,7 @@ extension NIOPipeBootstrap {
inputFileHandle = input.flatMap { NIOFileHandle(descriptor: $0) }
outputFileHandle = output.flatMap { NIOFileHandle(descriptor: $0) }
do {
channel = try PipeChannel(
channel = try self.hooks.makePipeChannel(
eventLoop: eventLoop as! SelectableEventLoop,
inputPipe: inputFileHandle,
outputPipe: outputFileHandle
Expand Down Expand Up @@ -2334,3 +2348,17 @@ extension NIOPipeBootstrap {

@available(*, unavailable)
extension NIOPipeBootstrap: Sendable {}

protocol NIOPipeBootstrapHooks {
func makePipeChannel(eventLoop: SelectableEventLoop,
inputPipe: NIOFileHandle?,
outputPipe: NIOFileHandle?) throws -> PipeChannel;
}

fileprivate struct DefaultNIOPipeBootstrapHooks : NIOPipeBootstrapHooks {
func makePipeChannel(eventLoop: SelectableEventLoop,
inputPipe: NIOFileHandle?,
outputPipe: NIOFileHandle?) throws -> PipeChannel {
return try PipeChannel(eventLoop: eventLoop, inputPipe: inputPipe, outputPipe: outputPipe)
}
}
82 changes: 82 additions & 0 deletions Tests/NIOPosixTests/SALBootstrapTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import XCTest
import NIOCore
@testable import NIOPosix
import Atomics

final class SALBootstrapTest: XCTestCase { //, SALTest {
/* var group: MultiThreadedEventLoopGroup!
var kernelToUserBox: LockedBox<KernelToUser>!
var userToKernelBox: LockedBox<UserToKernel>!
var wakeups: LockedBox<()>!
override func setUp() {
self.setUpSAL()
}
override func tearDown() {
self.tearDownSAL()
}
func testPipeInvalidHandle() throws {
let sock = socket(AF_LOCAL, SOCK_STREAM, 0)
// close(sock)
// There is only one loop in this group
let eventLoop = self.group.next()
let bootstrap = NIOPipeBootstrap(group: self.group)
try eventLoop.runSAL(syscallAssertions: {
try self.assertRegister { selectable, event, Registration in
//XCTAssertEqual([.reset], event)
//print("{sele}")
return true
}
try self.assertDeregister { selectable in
return true
}
try self.assertRegister { selectable, event, Registration in
//XCTAssertEqual([.reset], event)
//print("{sele}")
return true
}
try self.assertDeregister { selectable in
return true
}
try self.assertRegister { selectable, event, Registration in
//XCTAssertEqual([.reset], event)
//print("{sele}")
return true
}
try self.assertDeregister { selectable in
return true
}
}) {
let channelFuture = bootstrap.takingOwnershipOfDescriptor(inputOutput: sock)
let channel = try channelFuture.wait()
}
} */

func testReleaseFileHandleOnOwningFailure() {
let sock = socket(AF_LOCAL, SOCK_STREAM, 0)
defer {
close(sock)
}
let elg = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer {
try! elg.syncShutdownGracefully()
}

let bootstrap = NIOPipeBootstrap(validatingGroup: elg, hooks: NIOPipeBootstrapHooksChannelFail())
XCTAssertNotNil(bootstrap)

let channelFuture = bootstrap?.takingOwnershipOfDescriptor(inputOutput: sock)
XCTAssertThrowsError(try channelFuture?.wait())
}
}


struct NIOPipeBootstrapHooksChannelFail: NIOPipeBootstrapHooks {
func makePipeChannel(eventLoop: NIOPosix.SelectableEventLoop, inputPipe: NIOCore.NIOFileHandle?, outputPipe: NIOCore.NIOFileHandle?) throws -> NIOPosix.PipeChannel {
throw IOError(errnoCode: EBADF, reason: "testing")
}
}

0 comments on commit e5a1255

Please sign in to comment.