| // | |
| // RACMulticastConnectionSpec.m | |
| // ReactiveCocoa | |
| // | |
| // Created by Josh Abernathy on 10/8/12. | |
| // Copyright (c) 2012 GitHub, Inc. All rights reserved. | |
| // | |
| #import "RACMulticastConnection.h" | |
| #import "RACDisposable.h" | |
| #import "RACSignal+Operations.h" | |
| #import "RACSubscriber.h" | |
| #import "RACReplaySubject.h" | |
| #import "RACScheduler.h" | |
| #import <libkern/OSAtomic.h> | |
| SpecBegin(RACMulticastConnection) | |
| __block NSUInteger subscriptionCount = 0; | |
| __block RACMulticastConnection *connection; | |
| __block BOOL disposed = NO; | |
| beforeEach(^{ | |
| subscriptionCount = 0; | |
| disposed = NO; | |
| connection = [[RACSignal createSignal:^(id<RACSubscriber> subscriber) { | |
| subscriptionCount++; | |
| return [RACDisposable disposableWithBlock:^{ | |
| disposed = YES; | |
| }]; | |
| }] publish]; | |
| expect(subscriptionCount).to.equal(0); | |
| }); | |
| describe(@"-connect", ^{ | |
| it(@"should subscribe to the underlying signal", ^{ | |
| [connection connect]; | |
| expect(subscriptionCount).to.equal(1); | |
| }); | |
| it(@"should return the same disposable for each invocation", ^{ | |
| RACDisposable *d1 = [connection connect]; | |
| RACDisposable *d2 = [connection connect]; | |
| expect(d1).to.equal(d2); | |
| expect(subscriptionCount).to.equal(1); | |
| }); | |
| it(@"shouldn't reconnect after disposal", ^{ | |
| RACDisposable *disposable1 = [connection connect]; | |
| expect(subscriptionCount).to.equal(1); | |
| [disposable1 dispose]; | |
| RACDisposable *disposable2 = [connection connect]; | |
| expect(subscriptionCount).to.equal(1); | |
| expect(disposable1).to.equal(disposable2); | |
| }); | |
| it(@"shouldn't race when connecting", ^{ | |
| dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); | |
| RACMulticastConnection *connection = [[RACSignal | |
| defer:^ id { | |
| dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); | |
| return nil; | |
| }] | |
| publish]; | |
| __block RACDisposable *disposable; | |
| [RACScheduler.scheduler schedule:^{ | |
| disposable = [connection connect]; | |
| dispatch_semaphore_signal(semaphore); | |
| }]; | |
| expect([connection connect]).notTo.beNil(); | |
| dispatch_semaphore_signal(semaphore); | |
| expect(disposable).willNot.beNil(); | |
| dispatch_release(semaphore); | |
| }); | |
| }); | |
| describe(@"-autoconnect", ^{ | |
| __block RACSignal *autoconnectedSignal; | |
| beforeEach(^{ | |
| autoconnectedSignal = [connection autoconnect]; | |
| }); | |
| it(@"should subscribe to the multicasted signal on the first subscription", ^{ | |
| expect(subscriptionCount).to.equal(0); | |
| [autoconnectedSignal subscribeNext:^(id x) {}]; | |
| expect(subscriptionCount).to.equal(1); | |
| [autoconnectedSignal subscribeNext:^(id x) {}]; | |
| expect(subscriptionCount).to.equal(1); | |
| }); | |
| it(@"should dispose of the multicasted subscription when the signal has no subscribers", ^{ | |
| RACDisposable *disposable = [autoconnectedSignal subscribeNext:^(id x) {}]; | |
| expect(disposed).to.beFalsy(); | |
| [disposable dispose]; | |
| expect(disposed).to.beTruthy(); | |
| }); | |
| it(@"shouldn't reconnect after disposal", ^{ | |
| RACDisposable *disposable = [autoconnectedSignal subscribeNext:^(id x) {}]; | |
| expect(subscriptionCount).to.equal(1); | |
| [disposable dispose]; | |
| disposable = [autoconnectedSignal subscribeNext:^(id x) {}]; | |
| expect(subscriptionCount).to.equal(1); | |
| [disposable dispose]; | |
| }); | |
| it(@"should replay values after disposal when multicasted to a replay subject", ^{ | |
| RACSubject *subject = [RACSubject subject]; | |
| RACSignal *signal = [[subject multicast:[RACReplaySubject subject]] autoconnect]; | |
| NSMutableArray *results1 = [NSMutableArray array]; | |
| RACDisposable *disposable = [signal subscribeNext:^(id x) { | |
| [results1 addObject:x]; | |
| }]; | |
| [subject sendNext:@1]; | |
| [subject sendNext:@2]; | |
| expect(results1).to.equal((@[ @1, @2 ])); | |
| [disposable dispose]; | |
| NSMutableArray *results2 = [NSMutableArray array]; | |
| [signal subscribeNext:^(id x) { | |
| [results2 addObject:x]; | |
| }]; | |
| expect(results2).will.equal((@[ @1, @2 ])); | |
| }); | |
| }); | |
| SpecEnd |