Source release 15.3.0

This commit is contained in:
John W. Bruce
2020-02-11 14:22:17 -08:00
parent 2990f23065
commit 1ff9f8588a
29 changed files with 534 additions and 153 deletions

View File

@@ -216,7 +216,7 @@ class CdmTest : public WvCdmTestBase, public Cdm::IEventListener {
// Reinit the library.
Cdm::Status status = Cdm::initialize(
Cdm::kNoSecureOutput, PropertiesCE::GetClientInfo(), g_host, g_host,
g_host, static_cast<Cdm::LogLevel>(g_cutoff));
g_host, static_cast<Cdm::LogLevel>(g_cutoff), g_sandbox_id);
ASSERT_EQ(Cdm::kSuccess, status);
// Make a fresh CDM.
@@ -541,12 +541,11 @@ TEST_F(CdmTest, TestHostTimer) {
}
TEST_F(CdmTest, Initialize) {
Cdm::Status status;
// Try with an invalid output type.
status = Cdm::initialize(static_cast<Cdm::SecureOutputType>(-1),
PropertiesCE::GetClientInfo(), g_host, g_host,
g_host, static_cast<Cdm::LogLevel>(g_cutoff));
Cdm::Status status =
Cdm::initialize(static_cast<Cdm::SecureOutputType>(-1),
PropertiesCE::GetClientInfo(), g_host, g_host, g_host,
static_cast<Cdm::LogLevel>(g_cutoff), g_sandbox_id);
EXPECT_EQ(Cdm::kTypeError, status);
// Try with various client info properties missing.
@@ -555,77 +554,77 @@ TEST_F(CdmTest, Initialize) {
broken_client_info = working_client_info;
broken_client_info.product_name.clear();
status =
Cdm::initialize(Cdm::kNoSecureOutput, broken_client_info, g_host, g_host,
g_host, static_cast<Cdm::LogLevel>(g_cutoff));
status = Cdm::initialize(Cdm::kNoSecureOutput, broken_client_info, g_host,
g_host, g_host, static_cast<Cdm::LogLevel>(g_cutoff),
g_sandbox_id);
EXPECT_EQ(Cdm::kTypeError, status);
broken_client_info = working_client_info;
broken_client_info.company_name.clear();
status =
Cdm::initialize(Cdm::kNoSecureOutput, broken_client_info, g_host, g_host,
g_host, static_cast<Cdm::LogLevel>(g_cutoff));
status = Cdm::initialize(Cdm::kNoSecureOutput, broken_client_info, g_host,
g_host, g_host, static_cast<Cdm::LogLevel>(g_cutoff),
g_sandbox_id);
EXPECT_EQ(Cdm::kTypeError, status);
broken_client_info = working_client_info;
broken_client_info.device_name.clear(); // Not required
status =
Cdm::initialize(Cdm::kNoSecureOutput, broken_client_info, g_host, g_host,
g_host, static_cast<Cdm::LogLevel>(g_cutoff));
status = Cdm::initialize(Cdm::kNoSecureOutput, broken_client_info, g_host,
g_host, g_host, static_cast<Cdm::LogLevel>(g_cutoff),
g_sandbox_id);
EXPECT_EQ(Cdm::kSuccess, status);
broken_client_info = working_client_info;
broken_client_info.model_name.clear();
status =
Cdm::initialize(Cdm::kNoSecureOutput, broken_client_info, g_host, g_host,
g_host, static_cast<Cdm::LogLevel>(g_cutoff));
status = Cdm::initialize(Cdm::kNoSecureOutput, broken_client_info, g_host,
g_host, g_host, static_cast<Cdm::LogLevel>(g_cutoff),
g_sandbox_id);
EXPECT_EQ(Cdm::kTypeError, status);
broken_client_info = working_client_info;
broken_client_info.arch_name.clear(); // Not required
status =
Cdm::initialize(Cdm::kNoSecureOutput, broken_client_info, g_host, g_host,
g_host, static_cast<Cdm::LogLevel>(g_cutoff));
status = Cdm::initialize(Cdm::kNoSecureOutput, broken_client_info, g_host,
g_host, g_host, static_cast<Cdm::LogLevel>(g_cutoff),
g_sandbox_id);
EXPECT_EQ(Cdm::kSuccess, status);
broken_client_info = working_client_info;
broken_client_info.build_info.clear(); // Not required
status =
Cdm::initialize(Cdm::kNoSecureOutput, broken_client_info, g_host, g_host,
g_host, static_cast<Cdm::LogLevel>(g_cutoff));
status = Cdm::initialize(Cdm::kNoSecureOutput, broken_client_info, g_host,
g_host, g_host, static_cast<Cdm::LogLevel>(g_cutoff),
g_sandbox_id);
EXPECT_EQ(Cdm::kSuccess, status);
// Try with various host interfaces missing.
status =
Cdm::initialize(Cdm::kNoSecureOutput, working_client_info, nullptr,
g_host, g_host, static_cast<Cdm::LogLevel>(g_cutoff));
status = Cdm::initialize(Cdm::kNoSecureOutput, working_client_info, nullptr,
g_host, g_host, static_cast<Cdm::LogLevel>(g_cutoff),
g_sandbox_id);
EXPECT_EQ(Cdm::kTypeError, status);
status =
Cdm::initialize(Cdm::kNoSecureOutput, working_client_info, g_host,
nullptr, g_host, static_cast<Cdm::LogLevel>(g_cutoff));
status = Cdm::initialize(Cdm::kNoSecureOutput, working_client_info, g_host,
nullptr, g_host,
static_cast<Cdm::LogLevel>(g_cutoff), g_sandbox_id);
EXPECT_EQ(Cdm::kTypeError, status);
status =
Cdm::initialize(Cdm::kNoSecureOutput, working_client_info, g_host, g_host,
nullptr, static_cast<Cdm::LogLevel>(g_cutoff));
status = Cdm::initialize(Cdm::kNoSecureOutput, working_client_info, g_host,
g_host, nullptr,
static_cast<Cdm::LogLevel>(g_cutoff), g_sandbox_id);
EXPECT_EQ(Cdm::kTypeError, status);
// Try all output types.
status =
Cdm::initialize(Cdm::kDirectRender, working_client_info, g_host, g_host,
g_host, static_cast<Cdm::LogLevel>(g_cutoff));
status = Cdm::initialize(Cdm::kDirectRender, working_client_info, g_host,
g_host, g_host, static_cast<Cdm::LogLevel>(g_cutoff),
g_sandbox_id);
EXPECT_EQ(Cdm::kSuccess, status);
status =
Cdm::initialize(Cdm::kOpaqueHandle, working_client_info, g_host, g_host,
g_host, static_cast<Cdm::LogLevel>(g_cutoff));
status = Cdm::initialize(Cdm::kOpaqueHandle, working_client_info, g_host,
g_host, g_host, static_cast<Cdm::LogLevel>(g_cutoff),
g_sandbox_id);
EXPECT_EQ(Cdm::kSuccess, status);
// One last init with everything correct and working.
status =
Cdm::initialize(Cdm::kNoSecureOutput, working_client_info, g_host, g_host,
g_host, static_cast<Cdm::LogLevel>(g_cutoff));
status = Cdm::initialize(Cdm::kNoSecureOutput, working_client_info, g_host,
g_host, g_host, static_cast<Cdm::LogLevel>(g_cutoff),
g_sandbox_id);
EXPECT_EQ(Cdm::kSuccess, status);
}
@@ -747,6 +746,34 @@ TEST_F(CdmTest, SetServiceCertificate) {
EXPECT_EQ(Cdm::kTypeError, status);
}
TEST_F(CdmTest, OpenSessionWithoutServiceCertificate) {
// Create a CDM instance that does not have any service certificates
// installed.
ASSERT_NO_FATAL_FAILURE(CreateAdditionalCdm(true /* privacy_mode */, &cdm_));
EnsureProvisioned();
// Verify that sessions can be opened.
std::string session_id;
ASSERT_EQ(Cdm::kSuccess, cdm_->createSession(Cdm::kTemporary, &session_id));
// License request generation, however, should fail.
EXPECT_CALL(*this, onMessage(session_id, _, _)).Times(0);
EXPECT_EQ(Cdm::kNeedsServiceCertificate,
generateRequestWithRetry(session_id, Cdm::kCenc, kCencInitData));
Mock::VerifyAndClear(this);
// Once a service certificate has been set, the existing session should be
// able to generate a request.
ASSERT_EQ(Cdm::kSuccess,
cdm_->setServiceCertificate(Cdm::kLicensingService,
config_.license_service_certificate()));
EXPECT_CALL(*this, onMessage(session_id, _, _)).Times(AtLeast(1));
EXPECT_EQ(Cdm::kSuccess,
generateRequestWithRetry(session_id, Cdm::kCenc, kCencInitData));
Mock::VerifyAndClear(this);
}
TEST_F(CdmTest, GetRobustnessLevel) {
Cdm::RobustnessLevel level;
Cdm::Status status = cdm_->getRobustnessLevel(&level);
@@ -1981,6 +2008,10 @@ TEST_F(CdmTest, GetStatusForHdcpResolution) {
ASSERT_EQ(Cdm::kSuccess,
cdm_->getStatusForHdcpVersion(Cdm::kHdcp2_2, &key_status));
EXPECT_THAT(key_status, AnyOf(Cdm::kUsable, Cdm::kOutputRestricted));
ASSERT_EQ(Cdm::kSuccess,
cdm_->getStatusForHdcpVersion(Cdm::kHdcp2_3, &key_status));
EXPECT_THAT(key_status, AnyOf(Cdm::kUsable, Cdm::kOutputRestricted));
}
TEST_F(CdmTest, HandlesKeyRotationWithOnlyOneLicenseRequest) {

View File

@@ -4,7 +4,11 @@
#include <assert.h>
#include <gtest/gtest.h>
#include <string.h>
#include <time.h>
#include <algorithm>
#include <string>
#include <vector>
#if defined(__linux__)
#include <sys/utsname.h>
@@ -19,11 +23,34 @@
using namespace widevine;
TestHost* g_host = nullptr;
std::string g_sandbox_id = "";
namespace {
constexpr const char kSandboxIdParam[] = "--sandbox_id=";
// Following the pattern established by help text in test_base.cpp
constexpr const char kExtraHelpText[] =
" --sandbox_id=<sandbox_id>\n"
" Specifies the Sandbox ID that should be sent to OEMCrypto via\n"
" OEMCrypto_SetSandbox(). On most platforms, since Sandbox IDs are not\n"
" in use, this parameter should be omitted.\n";
} // namespace
int main(int argc, char** argv) {
// Init gtest and let it consume arguments.
::testing::InitGoogleTest(&argc, argv);
// Find and filter out the Sandbox ID, if any.
std::vector<std::string> args(argv, argv + argc);
auto sandbox_id_iter = std::find_if(std::begin(args) + 1, std::end(args),
[](const std::string& elem) -> bool {
return elem.find(kSandboxIdParam) == 0;
});
if (sandbox_id_iter != std::end(args)) {
g_sandbox_id = sandbox_id_iter->substr(strlen(kSandboxIdParam));
args.erase(sandbox_id_iter);
}
// Set up a Host and initialize the library. This makes these services
// available to the tests. We would do this in the test suite itself, but the
// core & OEMCrypto tests don't know they depend on this for storage.
@@ -46,15 +73,22 @@ int main(int argc, char** argv) {
#endif
client_info.build_info = __DATE__;
Cdm::Status status =
Cdm::initialize(Cdm::kNoSecureOutput, client_info, g_host, g_host, g_host,
static_cast<Cdm::LogLevel>(wvcdm::g_cutoff));
Cdm::Status status = Cdm::initialize(
Cdm::kNoSecureOutput, client_info, g_host, g_host, g_host,
static_cast<Cdm::LogLevel>(wvcdm::g_cutoff), g_sandbox_id);
(void)status; // status is now used when assertions are turned off.
assert(status == Cdm::kSuccess);
// This must take place after the call to Cdm::initialize() because it may
// make calls that are only valid after the library is initialized.
if (!wvcdm::WvCdmTestBase::Initialize(argc, argv)) return 0;
std::vector<const char*> new_argv(args.size());
std::transform(
std::begin(args), std::end(args), std::begin(new_argv),
[](const std::string& arg) -> const char* { return arg.c_str(); });
// This must take place after the call to Cdm::initialize() because it makes
// calls that are only valid after the library is initialized.
if (!wvcdm::WvCdmTestBase::Initialize(new_argv.size(), new_argv.data(),
kExtraHelpText)) {
return 0;
}
return RUN_ALL_TESTS();
}

View File

@@ -31,18 +31,7 @@ void PrintTo(const Cdm::Status& value, ::std::ostream* os) {
case Cdm::kSuccess:
*os << "Cdm::kSuccess";
break;
case Cdm::kNeedsDeviceCertificate:
*os << "Cdm::kNeedsDeviceCertificate";
break;
case Cdm::kSessionNotFound:
*os << "Cdm::kSessionNotFound";
break;
case Cdm::kDecryptError:
*os << "Cdm::kDecryptError";
break;
case Cdm::kNoKey:
*os << "Cdm::kNoKey";
break;
case Cdm::kTypeError:
*os << "Cdm::kTypeError";
break;
@@ -55,12 +44,45 @@ void PrintTo(const Cdm::Status& value, ::std::ostream* os) {
case Cdm::kQuotaExceeded:
*os << "Cdm::kQuotaExceeded";
break;
case Cdm::kNeedsDeviceCertificate:
*os << "Cdm::kNeedsDeviceCertificate";
break;
case Cdm::kSessionNotFound:
*os << "Cdm::kSessionNotFound";
break;
case Cdm::kDecryptError:
*os << "Cdm::kDecryptError";
break;
case Cdm::kNoKey:
*os << "Cdm::kNoKey";
break;
case Cdm::kKeyUsageBlockedByPolicy:
*os << "Cdm::kKeyUsageBlockedByPolicy";
break;
case Cdm::kRangeError:
*os << "Cdm::kRangeError";
break;
case Cdm::kResourceContention:
*os << "Cdm::kResourceContention";
break;
case Cdm::kSessionStateLost:
*os << "Cdm::kSessionStateLost";
break;
case Cdm::kSystemStateLost:
*os << "Cdm::kSystemStateLost";
break;
case Cdm::kOutputTooLarge:
*os << "Cdm::kOutputTooLarge";
break;
case Cdm::kNeedsServiceCertificate:
*os << "Cdm::kNeedsServiceCertificate";
break;
case Cdm::kUnexpectedError:
*os << "Cdm::kUnexpectedError";
break;
default:
*os << "Unknown Cdm::Status value " << value;
break;
@@ -84,6 +106,9 @@ void PrintTo(const Cdm::KeyStatus& value, ::std::ostream* os) {
case Cdm::kInternalError:
*os << "Cdm::kInternalError";
break;
case Cdm::kReleased:
*os << "Cdm::kReleased";
break;
default:
*os << "Unknown Cdm::KeyStatus value " << value;
break;

View File

@@ -66,5 +66,6 @@ class TestHost : public widevine::Cdm::IStorage,
// Owned and managed by the test runner.
extern TestHost* g_host;
extern std::string g_sandbox_id;
#endif // WVCDM_CDM_TEST_TEST_HOST_H_