2
0
Эх сурвалжийг харах

Add a first set of XCTest-based tests.

Daniel Alm 7 жил өмнө
parent
commit
1db9d4d477

+ 5 - 0
Examples/Echo/Generated/echo.grpc.swift

@@ -251,6 +251,11 @@ internal final class Echo_EchoServer: ServiceServer {
     super.init(address: address, certificateURL: certificateURL, keyURL: keyURL)
   }
 
+  internal init?(address: String, certificateString: String, keyString: String, provider: Echo_EchoProvider) {
+    self.provider = provider
+    super.init(address: address, certificateString: certificateString, keyString: keyString)
+  }
+
   /// Start the server.
   internal override func handleMethod(_ method: String, handler: Handler, queue: DispatchQueue) throws -> Bool {
     let provider = self.provider

+ 39 - 17
Sources/RootsEncoder/main.swift

@@ -49,21 +49,43 @@ s += " * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
 s += " *\n"
 s += " */\n"
 s += "// GENERATED: DO NOT EDIT\n"
-s += "//\n"
-s += "// This file contain a function that returns the default roots.pem.\n"
-s += "//\n"
-s += "import Foundation\n"
-s += "\n"
-s += "func roots_pem() -> String? {\n"
-let fileURL = URL(fileURLWithPath: "Assets/roots.pem")
-let filedata = try Data(contentsOf: fileURL)
-let encoding = filedata.base64EncodedString()
-s += "  let roots = \n"
-s += "    \"" + encoding + "\"\n"
-s += "  if let data = Data(base64Encoded: roots, options:[]) {\n"
-s += "    return String(data:data, encoding:.utf8)\n"
-s += "  } else {\n"
-s += "    return nil\n"
-s += "  }\n"
-s += "}\n"
+
+if CommandLine.arguments.contains("test") {
+  s += "//\n"
+  s += "// This file contain a function that returns the contents of Tests/ssl.crt and Tests/ssl.key.\n"
+  s += "//\n"
+  s += "import Foundation\n"
+  s += "\n"
+
+  s += "let certificateForTests = "
+  let certificateURL = URL(fileURLWithPath: "Tests/ssl.crt")
+  let certificateData = try Data(contentsOf: certificateURL)
+  let encodedCertificate = certificateData.base64EncodedString()
+  s += "Data(base64Encoded: \"\(encodedCertificate)\", options:[])!\n"
+
+  s += "let keyForTests = "
+  let keyURL = URL(fileURLWithPath: "Tests/ssl.key")
+  let keyData = try Data(contentsOf: keyURL)
+  let encodedKey = keyData.base64EncodedString()
+  s += "Data(base64Encoded: \"\(encodedKey)\", options:[])!"
+} else {
+  s += "//\n"
+  s += "// This file contain a function that returns the default roots.pem.\n"
+  s += "//\n"
+  s += "import Foundation\n"
+  s += "\n"
+
+  s += "func roots_pem() -> String? {\n"
+  let fileURL = URL(fileURLWithPath: "Assets/roots.pem")
+  let filedata = try Data(contentsOf: fileURL)
+  let encoding = filedata.base64EncodedString()
+  s += "  let roots = \n"
+  s += "    \"" + encoding + "\"\n"
+  s += "  if let data = Data(base64Encoded: roots, options:[]) {\n"
+  s += "    return String(data:data, encoding:.utf8)\n"
+  s += "  } else {\n"
+  s += "    return nil\n"
+  s += "  }\n"
+  s += "}\n"
+}
 print(s)

+ 9 - 2
Sources/gRPC/GenCodeSupport/ServiceServer.swift

@@ -30,12 +30,19 @@ open class ServiceServer {
   }
 
   /// Create a server that accepts secure connections.
-  public init?(address: String, certificateURL: URL, keyURL: URL) {
+  public init(address: String, certificateString: String, keyString: String) {
     gRPC.initialize()
     self.address = address
+    server = Server(address: address, key: keyString, certs: certificateString)
+  }
+
+  /// Create a server that accepts secure connections.
+  public init?(address: String, certificateURL: URL, keyURL: URL) {
     guard let certificate = try? String(contentsOf: certificateURL, encoding: .utf8),
       let key = try? String(contentsOf: keyURL, encoding: .utf8)
-    else { return nil }
+      else { return nil }
+    gRPC.initialize()
+    self.address = address
     server = Server(address: address, key: key, certs: certificate)
   }
 

+ 3 - 1
Sources/gRPC/Server.swift

@@ -71,8 +71,10 @@ public class Server {
         do {
           let handler = Handler(underlyingServer: self.underlyingServer)
           try handler.requestCall(tag: 101)
+
           // block while waiting for an incoming request
           let event = self.completionQueue.wait(timeout: 600)
+
           if event.type == .complete {
             if event.tag == 101 {
               // run the handler and remove it when it finishes
@@ -93,7 +95,7 @@ public class Server {
                 // call the handler function on the server thread
                 handlerFunction(handler)
               }
-            } else if event.tag == 0 {
+            } else if event.tag == 0 || event.tag == 1000 {
               running = false // exit the loop
             }
           } else if event.type == .queueTimeout {

+ 7 - 0
Sources/protoc-gen-swiftgrpc/Generator-Server.swift

@@ -81,6 +81,13 @@ extension Generator {
     outdent()
     println("}")
     println()
+    println("\(access) init?(address: String, certificateString: String, keyString: String, provider: \(providerName)) {")
+    indent()
+    println("self.provider = provider")
+    println("super.init(address: address, certificateString: certificateString, keyString: keyString)")
+    outdent()
+    println("}")
+    println()
     println("/// Start the server.")
     println("\(access) override func handleMethod(_ method: String, handler: Handler, queue: DispatchQueue) throws -> Bool {")
     indent()

+ 2 - 1
Tests/LinuxMain.swift

@@ -17,5 +17,6 @@ import XCTest
 @testable import gRPCTests
 
 XCTMain([
-  testCase(gRPCTests.allTests)
+  testCase(gRPCTests.allTests),
+  testCase(EchoTests.allTests)
 ])

+ 1 - 0
Tests/gRPCTests/EchoProvider.swift

@@ -0,0 +1 @@
+../../Examples/Echo/EchoProvider.swift

+ 269 - 0
Tests/gRPCTests/EchoTests.swift

@@ -0,0 +1,269 @@
+/*
+ * Copyright 2018, gRPC Authors All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import Dispatch
+import Foundation
+@testable import gRPC
+import XCTest
+
+extension Echo_EchoRequest {
+  init(text: String) {
+    self.text = text
+  }
+}
+
+class EchoTests: XCTestCase {
+  static var allTests: [(String, (EchoTests) -> () throws -> Void)] {
+    return [
+      ("testUnary", testUnary),
+      ("testClientStreaming", testClientStreaming),
+      ("testClientStreamingLotsOfMessages", testClientStreamingLotsOfMessages),
+      ("testServerStreaming", testServerStreaming),
+      ("testServerStreamingLotsOfMessages", testServerStreamingLotsOfMessages),
+      ("testBidirectionalStreamingBatched", testBidirectionalStreamingBatched),
+      ("testBidirectionalStreamingPingPong", testBidirectionalStreamingPingPong),
+      ("testBidirectionalStreamingLotsOfMessagesBatched", testBidirectionalStreamingLotsOfMessagesBatched),
+      ("testBidirectionalStreamingLotsOfMessagesPingPong", testBidirectionalStreamingLotsOfMessagesPingPong)
+    ]
+  }
+
+  static let lotsOfStrings = (0..<1000).map { String(describing: $0) }
+
+  let defaultTimeout: TimeInterval = 5.0
+
+  let provider = EchoProvider()
+  var server: Echo_EchoServer!
+  var client: Echo_EchoServiceClient!
+
+  var secure: Bool { return false }
+
+  override func setUp() {
+    super.setUp()
+
+    let address = "localhost:5050"
+    if secure {
+      let certificateString = String(data: certificateForTests, encoding: .utf8)!
+      server = Echo_EchoServer(address: address,
+                               certificateString: certificateString,
+                               keyString: String(data: keyForTests, encoding: .utf8)!,
+                               provider: provider)
+      server.start(queue: DispatchQueue.global())
+      client = Echo_EchoServiceClient(address: address, certificates: certificateString, host: "example.com")
+    } else {
+      server = Echo_EchoServer(address: address, provider: provider)
+      server.start(queue: DispatchQueue.global())
+      client = Echo_EchoServiceClient(address: address, secure: false)
+    }
+
+    client.timeout = defaultTimeout
+  }
+
+  override func tearDown() {
+    client = nil
+
+    server.server.stop()
+    server = nil
+
+    #if os(Linux)
+      // Having to sleep here is really not a good solution,
+      // but it appears to help with fixing test flakes under Linux.
+      Thread.sleep(forTimeInterval: 1.0)
+    #endif
+
+    super.tearDown()
+  }
+}
+
+// Currently broken and thus commented out.
+// TODO(danielalm): Fix these.
+//class EchoTestsSecure: EchoTests {
+//  override var secure: Bool { return true }
+//}
+
+extension EchoTests {
+  func testUnary() {
+    XCTAssertEqual("Swift echo get: foo", try! client.get(Echo_EchoRequest(text: "foo")).text)
+    XCTAssertEqual("Swift echo get: foo", try! client.get(Echo_EchoRequest(text: "foo")).text)
+    XCTAssertEqual("Swift echo get: foo", try! client.get(Echo_EchoRequest(text: "foo")).text)
+    XCTAssertEqual("Swift echo get: foo", try! client.get(Echo_EchoRequest(text: "foo")).text)
+    XCTAssertEqual("Swift echo get: foo", try! client.get(Echo_EchoRequest(text: "foo")).text)
+  }
+}
+
+extension EchoTests {
+  func testClientStreaming() {
+    let completionHandlerExpectation = expectation(description: "final completion handler called")
+    let call = try! client.collect { callResult in
+      XCTAssertEqual(.ok, callResult.statusCode)
+      completionHandlerExpectation.fulfill()
+    }
+
+    var sendExpectation = expectation(description: "send completion handler 1 called")
+    try! call.send(Echo_EchoRequest(text: "foo")) { [sendExpectation] in XCTAssertNil($0); sendExpectation.fulfill() }
+    sendExpectation = expectation(description: "send completion handler 2 called")
+    try! call.send(Echo_EchoRequest(text: "bar")) { [sendExpectation] in XCTAssertNil($0); sendExpectation.fulfill() }
+    sendExpectation = expectation(description: "send completion handler 3 called")
+    try! call.send(Echo_EchoRequest(text: "baz")) { [sendExpectation] in XCTAssertNil($0); sendExpectation.fulfill() }
+    call.waitForSendOperationsToFinish()
+
+    let response = try! call.closeAndReceive()
+    XCTAssertEqual("Swift echo collect: foo bar baz", response.text)
+
+    waitForExpectations(timeout: defaultTimeout)
+  }
+
+  func testClientStreamingLotsOfMessages() {
+    let completionHandlerExpectation = expectation(description: "completion handler called")
+    let call = try! client.collect { callResult in
+      XCTAssertEqual(.ok, callResult.statusCode)
+      completionHandlerExpectation.fulfill()
+    }
+
+    for string in EchoTests.lotsOfStrings {
+      let sendExpectation = expectation(description: "send completion handler \(string) called")
+      try! call.send(Echo_EchoRequest(text: string)) { [sendExpectation] in XCTAssertNil($0); sendExpectation.fulfill() }
+    }
+    call.waitForSendOperationsToFinish()
+
+    let response = try! call.closeAndReceive()
+    XCTAssertEqual("Swift echo collect: " + EchoTests.lotsOfStrings.joined(separator: " "), response.text)
+
+    waitForExpectations(timeout: defaultTimeout)
+  }
+}
+
+extension EchoTests {
+  func testServerStreaming() {
+    let completionHandlerExpectation = expectation(description: "completion handler called")
+    let call = try! client.expand(Echo_EchoRequest(text: "foo bar baz")) { callResult in
+      XCTAssertEqual(.ok, callResult.statusCode)
+      completionHandlerExpectation.fulfill()
+    }
+
+    XCTAssertEqual("Swift echo expand (0): foo", try! call.receive().text)
+    XCTAssertEqual("Swift echo expand (1): bar", try! call.receive().text)
+    XCTAssertEqual("Swift echo expand (2): baz", try! call.receive().text)
+
+    waitForExpectations(timeout: defaultTimeout)
+  }
+
+  func testServerStreamingLotsOfMessages() {
+    let completionHandlerExpectation = expectation(description: "completion handler called")
+    let call = try! client.expand(Echo_EchoRequest(text: EchoTests.lotsOfStrings.joined(separator: " "))) { callResult in
+      XCTAssertEqual(.ok, callResult.statusCode)
+      completionHandlerExpectation.fulfill()
+    }
+
+    for string in EchoTests.lotsOfStrings {
+      XCTAssertEqual("Swift echo expand (\(string)): \(string)", try! call.receive().text)
+    }
+
+    waitForExpectations(timeout: defaultTimeout)
+  }
+}
+
+extension EchoTests {
+  func testBidirectionalStreamingBatched() {
+    let finalCompletionHandlerExpectation = expectation(description: "final completion handler called")
+    let call = try! client.update { callResult in
+      XCTAssertEqual(.ok, callResult.statusCode)
+      finalCompletionHandlerExpectation.fulfill()
+    }
+
+    var sendExpectation = expectation(description: "send completion handler 1 called")
+    try! call.send(Echo_EchoRequest(text: "foo")) { [sendExpectation] in XCTAssertNil($0); sendExpectation.fulfill() }
+    sendExpectation = expectation(description: "send completion handler 2 called")
+    try! call.send(Echo_EchoRequest(text: "bar")) { [sendExpectation] in XCTAssertNil($0); sendExpectation.fulfill() }
+    sendExpectation = expectation(description: "send completion handler 3 called")
+    try! call.send(Echo_EchoRequest(text: "baz")) { [sendExpectation] in XCTAssertNil($0); sendExpectation.fulfill() }
+    call.waitForSendOperationsToFinish()
+
+    let closeCompletionHandlerExpectation = expectation(description: "close completion handler called")
+    try! call.closeSend { closeCompletionHandlerExpectation.fulfill() }
+
+    XCTAssertEqual("Swift echo update (0): foo", try! call.receive().text)
+    XCTAssertEqual("Swift echo update (1): bar", try! call.receive().text)
+    XCTAssertEqual("Swift echo update (2): baz", try! call.receive().text)
+
+    waitForExpectations(timeout: defaultTimeout)
+  }
+
+  func testBidirectionalStreamingPingPong() {
+    let finalCompletionHandlerExpectation = expectation(description: "final completion handler called")
+    let call = try! client.update { callResult in
+      XCTAssertEqual(.ok, callResult.statusCode)
+      finalCompletionHandlerExpectation.fulfill()
+    }
+
+    var sendExpectation = expectation(description: "send completion handler 1 called")
+    try! call.send(Echo_EchoRequest(text: "foo")) { [sendExpectation] in XCTAssertNil($0); sendExpectation.fulfill() }
+    XCTAssertEqual("Swift echo update (0): foo", try! call.receive().text)
+
+    sendExpectation = expectation(description: "send completion handler 2 called")
+    try! call.send(Echo_EchoRequest(text: "bar")) { [sendExpectation] in XCTAssertNil($0); sendExpectation.fulfill() }
+    XCTAssertEqual("Swift echo update (1): bar", try! call.receive().text)
+
+    sendExpectation = expectation(description: "send completion handler 3 called")
+    try! call.send(Echo_EchoRequest(text: "baz")) { [sendExpectation] in XCTAssertNil($0); sendExpectation.fulfill() }
+    XCTAssertEqual("Swift echo update (2): baz", try! call.receive().text)
+
+    let closeCompletionHandlerExpectation = expectation(description: "close completion handler called")
+    try! call.closeSend { closeCompletionHandlerExpectation.fulfill() }
+
+    waitForExpectations(timeout: defaultTimeout)
+  }
+
+  func testBidirectionalStreamingLotsOfMessagesBatched() {
+    let finalCompletionHandlerExpectation = expectation(description: "final completion handler called")
+    let call = try! client.update { callResult in
+      XCTAssertEqual(.ok, callResult.statusCode)
+      finalCompletionHandlerExpectation.fulfill()
+    }
+
+    for string in EchoTests.lotsOfStrings {
+      let sendExpectation = expectation(description: "send completion handler \(string) called")
+      try! call.send(Echo_EchoRequest(text: string)) { [sendExpectation] in XCTAssertNil($0); sendExpectation.fulfill() }
+    }
+    call.waitForSendOperationsToFinish()
+
+    let closeCompletionHandlerExpectation = expectation(description: "close completion handler called")
+    try! call.closeSend { closeCompletionHandlerExpectation.fulfill() }
+
+    for string in EchoTests.lotsOfStrings {
+      XCTAssertEqual("Swift echo update (\(string)): \(string)", try! call.receive().text)
+    }
+
+    waitForExpectations(timeout: defaultTimeout)
+  }
+
+  func testBidirectionalStreamingLotsOfMessagesPingPong() {
+    let finalCompletionHandlerExpectation = expectation(description: "final completion handler called")
+    let call = try! client.update { callResult in
+      XCTAssertEqual(.ok, callResult.statusCode)
+      finalCompletionHandlerExpectation.fulfill()
+    }
+
+    for string in EchoTests.lotsOfStrings {
+      let sendExpectation = expectation(description: "send completion handler \(string) called")
+      try! call.send(Echo_EchoRequest(text: string)) { [sendExpectation] in XCTAssertNil($0); sendExpectation.fulfill() }
+      XCTAssertEqual("Swift echo update (\(string)): \(string)", try! call.receive().text)
+    }
+
+    let closeCompletionHandlerExpectation = expectation(description: "close completion handler called")
+    try! call.closeSend { closeCompletionHandlerExpectation.fulfill() }
+
+    waitForExpectations(timeout: defaultTimeout)
+  }
+}

+ 1 - 0
Tests/gRPCTests/GRPCTests.swift

@@ -88,6 +88,7 @@ func runTest(useSSL: Bool) {
       let certificate = try? String(contentsOf: certificateURL, encoding: .utf8),
       let key = try? String(contentsOf: keyURL, encoding: .utf8)
     else {
+      // FIXME: We don't want tests to silently pass just because the certificates can't be loaded.
       return
     }
     server = Server(address: address,

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 39 - 0
Tests/gRPCTests/TestKeys.swift


+ 1 - 0
Tests/gRPCTests/echo.grpc.swift

@@ -0,0 +1 @@
+../../Examples/Echo/Generated/echo.grpc.swift

+ 1 - 0
Tests/gRPCTests/echo.pb.swift

@@ -0,0 +1 @@
+../../Examples/Echo/Generated/echo.pb.swift

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно