blob: 727cfd560030f981fb5230b944cb50e7f63bdb18 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/filters/hls_data_source_provider.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media::hls {
namespace {
class FakeHlsDataSource : public HlsDataSource {
public:
FakeHlsDataSource(absl::optional<uint64_t> size, std::string pattern)
: HlsDataSource(size), pattern_(pattern) {
remaining_ = size;
}
~FakeHlsDataSource() override {}
void Read(uint64_t pos,
size_t size,
uint8_t* buf,
HlsDataSource::ReadCb cb) override {
size_t offset = pos % pattern_.length();
size_t bytes = std::min(remaining_.value_or(size), size);
if (!bytes) {
std::move(cb).Run(HlsDataSource::ReadStatusCodes::kError);
}
for (size_t i = 0; i < bytes; i++) {
buf[i] = pattern_[(offset + i) % pattern_.length()];
}
if (remaining_.has_value()) {
*remaining_ -= bytes;
}
std::move(cb).Run(bytes);
}
base::StringPiece GetMimeType() const override { return "INVALID"; }
private:
absl::optional<size_t> remaining_ = absl::nullopt;
std::string pattern_;
};
HlsDataSourceStream GetUnlimitedStream() {
return HlsDataSourceStream(std::make_unique<FakeHlsDataSource>(
absl::nullopt, "The Quick Brown Fox Jumped Over The Lazy Dog"));
}
HlsDataSourceStream GetLimitedStream() {
return HlsDataSourceStream(std::make_unique<FakeHlsDataSource>(
44, "The Quick Brown Fox Jumped Over The Lazy Dog"));
}
HlsDataSourceStream GetMassiveStream(bool limited) {
std::stringstream ss;
for (int i = 0; i < 1000; i++) {
ss << "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
<< "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim "
<< "ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut "
<< "aliquip ex ea commodo consequat. Duis aute irure dolor in "
<< "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla "
<< "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in "
<< "culpa qui officia deserunt mollit anim id est laborum.\n";
}
std::string content = ss.str();
absl::optional<uint64_t> size = absl::nullopt;
if (limited) {
size = content.size();
}
return HlsDataSourceStream(
std::make_unique<FakeHlsDataSource>(size, content));
}
} // namespace
TEST(HlsDataSourceStreamUnittest, TestReadAllFromLimitedStream) {
GetLimitedStream().ReadAll(
base::BindOnce([](HlsDataSourceStream::ReadResult result) {
ASSERT_TRUE(result.has_value());
auto stream = std::move(result).value();
ASSERT_FALSE(stream.CanReadMore());
ASSERT_EQ(stream.BytesInBuffer(), (size_t)44);
ASSERT_EQ(std::string(stream.AsStringPiece()),
"The Quick Brown Fox Jumped Over The Lazy Dog");
}));
}
TEST(HlsDataSourceStreamUnittest, TestReadAllFromUnlimitedStream) {
GetUnlimitedStream().ReadAll(
base::BindOnce([](HlsDataSourceStream::ReadResult result) {
ASSERT_TRUE(result.has_value());
auto stream = std::move(result).value();
ASSERT_TRUE(stream.CanReadMore());
ASSERT_EQ(stream.BytesInBuffer(), (size_t)0xFFFF);
// make sure it's repeating.
for (int i = 0; i < 4; i++) {
ASSERT_EQ(stream.AsStringPiece()[i * 44 + 0], 'T');
ASSERT_EQ(stream.AsStringPiece()[i * 44 + 1], 'h');
ASSERT_EQ(stream.AsStringPiece()[i * 44 + 2], 'e');
ASSERT_EQ(stream.AsStringPiece()[i * 44 + 4], 'Q');
ASSERT_EQ(stream.AsStringPiece()[i * 44 + 5], 'u');
ASSERT_EQ(stream.AsStringPiece()[i * 44 + 6], 'i');
}
}));
}
TEST(HlsDataSourceStreamUnittest, TestReadDefaultChunkFromLimitedStream) {
// Read the default size chunk (0xFFFF). Should be pretty much the same
// as reading all from a limited stream.
GetLimitedStream().ReadChunk(
base::BindOnce([](HlsDataSourceStream::ReadResult result) {
ASSERT_TRUE(result.has_value());
auto stream = std::move(result).value();
ASSERT_FALSE(stream.CanReadMore());
ASSERT_EQ(stream.BytesInBuffer(), (size_t)44);
ASSERT_EQ(std::string(stream.AsStringPiece()),
"The Quick Brown Fox Jumped Over The Lazy Dog");
}));
}
TEST(HlsDataSourceStreamUnittest, TestReadDefaultChunkFromUnlimitedStream) {
// Read the default size chunk (0xFFFF). Should be pretty much the same
// as reading all from an unlimited stream, which just reverts to chunks.
GetUnlimitedStream().ReadChunk(
base::BindOnce([](HlsDataSourceStream::ReadResult result) {
ASSERT_TRUE(result.has_value());
auto stream = std::move(result).value();
ASSERT_TRUE(stream.CanReadMore());
ASSERT_EQ(stream.BytesInBuffer(), (size_t)0xFFFF);
// make sure it's repeating.
for (int i = 0; i < 4; i++) {
ASSERT_EQ(stream.AsStringPiece()[i * 44 + 0], 'T');
ASSERT_EQ(stream.AsStringPiece()[i * 44 + 1], 'h');
ASSERT_EQ(stream.AsStringPiece()[i * 44 + 2], 'e');
ASSERT_EQ(stream.AsStringPiece()[i * 44 + 4], 'Q');
ASSERT_EQ(stream.AsStringPiece()[i * 44 + 5], 'u');
ASSERT_EQ(stream.AsStringPiece()[i * 44 + 6], 'i');
}
}));
}
TEST(HlsDataSourceStreamUnittest, TestReadSmallSizeFromLimitedStream) {
GetLimitedStream().ReadChunk(
base::BindOnce([](HlsDataSourceStream::ReadResult result) {
ASSERT_TRUE(result.has_value());
auto stream = std::move(result).value();
ASSERT_TRUE(stream.CanReadMore());
ASSERT_EQ(stream.BytesInBuffer(), (size_t)14);
ASSERT_EQ(std::string(stream.AsStringPiece()), "The Quick Brow");
// Read it again!
std::move(stream).ReadChunk(
base::BindOnce([](HlsDataSourceStream::ReadResult result) {
ASSERT_TRUE(result.has_value());
auto stream = std::move(result).value();
ASSERT_TRUE(stream.CanReadMore());
ASSERT_EQ(stream.BytesInBuffer(), (size_t)28);
ASSERT_EQ(std::string(stream.AsStringPiece()),
"The Quick Brown Fox Jumped O");
}),
14);
}),
14);
}
TEST(HlsDataSourceStreamUnittest, TestReadSmallSizeFromUnlimitedStream) {
GetUnlimitedStream().ReadChunk(
base::BindOnce([](HlsDataSourceStream::ReadResult result) {
ASSERT_TRUE(result.has_value());
auto stream = std::move(result).value();
ASSERT_TRUE(stream.CanReadMore());
ASSERT_EQ(stream.BytesInBuffer(), (size_t)14);
ASSERT_EQ(std::string(stream.AsStringPiece()), "The Quick Brow");
// Read it again!
std::move(stream).ReadChunk(
base::BindOnce([](HlsDataSourceStream::ReadResult result) {
ASSERT_TRUE(result.has_value());
auto stream = std::move(result).value();
ASSERT_TRUE(stream.CanReadMore());
ASSERT_EQ(stream.BytesInBuffer(), (size_t)28);
ASSERT_EQ(std::string(stream.AsStringPiece()),
"The Quick Brown Fox Jumped O");
}),
14);
}),
14);
}
TEST(HlsDataSourceStreamUnittest, TestReadSmallSizeWithFlush) {
GetUnlimitedStream().ReadChunk(
base::BindOnce([](HlsDataSourceStream::ReadResult result) {
ASSERT_TRUE(result.has_value());
auto stream = std::move(result).value();
ASSERT_TRUE(stream.CanReadMore());
ASSERT_EQ(stream.BytesInBuffer(), (size_t)14);
ASSERT_EQ(std::string(stream.AsStringPiece()), "The Quick Brow");
// clear the buffer
stream.Flush();
// Read it again!
std::move(stream).ReadChunk(
base::BindOnce([](HlsDataSourceStream::ReadResult result) {
ASSERT_TRUE(result.has_value());
auto stream = std::move(result).value();
ASSERT_TRUE(stream.CanReadMore());
ASSERT_EQ(stream.BytesInBuffer(), (size_t)14);
ASSERT_EQ(std::string(stream.AsStringPiece()), "n Fox Jumped O");
}),
14);
}),
14);
}
TEST(HlsDataSourceStreamUnittest, ReadAllFromMultiChunkStream) {
// Read from a stream longer than 0xFFFF bytes, to assert that |ReadAll|
// really does read all the data from a size-limited stream.
GetMassiveStream(/*limited=*/true)
.ReadAll(base::BindOnce([](HlsDataSourceStream::ReadResult result) {
ASSERT_TRUE(result.has_value());
auto stream = std::move(result).value();
ASSERT_FALSE(stream.CanReadMore());
// 0xFFFF = 65535
// readsize = 446000
ASSERT_EQ(stream.BytesInBuffer(), (size_t)446000);
}));
}
TEST(HlsDataSourceStreamUnittest, ReadAllFromMultiChunkStreamUnknownLength) {
// Read from a stream longer than 0xFFFF bytes, to assert that |ReadAll|
// really does read all the data from a size-limited stream.
GetMassiveStream(/*limited=*/false)
.ReadAll(base::BindOnce([](HlsDataSourceStream::ReadResult result) {
ASSERT_TRUE(result.has_value());
auto stream = std::move(result).value();
ASSERT_TRUE(stream.CanReadMore());
ASSERT_EQ(stream.BytesInBuffer(), (size_t)0xFFFF);
// clear the buffer
stream.Flush();
ASSERT_EQ(stream.BytesInBuffer(), (size_t)0);
std::move(stream).ReadAll(
base::BindOnce([](HlsDataSourceStream::ReadResult res) {
ASSERT_TRUE(res.has_value());
auto stream = std::move(res).value();
// 0xFFFF * 2 is still less than stream size.
ASSERT_TRUE(stream.CanReadMore());
ASSERT_EQ(stream.BytesInBuffer(), (size_t)0xFFFF);
}));
}));
}
} // namespace media::hls