|
2 | 2 | // Use of this source code is governed by a BSD-style license that can be
|
3 | 3 | // found in the LICENSE file.
|
4 | 4 |
|
5 |
| -#include <objc/objc.h> |
6 | 5 | #import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h"
|
7 | 6 | #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h"
|
8 |
| -#include "gtest/gtest.h" |
| 7 | + |
| 8 | +#include <objc/objc.h> |
9 | 9 |
|
10 | 10 | #include <functional>
|
11 | 11 | #include <thread>
|
|
14 | 14 | #include "flutter/lib/ui/window/platform_message.h"
|
15 | 15 | #include "flutter/shell/platform/common/accessibility_bridge.h"
|
16 | 16 | #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h"
|
| 17 | +#import "flutter/shell/platform/darwin/common/framework/Source/FlutterBinaryMessengerRelay.h" |
17 | 18 | #import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterAppDelegate.h"
|
18 | 19 | #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineTestUtils.h"
|
19 | 20 | #import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.h"
|
20 | 21 | #include "flutter/shell/platform/embedder/embedder.h"
|
21 | 22 | #include "flutter/shell/platform/embedder/embedder_engine.h"
|
22 | 23 | #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
|
23 | 24 | #include "flutter/testing/test_dart_native_resolver.h"
|
| 25 | +#include "gtest/gtest.h" |
24 | 26 |
|
25 | 27 | // CREATE_NATIVE_ENTRY and MOCK_ENGINE_PROC are leaky by design
|
26 | 28 | // NOLINTBEGIN(clang-analyzer-core.StackAddressEscape)
|
@@ -496,6 +498,38 @@ - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication* _Nonnu
|
496 | 498 | EXPECT_TRUE(called);
|
497 | 499 | }
|
498 | 500 |
|
| 501 | +// Verify that the engine is not retained indirectly via the binary messenger held by channels and |
| 502 | +// plugins. Previously, FlutterEngine.binaryMessenger returned the engine itself, and thus plugins |
| 503 | +// could cause a retain cycle, preventing the engine from being deallocated. |
| 504 | +// FlutterEngine.binaryMessenger now returns a FlutterBinaryMessengerRelay whose pointer back to |
| 505 | +// the engine is cleared when the engine is deallocated. |
| 506 | +// Issue: https://github.com/flutter/flutter/issues/116445 |
| 507 | +TEST_F(FlutterEngineTest, FlutterBinaryMessengerNullsParentOnEngineRelease) { |
| 508 | + FlutterBinaryMessengerRelay* relay = nil; |
| 509 | + @autoreleasepool { |
| 510 | + // Create a test engine. |
| 511 | + NSString* fixtures = @(flutter::testing::GetFixturesPath()); |
| 512 | + FlutterDartProject* project = [[FlutterDartProject alloc] |
| 513 | + initWithAssetsPath:fixtures |
| 514 | + ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]]; |
| 515 | + FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" |
| 516 | + project:project |
| 517 | + allowHeadlessExecution:true]; |
| 518 | + |
| 519 | + // Get the binary messenger for the engine. |
| 520 | + id<FlutterBinaryMessenger> binaryMessenger = engine.binaryMessenger; |
| 521 | + ASSERT_TRUE([binaryMessenger isKindOfClass:[FlutterBinaryMessengerRelay class]]); |
| 522 | + relay = (FlutterBinaryMessengerRelay*)binaryMessenger; |
| 523 | + |
| 524 | + // Verify the relay parent (the engine) is non-nil. |
| 525 | + EXPECT_NE(relay.parent, nil); |
| 526 | + } |
| 527 | + |
| 528 | + // Once the engine has been deallocated, verify the relay parent is nil, and thus the engine is |
| 529 | + // not retained by the holder of the relay. |
| 530 | + EXPECT_EQ(relay.parent, nil); |
| 531 | +} |
| 532 | + |
499 | 533 | // If a channel overrides a previous channel with the same name, cleaning
|
500 | 534 | // the previous channel should not affect the new channel.
|
501 | 535 | //
|
|
0 commit comments