|
|
@@ -16,6 +16,7 @@
|
|
|
|
|
|
import GRPCCore
|
|
|
import NIOCore
|
|
|
+import NIOEmbedded
|
|
|
import NIOHPACK
|
|
|
import XCTest
|
|
|
|
|
|
@@ -238,7 +239,7 @@ final class GRPCStreamClientStateMachineTests: XCTestCase {
|
|
|
// Try to send a message without opening (i.e. without sending initial metadata)
|
|
|
XCTAssertThrowsError(
|
|
|
ofType: RPCError.self,
|
|
|
- try stateMachine.send(message: [])
|
|
|
+ try stateMachine.send(message: [], promise: nil)
|
|
|
) { error in
|
|
|
XCTAssertEqual(error.code, .internalError)
|
|
|
XCTAssertEqual(error.message, "Client not yet open.")
|
|
|
@@ -252,7 +253,7 @@ final class GRPCStreamClientStateMachineTests: XCTestCase {
|
|
|
var stateMachine = self.makeClientStateMachine(targetState: targetState)
|
|
|
|
|
|
// Now send a message
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: []))
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: [], promise: nil))
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -266,7 +267,7 @@ final class GRPCStreamClientStateMachineTests: XCTestCase {
|
|
|
// Try sending another message: it should fail
|
|
|
XCTAssertThrowsError(
|
|
|
ofType: RPCError.self,
|
|
|
- try stateMachine.send(message: [])
|
|
|
+ try stateMachine.send(message: [], promise: nil)
|
|
|
) { error in
|
|
|
XCTAssertEqual(error.code, .internalError)
|
|
|
XCTAssertEqual(error.message, "Client is closed, cannot send a message.")
|
|
|
@@ -624,7 +625,7 @@ final class GRPCStreamClientStateMachineTests: XCTestCase {
|
|
|
|
|
|
XCTAssertThrowsError(
|
|
|
ofType: RPCError.self,
|
|
|
- try stateMachine.nextOutboundMessage()
|
|
|
+ try stateMachine.nextOutboundFrame()
|
|
|
) { error in
|
|
|
XCTAssertEqual(error.code, .internalError)
|
|
|
XCTAssertEqual(error.message, "Client is not open yet.")
|
|
|
@@ -635,9 +636,9 @@ final class GRPCStreamClientStateMachineTests: XCTestCase {
|
|
|
for targetState in [TargetStateMachineState.clientOpenServerIdle, .clientOpenServerOpen] {
|
|
|
var stateMachine = self.makeClientStateMachine(targetState: targetState)
|
|
|
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .awaitMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .awaitMoreMessages)
|
|
|
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: [42, 42]))
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: [42, 42], promise: nil))
|
|
|
|
|
|
let expectedBytes: [UInt8] = [
|
|
|
0, // compression flag: unset
|
|
|
@@ -645,12 +646,12 @@ final class GRPCStreamClientStateMachineTests: XCTestCase {
|
|
|
42, 42, // original message
|
|
|
]
|
|
|
XCTAssertEqual(
|
|
|
- try stateMachine.nextOutboundMessage(),
|
|
|
- .sendMessage(ByteBuffer(bytes: expectedBytes))
|
|
|
+ try stateMachine.nextOutboundFrame(),
|
|
|
+ .sendFrame(frame: ByteBuffer(bytes: expectedBytes), promise: nil)
|
|
|
)
|
|
|
|
|
|
// And then make sure that nothing else is returned anymore
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .awaitMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .awaitMoreMessages)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -660,14 +661,14 @@ final class GRPCStreamClientStateMachineTests: XCTestCase {
|
|
|
compressionEnabled: true
|
|
|
)
|
|
|
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .awaitMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .awaitMoreMessages)
|
|
|
|
|
|
let originalMessage = [UInt8]([42, 42, 43, 43])
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: originalMessage))
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: originalMessage, promise: nil))
|
|
|
|
|
|
- let request = try stateMachine.nextOutboundMessage()
|
|
|
+ let request = try stateMachine.nextOutboundFrame()
|
|
|
let framedMessage = try self.frameMessage(originalMessage, compress: true)
|
|
|
- XCTAssertEqual(request, .sendMessage(framedMessage))
|
|
|
+ XCTAssertEqual(request, .sendFrame(frame: framedMessage, promise: nil))
|
|
|
}
|
|
|
|
|
|
func testNextOutboundMessageWhenClientOpenAndServerOpen_WithCompression() throws {
|
|
|
@@ -676,74 +677,74 @@ final class GRPCStreamClientStateMachineTests: XCTestCase {
|
|
|
compressionEnabled: true
|
|
|
)
|
|
|
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .awaitMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .awaitMoreMessages)
|
|
|
|
|
|
let originalMessage = [UInt8]([42, 42, 43, 43])
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: originalMessage))
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: originalMessage, promise: nil))
|
|
|
|
|
|
- let request = try stateMachine.nextOutboundMessage()
|
|
|
+ let request = try stateMachine.nextOutboundFrame()
|
|
|
let framedMessage = try self.frameMessage(originalMessage, compress: true)
|
|
|
- XCTAssertEqual(request, .sendMessage(framedMessage))
|
|
|
+ XCTAssertEqual(request, .sendFrame(frame: framedMessage, promise: nil))
|
|
|
}
|
|
|
|
|
|
func testNextOutboundMessageWhenClientOpenAndServerClosed() throws {
|
|
|
var stateMachine = self.makeClientStateMachine(targetState: .clientOpenServerClosed)
|
|
|
|
|
|
// No more messages to send
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .noMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .noMoreMessages)
|
|
|
|
|
|
// Queue a message, but assert the action is .noMoreMessages nevertheless,
|
|
|
// because the server is closed.
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: [42, 42]))
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .noMoreMessages)
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: [42, 42], promise: nil))
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .noMoreMessages)
|
|
|
}
|
|
|
|
|
|
func testNextOutboundMessageWhenClientClosedAndServerIdle() throws {
|
|
|
var stateMachine = self.makeClientStateMachine(targetState: .clientOpenServerIdle)
|
|
|
|
|
|
// Send a message and close client
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: [42, 42]))
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: [42, 42], promise: nil))
|
|
|
XCTAssertNoThrow(try stateMachine.closeOutbound())
|
|
|
|
|
|
// Make sure that getting the next outbound message _does_ return the message
|
|
|
// we have enqueued.
|
|
|
- let request = try stateMachine.nextOutboundMessage()
|
|
|
+ let request = try stateMachine.nextOutboundFrame()
|
|
|
let expectedBytes: [UInt8] = [
|
|
|
0, // compression flag: unset
|
|
|
0, 0, 0, 2, // message length: 2 bytes
|
|
|
42, 42, // original message
|
|
|
]
|
|
|
- XCTAssertEqual(request, .sendMessage(ByteBuffer(bytes: expectedBytes)))
|
|
|
+ XCTAssertEqual(request, .sendFrame(frame: ByteBuffer(bytes: expectedBytes), promise: nil))
|
|
|
|
|
|
// And then make sure that nothing else is returned anymore
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .noMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .noMoreMessages)
|
|
|
}
|
|
|
|
|
|
func testNextOutboundMessageWhenClientClosedAndServerOpen() throws {
|
|
|
var stateMachine = self.makeClientStateMachine(targetState: .clientOpenServerOpen)
|
|
|
|
|
|
// Send a message and close client
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: [42, 42]))
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: [42, 42], promise: nil))
|
|
|
XCTAssertNoThrow(try stateMachine.closeOutbound())
|
|
|
|
|
|
// Make sure that getting the next outbound message _does_ return the message
|
|
|
// we have enqueued.
|
|
|
- let request = try stateMachine.nextOutboundMessage()
|
|
|
+ let request = try stateMachine.nextOutboundFrame()
|
|
|
let expectedBytes: [UInt8] = [
|
|
|
0, // compression flag: unset
|
|
|
0, 0, 0, 2, // message length: 2 bytes
|
|
|
42, 42, // original message
|
|
|
]
|
|
|
- XCTAssertEqual(request, .sendMessage(ByteBuffer(bytes: expectedBytes)))
|
|
|
+ XCTAssertEqual(request, .sendFrame(frame: ByteBuffer(bytes: expectedBytes), promise: nil))
|
|
|
|
|
|
// And then make sure that nothing else is returned anymore
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .noMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .noMoreMessages)
|
|
|
}
|
|
|
|
|
|
func testNextOutboundMessageWhenClientClosedAndServerClosed() throws {
|
|
|
var stateMachine = self.makeClientStateMachine(targetState: .clientOpenServerOpen)
|
|
|
// Send a message
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: [42, 42]))
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: [42, 42], promise: nil))
|
|
|
|
|
|
// Close server
|
|
|
XCTAssertNoThrow(try stateMachine.receive(headers: .serverTrailers, endStream: true))
|
|
|
@@ -753,7 +754,7 @@ final class GRPCStreamClientStateMachineTests: XCTestCase {
|
|
|
|
|
|
// Even though we have enqueued a message, don't send it, because the server
|
|
|
// is closed.
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .noMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .noMoreMessages)
|
|
|
}
|
|
|
|
|
|
// - MARK: Next inbound message
|
|
|
@@ -887,13 +888,16 @@ final class GRPCStreamClientStateMachineTests: XCTestCase {
|
|
|
)
|
|
|
|
|
|
// Client sends messages
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .awaitMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .awaitMoreMessages)
|
|
|
|
|
|
let message = [UInt8]([1, 2, 3, 4])
|
|
|
let framedMessage = try self.frameMessage(message, compress: false)
|
|
|
- try stateMachine.send(message: message)
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .sendMessage(framedMessage))
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .awaitMoreMessages)
|
|
|
+ try stateMachine.send(message: message, promise: nil)
|
|
|
+ XCTAssertEqual(
|
|
|
+ try stateMachine.nextOutboundFrame(),
|
|
|
+ .sendFrame(frame: framedMessage, promise: nil)
|
|
|
+ )
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .awaitMoreMessages)
|
|
|
|
|
|
// Server sends response
|
|
|
XCTAssertEqual(stateMachine.nextInboundMessage(), .awaitMoreMessages)
|
|
|
@@ -929,7 +933,7 @@ final class GRPCStreamClientStateMachineTests: XCTestCase {
|
|
|
.receivedStatusAndMetadata(status: .init(code: .ok, message: ""), metadata: receivedMetadata)
|
|
|
)
|
|
|
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .noMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .noMoreMessages)
|
|
|
XCTAssertEqual(stateMachine.nextInboundMessage(), .noMoreMessages)
|
|
|
}
|
|
|
|
|
|
@@ -951,14 +955,17 @@ final class GRPCStreamClientStateMachineTests: XCTestCase {
|
|
|
)
|
|
|
|
|
|
// Client sends messages and ends
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .awaitMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .awaitMoreMessages)
|
|
|
|
|
|
let message = [UInt8]([1, 2, 3, 4])
|
|
|
let framedMessage = try self.frameMessage(message, compress: false)
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: message))
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: message, promise: nil))
|
|
|
XCTAssertNoThrow(try stateMachine.closeOutbound())
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .sendMessage(framedMessage))
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .noMoreMessages)
|
|
|
+ XCTAssertEqual(
|
|
|
+ try stateMachine.nextOutboundFrame(),
|
|
|
+ .sendFrame(frame: framedMessage, promise: nil)
|
|
|
+ )
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .noMoreMessages)
|
|
|
|
|
|
// Server sends initial metadata
|
|
|
let serverInitialHeadersAction = try stateMachine.receive(
|
|
|
@@ -1005,7 +1012,7 @@ final class GRPCStreamClientStateMachineTests: XCTestCase {
|
|
|
.receivedStatusAndMetadata(status: .init(code: .ok, message: ""), metadata: receivedMetadata)
|
|
|
)
|
|
|
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .noMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .noMoreMessages)
|
|
|
XCTAssertEqual(stateMachine.nextInboundMessage(), .noMoreMessages)
|
|
|
}
|
|
|
|
|
|
@@ -1027,13 +1034,16 @@ final class GRPCStreamClientStateMachineTests: XCTestCase {
|
|
|
)
|
|
|
|
|
|
// Client sends messages
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .awaitMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .awaitMoreMessages)
|
|
|
|
|
|
let message = [UInt8]([1, 2, 3, 4])
|
|
|
let framedMessage = try self.frameMessage(message, compress: false)
|
|
|
- try stateMachine.send(message: message)
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .sendMessage(framedMessage))
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .awaitMoreMessages)
|
|
|
+ try stateMachine.send(message: message, promise: nil)
|
|
|
+ XCTAssertEqual(
|
|
|
+ try stateMachine.nextOutboundFrame(),
|
|
|
+ .sendFrame(frame: framedMessage, promise: nil)
|
|
|
+ )
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .awaitMoreMessages)
|
|
|
|
|
|
// Server sends initial metadata
|
|
|
let serverInitialHeadersAction = try stateMachine.receive(
|
|
|
@@ -1083,7 +1093,7 @@ final class GRPCStreamClientStateMachineTests: XCTestCase {
|
|
|
.receivedStatusAndMetadata(status: .init(code: .ok, message: ""), metadata: receivedMetadata)
|
|
|
)
|
|
|
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .noMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .noMoreMessages)
|
|
|
XCTAssertEqual(stateMachine.nextInboundMessage(), .noMoreMessages)
|
|
|
}
|
|
|
}
|
|
|
@@ -1242,7 +1252,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
|
|
|
XCTAssertThrowsError(
|
|
|
ofType: RPCError.self,
|
|
|
- try stateMachine.send(message: [])
|
|
|
+ try stateMachine.send(message: [], promise: nil)
|
|
|
) { error in
|
|
|
XCTAssertEqual(error.code, .internalError)
|
|
|
XCTAssertEqual(
|
|
|
@@ -1258,7 +1268,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
// Now send a message
|
|
|
XCTAssertThrowsError(
|
|
|
ofType: RPCError.self,
|
|
|
- try stateMachine.send(message: [])
|
|
|
+ try stateMachine.send(message: [], promise: nil)
|
|
|
) { error in
|
|
|
XCTAssertEqual(error.code, .internalError)
|
|
|
XCTAssertEqual(
|
|
|
@@ -1272,7 +1282,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
var stateMachine = self.makeServerStateMachine(targetState: .clientOpenServerOpen)
|
|
|
|
|
|
// Now send a message
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: []))
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: [], promise: nil))
|
|
|
}
|
|
|
|
|
|
func testSendMessageWhenClientOpenAndServerClosed() {
|
|
|
@@ -1281,7 +1291,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
// Try sending another message: it should fail
|
|
|
XCTAssertThrowsError(
|
|
|
ofType: RPCError.self,
|
|
|
- try stateMachine.send(message: [])
|
|
|
+ try stateMachine.send(message: [], promise: nil)
|
|
|
) { error in
|
|
|
XCTAssertEqual(error.code, .internalError)
|
|
|
XCTAssertEqual(error.message, "Server can't send a message if it's closed.")
|
|
|
@@ -1293,7 +1303,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
|
|
|
XCTAssertThrowsError(
|
|
|
ofType: RPCError.self,
|
|
|
- try stateMachine.send(message: [])
|
|
|
+ try stateMachine.send(message: [], promise: nil)
|
|
|
) { error in
|
|
|
XCTAssertEqual(error.code, .internalError)
|
|
|
XCTAssertEqual(
|
|
|
@@ -1308,7 +1318,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
|
|
|
// Try sending a message: even though client is closed, we should send it
|
|
|
// because it may be expecting a response.
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: []))
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: [], promise: nil))
|
|
|
}
|
|
|
|
|
|
func testSendMessageWhenClientClosedAndServerClosed() {
|
|
|
@@ -1317,7 +1327,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
// Try sending another message: it should fail
|
|
|
XCTAssertThrowsError(
|
|
|
ofType: RPCError.self,
|
|
|
- try stateMachine.send(message: [])
|
|
|
+ try stateMachine.send(message: [], promise: nil)
|
|
|
) { error in
|
|
|
XCTAssertEqual(error.code, .internalError)
|
|
|
XCTAssertEqual(error.message, "Server can't send a message if it's closed.")
|
|
|
@@ -1363,7 +1373,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
// Try sending another message: it should fail because server is now closed.
|
|
|
XCTAssertThrowsError(
|
|
|
ofType: RPCError.self,
|
|
|
- try stateMachine.send(message: [])
|
|
|
+ try stateMachine.send(message: [], promise: nil)
|
|
|
) { error in
|
|
|
XCTAssertEqual(error.code, .internalError)
|
|
|
XCTAssertEqual(error.message, "Server can't send a message if it's closed.")
|
|
|
@@ -1385,7 +1395,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
// Try sending another message: it should fail because server is now closed.
|
|
|
XCTAssertThrowsError(
|
|
|
ofType: RPCError.self,
|
|
|
- try stateMachine.send(message: [])
|
|
|
+ try stateMachine.send(message: [], promise: nil)
|
|
|
) { error in
|
|
|
XCTAssertEqual(error.code, .internalError)
|
|
|
XCTAssertEqual(error.message, "Server can't send a message if it's closed.")
|
|
|
@@ -1429,7 +1439,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
// Try sending another message: it should fail because server is now closed.
|
|
|
XCTAssertThrowsError(
|
|
|
ofType: RPCError.self,
|
|
|
- try stateMachine.send(message: [])
|
|
|
+ try stateMachine.send(message: [], promise: nil)
|
|
|
) { error in
|
|
|
XCTAssertEqual(error.code, .internalError)
|
|
|
XCTAssertEqual(error.message, "Server can't send a message if it's closed.")
|
|
|
@@ -1451,7 +1461,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
// Try sending another message: it should fail because server is now closed.
|
|
|
XCTAssertThrowsError(
|
|
|
ofType: RPCError.self,
|
|
|
- try stateMachine.send(message: [])
|
|
|
+ try stateMachine.send(message: [], promise: nil)
|
|
|
) { error in
|
|
|
XCTAssertEqual(error.code, .internalError)
|
|
|
XCTAssertEqual(error.message, "Server can't send a message if it's closed.")
|
|
|
@@ -1873,7 +1883,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
|
|
|
XCTAssertThrowsError(
|
|
|
ofType: RPCError.self,
|
|
|
- try stateMachine.nextOutboundMessage()
|
|
|
+ try stateMachine.nextOutboundFrame()
|
|
|
) { error in
|
|
|
XCTAssertEqual(error.code, .internalError)
|
|
|
XCTAssertEqual(error.message, "Server is not open yet.")
|
|
|
@@ -1885,7 +1895,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
|
|
|
XCTAssertThrowsError(
|
|
|
ofType: RPCError.self,
|
|
|
- try stateMachine.nextOutboundMessage()
|
|
|
+ try stateMachine.nextOutboundFrame()
|
|
|
) { error in
|
|
|
XCTAssertEqual(error.code, .internalError)
|
|
|
XCTAssertEqual(error.message, "Server is not open yet.")
|
|
|
@@ -1897,7 +1907,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
|
|
|
XCTAssertThrowsError(
|
|
|
ofType: RPCError.self,
|
|
|
- try stateMachine.nextOutboundMessage()
|
|
|
+ try stateMachine.nextOutboundFrame()
|
|
|
) { error in
|
|
|
XCTAssertEqual(error.code, .internalError)
|
|
|
XCTAssertEqual(error.message, "Server is not open yet.")
|
|
|
@@ -1907,20 +1917,20 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
func testNextOutboundMessageWhenClientOpenAndServerOpen() throws {
|
|
|
var stateMachine = self.makeServerStateMachine(targetState: .clientOpenServerOpen)
|
|
|
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .awaitMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .awaitMoreMessages)
|
|
|
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: [42, 42]))
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: [42, 42], promise: nil))
|
|
|
|
|
|
- let response = try stateMachine.nextOutboundMessage()
|
|
|
+ let response = try stateMachine.nextOutboundFrame()
|
|
|
let expectedBytes: [UInt8] = [
|
|
|
0, // compression flag: unset
|
|
|
0, 0, 0, 2, // message length: 2 bytes
|
|
|
42, 42, // original message
|
|
|
]
|
|
|
- XCTAssertEqual(response, .sendMessage(ByteBuffer(bytes: expectedBytes)))
|
|
|
+ XCTAssertEqual(response, .sendFrame(frame: ByteBuffer(bytes: expectedBytes), promise: nil))
|
|
|
|
|
|
// And then make sure that nothing else is returned
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .awaitMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .awaitMoreMessages)
|
|
|
}
|
|
|
|
|
|
func testNextOutboundMessageWhenClientOpenAndServerOpen_WithCompression() throws {
|
|
|
@@ -1929,21 +1939,21 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
compressionEnabled: true
|
|
|
)
|
|
|
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .awaitMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .awaitMoreMessages)
|
|
|
|
|
|
let originalMessage = [UInt8]([42, 42, 43, 43])
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: originalMessage))
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: originalMessage, promise: nil))
|
|
|
|
|
|
- let response = try stateMachine.nextOutboundMessage()
|
|
|
+ let response = try stateMachine.nextOutboundFrame()
|
|
|
let framedMessage = try self.frameMessage(originalMessage, compress: true)
|
|
|
- XCTAssertEqual(response, .sendMessage(framedMessage))
|
|
|
+ XCTAssertEqual(response, .sendFrame(frame: framedMessage, promise: nil))
|
|
|
}
|
|
|
|
|
|
func testNextOutboundMessageWhenClientOpenAndServerClosed() throws {
|
|
|
var stateMachine = self.makeServerStateMachine(targetState: .clientOpenServerOpen)
|
|
|
|
|
|
// Send message and close server
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: [42, 42]))
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: [42, 42], promise: nil))
|
|
|
XCTAssertNoThrow(
|
|
|
try stateMachine.send(
|
|
|
status: .init(code: .ok, message: ""),
|
|
|
@@ -1951,16 +1961,16 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
)
|
|
|
)
|
|
|
|
|
|
- let response = try stateMachine.nextOutboundMessage()
|
|
|
+ let response = try stateMachine.nextOutboundFrame()
|
|
|
let expectedBytes: [UInt8] = [
|
|
|
0, // compression flag: unset
|
|
|
0, 0, 0, 2, // message length: 2 bytes
|
|
|
42, 42, // original message
|
|
|
]
|
|
|
- XCTAssertEqual(response, .sendMessage(ByteBuffer(bytes: expectedBytes)))
|
|
|
+ XCTAssertEqual(response, .sendFrame(frame: ByteBuffer(bytes: expectedBytes), promise: nil))
|
|
|
|
|
|
// And then make sure that nothing else is returned anymore
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .noMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .noMoreMessages)
|
|
|
}
|
|
|
|
|
|
func testNextOutboundMessageWhenClientClosedAndServerIdle() throws {
|
|
|
@@ -1968,7 +1978,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
|
|
|
XCTAssertThrowsError(
|
|
|
ofType: RPCError.self,
|
|
|
- try stateMachine.nextOutboundMessage()
|
|
|
+ try stateMachine.nextOutboundFrame()
|
|
|
) { error in
|
|
|
XCTAssertEqual(error.code, .internalError)
|
|
|
XCTAssertEqual(error.message, "Server is not open yet.")
|
|
|
@@ -1979,17 +1989,17 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
var stateMachine = self.makeServerStateMachine(targetState: .clientOpenServerOpen)
|
|
|
|
|
|
// Send a message
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: [42, 42]))
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: [42, 42], promise: nil))
|
|
|
|
|
|
// Close client
|
|
|
XCTAssertNoThrow(try stateMachine.receive(buffer: .init(), endStream: true))
|
|
|
|
|
|
// Send another message
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: [43, 43]))
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: [43, 43], promise: nil))
|
|
|
|
|
|
// Make sure that getting the next outbound message _does_ return the message
|
|
|
// we have enqueued.
|
|
|
- let response = try stateMachine.nextOutboundMessage()
|
|
|
+ let response = try stateMachine.nextOutboundFrame()
|
|
|
let expectedBytes: [UInt8] = [
|
|
|
0, // compression flag: unset
|
|
|
0, 0, 0, 2, // message length: 2 bytes
|
|
|
@@ -1999,17 +2009,17 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
0, 0, 0, 2, // message length: 2 bytes
|
|
|
43, 43, // original message
|
|
|
]
|
|
|
- XCTAssertEqual(response, .sendMessage(ByteBuffer(bytes: expectedBytes)))
|
|
|
+ XCTAssertEqual(response, .sendFrame(frame: ByteBuffer(bytes: expectedBytes), promise: nil))
|
|
|
|
|
|
// And then make sure that nothing else is returned anymore
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .awaitMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .awaitMoreMessages)
|
|
|
}
|
|
|
|
|
|
func testNextOutboundMessageWhenClientClosedAndServerClosed() throws {
|
|
|
var stateMachine = self.makeServerStateMachine(targetState: .clientClosedServerOpen)
|
|
|
|
|
|
// Send a message and close server
|
|
|
- XCTAssertNoThrow(try stateMachine.send(message: [42, 42]))
|
|
|
+ XCTAssertNoThrow(try stateMachine.send(message: [42, 42], promise: nil))
|
|
|
XCTAssertNoThrow(
|
|
|
try stateMachine.send(
|
|
|
status: .init(code: .ok, message: ""),
|
|
|
@@ -2019,16 +2029,16 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
|
|
|
// We have enqueued a message, make sure we return it even though server is closed,
|
|
|
// because we haven't yet drained all of the pending messages.
|
|
|
- let response = try stateMachine.nextOutboundMessage()
|
|
|
+ let response = try stateMachine.nextOutboundFrame()
|
|
|
let expectedBytes: [UInt8] = [
|
|
|
0, // compression flag: unset
|
|
|
0, 0, 0, 2, // message length: 2 bytes
|
|
|
42, 42, // original message
|
|
|
]
|
|
|
- XCTAssertEqual(response, .sendMessage(ByteBuffer(bytes: expectedBytes)))
|
|
|
+ XCTAssertEqual(response, .sendFrame(frame: ByteBuffer(bytes: expectedBytes), promise: nil))
|
|
|
|
|
|
// And then make sure that nothing else is returned anymore
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .noMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .noMoreMessages)
|
|
|
}
|
|
|
|
|
|
// - MARK: Next inbound message
|
|
|
@@ -2185,15 +2195,35 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
XCTAssertEqual(stateMachine.nextInboundMessage(), .receiveMessage(deframedMessage))
|
|
|
|
|
|
// Server sends response
|
|
|
+ let eventLoop = EmbeddedEventLoop()
|
|
|
+ let firstPromise = eventLoop.makePromise(of: Void.self)
|
|
|
+ let secondPromise = eventLoop.makePromise(of: Void.self)
|
|
|
+
|
|
|
let firstResponse = [UInt8]([5, 6, 7])
|
|
|
let secondResponse = [UInt8]([8, 9, 10])
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .awaitMoreMessages)
|
|
|
- try stateMachine.send(message: firstResponse)
|
|
|
- try stateMachine.send(message: secondResponse)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .awaitMoreMessages)
|
|
|
+
|
|
|
+ try stateMachine.send(message: firstResponse, promise: firstPromise)
|
|
|
+ try stateMachine.send(message: secondResponse, promise: secondPromise)
|
|
|
|
|
|
// Make sure messages are outbound
|
|
|
let framedMessages = try self.frameMessages([firstResponse, secondResponse], compress: false)
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .sendMessage(framedMessages))
|
|
|
+
|
|
|
+ guard
|
|
|
+ case .sendFrame(let nextOutboundByteBuffer, let nextOutboundPromise) =
|
|
|
+ try stateMachine.nextOutboundFrame()
|
|
|
+ else {
|
|
|
+ XCTFail("Should have received .sendMessage")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ XCTAssertEqual(nextOutboundByteBuffer, framedMessages)
|
|
|
+ XCTAssertTrue(firstPromise.futureResult === nextOutboundPromise?.futureResult)
|
|
|
+
|
|
|
+ // Make sure that the promises associated with each sent message are chained
|
|
|
+ // together: when succeeding the one returned by the state machine on
|
|
|
+ // `nextOutboundMessage()`, the others should also be succeeded.
|
|
|
+ firstPromise.succeed()
|
|
|
+ try secondPromise.futureResult.assertSuccess().wait()
|
|
|
|
|
|
// Client sends end
|
|
|
try stateMachine.receive(buffer: ByteBuffer(), endStream: true)
|
|
|
@@ -2205,7 +2235,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
)
|
|
|
XCTAssertEqual(response, ["grpc-status": "0"])
|
|
|
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .noMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .noMoreMessages)
|
|
|
XCTAssertEqual(stateMachine.nextInboundMessage(), .noMoreMessages)
|
|
|
}
|
|
|
|
|
|
@@ -2252,13 +2282,16 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
// Server sends response
|
|
|
let firstResponse = [UInt8]([5, 6, 7])
|
|
|
let secondResponse = [UInt8]([8, 9, 10])
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .awaitMoreMessages)
|
|
|
- try stateMachine.send(message: firstResponse)
|
|
|
- try stateMachine.send(message: secondResponse)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .awaitMoreMessages)
|
|
|
+ try stateMachine.send(message: firstResponse, promise: nil)
|
|
|
+ try stateMachine.send(message: secondResponse, promise: nil)
|
|
|
|
|
|
// Make sure messages are outbound
|
|
|
let framedMessages = try self.frameMessages([firstResponse, secondResponse], compress: false)
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .sendMessage(framedMessages))
|
|
|
+ XCTAssertEqual(
|
|
|
+ try stateMachine.nextOutboundFrame(),
|
|
|
+ .sendFrame(frame: framedMessages, promise: nil)
|
|
|
+ )
|
|
|
|
|
|
// Server ends
|
|
|
let response = try stateMachine.send(
|
|
|
@@ -2267,7 +2300,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
)
|
|
|
XCTAssertEqual(response, ["grpc-status": "0"])
|
|
|
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .noMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .noMoreMessages)
|
|
|
XCTAssertEqual(stateMachine.nextInboundMessage(), .noMoreMessages)
|
|
|
}
|
|
|
|
|
|
@@ -2314,13 +2347,16 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
// Server sends response
|
|
|
let firstResponse = [UInt8]([5, 6, 7])
|
|
|
let secondResponse = [UInt8]([8, 9, 10])
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .awaitMoreMessages)
|
|
|
- try stateMachine.send(message: firstResponse)
|
|
|
- try stateMachine.send(message: secondResponse)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .awaitMoreMessages)
|
|
|
+ try stateMachine.send(message: firstResponse, promise: nil)
|
|
|
+ try stateMachine.send(message: secondResponse, promise: nil)
|
|
|
|
|
|
// Make sure messages are outbound
|
|
|
let framedMessages = try self.frameMessages([firstResponse, secondResponse], compress: false)
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .sendMessage(framedMessages))
|
|
|
+ XCTAssertEqual(
|
|
|
+ try stateMachine.nextOutboundFrame(),
|
|
|
+ .sendFrame(frame: framedMessages, promise: nil)
|
|
|
+ )
|
|
|
|
|
|
// Server ends
|
|
|
let response = try stateMachine.send(
|
|
|
@@ -2329,7 +2365,7 @@ final class GRPCStreamServerStateMachineTests: XCTestCase {
|
|
|
)
|
|
|
XCTAssertEqual(response, ["grpc-status": "0"])
|
|
|
|
|
|
- XCTAssertEqual(try stateMachine.nextOutboundMessage(), .noMoreMessages)
|
|
|
+ XCTAssertEqual(try stateMachine.nextOutboundFrame(), .noMoreMessages)
|
|
|
XCTAssertEqual(stateMachine.nextInboundMessage(), .noMoreMessages)
|
|
|
}
|
|
|
}
|
|
|
@@ -2362,8 +2398,29 @@ extension XCTestCase {
|
|
|
}()
|
|
|
defer { compressor?.end() }
|
|
|
for message in messages {
|
|
|
- framer.append(message)
|
|
|
+ framer.append(message, promise: nil)
|
|
|
+ }
|
|
|
+ return try XCTUnwrap(framer.next(compressor: compressor)).bytes
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *)
|
|
|
+extension GRPCStreamStateMachine.OnNextOutboundFrame: Equatable {
|
|
|
+ public static func == (
|
|
|
+ lhs: GRPCStreamStateMachine.OnNextOutboundFrame,
|
|
|
+ rhs: GRPCStreamStateMachine.OnNextOutboundFrame
|
|
|
+ ) -> Bool {
|
|
|
+ switch (lhs, rhs) {
|
|
|
+ case (.noMoreMessages, .noMoreMessages):
|
|
|
+ return true
|
|
|
+ case (.awaitMoreMessages, .awaitMoreMessages):
|
|
|
+ return true
|
|
|
+ case (.sendFrame(let lhsMessage, _), .sendFrame(let rhsMessage, _)):
|
|
|
+ // Note that we're not comparing the EventLoopPromises here, as they're
|
|
|
+ // not Equatable. This is fine though, since we only use this in tests.
|
|
|
+ return lhsMessage == rhsMessage
|
|
|
+ default:
|
|
|
+ return false
|
|
|
}
|
|
|
- return try XCTUnwrap(framer.next(compressor: compressor))
|
|
|
}
|
|
|
}
|