Automated update of OPK code

Included changes:

  - 676ac7be8548d80c420591fc0b4fb9a11723ef34 Backwards compatibility script for CDM v18 and OPK v19 by Vicky Min <vickymin@google.com>
  - 3cd4f71fda91245ac0b61c4c847950952f3021c0 Change BuildInformation ree fields to optional by Matt Feddersen <mattfedd@google.com>
  - a2259e95dea40c27a4be02ad479aec8f1fc84737 Created a DICE CBOR Cert parser/serializer. by Alex Dale <sigquit@google.com>
  - b8f2c364afeb6279e5aee6488d4527e189ac42ff Don't create invalid enum value by John "Juce" Bruce <juce@google.com>
  - b0aed212a3b2dd8f752d8fc43982848c1aa6c152 Created an HLS Key type. by Alex Dale <sigquit@google.com>
  - f8cfc54b41f124ba849596dbe6438b7f271a72b7 Specify C/C++ standard when running clang-tidy on OPK by John "Juce" Bruce <juce@google.com>

GitOrigin-RevId: 676ac7be8548d80c420591fc0b4fb9a11723ef34
This commit is contained in:
Googler
2025-05-13 21:44:08 +00:00
committed by mattfedd
parent a2b9e085e9
commit 5387878a5b
25 changed files with 3139 additions and 937 deletions

View File

@@ -0,0 +1,866 @@
// 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 <inttypes.h>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <gtest/gtest.h>
#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<uint64_t>::max()));
}
TEST(HlsKeyTest, IsValidKeyFormatVersion_Invalid) {
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersion(0));
}
TEST(HlsKeyTest, IsValidKeyFormatVersions) {
const std::set<uint64_t> kSingleVersion = {2};
EXPECT_TRUE(HlsKey::IsValidKeyFormatVersions(kSingleVersion));
const std::set<uint64_t> kFewVersions = {1, 2, 5};
EXPECT_TRUE(HlsKey::IsValidKeyFormatVersions(kFewVersions));
const std::set<uint64_t> kLargeVersion = {
1, 2, std::numeric_limits<uint64_t>::max()};
EXPECT_TRUE(HlsKey::IsValidKeyFormatVersions(kLargeVersion));
}
TEST(HlsKeyTest, IsValidKeyFormatVersions_Invalid) {
const std::set<uint64_t> kEmptySet;
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersions(kEmptySet));
const std::set<uint64_t> kZeroOnly = {0};
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersions(kZeroOnly));
const std::set<uint64_t> 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<uint8_t> 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<uint8_t> kGoodIv(HlsKey::kIvLength, 42);
const std::vector<uint8_t> kEmptyIv;
const std::vector<uint8_t> kShortIv(HlsKey::kIvLength / 2, 22);
const std::vector<uint8_t> 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<uint8_t> kGoodIvVec(kGoodIv.begin(), kGoodIv.end());
EXPECT_EQ(key.iv(), kGoodIvVec);
key.ClearIv();
EXPECT_FALSE(key.HasIv());
}
TEST(HlsKeyTest, SetIv_String_Invalid) {
const std::vector<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint64_t> kSingleVersion = {3};
const std::set<uint64_t> 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<uint64_t> kSingleVersion = {3};
const std::set<uint64_t> 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<uint64_t> kSingleVersionVec = {3};
const std::vector<uint64_t> kFewVersionsVec = {1, 2, 5};
const std::vector<uint64_t> kRepeatedVersionsVec = {1, 1, 2, 5, 5, 5, 5, 5};
const std::set<uint64_t> kSingleVersion = {3};
const std::set<uint64_t> 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<uint64_t> kSingleVersion = {3};
const std::vector<uint64_t> 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<uint64_t> kFewVersions = {1, 2, 5};
HlsKey key;
EXPECT_FALSE(key.HasKeyFormatVersion(1));
EXPECT_FALSE(key.HasKeyFormatVersion(std::numeric_limits<uint64_t>::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<uint64_t>::max()));
}
TEST(HlsKeyTest, AddKeyFormatVersion) {
const std::set<uint64_t> 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<uint8_t>(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<uint8_t>(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<uint8_t>(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<uint8_t> 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<uint64_t> 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<uint8_t> kIv(HlsKey::kIvLength, 42);
const std::string kUri = "http://domain.tld/key";
const std::string kKeyFormat = "com.widevine";
const std::set<uint64_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> kEmptyIv;
const std::string kDefaultKeyFormat = "identity";
const std::set<uint64_t> 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<uint8_t> kIv(HlsKey::kIvLength, 0xaa);
const std::string kUri = "http://domain.tld/key";
const std::string kKeyFormat = "com.widevine";
const std::set<uint64_t> 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