[M120 Migration][MM][CAPI] Fix the logic for media using capi player.
[platform/framework/web/chromium-efl.git] / media / mojo / services / media_service_unittest.cc
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stdint.h>
6
7 #include <memory>
8 #include <tuple>
9 #include <utility>
10
11 #include "base/functional/bind.h"
12 #include "base/functional/callback.h"
13 #include "base/run_loop.h"
14 #include "base/task/single_thread_task_runner.h"
15 #include "base/test/task_environment.h"
16 #include "build/build_config.h"
17 #include "media/base/cdm_config.h"
18 #include "media/base/mock_filters.h"
19 #include "media/base/test_helpers.h"
20 #include "media/cdm/clear_key_cdm_common.h"
21 #include "media/media_buildflags.h"
22 #include "media/mojo/buildflags.h"
23 #include "media/mojo/clients/mojo_decryptor.h"
24 #include "media/mojo/clients/mojo_demuxer_stream_impl.h"
25 #include "media/mojo/common/media_type_converters.h"
26 #include "media/mojo/mojom/content_decryption_module.mojom.h"
27 #include "media/mojo/mojom/decryptor.mojom.h"
28 #include "media/mojo/mojom/interface_factory.mojom.h"
29 #include "media/mojo/mojom/media_service.mojom.h"
30 #include "media/mojo/mojom/renderer.mojom.h"
31 #include "media/mojo/services/media_service_factory.h"
32 #include "mojo/public/cpp/bindings/associated_receiver.h"
33 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
34 #include "mojo/public/cpp/bindings/pending_remote.h"
35 #include "mojo/public/cpp/bindings/remote.h"
36 #include "testing/gmock/include/gmock/gmock.h"
37 #include "testing/gtest/include/gtest/gtest.h"
38 #include "url/gurl.h"
39
40 namespace media {
41
42 namespace {
43
44 using testing::_;
45 using testing::DoAll;
46 using testing::Invoke;
47 using testing::InvokeWithoutArgs;
48 using testing::NiceMock;
49 using testing::SaveArg;
50 using testing::StrictMock;
51 using testing::WithArg;
52
53 MATCHER_P(MatchesResult, success, "") {
54   return arg->success == success;
55 }
56
57 #if BUILDFLAG(ENABLE_MOJO_CDM) && !BUILDFLAG(IS_ANDROID)
58 const char kInvalidKeySystem[] = "invalid.key.system";
59 #endif
60
61 class MockRendererClient : public mojom::RendererClient {
62  public:
63   MockRendererClient() = default;
64
65   MockRendererClient(const MockRendererClient&) = delete;
66   MockRendererClient& operator=(const MockRendererClient&) = delete;
67
68   ~MockRendererClient() override = default;
69
70   // mojom::RendererClient implementation.
71   MOCK_METHOD3(OnTimeUpdate,
72                void(base::TimeDelta time,
73                     base::TimeDelta max_time,
74                     base::TimeTicks capture_time));
75   MOCK_METHOD2(OnBufferingStateChange,
76                void(BufferingState state, BufferingStateChangeReason reason));
77   MOCK_METHOD0(OnEnded, void());
78   MOCK_METHOD1(OnError, void(const PipelineStatus& status));
79   MOCK_METHOD1(OnVideoOpacityChange, void(bool opaque));
80   MOCK_METHOD1(OnAudioConfigChange, void(const AudioDecoderConfig&));
81   MOCK_METHOD1(OnVideoConfigChange, void(const VideoDecoderConfig&));
82   MOCK_METHOD1(OnVideoNaturalSizeChange, void(const gfx::Size& size));
83   MOCK_METHOD1(OnStatisticsUpdate, void(const PipelineStatistics& stats));
84   MOCK_METHOD1(OnWaiting, void(WaitingReason));
85   MOCK_METHOD1(OnDurationChange, void(base::TimeDelta duration));
86   MOCK_METHOD1(OnRemotePlayStateChange, void(MediaStatus::State state));
87 };
88
89 ACTION_P(QuitLoop, run_loop) {
90   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
91       FROM_HERE, run_loop->QuitClosure());
92 }
93
94 // Tests MediaService using TestMojoMediaClient, which supports CDM creation
95 // using DefaultCdmFactory (only supports Clear Key key system), and Renderer
96 // creation using RendererImplFactory that always create RendererImpl.
97 class MediaServiceTest : public testing::Test {
98  public:
99   MediaServiceTest()
100       : renderer_client_receiver_(&renderer_client_),
101         video_stream_(DemuxerStream::VIDEO) {}
102
103   MediaServiceTest(const MediaServiceTest&) = delete;
104   MediaServiceTest& operator=(const MediaServiceTest&) = delete;
105
106   ~MediaServiceTest() override = default;
107
108   void SetUp() override {
109     mojo::PendingRemote<mojom::FrameInterfaceFactory> frame_interfaces;
110     std::ignore = frame_interfaces.InitWithNewPipeAndPassReceiver();
111
112     media_service_impl_ = CreateMediaServiceForTesting(
113         media_service_.BindNewPipeAndPassReceiver());
114     media_service_.set_idle_handler(
115         base::TimeDelta(),
116         base::BindRepeating(&MediaServiceTest::OnMediaServiceIdle,
117                             base::Unretained(this)));
118     media_service_->CreateInterfaceFactory(
119         interface_factory_.BindNewPipeAndPassReceiver(),
120         std::move(frame_interfaces));
121   }
122
123   MOCK_METHOD0(OnCdmConnectionError, void());
124
125   void InitializeCdm(const std::string& key_system, bool expected_result) {
126     interface_factory_->CreateCdm(
127         {key_system, false, false, false},
128         base::BindOnce(&MediaServiceTest::OnCdmCreated, base::Unretained(this),
129                        expected_result));
130     // Run this to idle to complete the CreateCdm call.
131     task_environment_.RunUntilIdle();
132   }
133
134   MOCK_METHOD1(OnRendererInitialized, void(bool));
135
136   void InitializeRenderer(const VideoDecoderConfig& video_config,
137                           bool expected_result) {
138     base::RunLoop run_loop;
139     interface_factory_->CreateDefaultRenderer(
140         std::string(), renderer_.BindNewPipeAndPassReceiver());
141
142     video_stream_.set_video_decoder_config(video_config);
143
144     mojo::PendingRemote<mojom::DemuxerStream> video_stream_proxy;
145     mojo_video_stream_ = std::make_unique<MojoDemuxerStreamImpl>(
146         &video_stream_, video_stream_proxy.InitWithNewPipeAndPassReceiver());
147
148     mojo::PendingAssociatedRemote<mojom::RendererClient> client_remote;
149     renderer_client_receiver_.Bind(
150         client_remote.InitWithNewEndpointAndPassReceiver());
151
152     std::vector<mojo::PendingRemote<mojom::DemuxerStream>> streams;
153     streams.push_back(std::move(video_stream_proxy));
154
155     EXPECT_CALL(*this, OnRendererInitialized(expected_result))
156         .WillOnce(QuitLoop(&run_loop));
157     renderer_->Initialize(
158         std::move(client_remote), std::move(streams), nullptr,
159         base::BindOnce(&MediaServiceTest::OnRendererInitialized,
160                        base::Unretained(this)));
161     run_loop.Run();
162   }
163
164   MOCK_METHOD0(OnMediaServiceIdle, void());
165
166  protected:
167   void OnCdmCreated(bool expected_result,
168                     mojo::PendingRemote<mojom::ContentDecryptionModule> remote,
169                     mojom::CdmContextPtr cdm_context,
170                     const std::string& error_message) {
171     if (!expected_result) {
172       EXPECT_FALSE(remote);
173       EXPECT_FALSE(cdm_context);
174       EXPECT_TRUE(!error_message.empty());
175       return;
176     }
177     EXPECT_TRUE(remote);
178     EXPECT_TRUE(error_message.empty());
179     cdm_.Bind(std::move(remote));
180     cdm_.set_disconnect_handler(base::BindOnce(
181         &MediaServiceTest::OnCdmConnectionError, base::Unretained(this)));
182   }
183   base::test::TaskEnvironment task_environment_;
184
185   mojo::Remote<mojom::MediaService> media_service_;
186   mojo::Remote<mojom::InterfaceFactory> interface_factory_;
187   mojo::Remote<mojom::ContentDecryptionModule> cdm_;
188   mojo::Remote<mojom::Renderer> renderer_;
189
190   std::unique_ptr<MediaService> media_service_impl_;
191
192   NiceMock<MockRendererClient> renderer_client_;
193   mojo::AssociatedReceiver<mojom::RendererClient> renderer_client_receiver_;
194
195   StrictMock<MockDemuxerStream> video_stream_;
196   std::unique_ptr<MojoDemuxerStreamImpl> mojo_video_stream_;
197 };
198
199 }  // namespace
200
201 // Note: base::RunLoop::RunUntilIdle() does not work well in these tests because
202 // even when the loop is idle, we may still have pending events in the pipe.
203 // - If you have an InterfacePtr hosted by the service in the service process,
204 //   you can use InterfacePtr::FlushForTesting(). Note that this doesn't drain
205 //   the task runner in the test process and doesn't cover all negative cases.
206 // - If you expect a callback on an InterfacePtr call or connection error, use
207 //   base::RunLoop::Run() and QuitLoop().
208
209 // TODO(crbug.com/829233): Enable these tests on Android.
210 #if BUILDFLAG(ENABLE_MOJO_CDM) && !BUILDFLAG(IS_ANDROID)
211 TEST_F(MediaServiceTest, InitializeCdm_Success) {
212   InitializeCdm(kClearKeyKeySystem, true);
213 }
214
215 TEST_F(MediaServiceTest, InitializeCdm_InvalidKeySystem) {
216   InitializeCdm(kInvalidKeySystem, false);
217 }
218 #endif  // BUILDFLAG(ENABLE_MOJO_CDM) && !BUILDFLAG(IS_ANDROID)
219
220 #if BUILDFLAG(ENABLE_MOJO_RENDERER)
221 TEST_F(MediaServiceTest, InitializeRenderer) {
222   InitializeRenderer(TestVideoConfig::Normal(), true);
223 }
224 #endif  // BUILDFLAG(ENABLE_MOJO_RENDERER)
225
226 TEST_F(MediaServiceTest, InterfaceFactoryPreventsIdling) {
227   // The service should not idle during this operation.
228   interface_factory_.FlushForTesting();
229
230   // Disconnecting InterfaceFactory will cause the service to idle since there
231   // are no media components hosted and so no other interfaces should be
232   // connected.
233   base::RunLoop run_loop;
234   EXPECT_CALL(*this, OnMediaServiceIdle()).WillOnce(QuitLoop(&run_loop));
235   interface_factory_.reset();
236   run_loop.Run();
237 }
238
239 #if (BUILDFLAG(ENABLE_MOJO_CDM) && !BUILDFLAG(IS_ANDROID)) || \
240     BUILDFLAG(ENABLE_MOJO_RENDERER)
241 // MediaService stays alive as long as there are InterfaceFactory impls, which
242 // are then deferred destroyed until no media components (e.g. CDM or Renderer)
243 // are hosted.
244 TEST_F(MediaServiceTest, Idling) {
245 #if BUILDFLAG(ENABLE_MOJO_CDM) && !BUILDFLAG(IS_ANDROID)
246   InitializeCdm(kClearKeyKeySystem, true);
247 #endif
248
249 #if BUILDFLAG(ENABLE_MOJO_RENDERER)
250   InitializeRenderer(TestVideoConfig::Normal(), true);
251 #endif
252
253   // Disconnecting CDM and Renderer services doesn't terminate MediaService
254   // since |interface_factory_| is still alive.
255   cdm_.reset();
256   renderer_.reset();
257   interface_factory_.FlushForTesting();
258
259   // Disconnecting InterfaceFactory will cause the service to idle since no
260   // other interfaces are connected.
261   base::RunLoop run_loop;
262   EXPECT_CALL(*this, OnMediaServiceIdle()).WillOnce(QuitLoop(&run_loop));
263   interface_factory_.reset();
264   run_loop.Run();
265 }
266
267 TEST_F(MediaServiceTest, MoreIdling) {
268 #if BUILDFLAG(ENABLE_MOJO_CDM) && !BUILDFLAG(IS_ANDROID)
269   InitializeCdm(kClearKeyKeySystem, true);
270 #endif
271
272 #if BUILDFLAG(ENABLE_MOJO_RENDERER)
273   InitializeRenderer(TestVideoConfig::Normal(), true);
274 #endif
275
276   ASSERT_TRUE(cdm_ || renderer_);
277
278   // Disconnecting InterfaceFactory should not terminate the MediaService since
279   // there are still media components (CDM or Renderer) hosted.
280   interface_factory_.reset();
281   if (cdm_)
282     cdm_.FlushForTesting();
283   else if (renderer_)
284     renderer_.FlushForTesting();
285   else
286     NOTREACHED();
287
288   // Disconnecting CDM and Renderer will cause the service to idle since no
289   // other interfaces are connected.
290   base::RunLoop run_loop;
291   EXPECT_CALL(*this, OnMediaServiceIdle()).WillOnce(QuitLoop(&run_loop));
292   cdm_.reset();
293   renderer_.reset();
294   run_loop.Run();
295 }
296 #endif  // (BUILDFLAG(ENABLE_MOJO_CDM) && !BUILDFLAG(IS_ANDROID)) ||
297         //  BUILDFLAG(ENABLE_MOJO_RENDERER)
298
299 }  // namespace media