Skip to content
This repository has been archived by the owner on Dec 5, 2019. It is now read-only.

RVM Crash with take: on didBecomeActiveSignal when using OCMock #29

Closed
ashfurrow opened this issue Jul 30, 2014 · 3 comments
Closed

RVM Crash with take: on didBecomeActiveSignal when using OCMock #29

ashfurrow opened this issue Jul 30, 2014 · 3 comments

Comments

@ashfurrow
Copy link
Member

This isn't an RVM issue per se, but I wanted to document it in case anyone else had this issue and was google for an answer. Also, I'm looking for workaround (other than "don't use mocks", of course).

I have a very simple view model:

@implementation ASHViewModel

-(id)init
{
    self = [super init];
    if (self == nil) { return nil; }

    [[self.didBecomeActiveSignal take:1] subscribeNext:^(id x) {
        NSLog(@"Active");
    }];

    return self;
}

@end

Nothing special. Now, when I unit test it, I create a mock.

SpecBegin(ASHViewModel)

describe(@"in a describe block", ^{
    it(@"shouldn't crash", ^{
        ASHViewModel *viewModel = [[ASHViewModel alloc] init];
        id mockViewModel = [OCMockObject partialMockForObject:viewModel];

        [mockViewModel setActive:YES];
    });
});

SpecEnd

The problem is, due to the mocking, something funky is going on under the hood with take: being disposed of. It results in the following crash:

