Revert "[M120 Migration]Fix for crash during chrome exit"
[platform/framework/web/chromium-efl.git] / media / filters / decrypting_media_resource_unittest.cc
1 // Copyright 2018 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 <memory>
6 #include <string>
7 #include <vector>
8
9 #include "base/functional/bind.h"
10 #include "base/functional/callback_helpers.h"
11 #include "base/test/gmock_callback_support.h"
12 #include "base/test/mock_callback.h"
13 #include "base/test/task_environment.h"
14 #include "media/base/decoder_buffer.h"
15 #include "media/base/decrypt_config.h"
16 #include "media/base/decryptor.h"
17 #include "media/base/demuxer_stream.h"
18 #include "media/base/media_util.h"
19 #include "media/base/mock_filters.h"
20 #include "media/base/pipeline_status.h"
21 #include "media/base/test_helpers.h"
22 #include "media/filters/decrypting_demuxer_stream.h"
23 #include "media/filters/decrypting_media_resource.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25
26 using ::base::test::RunCallback;
27 using ::base::test::RunOnceCallback;
28 using ::testing::_;
29 using ::testing::AnyNumber;
30 using ::testing::Invoke;
31 using ::testing::Return;
32 using ::testing::StrictMock;
33
34 namespace media {
35
36 static constexpr int kFakeBufferSize = 16;
37 static constexpr char kFakeKeyId[] = "Key ID";
38 static constexpr char kFakeIv[] = "0123456789abcdef";
39
40 // Use anonymous namespace here to prevent the actions to be defined multiple
41 // times across multiple test files. Sadly we can't use static for them.
42 namespace {
43
44 ACTION_P(ReturnBuffer, buffer) {
45   std::move(arg0).Run(
46       buffer.get() ? DemuxerStream::kOk : DemuxerStream::kAborted, {buffer});
47 }
48
49 }  // namespace
50
51 class DecryptingMediaResourceTest : public testing::Test {
52  public:
53   DecryptingMediaResourceTest() {
54     encrypted_buffer_ = base::MakeRefCounted<DecoderBuffer>(kFakeBufferSize);
55     encrypted_buffer_->set_decrypt_config(
56         DecryptConfig::CreateCencConfig(kFakeKeyId, kFakeIv, {}));
57
58     EXPECT_CALL(cdm_context_, RegisterEventCB(_)).Times(AnyNumber());
59     EXPECT_CALL(cdm_context_, GetDecryptor())
60         .WillRepeatedly(Return(&decryptor_));
61     EXPECT_CALL(decryptor_, CanAlwaysDecrypt()).WillRepeatedly(Return(true));
62     EXPECT_CALL(decryptor_, CancelDecrypt(_)).Times(AnyNumber());
63     EXPECT_CALL(demuxer_, GetAllStreams())
64         .WillRepeatedly(
65             Invoke(this, &DecryptingMediaResourceTest::GetAllStreams));
66
67     decrypting_media_resource_ = std::make_unique<DecryptingMediaResource>(
68         &demuxer_, &cdm_context_, &null_media_log_,
69         task_environment_.GetMainThreadTaskRunner());
70   }
71
72   ~DecryptingMediaResourceTest() override {
73     // Ensure that the DecryptingMediaResource is destructed before other
74     // objects that it internally references but does not own.
75     decrypting_media_resource_.reset();
76   }
77
78   bool HasEncryptedStream() {
79     for (auto* stream : decrypting_media_resource_->GetAllStreams()) {
80       if ((stream->type() == DemuxerStream::AUDIO &&
81            stream->audio_decoder_config().is_encrypted()) ||
82           (stream->type() == DemuxerStream::VIDEO &&
83            stream->video_decoder_config().is_encrypted()))
84         return true;
85     }
86
87     return false;
88   }
89
90   void AddStream(DemuxerStream::Type type, bool encrypted) {
91     streams_.push_back(CreateMockDemuxerStream(type, encrypted));
92   }
93
94   std::vector<DemuxerStream*> GetAllStreams() {
95     std::vector<DemuxerStream*> streams;
96
97     for (auto& stream : streams_) {
98       streams.push_back(stream.get());
99     }
100
101     return streams;
102   }
103
104   MOCK_METHOD2(BufferReady,
105                void(DemuxerStream::Status, DemuxerStream::DecoderBufferVector));
106
107  protected:
108   base::test::TaskEnvironment task_environment_;
109   base::MockCallback<DecryptingMediaResource::InitCB>
110       decrypting_media_resource_init_cb_;
111   base::MockCallback<WaitingCB> waiting_cb_;
112   NullMediaLog null_media_log_;
113   StrictMock<MockDecryptor> decryptor_;
114   StrictMock<MockDemuxer> demuxer_;
115   StrictMock<MockCdmContext> cdm_context_;
116   std::unique_ptr<DecryptingMediaResource> decrypting_media_resource_;
117   std::vector<std::unique_ptr<StrictMock<MockDemuxerStream>>> streams_;
118
119   // Constant buffer to be returned by the input demuxer streams and
120   // |decryptor_|.
121   scoped_refptr<DecoderBuffer> encrypted_buffer_;
122 };
123
124 TEST_F(DecryptingMediaResourceTest, ClearStreams) {
125   AddStream(DemuxerStream::AUDIO, /* encrypted = */ false);
126   AddStream(DemuxerStream::VIDEO, /* encrypted = */ false);
127
128   EXPECT_CALL(decrypting_media_resource_init_cb_, Run(true));
129
130   decrypting_media_resource_->Initialize(
131       decrypting_media_resource_init_cb_.Get(), waiting_cb_.Get());
132   task_environment_.RunUntilIdle();
133
134   EXPECT_EQ(
135       decrypting_media_resource_->DecryptingDemuxerStreamCountForTesting(), 2);
136   EXPECT_FALSE(HasEncryptedStream());
137 }
138
139 TEST_F(DecryptingMediaResourceTest, EncryptedStreams) {
140   AddStream(DemuxerStream::AUDIO, /* encrypted = */ true);
141   AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
142
143   EXPECT_CALL(decrypting_media_resource_init_cb_, Run(true));
144
145   decrypting_media_resource_->Initialize(
146       decrypting_media_resource_init_cb_.Get(), waiting_cb_.Get());
147   task_environment_.RunUntilIdle();
148
149   // When using an AesDecryptor we preemptively wrap our streams with a
150   // DecryptingDemuxerStream, regardless of encryption. With this in mind, we
151   // should have three DecryptingDemuxerStreams.
152   EXPECT_EQ(
153       decrypting_media_resource_->DecryptingDemuxerStreamCountForTesting(), 2);
154
155   // All of the streams that we get from our DecryptingMediaResource, NOT the
156   // internal MediaResource implementation, should be clear.
157   EXPECT_FALSE(HasEncryptedStream());
158 }
159
160 TEST_F(DecryptingMediaResourceTest, MixedStreams) {
161   AddStream(DemuxerStream::AUDIO, /* encrypted = */ false);
162   AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
163
164   EXPECT_CALL(decrypting_media_resource_init_cb_, Run(true));
165
166   decrypting_media_resource_->Initialize(
167       decrypting_media_resource_init_cb_.Get(), waiting_cb_.Get());
168   task_environment_.RunUntilIdle();
169
170   EXPECT_EQ(
171       decrypting_media_resource_->DecryptingDemuxerStreamCountForTesting(), 2);
172   EXPECT_FALSE(HasEncryptedStream());
173 }
174
175 TEST_F(DecryptingMediaResourceTest,
176        OneDecryptingDemuxerStreamFailsInitialization) {
177   AddStream(DemuxerStream::AUDIO, /* encrypted = */ false);
178   AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
179
180   // The first DecryptingDemuxerStream will fail to initialize, causing the
181   // callback to be run with a value of false. The second
182   // DecryptingDemuxerStream will succeed but never invoke the callback.
183   EXPECT_CALL(cdm_context_, GetDecryptor())
184       .WillOnce(Return(nullptr))
185       .WillRepeatedly(Return(&decryptor_));
186   EXPECT_CALL(decrypting_media_resource_init_cb_, Run(false));
187
188   decrypting_media_resource_->Initialize(
189       decrypting_media_resource_init_cb_.Get(), waiting_cb_.Get());
190   task_environment_.RunUntilIdle();
191 }
192
193 TEST_F(DecryptingMediaResourceTest,
194        BothDecryptingDemuxerStreamsFailInitialization) {
195   AddStream(DemuxerStream::AUDIO, /* encrypted = */ false);
196   AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
197
198   // Both DecryptingDemuxerStreams will fail to initialize but the callback
199   // should still only be invoked a single time.
200   EXPECT_CALL(cdm_context_, GetDecryptor()).WillRepeatedly(Return(nullptr));
201   EXPECT_CALL(decrypting_media_resource_init_cb_, Run(false));
202
203   decrypting_media_resource_->Initialize(
204       decrypting_media_resource_init_cb_.Get(), waiting_cb_.Get());
205   task_environment_.RunUntilIdle();
206 }
207
208 TEST_F(DecryptingMediaResourceTest, WaitingCallback) {
209   AddStream(DemuxerStream::VIDEO, /* encrypted = */ true);
210
211   EXPECT_CALL(*streams_.front(), OnRead(_))
212       .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
213   EXPECT_CALL(decryptor_, Decrypt(_, encrypted_buffer_, _))
214       .WillRepeatedly(RunOnceCallback<2>(Decryptor::kNoKey,
215                                          scoped_refptr<DecoderBuffer>()));
216   EXPECT_CALL(decrypting_media_resource_init_cb_, Run(true));
217   EXPECT_CALL(waiting_cb_, Run(WaitingReason::kNoDecryptionKey));
218
219   decrypting_media_resource_->Initialize(
220       decrypting_media_resource_init_cb_.Get(), waiting_cb_.Get());
221   decrypting_media_resource_->GetAllStreams().front()->Read(
222       1, base::BindOnce(&DecryptingMediaResourceTest::BufferReady,
223                         base::Unretained(this)));
224   task_environment_.RunUntilIdle();
225 }
226
227 }  // namespace media