blob: fd7ef08b328442c24e8d0ffc3a6a9068e5d7b624 [file] [log] [blame]
// 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.
#include <array>
#include <gtest/gtest.h>
#include <lib/async-loop/default.h>
#include <lib/zx/event.h>
#include <zircon/syscalls.h>
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/fml/time/time_delta.h"
#include "flutter/fml/time/time_point.h"
#include "flutter/shell/common/thread_host.h"
#include "flutter/shell/common/vsync_waiter.h"
#include "flutter/shell/platform/fuchsia/flutter/flutter_runner_product_configuration.h"
#include "flutter/shell/platform/fuchsia/flutter/task_runner_adapter.h"
#include "flutter/shell/platform/fuchsia/flutter/thread.h"
#include "flutter/shell/platform/fuchsia/flutter/vsync_waiter.h"
namespace flutter_runner_test {
class VsyncWaiterTest : public testing::Test {
public:
VsyncWaiterTest() {}
~VsyncWaiterTest() = default;
std::unique_ptr<flutter::VsyncWaiter> CreateVsyncWaiter(
flutter::TaskRunners task_runners) {
return std::make_unique<flutter_runner::VsyncWaiter>(
"VsyncWaiterTest", vsync_event_.get(), task_runners,
fml::TimeDelta::Zero());
}
void SignalVsyncEvent() {
auto status =
zx_object_signal(vsync_event_.get(), 0,
flutter_runner::VsyncWaiter::SessionPresentSignal);
EXPECT_EQ(status, ZX_OK);
}
protected:
void SetUp() override {
auto status = zx::event::create(0, &vsync_event_);
EXPECT_EQ(status, ZX_OK);
}
private:
zx::event vsync_event_;
};
TEST_F(VsyncWaiterTest, AwaitVsync) {
std::array<std::unique_ptr<flutter_runner::Thread>, 3> threads;
for (auto& thread : threads) {
thread.reset(new flutter_runner::Thread());
}
async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
const flutter::TaskRunners task_runners(
"VsyncWaiterTests", // Dart thread labels
flutter_runner::CreateFMLTaskRunner(
async_get_default_dispatcher()), // platform
flutter_runner::CreateFMLTaskRunner(threads[0]->dispatcher()), // raster
flutter_runner::CreateFMLTaskRunner(threads[1]->dispatcher()), // ui
flutter_runner::CreateFMLTaskRunner(threads[2]->dispatcher()) // io
);
auto vsync_waiter = CreateVsyncWaiter(std::move(task_runners));
fml::AutoResetWaitableEvent latch;
vsync_waiter->AsyncWaitForVsync(
[&latch](fml::TimePoint frame_start_time,
fml::TimePoint frame_target_time) { latch.Signal(); });
SignalVsyncEvent();
bool did_timeout =
latch.WaitWithTimeout(fml::TimeDelta::FromMilliseconds(5000));
// False indicates we were signalled rather than timed out
EXPECT_FALSE(did_timeout);
vsync_waiter.reset();
for (const auto& thread : threads) {
thread->Quit();
}
}
TEST_F(VsyncWaiterTest, SnapToNextPhaseOverlapsWithNow) {
const auto now = fml::TimePoint::Now();
const auto last_presentation_time = now - fml::TimeDelta::FromNanoseconds(10);
const auto delta = fml::TimeDelta::FromNanoseconds(10);
const auto next_vsync = flutter_runner::VsyncWaiter::SnapToNextPhase(
now, last_presentation_time, delta);
EXPECT_EQ(now + delta, next_vsync);
}
TEST_F(VsyncWaiterTest, SnapToNextPhaseAfterNow) {
const auto now = fml::TimePoint::Now();
const auto last_presentation_time = now - fml::TimeDelta::FromNanoseconds(9);
const auto delta = fml::TimeDelta::FromNanoseconds(10);
const auto next_vsync = flutter_runner::VsyncWaiter::SnapToNextPhase(
now, last_presentation_time, delta);
// math here: 10 - 9 = 1
EXPECT_EQ(now + fml::TimeDelta::FromNanoseconds(1), next_vsync);
}
TEST_F(VsyncWaiterTest, SnapToNextPhaseAfterNowMultiJump) {
const auto now = fml::TimePoint::Now();
const auto last_presentation_time = now - fml::TimeDelta::FromNanoseconds(34);
const auto delta = fml::TimeDelta::FromNanoseconds(10);
const auto next_vsync = flutter_runner::VsyncWaiter::SnapToNextPhase(
now, last_presentation_time, delta);
// zeroes: -34, -24, -14, -4, 6, ...
EXPECT_EQ(now + fml::TimeDelta::FromNanoseconds(6), next_vsync);
}
TEST_F(VsyncWaiterTest, SnapToNextPhaseAfterNowMultiJumpAccountForCeils) {
const auto now = fml::TimePoint::Now();
const auto last_presentation_time = now - fml::TimeDelta::FromNanoseconds(20);
const auto delta = fml::TimeDelta::FromNanoseconds(16);
const auto next_vsync = flutter_runner::VsyncWaiter::SnapToNextPhase(
now, last_presentation_time, delta);
// zeroes: -20, -4, 12, 28, ...
EXPECT_EQ(now + fml::TimeDelta::FromNanoseconds(12), next_vsync);
}
} // namespace flutter_runner_test