Skip to content

Commit

Permalink
EventLoopFuture: more tests for andAll/whenAllComplete (#1297)
Browse files Browse the repository at this point in the history
Motivation:

andAllComplete and whenAllComplete weren't very well tested but have
fairly complex code.

Modifications:

- add more tests
- move two tests that were in the wrong file

Result:

better test coverage
  • Loading branch information
weissi authored and Lukasa committed Dec 9, 2019
1 parent e208ab9 commit e0757ea
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 28 deletions.
6 changes: 6 additions & 0 deletions Tests/NIOTests/EventLoopFutureTest+XCTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ extension EventLoopFutureTest {
("testPromiseCompletedWithFailedFuture", testPromiseCompletedWithFailedFuture),
("testPromiseCompletedWithSuccessfulResult", testPromiseCompletedWithSuccessfulResult),
("testPromiseCompletedWithFailedResult", testPromiseCompletedWithFailedResult),
("testAndAllCompleteWithZeroFutures", testAndAllCompleteWithZeroFutures),
("testAndAllSucceedWithZeroFutures", testAndAllSucceedWithZeroFutures),
("testAndAllCompleteWithPreSucceededFutures", testAndAllCompleteWithPreSucceededFutures),
("testAndAllCompleteWithPreFailedFutures", testAndAllCompleteWithPreFailedFutures),
("testAndAllCompleteWithMixOfPreSuccededAndNotYetCompletedFutures", testAndAllCompleteWithMixOfPreSuccededAndNotYetCompletedFutures),
("testWhenAllCompleteWithMixOfPreSuccededAndNotYetCompletedFutures", testWhenAllCompleteWithMixOfPreSuccededAndNotYetCompletedFutures),
]
}
}
Expand Down
128 changes: 128 additions & 0 deletions Tests/NIOTests/EventLoopFutureTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1112,4 +1112,132 @@ class EventLoopFutureTest : XCTestCase {
XCTAssert(type(of: error) == EventLoopFutureTestError.self)
}
}

func testAndAllCompleteWithZeroFutures() {
let eventLoop = EmbeddedEventLoop()
let done = DispatchWorkItem {}
EventLoopFuture<Void>.andAllComplete([], on: eventLoop).whenComplete { (result: Result<Void, Error>) in
_ = result.mapError { error -> Error in
XCTFail("unexpected error \(error)")
return error
}
done.perform()
}
done.wait()
}

func testAndAllSucceedWithZeroFutures() {
let eventLoop = EmbeddedEventLoop()
let done = DispatchWorkItem {}
EventLoopFuture<Void>.andAllSucceed([], on: eventLoop).whenComplete { result in
_ = result.mapError { error -> Error in
XCTFail("unexpected error \(error)")
return error
}
done.perform()
}
done.wait()
}

func testAndAllCompleteWithPreSucceededFutures() {
let eventLoop = EmbeddedEventLoop()
let succeeded = eventLoop.makeSucceededFuture(())

for i in 0..<10 {
XCTAssertNoThrow(try EventLoopFuture<Void>.andAllComplete(Array(repeating: succeeded, count: i),
on: eventLoop).wait())
}
}

func testAndAllCompleteWithPreFailedFutures() {
struct Dummy: Error {}
let eventLoop = EmbeddedEventLoop()
let failed: EventLoopFuture<Void> = eventLoop.makeFailedFuture(Dummy())

for i in 0..<10 {
XCTAssertNoThrow(try EventLoopFuture<Void>.andAllComplete(Array(repeating: failed, count: i),
on: eventLoop).wait())
}
}

func testAndAllCompleteWithMixOfPreSuccededAndNotYetCompletedFutures() {
struct Dummy: Error {}
let eventLoop = EmbeddedEventLoop()
let succeeded = eventLoop.makeSucceededFuture(())
let incompletes = [eventLoop.makePromise(of: Void.self), eventLoop.makePromise(of: Void.self),
eventLoop.makePromise(of: Void.self), eventLoop.makePromise(of: Void.self),
eventLoop.makePromise(of: Void.self)]
var futures: [EventLoopFuture<Void>] = []

for i in 0..<10 {
if i % 2 == 0 {
futures.append(succeeded)
} else {
futures.append(incompletes[i/2].futureResult)
}
}

let overall = EventLoopFuture<Void>.andAllComplete(futures, on: eventLoop)
XCTAssertFalse(overall.isFulfilled)
for (idx, incomplete) in incompletes.enumerated() {
XCTAssertFalse(overall.isFulfilled)
if idx % 2 == 0 {
incomplete.succeed(())
} else {
incomplete.fail(Dummy())
}
}
XCTAssertNoThrow(try overall.wait())
}

