| Index: media/gpu/avda_overlay_helper_impl_unittest.cc
|
| diff --git a/media/gpu/avda_overlay_helper_impl_unittest.cc b/media/gpu/avda_overlay_helper_impl_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8a128cf6e5fcb73f0ff78b942bf2cffd271eeec2
|
| --- /dev/null
|
| +++ b/media/gpu/avda_overlay_helper_impl_unittest.cc
|
| @@ -0,0 +1,306 @@
|
| +// Copyright 2017 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 "media/gpu/avda_overlay_helper_impl.h"
|
| +
|
| +#include <stdint.h>
|
| +
|
| +#include <memory>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/logging.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "media/base/android/android_overlay_factory.h"
|
| +#include "media/base/android/mock_android_overlay.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +using ::testing::_;
|
| +using ::testing::AnyNumber;
|
| +using ::testing::NiceMock;
|
| +using ::testing::NotNull;
|
| +using ::testing::Return;
|
| +using ::testing::StrictMock;
|
| +
|
| +namespace media {
|
| +
|
| +// Unit tests for AVDAOverlayHelperImpl
|
| +class AVDAOverlayHelperImplTest : public testing::Test {
|
| + public:
|
| + class MockClient {
|
| + public:
|
| + MOCK_METHOD1(UseOverlay, void(AndroidOverlay*));
|
| +
|
| + void UseOverlayImpl(std::unique_ptr<AndroidOverlay> overlay) {
|
| + UseOverlay(overlay.get());
|
| +
|
| + // Also take ownership of the overlay, so that it's not destroyed.
|
| + overlay_ = std::move(overlay);
|
| + }
|
| +
|
| + // Note that this won't clear |overlay_|, which is helpful. One might argue
|
| + // that we should drop it, and provide a separate TakeOverlay() method to
|
| + // hand off ownership to the caller.
|
| + MOCK_METHOD0(UseSurfaceTexture, void(void));
|
| + MOCK_METHOD1(StopUsingOverlayImmediately, void(AndroidOverlay*));
|
| +
|
| + private:
|
| + std::unique_ptr<AndroidOverlay> overlay_;
|
| + };
|
| +
|
| + // Mock factory which will return one overlay.
|
| + class MockAndroidOverlayFactory : public AndroidOverlayFactory {
|
| + public:
|
| + MockAndroidOverlayFactory()
|
| + : overlay_(base::MakeUnique<MockAndroidOverlay>()),
|
| + overlay_weak_(overlay_->GetWeakPtr()),
|
| + weak_this_factory_(this) {}
|
| +
|
| + // Called by CreateOverlay.
|
| + MOCK_METHOD0(MockCreateOverlay, void());
|
| +
|
| + std::unique_ptr<AndroidOverlay> CreateOverlay(
|
| + const AndroidOverlay::Config& config) override {
|
| + MockCreateOverlay();
|
| +
|
| + // Notify the overlay about the config that was used to create it. We
|
| + // can't do this during overlay construction since we might want the
|
| + // overlay to set test expectations.
|
| + if (overlay_)
|
| + overlay_->SetConfig(config);
|
| +
|
| + most_recent_config_ = config;
|
| + return std::move(overlay_);
|
| + }
|
| +
|
| + // Return a weak ptr to the overlay that we will / did create.
|
| + base::WeakPtr<MockAndroidOverlay> overlay() { return overlay_weak_; }
|
| +
|
| + // Return the most recent config that we were given during CreateOverlay.
|
| + AndroidOverlay::Config& most_recent_config() { return most_recent_config_; }
|
| +
|
| + // Set the overlay that we'll provide next, or nullptr.
|
| + void SetOverlay(std::unique_ptr<MockAndroidOverlay> overlay) {
|
| + overlay_ = std::move(overlay);
|
| + if (overlay_)
|
| + overlay_weak_ = overlay_->GetWeakPtr();
|
| + else
|
| + overlay_weak_ = nullptr;
|
| + }
|
| +
|
| + base::WeakPtr<MockAndroidOverlayFactory> GetWeakPtr() {
|
| + return weak_this_factory_.GetWeakPtr();
|
| + }
|
| +
|
| + // Shorthand for overlay()->On*() callbacks.
|
| + void OnOverlayReady() { overlay()->OnOverlayReady(); }
|
| +
|
| + void OnOverlayFailed() { overlay()->OnOverlayFailed(); }
|
| +
|
| + void OnSurfaceDestroyed() { overlay()->OnSurfaceDestroyed(); }
|
| +
|
| + private:
|
| + AndroidOverlay::Config most_recent_config_;
|
| + std::unique_ptr<MockAndroidOverlay> overlay_;
|
| + base::WeakPtr<MockAndroidOverlay> overlay_weak_;
|
| +
|
| + base::WeakPtrFactory<MockAndroidOverlayFactory> weak_this_factory_;
|
| + };
|
| +
|
| + ~AVDAOverlayHelperImplTest() override {}
|
| +
|
| + void SetUp() override {
|
| + helper_ = base::MakeUnique<AVDAOverlayHelperImpl>();
|
| + factory_ = base::MakeUnique<StrictMock<MockAndroidOverlayFactory>>();
|
| + factory_weak_ = factory_->GetWeakPtr();
|
| + }
|
| +
|
| + void StartHelper(std::unique_ptr<MockAndroidOverlayFactory> factory) {
|
| + helper_->Startup(
|
| + base::Bind(&MockClient::UseOverlayImpl, base::Unretained(&client_)),
|
| + base::Bind(&MockClient::UseSurfaceTexture, base::Unretained(&client_)),
|
| + base::Bind(&MockClient::StopUsingOverlayImmediately,
|
| + base::Unretained(&client_)),
|
| + std::move(factory));
|
| + }
|
| +
|
| + std::unique_ptr<AVDAOverlayHelperImpl> helper_;
|
| + StrictMock<MockClient> client_;
|
| + std::unique_ptr<StrictMock<MockAndroidOverlayFactory>> factory_;
|
| + base::WeakPtr<MockAndroidOverlayFactory> factory_weak_;
|
| +};
|
| +
|
| +TEST_F(AVDAOverlayHelperImplTest, StartupWithoutFactoryUsesSurfaceTexture) {
|
| + // Calling Startup() with no factory should result in a callback to use
|
| + // surface texture.
|
| + EXPECT_CALL(client_, UseSurfaceTexture());
|
| + StartHelper(nullptr);
|
| +}
|
| +
|
| +TEST_F(AVDAOverlayHelperImplTest, ProvideInitialOverlaySuccessfully) {
|
| + // Providing a factory at startup should result in a switch to overlay. It
|
| + // should not switch to SurfaceTexture initially, since pre-M requires it.
|
| + // Note that post-M (especially DS), it might be fine to start with ST. We
|
| + // just don't differentiate those cases yet in the impl.
|
| +
|
| + // Initially, there should be no callback into |client_|, since we haven't
|
| + // told |helper_| that the overlay is ready. It should, however, request the
|
| + // overlay from |factory_|.
|
| + EXPECT_CALL(*factory_, MockCreateOverlay());
|
| + StartHelper(std::move(factory_));
|
| +
|
| + // |factory_| should not have been deleted
|
| + ASSERT_TRUE(factory_weak_ != nullptr);
|
| +
|
| + testing::Mock::VerifyAndClearExpectations(&client_);
|
| + testing::Mock::VerifyAndClearExpectations(factory_weak_.get());
|
| +
|
| + // Notify the factory that the overlay is ready. Expect that |client_| will
|
| + // be told to use it.
|
| + EXPECT_CALL(client_, UseOverlay(factory_weak_->overlay().get()));
|
| + factory_weak_->OnOverlayReady();
|
| +}
|
| +
|
| +TEST_F(AVDAOverlayHelperImplTest, NullInitialOverlayUsesSurfaceTexture) {
|
| + // If we provide a factory, but it fails to create an overlay, then |client_|
|
| + // should be notified to use a surface texture.
|
| +
|
| + EXPECT_CALL(*factory_, MockCreateOverlay());
|
| + EXPECT_CALL(client_, UseSurfaceTexture());
|
| + factory_->SetOverlay(nullptr);
|
| + StartHelper(std::move(factory_));
|
| +}
|
| +
|
| +TEST_F(AVDAOverlayHelperImplTest, FailedInitialOverlayUsesSurfaceTexture) {
|
| + // If we provide a factory, but the overlay that it provides returns 'failed',
|
| + // then |client_| should use surface texture.
|
| + EXPECT_CALL(*factory_, MockCreateOverlay());
|
| + StartHelper(std::move(factory_));
|
| +
|
| + testing::Mock::VerifyAndClearExpectations(&client_);
|
| + testing::Mock::VerifyAndClearExpectations(factory_weak_.get());
|
| +
|
| + EXPECT_CALL(client_, UseSurfaceTexture());
|
| + factory_weak_->OnOverlayFailed();
|
| +}
|
| +
|
| +TEST_F(AVDAOverlayHelperImplTest, OnSurfaceDestroyedSendsNotification) {
|
| + // If |helper_| is notified about OnSurfaceDestroyed, then |client_| should
|
| + // also be notified.
|
| +
|
| + EXPECT_CALL(*factory_, MockCreateOverlay());
|
| + StartHelper(std::move(factory_));
|
| + EXPECT_CALL(client_, UseOverlay(factory_weak_->overlay().get()));
|
| + factory_weak_->OnOverlayReady();
|
| +
|
| + testing::Mock::VerifyAndClearExpectations(&client_);
|
| + testing::Mock::VerifyAndClearExpectations(factory_weak_.get());
|
| +
|
| + EXPECT_CALL(client_, UseSurfaceTexture());
|
| + base::WeakPtr<MockAndroidOverlay> overlay = factory_weak_->overlay();
|
| + helper_->OnOverlayFactory(nullptr);
|
| + testing::Mock::VerifyAndClearExpectations(&client_);
|
| +
|
| + EXPECT_CALL(client_, StopUsingOverlayImmediately(overlay.get()));
|
| + overlay->OnSurfaceDestroyed();
|
| +}
|
| +
|
| +TEST_F(AVDAOverlayHelperImplTest,
|
| + OnSurfaceDestroyedSendsNotificationAfterSwitch) {
|
| + // This tests two things. First:
|
| + // If |helper_| is notified about OnSurfaceDestroyed, then |client_| should
|
| + // also be notified even if |helper_| has already told |client_| to transition
|
| + // to SurfaceTexture. It has no idea if |client_| has actually transitioned,
|
| + // so it has to notify it to stop immediately, in case it hasn't.
|
| + // Second:
|
| + // |helper_| should notify |client_| to switch to surface texture if it
|
| + // provided an overlay, and the factory is changed. This indicates that
|
| + // whoever provided the factory is revoking it, so we shouldn't be using
|
| + // overlays from that factory anymore.
|
| + // We specifically test overlay => no factory, since |helper_| could elide
|
| + // multiple calls to switch to surface texture.
|
| + //
|
| + // We test these together, since switching the factory is the only way we have
|
| + // to make |helper_| transition to SurfaceTexture without sending destroyed.
|
| +
|
| + EXPECT_CALL(*factory_, MockCreateOverlay());
|
| + StartHelper(std::move(factory_));
|
| + EXPECT_CALL(client_, UseOverlay(factory_weak_->overlay().get()));
|
| + factory_weak_->OnOverlayReady();
|
| +
|
| + testing::Mock::VerifyAndClearExpectations(&client_);
|
| + testing::Mock::VerifyAndClearExpectations(factory_weak_.get());
|
| +
|
| + // Switch factories, to notify the client back to switch to SurfaceTexture.
|
| + // We save the overlay ptr, since |factory_weak_| may be destroyed.
|
| + EXPECT_CALL(client_, UseSurfaceTexture());
|
| + base::WeakPtr<MockAndroidOverlay> overlay = factory_weak_->overlay();
|
| + helper_->OnOverlayFactory(nullptr);
|
| + testing::Mock::VerifyAndClearExpectations(&client_);
|
| +
|
| + // Destroy the original surface.
|
| + EXPECT_CALL(client_, StopUsingOverlayImmediately(overlay.get()));
|
| + overlay->OnSurfaceDestroyed();
|
| +}
|
| +
|
| +TEST_F(AVDAOverlayHelperImplTest, NullLaterOverlayUsesSurfaceTexture) {
|
| + // If an overlay factory is provided after startup that returns a null overlay
|
| + // from CreateOverlay, |helper_| should, at most, notify |client_| to use
|
| + // SurfaceTexture zero or more times.
|
| +
|
| + // Start with SurfaceTexture.
|
| + EXPECT_CALL(client_, UseSurfaceTexture());
|
| + StartHelper(nullptr);
|
| + testing::Mock::VerifyAndClearExpectations(&client_);
|
| +
|
| + // Provide a factory that will return a null overlay.
|
| + EXPECT_CALL(*factory_, MockCreateOverlay());
|
| + EXPECT_CALL(client_, UseSurfaceTexture()).Times(AnyNumber());
|
| + helper_->OnOverlayFactory(std::move(factory_));
|
| + factory_weak_->SetOverlay(nullptr);
|
| +}
|
| +
|
| +TEST_F(AVDAOverlayHelperImplTest, FailedLaterOverlayDoesNothing) {
|
| + // If we send an overlay factory that returns an overlay, and that overlay
|
| + // fails, then the client should not be notified except for zero or more
|
| + // callbacks to switch to surface texture.
|
| +
|
| + // Start with SurfaceTexture.
|
| + EXPECT_CALL(client_, UseSurfaceTexture());
|
| + StartHelper(nullptr);
|
| + testing::Mock::VerifyAndClearExpectations(&client_);
|
| +
|
| + // Provide a factory.
|
| + EXPECT_CALL(*factory_, MockCreateOverlay());
|
| + EXPECT_CALL(client_, UseSurfaceTexture()).Times(AnyNumber());
|
| + helper_->OnOverlayFactory(std::move(factory_));
|
| + testing::Mock::VerifyAndClearExpectations(&client_);
|
| +
|
| + // Fail the overlay.
|
| + factory_weak_->OnOverlayFailed();
|
| +}
|
| +
|
| +TEST_F(AVDAOverlayHelperImplTest, SuccessfulLaterOverlayNotifiesClient) {
|
| + // |client_| is notified if we provide a factory that gets an overlay.
|
| +
|
| + // Start with SurfaceTexture.
|
| + EXPECT_CALL(client_, UseSurfaceTexture());
|
| + StartHelper(nullptr);
|
| + testing::Mock::VerifyAndClearExpectations(&client_);
|
| +
|
| + // Provide a factory. |helper_| should try to create an overlay. We don't
|
| + // care if a call to UseSurfaceTexture is elided or not. Note that AVDA will
|
| + // ignore duplicate calls anyway (MultipleSurfaceTextureCallbacksAreIgnored).
|
| + EXPECT_CALL(*factory_, MockCreateOverlay());
|
| + EXPECT_CALL(client_, UseSurfaceTexture()).Times(AnyNumber());
|
| + helper_->OnOverlayFactory(std::move(factory_));
|
| + testing::Mock::VerifyAndClearExpectations(&client_);
|
| + testing::Mock::VerifyAndClearExpectations(factory_weak_.get());
|
| +
|
| + // Notify |helper_| that the overlay is ready.
|
| + EXPECT_CALL(client_, UseOverlay(factory_weak_->overlay().get()));
|
| + factory_weak_->OnOverlayReady();
|
| +}
|
| +
|
| +} // namespace media
|
|
|