Skip to content

Commit 54dc4b7

Browse files
authored
Merge pull request #136 from swhitty/more-datagram-tests
More datagram tests
2 parents 13778ca + 02e89e5 commit 54dc4b7

File tree

2 files changed

+101
-53
lines changed

2 files changed

+101
-53
lines changed

FlyingSocks/Sources/AsyncSocket.swift

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@
2929
// SOFTWARE.
3030
//
3131

32+
#if canImport(FoundationEssentials)
33+
import FoundationEssentials
34+
#else
3235
import Foundation
36+
#endif
3337

3438
public protocol AsyncSocketPool: Sendable {
3539

@@ -63,19 +67,35 @@ public extension AsyncSocketPool where Self == SocketPool<Poll> {
6367
public struct AsyncSocket: Sendable {
6468

6569
public struct Message: Sendable {
66-
public let peerAddress: any SocketAddress
67-
public let bytes: [UInt8]
68-
public let interfaceIndex: UInt32?
69-
public let localAddress: (any SocketAddress)?
70+
public var peerAddress: any SocketAddress
71+
public var payload: Data
72+
public var interfaceIndex: UInt32?
73+
public var localAddress: (any SocketAddress)?
7074

75+
public init(
76+
peerAddress: any SocketAddress,
77+
payload: Data,
78+
interfaceIndex: UInt32? = nil,
79+
localAddress: (any SocketAddress)? = nil
80+
) {
81+
self.peerAddress = peerAddress
82+
self.payload = payload
83+
self.interfaceIndex = interfaceIndex
84+
self.localAddress = localAddress
85+
}
86+
87+
@available(*, deprecated, renamed: "payload")
88+
public var bytes: [UInt8] { Array(payload) }
89+
90+
@available(*, deprecated, renamed: "init(peerAddress:payload:)")
7191
public init(
7292
peerAddress: any SocketAddress,
7393
bytes: [UInt8],
7494
interfaceIndex: UInt32? = nil,
7595
localAddress: (any SocketAddress)? = nil
7696
) {
7797
self.peerAddress = peerAddress
78-
self.bytes = bytes
98+
self.payload = Data(bytes)
7999
self.interfaceIndex = interfaceIndex
80100
self.localAddress = localAddress
81101
}
@@ -169,7 +189,7 @@ public struct AsyncSocket: Sendable {
169189
repeat {
170190
do {
171191
let (peerAddress, bytes, interfaceIndex, localAddress) = try socket.receive(length: length)
172-
return Message(peerAddress: peerAddress, bytes: bytes, interfaceIndex: interfaceIndex, localAddress: localAddress)
192+
return Message(peerAddress: peerAddress, payload: Data(bytes), interfaceIndex: interfaceIndex, localAddress: localAddress)
173193
} catch SocketError.blocked {
174194
try await pool.suspendSocket(socket, untilReadyFor: .read)
175195
} catch {
@@ -228,11 +248,12 @@ public struct AsyncSocket: Sendable {
228248

229249
#if !canImport(WinSDK)
230250
public func send(
231-
message: [UInt8],
251+
message: some Sequence<UInt8>,
232252
to peerAddress: some SocketAddress,
233253
interfaceIndex: UInt32? = nil,
234254
from localAddress: (any SocketAddress)? = nil
235255
) async throws {
256+
let message = Array(message)
236257
let sent = try await pool.loopUntilReady(for: .write, on: socket) {
237258
try socket.send(message: message, to: peerAddress, interfaceIndex: interfaceIndex, from: localAddress)
238259
}
@@ -241,18 +262,9 @@ public struct AsyncSocket: Sendable {
241262
}
242263
}
243264

244-
public func send(
245-
message: Data,
246-
to peerAddress: some SocketAddress,
247-
interfaceIndex: UInt32? = nil,
248-
from localAddress: (some SocketAddress)? = nil
249-
) async throws {
250-
try await send(message: Array(message), to: peerAddress, interfaceIndex: interfaceIndex, from: localAddress)
251-
}
252-
253265
public func send(message: Message) async throws {
254266
try await send(
255-
message: message.bytes,
267+
message: message.payload,
256268
to: AnySocketAddress(message.peerAddress),
257269
interfaceIndex: message.interfaceIndex,
258270
from: message.localAddress

FlyingSocks/Tests/AsyncSocketTests.swift

Lines changed: 72 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -209,52 +209,43 @@ struct AsyncSocketTests {
209209
}
210210

211211
#if !canImport(WinSDK)
212+
#if canImport(Darwin)
212213
@Test
213-
func datagramSocketReceivesMessageTupleAPI_WhenAvailable() async throws {
214-
let (s1, s2, addr) = try await AsyncSocket.makeDatagramPair()
214+
func messageSequence_sendsMessage_receivesTuple() async throws {
215+
let (socket, port) = try await AsyncSocket.makeLoopbackDatagram()
215216

216-
async let d2: AsyncSocket.Message = s2.receive(atMost: 100)
217-
#if canImport(Darwin)
218-
try await s1.write("Swift".data(using: .utf8)!)
219-
#else
220-
try await s1.send(message: "Swift".data(using: .utf8)!, to: addr, from: addr)
221-
#endif
222-
let v2 = try await d2
223-
#expect(String(data: Data(v2.bytes), encoding: .utf8) == "Swift")
217+
async let received: (any SocketAddress, [UInt8]) = socket.receive(atMost: 100)
224218

225-
try s1.close()
226-
try s2.close()
227-
try? Socket.unlink(addr)
228-
}
229-
#endif
219+
let client = try await AsyncSocket.makeLoopbackDatagram().0
220+
let message = AsyncSocket.Message(peerAddress: .loopback(port: port), payload: "Chips 🍟")
221+
try await client.send(message: message)
230222

231-
#if !canImport(WinSDK)
223+
#expect(
224+
try await received.1 == Array("Chips 🍟".data(using: .utf8)!)
225+
)
226+
}
227+
#else
232228
@Test
233-
func datagramSocketReceivesMessageStructAPI_WhenAvailable() async throws {
229+
func sendMessage_receivesTuple() async throws {
234230
let (s1, s2, addr) = try await AsyncSocket.makeDatagramPair()
235-
let messageToSend = AsyncSocket.Message(
236-
peerAddress: addr,
237-
bytes: Array("Swift".data(using: .utf8)!),
238-
localAddress: addr
239-
)
231+
defer {
232+
try? s1.close()
233+
try? s2.close()
234+
try? Socket.unlink(addr)
235+
}
236+
async let received: (any SocketAddress, [UInt8]) = s2.receive(atMost: 100)
240237

241-
async let d2: AsyncSocket.Message = s2.receive(atMost: 100)
242-
#if canImport(Darwin)
243-
try await s1.write("Swift".data(using: .utf8)!)
244-
#else
245-
try await s1.send(message: messageToSend)
246-
#endif
247-
let v2 = try await d2
248-
#expect(String(data: Data(v2.bytes), encoding: .utf8) == "Swift")
238+
let message = AsyncSocket.Message(peerAddress: addr, payload: "Shrimp 🦐")
239+
try await s1.send(message: message)
249240

250-
try s1.close()
251-
try s2.close()
252-
try? Socket.unlink(addr)
241+
#expect(
242+
try await received.1 == Array("Shrimp 🦐".data(using: .utf8)!)
243+
)
253244
}
254-
#endif
245+
#endif
255246

256247
@Test
257-
func messageSequence_receives_messages() async throws {
248+
func messageSequence_sendsData_receivesMessage() async throws {
258249
let (socket, port) = try await AsyncSocket.makeLoopbackDatagram()
259250
var messages = socket.messages
260251

@@ -267,6 +258,44 @@ struct AsyncSocketTests {
267258
try await received?.payloadString == "Fish 🐡"
268259
)
269260
}
261+
262+
#if canImport(Darwin)
263+
@Test
264+
func messageSequence_sendsMessage_receivesMessage() async throws {
265+
let (socket, port) = try await AsyncSocket.makeLoopbackDatagram()
266+
var messages = socket.messages
267+
268+
async let received = messages.next()
269+
270+
let client = try await AsyncSocket.makeLoopbackDatagram().0
271+
let message = AsyncSocket.Message(peerAddress: .loopback(port: port), payload: "Chips 🍟")
272+
try await client.send(message: message)
273+
274+
#expect(
275+
try await received?.payloadString == "Chips 🍟"
276+
)
277+
}
278+
#else
279+
@Test
280+
func sendMessage_receivesMessage() async throws {
281+
let (s1, s2, addr) = try await AsyncSocket.makeDatagramPair()
282+
defer {
283+
try? s1.close()
284+
try? s2.close()
285+
try? Socket.unlink(addr)
286+
}
287+
288+
async let received: AsyncSocket.Message = s2.receive(atMost: 100)
289+
290+
let message = AsyncSocket.Message(peerAddress: addr, payload: "Shrimp 🦐")
291+
try await s1.send(message: message)
292+
293+
#expect(
294+
try await received.payloadString == "Shrimp 🦐"
295+
)
296+
}
297+
#endif
298+
#endif
270299
}
271300

272301
extension AsyncSocket {
@@ -341,12 +370,19 @@ private extension AsyncSocket.Message {
341370

342371
var payloadString: String {
343372
get throws {
344-
guard let text = String(bytes: bytes, encoding: .utf8) else {
373+
guard let text = String(data: payload, encoding: .utf8) else {
345374
throw SocketError.disconnected
346375
}
347376
return text
348377
}
349378
}
379+
380+
init(peerAddress: some SocketAddress, payload: String) {
381+
self.init(
382+
peerAddress: peerAddress,
383+
payload: payload.data(using: .utf8)!
384+
)
385+
}
350386
}
351387

352388
struct DisconnectedPool: AsyncSocketPool {

0 commit comments

Comments
 (0)