Chromium Code Reviews| Index: base/ios/crb_protocol_observers_unittest.mm |
| diff --git a/base/ios/crb_protocol_observers_unittest.mm b/base/ios/crb_protocol_observers_unittest.mm |
| index d235c98b21f0919a2742cd40eb07e371486a5345..11946fa6ffe98e6e7b6d959f41944f94a3b4392d 100644 |
| --- a/base/ios/crb_protocol_observers_unittest.mm |
| +++ b/base/ios/crb_protocol_observers_unittest.mm |
| @@ -18,6 +18,8 @@ |
| @optional |
| - (void)optionalMethod; |
| +- (void)mutateByAddingObserver:(id<TestObserver>)observer; |
| +- (void)mutateByRemovingObserver:(id<TestObserver>)observer; |
| @end |
| @@ -31,6 +33,13 @@ |
| @property(nonatomic, readonly) BOOL optionalMethodInvoked; |
| @end |
| +@interface TestMutateObserver : TestCompleteObserver |
| + |
| +- (instancetype)initWithObserver:(CRBProtocolObservers*)observer |
| + NS_DESIGNATED_INITIALIZER; |
| + |
| +@end |
| + |
| namespace { |
| class CRBProtocolObserversTest : public PlatformTest { |
| @@ -50,11 +59,16 @@ class CRBProtocolObserversTest : public PlatformTest { |
| complete_observer_.reset([[TestCompleteObserver alloc] init]); |
| EXPECT_FALSE([complete_observer_ requiredMethodInvoked]); |
| EXPECT_FALSE([complete_observer_ optionalMethodInvoked]); |
| + |
| + mutate_observer_.reset( |
| + [[TestMutateObserver alloc] initWithObserver:observers_.get()]); |
| + EXPECT_FALSE([mutate_observer_ requiredMethodInvoked]); |
| } |
| base::scoped_nsobject<id> observers_; |
| base::scoped_nsobject<TestPartialObserver> partial_observer_; |
| base::scoped_nsobject<TestCompleteObserver> complete_observer_; |
| + base::scoped_nsobject<TestMutateObserver> mutate_observer_; |
| }; |
| // Verifies basic functionality of -[CRBProtocolObservers addObserver:] and |
| @@ -119,6 +133,34 @@ TEST_F(CRBProtocolObserversTest, WeakReference) { |
| EXPECT_FALSE(weak_observer.get()); |
| } |
| +// Verifies that - [CRBProtocolObservers addObserver:] and |
| +// - [CRBProtocolObservers removeObserver:] can be called while methods are |
| +// being forwarded. |
| +TEST_F(CRBProtocolObserversTest, MutateObservers) { |
| + // Indirectly add an observer while forwarding an observer method. |
| + [observers_ addObserver:mutate_observer_]; |
| + |
| + [observers_ mutateByAddingObserver:partial_observer_]; |
| + EXPECT_FALSE([partial_observer_ requiredMethodInvoked]); |
| + |
| + // Check that methods are correctly forwared to the indirectly added observer. |
| + [mutate_observer_ reset]; |
| + [observers_ requiredMethod]; |
| + EXPECT_TRUE([mutate_observer_ requiredMethodInvoked]); |
| + EXPECT_TRUE([partial_observer_ requiredMethodInvoked]); |
| + |
| + [mutate_observer_ reset]; |
| + [partial_observer_ reset]; |
| + |
| + // Indirectly remove an observer while forwarding an observer method. |
| + [observers_ mutateByRemovingObserver:partial_observer_]; |
| + |
| + // Check that method is not forwared to the indirectly removed observer. |
| + [observers_ requiredMethod]; |
| + EXPECT_TRUE([mutate_observer_ requiredMethodInvoked]); |
| + EXPECT_FALSE([partial_observer_ requiredMethodInvoked]); |
| +} |
| + |
|
droger
2015/06/04 10:04:23
We should also probably test the case where _invoc
jbbegue
2015/06/04 12:13:03
I added a test for the nested case.
I also added a
|
| } // namespace |
| @implementation TestPartialObserver { |
| @@ -157,3 +199,25 @@ TEST_F(CRBProtocolObserversTest, WeakReference) { |
| } |
| @end |
| + |
| +@implementation TestMutateObserver { |
| + __weak CRBProtocolObservers* _observers; |
| +} |
| + |
| +- (instancetype)initWithObserver:(CRBProtocolObservers*)observers { |
| + self = [super init]; |
| + if (self) { |
| + _observers = observers; |
| + } |
| + return self; |
| +} |
| + |
| +- (void)mutateByAddingObserver:(id<TestObserver>)observer { |
| + [_observers addObserver:observer]; |
| +} |
| + |
| +- (void)mutateByRemovingObserver:(id<TestObserver>)observer { |
| + [_observers removeObserver:observer]; |
| +} |
| + |
| +@end |