blob: d7d32901596b52949c220d8f6ba019af7f2754f9 [file] [log] [blame]
// Copyright 2019 The Chromium 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 "third_party/blink/renderer/modules/video_rvfc/video_frame_request_callback_collection.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/testing/null_execution_context.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
using testing::_;
namespace blink {
constexpr double kDefaultTimestamp = 12345.0;
class MockVideoFrameCallback
: public VideoFrameRequestCallbackCollection::VideoFrameCallback {
public:
MOCK_METHOD2(Invoke, void(double, const VideoFrameMetadata*));
};
class VideoFrameRequestCallbackCollectionTest : public PageTestBase {
public:
using CallbackId = int;
VideoFrameRequestCallbackCollectionTest()
: execution_context_(MakeGarbageCollected<NullExecutionContext>()),
collection_(MakeGarbageCollected<VideoFrameRequestCallbackCollection>(
execution_context_.Get())) {}
~VideoFrameRequestCallbackCollectionTest() override {
execution_context_->NotifyContextDestroyed();
}
VideoFrameRequestCallbackCollection* collection() {
return collection_.Get();
}
Persistent<MockVideoFrameCallback> CreateCallback() {
return MakeGarbageCollected<MockVideoFrameCallback>();
}
private:
Persistent<ExecutionContext> execution_context_;
Persistent<VideoFrameRequestCallbackCollection> collection_;
};
TEST_F(VideoFrameRequestCallbackCollectionTest, AddSingleCallback) {
EXPECT_TRUE(collection()->IsEmpty());
auto callback = CreateCallback();
CallbackId id = collection()->RegisterFrameCallback(callback.Get());
EXPECT_EQ(id, callback->Id());
EXPECT_FALSE(collection()->IsEmpty());
}
TEST_F(VideoFrameRequestCallbackCollectionTest, InvokeSingleCallback) {
auto* metadata = VideoFrameMetadata::Create();
auto callback = CreateCallback();
collection()->RegisterFrameCallback(callback.Get());
EXPECT_CALL(*callback, Invoke(kDefaultTimestamp, metadata));
collection()->ExecuteFrameCallbacks(kDefaultTimestamp, metadata);
EXPECT_TRUE(collection()->IsEmpty());
}
TEST_F(VideoFrameRequestCallbackCollectionTest, CancelSingleCallback) {
auto callback = CreateCallback();
CallbackId id = collection()->RegisterFrameCallback(callback.Get());
EXPECT_FALSE(callback->IsCancelled());
// The callback should not be invoked.
EXPECT_CALL(*callback, Invoke(_, _)).Times(0);
// Cancelling an non existent ID should do nothing.
collection()->CancelFrameCallback(id + 100);
EXPECT_FALSE(collection()->IsEmpty());
EXPECT_FALSE(callback->IsCancelled());
// Cancel the callback this time.
collection()->CancelFrameCallback(id);
EXPECT_TRUE(collection()->IsEmpty());
collection()->ExecuteFrameCallbacks(kDefaultTimestamp,
VideoFrameMetadata::Create());
EXPECT_TRUE(collection()->IsEmpty());
}
TEST_F(VideoFrameRequestCallbackCollectionTest, ExecuteMultipleCallbacks) {
auto callback_1 = CreateCallback();
collection()->RegisterFrameCallback(callback_1.Get());
auto callback_2 = CreateCallback();
collection()->RegisterFrameCallback(callback_2.Get());
EXPECT_CALL(*callback_1, Invoke(_, _));
EXPECT_CALL(*callback_2, Invoke(_, _));
collection()->ExecuteFrameCallbacks(kDefaultTimestamp,
VideoFrameMetadata::Create());
// All callbacks should have been executed and removed.
EXPECT_TRUE(collection()->IsEmpty());
}
TEST_F(VideoFrameRequestCallbackCollectionTest, CreateCallbackDuringExecution) {
Persistent<MockVideoFrameCallback> created_callback;
CallbackId created_id = 0;
auto callback = CreateCallback();
EXPECT_CALL(*callback, Invoke(_, _))
.WillOnce(testing::WithoutArgs(testing::Invoke([&]() {
created_callback = CreateCallback();
created_id =
collection()->RegisterFrameCallback(created_callback.Get());
EXPECT_CALL(*created_callback, Invoke(_, _)).Times(0);
})));
collection()->RegisterFrameCallback(callback.Get());
collection()->ExecuteFrameCallbacks(kDefaultTimestamp,
VideoFrameMetadata::Create());
EXPECT_NE(created_id, 0);
EXPECT_FALSE(collection()->IsEmpty());
// The created callback should be executed the second time around.
EXPECT_CALL(*created_callback, Invoke(_, _)).Times(1);
collection()->ExecuteFrameCallbacks(kDefaultTimestamp,
VideoFrameMetadata::Create());
EXPECT_TRUE(collection()->IsEmpty());
}
TEST_F(VideoFrameRequestCallbackCollectionTest, CancelCallbackDuringExecution) {
auto dummy_callback = CreateCallback();
CallbackId dummy_callback_id =
collection()->RegisterFrameCallback(dummy_callback.Get());
// This is a hacky way of simulating a callback being cancelled mid-execution.
// We guess the ID of the 3rd callback, since (as an implementation detail)
// CallbackIds are distributed sequentially.
int expected_target_id = dummy_callback_id + 2;
auto cancelling_callback = CreateCallback();
EXPECT_CALL(*cancelling_callback, Invoke(_, _))
.WillOnce(testing::WithoutArgs(testing::Invoke(
[&]() { collection()->CancelFrameCallback(expected_target_id); })));
collection()->RegisterFrameCallback(cancelling_callback.Get());
auto target_callback = CreateCallback();
CallbackId target_callback_id =
collection()->RegisterFrameCallback(target_callback.Get());
EXPECT_CALL(*target_callback, Invoke(_, _)).Times(0);
EXPECT_EQ(expected_target_id, target_callback_id);
collection()->ExecuteFrameCallbacks(kDefaultTimestamp,
VideoFrameMetadata::Create());
// Everything should have been cleared
EXPECT_TRUE(collection()->IsEmpty());
}
} // namespace blink