GRPCTests.swift 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import XCTest
  2. import Foundation
  3. import Dispatch
  4. @testable import gRPC
  5. func Log(_ message : String) {
  6. FileHandle.standardError.write((message + "\n").data(using:.utf8)!)
  7. }
  8. class gRPCTests: XCTestCase {
  9. var count : Int = 0
  10. func testBasicSanity() {
  11. gRPC.initialize()
  12. let done = NSCondition()
  13. self.count = 2
  14. DispatchQueue.global().async() {
  15. server()
  16. Log("server finished")
  17. done.lock()
  18. self.count = self.count - 1
  19. done.signal()
  20. done.unlock()
  21. }
  22. DispatchQueue.global().async() {
  23. client()
  24. Log("client finished")
  25. done.lock()
  26. self.count = self.count - 1
  27. done.signal()
  28. done.unlock()
  29. }
  30. var running = true
  31. while (running) {
  32. Log("waiting")
  33. done.lock()
  34. done.wait()
  35. if (self.count == 0) {
  36. running = false
  37. }
  38. Log("count \(self.count)")
  39. done.unlock()
  40. }
  41. }
  42. }
  43. extension gRPCTests {
  44. static var allTests : [(String, (gRPCTests) -> () throws -> Void)] {
  45. return [
  46. ("testBasicSanity", testBasicSanity),
  47. ]
  48. }
  49. }
  50. let address = "localhost:8999"
  51. let host = "foo.test.google.fr"
  52. let clientText = "hello, server!"
  53. let serverText = "hello, client!"
  54. let initialClientMetadata =
  55. ["x": "xylophone",
  56. "y": "yu",
  57. "z": "zither"]
  58. let initialServerMetadata =
  59. ["a": "Apple",
  60. "b": "Banana",
  61. "c": "Cherry"]
  62. let trailingServerMetadata =
  63. ["0": "zero",
  64. "1": "one",
  65. "2": "two"]
  66. let steps = 30
  67. let hello = "/hello"
  68. let goodbye = "/goodbye"
  69. let statusCode = 0
  70. let statusMessage = "OK"
  71. func verify_metadata(_ metadata: Metadata, expected: [String:String]) {
  72. XCTAssertGreaterThanOrEqual(metadata.count(), expected.count)
  73. for i in 0..<metadata.count() {
  74. if expected[metadata.key(i)] != nil {
  75. XCTAssertEqual(metadata.value(i), expected[metadata.key(i)])
  76. }
  77. }
  78. }
  79. func client() {
  80. let message = clientText.data(using: .utf8)
  81. let c = gRPC.Channel(address:address)
  82. c.host = host
  83. let done = NSCondition()
  84. for i in 0..<steps {
  85. do {
  86. let method = (i < steps-1) ? hello : goodbye
  87. let call = c.makeCall(method)
  88. let metadata = Metadata(initialClientMetadata)
  89. try call.start(.unary, metadata:metadata, message:message) {
  90. (response) in
  91. // verify the basic response from the server
  92. XCTAssertEqual(response.statusCode, statusCode)
  93. XCTAssertEqual(response.statusMessage, statusMessage)
  94. // verify the message from the server
  95. let resultData = response.resultData
  96. let messageString = String(data: resultData!, encoding: .utf8)
  97. XCTAssertEqual(messageString, serverText)
  98. // verify the initial metadata from the server
  99. let initialMetadata = response.initialMetadata!
  100. verify_metadata(initialMetadata, expected: initialServerMetadata)
  101. // verify the trailing metadata from the server
  102. let trailingMetadata = response.trailingMetadata!
  103. verify_metadata(trailingMetadata, expected: trailingServerMetadata)
  104. done.lock()
  105. done.signal()
  106. done.unlock()
  107. }
  108. } catch (let error) {
  109. XCTFail("error \(error)")
  110. }
  111. // wait for the call to complete
  112. done.lock()
  113. done.wait()
  114. done.unlock()
  115. Log("finished client call \(i)")
  116. }
  117. Log("client done")
  118. // temporary workaround for a synchronization problem,
  119. // we fail intermittently if the channel is freed too soon after the call is deleted
  120. usleep(1000)
  121. }
  122. func server() {
  123. let server = gRPC.Server(address:address)
  124. var requestCount = 0
  125. let done = NSCondition()
  126. server.run() {(requestHandler) in
  127. do {
  128. requestCount += 1
  129. XCTAssertEqual(requestHandler.host, host)
  130. if (requestCount < steps) {
  131. XCTAssertEqual(requestHandler.method, hello)
  132. } else {
  133. XCTAssertEqual(requestHandler.method, goodbye)
  134. }
  135. let initialMetadata = requestHandler.requestMetadata
  136. verify_metadata(initialMetadata, expected: initialClientMetadata)
  137. let initialMetadataToSend = Metadata(initialServerMetadata)
  138. try requestHandler.receiveMessage(initialMetadata:initialMetadataToSend)
  139. {(messageData) in
  140. let messageString = String(data: messageData!, encoding: .utf8)
  141. XCTAssertEqual(messageString, clientText)
  142. }
  143. if requestHandler.method == goodbye {
  144. server.stop()
  145. }
  146. let replyMessage = serverText
  147. let trailingMetadataToSend = Metadata(trailingServerMetadata)
  148. try requestHandler.sendResponse(message:replyMessage.data(using: .utf8)!,
  149. statusCode:statusCode,
  150. statusMessage:statusMessage,
  151. trailingMetadata:trailingMetadataToSend)
  152. } catch (let error) {
  153. XCTFail("error \(error)")
  154. }
  155. }
  156. server.onCompletion() {
  157. // exit the server thread
  158. Log("signaling completion")
  159. done.lock()
  160. done.signal()
  161. done.unlock()
  162. }
  163. // wait for the server to exit
  164. done.lock()
  165. done.wait()
  166. done.unlock()
  167. Log("server done")
  168. }