mirror of
https://github.com/ReactiveX/RxSwift.git
synced 2024-10-04 05:57:23 +03:00
Merge branch 'feature/materialize_operator' of https://github.com/sergdort/RxSwift into sergdort-feature/materialize_operator
This commit is contained in:
commit
4ebb4f844f
@ -68,6 +68,7 @@ custom_categories:
|
||||
- Deferred
|
||||
- Delay
|
||||
- DelaySubscription
|
||||
- Dematerialize
|
||||
- DistinctUntilChanged
|
||||
- Do
|
||||
- ElementAt
|
||||
@ -78,6 +79,7 @@ custom_categories:
|
||||
- GroupBy
|
||||
- Just
|
||||
- Map
|
||||
- Materialize
|
||||
- Merge
|
||||
- Multicast
|
||||
- Never
|
||||
|
@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.
|
||||
## Master
|
||||
|
||||
* Deprecates `bindTo` in favor of `bind(to:)`.
|
||||
* Adds [`materialize()`](http://reactivex.io/documentation/operators/materialize-dematerialize.html) operator
|
||||
|
||||
## [3.3.1](https://github.com/ReactiveX/RxSwift/releases/tag/3.3.1) (Xcode 8 / Swift 3.0 compatible)
|
||||
|
||||
|
@ -952,6 +952,14 @@
|
||||
C8BF34D01C2E426800416CAE /* Platform.Linux.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8BF34CA1C2E426800416CAE /* Platform.Linux.swift */; };
|
||||
C8BF34D11C2E426800416CAE /* Platform.Linux.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8BF34CA1C2E426800416CAE /* Platform.Linux.swift */; };
|
||||
C8BF34D21C2E426800416CAE /* Platform.Linux.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8BF34CA1C2E426800416CAE /* Platform.Linux.swift */; };
|
||||
C8C0A4A11E886B1200B8215F /* Dematerialize.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C0A49F1E886B1200B8215F /* Dematerialize.swift */; };
|
||||
C8C0A4A21E886B1200B8215F /* Dematerialize.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C0A49F1E886B1200B8215F /* Dematerialize.swift */; };
|
||||
C8C0A4A31E886B1200B8215F /* Dematerialize.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C0A49F1E886B1200B8215F /* Dematerialize.swift */; };
|
||||
C8C0A4A41E886B1200B8215F /* Dematerialize.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C0A49F1E886B1200B8215F /* Dematerialize.swift */; };
|
||||
C8C0A4A51E886B1200B8215F /* Materialize.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C0A4A01E886B1200B8215F /* Materialize.swift */; };
|
||||
C8C0A4A61E886B1200B8215F /* Materialize.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C0A4A01E886B1200B8215F /* Materialize.swift */; };
|
||||
C8C0A4A71E886B1200B8215F /* Materialize.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C0A4A01E886B1200B8215F /* Materialize.swift */; };
|
||||
C8C0A4A81E886B1200B8215F /* Materialize.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C0A4A01E886B1200B8215F /* Materialize.swift */; };
|
||||
C8C217D51CB7100E0038A2E6 /* UITableView+RxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C217D41CB7100E0038A2E6 /* UITableView+RxTests.swift */; };
|
||||
C8C217D71CB710200038A2E6 /* UICollectionView+RxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C217D61CB710200038A2E6 /* UICollectionView+RxTests.swift */; };
|
||||
C8C3D9FE1B935EDF004D233E /* Zip+Collection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C3D9FD1B935EDF004D233E /* Zip+Collection.swift */; };
|
||||
@ -1958,6 +1966,8 @@
|
||||
C8BCD3F31C14B6D1005F1280 /* NSLayoutConstraint+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraint+Rx.swift"; sourceTree = "<group>"; };
|
||||
C8BF34C91C2E426800416CAE /* Platform.Darwin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Platform.Darwin.swift; sourceTree = "<group>"; };
|
||||
C8BF34CA1C2E426800416CAE /* Platform.Linux.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Platform.Linux.swift; sourceTree = "<group>"; };
|
||||
C8C0A49F1E886B1200B8215F /* Dematerialize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dematerialize.swift; sourceTree = "<group>"; };
|
||||
C8C0A4A01E886B1200B8215F /* Materialize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Materialize.swift; sourceTree = "<group>"; };
|
||||
C8C217D41CB7100E0038A2E6 /* UITableView+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITableView+RxTests.swift"; sourceTree = "<group>"; };
|
||||
C8C217D61CB710200038A2E6 /* UICollectionView+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UICollectionView+RxTests.swift"; sourceTree = "<group>"; };
|
||||
C8C3D9FD1B935EDF004D233E /* Zip+Collection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Zip+Collection.swift"; sourceTree = "<group>"; };
|
||||
@ -2273,10 +2283,11 @@
|
||||
C8093C6A1B8A72BE0088E94D /* Implementations */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C85217E31E3374710015DD38 /* GroupBy.swift */,
|
||||
CB883B491BE369AA000AC2EE /* AddRef.swift */,
|
||||
C8093C6B1B8A72BE0088E94D /* Amb.swift */,
|
||||
C8C3DA111B93A3EA004D233E /* AnonymousObservable.swift */,
|
||||
C89814811E75B77B0035949C /* AsMaybe.swift */,
|
||||
C89814861E75BE590035949C /* AsSingle.swift */,
|
||||
C821DBA11BA4DCAB008F3809 /* Buffer.swift */,
|
||||
C8093C6E1B8A72BE0088E94D /* Catch.swift */,
|
||||
C8093C711B8A72BE0088E94D /* CombineLatest.swift */,
|
||||
@ -2291,6 +2302,7 @@
|
||||
C8093C761B8A72BE0088E94D /* Deferred.swift */,
|
||||
C86B0A551D735CCC005D8A16 /* Delay.swift */,
|
||||
C8093C771B8A72BE0088E94D /* DelaySubscription.swift */,
|
||||
C8C0A49F1E886B1200B8215F /* Dematerialize.swift */,
|
||||
C8093C781B8A72BE0088E94D /* DistinctUntilChanged.swift */,
|
||||
C8093C791B8A72BE0088E94D /* Do.swift */,
|
||||
C84CC53F1BDC3B3700E06A64 /* ElementAt.swift */,
|
||||
@ -2298,8 +2310,10 @@
|
||||
C8C3DA081B93941E004D233E /* Error.swift */,
|
||||
C8093C7A1B8A72BE0088E94D /* Filter.swift */,
|
||||
C84B38ED1BA433CD001B7D88 /* Generate.swift */,
|
||||
C85217E31E3374710015DD38 /* GroupBy.swift */,
|
||||
C8C3DA021B9390C4004D233E /* Just.swift */,
|
||||
C8093C7C1B8A72BE0088E94D /* Map.swift */,
|
||||
C8C0A4A01E886B1200B8215F /* Materialize.swift */,
|
||||
C8093C7D1B8A72BE0088E94D /* Merge.swift */,
|
||||
C8093C7E1B8A72BE0088E94D /* Multicast.swift */,
|
||||
C8C3DA0B1B93959F004D233E /* Never.swift */,
|
||||
@ -2325,6 +2339,7 @@
|
||||
C8093C8A1B8A72BE0088E94D /* StartWith.swift */,
|
||||
C8093C8B1B8A72BE0088E94D /* SubscribeOn.swift */,
|
||||
C8093C8C1B8A72BE0088E94D /* Switch.swift */,
|
||||
252FC1DE1E0DC64C00D28877 /* SwitchIfEmpty.swift */,
|
||||
C8093C8D1B8A72BE0088E94D /* Take.swift */,
|
||||
B1B7C3BC1BDD39DB0076934E /* TakeLast.swift */,
|
||||
C8093C8E1B8A72BE0088E94D /* TakeUntil.swift */,
|
||||
@ -2340,9 +2355,6 @@
|
||||
C8093C921B8A72BE0088E94D /* Zip+arity.swift */,
|
||||
C8093C931B8A72BE0088E94D /* Zip+arity.tt */,
|
||||
C8C3D9FD1B935EDF004D233E /* Zip+Collection.swift */,
|
||||
252FC1DE1E0DC64C00D28877 /* SwitchIfEmpty.swift */,
|
||||
C89814811E75B77B0035949C /* AsMaybe.swift */,
|
||||
C89814861E75BE590035949C /* AsSingle.swift */,
|
||||
);
|
||||
path = Implementations;
|
||||
sourceTree = "<group>";
|
||||
@ -4422,6 +4434,7 @@
|
||||
C84CC5541BDCF49300E06A64 /* SynchronizedOnType.swift in Sources */,
|
||||
C8093D261B8A72BE0088E94D /* Multicast.swift in Sources */,
|
||||
C8C3DA101B939767004D233E /* CurrentThreadScheduler.swift in Sources */,
|
||||
C8C0A4A61E886B1200B8215F /* Materialize.swift in Sources */,
|
||||
252FC1D01E0D250500D28877 /* DefaultIfEmpty.swift in Sources */,
|
||||
C8093D861B8A72BE0088E94D /* Rx.swift in Sources */,
|
||||
C80D342F1B9245A40014629D /* CombineLatest+Collection.swift in Sources */,
|
||||
@ -4497,6 +4510,7 @@
|
||||
C8093CEC1B8A72BE0088E94D /* SerialDisposable.swift in Sources */,
|
||||
C8C3DA0D1B93959F004D233E /* Never.swift in Sources */,
|
||||
C85217E51E3374710015DD38 /* GroupBy.swift in Sources */,
|
||||
C8C0A4A21E886B1200B8215F /* Dematerialize.swift in Sources */,
|
||||
C84CC5681BDD08A500E06A64 /* SubscriptionDisposable.swift in Sources */,
|
||||
C8093CF61B8A72BE0088E94D /* Event.swift in Sources */,
|
||||
C83D73C51C1DBAEE003DC470 /* ScheduledItem.swift in Sources */,
|
||||
@ -4664,6 +4678,7 @@
|
||||
C8C3DA0F1B939767004D233E /* CurrentThreadScheduler.swift in Sources */,
|
||||
C8093D851B8A72BE0088E94D /* Rx.swift in Sources */,
|
||||
C80D342E1B9245A40014629D /* CombineLatest+Collection.swift in Sources */,
|
||||
C8C0A4A51E886B1200B8215F /* Materialize.swift in Sources */,
|
||||
252FC1CF1E0D250500D28877 /* DefaultIfEmpty.swift in Sources */,
|
||||
C84CC5401BDC3B3700E06A64 /* ElementAt.swift in Sources */,
|
||||
C8093DA51B8A72BE0088E94D /* SubjectType.swift in Sources */,
|
||||
@ -4739,6 +4754,7 @@
|
||||
C8093CEB1B8A72BE0088E94D /* SerialDisposable.swift in Sources */,
|
||||
C8C3DA0C1B93959F004D233E /* Never.swift in Sources */,
|
||||
C85217E41E3374710015DD38 /* GroupBy.swift in Sources */,
|
||||
C8C0A4A11E886B1200B8215F /* Dematerialize.swift in Sources */,
|
||||
C84CC5671BDD08A500E06A64 /* SubscriptionDisposable.swift in Sources */,
|
||||
C8093CF51B8A72BE0088E94D /* Event.swift in Sources */,
|
||||
C83D73C41C1DBAEE003DC470 /* ScheduledItem.swift in Sources */,
|
||||
@ -4834,6 +4850,7 @@
|
||||
C84CC5561BDCF49300E06A64 /* SynchronizedOnType.swift in Sources */,
|
||||
C8F0BFBA1BBBFB8B001B112F /* Multicast.swift in Sources */,
|
||||
C8F0BFBB1BBBFB8B001B112F /* CurrentThreadScheduler.swift in Sources */,
|
||||
C8C0A4A81E886B1200B8215F /* Materialize.swift in Sources */,
|
||||
252FC1D21E0D250500D28877 /* DefaultIfEmpty.swift in Sources */,
|
||||
C8F0BFBC1BBBFB8B001B112F /* Rx.swift in Sources */,
|
||||
C8F0BFBD1BBBFB8B001B112F /* CombineLatest+Collection.swift in Sources */,
|
||||
@ -4909,6 +4926,7 @@
|
||||
C8F0BFF61BBBFB8B001B112F /* SerialDisposable.swift in Sources */,
|
||||
C8F0BFF71BBBFB8B001B112F /* Never.swift in Sources */,
|
||||
C85217E71E3374710015DD38 /* GroupBy.swift in Sources */,
|
||||
C8C0A4A41E886B1200B8215F /* Dematerialize.swift in Sources */,
|
||||
C84CC56A1BDD08A500E06A64 /* SubscriptionDisposable.swift in Sources */,
|
||||
C8F0BFF91BBBFB8B001B112F /* Event.swift in Sources */,
|
||||
C83D73C71C1DBAEE003DC470 /* ScheduledItem.swift in Sources */,
|
||||
@ -5191,6 +5209,7 @@
|
||||
D2752D631BC5551B0070C418 /* SkipUntil.swift in Sources */,
|
||||
D2EBEB351BB9B6D2003A27DC /* ObserverBase.swift in Sources */,
|
||||
D2EBEB0F1BB9B6C1003A27DC /* Generate.swift in Sources */,
|
||||
C8C0A4A71E886B1200B8215F /* Materialize.swift in Sources */,
|
||||
252FC1D11E0D250500D28877 /* DefaultIfEmpty.swift in Sources */,
|
||||
D2EBEB1F1BB9B6C1003A27DC /* Skip.swift in Sources */,
|
||||
D2EBEB321BB9B6CA003A27DC /* Observable+StandardSequenceOperators.swift in Sources */,
|
||||
@ -5266,6 +5285,7 @@
|
||||
D2EBEB171BB9B6C1003A27DC /* Producer.swift in Sources */,
|
||||
D2EBEAF91BB9B6B2003A27DC /* SerialDisposable.swift in Sources */,
|
||||
C85217E61E3374710015DD38 /* GroupBy.swift in Sources */,
|
||||
C8C0A4A31E886B1200B8215F /* Dematerialize.swift in Sources */,
|
||||
C84CC5691BDD08A500E06A64 /* SubscriptionDisposable.swift in Sources */,
|
||||
D2EBEB0A1BB9B6C1003A27DC /* Do.swift in Sources */,
|
||||
C83D73C61C1DBAEE003DC470 /* ScheduledItem.swift in Sources */,
|
||||
|
@ -88,3 +88,19 @@ extension Event {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A type that can be converted to `Event<Element>`.
|
||||
public protocol EventConvertible {
|
||||
/// Type of element in event
|
||||
associatedtype ElementType
|
||||
|
||||
/// Event representation of this instance
|
||||
var event: Event<ElementType> { get }
|
||||
}
|
||||
|
||||
extension Event : EventConvertible {
|
||||
/// Event representation of this instance
|
||||
public var event: Event<Element> {
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
39
RxSwift/Observables/Implementations/Dematerialize.swift
Normal file
39
RxSwift/Observables/Implementations/Dematerialize.swift
Normal file
@ -0,0 +1,39 @@
|
||||
//
|
||||
// Dematerialize.swift
|
||||
// RxSwift
|
||||
//
|
||||
// Created by Jamie Pinkham on 3/13/17.
|
||||
// Copyright © 2017 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
fileprivate final class DematerializeSink<Element: EventConvertible, O: ObserverType>: Sink<O>, ObserverType where O.E == Element.ElementType {
|
||||
fileprivate func on(_ event: Event<Element>) {
|
||||
switch event {
|
||||
case .next(let element):
|
||||
forwardOn(element.event)
|
||||
if element.event.isStopEvent {
|
||||
dispose()
|
||||
}
|
||||
case .completed:
|
||||
forwardOn(.completed)
|
||||
dispose()
|
||||
case .error(let error):
|
||||
forwardOn(.error(error))
|
||||
dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class Dematerialize<Element: EventConvertible>: Producer<Element.ElementType> {
|
||||
private let _source: Observable<Element>
|
||||
|
||||
init(source: Observable<Element>) {
|
||||
_source = source
|
||||
}
|
||||
|
||||
override func run<O : ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element.ElementType {
|
||||
let sink = DematerializeSink<Element, O>(observer: observer, cancel: cancel)
|
||||
let subscription = _source.subscribe(sink)
|
||||
return (sink: sink, subscription: subscription)
|
||||
}
|
||||
}
|
33
RxSwift/Observables/Implementations/Materialize.swift
Normal file
33
RxSwift/Observables/Implementations/Materialize.swift
Normal file
@ -0,0 +1,33 @@
|
||||
//
|
||||
// Materialize.swift
|
||||
// RxSwift
|
||||
//
|
||||
// Created by sergdort on 08/03/2017.
|
||||
// Copyright © 2017 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
|
||||
fileprivate final class MaterializeSink<Element, O: ObserverType>: Sink<O>, ObserverType where O.E == Event<Element> {
|
||||
|
||||
func on(_ event: Event<Element>) {
|
||||
forwardOn(.next(event))
|
||||
if event.isStopEvent {
|
||||
forwardOn(.completed)
|
||||
dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class Materialize<Element>: Producer<Event<Element>> {
|
||||
private let _source: Observable<Element>
|
||||
|
||||
init(source: Observable<Element>) {
|
||||
_source = source
|
||||
}
|
||||
|
||||
override func run<O: ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == E {
|
||||
let sink = MaterializeSink(observer: observer, cancel: cancel)
|
||||
let subscription = _source.subscribe(sink)
|
||||
|
||||
return (sink: sink, subscription: subscription)
|
||||
}
|
||||
}
|
@ -229,3 +229,28 @@ extension ObservableType {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: materialize
|
||||
|
||||
extension ObservableType {
|
||||
/**
|
||||
Convert any Observable into an Observable of its events.
|
||||
- seealso: [materialize operator on reactivex.io](http://reactivex.io/documentation/operators/materialize-dematerialize.html)
|
||||
- returns: An observable sequence that wraps events in an Event<E>. The returned Observable never errors, but it does complete after observing all of the events of the underlying Observable.
|
||||
*/
|
||||
public func materialize() -> Observable<Event<E>> {
|
||||
return Materialize(source: self.asObservable())
|
||||
}
|
||||
}
|
||||
|
||||
extension ObservableType where E: EventConvertible {
|
||||
/**
|
||||
Convert any previously materialized Observable into it's original form.
|
||||
- seealso: [materialize operator on reactivex.io](http://reactivex.io/documentation/operators/materialize-dematerialize.html)
|
||||
- returns: The dematerialized observable sequence.
|
||||
*/
|
||||
public func dematerialize() -> Observable<E.ElementType> {
|
||||
return Dematerialize(source: self.asObservable())
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -416,6 +416,18 @@ final class ObservableSingleTest_ : ObservableSingleTest, RxTestCase {
|
||||
("testDefaultIfEmpty_Source_Errors", ObservableSingleTest.testDefaultIfEmpty_Source_Errors),
|
||||
("testDefaultIfEmpty_Source_Emits", ObservableSingleTest.testDefaultIfEmpty_Source_Emits),
|
||||
("testDefaultIfEmpty_Never", ObservableSingleTest.testDefaultIfEmpty_Never),
|
||||
("testMaterializeNever", ObservableSingleTest.testMaterializeNever),
|
||||
("testMaterializeEmpty", ObservableSingleTest.testMaterializeEmpty),
|
||||
("testMaterializeEmits", ObservableSingleTest.testMaterializeEmits),
|
||||
("testMaterializeThrow", ObservableSingleTest.testMaterializeThrow),
|
||||
("testDematerialize_Range1", ObservableSingleTest.testDematerialize_Range1),
|
||||
("testDematerialize_Range2", ObservableSingleTest.testDematerialize_Range2),
|
||||
("testDematerialize_Error", ObservableSingleTest.testDematerialize_Error),
|
||||
("testDematerialize_Error2", ObservableSingleTest.testDematerialize_Error2),
|
||||
("testMaterialize_Dematerialize_Never", ObservableSingleTest.testMaterialize_Dematerialize_Never),
|
||||
("testMaterialize_Dematerialize_Empty", ObservableSingleTest.testMaterialize_Dematerialize_Empty),
|
||||
("testMaterialize_Dematerialize_Return", ObservableSingleTest.testMaterialize_Dematerialize_Return),
|
||||
("testMaterialize_Dematerialize_Throw", ObservableSingleTest.testMaterialize_Dematerialize_Throw),
|
||||
("testGroupBy_TwoGroup", ObservableSingleTest.testGroupBy_TwoGroup),
|
||||
("testGroupBy_OuterComplete", ObservableSingleTest.testGroupBy_OuterComplete),
|
||||
("testGroupBy_OuterError", ObservableSingleTest.testGroupBy_OuterError),
|
||||
|
1
Sources/RxSwift/Dematerialize.swift
Symbolic link
1
Sources/RxSwift/Dematerialize.swift
Symbolic link
@ -0,0 +1 @@
|
||||
../../RxSwift/Observables/Implementations/Dematerialize.swift
|
1
Sources/RxSwift/Materialize.swift
Symbolic link
1
Sources/RxSwift/Materialize.swift
Symbolic link
@ -0,0 +1 @@
|
||||
../../RxSwift/Observables/Implementations/Materialize.swift
|
@ -1829,3 +1829,328 @@ extension ObservableSingleTest {
|
||||
#endif
|
||||
}
|
||||
|
||||
// materialize
|
||||
|
||||
extension ObservableSingleTest {
|
||||
func testMaterializeNever() {
|
||||
let scheduler = TestScheduler(initialClock: 0)
|
||||
let res = scheduler.start {
|
||||
return Observable<Int>.never().materialize()
|
||||
}
|
||||
XCTAssertEqual(res.events, [], materializedRecoredEventsComparison)
|
||||
}
|
||||
|
||||
func testMaterializeEmpty() {
|
||||
let scheduler = TestScheduler(initialClock: 0)
|
||||
let xs = scheduler.createHotObservable([
|
||||
completed(201, Int.self),
|
||||
completed(202, Int.self),
|
||||
])
|
||||
let res = scheduler.start {
|
||||
return xs.materialize()
|
||||
}
|
||||
let expectedEvents = [
|
||||
next(201, Event<Int>.completed),
|
||||
completed(201)
|
||||
]
|
||||
|
||||
XCTAssertEqual(xs.subscriptions, [Subscription(200, 201)])
|
||||
XCTAssertEqual(res.events, expectedEvents, materializedRecoredEventsComparison)
|
||||
}
|
||||
|
||||
func testMaterializeEmits() {
|
||||
let scheduler = TestScheduler(initialClock: 0)
|
||||
let xs = scheduler.createHotObservable([
|
||||
next(150, 1),
|
||||
next(210, 2),
|
||||
completed(250),
|
||||
completed(251),
|
||||
])
|
||||
let res = scheduler.start {
|
||||
return xs.materialize()
|
||||
}
|
||||
let expectedEvents = [
|
||||
next(210, Event.next(2)),
|
||||
next(250, Event.completed),
|
||||
completed(250)
|
||||
]
|
||||
|
||||
XCTAssertEqual(xs.subscriptions, [Subscription(200, 250)])
|
||||
XCTAssertEqual(res.events, expectedEvents, materializedRecoredEventsComparison)
|
||||
}
|
||||
|
||||
func testMaterializeThrow() {
|
||||
let scheduler = TestScheduler(initialClock: 0)
|
||||
let xs = scheduler.createHotObservable([
|
||||
next(150, 1),
|
||||
error(250, testError),
|
||||
error(251, testError),
|
||||
])
|
||||
let res = scheduler.start {
|
||||
return xs.materialize()
|
||||
}
|
||||
let expectedEvents = [
|
||||
next(250, Event<Int>.error(testError)),
|
||||
completed(250)
|
||||
]
|
||||
|
||||
XCTAssertEqual(xs.subscriptions, [Subscription(200, 250)])
|
||||
XCTAssertEqual(res.events, expectedEvents, materializedRecoredEventsComparison)
|
||||
}
|
||||
|
||||
#if TRACE_RESOURCES
|
||||
func testMaterializeReleasesResourcesOnComplete1() {
|
||||
_ = Observable<Int>.just(1).materialize().subscribe()
|
||||
}
|
||||
|
||||
func testMaterializeReleasesResourcesOnComplete2() {
|
||||
_ = Observable<Int>.empty().materialize().subscribe()
|
||||
}
|
||||
|
||||
func testMaterializeReleasesResourcesOnError() {
|
||||
_ = Observable<Int>.error(testError).materialize().subscribe()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//dematerialize
|
||||
|
||||
extension ObservableSingleTest {
|
||||
func testDematerialize_Range1() {
|
||||
let scheduler = TestScheduler(initialClock: 0)
|
||||
|
||||
let xs = scheduler.createHotObservable([
|
||||
next(150, Event.next(41)),
|
||||
next(210, Event.next(42)),
|
||||
next(220, Event.next(43)),
|
||||
completed(250),
|
||||
completed(251),
|
||||
])
|
||||
|
||||
let res = scheduler.start {
|
||||
xs.dematerialize()
|
||||
}
|
||||
|
||||
|
||||
XCTAssertEqual(res.events, [
|
||||
next(210, 42),
|
||||
next(220, 43),
|
||||
completed(250)
|
||||
])
|
||||
XCTAssertEqual(xs.subscriptions, [
|
||||
Subscription(200, 250)
|
||||
])
|
||||
|
||||
}
|
||||
|
||||
func testDematerialize_Range2() {
|
||||
let scheduler = TestScheduler(initialClock: 0)
|
||||
|
||||
let xs = scheduler.createHotObservable([
|
||||
next(150, Event.next(41)),
|
||||
next(210, Event.next(42)),
|
||||
next(220, Event.next(43)),
|
||||
next(230, Event.completed),
|
||||
next(231, Event.completed),
|
||||
])
|
||||
|
||||
let res = scheduler.start {
|
||||
xs.dematerialize()
|
||||
}
|
||||
|
||||
XCTAssertEqual(res.events, [
|
||||
next(210, 42),
|
||||
next(220, 43),
|
||||
completed(230)
|
||||
])
|
||||
|
||||
XCTAssertEqual(xs.subscriptions, [
|
||||
Subscription(200, 230)
|
||||
])
|
||||
|
||||
}
|
||||
|
||||
func testDematerialize_Error() {
|
||||
let scheduler = TestScheduler(initialClock: 0)
|
||||
|
||||
|
||||
let xs = scheduler.createHotObservable([
|
||||
next(150, Event.next(41)),
|
||||
next(210, Event.next(42)),
|
||||
next(220, Event.next(43)),
|
||||
error(230, TestError.dummyError),
|
||||
error(231, TestError.dummyError),
|
||||
])
|
||||
|
||||
let res = scheduler.start {
|
||||
xs.dematerialize()
|
||||
}
|
||||
|
||||
XCTAssertEqual(res.events, [
|
||||
next(210, 42),
|
||||
next(220, 43),
|
||||
error(230, TestError.dummyError)
|
||||
])
|
||||
|
||||
XCTAssertEqual(xs.subscriptions, [
|
||||
Subscription(200, 230)
|
||||
])
|
||||
}
|
||||
|
||||
func testDematerialize_Error2() {
|
||||
let scheduler = TestScheduler(initialClock: 0)
|
||||
|
||||
|
||||
let xs = scheduler.createHotObservable([
|
||||
next(150, Event.next(41)),
|
||||
next(210, Event.next(42)),
|
||||
next(220, Event.next(43)),
|
||||
next(230, Event.error(TestError.dummyError)),
|
||||
next(231, Event.error(TestError.dummyError))
|
||||
])
|
||||
|
||||
let res = scheduler.start {
|
||||
xs.dematerialize()
|
||||
}
|
||||
|
||||
XCTAssertEqual(res.events, [
|
||||
next(210, 42),
|
||||
next(220, 43),
|
||||
error(230, TestError.dummyError)
|
||||
])
|
||||
|
||||
XCTAssertEqual(xs.subscriptions, [
|
||||
Subscription(200, 230)
|
||||
])
|
||||
}
|
||||
|
||||
func testMaterialize_Dematerialize_Never() {
|
||||
let scheduler = TestScheduler(initialClock: 0)
|
||||
|
||||
let xs = Observable<Int>.never()
|
||||
|
||||
let res = scheduler.start {
|
||||
xs.materialize().dematerialize()
|
||||
}
|
||||
|
||||
XCTAssertEqual(res.events, [])
|
||||
}
|
||||
|
||||
func testMaterialize_Dematerialize_Empty() {
|
||||
let scheduler = TestScheduler(initialClock: 0)
|
||||
|
||||
let xs = scheduler.createHotObservable([
|
||||
next(150, 1),
|
||||
completed(250)
|
||||
])
|
||||
|
||||
let res = scheduler.start {
|
||||
xs.materialize().dematerialize()
|
||||
}
|
||||
|
||||
XCTAssertEqual(res.events, [
|
||||
completed(250)
|
||||
])
|
||||
|
||||
XCTAssertEqual(xs.subscriptions, [
|
||||
Subscription(200, 250)
|
||||
])
|
||||
}
|
||||
|
||||
func testMaterialize_Dematerialize_Return() {
|
||||
let scheduler = TestScheduler(initialClock: 0)
|
||||
|
||||
let xs = scheduler.createHotObservable([
|
||||
next(150, 1),
|
||||
next(210, 2),
|
||||
completed(250)
|
||||
])
|
||||
|
||||
let res = scheduler.start {
|
||||
xs.materialize().dematerialize()
|
||||
}
|
||||
|
||||
XCTAssertEqual(res.events, [
|
||||
next(210, 2),
|
||||
completed(250)
|
||||
])
|
||||
|
||||
XCTAssertEqual(xs.subscriptions, [
|
||||
Subscription(200, 250)
|
||||
])
|
||||
}
|
||||
|
||||
func testMaterialize_Dematerialize_Throw() {
|
||||
let scheduler = TestScheduler(initialClock: 0)
|
||||
let dummyError = TestError.dummyError
|
||||
|
||||
let xs = scheduler.createHotObservable([
|
||||
next(150, 1),
|
||||
error(250, dummyError)
|
||||
])
|
||||
|
||||
let res = scheduler.start {
|
||||
xs.materialize().dematerialize()
|
||||
}
|
||||
|
||||
XCTAssertEqual(res.events, [
|
||||
error(250, dummyError)
|
||||
])
|
||||
|
||||
XCTAssertEqual(xs.subscriptions, [
|
||||
Subscription(200, 250)
|
||||
])
|
||||
}
|
||||
|
||||
#if TRACE_RESOURCES
|
||||
func testDematerializeReleasesResourcesOnComplete1() {
|
||||
_ = Observable.just(Event.next(1)).dematerialize().subscribe()
|
||||
}
|
||||
|
||||
func testDematerializeReleasesResourcesOnComplete2() {
|
||||
_ = Observable<Event<Int>>.empty().dematerialize().subscribe()
|
||||
}
|
||||
|
||||
func testDematerializeReleasesResourcesOnError() {
|
||||
_ = Observable<Event<Int>>.error(testError).dematerialize().subscribe()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
fileprivate func materializedRecoredEventsComparison<T: Equatable>(lhs: [Recorded<Event<Event<T>>>], rhs: [Recorded<Event<Event<T>>>]) -> Bool {
|
||||
guard lhs.count == rhs.count else {
|
||||
return false
|
||||
}
|
||||
for (lhsElement, rhsElement) in zip(lhs, rhs) {
|
||||
guard lhsElement == rhsElement else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fileprivate func == <T: Equatable>(lhs: Recorded<Event<Event<T>>>, rhs: Recorded<Event<Event<T>>>) -> Bool {
|
||||
return lhs.time == rhs.time && lhs.value == rhs.value
|
||||
}
|
||||
|
||||
fileprivate func == <T: Equatable>(lhs: Event<Event<T>>, rhs: Event<Event<T>>) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case (.next(let lhsEvent), .next(let rhsEvent)):
|
||||
return lhsEvent == rhsEvent
|
||||
case (.completed, .completed): return true
|
||||
case (.error(let e1), .error(let e2)):
|
||||
#if os(Linux)
|
||||
return "\(e1)" == "\(e2)"
|
||||
#else
|
||||
let error1 = e1 as NSError
|
||||
let error2 = e2 as NSError
|
||||
|
||||
return error1.domain == error2.domain
|
||||
&& error1.code == error2.code
|
||||
&& "\(e1)" == "\(e2)"
|
||||
#endif
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user