-
Notifications
You must be signed in to change notification settings - Fork 6k
Reland: Started waiting for the notifications locally before asserting side-effects #25257
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,22 @@ | |
| class PointerDataPacket {}; | ||
| } | ||
|
|
||
| /// Sometimes we have to use a custom mock to avoid retain cycles in ocmock. | ||
| @interface FlutterEnginePartialMock : FlutterEngine | ||
| @property(nonatomic, strong) FlutterBasicMessageChannel* lifecycleChannel; | ||
| @property(nonatomic, weak) FlutterViewController* viewController; | ||
| @property(nonatomic, assign) BOOL didCallNotifyLowMemory; | ||
| @end | ||
|
|
||
| @implementation FlutterEnginePartialMock | ||
| @synthesize viewController; | ||
| @synthesize lifecycleChannel; | ||
|
|
||
| - (void)notifyLowMemory { | ||
| _didCallNotifyLowMemory = YES; | ||
| } | ||
| @end | ||
|
|
||
| @interface FlutterEngine () | ||
| - (BOOL)createShell:(NSString*)entrypoint | ||
| libraryURI:(NSString*)libraryURI | ||
|
|
@@ -87,30 +103,37 @@ - (void)tearDown { | |
|
|
||
| - (void)testViewDidDisappearDoesntPauseEngineWhenNotTheViewController { | ||
| id lifecycleChannel = OCMClassMock([FlutterBasicMessageChannel class]); | ||
| OCMStub([self.mockEngine lifecycleChannel]).andReturn(lifecycleChannel); | ||
| FlutterEnginePartialMock* mockEngine = [[FlutterEnginePartialMock alloc] init]; | ||
| mockEngine.lifecycleChannel = lifecycleChannel; | ||
| FlutterViewController* viewControllerA = | ||
| [[FlutterViewController alloc] initWithEngine:self.mockEngine nibName:nil bundle:nil]; | ||
| FlutterViewController* viewControllerB = | ||
| [[FlutterViewController alloc] initWithEngine:self.mockEngine nibName:nil bundle:nil]; | ||
| id viewControllerMock = OCMPartialMock(viewControllerA); | ||
| OCMStub([viewControllerMock surfaceUpdated:NO]); | ||
| OCMStub([self.mockEngine viewController]).andReturn(viewControllerB); | ||
| mockEngine.viewController = viewControllerB; | ||
| [viewControllerA viewDidDisappear:NO]; | ||
| OCMReject([lifecycleChannel sendMessage:@"AppLifecycleState.paused"]); | ||
| OCMReject([viewControllerMock surfaceUpdated:[OCMArg any]]); | ||
| } | ||
|
|
||
| - (void)testViewDidDisappearDoesPauseEngineWhenIsTheViewController { | ||
| id lifecycleChannel = OCMClassMock([FlutterBasicMessageChannel class]); | ||
| OCMStub([self.mockEngine lifecycleChannel]).andReturn(lifecycleChannel); | ||
| FlutterViewController* viewController = | ||
| [[FlutterViewController alloc] initWithEngine:self.mockEngine nibName:nil bundle:nil]; | ||
| id viewControllerMock = OCMPartialMock(viewController); | ||
| OCMStub([viewControllerMock surfaceUpdated:NO]); | ||
| OCMStub([self.mockEngine viewController]).andReturn(viewController); | ||
| [viewController viewDidDisappear:NO]; | ||
| OCMVerify([lifecycleChannel sendMessage:@"AppLifecycleState.paused"]); | ||
| OCMVerify([viewControllerMock surfaceUpdated:NO]); | ||
| FlutterEnginePartialMock* mockEngine = [[FlutterEnginePartialMock alloc] init]; | ||
| mockEngine.lifecycleChannel = lifecycleChannel; | ||
| __weak FlutterViewController* weakViewController; | ||
| @autoreleasepool { | ||
| FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:mockEngine | ||
| nibName:nil | ||
| bundle:nil]; | ||
| weakViewController = viewController; | ||
| id viewControllerMock = OCMPartialMock(viewController); | ||
| OCMStub([viewControllerMock surfaceUpdated:NO]); | ||
| [viewController viewDidDisappear:NO]; | ||
| OCMVerify([lifecycleChannel sendMessage:@"AppLifecycleState.paused"]); | ||
| OCMVerify([viewControllerMock surfaceUpdated:NO]); | ||
| } | ||
| XCTAssertNil(weakViewController); | ||
| } | ||
|
|
||
| - (void)testBinaryMessenger { | ||
|
|
@@ -528,15 +551,16 @@ - (void)testHideOverlay { | |
| } | ||
|
|
||
| - (void)testNotifyLowMemory { | ||
| FlutterViewController* viewController = | ||
| [[FlutterViewController alloc] initWithEngine:self.mockEngine nibName:nil bundle:nil]; | ||
| OCMStub([self.mockEngine viewController]).andReturn(viewController); | ||
| FlutterEnginePartialMock* mockEngine = [[FlutterEnginePartialMock alloc] init]; | ||
| FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:mockEngine | ||
| nibName:nil | ||
| bundle:nil]; | ||
| id viewControllerMock = OCMPartialMock(viewController); | ||
| OCMStub([viewControllerMock surfaceUpdated:NO]); | ||
|
|
||
| [viewController beginAppearanceTransition:NO animated:NO]; | ||
| [viewController endAppearanceTransition]; | ||
| OCMVerify([self.mockEngine notifyLowMemory]); | ||
| XCTAssertTrue(mockEngine.didCallNotifyLowMemory); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you can actually allocate a [self keyValueObservingExpectation:mockEngine keyPath:@"notifyLowMemory" handler:nil]
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mean could we use a real FlutterEngine? There shouldn't be a keyPath
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (the subclass is also necessary for setting the lifecycle channel, not just needed for the notifyLowMemory stuff) |
||
| [viewControllerMock stopMocking]; | ||
| } | ||
|
|
||
| - (void)testValidKeyUpEvent API_AVAILABLE(ios(13.4)) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -970,5 +970,6 @@ - (void)testAccessibilityMessageAfterDeletion { | |
| }); | ||
| latch.Wait(); | ||
| OCMVerify([messenger cleanupConnection:connection]); | ||
| [engine stopMocking]; | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This might be superfluous now. I don't think it hurts anything. Once I got everything working I didn't try to cull any of the previous work I did. |
||
| } | ||
| @end | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jmagman This is what I had to do in order to get rid of the cycles. I would hope that upgrading ocmock would also fix this, but it was hard to upgrade ocmock because it changed its dependencies, it's complicated to get GN working with it.