LengthPrefixedMessageReaderTests.swift 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /*
  2. * Copyright 2019, gRPC Authors All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. import Logging
  17. import NIOCore
  18. import XCTest
  19. @testable import GRPC
  20. class LengthPrefixedMessageReaderTests: GRPCTestCase {
  21. var reader: LengthPrefixedMessageReader!
  22. override func setUp() {
  23. super.setUp()
  24. self.reader = LengthPrefixedMessageReader()
  25. }
  26. var allocator = ByteBufferAllocator()
  27. func byteBuffer(withBytes bytes: [UInt8]) -> ByteBuffer {
  28. var buffer = self.allocator.buffer(capacity: bytes.count)
  29. buffer.writeBytes(bytes)
  30. return buffer
  31. }
  32. final let twoByteMessage: [UInt8] = [0x01, 0x02]
  33. func lengthPrefixedTwoByteMessage(withCompression compression: Bool = false) -> [UInt8] {
  34. return [
  35. compression ? 0x01 : 0x00, // 1-byte compression flag
  36. 0x00, 0x00, 0x00, 0x02, // 4-byte message length (2)
  37. ] + self.twoByteMessage
  38. }
  39. private func assertMessagesEqual(
  40. expected expectedBytes: [UInt8],
  41. actual buffer: ByteBuffer?,
  42. line: UInt = #line
  43. ) {
  44. guard let buffer = buffer else {
  45. XCTFail("buffer is nil", line: line)
  46. return
  47. }
  48. guard let bytes = buffer.getBytes(at: buffer.readerIndex, length: expectedBytes.count) else {
  49. XCTFail(
  50. "Expected \(expectedBytes.count) bytes, but only \(buffer.readableBytes) bytes are readable",
  51. line: line
  52. )
  53. return
  54. }
  55. XCTAssertEqual(expectedBytes, bytes, line: line)
  56. }
  57. func testNextMessageReturnsNilWhenNoBytesAppended() throws {
  58. XCTAssertNil(try self.reader.nextMessage())
  59. }
  60. func testNextMessageReturnsMessageIsAppendedInOneBuffer() throws {
  61. var buffer = self.byteBuffer(withBytes: self.lengthPrefixedTwoByteMessage())
  62. self.reader.append(buffer: &buffer)
  63. self.assertMessagesEqual(expected: self.twoByteMessage, actual: try self.reader.nextMessage())
  64. }
  65. func testNextMessageReturnsMessageForZeroLengthMessage() throws {
  66. let bytes: [UInt8] = [
  67. 0x00, // 1-byte compression flag
  68. 0x00, 0x00, 0x00, 0x00, // 4-byte message length (0)
  69. // 0-byte message
  70. ]
  71. var buffer = self.byteBuffer(withBytes: bytes)
  72. self.reader.append(buffer: &buffer)
  73. self.assertMessagesEqual(expected: [], actual: try self.reader.nextMessage())
  74. }
  75. func testNextMessageDeliveredAcrossMultipleByteBuffers() throws {
  76. let firstBytes: [UInt8] = [
  77. 0x00, // 1-byte compression flag
  78. 0x00, 0x00, 0x00, // first 3 bytes of 4-byte message length
  79. ]
  80. let secondBytes: [UInt8] = [
  81. 0x02, // fourth byte of 4-byte message length (2)
  82. 0xF0, 0xBA, // 2-byte message
  83. ]
  84. var firstBuffer = self.byteBuffer(withBytes: firstBytes)
  85. self.reader.append(buffer: &firstBuffer)
  86. var secondBuffer = self.byteBuffer(withBytes: secondBytes)
  87. self.reader.append(buffer: &secondBuffer)
  88. self.assertMessagesEqual(expected: [0xF0, 0xBA], actual: try self.reader.nextMessage())
  89. }
  90. func testNextMessageWhenMultipleMessagesAreBuffered() throws {
  91. let bytes: [UInt8] = [
  92. // 1st message
  93. 0x00, // 1-byte compression flag
  94. 0x00, 0x00, 0x00, 0x02, // 4-byte message length (2)
  95. 0x0F, 0x00, // 2-byte message
  96. // 2nd message
  97. 0x00, // 1-byte compression flag
  98. 0x00, 0x00, 0x00, 0x04, // 4-byte message length (4)
  99. 0xDE, 0xAD, 0xBE, 0xEF, // 4-byte message
  100. // 3rd message
  101. 0x00, // 1-byte compression flag
  102. 0x00, 0x00, 0x00, 0x01, // 4-byte message length (1)
  103. 0x01, // 1-byte message
  104. ]
  105. var buffer = self.byteBuffer(withBytes: bytes)
  106. self.reader.append(buffer: &buffer)
  107. self.assertMessagesEqual(expected: [0x0F, 0x00], actual: try self.reader.nextMessage())
  108. self.assertMessagesEqual(
  109. expected: [0xDE, 0xAD, 0xBE, 0xEF],
  110. actual: try self.reader.nextMessage()
  111. )
  112. self.assertMessagesEqual(expected: [0x01], actual: try self.reader.nextMessage())
  113. }
  114. func testNextMessageReturnsNilWhenNoMessageLengthIsAvailable() throws {
  115. let bytes: [UInt8] = [
  116. 0x00 // 1-byte compression flag
  117. ]
  118. var buffer = self.byteBuffer(withBytes: bytes)
  119. self.reader.append(buffer: &buffer)
  120. XCTAssertNil(try self.reader.nextMessage())
  121. // Ensure we can read a message when the rest of the bytes are delivered
  122. let restOfBytes: [UInt8] = [
  123. 0x00, 0x00, 0x00, 0x01, // 4-byte message length (1)
  124. 0x00, // 1-byte message
  125. ]
  126. var secondBuffer = self.byteBuffer(withBytes: restOfBytes)
  127. self.reader.append(buffer: &secondBuffer)
  128. self.assertMessagesEqual(expected: [0x00], actual: try self.reader.nextMessage())
  129. }
  130. func testNextMessageReturnsNilWhenNotAllMessageLengthIsAvailable() throws {
  131. let bytes: [UInt8] = [
  132. 0x00, // 1-byte compression flag
  133. 0x00, 0x00, // 2-bytes of message length (should be 4)
  134. ]
  135. var buffer = self.byteBuffer(withBytes: bytes)
  136. self.reader.append(buffer: &buffer)
  137. XCTAssertNil(try self.reader.nextMessage())
  138. // Ensure we can read a message when the rest of the bytes are delivered
  139. let restOfBytes: [UInt8] = [
  140. 0x00, 0x01, // 4-byte message length (1)
  141. 0x00, // 1-byte message
  142. ]
  143. var secondBuffer = self.byteBuffer(withBytes: restOfBytes)
  144. self.reader.append(buffer: &secondBuffer)
  145. self.assertMessagesEqual(expected: [0x00], actual: try self.reader.nextMessage())
  146. }
  147. func testNextMessageReturnsNilWhenNoMessageBytesAreAvailable() throws {
  148. let bytes: [UInt8] = [
  149. 0x00, // 1-byte compression flag
  150. 0x00, 0x00, 0x00, 0x02, // 4-byte message length (2)
  151. ]
  152. var buffer = self.byteBuffer(withBytes: bytes)
  153. self.reader.append(buffer: &buffer)
  154. XCTAssertNil(try self.reader.nextMessage())
  155. // Ensure we can read a message when the rest of the bytes are delivered
  156. var secondBuffer = self.byteBuffer(withBytes: self.twoByteMessage)
  157. self.reader.append(buffer: &secondBuffer)
  158. self.assertMessagesEqual(expected: self.twoByteMessage, actual: try self.reader.nextMessage())
  159. }
  160. func testNextMessageReturnsNilWhenNotAllMessageBytesAreAvailable() throws {
  161. let bytes: [UInt8] = [
  162. 0x00, // 1-byte compression flag
  163. 0x00, 0x00, 0x00, 0x02, // 4-byte message length (2)
  164. 0x00, // 1-byte of message
  165. ]
  166. var buffer = self.byteBuffer(withBytes: bytes)
  167. self.reader.append(buffer: &buffer)
  168. XCTAssertNil(try self.reader.nextMessage())
  169. // Ensure we can read a message when the rest of the bytes are delivered
  170. let restOfBytes: [UInt8] = [
  171. 0x01 // final byte of message
  172. ]
  173. var secondBuffer = self.byteBuffer(withBytes: restOfBytes)
  174. self.reader.append(buffer: &secondBuffer)
  175. self.assertMessagesEqual(expected: [0x00, 0x01], actual: try self.reader.nextMessage())
  176. }
  177. func testNextMessageThrowsWhenCompressionFlagIsSetButNotExpected() throws {
  178. // Default compression mechanism is `nil` which requires that no
  179. // compression flag is set as it indicates a lack of message encoding header.
  180. XCTAssertNil(self.reader.compression)
  181. var buffer =
  182. self
  183. .byteBuffer(withBytes: self.lengthPrefixedTwoByteMessage(withCompression: true))
  184. self.reader.append(buffer: &buffer)
  185. XCTAssertThrowsError(try self.reader.nextMessage()) { error in
  186. let errorWithContext = error as? GRPCError.WithContext
  187. XCTAssertTrue(errorWithContext?.error is GRPCError.CompressionUnsupported)
  188. }
  189. }
  190. func testNextMessageDoesNotThrowWhenCompressionFlagIsExpectedButNotSet() throws {
  191. // `.identity` should always be supported and requires a flag.
  192. self.reader = LengthPrefixedMessageReader(compression: .identity, decompressionLimit: .ratio(1))
  193. var buffer = self.byteBuffer(withBytes: self.lengthPrefixedTwoByteMessage())
  194. self.reader.append(buffer: &buffer)
  195. self.assertMessagesEqual(expected: self.twoByteMessage, actual: try self.reader.nextMessage())
  196. }
  197. func testAppendReadsAllBytes() throws {
  198. var buffer = self.byteBuffer(withBytes: self.lengthPrefixedTwoByteMessage())
  199. self.reader.append(buffer: &buffer)
  200. XCTAssertEqual(0, buffer.readableBytes)
  201. }
  202. func testExcessiveBytesAreDiscarded() throws {
  203. // We're going to use a 1kB message here for ease of testing.
  204. let message = Array(repeating: UInt8(0), count: 1024)
  205. let largeMessage: [UInt8] =
  206. [
  207. 0x00, // 1-byte compression flag
  208. 0x00, 0x00, 0x04, 0x00, // 4-byte message length (1024)
  209. ] + message
  210. var buffer = self.byteBuffer(withBytes: largeMessage)
  211. buffer.writeBytes(largeMessage)
  212. buffer.writeBytes(largeMessage)
  213. self.reader.append(buffer: &buffer)
  214. XCTAssertEqual(self.reader.unprocessedBytes, (1024 + 5) * 3)
  215. XCTAssertEqual(self.reader._consumedNonDiscardedBytes, 0)
  216. self.assertMessagesEqual(expected: message, actual: try self.reader.nextMessage())
  217. XCTAssertEqual(self.reader.unprocessedBytes, (1024 + 5) * 2)
  218. XCTAssertEqual(self.reader._consumedNonDiscardedBytes, 1024 + 5)
  219. self.assertMessagesEqual(expected: message, actual: try self.reader.nextMessage())
  220. XCTAssertEqual(self.reader.unprocessedBytes, 1024 + 5)
  221. XCTAssertEqual(self.reader._consumedNonDiscardedBytes, 0)
  222. }
  223. }
  224. extension LengthPrefixedMessageReader {
  225. fileprivate mutating func nextMessage() throws -> ByteBuffer? {
  226. return try self.nextMessage(maxLength: .max)
  227. }
  228. }