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 |