Skip to content

Commit 9e723c8

Browse files
committed
Fixes observable sequence completion in case of empty arrays for combineLatest and zip. ReactiveX#1205
1 parent 3e3af7e commit 9e723c8

File tree

5 files changed

+51
-0
lines changed

5 files changed

+51
-0
lines changed

RxSwift/Observables/CombineLatest+Collection.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ final fileprivate class CombineLatestCollectionTypeSink<C: Collection, O: Observ
127127

128128
j += 1
129129
}
130+
131+
if _parent._sources.isEmpty {
132+
self.forwardOn(.completed)
133+
}
130134

131135
return Disposables.create(_subscriptions)
132136
}

RxSwift/Observables/Zip+Collection.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ final fileprivate class ZipCollectionTypeSink<C: Collection, O: ObserverType>
139139
_subscriptions[j].setDisposable(disposable)
140140
j += 1
141141
}
142+
143+
if _parent.sources.isEmpty {
144+
self.forwardOn(.completed)
145+
}
142146

143147
return Disposables.create(_subscriptions)
144148
}

Sources/AllTestz/main.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,7 @@ final class ObservableZipTest_ : ObservableZipTest, RxTestCase {
725725
("testZip_RightCompletesFirst", ObservableZipTest.testZip_RightCompletesFirst),
726726
("testZip_LeftTriggersSelectorError", ObservableZipTest.testZip_LeftTriggersSelectorError),
727727
("testZip_RightTriggersSelectorError", ObservableZipTest.testZip_RightTriggersSelectorError),
728+
("testZip_NAry_emptyArray", ObservableZipTest.testZip_NAry_emptyArray),
728729
("testZip_NAry_symmetric", ObservableZipTest.testZip_NAry_symmetric),
729730
("testZip_NAry_asymmetric", ObservableZipTest.testZip_NAry_asymmetric),
730731
("testZip_NAry_error", ObservableZipTest.testZip_NAry_error),
@@ -1294,6 +1295,7 @@ final class ObservableCombineLatestTest_ : ObservableCombineLatestTest, RxTestCa
12941295
("testCombineLatest_DeadlockErrorAfterN", ObservableCombineLatestTest.testCombineLatest_DeadlockErrorAfterN),
12951296
("testCombineLatest_DeadlockErrorImmediatelly", ObservableCombineLatestTest.testCombineLatest_DeadlockErrorImmediatelly),
12961297
("testReplay_DeadlockEmpty", ObservableCombineLatestTest.testReplay_DeadlockEmpty),
1298+
("testCombineLatest_emptyArrayN", ObservableCombineLatestTest.testCombineLatest_emptyArrayN),
12971299
("testCombineLatest_NeverN", ObservableCombineLatestTest.testCombineLatest_NeverN),
12981300
("testCombineLatest_NeverEmptyN", ObservableCombineLatestTest.testCombineLatest_NeverEmptyN),
12991301
("testCombineLatest_EmptyNeverN", ObservableCombineLatestTest.testCombineLatest_EmptyNeverN),

Tests/RxSwiftTests/Observable+CombineLatestTests.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,27 @@ extension ObservableCombineLatestTest {
886886

887887

888888
extension ObservableCombineLatestTest {
889+
func testCombineLatest_emptyArrayN() {
890+
let factories: [() -> Observable<Int>] =
891+
[
892+
{
893+
Observable<Int>.combineLatest(([] as [Observable<Int>]).map { $0.asObservable() }).map { $0.reduce(0, +) }
894+
},
895+
{
896+
Observable.combineLatest(([] as [Observable<Int>]).map { $0.asObservable() }) { $0.reduce(0, +) }
897+
},
898+
]
899+
for factory in factories {
900+
let scheduler = TestScheduler(initialClock: 0)
901+
902+
let res = scheduler.start {
903+
factory()
904+
}
905+
906+
XCTAssertEqual(res.events, [completed(200, Int.self)])
907+
}
908+
}
909+
889910
func testCombineLatest_NeverN() {
890911
let factories: [(TestableObservable<Int>, TestableObservable<Int>, TestableObservable<Int>) -> Observable<Int>] =
891912
[

Tests/RxSwiftTests/Observable+ZipTests.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,26 @@ extension ObservableZipTest {
606606
}
607607

608608
extension ObservableZipTest {
609+
func testZip_NAry_emptyArray() {
610+
let factories: [() -> Observable<EquatableArray<Int>>] =
611+
[
612+
{ Observable.zip(([] as [Observable<Int>]).map { $0.asObservable() }) { EquatableArray($0) } },
613+
{ Observable.zip(([] as [Observable<Int>]).map { $0.asObservable() }).map { EquatableArray($0) } },
614+
]
615+
616+
for factory in factories {
617+
let scheduler = TestScheduler(initialClock: 0)
618+
619+
let res = scheduler.start {
620+
factory()
621+
}
622+
623+
XCTAssertEqual(res.events, [
624+
completed(200)
625+
])
626+
}
627+
}
628+
609629
func testZip_NAry_symmetric() {
610630
let factories: [(TestableObservable<Int>, TestableObservable<Int>, TestableObservable<Int>) -> Observable<EquatableArray<Int>>] =
611631
[

0 commit comments

Comments
 (0)