Merge changes I7cd424ae,I20f5d6a9
* changes: Add Duration Use Case integration tests Add some policy integration tests
This commit is contained in:
@@ -40,6 +40,7 @@ WV_TEST_TARGETS="base64_test \
|
|||||||
crypto_session_unittest \
|
crypto_session_unittest \
|
||||||
device_files_unittest \
|
device_files_unittest \
|
||||||
distribution_unittest \
|
distribution_unittest \
|
||||||
|
duration_use_case_test \
|
||||||
event_metric_unittest \
|
event_metric_unittest \
|
||||||
file_store_unittest \
|
file_store_unittest \
|
||||||
file_utils_unittest \
|
file_utils_unittest \
|
||||||
@@ -60,6 +61,7 @@ WV_TEST_TARGETS="base64_test \
|
|||||||
odk_test \
|
odk_test \
|
||||||
policy_engine_constraints_unittest \
|
policy_engine_constraints_unittest \
|
||||||
policy_engine_unittest \
|
policy_engine_unittest \
|
||||||
|
policy_integration_test \
|
||||||
request_license_test \
|
request_license_test \
|
||||||
rw_lock_test \
|
rw_lock_test \
|
||||||
service_certificate_unittest \
|
service_certificate_unittest \
|
||||||
|
|||||||
@@ -347,11 +347,6 @@ class CdmEngine {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class CdmEngineFactory;
|
friend class CdmEngineFactory;
|
||||||
friend class ParallelCdmTest;
|
|
||||||
friend class WvCdmEnginePreProvTest;
|
|
||||||
friend class WvCdmTestBase;
|
|
||||||
friend class WvGenericCryptoTest;
|
|
||||||
friend class TestLicenseHolder;
|
|
||||||
|
|
||||||
CdmEngine(FileSystem* file_system,
|
CdmEngine(FileSystem* file_system,
|
||||||
std::shared_ptr<metrics::EngineMetrics> metrics);
|
std::shared_ptr<metrics::EngineMetrics> metrics);
|
||||||
|
|||||||
@@ -48,12 +48,9 @@ const std::string kFakeSessionId = "TotallyARealSession123456789";
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
class WvCdmEnginePreProvTest : public WvCdmTestBase {
|
class WvCdmEnginePreProvTest : public WvCdmTestBaseWithEngine {
|
||||||
public:
|
public:
|
||||||
WvCdmEnginePreProvTest()
|
WvCdmEnginePreProvTest() : session_opened_(false) {}
|
||||||
: dummy_engine_metrics_(new EngineMetrics),
|
|
||||||
cdm_engine_(&file_system_, dummy_engine_metrics_),
|
|
||||||
session_opened_(false) {}
|
|
||||||
|
|
||||||
~WvCdmEnginePreProvTest() override {}
|
~WvCdmEnginePreProvTest() override {}
|
||||||
|
|
||||||
@@ -116,9 +113,6 @@ class WvCdmEnginePreProvTest : public WvCdmTestBase {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSystem file_system_;
|
|
||||||
shared_ptr<metrics::EngineMetrics> dummy_engine_metrics_;
|
|
||||||
CdmEngine cdm_engine_;
|
|
||||||
bool session_opened_;
|
bool session_opened_;
|
||||||
std::string key_msg_;
|
std::string key_msg_;
|
||||||
std::string session_id_;
|
std::string session_id_;
|
||||||
|
|||||||
1632
libwvdrmengine/cdm/core/test/duration_use_case_test.cpp
Normal file
1632
libwvdrmengine/cdm/core/test/duration_use_case_test.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -29,12 +29,9 @@
|
|||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
|
|
||||||
class WvGenericCryptoTest : public WvCdmTestBase {
|
class WvGenericCryptoTest : public WvCdmTestBaseWithEngine {
|
||||||
public:
|
public:
|
||||||
WvGenericCryptoTest()
|
WvGenericCryptoTest() : holder_(&cdm_engine_) {}
|
||||||
: dummy_engine_metrics_(new metrics::EngineMetrics),
|
|
||||||
cdm_engine_(&file_system_, dummy_engine_metrics_),
|
|
||||||
holder_(&cdm_engine_) {}
|
|
||||||
|
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
WvCdmTestBase::SetUp();
|
WvCdmTestBase::SetUp();
|
||||||
@@ -74,9 +71,6 @@ class WvGenericCryptoTest : public WvCdmTestBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FileSystem file_system_;
|
|
||||||
std::shared_ptr<metrics::EngineMetrics> dummy_engine_metrics_;
|
|
||||||
CdmEngine cdm_engine_;
|
|
||||||
TestLicenseHolder holder_;
|
TestLicenseHolder holder_;
|
||||||
|
|
||||||
KeyId ency_id_;
|
KeyId ency_id_;
|
||||||
|
|||||||
195
libwvdrmengine/cdm/core/test/policy_integration_test.cpp
Normal file
195
libwvdrmengine/cdm/core/test/policy_integration_test.cpp
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
// Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
|
||||||
|
// source code may only be used and distributed under the Widevine License
|
||||||
|
// Agreement.
|
||||||
|
|
||||||
|
// These tests perform various end-to-end actions similar to what an application
|
||||||
|
// would do. They verify that policies specified on UAT are honored on the
|
||||||
|
// device.
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "cdm_engine.h"
|
||||||
|
#include "clock.h"
|
||||||
|
#include "config_test_env.h"
|
||||||
|
#include "initialization_data.h"
|
||||||
|
#include "license_request.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "metrics_collections.h"
|
||||||
|
#include "test_base.h"
|
||||||
|
#include "test_printers.h"
|
||||||
|
#include "test_sleep.h"
|
||||||
|
#include "url_request.h"
|
||||||
|
#include "wv_cdm_constants.h"
|
||||||
|
#include "wv_cdm_types.h"
|
||||||
|
|
||||||
|
namespace wvcdm {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr int kHttpOk = 200;
|
||||||
|
const std::string kCencMimeType = "cenc";
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// Core Policy Integration Test
|
||||||
|
class CorePIGTest : public WvCdmTestBaseWithEngine {
|
||||||
|
protected:
|
||||||
|
void SetUp() override {
|
||||||
|
WvCdmTestBase::SetUp();
|
||||||
|
EnsureProvisioned();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenSession(CdmSessionId* session_id) {
|
||||||
|
CdmResponseType status = cdm_engine_.OpenSession(
|
||||||
|
config_.key_system(), nullptr, nullptr, session_id);
|
||||||
|
ASSERT_EQ(NO_ERROR, status);
|
||||||
|
ASSERT_TRUE(cdm_engine_.IsOpenSession(*session_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CloseSession(const CdmSessionId& session_id) {
|
||||||
|
CdmResponseType status = cdm_engine_.CloseSession(session_id);
|
||||||
|
ASSERT_EQ(NO_ERROR, status);
|
||||||
|
ASSERT_FALSE(cdm_engine_.IsOpenSession(session_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a license request for the given content_id and requesting the
|
||||||
|
// specified license_type.
|
||||||
|
void GenerateKeyRequest(const CdmSessionId& session_id,
|
||||||
|
const std::string& content_id,
|
||||||
|
CdmKeyRequest* key_request,
|
||||||
|
CdmLicenseType license_type) {
|
||||||
|
video_widevine::WidevinePsshData pssh;
|
||||||
|
pssh.set_content_id(content_id);
|
||||||
|
const std::string init_data_string = MakePSSH(pssh);
|
||||||
|
const InitializationData init_data(kCencMimeType, init_data_string);
|
||||||
|
init_data.DumpToLogs();
|
||||||
|
CdmAppParameterMap empty_app_parameters;
|
||||||
|
CdmKeySetId empty_key_set_id;
|
||||||
|
CdmResponseType result = cdm_engine_.GenerateKeyRequest(
|
||||||
|
session_id, empty_key_set_id, init_data, license_type,
|
||||||
|
empty_app_parameters, key_request);
|
||||||
|
ASSERT_EQ(KEY_MESSAGE, result);
|
||||||
|
ASSERT_EQ(kKeyRequestTypeInitial, key_request->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the request to the server and get the response.
|
||||||
|
void GetKeyResponse(const CdmKeyRequest& key_request,
|
||||||
|
std::string* key_response) {
|
||||||
|
const std::string url = config_.license_server() + config_.client_auth();
|
||||||
|
UrlRequest url_request(url);
|
||||||
|
ASSERT_TRUE(url_request.is_connected());
|
||||||
|
|
||||||
|
std::string http_response;
|
||||||
|
url_request.PostRequest(key_request.message);
|
||||||
|
ASSERT_TRUE(url_request.GetResponse(&http_response));
|
||||||
|
int status_code = url_request.GetStatusCode(http_response);
|
||||||
|
ASSERT_EQ(kHttpOk, status_code);
|
||||||
|
|
||||||
|
LicenseRequest license_request;
|
||||||
|
license_request.GetDrmMessage(http_response, *key_response);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the license response into the specified session. Verify it has the
|
||||||
|
// correct license type (either streaming or offline).
|
||||||
|
void AddKey(const CdmSessionId& session_id, const std::string& key_response,
|
||||||
|
CdmLicenseType expected_license_type, CdmKeySetId* key_set_id) {
|
||||||
|
CdmLicenseType license_type;
|
||||||
|
CdmResponseType status =
|
||||||
|
cdm_engine_.AddKey(session_id, key_response, &license_type, key_set_id);
|
||||||
|
ASSERT_EQ(KEY_ADDED, status);
|
||||||
|
ASSERT_EQ(expected_license_type, license_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload the license response into the specified session.
|
||||||
|
void RestoreKey(const CdmSessionId& session_id,
|
||||||
|
const CdmKeySetId& key_set_id) {
|
||||||
|
CdmResponseType status = cdm_engine_.RestoreKey(session_id, key_set_id);
|
||||||
|
ASSERT_EQ(KEY_ADDED, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the key to decrypt.
|
||||||
|
void Decrypt(const CdmSessionId& session_id, const KeyId& key_id) {
|
||||||
|
constexpr size_t buffer_size = 500;
|
||||||
|
const std::vector<uint8_t> input(buffer_size, 0);
|
||||||
|
std::vector<uint8_t> output(buffer_size, 0);
|
||||||
|
const std::vector<uint8_t> iv(KEY_IV_SIZE, 0);
|
||||||
|
Decrypt(session_id, key_id, input, iv, &output, NO_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to use the key to decrypt, but expect the key has expired.
|
||||||
|
void FailDecrypt(const CdmSessionId& session_id, const KeyId& key_id) {
|
||||||
|
constexpr size_t buffer_size = 500;
|
||||||
|
const std::vector<uint8_t> input(buffer_size, 0);
|
||||||
|
std::vector<uint8_t> output(buffer_size, 0);
|
||||||
|
const std::vector<uint8_t> iv(KEY_IV_SIZE, 0);
|
||||||
|
Decrypt(session_id, key_id, input, iv, &output, NEED_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decrypt(const CdmSessionId& session_id, const KeyId& key_id,
|
||||||
|
const std::vector<uint8_t>& input,
|
||||||
|
const std::vector<uint8_t>& iv, std::vector<uint8_t>* output,
|
||||||
|
CdmResponseType expected_status) {
|
||||||
|
CdmDecryptionParametersV16 params(key_id);
|
||||||
|
params.is_secure = false;
|
||||||
|
CdmDecryptionSample sample(input.data(), output->data(), 0, input.size(),
|
||||||
|
iv);
|
||||||
|
CdmDecryptionSubsample subsample(0, input.size());
|
||||||
|
sample.subsamples.push_back(subsample);
|
||||||
|
params.samples.push_back(sample);
|
||||||
|
|
||||||
|
CdmResponseType status = cdm_engine_.DecryptV16(session_id, params);
|
||||||
|
ASSERT_EQ(expected_status, status);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// An offline license with nonce not required.
|
||||||
|
TEST_F(CorePIGTest, OfflineNoNonce) {
|
||||||
|
const std::string content_id = "2015_tears";
|
||||||
|
const KeyId key_id = "0000000000000000";
|
||||||
|
|
||||||
|
const CdmLicenseType license_type = kLicenseTypeOffline;
|
||||||
|
CdmSessionId session_id;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(OpenSession(&session_id));
|
||||||
|
CdmKeyRequest key_request;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(
|
||||||
|
GenerateKeyRequest(session_id, content_id, &key_request, license_type));
|
||||||
|
std::string key_response;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(GetKeyResponse(key_request, &key_response));
|
||||||
|
CdmKeySetId key_set_id;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(
|
||||||
|
AddKey(session_id, key_response, license_type, &key_set_id));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(Decrypt(session_id, key_id));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(CloseSession(session_id));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(OpenSession(&session_id));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(RestoreKey(session_id, key_set_id));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(Decrypt(session_id, key_id));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(CloseSession(session_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// An offline license with nonce and provider session token.
|
||||||
|
TEST_F(CorePIGTest, OfflineWithPST) {
|
||||||
|
const std::string content_id = "offline_clip2";
|
||||||
|
const KeyId key_id =
|
||||||
|
"\x32\x60\xF3\x9E\x12\xCC\xF6\x53\x52\x99\x90\x16\x8A\x35\x83\xFF";
|
||||||
|
const CdmLicenseType license_type = kLicenseTypeOffline;
|
||||||
|
CdmSessionId session_id;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(OpenSession(&session_id));
|
||||||
|
CdmKeyRequest key_request;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(
|
||||||
|
GenerateKeyRequest(session_id, content_id, &key_request, license_type));
|
||||||
|
std::string key_response;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(GetKeyResponse(key_request, &key_response));
|
||||||
|
CdmKeySetId key_set_id;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(
|
||||||
|
AddKey(session_id, key_response, license_type, &key_set_id));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(Decrypt(session_id, key_id));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(CloseSession(session_id));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(OpenSession(&session_id));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(RestoreKey(session_id, key_set_id));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(Decrypt(session_id, key_id));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(CloseSession(session_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace wvcdm
|
||||||
@@ -290,8 +290,8 @@ void WvCdmTestBase::Provision() {
|
|||||||
if (config_.provisioning_server() == "fake") {
|
if (config_.provisioning_server() == "fake") {
|
||||||
LOGD("Using fake provisioning server.");
|
LOGD("Using fake provisioning server.");
|
||||||
|
|
||||||
CdmEngine cdm_engine(&file_system,
|
TestCdmEngine cdm_engine(&file_system,
|
||||||
std::shared_ptr<EngineMetrics>(new EngineMetrics));
|
std::shared_ptr<EngineMetrics>(new EngineMetrics));
|
||||||
FakeProvisioningServer server;
|
FakeProvisioningServer server;
|
||||||
CdmResponseType result = cdm_engine.GetProvisioningRequest(
|
CdmResponseType result = cdm_engine.GetProvisioningRequest(
|
||||||
cert_type, cert_authority, server.service_certificate(), kLevelDefault,
|
cert_type, cert_authority, server.service_certificate(), kLevelDefault,
|
||||||
@@ -309,8 +309,8 @@ void WvCdmTestBase::Provision() {
|
|||||||
EXPECT_EQ(NO_ERROR, result);
|
EXPECT_EQ(NO_ERROR, result);
|
||||||
} else {
|
} else {
|
||||||
// TODO(fredgc): provision for different SPOIDs.
|
// TODO(fredgc): provision for different SPOIDs.
|
||||||
CdmEngine cdm_engine(&file_system,
|
TestCdmEngine cdm_engine(&file_system,
|
||||||
std::shared_ptr<EngineMetrics>(new EngineMetrics));
|
std::shared_ptr<EngineMetrics>(new EngineMetrics));
|
||||||
|
|
||||||
CdmResponseType result = cdm_engine.GetProvisioningRequest(
|
CdmResponseType result = cdm_engine.GetProvisioningRequest(
|
||||||
cert_type, cert_authority, config_.provisioning_service_certificate(),
|
cert_type, cert_authority, config_.provisioning_service_certificate(),
|
||||||
@@ -387,8 +387,8 @@ void WvCdmTestBase::Provision() {
|
|||||||
void WvCdmTestBase::EnsureProvisioned() {
|
void WvCdmTestBase::EnsureProvisioned() {
|
||||||
CdmSessionId session_id;
|
CdmSessionId session_id;
|
||||||
FileSystem file_system;
|
FileSystem file_system;
|
||||||
CdmEngine cdm_engine(&file_system,
|
TestCdmEngine cdm_engine(&file_system,
|
||||||
std::shared_ptr<EngineMetrics>(new EngineMetrics));
|
std::shared_ptr<EngineMetrics>(new EngineMetrics));
|
||||||
CdmResponseType status = cdm_engine.OpenSession(config_.key_system(), nullptr,
|
CdmResponseType status = cdm_engine.OpenSession(config_.key_system(), nullptr,
|
||||||
nullptr, &session_id);
|
nullptr, &session_id);
|
||||||
if (status == NEED_PROVISIONING) {
|
if (status == NEED_PROVISIONING) {
|
||||||
|
|||||||
@@ -76,6 +76,27 @@ class WvCdmTestBase : public ::testing::Test {
|
|||||||
bool binary_provisioning_;
|
bool binary_provisioning_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This just makes the constructor public so that we can create one with dummy
|
||||||
|
// metrics and file system.
|
||||||
|
class TestCdmEngine : public CdmEngine {
|
||||||
|
public:
|
||||||
|
TestCdmEngine(FileSystem* file_system,
|
||||||
|
std::shared_ptr<metrics::EngineMetrics> metrics)
|
||||||
|
: CdmEngine(file_system, metrics) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class WvCdmTestBaseWithEngine : public WvCdmTestBase {
|
||||||
|
public:
|
||||||
|
WvCdmTestBaseWithEngine()
|
||||||
|
: dummy_engine_metrics_(new metrics::EngineMetrics()),
|
||||||
|
cdm_engine_(&file_system_, dummy_engine_metrics_) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
FileSystem file_system_;
|
||||||
|
shared_ptr<metrics::EngineMetrics> dummy_engine_metrics_;
|
||||||
|
TestCdmEngine cdm_engine_;
|
||||||
|
};
|
||||||
|
|
||||||
class TestCryptoSession : public CryptoSession {
|
class TestCryptoSession : public CryptoSession {
|
||||||
public:
|
public:
|
||||||
explicit TestCryptoSession(metrics::CryptoMetrics* crypto_metrics);
|
explicit TestCryptoSession(metrics::CryptoMetrics* crypto_metrics);
|
||||||
|
|||||||
@@ -67,6 +67,11 @@ test_name := distribution_unittest
|
|||||||
test_src_dir := ../metrics/test
|
test_src_dir := ../metrics/test
|
||||||
include $(LOCAL_PATH)/unit-test.mk
|
include $(LOCAL_PATH)/unit-test.mk
|
||||||
|
|
||||||
|
test_name := duration_use_case_test
|
||||||
|
test_src_dir := ../core/test
|
||||||
|
test_main := ../core/test/test_main.cpp
|
||||||
|
include $(LOCAL_PATH)/integration-test.mk
|
||||||
|
|
||||||
test_name := event_metric_unittest
|
test_name := event_metric_unittest
|
||||||
test_src_dir := ../metrics/test
|
test_src_dir := ../metrics/test
|
||||||
include $(LOCAL_PATH)/unit-test.mk
|
include $(LOCAL_PATH)/unit-test.mk
|
||||||
@@ -116,6 +121,11 @@ test_src_dir := ../core/test
|
|||||||
test_main := ../core/test/test_main.cpp
|
test_main := ../core/test/test_main.cpp
|
||||||
include $(LOCAL_PATH)/integration-test.mk
|
include $(LOCAL_PATH)/integration-test.mk
|
||||||
|
|
||||||
|
test_name := policy_integration_test
|
||||||
|
test_src_dir := ../core/test
|
||||||
|
test_main := ../core/test/test_main.cpp
|
||||||
|
include $(LOCAL_PATH)/integration-test.mk
|
||||||
|
|
||||||
test_name := request_license_test
|
test_name := request_license_test
|
||||||
test_src_dir := .
|
test_src_dir := .
|
||||||
test_main := ../core/test/test_main.cpp
|
test_main := ../core/test/test_main.cpp
|
||||||
|
|||||||
@@ -97,6 +97,9 @@ adb_shell_run request_license_test $PROVISIONING_ARG
|
|||||||
# cdm_extended_duration_test takes >30 minutes to run.
|
# cdm_extended_duration_test takes >30 minutes to run.
|
||||||
# adb_shell_run cdm_extended_duration_test
|
# adb_shell_run cdm_extended_duration_test
|
||||||
|
|
||||||
|
# duration_use_case_test takes a very long time to run.
|
||||||
|
# adb_shell_run duration_use_case_test
|
||||||
|
|
||||||
# cdm_feature_test to be run with modified/mock oemcrypto
|
# cdm_feature_test to be run with modified/mock oemcrypto
|
||||||
# adb_shell_run cdm_feature_test
|
# adb_shell_run cdm_feature_test
|
||||||
|
|
||||||
@@ -127,6 +130,7 @@ adb_shell_run license_unittest
|
|||||||
adb_shell_run odk_test
|
adb_shell_run odk_test
|
||||||
adb_shell_run policy_engine_constraints_unittest
|
adb_shell_run policy_engine_constraints_unittest
|
||||||
adb_shell_run policy_engine_unittest
|
adb_shell_run policy_engine_unittest
|
||||||
|
adb_shell_run policy_integration_test
|
||||||
adb_shell_run rw_lock_test
|
adb_shell_run rw_lock_test
|
||||||
adb_shell_run service_certificate_unittest
|
adb_shell_run service_certificate_unittest
|
||||||
adb_shell_run timer_unittest
|
adb_shell_run timer_unittest
|
||||||
|
|||||||
Reference in New Issue
Block a user