#include "media/formats/hls/playlist.h"
#include <string_view>
#include "base/location.h"
#include "base/strings/string_number_conversions.h"
#include "media/formats/hls/parse_status.h"
#include "media/formats/hls/quirks.h"
#include "media/formats/hls/tag_name.h"
#include "media/formats/hls/types.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media::hls {
TEST(HlsPlaylistTest, IdentifyPlaylist) {
constexpr auto ok_test = [](types::DecimalInteger version,
Playlist::Kind kind, std::string_view src,
const base::Location& from =
base::Location::Current()) {
auto result = Playlist::IdentifyPlaylist(src);
ASSERT_TRUE(result.has_value()) << from.ToString();
auto ident = std::move(result).value();
EXPECT_EQ(ident.version, version) << from.ToString();
EXPECT_EQ(ident.kind, kind) << from.ToString();
};
constexpr auto error_test =
[](ParseStatusCode expected_error, std::string_view src,
const base::Location& from = base::Location::Current()) {
auto result = Playlist::IdentifyPlaylist(src);
ASSERT_FALSE(result.has_value()) << from.ToString();
auto error = std::move(result).error();
EXPECT_EQ(error.code(), expected_error) << from.ToString();
};
ok_test(Playlist::kDefaultVersion, Playlist::Kind::kMultivariantPlaylist, "");
ok_test(5, Playlist::Kind::kMultivariantPlaylist, "#EXT-X-VERSION:5\n");
ok_test(Playlist::kDefaultVersion, Playlist::Kind::kMediaPlaylist, "#EXTINF");
for (TagName tag = kMinTagName; tag <= kMaxTagName; ++tag) {
if (tag == ToTagName(CommonTagName::kXVersion)) {
continue;
}
for (types::DecimalInteger version : {0, 1, 5, 10}) {
for (bool common_tag : {true, false}) {
std::string src;
if (common_tag) {
src += "#EXTM3U\n";
}
if (version) {
src += "#EXT-X-VERSION:" + base::NumberToString(version) + "\n";
}
src += "#" + std::string(TagNameToString(tag)) + "\n";
switch (GetTagKind(tag)) {
case TagKind::kCommonTag:
ok_test(version ? version : Playlist::kDefaultVersion,
Playlist::Kind::kMultivariantPlaylist, src);
break;
case TagKind::kMultivariantPlaylistTag:
ok_test(version ? version : Playlist::kDefaultVersion,
Playlist::Kind::kMultivariantPlaylist, src);
break;
case TagKind::kMediaPlaylistTag:
ok_test(version ? version : Playlist::kDefaultVersion,
Playlist::Kind::kMediaPlaylist, src);
break;
}
}
}
}
error_test(ParseStatusCode::kFailedToParseDecimalInteger,
"#EXT-X-VERSION:-1\n");
error_test(ParseStatusCode::kInvalidPlaylistVersion, "#EXT-X-VERSION:0\n");
error_test(ParseStatusCode::kPlaylistHasUnsupportedVersion,
"#EXT-X-VERSION:11\n");
if (HLSQuirks::AllowMediaTagsInMultivariantPlaylists()) {
ok_test(Playlist::kDefaultVersion, Playlist::Kind::kMultivariantPlaylist,
"#EXT-X-STREAM-INF\n#EXTINF\n");
} else {
error_test(ParseStatusCode::kMultivariantPlaylistHasMediaPlaylistTag,
"#EXT-X-STREAM-INF\n#EXTINF\n");
}
error_test(ParseStatusCode::kMediaPlaylistHasMultivariantPlaylistTag,
"#EXTINF\n#EXT-X-STREAM-INF\n");
ok_test(5, Playlist::Kind::kMediaPlaylist,
"#EXT-X-VERSION:5\n#EXTINF\n#EXT-X-STREAM-INF\n");
error_test(ParseStatusCode::kPlaylistHasDuplicateTags,
"#EXT-X-VERSION:3\n#EXT-X-VERSION:3\n");
error_test(ParseStatusCode::kPlaylistHasDuplicateTags,
"#EXT-X-VERSION:3\n#EXT-X-VERSION:4\n");
ok_test(5, Playlist::Kind::kMediaPlaylist,
"#EXT-X-VERSION:5\n#EXTINF\n#EXT-X-VERSION:6\n");
ok_test(5, Playlist::Kind::kMediaPlaylist,
"#EXT-X-VERSION:5\n#EXT-X-FAKE-TAG\n#EXTINF\n");
}
}