Files
oemcrypto/util/test/hls_attribute_list_unittest.cpp
2025-05-22 16:33:29 -07:00

1386 lines
56 KiB
C++

// Copyright 2025 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#include "hls_attribute_list.h"
#include <inttypes.h>
#include <limits>
#include <sstream>
#include <string>
#include <vector>
#include <gtest/gtest.h>
#include "string_conversions.h"
#include "string_utils.h"
namespace wvutil {
namespace test {
namespace {
constexpr uint64_t kZeroInt = 0;
constexpr uint64_t kMaxInt = std::numeric_limits<uint64_t>::max();
constexpr char kMaxIntString[] = "18446744073709551615";
// FYI: 2^52 is the largest float value with whole integer
// precision.
constexpr double kMaxIntFloat = 9007199254740992.0;
constexpr uint64_t kMaxIntFloatInt = 9007199254740992;
constexpr char kMaxIntFloatString[] = "9007199254740992";
} // namespace
TEST(HlsAttributeListTest, IsValidName) {
// Valid attribute names.
EXPECT_TRUE(HlsAttributeList::IsValidName("METHOD"));
EXPECT_TRUE(HlsAttributeList::IsValidName("START-DATE"));
EXPECT_TRUE(HlsAttributeList::IsValidName("SCTE35-CMD"));
EXPECT_TRUE(HlsAttributeList::IsValidName("SCTE35-IN"));
EXPECT_TRUE(HlsAttributeList::IsValidName("GROUP-ID"));
EXPECT_TRUE(HlsAttributeList::IsValidName("X-WIDEVINE-1337"));
// Unlikely but still valid.
EXPECT_TRUE(HlsAttributeList::IsValidName("-"));
EXPECT_TRUE(HlsAttributeList::IsValidName("-----------"));
EXPECT_TRUE(HlsAttributeList::IsValidName("123456789"));
EXPECT_TRUE(HlsAttributeList::IsValidName("-0"));
// Invalid attribute names.
EXPECT_FALSE(HlsAttributeList::IsValidName(""));
EXPECT_FALSE(HlsAttributeList::IsValidName("lower-case"));
EXPECT_FALSE(HlsAttributeList::IsValidName("sOME-LOWER-CASE"));
EXPECT_FALSE(HlsAttributeList::IsValidName("SOME-LOWER-CASe"));
EXPECT_FALSE(HlsAttributeList::IsValidName("sOME-LOwER-CASE"));
EXPECT_FALSE(HlsAttributeList::IsValidName("METHOD=NONE"));
EXPECT_FALSE(HlsAttributeList::IsValidName("WHITE SPACE"));
EXPECT_FALSE(HlsAttributeList::IsValidName(" WHITE-SPACE"));
EXPECT_FALSE(HlsAttributeList::IsValidName("WHITE-SPACE "));
EXPECT_FALSE(HlsAttributeList::IsValidName("NO,COMMA"));
EXPECT_FALSE(HlsAttributeList::IsValidName("NO\"QUOTE"));
EXPECT_FALSE(HlsAttributeList::IsValidName("NO\nLF"));
EXPECT_FALSE(HlsAttributeList::IsValidName("NO\rCR"));
}
TEST(HlsAttributeListTest, IsValidEnumStringValue) {
// Valid from HLS standard.
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue("NONE"));
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue("AES-128"));
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue("SAMPLE-AES"));
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue("CLOSED-CAPTIONS"));
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue("YES"));
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue("TYPE-0"));
// Other valid values.
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue("lower-case"));
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue("------"));
// All punctuation except commas and double quotes.
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue("!@#$%^&*()"));
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue("-=_+{}[]\\|"));
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue(";:'<>./?~`"));
// Values that look like other types.
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue("1234"));
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue("-12.3"));
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue("0x1234"));
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue("1920x1080"));
// Invalid
EXPECT_FALSE(HlsAttributeList::IsValidEnumStringValue(""));
EXPECT_FALSE(HlsAttributeList::IsValidEnumStringValue("WHITE SPACE"));
EXPECT_FALSE(HlsAttributeList::IsValidEnumStringValue(" WHITESPACE"));
EXPECT_FALSE(HlsAttributeList::IsValidEnumStringValue("WHITESPACE "));
EXPECT_FALSE(HlsAttributeList::IsValidEnumStringValue("NO,COMMAS"));
EXPECT_FALSE(HlsAttributeList::IsValidEnumStringValue("NO\"QUOTE"));
EXPECT_FALSE(HlsAttributeList::IsValidEnumStringValue("NO\nLF"));
EXPECT_FALSE(HlsAttributeList::IsValidEnumStringValue("NO\rCR"));
}
TEST(HlsAttributeListTest, IsValidQuotedStringValue) {
// Valid from standard.
EXPECT_TRUE(HlsAttributeList::IsValidQuotedStringValue(
"uri:text/plain;base64,SGVsbG8sIFdvcmxkIQ=="));
EXPECT_TRUE(HlsAttributeList::IsValidQuotedStringValue("com.widevine"));
EXPECT_TRUE(HlsAttributeList::IsValidQuotedStringValue("1/2/5"));
EXPECT_TRUE(
HlsAttributeList::IsValidQuotedStringValue("2024-07-31T11:43:55-12:00"));
EXPECT_TRUE(HlsAttributeList::IsValidQuotedStringValue(""));
EXPECT_TRUE(
HlsAttributeList::IsValidQuotedStringValue("white space, and commas"));
EXPECT_FALSE(HlsAttributeList::IsValidQuotedStringValue("NO\"QUOTE"));
EXPECT_FALSE(HlsAttributeList::IsValidQuotedStringValue("NO\nLF"));
EXPECT_FALSE(HlsAttributeList::IsValidQuotedStringValue("NO\rCR"));
}
TEST(HlsAttributeListTest, EmptyList) {
const HlsAttributeList list;
constexpr size_t kZero = 0;
EXPECT_EQ(list.Count(), kZero);
EXPECT_TRUE(list.IsEmpty());
const std::vector<std::string> kEmptyVector;
EXPECT_EQ(list.GetNames(), kEmptyVector);
EXPECT_FALSE(list.Contains("METHOD"));
}
TEST(HlsAttributeListTest, SetEnumString) {
HlsAttributeList list;
EXPECT_TRUE(list.SetEnumString("METHOD", "NONE"));
EXPECT_TRUE(list.SetEnumString("TYPE", "AUDIO"));
EXPECT_TRUE(list.SetEnumString("DEFAULT", "NO"));
// Overwrite.
EXPECT_TRUE(list.SetEnumString("TYPE", "VIDEO"));
EXPECT_EQ(list.Count(), static_cast<size_t>(3));
EXPECT_TRUE(list.Contains("METHOD"));
EXPECT_FALSE(list.Contains("AUDIO"));
const std::vector<std::string> kExpectedNames = {"DEFAULT", "METHOD", "TYPE"};
EXPECT_EQ(list.GetNames(), kExpectedNames);
std::string value;
EXPECT_TRUE(list.GetEnumString("METHOD", &value));
EXPECT_EQ(value, "NONE");
EXPECT_TRUE(list.GetEnumString("TYPE", &value));
EXPECT_EQ(value, "VIDEO");
EXPECT_TRUE(list.GetEnumString("DEFAULT", &value));
EXPECT_EQ(value, "NO");
EXPECT_FALSE(list.GetEnumString("INSTREAM-ID", &value));
}
TEST(HlsAttributeListTest, SetEnumString_Invalid) {
HlsAttributeList list;
EXPECT_FALSE(list.SetEnumString("", "NONE"));
EXPECT_FALSE(list.SetEnumString("BAD NAME", "NONE"));
EXPECT_FALSE(list.SetEnumString("bad-name", "NONE"));
EXPECT_FALSE(list.SetEnumString("METHOD", ""));
EXPECT_FALSE(list.SetEnumString("METHOD", "BAD VALUE"));
EXPECT_FALSE(list.SetEnumString("METHOD", "BAD,VALUE"));
EXPECT_FALSE(list.SetEnumString("METHOD", "BAD\"VALUE"));
EXPECT_TRUE(list.IsEmpty());
}
TEST(HlsAttributeListTest, SetQuotedString) {
HlsAttributeList list;
const std::string kUriValue = "uri:text/plain;base64,SGVsbG8sIFdvcmxkIQ==";
EXPECT_TRUE(list.SetQuotedString("URI", kUriValue));
EXPECT_TRUE(list.SetQuotedString("VERSION", ""));
EXPECT_TRUE(list.SetQuotedString("MESSAGE", "Hello, world!"));
EXPECT_EQ(list.Count(), static_cast<size_t>(3));
EXPECT_TRUE(list.Contains("VERSION"));
EXPECT_FALSE(list.Contains("AUDIO"));
const std::vector<std::string> kExpectedNames = {"MESSAGE", "URI", "VERSION"};
EXPECT_EQ(list.GetNames(), kExpectedNames);
std::string value;
EXPECT_TRUE(list.GetQuotedString("URI", &value));
EXPECT_EQ(value, kUriValue);
EXPECT_TRUE(list.GetQuotedString("VERSION", &value));
EXPECT_EQ(value, "");
EXPECT_TRUE(list.GetQuotedString("MESSAGE", &value));
EXPECT_EQ(value, "Hello, world!");
EXPECT_FALSE(list.GetQuotedString("INSTREAM-ID", &value));
}
TEST(HlsAttributeListTest, SetQuotedString_Invalid) {
HlsAttributeList list;
EXPECT_FALSE(list.SetQuotedString("", "NONE"));
EXPECT_FALSE(list.SetQuotedString("BAD NAME", "NONE"));
EXPECT_FALSE(list.SetQuotedString("bad-name", "NONE"));
EXPECT_FALSE(list.SetQuotedString("METHOD", "BAD\rVALUE"));
EXPECT_FALSE(list.SetQuotedString("METHOD", "BAD\nVALUE"));
EXPECT_FALSE(list.SetQuotedString("METHOD", "BAD\"VALUE"));
EXPECT_TRUE(list.IsEmpty());
}
TEST(HlsAttributeListTest, SetHexSequenceAsString) {
HlsAttributeList list;
EXPECT_TRUE(list.SetHexSequence("IV", "some IV value"));
EXPECT_TRUE(list.SetHexSequence("OTHERWISE-FORBIDDEN", "\r\n \"\b"));
EXPECT_TRUE(list.SetHexSequence("SMALL", "-"));
EXPECT_EQ(list.Count(), static_cast<size_t>(3));
EXPECT_TRUE(list.Contains("IV"));
EXPECT_FALSE(list.Contains("AUDIO"));
const std::vector<std::string> kExpectedNames = {"IV", "OTHERWISE-FORBIDDEN",
"SMALL"};
EXPECT_EQ(list.GetNames(), kExpectedNames);
std::string value;
EXPECT_TRUE(list.GetHexSequence("IV", &value));
EXPECT_EQ(value, "some IV value");
EXPECT_TRUE(list.GetHexSequence("OTHERWISE-FORBIDDEN", &value));
EXPECT_EQ(value, "\r\n \"\b");
EXPECT_TRUE(list.GetHexSequence("SMALL", &value));
EXPECT_EQ(value, "-");
EXPECT_FALSE(list.GetHexSequence("INSTREAM-ID", &value));
}
TEST(HlsAttributeListTest, SetHexSequenceAsString_Invalid) {
HlsAttributeList list;
EXPECT_FALSE(list.SetHexSequence("", "NONE"));
EXPECT_FALSE(list.SetHexSequence("BAD NAME", "NONE"));
EXPECT_FALSE(list.SetHexSequence("bad-name", "NONE"));
EXPECT_FALSE(list.SetHexSequence("METHOD", ""));
EXPECT_TRUE(list.IsEmpty());
}
TEST(HlsAttributeListTest, SetHexSequenceAsVector) {
HlsAttributeList list;
const std::vector<uint8_t> kIvValue(16, 0x33);
EXPECT_TRUE(list.SetHexSequence("IV", kIvValue));
const std::vector<uint8_t> kSmallValue(1, 0xff);
EXPECT_TRUE(list.SetHexSequence("SMALL", kSmallValue));
EXPECT_EQ(list.Count(), static_cast<size_t>(2));
EXPECT_TRUE(list.Contains("IV"));
EXPECT_FALSE(list.Contains("AUDIO"));
const std::vector<std::string> kExpectedNames = {"IV", "SMALL"};
EXPECT_EQ(list.GetNames(), kExpectedNames);
std::vector<uint8_t> value;
EXPECT_TRUE(list.GetHexSequence("IV", &value));
EXPECT_EQ(value, kIvValue);
EXPECT_TRUE(list.GetHexSequence("SMALL", &value));
EXPECT_EQ(value, kSmallValue);
EXPECT_FALSE(list.GetHexSequence("INSTREAM-ID", &value));
}
TEST(HlsAttributeListTest, SetHexSequenceAsVector_Invalid) {
HlsAttributeList list;
const std::vector<uint8_t> kValidValue(4, 0x20);
EXPECT_FALSE(list.SetHexSequence("", kValidValue));
EXPECT_FALSE(list.SetHexSequence("BAD NAME", kValidValue));
EXPECT_FALSE(list.SetHexSequence("bad-name", kValidValue));
const std::vector<uint8_t> kEmptyVector;
EXPECT_FALSE(list.SetHexSequence("METHOD", kEmptyVector));
EXPECT_TRUE(list.IsEmpty());
}
TEST(HlsAttributeListTest, SetInteger) {
HlsAttributeList list;
const uint64_t kInStreamId = 32;
EXPECT_TRUE(list.SetInteger("INSTREAM-ID", kInStreamId));
EXPECT_TRUE(list.SetInteger("ZERO", kZeroInt));
EXPECT_TRUE(list.SetInteger("MAX", kMaxInt));
EXPECT_EQ(list.Count(), static_cast<size_t>(3));
EXPECT_TRUE(list.Contains("ZERO"));
EXPECT_FALSE(list.Contains("AUDIO"));
const std::vector<std::string> kExpectedNames = {"INSTREAM-ID", "MAX",
"ZERO"};
EXPECT_EQ(list.GetNames(), kExpectedNames);
uint64_t value = 0;
EXPECT_TRUE(list.GetInteger("INSTREAM-ID", &value));
EXPECT_EQ(value, kInStreamId);
EXPECT_TRUE(list.GetInteger("ZERO", &value));
EXPECT_EQ(value, kZeroInt);
EXPECT_TRUE(list.GetInteger("MAX", &value));
EXPECT_EQ(value, kMaxInt);
EXPECT_FALSE(list.GetInteger("VERSION", &value));
}
TEST(HlsAttributeListTest, SetInteger_Invalid) {
HlsAttributeList list;
const uint64_t kValidValue = 1337;
EXPECT_FALSE(list.SetInteger("", kValidValue));
EXPECT_FALSE(list.SetInteger("BAD NAME", kValidValue));
EXPECT_FALSE(list.SetInteger("bad-name", kValidValue));
}
TEST(HlsAttributeListTest, SetFloat) {
HlsAttributeList list;
const double kFrameRate = 29.97;
EXPECT_TRUE(list.SetFloat("FRAME-RATE", kFrameRate));
const double kTimeOffset = -5.5;
EXPECT_TRUE(list.SetFloat("TIME-OFFSET", kTimeOffset));
const double kZero = 0.0;
EXPECT_TRUE(list.SetFloat("ZERO", kZero));
EXPECT_EQ(list.Count(), static_cast<size_t>(3));
EXPECT_TRUE(list.Contains("TIME-OFFSET"));
EXPECT_FALSE(list.Contains("AUDIO"));
const std::vector<std::string> kExpectedNames = {"FRAME-RATE", "TIME-OFFSET",
"ZERO"};
EXPECT_EQ(list.GetNames(), kExpectedNames);
double value = 0;
EXPECT_TRUE(list.GetFloat("FRAME-RATE", &value));
EXPECT_EQ(value, kFrameRate);
EXPECT_TRUE(list.GetFloat("ZERO", &value));
EXPECT_EQ(value, kZero);
EXPECT_TRUE(list.GetFloat("TIME-OFFSET", &value));
EXPECT_EQ(value, kTimeOffset);
EXPECT_FALSE(list.GetFloat("VERSION", &value));
}
TEST(HlsAttributeListTest, SetFloat_Invalid) {
HlsAttributeList list;
const double kValidValue = 1337.0;
EXPECT_FALSE(list.SetFloat("", kValidValue));
EXPECT_FALSE(list.SetFloat("BAD NAME", kValidValue));
EXPECT_FALSE(list.SetFloat("bad-name", kValidValue));
}
TEST(HlsAttributeListTest, SetResolution) {
HlsAttributeList list;
EXPECT_TRUE(list.SetResolution("RESOLUTION", 1920, 1080));
EXPECT_TRUE(list.SetResolution("SVGA-RESOLUTION", 800, 600));
EXPECT_TRUE(list.SetResolution("NULL-RESOLUTION", 0, 0));
const std::vector<std::string> kExpectedNames = {
"NULL-RESOLUTION", "RESOLUTION", "SVGA-RESOLUTION"};
EXPECT_EQ(list.GetNames(), kExpectedNames);
uint64_t width = 0;
uint64_t height = 0;
EXPECT_TRUE(list.GetResolution("RESOLUTION", &width, &height));
EXPECT_EQ(width, static_cast<uint64_t>(1920));
EXPECT_EQ(height, static_cast<uint64_t>(1080));
EXPECT_TRUE(list.GetResolution("NULL-RESOLUTION", &width, &height));
EXPECT_EQ(width, kZeroInt);
EXPECT_EQ(height, kZeroInt);
EXPECT_TRUE(list.GetResolution("SVGA-RESOLUTION", &width, &height));
EXPECT_EQ(width, static_cast<uint64_t>(800));
EXPECT_EQ(height, static_cast<uint64_t>(600));
EXPECT_FALSE(list.GetResolution("VERSION", &width, &height));
}
TEST(HlsAttributeListTest, SetResolution_Invalid) {
HlsAttributeList list;
EXPECT_FALSE(list.SetResolution("", 1920, 1080));
EXPECT_FALSE(list.SetResolution("BAD NAME", 1920, 1080));
EXPECT_FALSE(list.SetResolution("bad-name", 1920, 1080));
}
TEST(HlsAttributeListTest, Remove) {
HlsAttributeList list;
EXPECT_TRUE(list.SetEnumString("METHOD", "SAMPLE-AES"));
EXPECT_TRUE(list.SetQuotedString("VERSION", "1/2/5"));
const std::vector<uint8_t> kIv(16, 0x42);
EXPECT_TRUE(list.SetHexSequence("IV", kIv));
const uint64_t kInStreamId = 32;
EXPECT_TRUE(list.SetInteger("INSTREAM-ID", kInStreamId));
const double kFrameRate = 29.97;
EXPECT_TRUE(list.SetFloat("FRAME-RATE", kFrameRate));
const uint64_t kWidth = 1920;
const uint64_t kHeight = 1080;
EXPECT_TRUE(list.SetResolution("RESOLUTION", kWidth, kHeight));
const std::vector<std::string> kExpectedInitialNames = {
"FRAME-RATE", "INSTREAM-ID", "IV", "METHOD", "RESOLUTION", "VERSION"};
EXPECT_EQ(list.GetNames(), kExpectedInitialNames);
EXPECT_TRUE(list.Remove("IV"));
EXPECT_TRUE(list.Remove("VERSION"));
EXPECT_FALSE(list.Remove("TIME-OFFSET"));
EXPECT_EQ(list.Count(), static_cast<size_t>(4));
const std::vector<std::string> kExpectedFinalNames = {
"FRAME-RATE", "INSTREAM-ID", "METHOD", "RESOLUTION"};
EXPECT_EQ(list.GetNames(), kExpectedFinalNames);
std::string string_value;
EXPECT_TRUE(list.GetEnumString("METHOD", &string_value));
EXPECT_EQ(string_value, "SAMPLE-AES");
EXPECT_FALSE(list.GetEnumString("VERSION", &string_value));
std::vector<uint8_t> vec_value;
EXPECT_FALSE(list.GetHexSequence("IV", &vec_value));
uint64_t int_value = 0;
EXPECT_TRUE(list.GetInteger("INSTREAM-ID", &int_value));
EXPECT_EQ(int_value, kInStreamId);
}
TEST(HlsAttributeListTest, AmbiguousValues_EnumStringAsInteger) {
HlsAttributeList list;
EXPECT_TRUE(list.SetEnumString("POSITIVE-INT", "1234"));
// Max u64 2^64-1
EXPECT_TRUE(list.SetEnumString("MAX-INT", kMaxIntString));
EXPECT_TRUE(list.SetEnumString("BIG-ZERO-INT", "00000000000000000000"));
// Over max, 2^64
EXPECT_TRUE(list.SetEnumString("OVER-MAX-INT", "18446744073709551616"));
// Integers cannot be negative
EXPECT_TRUE(list.SetEnumString("NEGATIVE-INT", "-1337"));
// Integers cannot use positive sign.
EXPECT_TRUE(list.SetEnumString("BAD-SIGN", "+42"));
EXPECT_TRUE(list.SetEnumString("NOT-INT", "OTHER"));
EXPECT_TRUE(list.IsType("POSITIVE-INT", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("POSITIVE-INT", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("MAX-INT", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("MAX-INT", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("BIG-ZERO-INT", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("BIG-ZERO-INT", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("OVER-MAX-INT", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(list.IsType("OVER-MAX-INT", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("BAD-SIGN", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(list.IsType("BAD-SIGN", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("NEGATIVE-INT", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(list.IsType("NEGATIVE-INT", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("NOT-INT", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(list.IsType("NOT-INT", HlsAttributeList::kIntegerType));
uint64_t value = 0;
EXPECT_TRUE(list.GetInteger("POSITIVE-INT", &value));
EXPECT_EQ(value, static_cast<uint64_t>(1234));
EXPECT_TRUE(list.GetInteger("MAX-INT", &value));
EXPECT_EQ(value, kMaxInt);
EXPECT_TRUE(list.GetInteger("BIG-ZERO-INT", &value));
EXPECT_EQ(value, kZeroInt);
EXPECT_FALSE(list.GetInteger("OVER-MAX-INT", &value));
EXPECT_FALSE(list.GetInteger("NEGATIVE-INT", &value));
EXPECT_FALSE(list.GetInteger("BAD-SIGN", &value));
EXPECT_FALSE(list.GetInteger("NOT-INT", &value));
}
TEST(HlsAttributeListTest, AmbiguousValues_EnumStringAsFloat) {
HlsAttributeList list;
EXPECT_TRUE(list.SetEnumString("POSITIVE-INT", "1234"));
EXPECT_TRUE(list.SetEnumString("NEGATIVE-INT", "-1337"));
EXPECT_TRUE(list.SetEnumString("POSITIVE-FLOAT", "29.97"));
EXPECT_TRUE(list.SetEnumString("NEGATIVE-FLOAT", "-180.0"));
EXPECT_TRUE(list.SetEnumString("MAX-INT-FLOAT", kMaxIntFloatString));
EXPECT_TRUE(list.SetEnumString("NO-FRAC", "12."));
EXPECT_TRUE(list.SetEnumString("NO-INT", ".345"));
// Floats cannot have positive signs.
EXPECT_TRUE(list.SetEnumString("BAD-SIGN", "+12.345"));
EXPECT_TRUE(list.SetEnumString("NOT-FLOAT", "OTHER"));
EXPECT_TRUE(list.IsType("POSITIVE-INT", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("POSITIVE-INT", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("NEGATIVE-INT", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("NEGATIVE-INT", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("POSITIVE-FLOAT", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("POSITIVE-FLOAT", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("NEGATIVE-FLOAT", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("NEGATIVE-FLOAT", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("MAX-INT-FLOAT", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("MAX-INT-FLOAT", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("NO-FRAC", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(list.IsType("NO-FRAC", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("NO-INT", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(list.IsType("NO-INT", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("BAD-SIGN", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(list.IsType("BAD-SIGN", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("NOT-FLOAT", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(list.IsType("NOT-FLOAT", HlsAttributeList::kFloatType));
double value = 0.0;
EXPECT_TRUE(list.GetFloat("POSITIVE-INT", &value));
EXPECT_EQ(value, 1234.0);
EXPECT_TRUE(list.GetFloat("NEGATIVE-INT", &value));
EXPECT_EQ(value, -1337.0);
EXPECT_TRUE(list.GetFloat("POSITIVE-FLOAT", &value));
EXPECT_EQ(value, 29.97);
EXPECT_TRUE(list.GetFloat("NEGATIVE-FLOAT", &value));
EXPECT_EQ(value, -180.0);
EXPECT_TRUE(list.GetFloat("MAX-INT-FLOAT", &value));
EXPECT_EQ(value, kMaxIntFloat);
EXPECT_FALSE(list.GetFloat("NO-FRAC", &value));
EXPECT_FALSE(list.GetFloat("NO-INT", &value));
EXPECT_FALSE(list.GetFloat("BAD-SIGN", &value));
EXPECT_FALSE(list.GetFloat("NOT-FLOAT", &value));
}
TEST(HlsAttributeListTest, AmbiguousValues_EnumStringAsHexSequence) {
HlsAttributeList list;
// Hex of "Hello, World!"
EXPECT_TRUE(list.SetEnumString("VALID-HEX", "0x48656C6C6F2C20576F726C6421"));
// Hex does not need to be even length.
EXPECT_TRUE(list.SetEnumString("ODD-HEX", "0X1020304"));
// Lower case is not valid HLS hex.
EXPECT_TRUE(
list.SetEnumString("INVALID-HEX", "0x48656c6c6f2c20576f726c6421"));
EXPECT_TRUE(list.SetEnumString("NULL-HEX", "0X"));
EXPECT_TRUE(list.SetEnumString("NOT-HEX", "OTHER"));
EXPECT_TRUE(list.IsType("VALID-HEX", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("VALID-HEX", HlsAttributeList::kHexSequenceType));
EXPECT_TRUE(list.IsType("ODD-HEX", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("ODD-HEX", HlsAttributeList::kHexSequenceType));
EXPECT_TRUE(list.IsType("INVALID-HEX", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(list.IsType("INVALID-HEX", HlsAttributeList::kHexSequenceType));
EXPECT_TRUE(list.IsType("NULL-HEX", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(list.IsType("NULL-HEX", HlsAttributeList::kHexSequenceType));
EXPECT_TRUE(list.IsType("NOT-HEX", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(list.IsType("NOT-HEX", HlsAttributeList::kHexSequenceType));
std::string string_value;
EXPECT_TRUE(list.GetHexSequence("VALID-HEX", &string_value));
EXPECT_EQ(string_value, "Hello, World!");
std::vector<uint8_t> vec_value;
EXPECT_TRUE(list.GetHexSequence("ODD-HEX", &vec_value));
const std::vector<uint8_t> kOddHexValue = {1, 2, 3, 4};
EXPECT_EQ(vec_value, kOddHexValue);
EXPECT_FALSE(list.GetHexSequence("INVALID-HEX", &string_value));
EXPECT_FALSE(list.GetHexSequence("NULL-HEX", &string_value));
EXPECT_FALSE(list.GetHexSequence("NOT-HEX", &string_value));
EXPECT_FALSE(list.GetHexSequence("INVALID-HEX", &vec_value));
EXPECT_FALSE(list.GetHexSequence("NULL-HEX", &vec_value));
EXPECT_FALSE(list.GetHexSequence("NOT-HEX", &vec_value));
}
TEST(HlsAttributeListTest, AmbiguousValues_EnumStringAsResolution) {
HlsAttributeList list;
EXPECT_TRUE(list.SetEnumString("VALID-RES", "1920x1080"));
EXPECT_TRUE(list.SetEnumString("ZERO-RES", "0x0"));
const std::string kMaxIntResString =
std::to_string(kMaxInt) + "x" + std::to_string(kMaxInt);
EXPECT_TRUE(list.SetEnumString("MAX-RES", kMaxIntResString));
// Resolution separator must be lower 'x'.
EXPECT_TRUE(list.SetEnumString("CAP-SEP-RES", "1920X1080"));
EXPECT_TRUE(list.SetEnumString("MISSING-WIDTH", "x1080"));
EXPECT_TRUE(list.SetEnumString("MISSING-HEIGHT", "1920x"));
EXPECT_TRUE(list.SetEnumString("BAD-WIDTH", "BADx1080"));
EXPECT_TRUE(list.SetEnumString("BAD-HEIGHT", "1920xBAD"));
EXPECT_TRUE(list.SetEnumString("NOT-RES", "OTHER"));
EXPECT_TRUE(list.IsType("VALID-RES", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("VALID-RES", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("ZERO-RES", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("ZERO-RES", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("MAX-RES", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("MAX-RES", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("CAP-SEP-RES", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(list.IsType("CAP-SEP-RES", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("MISSING-WIDTH", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(list.IsType("MISSING-WIDTH", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("MISSING-HEIGHT", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(
list.IsType("MISSING-HEIGHT", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("BAD-WIDTH", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(list.IsType("BAD-WIDTH", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("BAD-HEIGHT", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(list.IsType("BAD-HEIGHT", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("NOT-RES", HlsAttributeList::kEnumStringType));
EXPECT_FALSE(list.IsType("NOT-RES", HlsAttributeList::kResolutionType));
uint64_t width = 0;
uint64_t height = 0;
EXPECT_TRUE(list.GetResolution("VALID-RES", &width, &height));
EXPECT_EQ(width, static_cast<uint64_t>(1920));
EXPECT_EQ(height, static_cast<uint64_t>(1080));
EXPECT_TRUE(list.GetResolution("ZERO-RES", &width, &height));
EXPECT_EQ(width, kZeroInt);
EXPECT_EQ(height, kZeroInt);
EXPECT_TRUE(list.GetResolution("MAX-RES", &width, &height));
EXPECT_EQ(width, kMaxInt);
EXPECT_EQ(height, kMaxInt);
EXPECT_FALSE(list.GetResolution("CAP-SEP-RES", &width, &height));
EXPECT_FALSE(list.GetResolution("MISSING-WIDTH", &width, &height));
EXPECT_FALSE(list.GetResolution("MISSING-HEIGHT", &width, &height));
EXPECT_FALSE(list.GetResolution("BAD-WIDTH", &width, &height));
EXPECT_FALSE(list.GetResolution("BAD-HEIGHT", &width, &height));
EXPECT_FALSE(list.GetResolution("NOT-RES", &width, &height));
}
// Note: All valid hex sequences are also valid enum strings.
TEST(HlsAttributeListTest, AmbiguousValues_HexSequenceAsEnumString) {
HlsAttributeList list;
const std::vector<uint8_t> kValueData = a2b_hex("DEADBEAF");
EXPECT_TRUE(list.SetHexSequence("VALUE", kValueData));
EXPECT_TRUE(list.IsType("VALUE", HlsAttributeList::kHexSequenceType));
EXPECT_TRUE(list.IsType("VALUE", HlsAttributeList::kEnumStringType));
std::string value;
EXPECT_TRUE(list.GetEnumString("VALUE", &value));
// Our implementation will use "0x" prefix.
EXPECT_EQ(value, "0xDEADBEAF");
}
TEST(HlsAttributeListTest, AmbiguousValues_HexSequenceAsResolution) {
HlsAttributeList list;
const std::vector<uint8_t> kValidResData = a2b_hex("1920");
EXPECT_TRUE(list.SetHexSequence("VALID-RES", kValidResData));
const std::vector<uint8_t> kZeroResData = {0};
EXPECT_TRUE(list.SetHexSequence("ZERO-RES", kZeroResData));
// Max integer length is 20 (10 bytes -> 20 hex digits)
const std::vector<uint8_t> kBigZeroResData(10, 0);
EXPECT_TRUE(list.SetHexSequence("BIG-ZERO-RES", kBigZeroResData));
const std::vector<uint8_t> kTooBigZeroResData(11, 0);
EXPECT_TRUE(list.SetHexSequence("TOO-BIG-ZERO-RES", kTooBigZeroResData));
// Max integer as hex.
const std::vector<uint8_t> kMaxResData = a2b_hex(kMaxIntString);
EXPECT_TRUE(list.SetHexSequence("MAX-RES", kMaxResData));
// Over max as hex.
const std::vector<uint8_t> kOverMaxResData = a2b_hex("18446744073709551616");
EXPECT_TRUE(list.SetHexSequence("OVER-MAX-RES", kOverMaxResData));
// Resolution must be decimal, not hex.
const std::vector<uint8_t> kNotDecimalResData = a2b_hex("B000");
EXPECT_TRUE(list.SetHexSequence("NOT-DEC-RES", kNotDecimalResData));
EXPECT_TRUE(list.IsType("VALID-RES", HlsAttributeList::kHexSequenceType));
EXPECT_TRUE(list.IsType("VALID-RES", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("ZERO-RES", HlsAttributeList::kHexSequenceType));
EXPECT_TRUE(list.IsType("ZERO-RES", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("BIG-ZERO-RES", HlsAttributeList::kHexSequenceType));
EXPECT_TRUE(list.IsType("BIG-ZERO-RES", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("MAX-RES", HlsAttributeList::kHexSequenceType));
EXPECT_TRUE(list.IsType("MAX-RES", HlsAttributeList::kResolutionType));
EXPECT_TRUE(
list.IsType("TOO-BIG-ZERO-RES", HlsAttributeList::kHexSequenceType));
EXPECT_FALSE(
list.IsType("TOO-BIG-ZERO-RES", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("OVER-MAX-RES", HlsAttributeList::kHexSequenceType));
EXPECT_FALSE(list.IsType("OVER-MAX-RES", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("NOT-DEC-RES", HlsAttributeList::kHexSequenceType));
EXPECT_FALSE(list.IsType("NOT-DEC-RES", HlsAttributeList::kResolutionType));
uint64_t width = 0;
uint64_t height = 0;
EXPECT_TRUE(list.GetResolution("VALID-RES", &width, &height));
EXPECT_EQ(width, kZeroInt);
EXPECT_EQ(height, static_cast<uint64_t>(1920));
EXPECT_TRUE(list.GetResolution("ZERO-RES", &width, &height));
EXPECT_EQ(width, kZeroInt);
EXPECT_EQ(height, kZeroInt);
EXPECT_TRUE(list.GetResolution("BIG-ZERO-RES", &width, &height));
EXPECT_EQ(width, kZeroInt);
EXPECT_EQ(height, kZeroInt);
EXPECT_TRUE(list.GetResolution("MAX-RES", &width, &height));
EXPECT_EQ(width, kZeroInt);
EXPECT_EQ(height, kMaxInt);
EXPECT_FALSE(list.GetResolution("TOO-BIG-ZERO-RES", &width, &height));
EXPECT_FALSE(list.GetResolution("OVER-MAX-RES", &width, &height));
EXPECT_FALSE(list.GetResolution("NOT-DEC-RES", &width, &height));
}
TEST(HlsAttributeListTest, AmbiguousValues_FloatAsInteger) {
HlsAttributeList list;
EXPECT_TRUE(list.SetFloat("ZERO-INT", 0.0));
EXPECT_TRUE(list.SetFloat("POSITIVE-INT", 123.0));
EXPECT_TRUE(list.SetFloat("NOT-WHOLE", 123.456));
EXPECT_TRUE(list.SetFloat("FRAC-ONLY", 0.456));
EXPECT_TRUE(list.SetFloat("NEGATIVE-INT", -10.0));
EXPECT_TRUE(list.SetFloat("MAX-FLOAT-INT", kMaxIntFloat));
EXPECT_TRUE(list.IsType("ZERO-INT", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("ZERO-INT", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("POSITIVE-INT", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("POSITIVE-INT", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("MAX-FLOAT-INT", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("MAX-FLOAT-INT", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("NOT-WHOLE", HlsAttributeList::kFloatType));
EXPECT_FALSE(list.IsType("NOT-WHOLE", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("FRAC-ONLY", HlsAttributeList::kFloatType));
EXPECT_FALSE(list.IsType("FRAC-ONLY", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("NEGATIVE-INT", HlsAttributeList::kFloatType));
EXPECT_FALSE(list.IsType("NEGATIVE-INT", HlsAttributeList::kIntegerType));
uint64_t value = 0;
EXPECT_TRUE(list.GetInteger("ZERO-INT", &value));
EXPECT_EQ(value, kZeroInt);
EXPECT_TRUE(list.GetInteger("POSITIVE-INT", &value));
EXPECT_EQ(value, static_cast<uint64_t>(123));
EXPECT_TRUE(list.GetInteger("MAX-FLOAT-INT", &value));
EXPECT_EQ(value, kMaxIntFloatInt);
EXPECT_FALSE(list.GetInteger("NOT-WHOLE", &value));
EXPECT_FALSE(list.GetInteger("FRAC-ONLY", &value));
EXPECT_FALSE(list.GetInteger("NEGATIVE-INT", &value));
}
// Note: All floating point values are valid enum strings.
TEST(HlsAttributeListTest, AmbiguousValues_FloatAsEnumString) {
HlsAttributeList list;
EXPECT_TRUE(list.SetFloat("ZERO-INT", 0.0));
EXPECT_TRUE(list.SetFloat("POSITIVE-INT", 123.0));
EXPECT_TRUE(list.SetFloat("NOT-WHOLE", 123.456));
EXPECT_TRUE(list.SetFloat("FRAC-ONLY", 0.456));
EXPECT_TRUE(list.SetFloat("NEGATIVE-INT", -10.0));
EXPECT_TRUE(list.SetFloat("MAX-FLOAT-INT", kMaxIntFloat));
EXPECT_TRUE(list.IsType("ZERO-INT", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("ZERO-INT", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("POSITIVE-INT", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("POSITIVE-INT", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("MAX-FLOAT-INT", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("MAX-FLOAT-INT", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("NOT-WHOLE", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("NOT-WHOLE", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("FRAC-ONLY", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("FRAC-ONLY", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("NEGATIVE-INT", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("NEGATIVE-INT", HlsAttributeList::kEnumStringType));
std::string value;
EXPECT_TRUE(list.GetEnumString("ZERO-INT", &value));
EXPECT_EQ(value, "0");
EXPECT_TRUE(list.GetEnumString("POSITIVE-INT", &value));
EXPECT_EQ(value, "123");
EXPECT_TRUE(list.GetEnumString("NOT-WHOLE", &value));
EXPECT_EQ(value, "123.456");
EXPECT_TRUE(list.GetEnumString("FRAC-ONLY", &value));
EXPECT_EQ(value, "0.456");
EXPECT_TRUE(list.GetEnumString("NEGATIVE-INT", &value));
EXPECT_EQ(value, "-10");
EXPECT_TRUE(list.GetEnumString("MAX-FLOAT-INT", &value));
EXPECT_EQ(value, kMaxIntFloatString);
}
// Note: All integers values are valid enum strings.
TEST(HlsAttributeListTest, AmbiguousValues_IntegerAsEnumString) {
HlsAttributeList list;
EXPECT_TRUE(list.SetInteger("ZERO-INT", kZeroInt));
EXPECT_TRUE(list.SetInteger("SOME-INT", 123456));
EXPECT_TRUE(list.SetInteger("MAX-INT", kMaxInt));
EXPECT_TRUE(list.IsType("ZERO-INT", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("ZERO-INT", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("SOME-INT", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("SOME-INT", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("MAX-INT", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("MAX-INT", HlsAttributeList::kEnumStringType));
std::string value;
EXPECT_TRUE(list.GetEnumString("ZERO-INT", &value));
EXPECT_EQ(value, "0");
EXPECT_TRUE(list.GetEnumString("SOME-INT", &value));
EXPECT_EQ(value, "123456");
EXPECT_TRUE(list.GetEnumString("MAX-INT", &value));
EXPECT_EQ(value, kMaxIntString);
}
// Note: All integer values appear as valid float values;
// however, double-precision floats have limited range.
TEST(HlsAttributeListTest, AmbiguousValues_IntegerAsFloat) {
HlsAttributeList list;
EXPECT_TRUE(list.SetInteger("ZERO-INT", kZeroInt));
EXPECT_TRUE(list.SetInteger("SOME-INT", 123456));
EXPECT_TRUE(list.SetInteger("MAX-INT-FLOAT", kMaxIntFloat));
EXPECT_TRUE(list.IsType("ZERO-INT", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("ZERO-INT", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("SOME-INT", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("SOME-INT", HlsAttributeList::kFloatType));
EXPECT_TRUE(list.IsType("MAX-INT-FLOAT", HlsAttributeList::kIntegerType));
EXPECT_TRUE(list.IsType("MAX-INT-FLOAT", HlsAttributeList::kFloatType));
double value;
EXPECT_TRUE(list.GetFloat("ZERO-INT", &value));
EXPECT_EQ(value, 0.0);
EXPECT_TRUE(list.GetFloat("SOME-INT", &value));
EXPECT_EQ(value, 123456);
EXPECT_TRUE(list.GetFloat("MAX-INT-FLOAT", &value));
EXPECT_EQ(value, kMaxIntFloat);
}
// Note: All resolutions are valid enum strings.
TEST(HlsAttributeListTest, AmbiguousValues_ResolutionAsEnumString) {
HlsAttributeList list;
EXPECT_TRUE(list.SetResolution("ZERO-RES", kZeroInt, kZeroInt));
EXPECT_TRUE(list.SetResolution("RESOLUTION", 1920, 1080));
EXPECT_TRUE(list.SetResolution("MAX-RES", kMaxInt, kMaxInt));
EXPECT_TRUE(list.IsType("ZERO-RES", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("ZERO-RES", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("RESOLUTION", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("RESOLUTION", HlsAttributeList::kEnumStringType));
EXPECT_TRUE(list.IsType("MAX-RES", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("MAX-RES", HlsAttributeList::kEnumStringType));
std::string value;
EXPECT_TRUE(list.GetEnumString("ZERO-RES", &value));
EXPECT_EQ(value, "0x0");
EXPECT_TRUE(list.GetEnumString("RESOLUTION", &value));
EXPECT_EQ(value, "1920x1080");
EXPECT_TRUE(list.GetEnumString("MAX-RES", &value));
const std::string kMaxIntResString =
std::to_string(kMaxInt) + "x" + std::to_string(kMaxInt);
EXPECT_EQ(value, kMaxIntResString);
}
TEST(HlsAttributeListTest, AmbiguousValues_ResolutionAsHexSequence) {
HlsAttributeList list;
// Note: Only appears are resolution if width is zero.
EXPECT_TRUE(list.SetResolution("ZERO-RES", kZeroInt, kZeroInt));
EXPECT_TRUE(list.SetResolution("RESOLUTION", kZeroInt, 1080));
EXPECT_TRUE(list.SetResolution("MAX-RES", kZeroInt, kMaxInt));
EXPECT_TRUE(list.SetResolution("NON-ZERO-WIDTH", 1920, 1080));
EXPECT_TRUE(list.IsType("ZERO-RES", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("ZERO-RES", HlsAttributeList::kHexSequenceType));
EXPECT_TRUE(list.IsType("RESOLUTION", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("RESOLUTION", HlsAttributeList::kHexSequenceType));
EXPECT_TRUE(list.IsType("MAX-RES", HlsAttributeList::kResolutionType));
EXPECT_TRUE(list.IsType("MAX-RES", HlsAttributeList::kHexSequenceType));
EXPECT_TRUE(list.IsType("NON-ZERO-WIDTH", HlsAttributeList::kResolutionType));
EXPECT_FALSE(
list.IsType("NON-ZERO-WIDTH", HlsAttributeList::kHexSequenceType));
std::vector<uint8_t> value;
EXPECT_TRUE(list.GetHexSequence("ZERO-RES", &value));
const std::vector<uint8_t> kZeroResData = {0};
EXPECT_EQ(value, kZeroResData);
EXPECT_TRUE(list.GetHexSequence("RESOLUTION", &value));
const std::vector<uint8_t> kResData = {0x10, 0x80};
EXPECT_EQ(value, kResData);
EXPECT_TRUE(list.GetHexSequence("MAX-RES", &value));
const std::vector<uint8_t> kMaxResData = a2b_hex(kMaxIntString);
EXPECT_EQ(value, kMaxResData);
EXPECT_FALSE(list.GetHexSequence("NON-ZERO-WIDTH", &value));
}
// Quoted strings are always unambiguous.
TEST(HlsAttributeListTest, UnambiguousValues_QuotedStringAsAnything) {
HlsAttributeList list;
// Settings to quoted values of otherwise valid types.
EXPECT_TRUE(list.SetQuotedString("INT-LIKE", "1234"));
EXPECT_TRUE(list.SetQuotedString("FLOAT-LIKE", "-12.34"));
EXPECT_TRUE(list.SetQuotedString("ENUM-LIKE", "VALUE"));
EXPECT_TRUE(list.SetQuotedString("RES-LIKE", "1920x1080"));
EXPECT_TRUE(list.SetQuotedString("HEX-LIKE", "0xDEADBEAF"));
const std::vector<HlsAttributeList::ValueType> kNonQuotedStringTypes = {
HlsAttributeList::kIntegerType, HlsAttributeList::kFloatType,
HlsAttributeList::kEnumStringType, HlsAttributeList::kResolutionType,
HlsAttributeList::kHexSequenceType};
const std::vector<std::string> names = list.GetNames();
const std::vector<std::string> kExpectedNames = {
"ENUM-LIKE", "FLOAT-LIKE", "HEX-LIKE", "INT-LIKE", "RES-LIKE"};
// Validity check, if this fails, something other that what
// this test is checking for has failed.
ASSERT_EQ(names, kExpectedNames);
for (const auto& name : names) {
EXPECT_TRUE(list.IsType(name, HlsAttributeList::kQuotedStringType))
<< "name = " << name;
for (const auto& type : kNonQuotedStringTypes) {
EXPECT_FALSE(list.IsType(name, type))
<< "name = " << name
<< ", type = " << HlsAttributeList::ValueTypeToString(type);
}
}
// Accessor test for only similar looking types.
uint64_t int_value = 0;
EXPECT_FALSE(list.GetInteger("INT-LIKE", &int_value));
double float_value = 0.0;
EXPECT_FALSE(list.GetFloat("FLOAT-LIKE", &float_value));
std::string string_value;
EXPECT_FALSE(list.GetEnumString("ENUM-LIKE", &string_value));
EXPECT_FALSE(list.GetHexSequence("HEX-LIKE", &string_value));
std::vector<uint8_t> vec_value;
EXPECT_FALSE(list.GetHexSequence("HEX-LIKE", &vec_value));
uint64_t other_int_value = 0;
EXPECT_FALSE(list.GetResolution("RES-LIKE", &int_value, &other_int_value));
}
// Nothing can appear as a quoted string.
TEST(HlsAttributeListTest, UnambiguousValues_AnythingAsQuotedString) {
HlsAttributeList list;
EXPECT_TRUE(list.SetInteger("INT", 1234));
EXPECT_TRUE(list.SetHexSequence("HEX", "data"));
EXPECT_TRUE(list.SetEnumString("ENUM", "VALUE"));
EXPECT_TRUE(list.SetFloat("FLOAT", 12.34));
EXPECT_TRUE(list.SetResolution("RESOLUTION", 1920, 1080));
const std::vector<HlsAttributeList::ValueType> kNonQuotedStringTypes = {
HlsAttributeList::kIntegerType, HlsAttributeList::kFloatType,
HlsAttributeList::kEnumStringType, HlsAttributeList::kResolutionType,
HlsAttributeList::kHexSequenceType};
const std::vector<std::string> names = list.GetNames();
const std::vector<std::string> kExpectedNames = {"ENUM", "FLOAT", "HEX",
"INT", "RESOLUTION"};
// Validity check, if this fails, something other that what
// this test is checking for has failed.
ASSERT_EQ(names, kExpectedNames);
for (const auto& name : names) {
EXPECT_FALSE(list.IsType(name, HlsAttributeList::kQuotedStringType))
<< "name = " << name;
std::string value;
EXPECT_FALSE(list.GetQuotedString(name, &value));
}
}
// Integers can never appear are hex sequences or resolutions.
// Note: Also quoted strings, tested above.
TEST(HlsAttributeListTest, UnambiguousValues_Integer) {
HlsAttributeList list;
EXPECT_TRUE(list.SetInteger("ZERO-INT", kZeroInt));
EXPECT_TRUE(list.SetInteger("SOME-INT", 1234));
EXPECT_TRUE(list.SetInteger("MAX-INT", kMaxInt));
const std::vector<std::string> names = list.GetNames();
ASSERT_EQ(names.size(), static_cast<size_t>(3));
for (const auto& name : names) {
EXPECT_TRUE(list.IsType(name, HlsAttributeList::kIntegerType))
<< "name = " << name;
EXPECT_FALSE(list.IsType(name, HlsAttributeList::kHexSequenceType))
<< "name = " << name;
EXPECT_FALSE(list.IsType(name, HlsAttributeList::kResolutionType))
<< "name = " << name;
std::string string_value;
EXPECT_FALSE(list.GetHexSequence(name, &string_value)) << "name = " << name;
std::vector<uint8_t> vec_value;
EXPECT_FALSE(list.GetHexSequence(name, &vec_value)) << "name = " << name;
uint64_t width = 0;
uint64_t height = 0;
EXPECT_FALSE(list.GetResolution(name, &width, &height))
<< "name = " << name;
}
}
// Hex sequences can never appear as integers or floats.
// Note: Also quoted strings, tested above.
TEST(HlsAttributeListTest, UnambiguousValues_HexSequence) {
HlsAttributeList list;
const std::vector<uint8_t> kSmallZeroData = {0};
EXPECT_TRUE(list.SetHexSequence("SMALL-ZERO", kSmallZeroData));
const std::vector<uint8_t> kBigZeroData(10, 0);
EXPECT_TRUE(list.SetHexSequence("BIG-ZERO", kBigZeroData));
const std::vector<uint8_t> kDecimalData = a2b_hex("1234");
EXPECT_TRUE(list.SetHexSequence("DEC", kDecimalData));
const std::vector<uint8_t> kHexData = a2b_hex("deadbeaf");
EXPECT_TRUE(list.SetHexSequence("HEX", kHexData));
const std::vector<std::string> names = list.GetNames();
ASSERT_EQ(names.size(), static_cast<size_t>(4));
for (const auto& name : names) {
EXPECT_TRUE(list.IsType(name, HlsAttributeList::kHexSequenceType))
<< "name = " << name;
EXPECT_FALSE(list.IsType(name, HlsAttributeList::kIntegerType))
<< "name = " << name;
EXPECT_FALSE(list.IsType(name, HlsAttributeList::kFloatType))
<< "name = " << name;
uint64_t int_value = 0;
EXPECT_FALSE(list.GetInteger(name, &int_value)) << "name = " << name;
double float_value = 0.0;
EXPECT_FALSE(list.GetFloat(name, &float_value)) << "name = " << name;
}
}
// Floats can never appear as hex sequences or resolutions.
// Note: Also quoted strings, tested above.
TEST(HlsAttributeListTest, UnambiguousValues_Float) {
HlsAttributeList list;
EXPECT_TRUE(list.SetFloat("ZERO", 0.0));
EXPECT_TRUE(list.SetFloat("MAX-INT-FLOAT", kMaxIntFloat));
EXPECT_TRUE(list.SetFloat("SOME-FLOAT", 12.34));
const std::vector<std::string> names = list.GetNames();
ASSERT_EQ(names.size(), static_cast<size_t>(3));
for (const auto& name : names) {
EXPECT_TRUE(list.IsType(name, HlsAttributeList::kFloatType))
<< "name = " << name;
EXPECT_FALSE(list.IsType(name, HlsAttributeList::kHexSequenceType))
<< "name = " << name;
EXPECT_FALSE(list.IsType(name, HlsAttributeList::kResolutionType))
<< "name = " << name;
std::string string_value;
EXPECT_FALSE(list.GetHexSequence(name, &string_value)) << "name = " << name;
std::vector<uint8_t> vec_value;
EXPECT_FALSE(list.GetHexSequence(name, &vec_value)) << "name = " << name;
uint64_t width = 0;
uint64_t height = 0;
EXPECT_FALSE(list.GetResolution(name, &width, &height))
<< "name = " << name;
}
}
// Resolutions can never appear as integers or floats.
// Note: Also quoted strings, tested above.
TEST(HlsAttributeListTest, UnambiguousValues_Resolution) {
HlsAttributeList list;
EXPECT_TRUE(list.SetResolution("ZERO-RES", kZeroInt, kZeroInt));
EXPECT_TRUE(list.SetResolution("SOME-RES", 1920, 1080));
EXPECT_TRUE(list.SetResolution("ZERO-WIDTH-RES", kZeroInt, 1080));
EXPECT_TRUE(list.SetResolution("ZERO-HEIGHT-RES", 1920, kZeroInt));
EXPECT_TRUE(list.SetResolution("MAX-RES", kMaxInt, kMaxInt));
const std::vector<std::string> names = list.GetNames();
ASSERT_EQ(names.size(), static_cast<size_t>(5));
for (const auto& name : names) {
EXPECT_TRUE(list.IsType(name, HlsAttributeList::kResolutionType))
<< "name = " << name;
EXPECT_FALSE(list.IsType(name, HlsAttributeList::kIntegerType))
<< "name = " << name;
EXPECT_FALSE(list.IsType(name, HlsAttributeList::kFloatType))
<< "name = " << name;
uint64_t int_value = 0;
EXPECT_FALSE(list.GetInteger(name, &int_value)) << "name = " << name;
double float_value = 0.0;
EXPECT_FALSE(list.GetFloat(name, &float_value)) << "name = " << name;
}
}
TEST(HlsAttributeListTest, Parse_SingleInteger) {
const std::string rep = "INSTREAM-ID=32";
HlsAttributeList list;
EXPECT_TRUE(list.Parse(rep));
EXPECT_FALSE(list.IsEmpty());
EXPECT_EQ(list.Count(), static_cast<size_t>(1));
const uint64_t kInStreamId = 32;
uint64_t value = 0;
EXPECT_TRUE(list.GetInteger("INSTREAM-ID", &value));
EXPECT_EQ(value, kInStreamId);
}
TEST(HlsAttributeListTest, Parse_SingleFloat) {
const std::string rep = "FRAME-RATE=29.97";
HlsAttributeList list;
EXPECT_TRUE(list.Parse(rep));
EXPECT_FALSE(list.IsEmpty());
EXPECT_EQ(list.Count(), static_cast<size_t>(1));
const double kFrameRate = 29.97;
double value = 0;
EXPECT_TRUE(list.GetFloat("FRAME-RATE", &value));
EXPECT_EQ(value, kFrameRate);
}
TEST(HlsAttributeListTest, Parse_SingleEnumString) {
const std::string rep = "METHOD=AES-128";
HlsAttributeList list;
EXPECT_TRUE(list.Parse(rep));
EXPECT_FALSE(list.IsEmpty());
EXPECT_EQ(list.Count(), static_cast<size_t>(1));
const std::string kMethod = "AES-128";
std::string value;
EXPECT_TRUE(list.GetEnumString("METHOD", &value));
EXPECT_EQ(value, kMethod);
}
TEST(HlsAttributeListTest, Parse_SingleQuotedString) {
const std::string rep = "VERSION=\"1/2/5\"";
HlsAttributeList list;
EXPECT_TRUE(list.Parse(rep));
EXPECT_FALSE(list.IsEmpty());
EXPECT_EQ(list.Count(), static_cast<size_t>(1));
const std::string kVersion = "1/2/5";
std::string value;
EXPECT_TRUE(list.GetQuotedString("VERSION", &value));
EXPECT_EQ(value, kVersion);
}
TEST(HlsAttributeListTest, Parse_SingleEmptyQuotedString) {
const std::string rep = "KEYFORMAT=\"\"";
HlsAttributeList list;
EXPECT_TRUE(list.Parse(rep));
EXPECT_FALSE(list.IsEmpty());
EXPECT_EQ(list.Count(), static_cast<size_t>(1));
std::string value = "NOT-EMPTY";
EXPECT_TRUE(list.GetQuotedString("KEYFORMAT", &value));
EXPECT_EQ(value, "");
}
TEST(HlsAttributeListTest, Parse_SingleHexSequence) {
const std::string rep = "IV=0xDEADBEAF";
HlsAttributeList list;
EXPECT_TRUE(list.Parse(rep));
EXPECT_FALSE(list.IsEmpty());
EXPECT_EQ(list.Count(), static_cast<size_t>(1));
const std::string kIvString = a2bs_hex("DEADBEAF");
const std::vector<uint8_t> kIvVector(kIvString.begin(), kIvString.end());
std::string string_value;
EXPECT_TRUE(list.GetHexSequence("IV", &string_value));
EXPECT_EQ(string_value, kIvString);
std::vector<uint8_t> vec_value;
EXPECT_TRUE(list.GetHexSequence("IV", &vec_value));
EXPECT_EQ(vec_value, kIvVector);
}
TEST(HlsAttributeListTest, Parse_SingleResolution) {
const std::string rep = "RESOLUTION=1920x1080";
HlsAttributeList list;
EXPECT_TRUE(list.Parse(rep));
EXPECT_FALSE(list.IsEmpty());
EXPECT_EQ(list.Count(), static_cast<size_t>(1));
const uint64_t kWidth = 1920;
const uint64_t kHeight = 1080;
uint64_t width = 0;
uint64_t height = 0;
EXPECT_TRUE(list.GetResolution("RESOLUTION", &width, &height));
EXPECT_EQ(width, kWidth);
EXPECT_EQ(height, kHeight);
}
TEST(HlsAttributeListTest, Parse_OneOfEach) {
const uint64_t kInStreamId = 32;
const double kFrameRate = 29.97;
const std::string kIvString = a2bs_hex("DEADBEAF");
const uint64_t kWidth = 1920;
const uint64_t kHeight = 1080;
std::ostringstream hls_stream;
hls_stream << "INSTREAM-ID=32,";
hls_stream << "FRAME-RATE=29.97,";
hls_stream << "METHOD=AES-128,";
hls_stream << "VERSION=\"1/2/5\",";
hls_stream << "IV=0xDEADBEAF,";
hls_stream << "RESOLUTION=1920x1080";
const std::string rep = hls_stream.str();
HlsAttributeList list;
ASSERT_TRUE(list.Parse(rep));
EXPECT_EQ(list.Count(), static_cast<size_t>(6));
const std::vector<std::string> kExpectedNames = {
"FRAME-RATE", "INSTREAM-ID", "IV", "METHOD", "RESOLUTION", "VERSION",
};
uint64_t int_value = 0;
EXPECT_TRUE(list.GetInteger("INSTREAM-ID", &int_value));
EXPECT_EQ(int_value, kInStreamId);
double float_value = 0.0;
EXPECT_TRUE(list.GetFloat("FRAME-RATE", &float_value));
EXPECT_EQ(float_value, kFrameRate);
std::string string_value;
EXPECT_TRUE(list.GetEnumString("METHOD", &string_value));
EXPECT_EQ(string_value, "AES-128");
EXPECT_TRUE(list.GetQuotedString("VERSION", &string_value));
EXPECT_EQ(string_value, "1/2/5");
EXPECT_TRUE(list.GetHexSequence("IV", &string_value));
EXPECT_EQ(string_value, kIvString);
uint64_t other_int_value = 0;
EXPECT_TRUE(list.GetResolution("RESOLUTION", &int_value, &other_int_value));
EXPECT_EQ(int_value, kWidth);
EXPECT_EQ(other_int_value, kHeight);
}
TEST(HlsAttributeListTest, Parse_KeyLike) {
// #EXT-X-KEY
const std::string uri = "data:text/plain;base64,SSdtIGEga2V5IQ==";
std::ostringstream hls_stream;
hls_stream << "METHOD=AES-128,";
hls_stream << "URI=\"" << uri << "\",";
hls_stream << "IV=0xDEADBEAFDEADBEAFDEADBEAFDEADBEAF,";
hls_stream << "KEYFORMAT=\"com.widevine\",";
hls_stream << "KEYFORMATVERSIONS=\"1/2/5\"";
const std::string rep = hls_stream.str();
HlsAttributeList list;
ASSERT_TRUE(list.Parse(rep));
EXPECT_EQ(list.Count(), static_cast<size_t>(5));
const std::vector<std::string> kExpectedNames = {
"IV", "KEYFORMAT", "KEYFORMATVERSIONS", "METHOD", "URI"};
EXPECT_EQ(list.GetNames(), kExpectedNames);
std::string string_value;
EXPECT_TRUE(list.GetEnumString("METHOD", &string_value));
EXPECT_EQ(string_value, "AES-128");
EXPECT_TRUE(list.GetQuotedString("URI", &string_value));
EXPECT_EQ(string_value, uri);
const std::string iv = a2bs_hex("DEADBEAFDEADBEAFDEADBEAFDEADBEAF");
EXPECT_TRUE(list.GetHexSequence("IV", &string_value));
EXPECT_EQ(string_value, iv);
EXPECT_TRUE(list.GetQuotedString("KEYFORMAT", &string_value));
EXPECT_EQ(string_value, "com.widevine");
EXPECT_TRUE(list.GetQuotedString("KEYFORMATVERSIONS", &string_value));
EXPECT_EQ(string_value, "1/2/5");
}
TEST(HlsAttributeListTest, Parse_MediaLike) {
// #EXT-X-MEDIA
const std::string uri = "https://media.src/playlist";
const std::string group_id = "The Best Group";
const std::string language = "en";
const std::string associated_language = "fr";
const std::string name = "The Best Captioning";
const std::string characteristics = "public.easy-to-read";
std::ostringstream hls_stream;
hls_stream << "TYPE=CLOSED-CAPTIONS,";
hls_stream << "URI=\"" << uri << "\",";
hls_stream << "GROUP-ID=\"" << group_id << "\",";
hls_stream << "LANGUAGE=\"" << language << "\",";
hls_stream << "ASSOC-LANGUAGE=\"" << associated_language << "\",";
hls_stream << "NAME=\"" << name << "\",";
hls_stream << "DEFAULT=YES,";
hls_stream << "AUTOSELECT=NO,";
hls_stream << "FORCED=NO,";
hls_stream << "INSTREAM-ID=CC1,";
hls_stream << "CHARACTERISTICS=\"" << characteristics << "\",";
hls_stream << "CHANNELS=\"1/2/4/7\"";
const std::string rep = hls_stream.str();
HlsAttributeList list;
ASSERT_TRUE(list.Parse(rep));
EXPECT_EQ(list.Count(), static_cast<size_t>(12));
const std::vector<std::string> kExpectedNames = {
"ASSOC-LANGUAGE", "AUTOSELECT", "CHANNELS", "CHARACTERISTICS",
"DEFAULT", "FORCED", "GROUP-ID", "INSTREAM-ID",
"LANGUAGE", "NAME", "TYPE", "URI"};
EXPECT_EQ(list.GetNames(), kExpectedNames);
std::string string_value;
EXPECT_TRUE(list.GetEnumString("TYPE", &string_value));
EXPECT_EQ(string_value, "CLOSED-CAPTIONS");
EXPECT_TRUE(list.GetQuotedString("URI", &string_value));
EXPECT_EQ(string_value, uri);
EXPECT_TRUE(list.GetQuotedString("GROUP-ID", &string_value));
EXPECT_EQ(string_value, group_id);
EXPECT_TRUE(list.GetQuotedString("LANGUAGE", &string_value));
EXPECT_EQ(string_value, language);
EXPECT_TRUE(list.GetQuotedString("ASSOC-LANGUAGE", &string_value));
EXPECT_EQ(string_value, associated_language);
EXPECT_TRUE(list.GetQuotedString("NAME", &string_value));
EXPECT_EQ(string_value, name);
EXPECT_TRUE(list.GetEnumString("DEFAULT", &string_value));
EXPECT_EQ(string_value, "YES");
EXPECT_TRUE(list.GetEnumString("AUTOSELECT", &string_value));
EXPECT_EQ(string_value, "NO");
string_value.clear();
EXPECT_TRUE(list.GetEnumString("FORCED", &string_value));
EXPECT_EQ(string_value, "NO");
EXPECT_TRUE(list.GetEnumString("INSTREAM-ID", &string_value));
EXPECT_EQ(string_value, "CC1");
EXPECT_TRUE(list.GetQuotedString("CHARACTERISTICS", &string_value));
EXPECT_EQ(string_value, characteristics);
EXPECT_TRUE(list.GetQuotedString("CHANNELS", &string_value));
EXPECT_EQ(string_value, "1/2/4/7");
}
TEST(HlsAttributeListTest, BadParse_MissingValue) {
HlsAttributeList list;
EXPECT_FALSE(list.Parse("A=,B=2,C=3"));
EXPECT_FALSE(list.Parse("A=1,B=,C=3"));
EXPECT_FALSE(list.Parse("A=1,B=2,C="));
}
TEST(HlsAttributeListTest, BadParse_BadWhitespace) {
HlsAttributeList list;
EXPECT_FALSE(list.Parse("KEY=THIS VALUE"));
EXPECT_FALSE(list.Parse("THIS KEY=1"));
EXPECT_FALSE(list.Parse(" A=1,B=2"));
EXPECT_FALSE(list.Parse("A =1,B=2"));
EXPECT_FALSE(list.Parse("A= 1,B=2"));
EXPECT_FALSE(list.Parse("A=1 ,B=2"));
EXPECT_FALSE(list.Parse("A=1, B=2"));
EXPECT_FALSE(list.Parse("A=1,B =2"));
EXPECT_FALSE(list.Parse("A=1,B= 2"));
EXPECT_FALSE(list.Parse("A=1,B=2 "));
}
TEST(HlsAttributeListTest, BadParse_BadQuotes) {
HlsAttributeList list;
EXPECT_FALSE(list.Parse("\"KEY\"=VALUE"));
EXPECT_FALSE(list.Parse("KEY=\"VALUE"));
EXPECT_FALSE(list.Parse("KEY=VALUE\""));
EXPECT_FALSE(list.Parse("KEY=\"VALUE\"AND"));
}
TEST(HlsAttributeListTest, Serialize) {
HlsAttributeList list;
EXPECT_TRUE(list.SetInteger("INSTREAM-ID", 32));
EXPECT_TRUE(list.SetFloat("FRAME-RATE", 29.97));
EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128"));
EXPECT_TRUE(list.SetQuotedString("VERSION", "1/2/5"));
EXPECT_TRUE(list.SetHexSequence("IV", a2b_hex("DEADBEAF")));
EXPECT_TRUE(list.SetResolution("RESOLUTION", 1920, 1080));
// Note: The HlsAttributeList class does not guarantee any particular
// order when serializing to a string.
const std::vector<std::string> kExpectedParts = {
"FRAME-RATE=29.97", "INSTREAM-ID=32",
// Note: HlsAttributeList uses lower prefix "0x" for hex sequences.
"IV=0xDEADBEAF", "METHOD=AES-128", "RESOLUTION=1920x1080",
"VERSION=\"1/2/5\""};
const std::string result = list.Serialize();
ASSERT_FALSE(result.empty());
size_t expected_length = kExpectedParts.size() - 1; // Start with commas.
for (const auto& part : kExpectedParts) {
ASSERT_TRUE(StringContains(result, part)) << "result: " << result;
expected_length += part.size();
}
EXPECT_EQ(expected_length, result.size()) << "result: " << result;
}
TEST(HlsAttributeListTest, Serialize_Empty) {
HlsAttributeList list;
EXPECT_EQ(list.Serialize(), "");
}
TEST(HlsAttributeListTest, Serialize_One) {
HlsAttributeList list;
EXPECT_TRUE(list.SetInteger("INSTREAM-ID", 32));
EXPECT_EQ(list.Serialize(), "INSTREAM-ID=32");
}
TEST(HlsAttributeListTest, Serialize_QuotedEmpty) {
HlsAttributeList list;
EXPECT_TRUE(list.SetQuotedString("VERSION", ""));
EXPECT_EQ(list.Serialize(), "VERSION=\"\"");
}
} // namespace test
} // namespace wvutil