Skip to content

Commit 05b7633

Browse files
committed
Also add client-timeout tests and rename "ErrorHandlingTests" to "ConnectionFailureTests".
1 parent 2ebe048 commit 05b7633

File tree

5 files changed

+161
-51
lines changed

5 files changed

+161
-51
lines changed

Tests/LinuxMain.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ import XCTest
1818

1919
XCTMain([
2020
testCase(gRPCTests.allTests),
21+
testCase(ClientTimeoutTests.allTests),
22+
testCase(ConnectionFailureTests.allTests),
2123
testCase(EchoTests.allTests),
22-
testCase(ErrorHandlingTests.allTests),
2324
testCase(ServerTimeoutTests.allTests)
2425
])
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2018, 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 Dispatch
17+
import Foundation
18+
@testable import SwiftGRPC
19+
import XCTest
20+
21+
extension Echo_EchoRequest {
22+
init(text: String) {
23+
self.text = text
24+
}
25+
}
26+
27+
class BasicEchoTestCase: XCTestCase {
28+
let defaultTimeout: TimeInterval = 1.0
29+
30+
let provider = EchoProvider()
31+
var server: Echo_EchoServer!
32+
var client: Echo_EchoServiceClient!
33+
34+
var secure: Bool { return false }
35+
36+
override func setUp() {
37+
super.setUp()
38+
39+
let address = "localhost:5050"
40+
if secure {
41+
let certificateString = String(data: certificateForTests, encoding: .utf8)!
42+
server = Echo_EchoServer(address: address,
43+
certificateString: certificateString,
44+
keyString: String(data: keyForTests, encoding: .utf8)!,
45+
provider: provider)
46+
server.start(queue: DispatchQueue.global())
47+
client = Echo_EchoServiceClient(address: address, certificates: certificateString, host: "example.com")
48+
client.host = "example.com"
49+
} else {
50+
server = Echo_EchoServer(address: address, provider: provider)
51+
server.start(queue: DispatchQueue.global())
52+
client = Echo_EchoServiceClient(address: address, secure: false)
53+
}
54+
55+
client.timeout = defaultTimeout
56+
}
57+
58+
override func tearDown() {
59+
client = nil
60+
61+
server.server.stop()
62+
server = nil
63+
64+
super.tearDown()
65+
}
66+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright 2018, 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 Dispatch
17+
import Foundation
18+
@testable import SwiftGRPC
19+
import XCTest
20+
21+
class ClientTimeoutTests: BasicEchoTestCase {
22+
static var allTests: [(String, (ClientTimeoutTests) -> () throws -> Void)] {
23+
return [
24+
("testClientStreamingTimeoutBeforeSending", testClientStreamingTimeoutBeforeSending),
25+
("testClientStreamingTimeoutAfterSending", testClientStreamingTimeoutAfterSending)
26+
]
27+
}
28+
29+
override func setUp() {
30+
super.setUp()
31+
32+
client.timeout = 0.1
33+
}
34+
}
35+
36+
extension ClientTimeoutTests {
37+
func testClientStreamingTimeoutBeforeSending() {
38+
let completionHandlerExpectation = expectation(description: "final completion handler called")
39+
let call = try! client.collect { callResult in
40+
XCTAssertEqual(.deadlineExceeded, callResult.statusCode)
41+
completionHandlerExpectation.fulfill()
42+
}
43+
44+
Thread.sleep(forTimeInterval: 0.2)
45+
46+
let sendExpectation = expectation(description: "send completion handler 1 called")
47+
try! call.send(Echo_EchoRequest(text: "foo")) { [sendExpectation] in
48+
XCTAssertEqual(.unknown, $0 as! CallError)
49+
sendExpectation.fulfill()
50+
}
51+
call.waitForSendOperationsToFinish()
52+
53+
do {
54+
_ = try call.closeAndReceive()
55+
XCTFail("should have thrown")
56+
} catch let receiveError {
57+
XCTAssertEqual(.unknown, (receiveError as! RPCError).callResult!.statusCode)
58+
}
59+
60+
waitForExpectations(timeout: defaultTimeout)
61+
}
62+
63+
func testClientStreamingTimeoutAfterSending() {
64+
let completionHandlerExpectation = expectation(description: "final completion handler called")
65+
let call = try! client.collect { callResult in
66+
XCTAssertEqual(.deadlineExceeded, callResult.statusCode)
67+
completionHandlerExpectation.fulfill()
68+
}
69+
70+
let sendExpectation = expectation(description: "send completion handler 1 called")
71+
try! call.send(Echo_EchoRequest(text: "foo")) { [sendExpectation] in XCTAssertNil($0); sendExpectation.fulfill() }
72+
call.waitForSendOperationsToFinish()
73+
74+
Thread.sleep(forTimeInterval: 0.2)
75+
76+
do {
77+
_ = try call.closeAndReceive()
78+
XCTFail("should have thrown")
79+
} catch let receiveError {
80+
XCTAssertEqual(.unknown, (receiveError as! RPCError).callResult!.statusCode)
81+
}
82+
83+
waitForExpectations(timeout: defaultTimeout)
84+
}
85+
86+
// FIXME(danielalm): Add support for setting a maximum timeout on the server, to prevent DoS attacks where clients
87+
// start a ton of calls, but never finish them (i.e. essentially leaking a connection on the server side).
88+
}

Tests/SwiftGRPCTests/ErrorHandlingTests.swift renamed to Tests/SwiftGRPCTests/ConnectionFailureTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ import Foundation
1818
@testable import SwiftGRPC
1919
import XCTest
2020

21-
// TODO(danielalm): Also run a similar set of tests with SSL enabled.
22-
class ErrorHandlingTests: XCTestCase {
23-
static var allTests: [(String, (ErrorHandlingTests) -> () throws -> Void)] {
21+
// TODO(danielalm): Also test connection failure with regards to SSL issues.
22+
class ConnectionFailureTests: XCTestCase {
23+
static var allTests: [(String, (ConnectionFailureTests) -> () throws -> Void)] {
2424
return [
2525
("testConnectionFailureUnary", testConnectionFailureUnary),
2626
("testConnectionFailureClientStreaming", testConnectionFailureClientStreaming),
@@ -34,7 +34,7 @@ class ErrorHandlingTests: XCTestCase {
3434
let defaultTimeout: TimeInterval = 0.5
3535
}
3636

37-
extension ErrorHandlingTests {
37+
extension ConnectionFailureTests {
3838
func testConnectionFailureUnary() {
3939
let client = Echo_EchoServiceClient(address: "localhost:1234", secure: false)
4040
client.timeout = defaultTimeout

Tests/SwiftGRPCTests/EchoTests.swift

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,7 @@ import Foundation
1818
@testable import SwiftGRPC
1919
import XCTest
2020

21-
extension Echo_EchoRequest {
22-
init(text: String) {
23-
self.text = text
24-
}
25-
}
26-
27-
class EchoTests: XCTestCase {
21+
class EchoTests: BasicEchoTestCase {
2822
static var allTests: [(String, (EchoTests) -> () throws -> Void)] {
2923
return [
3024
("testUnary", testUnary),
@@ -40,45 +34,6 @@ class EchoTests: XCTestCase {
4034
}
4135

4236
static let lotsOfStrings = (0..<1000).map { String(describing: $0) }
43-
44-
let defaultTimeout: TimeInterval = 1.0
45-
46-
let provider = EchoProvider()
47-
var server: Echo_EchoServer!
48-
var client: Echo_EchoServiceClient!
49-
50-
var secure: Bool { return false }
51-
52-
override func setUp() {
53-
super.setUp()
54-
55-
let address = "localhost:5050"
56-
if secure {
57-
let certificateString = String(data: certificateForTests, encoding: .utf8)!
58-
server = Echo_EchoServer(address: address,
59-
certificateString: certificateString,
60-
keyString: String(data: keyForTests, encoding: .utf8)!,
61-
provider: provider)
62-
server.start(queue: DispatchQueue.global())
63-
client = Echo_EchoServiceClient(address: address, certificates: certificateString, host: "example.com")
64-
client.host = "example.com"
65-
} else {
66-
server = Echo_EchoServer(address: address, provider: provider)
67-
server.start(queue: DispatchQueue.global())
68-
client = Echo_EchoServiceClient(address: address, secure: false)
69-
}
70-
71-
client.timeout = defaultTimeout
72-
}
73-
74-
override func tearDown() {
75-
client = nil
76-
77-
server.server.stop()
78-
server = nil
79-
80-
super.tearDown()
81-
}
8237
}
8338

8439
class EchoTestsSecure: EchoTests {

0 commit comments

Comments
 (0)