| 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..10e8e9a0ba91a7786eab460ef5c1fe6ccd0a71f5
|
| --- /dev/null
|
| +++ b/media/gpu/avda_overlay_helper_impl_unittest.cc
|
| @@ -0,0 +1,320 @@
|
| +// 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>()),
|
| + 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);
|
| +
|
| + return std::move(overlay_);
|
| + }
|
| +
|
| + // Return the overlay, if we still own it. One the client creates an
|
| + // overlay, we'll re-assign ownership.
|
| + MockAndroidOverlay* overlay() { return overlay_.get(); }
|
| +
|
| + // Set the overlay that we'll provide next, or nullptr.
|
| + void SetOverlay(std::unique_ptr<MockAndroidOverlay> overlay) {
|
| + overlay_ = std::move(overlay);
|
| + }
|
| +
|
| + base::WeakPtr<MockAndroidOverlayFactory> GetWeakPtr() {
|
| + return weak_this_factory_.GetWeakPtr();
|
| + }
|
| +
|
| + private:
|
| + std::unique_ptr<MockAndroidOverlay> overlay_;
|
| +
|
| + base::WeakPtrFactory<MockAndroidOverlayFactory> weak_this_factory_;
|
| + };
|
| +
|
| + ~AVDAOverlayHelperImplTest() override {}
|
| +
|
| + void SetUp() override {
|
| + helper_ = base::MakeUnique<AVDAOverlayHelperImpl>();
|
| + factory_ = base::MakeUnique<StrictMock<MockAndroidOverlayFactory>>();
|
| + factory_weak_ = factory_->GetWeakPtr();
|
| +
|
| + overlay_callbacks_ = factory_->overlay()->GetCallbacks();
|
| + }
|
| +
|
| + void StartHelper(std::unique_ptr<MockAndroidOverlayFactory> factory) {
|
| + // Before we hand off the factory (and the overlay with it), get the
|
| + // callbacks to control the overlay.
|
| + if (factory && factory->overlay()) {
|
| + // By default, destruction of the overlay is not okay.
|
| + destruction_observer_ = factory->overlay()->CreateDestructionObserver();
|
| + }
|
| +
|
| + 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));
|
| + }
|
| +
|
| + // Verify that the overlay hasn't been destroyed yet, and set an expectation
|
| + // that it will be.
|
| + void ExpectOverlayDestruction() {
|
| + VerifyDestructionObserver();
|
| + EXPECT_CALL(*destruction_observer_, OnOverlayDestroyed());
|
| + }
|
| +
|
| + // If called without setting expectations, then this verifies that the overlay
|
| + // has not been destroyed.
|
| + void VerifyDestructionObserver() {
|
| + testing::Mock::VerifyAndClearExpectations(destruction_observer_.get());
|
| + }
|
| +
|
| + std::unique_ptr<AVDAOverlayHelperImpl> helper_;
|
| + StrictMock<MockClient> client_;
|
| + std::unique_ptr<StrictMock<MockAndroidOverlayFactory>> factory_;
|
| + base::WeakPtr<MockAndroidOverlayFactory> factory_weak_;
|
| +
|
| + // Callbacks to control the overlay that will be vended by |factory_|
|
| + MockAndroidOverlay::Callbacks overlay_callbacks_;
|
| +
|
| + std::unique_ptr<MockAndroidOverlay::DestructionObserver>
|
| + destruction_observer_;
|
| +};
|
| +
|
| +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 helper that the overlay is ready. Expect that |client_| will
|
| + // be told to use it.
|
| + EXPECT_CALL(client_, UseOverlay(NotNull()));
|
| + overlay_callbacks_.OverlayReady.Run();
|
| +
|
| + // The overlay should be destroyed during cleanup, but not before now.
|
| + VerifyDestructionObserver();
|
| +}
|
| +
|
| +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());
|
| +
|
| + // The overlay may be destroyed at any time after we send OverlayFailed.
|
| + ExpectOverlayDestruction();
|
| + EXPECT_CALL(client_, UseSurfaceTexture());
|
| + overlay_callbacks_.OverlayFailed.Run();
|
| +}
|
| +
|
| +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(NotNull()));
|
| + overlay_callbacks_.OverlayReady.Run();
|
| +
|
| + testing::Mock::VerifyAndClearExpectations(&client_);
|
| + testing::Mock::VerifyAndClearExpectations(factory_weak_.get());
|
| +
|
| + // Switch to a surface texture. OnSurfaceDestroyed should still be sent.
|
| + EXPECT_CALL(client_, UseSurfaceTexture());
|
| + helper_->OnOverlayFactory(nullptr);
|
| + testing::Mock::VerifyAndClearExpectations(&client_);
|
| +
|
| + EXPECT_CALL(client_, StopUsingOverlayImmediately(NotNull()));
|
| + overlay_callbacks_.SurfaceDestroyed.Run();
|
| +}
|
| +
|
| +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(NotNull()));
|
| + overlay_callbacks_.OverlayReady.Run();
|
| +
|
| + testing::Mock::VerifyAndClearExpectations(&client_);
|
| + testing::Mock::VerifyAndClearExpectations(factory_weak_.get());
|
| +
|
| + // Switch factories, to notify the client back to switch to SurfaceTexture.
|
| + EXPECT_CALL(client_, UseSurfaceTexture());
|
| + helper_->OnOverlayFactory(nullptr);
|
| + testing::Mock::VerifyAndClearExpectations(&client_);
|
| +
|
| + // Destroy the original surface.
|
| + EXPECT_CALL(client_, StopUsingOverlayImmediately(NotNull()));
|
| + overlay_callbacks_.SurfaceDestroyed.Run();
|
| +}
|
| +
|
| +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.
|
| + overlay_callbacks_.OverlayFailed.Run();
|
| +}
|
| +
|
| +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(NotNull()));
|
| + overlay_callbacks_.OverlayReady.Run();
|
| +}
|
| +
|
| +} // namespace media
|
|
|