shell_test.cc 11.2 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#define FML_USED_ON_EMBEDDER

#include "flutter/shell/common/shell_test.h"
8
#include "flutter/shell/common/shell_test_platform_view.h"
9

10 11
#include "flutter/flow/layers/layer_tree.h"
#include "flutter/flow/layers/transform_layer.h"
12
#include "flutter/fml/build_config.h"
13
#include "flutter/fml/make_copyable.h"
14 15
#include "flutter/fml/mapping.h"
#include "flutter/runtime/dart_vm.h"
16
#include "flutter/shell/common/vsync_waiter_fallback.h"
17 18
#include "flutter/testing/testing.h"

19
namespace flutter {
20 21 22
namespace testing {

ShellTest::ShellTest()
23 24 25 26 27 28
    : native_resolver_(std::make_shared<TestDartNativeResolver>()),
      thread_host_("io.flutter.test." + GetCurrentTestName() + ".",
                   ThreadHost::Type::Platform | ThreadHost::Type::IO |
                       ThreadHost::Type::UI | ThreadHost::Type::GPU),
      assets_dir_(fml::OpenDirectory(GetFixturesPath(),
                                     false,
29 30
                                     fml::FilePermission::kRead)),
      aot_symbols_(LoadELFSymbolFromFixturesIfNeccessary()) {}
31

32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
void ShellTest::SendEnginePlatformMessage(
    Shell* shell,
    fml::RefPtr<PlatformMessage> message) {
  fml::AutoResetWaitableEvent latch;
  fml::TaskRunner::RunNowOrPostTask(
      shell->GetTaskRunners().GetPlatformTaskRunner(),
      [shell, &latch, message = std::move(message)]() {
        if (auto engine = shell->weak_engine_) {
          engine->HandlePlatformMessage(std::move(message));
        }
        latch.Signal();
      });
  latch.Wait();
}

47
void ShellTest::SetSnapshotsAndAssets(Settings& settings) {
48 49 50 51 52 53 54 55
  if (!assets_dir_.is_valid()) {
    return;
  }

  settings.assets_dir = assets_dir_.get();

  // In JIT execution, all snapshots are present within the binary itself and
  // don't need to be explicitly suppiled by the embedder.
56
  if (DartVM::IsRunningPrecompiledCode()) {
57
    PrepareSettingsForAOTWithSymbols(settings, aot_symbols_);
58 59 60 61
  } else {
    settings.application_kernels = [this]() {
      std::vector<std::unique_ptr<const fml::Mapping>> kernel_mappings;
      kernel_mappings.emplace_back(
62
          fml::FileMapping::CreateReadOnly(assets_dir_, "kernel_blob.bin"));
63 64 65 66 67
      return kernel_mappings;
    };
  }
}

68 69 70 71 72 73 74 75 76 77 78 79 80
void ShellTest::PlatformViewNotifyCreated(Shell* shell) {
  fml::AutoResetWaitableEvent latch;
  fml::TaskRunner::RunNowOrPostTask(
      shell->GetTaskRunners().GetPlatformTaskRunner(), [shell, &latch]() {
        shell->GetPlatformView()->NotifyCreated();
        latch.Signal();
      });
  latch.Wait();
}

void ShellTest::RunEngine(Shell* shell, RunConfiguration configuration) {
  fml::AutoResetWaitableEvent latch;
  fml::TaskRunner::RunNowOrPostTask(
D
Dan Field 已提交
81 82 83 84 85 86 87 88
      shell->GetTaskRunners().GetPlatformTaskRunner(),
      [shell, &latch, &configuration]() {
        shell->RunEngine(std::move(configuration),
                         [&latch](Engine::RunStatus run_status) {
                           ASSERT_EQ(run_status, Engine::RunStatus::Success);
                           latch.Signal();
                         });
      });
89 90 91
  latch.Wait();
}

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
void ShellTest::RestartEngine(Shell* shell, RunConfiguration configuration) {
  std::promise<bool> restarted;
  fml::TaskRunner::RunNowOrPostTask(
      shell->GetTaskRunners().GetUITaskRunner(),
      [shell, &restarted, &configuration]() {
        restarted.set_value(shell->engine_->Restart(std::move(configuration)));
      });
  ASSERT_TRUE(restarted.get_future().get());
}

void ShellTest::VSyncFlush(Shell* shell, bool& will_draw_new_frame) {
  fml::AutoResetWaitableEvent latch;
  shell->GetTaskRunners().GetPlatformTaskRunner()->PostTask(
      [shell, &will_draw_new_frame, &latch] {
        // The following UI task ensures that all previous UI tasks are flushed.
        fml::AutoResetWaitableEvent ui_latch;
        shell->GetTaskRunners().GetUITaskRunner()->PostTask(
            [&ui_latch, &will_draw_new_frame]() {
              will_draw_new_frame = true;
              ui_latch.Signal();
            });

        ShellTestPlatformView* test_platform_view =
            static_cast<ShellTestPlatformView*>(shell->GetPlatformView().get());
        do {
          test_platform_view->SimulateVSync();
        } while (ui_latch.WaitWithTimeout(fml::TimeDelta::FromMilliseconds(1)));

        latch.Signal();
      });
  latch.Wait();
}

L
liyuqian 已提交
125 126 127 128
void ShellTest::PumpOneFrame(Shell* shell,
                             double width,
                             double height,
                             LayerTreeBuilder builder) {
129 130 131 132 133 134 135 136 137
  PumpOneFrame(shell,
               flutter::ViewportMetrics{1, width, height, flutter::kUnsetDepth,
                                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
               std::move(builder));
}

void ShellTest::PumpOneFrame(Shell* shell,
                             flutter::ViewportMetrics viewport_metrics,
                             LayerTreeBuilder builder) {
138 139 140 141 142
  // Set viewport to nonempty, and call Animator::BeginFrame to make the layer
  // tree pipeline nonempty. Without either of this, the layer tree below
  // won't be rasterized.
  fml::AutoResetWaitableEvent latch;
  shell->GetTaskRunners().GetUITaskRunner()->PostTask(
143 144
      [&latch, engine = shell->weak_engine_, viewport_metrics]() {
        engine->SetViewportMetrics(std::move(viewport_metrics));
145 146 147 148
        const auto frame_begin_time = fml::TimePoint::Now();
        const auto frame_end_time =
            frame_begin_time + fml::TimeDelta::FromSecondsF(1.0 / 60.0);
        engine->animator_->BeginFrame(frame_begin_time, frame_end_time);
149 150 151 152 153 154
        latch.Signal();
      });
  latch.Wait();

  latch.Reset();
  // Call |Render| to rasterize a layer tree and trigger |OnFrameRasterized|
D
Dan Field 已提交
155
  fml::WeakPtr<RuntimeDelegate> runtime_delegate = shell->weak_engine_;
156
  shell->GetTaskRunners().GetUITaskRunner()->PostTask(
157 158 159 160 161 162
      [&latch, runtime_delegate, &builder, viewport_metrics]() {
        auto layer_tree = std::make_unique<LayerTree>(
            SkISize::Make(viewport_metrics.physical_width,
                          viewport_metrics.physical_height),
            static_cast<float>(viewport_metrics.physical_depth),
            static_cast<float>(viewport_metrics.device_pixel_ratio));
163 164 165
        SkMatrix identity;
        identity.setIdentity();
        auto root_layer = std::make_shared<TransformLayer>(identity);
166
        layer_tree->set_root_layer(root_layer);
L
liyuqian 已提交
167 168 169
        if (builder) {
          builder(root_layer);
        }
170 171 172 173 174 175
        runtime_delegate->Render(std::move(layer_tree));
        latch.Signal();
      });
  latch.Wait();
}

176
void ShellTest::DispatchFakePointerData(Shell* shell) {
177 178 179 180 181 182
  auto packet = std::make_unique<PointerDataPacket>(1);
  DispatchPointerData(shell, std::move(packet));
}

void ShellTest::DispatchPointerData(Shell* shell,
                                    std::unique_ptr<PointerDataPacket> packet) {
183
  fml::AutoResetWaitableEvent latch;
184 185 186 187 188 189
  shell->GetTaskRunners().GetPlatformTaskRunner()->PostTask(
      [&latch, shell, &packet]() {
        // Goes through PlatformView to ensure packet is corrected converted.
        shell->GetPlatformView()->DispatchPointerDataPacket(std::move(packet));
        latch.Signal();
      });
190 191 192
  latch.Wait();
}

193 194 195 196 197 198 199 200 201 202 203 204
int ShellTest::UnreportedTimingsCount(Shell* shell) {
  return shell->unreported_timings_.size();
}

void ShellTest::SetNeedsReportTimings(Shell* shell, bool value) {
  shell->SetNeedsReportTimings(value);
}

bool ShellTest::GetNeedsReportTimings(Shell* shell) {
  return shell->needs_report_timings_;
}

205 206 207 208 209 210 211 212 213 214 215 216 217 218
void ShellTest::OnServiceProtocolGetSkSLs(
    Shell* shell,
    const ServiceProtocol::Handler::ServiceProtocolMap& params,
    rapidjson::Document& response) {
  std::promise<bool> finished;
  fml::TaskRunner::RunNowOrPostTask(shell->GetTaskRunners().GetIOTaskRunner(),
                                    [shell, params, &response, &finished]() {
                                      shell->OnServiceProtocolGetSkSLs(
                                          params, response);
                                      finished.set_value(true);
                                    });
  finished.get_future().wait();
}

219 220 221 222 223
std::shared_ptr<txt::FontCollection> ShellTest::GetFontCollection(
    Shell* shell) {
  return shell->weak_engine_->GetFontCollection().GetFontCollection();
}

224 225
Settings ShellTest::CreateSettingsForFixture() {
  Settings settings;
226
  settings.leak_vm = false;
227 228 229 230 231 232
  settings.task_observer_add = [](intptr_t key, fml::closure handler) {
    fml::MessageLoop::GetCurrent().AddTaskObserver(key, handler);
  };
  settings.task_observer_remove = [](intptr_t key) {
    fml::MessageLoop::GetCurrent().RemoveTaskObserver(key);
  };
233
  settings.isolate_create_callback = [this]() {
234 235
    native_resolver_->SetNativeResolverForIsolate();
  };
236 237 238
#if OS_FUCHSIA
  settings.verbose_logging = true;
#endif
239 240 241 242
  SetSnapshotsAndAssets(settings);
  return settings;
}

243
TaskRunners ShellTest::GetTaskRunnersForFixture() {
244 245
  return {
      "test",
246
      thread_host_.platform_thread->GetTaskRunner(),  // platform
247
      thread_host_.gpu_thread->GetTaskRunner(),       // raster
248 249
      thread_host_.ui_thread->GetTaskRunner(),        // ui
      thread_host_.io_thread->GetTaskRunner()         // io
250 251 252
  };
}

253 254 255 256
std::unique_ptr<Shell> ShellTest::CreateShell(Settings settings,
                                              bool simulate_vsync) {
  return CreateShell(std::move(settings), GetTaskRunnersForFixture(),
                     simulate_vsync);
257 258 259
}

std::unique_ptr<Shell> ShellTest::CreateShell(Settings settings,
260 261
                                              TaskRunners task_runners,
                                              bool simulate_vsync) {
262 263 264 265 266 267 268 269 270 271
  const auto vsync_clock = std::make_shared<ShellTestVsyncClock>();
  CreateVsyncWaiter create_vsync_waiter = [&]() {
    if (simulate_vsync) {
      return static_cast<std::unique_ptr<VsyncWaiter>>(
          std::make_unique<ShellTestVsyncWaiter>(task_runners, vsync_clock));
    } else {
      return static_cast<std::unique_ptr<VsyncWaiter>>(
          std::make_unique<VsyncWaiterFallback>(task_runners));
    }
  };
272 273
  return Shell::Create(
      task_runners, settings,
274
      [vsync_clock, &create_vsync_waiter](Shell& shell) {
275 276 277 278
        return ShellTestPlatformView::Create(
            shell, shell.GetTaskRunners(), vsync_clock,
            std::move(create_vsync_waiter),
            ShellTestPlatformView::BackendType::kDefaultBackend);
279 280 281 282 283 284
      },
      [](Shell& shell) {
        return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
      });
}

285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
void ShellTest::DestroyShell(std::unique_ptr<Shell> shell) {
  DestroyShell(std::move(shell), GetTaskRunnersForFixture());
}

void ShellTest::DestroyShell(std::unique_ptr<Shell> shell,
                             TaskRunners task_runners) {
  fml::AutoResetWaitableEvent latch;
  fml::TaskRunner::RunNowOrPostTask(task_runners.GetPlatformTaskRunner(),
                                    [&shell, &latch]() mutable {
                                      shell.reset();
                                      latch.Signal();
                                    });
  latch.Wait();
}

300 301 302 303 304 305
void ShellTest::AddNativeCallback(std::string name,
                                  Dart_NativeFunction callback) {
  native_resolver_->AddNativeCallback(std::move(name), callback);
}

}  // namespace testing
306
}  // namespace flutter