• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define FML_USED_ON_EMBEDDER
6 
7 #include "flutter/shell/common/shell_test.h"
8 
9 #include "flutter/flow/layers/layer_tree.h"
10 #include "flutter/flow/layers/transform_layer.h"
11 #include "flutter/fml/make_copyable.h"
12 #include "flutter/fml/mapping.h"
13 #include "flutter/runtime/dart_vm.h"
14 #include "flutter/shell/gpu/gpu_surface_gl.h"
15 #include "flutter/testing/testing.h"
16 
17 namespace flutter {
18 namespace testing {
19 
ShellTest()20 ShellTest::ShellTest()
21     : native_resolver_(std::make_shared<TestDartNativeResolver>()) {}
22 
23 ShellTest::~ShellTest() = default;
24 
SendEnginePlatformMessage(Shell * shell,fml::RefPtr<PlatformMessage> message)25 void ShellTest::SendEnginePlatformMessage(
26     Shell* shell,
27     fml::RefPtr<PlatformMessage> message) {
28   fml::AutoResetWaitableEvent latch;
29   fml::TaskRunner::RunNowOrPostTask(
30       shell->GetTaskRunners().GetPlatformTaskRunner(),
31       [shell, &latch, message = std::move(message)]() {
32         if (auto engine = shell->weak_engine_) {
33           engine->HandlePlatformMessage(std::move(message));
34         }
35         latch.Signal();
36       });
37   latch.Wait();
38 }
39 
SetSnapshotsAndAssets(Settings & settings)40 void ShellTest::SetSnapshotsAndAssets(Settings& settings) {
41   if (!assets_dir_.is_valid()) {
42     return;
43   }
44 
45   settings.assets_dir = assets_dir_.get();
46 
47   // In JIT execution, all snapshots are present within the binary itself and
48   // don't need to be explicitly suppiled by the embedder.
49   if (DartVM::IsRunningPrecompiledCode()) {
50     settings.vm_snapshot_data = [this]() {
51       return fml::FileMapping::CreateReadOnly(assets_dir_, "vm_snapshot_data");
52     };
53 
54     settings.isolate_snapshot_data = [this]() {
55       return fml::FileMapping::CreateReadOnly(assets_dir_,
56                                               "isolate_snapshot_data");
57     };
58 
59     if (DartVM::IsRunningPrecompiledCode()) {
60       settings.vm_snapshot_instr = [this]() {
61         return fml::FileMapping::CreateReadExecute(assets_dir_,
62                                                    "vm_snapshot_instr");
63       };
64 
65       settings.isolate_snapshot_instr = [this]() {
66         return fml::FileMapping::CreateReadExecute(assets_dir_,
67                                                    "isolate_snapshot_instr");
68       };
69     }
70   } else {
71     settings.application_kernels = [this]() {
72       std::vector<std::unique_ptr<const fml::Mapping>> kernel_mappings;
73       kernel_mappings.emplace_back(
74           fml::FileMapping::CreateReadOnly(assets_dir_, "kernel_blob.bin"));
75       return kernel_mappings;
76     };
77   }
78 }
79 
PlatformViewNotifyCreated(Shell * shell)80 void ShellTest::PlatformViewNotifyCreated(Shell* shell) {
81   fml::AutoResetWaitableEvent latch;
82   fml::TaskRunner::RunNowOrPostTask(
83       shell->GetTaskRunners().GetPlatformTaskRunner(), [shell, &latch]() {
84         shell->GetPlatformView()->NotifyCreated();
85         latch.Signal();
86       });
87   latch.Wait();
88 }
89 
RunEngine(Shell * shell,RunConfiguration configuration)90 void ShellTest::RunEngine(Shell* shell, RunConfiguration configuration) {
91   fml::AutoResetWaitableEvent latch;
92   fml::TaskRunner::RunNowOrPostTask(
93       shell->GetTaskRunners().GetPlatformTaskRunner(),
94       [shell, &latch, &configuration]() {
95         shell->RunEngine(std::move(configuration),
96                          [&latch](Engine::RunStatus run_status) {
97                            ASSERT_EQ(run_status, Engine::RunStatus::Success);
98                            latch.Signal();
99                          });
100       });
101   latch.Wait();
102 }
103 
PumpOneFrame(Shell * shell)104 void ShellTest::PumpOneFrame(Shell* shell) {
105   // Set viewport to nonempty, and call Animator::BeginFrame to make the layer
106   // tree pipeline nonempty. Without either of this, the layer tree below
107   // won't be rasterized.
108   fml::AutoResetWaitableEvent latch;
109   shell->GetTaskRunners().GetUITaskRunner()->PostTask(
110       [&latch, engine = shell->weak_engine_]() {
111         engine->SetViewportMetrics(
112             {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
113         engine->animator_->BeginFrame(fml::TimePoint::Now(),
114                                       fml::TimePoint::Now());
115         latch.Signal();
116       });
117   latch.Wait();
118 
119   latch.Reset();
120   // Call |Render| to rasterize a layer tree and trigger |OnFrameRasterized|
121   fml::WeakPtr<RuntimeDelegate> runtime_delegate = shell->weak_engine_;
122   shell->GetTaskRunners().GetUITaskRunner()->PostTask(
123       [&latch, runtime_delegate]() {
124         auto layer_tree = std::make_unique<LayerTree>();
125         SkMatrix identity;
126         identity.setIdentity();
127         auto root_layer = std::make_shared<TransformLayer>(identity);
128         layer_tree->set_root_layer(root_layer);
129         runtime_delegate->Render(std::move(layer_tree));
130         latch.Signal();
131       });
132   latch.Wait();
133 }
134 
UnreportedTimingsCount(Shell * shell)135 int ShellTest::UnreportedTimingsCount(Shell* shell) {
136   return shell->unreported_timings_.size();
137 }
138 
SetNeedsReportTimings(Shell * shell,bool value)139 void ShellTest::SetNeedsReportTimings(Shell* shell, bool value) {
140   shell->SetNeedsReportTimings(value);
141 }
142 
GetNeedsReportTimings(Shell * shell)143 bool ShellTest::GetNeedsReportTimings(Shell* shell) {
144   return shell->needs_report_timings_;
145 }
146 
CreateSettingsForFixture()147 Settings ShellTest::CreateSettingsForFixture() {
148   Settings settings;
149   settings.leak_vm = false;
150   settings.task_observer_add = [](intptr_t key, fml::closure handler) {
151     fml::MessageLoop::GetCurrent().AddTaskObserver(key, handler);
152   };
153   settings.task_observer_remove = [](intptr_t key) {
154     fml::MessageLoop::GetCurrent().RemoveTaskObserver(key);
155   };
156   settings.isolate_create_callback = [this]() {
157     native_resolver_->SetNativeResolverForIsolate();
158   };
159   SetSnapshotsAndAssets(settings);
160   return settings;
161 }
162 
GetTaskRunnersForFixture()163 TaskRunners ShellTest::GetTaskRunnersForFixture() {
164   return {
165       "test",
166       thread_host_->platform_thread->GetTaskRunner(),  // platform
167       thread_host_->gpu_thread->GetTaskRunner(),       // gpu
168       thread_host_->ui_thread->GetTaskRunner(),        // ui
169       thread_host_->io_thread->GetTaskRunner()         // io
170   };
171 }
172 
CreateShell(Settings settings)173 std::unique_ptr<Shell> ShellTest::CreateShell(Settings settings) {
174   return CreateShell(std::move(settings), GetTaskRunnersForFixture());
175 }
176 
CreateShell(Settings settings,TaskRunners task_runners)177 std::unique_ptr<Shell> ShellTest::CreateShell(Settings settings,
178                                               TaskRunners task_runners) {
179   return Shell::Create(
180       task_runners, settings,
181       [](Shell& shell) {
182         return std::make_unique<ShellTestPlatformView>(shell,
183                                                        shell.GetTaskRunners());
184       },
185       [](Shell& shell) {
186         return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
187       });
188 }
189 
190 // |testing::ThreadTest|
SetUp()191 void ShellTest::SetUp() {
192   ThreadTest::SetUp();
193   assets_dir_ =
194       fml::OpenDirectory(GetFixturesPath(), false, fml::FilePermission::kRead);
195   thread_host_ = std::make_unique<ThreadHost>(
196       "io.flutter.test." + GetCurrentTestName() + ".",
197       ThreadHost::Type::Platform | ThreadHost::Type::IO | ThreadHost::Type::UI |
198           ThreadHost::Type::GPU);
199 }
200 
201 // |testing::ThreadTest|
TearDown()202 void ShellTest::TearDown() {
203   ThreadTest::TearDown();
204   assets_dir_.reset();
205   thread_host_.reset();
206 }
207 
AddNativeCallback(std::string name,Dart_NativeFunction callback)208 void ShellTest::AddNativeCallback(std::string name,
209                                   Dart_NativeFunction callback) {
210   native_resolver_->AddNativeCallback(std::move(name), callback);
211 }
212 
ShellTestPlatformView(PlatformView::Delegate & delegate,TaskRunners task_runners)213 ShellTestPlatformView::ShellTestPlatformView(PlatformView::Delegate& delegate,
214                                              TaskRunners task_runners)
215     : PlatformView(delegate, std::move(task_runners)) {}
216 
217 ShellTestPlatformView::~ShellTestPlatformView() = default;
218 
219 // |PlatformView|
CreateRenderingSurface()220 std::unique_ptr<Surface> ShellTestPlatformView::CreateRenderingSurface() {
221   return std::make_unique<GPUSurfaceGL>(this, true);
222 }
223 
224 // |GPUSurfaceGLDelegate|
GLContextMakeCurrent()225 bool ShellTestPlatformView::GLContextMakeCurrent() {
226   return gl_surface_.MakeCurrent();
227 }
228 
229 // |GPUSurfaceGLDelegate|
GLContextClearCurrent()230 bool ShellTestPlatformView::GLContextClearCurrent() {
231   return gl_surface_.ClearCurrent();
232 }
233 
234 // |GPUSurfaceGLDelegate|
GLContextPresent()235 bool ShellTestPlatformView::GLContextPresent() {
236   return gl_surface_.Present();
237 }
238 
239 // |GPUSurfaceGLDelegate|
GLContextFBO() const240 intptr_t ShellTestPlatformView::GLContextFBO() const {
241   return gl_surface_.GetFramebuffer();
242 }
243 
244 // |GPUSurfaceGLDelegate|
GetGLProcResolver() const245 GPUSurfaceGLDelegate::GLProcResolver ShellTestPlatformView::GetGLProcResolver()
246     const {
247   return [surface = &gl_surface_](const char* name) -> void* {
248     return surface->GetProcAddress(name);
249   };
250 }
251 
252 // |GPUSurfaceGLDelegate|
GetExternalViewEmbedder()253 ExternalViewEmbedder* ShellTestPlatformView::GetExternalViewEmbedder() {
254   return nullptr;
255 }
256 
257 }  // namespace testing
258 }  // namespace flutter
259