| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- //
- // RACSerialDisposableSpec.m
- // ReactiveCocoa
- //
- // Created by Justin Spahr-Summers on 2013-07-22.
- // Copyright (c) 2013 GitHub, Inc. All rights reserved.
- //
- #import <Quick/Quick.h>
- #import <Nimble/Nimble.h>
- #import "RACSerialDisposable.h"
- QuickSpecBegin(RACSerialDisposableSpec)
- qck_it(@"should initialize with -init", ^{
- RACSerialDisposable *serial = [[RACSerialDisposable alloc] init];
- expect(serial).notTo(beNil());
- expect(serial.disposable).to(beNil());
- });
- qck_it(@"should initialize an inner disposable with -initWithBlock:", ^{
- __block BOOL disposed = NO;
- RACSerialDisposable *serial = [RACSerialDisposable disposableWithBlock:^{
- disposed = YES;
- }];
- expect(serial).notTo(beNil());
- expect(serial.disposable).notTo(beNil());
- [serial.disposable dispose];
- expect(@(serial.disposed)).to(beFalsy());
- expect(@(disposed)).to(beTruthy());
- });
- qck_it(@"should initialize with a disposable", ^{
- RACDisposable *inner = [[RACDisposable alloc] init];
- RACSerialDisposable *serial = [RACSerialDisposable serialDisposableWithDisposable:inner];
- expect(serial).notTo(beNil());
- expect(serial.disposable).to(equal(inner));
- });
- qck_it(@"should dispose of the inner disposable", ^{
- __block BOOL disposed = NO;
- RACDisposable *inner = [RACDisposable disposableWithBlock:^{
- disposed = YES;
- }];
- RACSerialDisposable *serial = [RACSerialDisposable serialDisposableWithDisposable:inner];
- expect(@(serial.disposed)).to(beFalsy());
- expect(@(disposed)).to(beFalsy());
- [serial dispose];
- expect(@(serial.disposed)).to(beTruthy());
- expect(serial.disposable).to(beNil());
- expect(@(disposed)).to(beTruthy());
- });
- qck_it(@"should dispose of a new inner disposable if it's already been disposed", ^{
- __block BOOL disposed = NO;
- RACDisposable *inner = [RACDisposable disposableWithBlock:^{
- disposed = YES;
- }];
- RACSerialDisposable *serial = [[RACSerialDisposable alloc] init];
- expect(@(serial.disposed)).to(beFalsy());
- [serial dispose];
- expect(@(serial.disposed)).to(beTruthy());
- expect(@(disposed)).to(beFalsy());
- serial.disposable = inner;
- expect(@(disposed)).to(beTruthy());
- expect(serial.disposable).to(beNil());
- });
- qck_it(@"should allow the inner disposable to be set to nil", ^{
- __block BOOL disposed = NO;
- RACDisposable *inner = [RACDisposable disposableWithBlock:^{
- disposed = YES;
- }];
- RACSerialDisposable *serial = [RACSerialDisposable serialDisposableWithDisposable:inner];
- expect(@(disposed)).to(beFalsy());
- serial.disposable = nil;
- expect(serial.disposable).to(beNil());
- serial.disposable = inner;
- expect(serial.disposable).to(equal(inner));
- [serial dispose];
- expect(@(disposed)).to(beTruthy());
- expect(serial.disposable).to(beNil());
- });
- qck_it(@"should swap inner disposables", ^{
- __block BOOL firstDisposed = NO;
- RACDisposable *first = [RACDisposable disposableWithBlock:^{
- firstDisposed = YES;
- }];
- __block BOOL secondDisposed = NO;
- RACDisposable *second = [RACDisposable disposableWithBlock:^{
- secondDisposed = YES;
- }];
- RACSerialDisposable *serial = [RACSerialDisposable serialDisposableWithDisposable:first];
- expect([serial swapInDisposable:second]).to(equal(first));
- expect(@(serial.disposed)).to(beFalsy());
- expect(@(firstDisposed)).to(beFalsy());
- expect(@(secondDisposed)).to(beFalsy());
- [serial dispose];
- expect(@(serial.disposed)).to(beTruthy());
- expect(serial.disposable).to(beNil());
- expect(@(firstDisposed)).to(beFalsy());
- expect(@(secondDisposed)).to(beTruthy());
- });
- qck_it(@"should release the inner disposable upon deallocation", ^{
- __weak RACDisposable *weakInnerDisposable;
- __weak RACSerialDisposable *weakSerialDisposable;
- @autoreleasepool {
- RACDisposable *innerDisposable __attribute__((objc_precise_lifetime)) = [[RACDisposable alloc] init];
- weakInnerDisposable = innerDisposable;
- RACSerialDisposable *serialDisposable __attribute__((objc_precise_lifetime)) = [[RACSerialDisposable alloc] init];
- serialDisposable.disposable = innerDisposable;
- weakSerialDisposable = serialDisposable;
- }
- expect(weakSerialDisposable).to(beNil());
- expect(weakInnerDisposable).to(beNil());
- });
- qck_it(@"should not crash when racing between swapInDisposable and disposable", ^{
- __block BOOL stop = NO;
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (long long)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- stop = YES;
- });
- RACSerialDisposable *serialDisposable = [[RACSerialDisposable alloc] init];
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- while (!stop) {
- [serialDisposable swapInDisposable:[RACDisposable disposableWithBlock:^{}]];
- }
- });
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- while (!stop) {
- (void)[serialDisposable disposable];
- }
- });
- expect(@(stop)).toEventually(beTruthy());
- });
- QuickSpecEnd
|