Flutter Engine
 
Loading...
Searching...
No Matches
scene_builder_unittests.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <memory>
8
16
17// CREATE_NATIVE_ENTRY is leaky by design
18// NOLINTBEGIN(clang-analyzer-core.StackAddressEscape)
19
20namespace flutter {
21namespace testing {
22
23TEST_F(ShellTest, SceneBuilderBuildAndSceneDisposeReleasesLayerStack) {
24 auto message_latch = std::make_shared<fml::AutoResetWaitableEvent>();
25
26 // prevent ClearDartWrapper() from deleting the scene builder.
27 SceneBuilder* retained_scene_builder;
28 Scene* retained_scene;
29
30 auto validate_builder_has_layers =
31 [&retained_scene_builder](Dart_NativeArguments args) {
32 auto handle = Dart_GetNativeArgument(args, 0);
33 intptr_t peer = 0;
34 Dart_Handle result = Dart_GetNativeInstanceField(
36 ASSERT_FALSE(Dart_IsError(result));
37 retained_scene_builder = reinterpret_cast<SceneBuilder*>(peer);
38 retained_scene_builder->AddRef();
39 ASSERT_TRUE(retained_scene_builder);
40 ASSERT_EQ(retained_scene_builder->layer_stack().size(), 2ul);
41 };
42
43 auto validate_builder_has_no_layers =
44 [&retained_scene_builder](Dart_NativeArguments args) {
45 ASSERT_EQ(retained_scene_builder->layer_stack().size(), 0ul);
46 retained_scene_builder->Release();
47 retained_scene_builder = nullptr;
48 };
49
50 auto capture_scene = [&retained_scene](Dart_NativeArguments args) {
51 auto handle = Dart_GetNativeArgument(args, 0);
52 intptr_t peer = 0;
53 Dart_Handle result = Dart_GetNativeInstanceField(
55 ASSERT_FALSE(Dart_IsError(result));
56 retained_scene = reinterpret_cast<Scene*>(peer);
57 retained_scene->AddRef();
58 ASSERT_TRUE(retained_scene);
59 };
60
61 auto validate_scene_has_no_layers =
62 [message_latch, &retained_scene](Dart_NativeArguments args) {
63 EXPECT_FALSE(retained_scene->takeLayerTree(100, 100));
64 retained_scene->Release();
65 retained_scene = nullptr;
66 message_latch->Signal();
67 };
68
69 Settings settings = CreateSettingsForFixture();
70 TaskRunners task_runners("test", // label
71 GetCurrentTaskRunner(), // platform
72 CreateNewThread(), // raster
73 CreateNewThread(), // ui
74 CreateNewThread() // io
75 );
76
77 AddNativeCallback("ValidateBuilderHasLayers",
78 CREATE_NATIVE_ENTRY(validate_builder_has_layers));
79 AddNativeCallback("ValidateBuilderHasNoLayers",
80 CREATE_NATIVE_ENTRY(validate_builder_has_no_layers));
81
82 AddNativeCallback("CaptureScene", CREATE_NATIVE_ENTRY(capture_scene));
83 AddNativeCallback("ValidateSceneHasNoLayers",
84 CREATE_NATIVE_ENTRY(validate_scene_has_no_layers));
85
86 std::unique_ptr<Shell> shell = CreateShell(settings, task_runners);
87
88 ASSERT_TRUE(shell->IsSetup());
89 auto configuration = RunConfiguration::InferFromSettings(settings);
90 configuration.SetEntrypoint("validateSceneBuilderAndScene");
91
92 shell->RunEngine(std::move(configuration), [](auto result) {
93 ASSERT_EQ(result, Engine::RunStatus::Success);
94 });
95
96 message_latch->Wait();
97 DestroyShell(std::move(shell), task_runners);
98}
99
100TEST_F(ShellTest, EngineLayerDisposeReleasesReference) {
101 auto message_latch = std::make_shared<fml::AutoResetWaitableEvent>();
102
103 std::shared_ptr<ContainerLayer> root_layer;
104
105 auto capture_root_layer = [&root_layer](Dart_NativeArguments args) {
106 auto handle = Dart_GetNativeArgument(args, 0);
107 intptr_t peer = 0;
108 Dart_Handle result = Dart_GetNativeInstanceField(
109 handle, tonic::DartWrappable::kPeerIndex, &peer);
110 ASSERT_FALSE(Dart_IsError(result));
111 SceneBuilder* scene_builder = reinterpret_cast<SceneBuilder*>(peer);
112 ASSERT_TRUE(scene_builder);
113 root_layer = scene_builder->layer_stack()[0];
114 ASSERT_TRUE(root_layer);
115 };
116
117 auto validate_layer_tree_counts = [&root_layer](Dart_NativeArguments args) {
118 // One for the EngineLayer, one for our pointer in the test.
119 EXPECT_EQ(root_layer->layers().front().use_count(), 2);
120 };
121
122 auto validate_engine_layer_dispose =
123 [message_latch, &root_layer](Dart_NativeArguments args) {
124 // Just one for our pointer now.
125 EXPECT_EQ(root_layer->layers().front().use_count(), 1);
126 root_layer.reset();
127 message_latch->Signal();
128 };
129
130 Settings settings = CreateSettingsForFixture();
131 TaskRunners task_runners("test", // label
132 GetCurrentTaskRunner(), // platform
133 CreateNewThread(), // raster
134 CreateNewThread(), // ui
135 CreateNewThread() // io
136 );
137
138 AddNativeCallback("CaptureRootLayer",
139 CREATE_NATIVE_ENTRY(capture_root_layer));
140 AddNativeCallback("ValidateLayerTreeCounts",
141 CREATE_NATIVE_ENTRY(validate_layer_tree_counts));
142 AddNativeCallback("ValidateEngineLayerDispose",
143 CREATE_NATIVE_ENTRY(validate_engine_layer_dispose));
144
145 std::unique_ptr<Shell> shell = CreateShell(settings, task_runners);
146
147 ASSERT_TRUE(shell->IsSetup());
148 auto configuration = RunConfiguration::InferFromSettings(settings);
149 configuration.SetEntrypoint("validateEngineLayerDispose");
150
151 shell->RunEngine(std::move(configuration), [](auto result) {
152 ASSERT_EQ(result, Engine::RunStatus::Success);
153 });
154
155 message_latch->Wait();
156 DestroyShell(std::move(shell), task_runners);
157}
158
159} // namespace testing
160} // namespace flutter
161
162// NOLINTEND(clang-analyzer-core.StackAddressEscape)
static RunConfiguration InferFromSettings(const Settings &settings, const fml::RefPtr< fml::TaskRunner > &io_worker=nullptr, IsolateLaunchType launch_type=IsolateLaunchType::kNewGroup)
Attempts to infer a run configuration from the settings object. This tries to create a run configurat...
const std::vector< std::shared_ptr< ContainerLayer > > & layer_stack()
std::unique_ptr< flutter::LayerTree > takeLayerTree(uint64_t width, uint64_t height)
Definition scene.cc:121
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
TEST_F(DisplayListTest, Defaults)
#define CREATE_NATIVE_ENTRY(native_entry)