2014-07-30 13:26:22.644 Bug[15566:60b] Active
<unknown>:0: error: -[ASHViewModelSpec in_a_describe_block_shouldn_t_crash] : Cannot remove an observer <RACKVOTrampoline 0xd73b7f0> for the key path "active" from <ASHViewModel 0x913ee70> because it is not registered as an observer.
(
    0   CoreFoundation                      0x019081e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x016878e5 objc_exception_throw + 44
    2   CoreFoundation                      0x01907fbb +[NSException raise:format:] + 139
    3   Foundation                          0x012d546d -[NSObject(NSKeyValueObserverRegistration) _removeObserver:forProperty:] + 538
    4   Foundation                          0x012d51f4 -[NSObject(NSKeyValueObserverRegistration) removeObserver:forKeyPath:] + 105
    5   Foundation                          0x012d5118 -[NSObject(NSKeyValueObserverRegistration) removeObserver:forKeyPath:context:] + 172
    6   Bug                                 0x0002b7a0 -[RACKVOTrampoline dispose] + 528
    7   Bug                                 0x0001fe43 -[RACCompoundDisposable dispose] + 355
    8   Bug                                 0x0000a994 __69-[NSObject(RACKVOWrapper) rac_observeKeyPath:options:observer:block:]_block_invoke96 + 52
    9   Bug                                 0x00020c79 -[RACDisposable dispose] + 201
    10  Bug                                 0x0001ffc1 disposeEach + 81
    11  CoreFoundation                      0x018a9c69 CFArrayApplyFunction + 57
    12  Bug                                 0x0001fed3 -[RACCompoundDisposable dispose] + 499
    13  Bug                                 0x0001fe43 -[RACCompoundDisposable dispose] + 355
    14  Bug                                 0x0001ffc1 disposeEach + 81
    15  CoreFoundation                      0x018a9c69 CFArrayApplyFunction + 57
    16  Bug                                 0x0001fed3 -[RACCompoundDisposable dispose] + 499
    17  Bug                                 0x000388e4 -[RACSerialDisposable dispose] + 196
    18  Bug                                 0x0001fe43 -[RACCompoundDisposable dispose] + 355
    19  Bug                                 0x0001ffc1 disposeEach + 81
    20  CoreFoundation                      0x018a9c69 CFArrayApplyFunction + 57
    21  Bug                                 0x0001fed3 -[RACCompoundDisposable dispose] + 499
    22  Bug                                 0x000388e4 -[RACSerialDisposable dispose] + 196
    23  Bug                                 0x0001fe43 -[RACCompoundDisposable dispose] + 355
    24  Bug                                 0x0001ffc1 disposeEach + 81
    25  CoreFoundation                      0x018a9c69 CFArrayApplyFunction + 57
    26  Bug                                 0x0001fed3 -[RACCompoundDisposable dispose] + 499
    27  Bug                                 0x000388e4 -[RACSerialDisposable dispose] + 196
    28  Bug                                 0x0001fe43 -[RACCompoundDisposable dispose] + 355
    29  Bug                                 0x0001ffc1 disposeEach + 81
    30  CoreFoundation                      0x018a9c69 CFArrayApplyFunction + 57
    31  Bug                                 0x0001fed3 -[RACCompoundDisposable dispose] + 499
    32  Bug                                 0x000388e4 -[RACSerialDisposable dispose] + 196
    33  Bug                                 0x0005f1e7 __29-[RACSignal(RACStream) bind:]_block_invoke125 + 247
    34  Bug                                 0x0006f69b -[RACSubscriber sendNext:] + 251
    35  Bug                                 0x0002cf57 -[RACPassthroughSubscriber sendNext:] + 487
    36  Bug                                 0x0005ec0a __29-[RACSignal(RACStream) bind:]_block_invoke_298 + 106
    37  Bug                                 0x0006f69b -[RACSubscriber sendNext:] + 251
    38  Bug                                 0x00030b91 __29-[RACReturnSignal subscribe:]_block_invoke + 97
    39  Bug                                 0x00070898 -[RACSubscriptionScheduler schedule:] + 488
    40  Bug                                 0x00030a9f -[RACReturnSignal subscribe:] + 479
    41  Bug                                 0x00062e6b -[RACSignal(Subscription) subscribeNext:error:completed:] + 1003
    42  Bug                                 0x0005ea11 __29-[RACSignal(RACStream) bind:]_block_invoke88 + 833
    43  Bug                                 0x0005f1b0 __29-[RACSignal(RACStream) bind:]_block_invoke125 + 192
    44  Bug                                 0x0006f69b -[RACSubscriber sendNext:] + 251
    45  Bug                                 0x0002cf57 -[RACPassthroughSubscriber sendNext:] + 487
    46  Bug                                 0x0005ec0a __29-[RACSignal(RACStream) bind:]_block_invoke_298 + 106
    47  Bug                                 0x0006f69b -[RACSubscriber sendNext:] + 251
    48  Bug                                 0x00030b91 __29-[RACReturnSignal subscribe:]_block_invoke + 97
    49  Bug                                 0x00070898 -[RACSubscriptionScheduler schedule:] + 488
    50  Bug                                 0x00030a9f -[RACReturnSignal subscribe:] + 479
    51  Bug                                 0x00062e6b -[RACSignal(Subscription) subscribeNext:error:completed:] + 1003
    52  Bug                                 0x0005ea11 __29-[RACSignal(RACStream) bind:]_block_invoke88 + 833
    53  Bug                                 0x0005f1b0 __29-[RACSignal(RACStream) bind:]_block_invoke125 + 192
    54  Bug                                 0x0006f69b -[RACSubscriber sendNext:] + 251
    55  Bug                                 0x0002cf57 -[RACPassthroughSubscriber sendNext:] + 487
    56  Bug                                 0x0005ec0a __29-[RACSignal(RACStream) bind:]_block_invoke_298 + 106
    57  Bug                                 0x0006f69b -[RACSubscriber sendNext:] + 251
    58  Bug                                 0x00030b91 __29-[RACReturnSignal subscribe:]_block_invoke + 97
    59  Bug                                 0x00070898 -[RACSubscriptionScheduler schedule:] + 488
    60  Bug                                 0x00030a9f -[RACReturnSignal subscribe:] + 479
    61  Bug                                 0x00062e6b -[RACSignal(Subscription) subscribeNext:error:completed:] + 1003
    62  Bug                                 0x0005ea11 __29-[RACSignal(RACStream) bind:]_block_invoke88 + 833
    63  Bug                                 0x0005f1b0 __29-[RACSignal(RACStream) bind:]_block_invoke125 + 192
    64  Bug                                 0x0006f69b -[RACSubscriber sendNext:] + 251
    65  Bug                                 0x0002cf57 -[RACPassthroughSubscriber sendNext:] + 487
    66  Bug                                 0x0004a74a __35-[RACSignal(Operations) takeUntil:]_block_invoke576 + 106
    67  Bug                                 0x0006f69b -[RACSubscriber sendNext:] + 251
    68  Bug                                 0x0002cf57 -[RACPassthroughSubscriber sendNext:] + 487
    69  Bug                                 0x0000d99c __84-[NSObject(RACPropertySubscribing) rac_valuesAndChangesForKeyPath:options:observer:]_block_invoke48 + 476
    70  Bug                                 0x0000a591 __69-[NSObject(RACKVOWrapper) rac_observeKeyPath:options:observer:block:]_block_invoke77 + 769
    71  Bug                                 0x0002ba55 -[RACKVOTrampoline observeValueForKeyPath:ofObject:change:context:] + 581
    72  Foundation                          0x012d5d77 NSKeyValueNotifyObserver + 362
    73  Foundation                          0x012d7686 NSKeyValueDidChange + 458
    74  Foundation                          0x01293dcd -[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:] + 120
    75  Bug                                 0x0007c83c -[RVMViewModel setActive:] + 332
    76  CoreFoundation                      0x018fc91d __invoking___ + 29
    77  CoreFoundation                      0x018fc82a -[NSInvocation invoke] + 362
    78  CoreFoundation                      0x018fc9aa -[NSInvocation invokeWithTarget:] + 74
    79  BugTests                            0x093aa624 -[OCPartialMockObject handleUnRecordedInvocation:] + 68
    80  BugTests                            0x093a782c -[OCMockObject forwardInvocation:] + 108
    81  CoreFoundation                      0x018f82da ___forwarding___ + 458
    82  CoreFoundation                      0x018f80ee _CF_forwarding_prep_0 + 14
    83  BugTests                            0x093821ee __34-[ASHViewModelSpec spt_defineSpec]_block_invoke_2 + 174
    84  BugTests                            0x093ad76c runExampleBlock + 1500
    85  BugTests                            0x093aedb2 __48-[SPTExampleGroup compileExamplesWithNameStack:]_block_invoke + 258
    86  BugTests                            0x093b413c -[SPTXCTestCase spt_runExampleAtIndex:] + 556
    87  CoreFoundation                      0x018fc91d __invoking___ + 29
    88  CoreFoundation                      0x018fc82a -[NSInvocation invoke] + 362
    89  XCTest                              0x20103c6c -[XCTestCase invokeTest] + 221
    90  XCTest                              0x20103d7b -[XCTestCase performTest:] + 111
    91  BugTests                            0x093b4b28 -[SPTXCTestCase performTest:] + 152
    92  XCTest                              0x20104c48 -[XCTest run] + 82
    93  XCTest                              0x201033e8 -[XCTestSuite performTest:] + 139
    94  XCTest                              0x20104c48 -[XCTest run] + 82
    95  XCTest                              0x201033e8 -[XCTestSuite performTest:] + 139
    96  XCTest                              0x20104c48 -[XCTest run] + 82
    97  XCTest                              0x201033e8 -[XCTestSuite performTest:] + 139
    98  XCTest                              0x20104c48 -[XCTest run] + 82
    99  XCTest                              0x201066ba +[XCTestProbe runTests:] + 183
    100 Foundation                          0x012bd5ec __NSFireDelayedPerform + 372
    101 CoreFoundation                      0x018c6ac6 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22
    102 CoreFoundation                      0x018c64ad __CFRunLoopDoTimer + 1181
    103 CoreFoundation                      0x018ae538 __CFRunLoopRun + 1816
    104 CoreFoundation                      0x018ad9d3 CFRunLoopRunSpecific + 467
    105 CoreFoundation                      0x018ad7eb CFRunLoopRunInMode + 123
    106 GraphicsServices                    0x038fc5ee GSEventRunModal + 192
    107 GraphicsServices                    0x038fc42b GSEventRun + 104
    108 UIKit                               0x00347f9b UIApplicationMain + 1225
    109 Bug                                 0x000023cd main + 141
    110 libdyld.dylib                       0x01f4f701 start + 1
)

Like I said, not strictly a RVM issue, but open to suggestions. Feel free to close if it's too off-topic.

@ashfurrow ashfurrow changed the title RVM Crash with take: on didBecomeActiveSignal RVM Crash with take: on didBecomeActiveSignal when using OCMock Jul 30, 2014
@jspahrsummers
Copy link
Member

KVO involves isa-swizzling, and so does mocking. Worse, KVO observers are associated per-class, and that association can break if the class of an instance changes.

RAC handles this. It sounds like your mocking framework does not.

@ashfurrow
Copy link
Member Author

Could be – like I said, I just want this to be documented somewhere.

@jspahrsummers
Copy link
Member

I mean this is a more general issue with KVO + mocking. I'd either follow up with the authors of the mocking framework, or just don't use mocks. :trollface:

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants