// 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_key.h" #include #include #include #include #include #include #include "hls_attribute_list.h" #include "string_conversions.h" namespace wvutil { namespace test { TEST(HlsKeyTest, ClassConstants) { // Validity checks on the class constants. // Verify names. EXPECT_TRUE(HlsAttributeList::IsValidName(HlsKey::kMethodName)) << "METHOD key invalid: " << HlsKey::kMethodName; EXPECT_TRUE(HlsAttributeList::IsValidName(HlsKey::kUriName)) << "URI key invalid: " << HlsKey::kUriName; EXPECT_TRUE(HlsAttributeList::IsValidName(HlsKey::kIvName)) << "IV key invalid: " << HlsKey::kIvName; EXPECT_TRUE(HlsAttributeList::IsValidName(HlsKey::kKeyFormatName)) << "KEYFORMAT key invalid: " << HlsKey::kKeyFormatName; EXPECT_TRUE(HlsAttributeList::IsValidName(HlsKey::kKeyFormatVersionsName)) << "KEYFORMATVERSIONS key invalid: " << HlsKey::kKeyFormatVersionsName; // Well-known methods. EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue(HlsKey::kMethodNone)) << "METHOD=NONE value invalid: " << HlsKey::kMethodNone; EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue(HlsKey::kMethodAes128)) << "METHOD=AES-128 value invalid: " << HlsKey::kMethodAes128; EXPECT_TRUE( HlsAttributeList::IsValidEnumStringValue(HlsKey::kMethodSampleAes)) << "METHOD=SAMPLE-AES value invalid: " << HlsKey::kMethodSampleAes; } TEST(HlsKeyTest, IsValidKeyFormatVersion) { EXPECT_TRUE(HlsKey::IsValidKeyFormatVersion(1)); EXPECT_TRUE(HlsKey::IsValidKeyFormatVersion(2)); EXPECT_TRUE(HlsKey::IsValidKeyFormatVersion(1337)); EXPECT_TRUE( HlsKey::IsValidKeyFormatVersion(std::numeric_limits::max())); } TEST(HlsKeyTest, IsValidKeyFormatVersion_Invalid) { EXPECT_FALSE(HlsKey::IsValidKeyFormatVersion(0)); } TEST(HlsKeyTest, IsValidKeyFormatVersions) { const std::set kSingleVersion = {2}; EXPECT_TRUE(HlsKey::IsValidKeyFormatVersions(kSingleVersion)); const std::set kFewVersions = {1, 2, 5}; EXPECT_TRUE(HlsKey::IsValidKeyFormatVersions(kFewVersions)); const std::set kLargeVersion = { 1, 2, std::numeric_limits::max()}; EXPECT_TRUE(HlsKey::IsValidKeyFormatVersions(kLargeVersion)); } TEST(HlsKeyTest, IsValidKeyFormatVersions_Invalid) { const std::set kEmptySet; EXPECT_FALSE(HlsKey::IsValidKeyFormatVersions(kEmptySet)); const std::set kZeroOnly = {0}; EXPECT_FALSE(HlsKey::IsValidKeyFormatVersions(kZeroOnly)); const std::set kWithZero = {0, 1, 2, 5}; EXPECT_FALSE(HlsKey::IsValidKeyFormatVersions(kWithZero)); } TEST(HlsKeyTest, IsValidKeyFormatVersionListRep) { EXPECT_TRUE(HlsKey::IsValidKeyFormatVersionListRep("1")); EXPECT_TRUE(HlsKey::IsValidKeyFormatVersionListRep("1/2")); EXPECT_TRUE(HlsKey::IsValidKeyFormatVersionListRep("1/2/5")); EXPECT_TRUE(HlsKey::IsValidKeyFormatVersionListRep("1337")); } TEST(HlsKeyTest, IsValidKeyFormatVersionListRep_Invalid) { // Empty not allowed. EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("")); // Zero is not allowed. EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("0")); EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("0/2/5")); EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/0/5")); EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/2/0")); EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/2/000000")); // All must integers. EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("NONE")); EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/NONE/4")); EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/1.2/2")); EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/0xDEADBEAF")); // Cannot have empty values. EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("/2/5")); EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1//5")); EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/2/")); EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("/")); // Must be a slash separated list. EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1,0,5")); // Cannot have spaces. EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep(" 1/2/5")); EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1 /2/5")); EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/ 2/5")); EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/2 /5")); EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/2/ 5")); EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/2/5 ")); // Must fit in the 64-bit integer range. EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("100000000000000000000")); } TEST(HlsKeyTest, Empty) { const HlsKey key; EXPECT_FALSE(key.HasMethod()); EXPECT_FALSE(key.HasUri()); EXPECT_FALSE(key.HasIv()); EXPECT_FALSE(key.HasKeyFormat()); EXPECT_FALSE(key.HasKeyFormatVersions()); EXPECT_FALSE(key.HasKeyFormatVersion(1)); } TEST(HlsKeyTest, SetMethod) { HlsKey key; EXPECT_TRUE(key.SetMethod("NONE")); EXPECT_TRUE(key.HasMethod()); EXPECT_EQ(key.method(), "NONE"); key.ClearMethod(); EXPECT_FALSE(key.HasMethod()); } TEST(HlsKeyTest, SetMethod_Invalid) { HlsKey key; // Check that an invalid cannot be set. EXPECT_FALSE(key.SetMethod("NOT VALID")); EXPECT_FALSE(key.HasMethod()); EXPECT_TRUE(key.SetMethod("SAMPLE-AES")); // Check that setting an invalid method does not // overwrite the existing method. EXPECT_FALSE(key.SetMethod("NOT VALID")); EXPECT_EQ(key.method(), "SAMPLE-AES"); } TEST(HlsKeyTest, SetUri) { const std::string kSampleUri = "http://media.src/some-key"; HlsKey key; EXPECT_TRUE(key.SetUri(kSampleUri)); EXPECT_TRUE(key.HasUri()); EXPECT_EQ(key.uri(), kSampleUri); key.ClearUri(); EXPECT_FALSE(key.HasUri()); } TEST(HlsKeyTest, SetUri_Invalid) { const std::string kBadUri = "No\"quotes"; const std::string kGoodUri = "http://media.src/some-key"; HlsKey key; EXPECT_FALSE(key.SetUri(kBadUri)); EXPECT_FALSE(key.HasUri()); EXPECT_FALSE(key.SetUri("")); EXPECT_FALSE(key.HasUri()); EXPECT_TRUE(key.SetUri(kGoodUri)); EXPECT_FALSE(key.SetUri(kBadUri)); EXPECT_EQ(key.uri(), kGoodUri); } TEST(HlsKeyTest, SetIv_Vec) { const std::vector kGoodIv(HlsKey::kIvLength, 42); HlsKey key; EXPECT_TRUE(key.SetIv(kGoodIv)); EXPECT_TRUE(key.HasIv()); EXPECT_EQ(key.iv(), kGoodIv); key.ClearIv(); EXPECT_FALSE(key.HasIv()); } TEST(HlsKeyTest, SetIv_Vec_Invalid) { const std::vector kGoodIv(HlsKey::kIvLength, 42); const std::vector kEmptyIv; const std::vector kShortIv(HlsKey::kIvLength / 2, 22); const std::vector kLargeIv(HlsKey::kIvLength * 2, 22); HlsKey key; EXPECT_FALSE(key.SetIv(kEmptyIv)); EXPECT_FALSE(key.SetIv(kShortIv)); EXPECT_FALSE(key.SetIv(kLargeIv)); EXPECT_FALSE(key.HasIv()); EXPECT_TRUE(key.SetIv(kGoodIv)); EXPECT_FALSE(key.SetIv(kShortIv)); EXPECT_EQ(key.iv(), kGoodIv); } TEST(HlsKeyTest, SetIv_String) { const std::string kGoodIv(HlsKey::kIvLength, 'x'); HlsKey key; EXPECT_TRUE(key.SetIv(kGoodIv)); EXPECT_TRUE(key.HasIv()); const std::vector kGoodIvVec(kGoodIv.begin(), kGoodIv.end()); EXPECT_EQ(key.iv(), kGoodIvVec); key.ClearIv(); EXPECT_FALSE(key.HasIv()); } TEST(HlsKeyTest, SetIv_String_Invalid) { const std::vector kGoodIv(HlsKey::kIvLength, 42); const std::string kEmptyIv; const std::string kShortIv(HlsKey::kIvLength / 2, 'y'); const std::string kLargeIv(HlsKey::kIvLength * 2, 'z'); HlsKey key; EXPECT_FALSE(key.SetIv(kEmptyIv)); EXPECT_FALSE(key.SetIv(kShortIv)); EXPECT_FALSE(key.SetIv(kLargeIv)); EXPECT_FALSE(key.HasIv()); EXPECT_TRUE(key.SetIv(kGoodIv)); EXPECT_FALSE(key.SetIv(kShortIv)); EXPECT_EQ(key.iv(), kGoodIv); } TEST(HlsKeyTest, SetIvHex) { const std::vector kGoodIv(HlsKey::kIvLength, 42); const std::string kGoodIvHex = b2a_hex(kGoodIv); HlsKey key; EXPECT_TRUE(key.SetIvHex(kGoodIvHex)); EXPECT_TRUE(key.HasIv()); EXPECT_EQ(key.iv(), kGoodIv); key.ClearIv(); EXPECT_FALSE(key.HasIv()); } TEST(HlsKeyTest, SetIvHex_Invalid) { const std::vector kGoodIv(HlsKey::kIvLength, 42); const std::string kEmptyIvHex; const std::string kShortIvHex(HlsKey::kIvLength, 'e'); const std::string kLargeIvHex(HlsKey::kIvLength * 4, 'e'); const std::string kNonHexIv(HlsKey::kIvLength * 2, 'x'); HlsKey key; EXPECT_FALSE(key.SetIvHex(kEmptyIvHex)); EXPECT_FALSE(key.SetIvHex(kShortIvHex)); EXPECT_FALSE(key.SetIvHex(kLargeIvHex)); EXPECT_FALSE(key.SetIvHex(kNonHexIv)); EXPECT_TRUE(key.SetIv(kGoodIv)); EXPECT_FALSE(key.SetIvHex(kShortIvHex)); EXPECT_EQ(key.iv(), kGoodIv); } TEST(HlsKeyTest, SetKeyFormat) { const std::string kGoodKeyFormat = "com.widevine"; HlsKey key; EXPECT_TRUE(key.SetKeyFormat(kGoodKeyFormat)); EXPECT_TRUE(key.HasKeyFormat()); EXPECT_EQ(key.key_format(), kGoodKeyFormat); key.ClearKeyFormat(); EXPECT_FALSE(key.HasKeyFormat()); } TEST(HlsKeyTest, SetKeyFormat_Invalid) { const std::string kGoodKeyFormat = "com.widevine"; const std::string kEmptyKeyFormat; const std::string kInvalidKeyFormat = "com\"widevine"; HlsKey key; EXPECT_FALSE(key.SetKeyFormat(kEmptyKeyFormat)); EXPECT_FALSE(key.SetKeyFormat(kInvalidKeyFormat)); EXPECT_TRUE(key.SetKeyFormat(kGoodKeyFormat)); EXPECT_FALSE(key.SetKeyFormat(kInvalidKeyFormat)); EXPECT_EQ(key.key_format(), kGoodKeyFormat); } TEST(HlsKeyTest, SetKeyFormatVersions_Set) { const std::set kSingleVersion = {3}; const std::set kFewVersions = {1, 2, 5}; HlsKey key; EXPECT_TRUE(key.SetKeyFormatVersions(kSingleVersion)); EXPECT_TRUE(key.HasKeyFormatVersions()); EXPECT_EQ(key.key_format_versions(), kSingleVersion); key.ClearKeyFormatVersions(); EXPECT_FALSE(key.HasKeyFormatVersions()); EXPECT_TRUE(key.SetKeyFormatVersions(kFewVersions)); EXPECT_TRUE(key.HasKeyFormatVersions()); EXPECT_EQ(key.key_format_versions(), kFewVersions); // Ensure that set is not merging. EXPECT_TRUE(key.SetKeyFormatVersions(kSingleVersion)); EXPECT_EQ(key.key_format_versions(), kSingleVersion); } TEST(HlsKeyTest, SetKeyFormatVersions_Set_Invalid) { const std::set kSingleVersion = {3}; const std::set kBadVersions = {0, 2, 5}; HlsKey key; EXPECT_FALSE(key.SetKeyFormatVersions(kBadVersions)); EXPECT_FALSE(key.HasKeyFormatVersions()); EXPECT_TRUE(key.SetKeyFormatVersions(kSingleVersion)); EXPECT_FALSE(key.SetKeyFormatVersions(kBadVersions)); EXPECT_EQ(key.key_format_versions(), kSingleVersion); } TEST(HlsKeyTest, SetKeyFormatVersions_Vec) { const std::vector kSingleVersionVec = {3}; const std::vector kFewVersionsVec = {1, 2, 5}; const std::vector kRepeatedVersionsVec = {1, 1, 2, 5, 5, 5, 5, 5}; const std::set kSingleVersion = {3}; const std::set kFewVersions = {1, 2, 5}; HlsKey key; EXPECT_TRUE(key.SetKeyFormatVersions(kSingleVersionVec)); EXPECT_TRUE(key.HasKeyFormatVersions()); EXPECT_EQ(key.key_format_versions(), kSingleVersion); key.ClearKeyFormatVersions(); EXPECT_FALSE(key.HasKeyFormatVersions()); EXPECT_TRUE(key.SetKeyFormatVersions(kFewVersionsVec)); EXPECT_TRUE(key.HasKeyFormatVersions()); EXPECT_EQ(key.key_format_versions(), kFewVersions); // Ensure that set is not merging. EXPECT_TRUE(key.SetKeyFormatVersions(kSingleVersionVec)); EXPECT_EQ(key.key_format_versions(), kSingleVersion); // Ensure that repeated values are not stored. EXPECT_TRUE(key.SetKeyFormatVersions(kRepeatedVersionsVec)); EXPECT_EQ(key.key_format_versions(), kFewVersions); } TEST(HlsKeyTest, SetKeyFormatVersions_Vec_Invalid) { const std::set kSingleVersion = {3}; const std::vector kBadVersionsVec = {1, 2, 0, 5}; HlsKey key; EXPECT_FALSE(key.SetKeyFormatVersions(kBadVersionsVec)); EXPECT_FALSE(key.HasKeyFormatVersions()); EXPECT_TRUE(key.SetKeyFormatVersions(kSingleVersion)); EXPECT_FALSE(key.SetKeyFormatVersions(kBadVersionsVec)); EXPECT_EQ(key.key_format_versions(), kSingleVersion); } TEST(HlsKeyTest, HasKeyFormatVersion) { const std::set kFewVersions = {1, 2, 5}; HlsKey key; EXPECT_FALSE(key.HasKeyFormatVersion(1)); EXPECT_FALSE(key.HasKeyFormatVersion(std::numeric_limits::max())); EXPECT_TRUE(key.SetKeyFormatVersions(kFewVersions)); EXPECT_FALSE(key.HasKeyFormatVersion(0)); EXPECT_TRUE(key.HasKeyFormatVersion(1)); EXPECT_TRUE(key.HasKeyFormatVersion(2)); EXPECT_FALSE(key.HasKeyFormatVersion(3)); EXPECT_FALSE(key.HasKeyFormatVersion(4)); EXPECT_TRUE(key.HasKeyFormatVersion(5)); EXPECT_FALSE(key.HasKeyFormatVersion(std::numeric_limits::max())); } TEST(HlsKeyTest, AddKeyFormatVersion) { const std::set kFewVersions = {1, 2, 5}; HlsKey key; EXPECT_TRUE(key.AddKeyFormatVersion(1)); EXPECT_TRUE(key.AddKeyFormatVersion(2)); EXPECT_TRUE(key.AddKeyFormatVersion(5)); EXPECT_EQ(key.key_format_versions(), kFewVersions); // Repeated adds doesn't count as error. EXPECT_TRUE(key.AddKeyFormatVersion(5)); // Cannot add invalid. EXPECT_FALSE(key.AddKeyFormatVersion(0)); EXPECT_EQ(key.key_format_versions(), kFewVersions); } TEST(HlsKeyTest, IsWellFormed_Empty) { const HlsKey key; EXPECT_FALSE(key.IsWellFormed()); } TEST(HlsKeyTest, IsWellFormed_MethodNone) { HlsKey key; EXPECT_TRUE(key.SetMethod("NONE")); EXPECT_TRUE(key.IsWellFormed()); } // When method is none, all other fields must be empty. TEST(HlsKeyTest, IsWellFormed_MethodNone_Invalid) { HlsKey key; EXPECT_TRUE(key.SetMethod("NONE")); // With URI. EXPECT_TRUE(key.SetUri("http://domain.tld/key")); EXPECT_FALSE(key.IsWellFormed()); key.ClearUri(); // With IV. EXPECT_TRUE(key.SetIv(std::vector(HlsKey::kIvLength, 42))); EXPECT_FALSE(key.IsWellFormed()); key.ClearIv(); // With key format. EXPECT_TRUE(key.SetKeyFormat("com.widevine")); EXPECT_FALSE(key.IsWellFormed()); key.ClearKeyFormat(); // With key format versions. EXPECT_TRUE(key.AddKeyFormatVersion(1)); EXPECT_FALSE(key.IsWellFormed()); key.ClearKeyFormatVersions(); // Should be well-formed again. EXPECT_TRUE(key.IsWellFormed()); } TEST(HlsKeyTest, IsWellFormed_MethodNonNone) { HlsKey key; EXPECT_TRUE(key.SetMethod("AES-128")); // Required fields. EXPECT_TRUE(key.SetUri("http://domain.tld/key")); EXPECT_TRUE(key.SetIv(std::vector(HlsKey::kIvLength, 42))); EXPECT_TRUE(key.IsWellFormed()); // Optional fields. EXPECT_TRUE(key.SetKeyFormat("com.widevine")); EXPECT_TRUE(key.IsWellFormed()); EXPECT_TRUE(key.AddKeyFormatVersion(1)); EXPECT_TRUE(key.IsWellFormed()); } TEST(HlsKeyTest, IsWellFormed_MethodNonNone_Invalid) { HlsKey key; EXPECT_TRUE(key.SetMethod("AES-128")); // Missing required all fields. EXPECT_FALSE(key.IsWellFormed()); // URI is the only required field. EXPECT_TRUE(key.SetUri("http://domain.tld/key")); EXPECT_TRUE(key.IsWellFormed()); // Missing URI. key.ClearUri(); EXPECT_FALSE(key.IsWellFormed()); } TEST(HlsKeyTest, FromAttributeList_MethodNone) { HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("METHOD", "NONE")); HlsKey key; EXPECT_TRUE(key.FromAttributeList(list)); EXPECT_TRUE(key.IsWellFormed()); EXPECT_EQ(key.method(), "NONE"); EXPECT_FALSE(key.HasUri()); EXPECT_FALSE(key.HasIv()); EXPECT_FALSE(key.HasKeyFormat()); EXPECT_FALSE(key.HasKeyFormatVersions()); } TEST(HlsKeyTest, FromAttributeList_MethodNone_IgnoreOtherFields) { // The HLS specification states that if METHOD is NONE, then // there should not be any other fields. However, this parser // is less strict, and will simply ignore the other fields // when reading from an attribute list. HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("METHOD", "NONE")); EXPECT_TRUE( list.SetHexSequence("IV", std::vector(HlsKey::kIvLength, 42))); EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data")); EXPECT_TRUE(list.SetQuotedString("KEYFORMAT", "com.example")); EXPECT_TRUE(list.SetQuotedString("KEYFORMATVERSIONS", "1337")); HlsKey key; EXPECT_TRUE(key.FromAttributeList(list)); EXPECT_TRUE(key.IsWellFormed()); EXPECT_EQ(key.method(), "NONE"); EXPECT_FALSE(key.HasUri()); EXPECT_FALSE(key.HasIv()); EXPECT_FALSE(key.HasKeyFormat()); EXPECT_FALSE(key.HasKeyFormatVersions()); } TEST(HlsKeyTest, FromAttributeList_MethodNonNone_OnlyRequiredFields) { const std::vector kIv(HlsKey::kIvLength, 42); const std::string kUri = "http://domain.tld/key"; // HLS standard says to use the following defaults if not // present in the HLS list. const std::string kDefaultKeyFormat = "identity"; const std::set kDefaultKeyFormatVersions = {1}; HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128")); EXPECT_TRUE(list.SetHexSequence("IV", kIv)); EXPECT_TRUE(list.SetQuotedString("URI", kUri)); HlsKey key; EXPECT_TRUE(key.FromAttributeList(list)); EXPECT_TRUE(key.IsWellFormed()); EXPECT_EQ(key.method(), "AES-128"); EXPECT_EQ(key.uri(), kUri); EXPECT_EQ(key.iv(), kIv); EXPECT_EQ(key.key_format(), kDefaultKeyFormat); EXPECT_EQ(key.key_format_versions(), kDefaultKeyFormatVersions); } TEST(HlsKeyTest, FromAttributeList_MethodNonNone_AllFields) { const std::vector kIv(HlsKey::kIvLength, 42); const std::string kUri = "http://domain.tld/key"; const std::string kKeyFormat = "com.widevine"; const std::set kKeyFormatVersion = {1, 2, 5}; HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("METHOD", "SAMPLE-AES")); EXPECT_TRUE(list.SetHexSequence("IV", kIv)); EXPECT_TRUE(list.SetQuotedString("URI", kUri)); EXPECT_TRUE(list.SetQuotedString("KEYFORMAT", kKeyFormat)); EXPECT_TRUE(list.SetQuotedString("KEYFORMATVERSIONS", "1/2/5")); HlsKey key; EXPECT_TRUE(key.FromAttributeList(list)); EXPECT_TRUE(key.IsWellFormed()); EXPECT_EQ(key.method(), "SAMPLE-AES"); EXPECT_EQ(key.uri(), kUri); EXPECT_EQ(key.iv(), kIv); EXPECT_EQ(key.key_format(), kKeyFormat); EXPECT_EQ(key.key_format_versions(), kKeyFormatVersion); } TEST(HlsKeyTest, FromAttributeList_MissingFields_All) { HlsAttributeList list; HlsKey key; EXPECT_FALSE(key.FromAttributeList(list)); } TEST(HlsKeyTest, FromAttributeList_MissingFields_Method) { const std::string kUri = "http://domain.tld/key"; const std::vector kIv(HlsKey::kIvLength, 42); HlsAttributeList list; EXPECT_TRUE(list.SetQuotedString("URI", kUri)); EXPECT_TRUE(list.SetHexSequence("IV", kIv)); HlsKey key; EXPECT_FALSE(key.FromAttributeList(list)); // Nothing should be set. EXPECT_FALSE(key.HasUri()); EXPECT_FALSE(key.HasIv()); } TEST(HlsKeyTest, FromAttributeList_MissingFields_MissingUri) { const std::vector kIv(HlsKey::kIvLength, 42); HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128")); EXPECT_TRUE(list.SetHexSequence("IV", kIv)); HlsKey key; EXPECT_FALSE(key.FromAttributeList(list)); // Nothing should be set. EXPECT_FALSE(key.HasMethod()); EXPECT_FALSE(key.HasIv()); } TEST(HlsKeyTest, FromAttributeList_InvalidFields_BadMethodType) { HlsAttributeList list; // Must be enum string not quoted string. EXPECT_TRUE(list.SetQuotedString("METHOD", "NONE")); HlsKey key; EXPECT_FALSE(key.FromAttributeList(list)); EXPECT_FALSE(key.HasMethod()); } TEST(HlsKeyTest, FromAttributeList_InvalidFields_EmptyUri) { const std::vector kIv(HlsKey::kIvLength, 42); HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128")); EXPECT_TRUE(list.SetQuotedString("URI", "")); EXPECT_TRUE(list.SetHexSequence("IV", kIv)); HlsKey key; EXPECT_FALSE(key.FromAttributeList(list)); // Nothing should be set. EXPECT_FALSE(key.HasMethod()); EXPECT_FALSE(key.HasUri()); EXPECT_FALSE(key.HasIv()); } TEST(HlsKeyTest, FromAttributeList_InvalidFields_BadUriType) { const std::vector kIv(HlsKey::kIvLength, 42); HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128")); EXPECT_TRUE(list.SetEnumString("URI", "DATA")); EXPECT_TRUE(list.SetHexSequence("IV", kIv)); HlsKey key; EXPECT_FALSE(key.FromAttributeList(list)); // Nothing should be set. EXPECT_FALSE(key.HasMethod()); EXPECT_FALSE(key.HasUri()); EXPECT_FALSE(key.HasIv()); } TEST(HlsKeyTest, FromAttributeList_InvalidFields_ShortIv) { const std::vector kShortIv(HlsKey::kIvLength / 2, 42); HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128")); EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data")); EXPECT_TRUE(list.SetHexSequence("IV", kShortIv)); HlsKey key; EXPECT_FALSE(key.FromAttributeList(list)); EXPECT_FALSE(key.HasMethod()); EXPECT_FALSE(key.HasUri()); EXPECT_FALSE(key.HasIv()); } TEST(HlsKeyTest, FromAttributeList_InvalidFields_LargeIv) { const std::vector kLargeIv(HlsKey::kIvLength * 2, 42); HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128")); EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data")); EXPECT_TRUE(list.SetHexSequence("IV", kLargeIv)); HlsKey key; EXPECT_FALSE(key.FromAttributeList(list)); EXPECT_FALSE(key.HasMethod()); EXPECT_FALSE(key.HasUri()); EXPECT_FALSE(key.HasIv()); } TEST(HlsKeyTest, FromAttributeList_InvalidFields_BadIvType) { HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128")); EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data")); EXPECT_TRUE(list.SetQuotedString("IV", "42 repeated 16 times")); HlsKey key; EXPECT_FALSE(key.FromAttributeList(list)); EXPECT_FALSE(key.HasMethod()); EXPECT_FALSE(key.HasUri()); EXPECT_FALSE(key.HasIv()); } TEST(HlsKeyTest, FromAttributeList_InvalidFields_EmptyKeyFormat) { const std::vector kIv(HlsKey::kIvLength, 42); HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128")); EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data")); EXPECT_TRUE(list.SetHexSequence("IV", kIv)); EXPECT_TRUE(list.SetQuotedString("KEYFORMAT", "")); HlsKey key; EXPECT_FALSE(key.FromAttributeList(list)); // Nothing should be set. EXPECT_FALSE(key.HasMethod()); EXPECT_FALSE(key.HasUri()); EXPECT_FALSE(key.HasIv()); } TEST(HlsKeyTest, FromAttributeList_InvalidFields_BadKeyFormatType) { const std::vector kIv(HlsKey::kIvLength, 42); HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128")); EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data")); EXPECT_TRUE(list.SetHexSequence("IV", kIv)); EXPECT_TRUE(list.SetEnumString("KEYFORMAT", "COM-EXAMPLE")); HlsKey key; EXPECT_FALSE(key.FromAttributeList(list)); // Nothing should be set. EXPECT_FALSE(key.HasMethod()); EXPECT_FALSE(key.HasUri()); EXPECT_FALSE(key.HasIv()); EXPECT_FALSE(key.HasKeyFormat()); } TEST(HlsKeyTest, FromAttributeList_InvalidFields_EmptyKeyFormatVersions) { const std::vector kIv(HlsKey::kIvLength, 42); HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128")); EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data")); EXPECT_TRUE(list.SetHexSequence("IV", kIv)); EXPECT_TRUE(list.SetQuotedString("KEYFORMAT", "com.example")); EXPECT_TRUE(list.SetQuotedString("KEYFORMATVERSIONS", "")); HlsKey key; EXPECT_FALSE(key.FromAttributeList(list)); // Nothing should be set. EXPECT_FALSE(key.HasMethod()); EXPECT_FALSE(key.HasUri()); EXPECT_FALSE(key.HasIv()); EXPECT_FALSE(key.HasKeyFormat()); } TEST(HlsKeyTest, FromAttributeList_InvalidFields_ZeroKeyFormatVersions) { const std::vector kIv(HlsKey::kIvLength, 42); HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128")); EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data")); EXPECT_TRUE(list.SetHexSequence("IV", kIv)); EXPECT_TRUE(list.SetQuotedString("KEYFORMAT", "com.example")); EXPECT_TRUE(list.SetQuotedString("KEYFORMATVERSIONS", "0/1/5")); HlsKey key; EXPECT_FALSE(key.FromAttributeList(list)); // Nothing should be set. EXPECT_FALSE(key.HasMethod()); EXPECT_FALSE(key.HasUri()); EXPECT_FALSE(key.HasIv()); EXPECT_FALSE(key.HasKeyFormat()); EXPECT_FALSE(key.HasKeyFormatVersions()); } TEST(HlsKeyTest, FromAttributeList_InvalidFields_BadKeyFormatVersionsFormat) { const std::vector kIv(HlsKey::kIvLength, 42); HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128")); EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data")); EXPECT_TRUE(list.SetHexSequence("IV", kIv)); EXPECT_TRUE(list.SetQuotedString("KEYFORMAT", "com.example")); EXPECT_TRUE(list.SetQuotedString("KEYFORMATVERSIONS", "1,2,5")); HlsKey key; EXPECT_FALSE(key.FromAttributeList(list)); // Nothing should be set. EXPECT_FALSE(key.HasMethod()); EXPECT_FALSE(key.HasUri()); EXPECT_FALSE(key.HasIv()); EXPECT_FALSE(key.HasKeyFormat()); EXPECT_FALSE(key.HasKeyFormatVersions()); } TEST(HlsKeyTest, FromAttributeList_InvalidFields_BadKeyFormatVersionsType) { const std::vector kIv(HlsKey::kIvLength, 42); HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128")); EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data")); EXPECT_TRUE(list.SetHexSequence("IV", kIv)); EXPECT_TRUE(list.SetQuotedString("KEYFORMAT", "com.example")); EXPECT_TRUE(list.SetInteger("KEYFORMATVERSIONS", 1)); HlsKey key; EXPECT_FALSE(key.FromAttributeList(list)); // Nothing should be set. EXPECT_FALSE(key.HasMethod()); EXPECT_FALSE(key.HasUri()); EXPECT_FALSE(key.HasIv()); EXPECT_FALSE(key.HasKeyFormat()); EXPECT_FALSE(key.HasKeyFormatVersions()); } TEST(HlsKeyTest, FromAttributeList_InvalidList) { // Populate HLS Attribute List as if it is a different message. // Using EXT-X-MEDIA. HlsAttributeList list; EXPECT_TRUE(list.SetEnumString("TYPE", "AUDIO")); EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/video-data")); EXPECT_TRUE(list.SetQuotedString("GROUP-ID", "Video Group")); EXPECT_TRUE(list.SetQuotedString("LANGUAGE", "en")); EXPECT_TRUE(list.SetQuotedString("NAME", "A nice video")); EXPECT_TRUE(list.SetEnumString("DEFAULT", "YES")); HlsKey key; EXPECT_FALSE(key.FromAttributeList(list)); } TEST(HlsKeyTest, ParseAttributeList_MethodNone) { HlsKey key; EXPECT_TRUE(key.ParseAttributeList("METHOD=NONE")); EXPECT_TRUE(key.IsWellFormed()); EXPECT_EQ(key.method(), "NONE"); } TEST(HlsKeyTest, ParseAttributeList_MethodNonNone_OnlyRequiredFields) { const std::string kUri = "http://domain.tld/key"; const std::vector kEmptyIv; const std::string kDefaultKeyFormat = "identity"; const std::set kDefaultKeyFormatVersions = {1}; std::ostringstream hls_stream; hls_stream << "METHOD=AES-128,"; hls_stream << "URI=\"" << kUri << "\""; const std::string key_rep = hls_stream.str(); HlsKey key; EXPECT_TRUE(key.ParseAttributeList(key_rep)); EXPECT_TRUE(key.IsWellFormed()); EXPECT_EQ(key.method(), "AES-128"); EXPECT_EQ(key.uri(), kUri); EXPECT_EQ(key.iv(), kEmptyIv); EXPECT_EQ(key.key_format(), kDefaultKeyFormat); EXPECT_EQ(key.key_format_versions(), kDefaultKeyFormatVersions); } TEST(HlsKeyTest, ParseAttributeList_MethodNonNone_AllFields) { const std::string kIvHex(HlsKey::kIvLength * 2, 'A'); const std::vector kIv(HlsKey::kIvLength, 0xaa); const std::string kUri = "http://domain.tld/key"; const std::string kKeyFormat = "com.widevine"; const std::set kKeyFormatVersion = {1, 2, 5}; std::ostringstream hls_stream; hls_stream << "METHOD=SAMPLE-AES,"; hls_stream << "URI=\"" << kUri << "\","; hls_stream << "IV=0x" << kIvHex << ','; hls_stream << "KEYFORMAT=\"" << kKeyFormat << "\","; hls_stream << "KEYFORMATVERSIONS=\"1/2/5\""; const std::string key_rep = hls_stream.str(); HlsKey key; EXPECT_TRUE(key.ParseAttributeList(key_rep)); EXPECT_TRUE(key.IsWellFormed()); EXPECT_EQ(key.method(), "SAMPLE-AES"); EXPECT_EQ(key.uri(), kUri); EXPECT_EQ(key.iv(), kIv); EXPECT_EQ(key.key_format(), kKeyFormat); EXPECT_EQ(key.key_format_versions(), kKeyFormatVersion); } TEST(HlsKeyTest, ParseAttributeList_Empty) { HlsKey key; EXPECT_FALSE(key.ParseAttributeList("")); } TEST(HlsKeyTest, ParseAttributeList_InvalidAttributeList) { HlsKey key; EXPECT_FALSE(key.ParseAttributeList("Not an Attribute List")); } } // namespace test } // namespace wvutil