Flutter Engine
The Flutter Engine
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
5#include "flutter/lib/ui/compositing/scene_builder.h"
6
7#include <memory>
8
9#include "flutter/common/task_runners.h"
10#include "flutter/fml/synchronization/waitable_event.h"
11#include "flutter/runtime/dart_vm.h"
12#include "flutter/shell/common/shell_test.h"
13#include "flutter/shell/common/thread_host.h"
14#include "flutter/testing/testing.h"
15
16// CREATE_NATIVE_ENTRY is leaky by design
17// NOLINTBEGIN(clang-analyzer-core.StackAddressEscape)
18
19namespace flutter {
20namespace testing {
21
22TEST_F(ShellTest, SceneBuilderBuildAndSceneDisposeReleasesLayerStack) {
23 auto message_latch = std::make_shared<fml::AutoResetWaitableEvent>();
24
25 // prevent ClearDartWrapper() from deleting the scene builder.
26 SceneBuilder* retained_scene_builder;
27 Scene* retained_scene;
28
29 auto validate_builder_has_layers =
30 [&retained_scene_builder](Dart_NativeArguments args) {
31 auto handle = Dart_GetNativeArgument(args, 0);
32 intptr_t peer = 0;
35 ASSERT_FALSE(Dart_IsError(result));
36 retained_scene_builder = reinterpret_cast<SceneBuilder*>(peer);
37 retained_scene_builder->AddRef();
38 ASSERT_TRUE(retained_scene_builder);
39 ASSERT_EQ(retained_scene_builder->layer_stack().size(), 2ul);
40 };
41
42 auto validate_builder_has_no_layers =
43 [&retained_scene_builder](Dart_NativeArguments args) {
44 ASSERT_EQ(retained_scene_builder->layer_stack().size(), 0ul);
45 retained_scene_builder->Release();
46 retained_scene_builder = nullptr;
47 };
48
49 auto capture_scene = [&retained_scene](Dart_NativeArguments args) {
50 auto handle = Dart_GetNativeArgument(args, 0);
51 intptr_t peer = 0;
54 ASSERT_FALSE(Dart_IsError(result));
55 retained_scene = reinterpret_cast<Scene*>(peer);
56 retained_scene->AddRef();
57 ASSERT_TRUE(retained_scene);
58 };
59
60 auto validate_scene_has_no_layers =
61 [message_latch, &retained_scene](Dart_NativeArguments args) {
62 EXPECT_FALSE(retained_scene->takeLayerTree(100, 100));
63 retained_scene->Release();
64 retained_scene = nullptr;
65 message_latch->Signal();
66 };
67
68 Settings settings = CreateSettingsForFixture();
69 TaskRunners task_runners("test", // label
70 GetCurrentTaskRunner(), // platform
71 CreateNewThread(), // raster
72 CreateNewThread(), // ui
73 CreateNewThread() // io
74 );
75
76 AddNativeCallback("ValidateBuilderHasLayers",
77 CREATE_NATIVE_ENTRY(validate_builder_has_layers));
78 AddNativeCallback("ValidateBuilderHasNoLayers",
79 CREATE_NATIVE_ENTRY(validate_builder_has_no_layers));
80
81 AddNativeCallback("CaptureScene", CREATE_NATIVE_ENTRY(capture_scene));
82 AddNativeCallback("ValidateSceneHasNoLayers",
83 CREATE_NATIVE_ENTRY(validate_scene_has_no_layers));
84
85 std::unique_ptr<Shell> shell = CreateShell(settings, task_runners);
86
87 ASSERT_TRUE(shell->IsSetup());
89 configuration.SetEntrypoint("validateSceneBuilderAndScene");
90
91 shell->RunEngine(std::move(configuration), [](auto result) {
93 });
94
95 message_latch->Wait();
96 DestroyShell(std::move(shell), task_runners);
97}
98
99TEST_F(ShellTest, EngineLayerDisposeReleasesReference) {
100 auto message_latch = std::make_shared<fml::AutoResetWaitableEvent>();
101
102 std::shared_ptr<ContainerLayer> root_layer;
103
104 auto capture_root_layer = [&root_layer](Dart_NativeArguments args) {
105 auto handle = Dart_GetNativeArgument(args, 0);
106 intptr_t peer = 0;
108 handle, tonic::DartWrappable::kPeerIndex, &peer);
109 ASSERT_FALSE(Dart_IsError(result));
110 SceneBuilder* scene_builder = reinterpret_cast<SceneBuilder*>(peer);
111 ASSERT_TRUE(scene_builder);
112 root_layer = scene_builder->layer_stack()[0];
113 ASSERT_TRUE(root_layer);
114 };
115
116 auto validate_layer_tree_counts = [&root_layer](Dart_NativeArguments args) {
117 // One for the EngineLayer, one for our pointer in the test.
118 EXPECT_EQ(root_layer->layers().front().use_count(), 2);
119 };
120
121 auto validate_engine_layer_dispose =
122 [message_latch, &root_layer](Dart_NativeArguments args) {
123 // Just one for our pointer now.
124 EXPECT_EQ(root_layer->layers().front().use_count(), 1);
125 root_layer.reset();
126 message_latch->Signal();
127 };
128
129 Settings settings = CreateSettingsForFixture();
130 TaskRunners task_runners("test", // label
131 GetCurrentTaskRunner(), // platform
132 CreateNewThread(), // raster
133 CreateNewThread(), // ui
134 CreateNewThread() // io
135 );
136
137 AddNativeCallback("CaptureRootLayer",
138 CREATE_NATIVE_ENTRY(capture_root_layer));
139 AddNativeCallback("ValidateLayerTreeCounts",
140 CREATE_NATIVE_ENTRY(validate_layer_tree_counts));
141 AddNativeCallback("ValidateEngineLayerDispose",
142 CREATE_NATIVE_ENTRY(validate_engine_layer_dispose));
143
144 std::unique_ptr<Shell> shell = CreateShell(settings, task_runners);
145
146 ASSERT_TRUE(shell->IsSetup());
147 auto configuration = RunConfiguration::InferFromSettings(settings);
148 configuration.SetEntrypoint("validateEngineLayerDispose");
149
150 shell->RunEngine(std::move(configuration), [](auto result) {
152 });
153
154 message_latch->Wait();
155 DestroyShell(std::move(shell), task_runners);
156}
157
158} // namespace testing
159} // namespace flutter
160
161// 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:122
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, int index)
DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj, int index, intptr_t *value)
struct _Dart_NativeArguments * Dart_NativeArguments
Definition: dart_api.h:3019
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
GAsyncResult * result
fml::RefPtr< fml::TaskRunner > CreateNewThread(const std::string &name)
fml::RefPtr< fml::TaskRunner > GetCurrentTaskRunner()
TEST_F(DisplayListTest, Defaults)
#define CREATE_NATIVE_ENTRY(native_entry)