#include "cc/trees/presentation_time_callback_buffer.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
std::vector<cc::PresentationTimeCallbackBuffer::Callback> GenerateCallbacks(
int num_callbacks) {
std::vector<cc::PresentationTimeCallbackBuffer::Callback> result;
while (num_callbacks-- > 0) {
result.push_back(base::BindOnce([](const gfx::PresentationFeedback&) {
FAIL() << "Callbacks should not be directly invoked by "
"PresentationTimeCallbackBuffer";
}));
}
return result;
}
std::vector<cc::PresentationTimeCallbackBuffer::SuccessfulCallback>
GenerateSuccessfulCallbacks(int num_callbacks) {
std::vector<cc::PresentationTimeCallbackBuffer::SuccessfulCallback> result;
while (num_callbacks-- > 0) {
result.push_back(base::BindOnce([](base::TimeTicks presentation_timestamp) {
FAIL() << "Callbacks should not be directly invoked by "
"PresentationTimeCallbackBuffer";
}));
}
return result;
}
constexpr uint32_t kFrameToken1 = 234;
constexpr uint32_t kFrameToken2 = 345;
constexpr uint32_t kFrameToken3 = 456;
constexpr uint32_t kFrameToken4 = 567;
}
namespace cc {
TEST(PresentationTimeCallbackBufferTest, TestNoCallbacks) {
PresentationTimeCallbackBuffer buffer;
auto result =
buffer.PopPendingCallbacks(kFrameToken1, false);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
TEST(PresentationTimeCallbackBufferTest, TestMainThreadCallbackOnSuccess) {
PresentationTimeCallbackBuffer buffer;
buffer.RegisterMainThreadCallbacks(kFrameToken2, GenerateCallbacks(1));
{
auto result =
buffer.PopPendingCallbacks(kFrameToken1, false);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
{
auto result =
buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_EQ(result.main_callbacks.size(), 1ull);
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
{
auto result =
buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
}
TEST(PresentationTimeCallbackBufferTest, TestMainThreadCallbackOnFailure) {
PresentationTimeCallbackBuffer buffer;
buffer.RegisterMainThreadCallbacks(kFrameToken2, GenerateCallbacks(1));
{
auto result =
buffer.PopPendingCallbacks(kFrameToken1, false);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
{
auto result =
buffer.PopPendingCallbacks(kFrameToken2, true);
EXPECT_EQ(result.main_callbacks.size(), 1ull);
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
{
auto result =
buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
}
TEST(PresentationTimeCallbackBufferTest, TestMainThreadSuccessfulCallback) {
PresentationTimeCallbackBuffer buffer;
buffer.RegisterMainThreadSuccessfulCallbacks(kFrameToken2,
GenerateSuccessfulCallbacks(1));
{
auto result =
buffer.PopPendingCallbacks(kFrameToken1, false);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
{
auto result =
buffer.PopPendingCallbacks(kFrameToken2, true);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
{
auto result =
buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_EQ(result.main_successful_callbacks.size(), 1ull);
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
{
auto result =
buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
}
TEST(PresentationTimeCallbackBufferTest,
TestCompositorThreadSuccessfulCallback) {
PresentationTimeCallbackBuffer buffer;
buffer.RegisterCompositorThreadSuccessfulCallbacks(
kFrameToken2, GenerateSuccessfulCallbacks(1));
{
auto result =
buffer.PopPendingCallbacks(kFrameToken1, false);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
{
auto result =
buffer.PopPendingCallbacks(kFrameToken2, true);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
{
auto result =
buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_EQ(result.compositor_successful_callbacks.size(), 1ull);
}
{
auto result =
buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
}
TEST(PresentationTimeCallbackBufferTest, TestMixedCallbacksOnSuccess) {
PresentationTimeCallbackBuffer buffer;
buffer.RegisterMainThreadCallbacks(kFrameToken2, GenerateCallbacks(1));
buffer.RegisterMainThreadSuccessfulCallbacks(kFrameToken2,
GenerateSuccessfulCallbacks(1));
buffer.RegisterCompositorThreadSuccessfulCallbacks(
kFrameToken2, GenerateSuccessfulCallbacks(1));
{
auto result =
buffer.PopPendingCallbacks(kFrameToken1, false);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
{
auto result =
buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_EQ(result.main_callbacks.size(), 1ull);
EXPECT_EQ(result.main_successful_callbacks.size(), 1ull);
EXPECT_EQ(result.compositor_successful_callbacks.size(), 1ull);
}
{
auto result =
buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
}
TEST(PresentationTimeCallbackBufferTest, TestMixedCallbacksOnFailure) {
PresentationTimeCallbackBuffer buffer;
buffer.RegisterMainThreadCallbacks(kFrameToken2, GenerateCallbacks(1));
buffer.RegisterMainThreadSuccessfulCallbacks(kFrameToken2,
GenerateSuccessfulCallbacks(1));
buffer.RegisterCompositorThreadSuccessfulCallbacks(
kFrameToken2, GenerateSuccessfulCallbacks(1));
{
auto result =
buffer.PopPendingCallbacks(kFrameToken1, false);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
{
auto result =
buffer.PopPendingCallbacks(kFrameToken2, true);
EXPECT_EQ(result.main_callbacks.size(), 1ull);
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
{
auto result =
buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_EQ(result.main_successful_callbacks.size(), 1ull);
EXPECT_EQ(result.compositor_successful_callbacks.size(), 1ull);
}
{
auto result =
buffer.PopPendingCallbacks(kFrameToken2, false);
EXPECT_TRUE(result.main_callbacks.empty());
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
}
TEST(PresentationTimeCallbackBufferTest, TestCallbackBatching) {
PresentationTimeCallbackBuffer buffer;
buffer.RegisterMainThreadCallbacks(kFrameToken1, GenerateCallbacks(1));
buffer.RegisterMainThreadCallbacks(kFrameToken2, GenerateCallbacks(2));
buffer.RegisterMainThreadCallbacks(kFrameToken4, GenerateCallbacks(2));
{
auto result =
buffer.PopPendingCallbacks(kFrameToken3, false);
EXPECT_EQ(result.main_callbacks.size(), 3ull);
EXPECT_TRUE(result.main_successful_callbacks.empty());
EXPECT_TRUE(result.compositor_successful_callbacks.empty());
}
}
}