[M120 Migration][hbbtv] Audio tracks count notification
[platform/framework/web/chromium-efl.git] / media / filters / hls_vod_rendition_unittest.cc
1 // Copyright 2023 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 "media/filters/hls_vod_rendition.h"
6 #include "base/test/gmock_callback_support.h"
7 #include "base/test/task_environment.h"
8 #include "media/base/test_helpers.h"
9 #include "media/filters/hls_test_helpers.h"
10
11 namespace media {
12
13 namespace {
14
15 constexpr char kInitialFetchVodPlaylist[] =
16     "#EXTM3U\n"
17     "#EXT-X-VERSION:3\n"
18     "#EXT-X-TARGETDURATION:2\n"
19     "#EXT-X-MEDIA-SEQUENCE:14551245\n"
20     "#EXTINF:2.00000,\n"
21     "playlist_4500Kb_14551245.ts\n"
22     "#EXTINF:2.00000,\n"
23     "playlist_4500Kb_14551246.ts\n"
24     "#EXTINF:2.00000,\n"
25     "playlist_4500Kb_14551247.ts\n"
26     "#EXTINF:2.00000,\n"
27     "playlist_4500Kb_14551248.ts\n"
28     "#EXTINF:2.00000,\n"
29     "playlist_4500Kb_14551249.ts\n"
30     "#EXTINF:2.00000,\n"
31     "playlist_4500Kb_14551250.ts\n"
32     "#EXTINF:2.00000,\n"
33     "playlist_4500Kb_14551251.ts\n"
34     "#EXTINF:2.00000,\n"
35     "playlist_4500Kb_14551252.ts\n"
36     "#EXTINF:2.00000,\n"
37     "playlist_4500Kb_14551253.ts\n"
38     "#EXTINF:2.00000,\n"
39     "playlist_4500Kb_14551254.ts\n";
40
41 }  // namespace
42
43 using testing::_;
44 using testing::Return;
45
46 class HlsVodRenditionUnittest : public testing::Test {
47  protected:
48   std::unique_ptr<MockManifestDemuxerEngineHost> mock_mdeh_;
49   std::unique_ptr<MockHlsRenditionHost> mock_hrh_;
50   base::test::TaskEnvironment task_environment_{
51       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
52
53   std::unique_ptr<HlsVodRendition> MakeVodRendition(base::StringPiece content) {
54     constexpr hls::types::DecimalInteger version = 3;
55     auto parsed = hls::MediaPlaylist::Parse(
56         content, GURL("https://example.m3u8"), version, nullptr);
57     if (!parsed.has_value()) {
58       LOG(ERROR) << MediaSerialize(std::move(parsed).error());
59       return nullptr;
60     }
61     auto playlist = std::move(parsed).value();
62     auto duration = playlist->GetComputedDuration();
63     return std::make_unique<HlsVodRendition>(mock_mdeh_.get(), mock_hrh_.get(),
64                                              "test", std::move(playlist),
65                                              duration);
66   }
67
68   MOCK_METHOD(void, CheckStateComplete, (base::TimeDelta delay), ());
69
70   ManifestDemuxer::DelayCallback BindCheckState(base::TimeDelta time) {
71     EXPECT_CALL(*this, CheckStateComplete(time));
72     return base::BindOnce(&HlsVodRenditionUnittest::CheckStateComplete,
73                           base::Unretained(this));
74   }
75
76   ManifestDemuxer::DelayCallback BindCheckStateNoExpect() {
77     return base::BindOnce(&HlsVodRenditionUnittest::CheckStateComplete,
78                           base::Unretained(this));
79   }
80
81   void RespondWithRange(base::TimeDelta start, base::TimeDelta end) {
82     Ranges<base::TimeDelta> ranges;
83     if (start != end) {
84       ranges.Add(start, end);
85     }
86     EXPECT_CALL(*mock_mdeh_, GetBufferedRanges("test"))
87         .WillOnce(Return(ranges));
88   }
89
90   void SupplyAndExpectJunkData(base::TimeDelta initial_response_start,
91                                base::TimeDelta initial_response_end,
92                                base::TimeDelta fetch_expected_time) {
93     std::string junk_content = "abcdefg, I dont like to sing rhyming songs";
94     EXPECT_CALL(*mock_hrh_, ReadFromUrl(_, _, _, _))
95         .WillOnce([content = std::move(junk_content), host = mock_hrh_.get()](
96                       GURL url, bool, absl::optional<hls::types::ByteRange>,
97                       HlsDataSourceProvider::ReadCb cb) {
98           auto stream = StringHlsDataSourceStreamFactory::CreateStream(content);
99           std::move(cb).Run(std::move(stream));
100         });
101     EXPECT_CALL(*mock_mdeh_, AppendAndParseData("test", _, _, _, _, 42))
102         .WillOnce(Return(true));
103     Ranges<base::TimeDelta> initial_range;
104     Ranges<base::TimeDelta> appended_range;
105     if (initial_response_end != initial_response_start) {
106       initial_range.Add(initial_response_start, initial_response_end);
107     }
108     appended_range.Add(fetch_expected_time - base::Seconds(1),
109                        fetch_expected_time + base::Seconds(1));
110     EXPECT_CALL(*mock_mdeh_, GetBufferedRanges("test"))
111         .Times(2)
112         .WillOnce(Return(initial_range))
113         .WillOnce(Return(appended_range));
114   }
115
116  public:
117   HlsVodRenditionUnittest()
118       : mock_mdeh_(std::make_unique<MockManifestDemuxerEngineHost>()),
119         mock_hrh_(std::make_unique<MockHlsRenditionHost>()) {
120     EXPECT_CALL(*mock_mdeh_, RemoveRole("test"));
121   }
122 };
123
124 TEST_F(HlsVodRenditionUnittest, TestCheckStateFromNoData) {
125   auto rendition = MakeVodRendition(kInitialFetchVodPlaylist);
126   ASSERT_NE(rendition, nullptr);
127
128   SupplyAndExpectJunkData(base::Seconds(0), base::Seconds(0), base::Seconds(1));
129   rendition->CheckState(base::Seconds(0), 1.0,
130                         BindCheckState(base::Seconds(0)));
131
132   task_environment_.RunUntilIdle();
133 }
134
135 TEST_F(HlsVodRenditionUnittest, TestCheckStateWithLargeBufferCached) {
136   auto rendition = MakeVodRendition(kInitialFetchVodPlaylist);
137   ASSERT_NE(rendition, nullptr);
138
139   // Prime the download speed cache.
140   SupplyAndExpectJunkData(base::Seconds(0), base::Seconds(0), base::Seconds(1));
141   rendition->CheckState(base::Seconds(0), 1.0,
142                         BindCheckState(base::Seconds(0)));
143   task_environment_.RunUntilIdle();
144
145   // This time respond with a large range of loaded data.
146   // Time until underflow is going to be 12 seconds here - the fetch time
147   // average is zero, since this is a unittest, and we subtract 5 seconds flag
148   // giving a delay of 7 seconds.
149   RespondWithRange(base::Seconds(0), base::Seconds(12));
150   rendition->CheckState(base::Seconds(0), 1.0,
151                         BindCheckState(base::Seconds(7)));
152
153   task_environment_.RunUntilIdle();
154 }
155
156 TEST_F(HlsVodRenditionUnittest, TestCheckStateWithTooLateBuffer) {
157   auto rendition = MakeVodRendition(kInitialFetchVodPlaylist);
158   ASSERT_NE(rendition, nullptr);
159
160   RespondWithRange(base::Seconds(10), base::Seconds(12));
161   EXPECT_CALL(*mock_mdeh_, OnError(_));
162   rendition->CheckState(base::Seconds(0), 1.0, BindCheckStateNoExpect());
163
164   task_environment_.RunUntilIdle();
165 }
166
167 TEST_F(HlsVodRenditionUnittest, TestStop) {
168   auto rendition = MakeVodRendition(kInitialFetchVodPlaylist);
169   ASSERT_NE(rendition, nullptr);
170
171   rendition->Stop();
172
173   // Should always be kNoTimestamp after `Stop()` and no network requests.
174   rendition->CheckState(base::Seconds(0), 1.0, BindCheckState(kNoTimestamp));
175 }
176
177 }  // namespace media