Skip to content

Commit ad6973c

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

File tree

8 files changed

+169
-80
lines changed

8 files changed

+169
-80
lines changed

Sources/Examples/Echo/EchoProvider.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ class EchoProvider: Echo_EchoProvider {
4949
else { break } // End of stream
5050
parts.append(request.text)
5151
} catch {
52-
print("\(error)")
52+
print("collect error: \(error)")
53+
break
5354
}
5455
}
5556
var response = Echo_EchoResponse()
@@ -73,7 +74,7 @@ class EchoProvider: Echo_EchoProvider {
7374
}
7475
}
7576
} catch {
76-
print("\(error)")
77+
print("update error: \(error)")
7778
break
7879
}
7980
}

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

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 {

Tests/SwiftGRPCTests/GRPCTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ func callServerStream(channel: Channel) throws {
214214
let messageString = String(data: data, encoding: .utf8)
215215
XCTAssertEqual(messageString, serverText)
216216
} else {
217-
print("callServerStream unexpected result: \(callResult)")
217+
XCTFail("callServerStream unexpected result: \(callResult)")
218218
}
219219
messageSem.signal()
220220
}
@@ -271,7 +271,7 @@ func callBiDiStream(channel: Channel) throws {
271271
let messageString = String(data: data, encoding: .utf8)
272272
XCTAssertEqual(messageString, serverPong)
273273
} else {
274-
print("callBiDiStream unexpected result: \(callResult)")
274+
XCTFail("callBiDiStream unexpected result: \(callResult)")
275275
}
276276
pongSem.signal()
277277
}

Tests/SwiftGRPCTests/ServerTimeoutTests.swift

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ fileprivate class TimingOutEchoProvider: Echo_EchoProvider {
3737
}
3838
}
3939

40-
class ServerTimeoutTests: XCTestCase {
40+
class ServerTimeoutTests: BasicEchoTestCase {
4141
static var allTests: [(String, (ServerTimeoutTests) -> () throws -> Void)] {
4242
return [
4343
("testTimeoutUnary", testTimeoutUnary),
@@ -47,31 +47,9 @@ class ServerTimeoutTests: XCTestCase {
4747
]
4848
}
4949

50-
let defaultTimeout: TimeInterval = 0.1
50+
override func makeProvider() -> Echo_EchoProvider { return TimingOutEchoProvider() }
5151

52-
fileprivate let provider = TimingOutEchoProvider()
53-
var server: Echo_EchoServer!
54-
var client: Echo_EchoServiceClient!
55-
56-
override func setUp() {
57-
super.setUp()
58-
59-
let address = "localhost:5050"
60-
server = Echo_EchoServer(address: address, provider: provider)
61-
server.start(queue: DispatchQueue.global())
62-
client = Echo_EchoServiceClient(address: address, secure: false)
63-
64-
client.timeout = defaultTimeout
65-
}
66-
67-
override func tearDown() {
68-
client = nil
69-
70-
server.server.stop()
71-
server = nil
72-
73-
super.tearDown()
74-
}
52+
override var defaultTimeout: TimeInterval { return 0.1 }
7553
}
7654

7755
extension ServerTimeoutTests {

0 commit comments

Comments
 (0)