func testWhenAllCompleteWithMixOfPreSuccededAndNotYetCompletedFutures() {
struct Dummy: Error {}
let eventLoop = EmbeddedEventLoop()
let succeeded = eventLoop.makeSucceededFuture(())
let incompletes = [eventLoop.makePromise(of: Void.self), eventLoop.makePromise(of: Void.self),
eventLoop.makePromise(of: Void.self), eventLoop.makePromise(of: Void.self),
eventLoop.makePromise(of: Void.self)]
var futures: [EventLoopFuture<Void>] = []

for i in 0..<10 {
if i % 2 == 0 {
futures.append(succeeded)
} else {
futures.append(incompletes[i/2].futureResult)
}
}

let overall = EventLoopFuture<Void>.whenAllComplete(futures, on: eventLoop)
XCTAssertFalse(overall.isFulfilled)
for (idx, incomplete) in incompletes.enumerated() {
XCTAssertFalse(overall.isFulfilled)
if idx % 2 == 0 {
incomplete.succeed(())
} else {
incomplete.fail(Dummy())
}
}
let expected: [Result<Void, Error>] = [.success(()), .success(()),
.success(()), .failure(Dummy()),
.success(()), .success(()),
.success(()), .failure(Dummy()),
.success(()), .success(())]
func assertIsEqual(_ expecteds: [Result<Void, Error>], _ actuals: [Result<Void, Error>]) {
XCTAssertEqual(expecteds.count, actuals.count, "counts not equal")
for i in expecteds.indices {
let expected = expecteds[i]
let actual = actuals[i]
switch (expected, actual) {
case (.success(()), .success(())):
()
case (.failure(let le), .failure(let re)):
XCTAssert(le is Dummy)
XCTAssert(re is Dummy)
default:
XCTFail("\(expecteds) and \(actuals) not equal")
}
}
}
XCTAssertNoThrow(assertIsEqual(expected, try overall.wait()))
}
}
2 changes: 0 additions & 2 deletions Tests/NIOTests/EventLoopTest+XCTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ extension EventLoopTest {
("testRepeatedTaskThatIsImmediatelyCancelledNotifies", testRepeatedTaskThatIsImmediatelyCancelledNotifies),
("testRepeatedTaskThatIsCancelledAfterRunningAtLeastTwiceNotifies", testRepeatedTaskThatIsCancelledAfterRunningAtLeastTwiceNotifies),
("testRepeatedTaskThatCancelsItselfNotifiesOnlyWhenFinished", testRepeatedTaskThatCancelsItselfNotifiesOnlyWhenFinished),
("testAndAllCompleteWithZeroFutures", testAndAllCompleteWithZeroFutures),
("testAndAllSucceedWithZeroFutures", testAndAllSucceedWithZeroFutures),
("testCancelledScheduledTasksDoNotHoldOnToRunClosure", testCancelledScheduledTasksDoNotHoldOnToRunClosure),
("testIllegalCloseOfEventLoopFails", testIllegalCloseOfEventLoopFails),
("testSubtractingDeadlineFromPastAndFuturesDeadlinesWorks", testSubtractingDeadlineFromPastAndFuturesDeadlinesWorks),
Expand Down
26 changes: 0 additions & 26 deletions Tests/NIOTests/EventLoopTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -738,32 +738,6 @@ public final class EventLoopTest : XCTestCase {
XCTAssertEqual(XCTWaiter.wait(for: [expect1, expect2], timeout: 0.5), .completed)
}

func testAndAllCompleteWithZeroFutures() {
let eventLoop = EmbeddedEventLoop()
let done = DispatchWorkItem {}
EventLoopFuture<Void>.andAllComplete([], on: eventLoop).whenComplete { (result: Result<Void, Error>) in
_ = result.mapError { error -> Error in
XCTFail("unexpected error \(error)")
return error
}
done.perform()
}
done.wait()
}

func testAndAllSucceedWithZeroFutures() {
let eventLoop = EmbeddedEventLoop()
let done = DispatchWorkItem {}
EventLoopFuture<Void>.andAllSucceed([], on: eventLoop).whenComplete { result in
_ = result.mapError { error -> Error in
XCTFail("unexpected error \(error)")
return error
}
done.perform()
}
done.wait()
}

func testCancelledScheduledTasksDoNotHoldOnToRunClosure() {
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer {
Expand Down

0 comments on commit e0757ea

Please sign in to comment.