/* * Copyright 2017, 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 SwiftGRPC import XCTest class gRPCTests: XCTestCase { func testConnectivity() { runTest(useSSL: false) } func testConnectivitySecure() { runTest(useSSL: true) } static var allTests: [(String, (gRPCTests) -> () throws -> Void)] { return [ ("testConnectivity", testConnectivity), ("testConnectivitySecure", testConnectivitySecure) ] } } let address = "localhost:8085" let host = "example.com" let clientText = "hello, server!" let serverText = "hello, client!" let initialClientMetadata = [ "x": "xylophone", "y": "yu", "z": "zither" ] let initialServerMetadata = [ "a": "Apple", "b": "Banana", "c": "Cherry" ] let trailingServerMetadata = [ // We have more than ten entries here to ensure that even large metadata entries work // and aren't limited by e.g. a fixed-size entry buffer. "0": "zero", "1": "one", "2": "two", "3": "three", "4": "four", "5": "five", "6": "six", "7": "seven", "8": "eight", "9": "nine", "10": "ten", "11": "eleven", "12": "twelve" ] let steps = 100 let hello = "/hello.unary" let helloServerStream = "/hello.server-stream" let helloBiDiStream = "/hello.bidi-stream" // Return code/message for unary test let oddStatusCode = StatusCode.ok let oddStatusMessage = "OK" let evenStatusCode = StatusCode.notFound let eventStatusMessage = "Not Found" func runTest(useSSL: Bool) { gRPC.initialize() var serverRunningSemaphore: DispatchSemaphore? // create the server let server: Server if useSSL { server = Server(address: address, key: String(data: keyForTests, encoding: .utf8)!, certs: String(data: certificateForTests, encoding: .utf8)!) } else { server = Server(address: address) } // start the server do { serverRunningSemaphore = try runServer(server: server) } catch { XCTFail("server error \(error)") } // run the client do { try runClient(useSSL: useSSL) } catch { XCTFail("client error \(error)") } // stop the server server.stop() // wait until the server has shut down _ = serverRunningSemaphore!.wait() } func verify_metadata(_ metadata: Metadata, expected: [String: String], file: StaticString = #file, line: UInt = #line) { XCTAssertGreaterThanOrEqual(metadata.count(), expected.count) var allPresentKeys = Set() for i in 0.. DispatchSemaphore { var requestCount = 0 let sem = DispatchSemaphore(value: 0) server.run { requestHandler in do { if let method = requestHandler.method { switch method { case hello: try handleUnary(requestHandler: requestHandler, requestCount: requestCount) case helloServerStream: try handleServerStream(requestHandler: requestHandler) case helloBiDiStream: try handleBiDiStream(requestHandler: requestHandler) default: XCTFail("Invalid method \(method)") } } requestCount += 1 } catch { XCTFail("error \(error)") } } server.onCompletion = { // return from runServer() sem.signal() } // wait for the server to exit return sem } func handleUnary(requestHandler: Handler, requestCount: Int) throws { XCTAssertEqual(requestHandler.host, host) XCTAssertEqual(requestHandler.method, hello) let initialMetadata = requestHandler.requestMetadata verify_metadata(initialMetadata, expected: initialClientMetadata) let initialMetadataToSend = Metadata(initialServerMetadata) try requestHandler.receiveMessage(initialMetadata: initialMetadataToSend) { messageData in let messageString = String(data: messageData!, encoding: .utf8) XCTAssertEqual(messageString, clientText) } if (requestCount % 2) == 0 { let replyMessage = serverText let trailingMetadataToSend = Metadata(trailingServerMetadata) try requestHandler.sendResponse(message: replyMessage.data(using: .utf8)!, status: ServerStatus(code: evenStatusCode, message: eventStatusMessage, trailingMetadata: trailingMetadataToSend)) } else { let trailingMetadataToSend = Metadata(trailingServerMetadata) try requestHandler.sendStatus(ServerStatus(code: oddStatusCode, message: oddStatusMessage, trailingMetadata: trailingMetadataToSend)) } } func handleServerStream(requestHandler: Handler) throws { XCTAssertEqual(requestHandler.host, host) XCTAssertEqual(requestHandler.method, helloServerStream) let initialMetadata = requestHandler.requestMetadata verify_metadata(initialMetadata, expected: initialClientMetadata) let initialMetadataToSend = Metadata(initialServerMetadata) try requestHandler.receiveMessage(initialMetadata: initialMetadataToSend) { messageData in let messageString = String(data: messageData!, encoding: .utf8) XCTAssertEqual(messageString, clientText) } let replyMessage = serverText for _ in 0..