Commit 100a062b authored by Willie Koomson's avatar Willie Koomson Committed by Chromium LUCI CQ

Start mini-ARCVM in ArcVmClientAdapter::StartMiniArc()

This change modifies ArcVmClientAdapter to start ARCVM before
login (to implement mini-ARC). Among the changes are:
 - Starts mini-ARCVM with a generic user kArcVmDefaultOwner
 - Sets correct owner id during UpgradeArc()
 - Stops VM if UpgradeArc() fails
 - On StopArcInstance(), checks if mini-ARC or full ARC is running
 - Update unittests

BUG=b:144542975
TEST=ArcVmClientAdapterTest unittests
TEST=tast run <DUT> arc.Boot.vm crostini.Basic.buster_amd64_stable
TEST=build and flash. On login screen, check chrome log and syslog
to make sure ARCVM has started successfully. Check guest logcat and
make sure init is blocked on arcvm-boot-notification-client. After
login, check that instance is upgraded successfully and Play Store
is able to start.

Change-Id: I190a9ede041b53f0dbcb1773ea82b2e0ac51ae54
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2354623Reviewed-by: default avatarRyo Hashimoto <hashimoto@chromium.org>
Reviewed-by: default avatarYusuke Sato <yusukes@chromium.org>
Commit-Queue: Willie Koomson <wvk@google.com>
Cr-Commit-Position: refs/heads/master@{#840674}
parent e41849ef
......@@ -252,6 +252,10 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS) FakeConciergeClient
resize_disk_image_response) {
resize_disk_image_response_ = resize_disk_image_response;
}
void set_set_vm_id_response(
base::Optional<vm_tools::concierge::SetVmIdResponse> set_vm_id_response) {
set_vm_id_response_ = set_vm_id_response;
}
void set_send_create_disk_image_response_delay(base::TimeDelta delay) {
send_create_disk_image_response_delay_ = delay;
......
......@@ -82,6 +82,10 @@ constexpr int kArcBugReportBackupTimeMetricBuckets = 50;
constexpr const char kArcBugReportBackupTimeMetric[] =
"Login.ArcBugReportBackupTime";
// The owner ID that ARCVM is started with for mini-ARCVM. On UpgradeArc,
// the owner ID is set to the logged-in user.
constexpr const char kArcVmDefaultOwner[] = "ARCVM_DEFAULT_OWNER";
constexpr int64_t kInvalidCid = -1;
constexpr base::TimeDelta kConnectTimeoutLimit =
......@@ -188,14 +192,10 @@ std::vector<std::string> GenerateUpgradeProps(
std::vector<std::string> GenerateKernelCmdline(
const StartParams& start_params,
const UpgradeParams& upgrade_params,
const FileSystemStatus& file_system_status,
bool is_dev_mode,
bool is_host_on_vm,
const std::string& channel,
const std::string& serial_number) {
DCHECK(!serial_number.empty());
const std::string& channel) {
std::string native_bridge;
switch (IdentifyBinaryTranslationType(start_params)) {
case ArcBinaryTranslationType::NONE:
......@@ -235,12 +235,6 @@ std::vector<std::string> GenerateKernelCmdline(
if (channel == "testimage")
result.push_back("androidboot.vshd_service_override=vshd_for_test");
// Since we don't do mini VM yet, set not only |start_params| but also
// |upgrade_params| here for now.
const std::vector<std::string> upgrade_props =
GenerateUpgradeProps(upgrade_params, serial_number, "androidboot");
result.insert(result.end(), upgrade_props.begin(), upgrade_props.end());
// TODO(niwa): Check if we need to set ro.boot.enable_adb_sideloading for
// ARCVM.
......@@ -274,7 +268,6 @@ std::vector<std::string> GenerateKernelCmdline(
}
vm_tools::concierge::StartArcVmRequest CreateStartArcVmRequest(
const std::string& user_id_hash,
uint32_t cpus,
const base::FilePath& demo_session_apps_path,
const FileSystemStatus& file_system_status,
......@@ -282,7 +275,7 @@ vm_tools::concierge::StartArcVmRequest CreateStartArcVmRequest(
vm_tools::concierge::StartArcVmRequest request;
request.set_name(kArcVmName);
request.set_owner_id(user_id_hash);
request.set_owner_id(kArcVmDefaultOwner);
request.add_params("root=/dev/vda");
if (file_system_status.is_host_rootfs_writable() &&
......@@ -476,12 +469,7 @@ class ArcVmClientAdapter : public ArcClientAdapter,
// ArcClientAdapter overrides:
void StartMiniArc(StartParams params,
chromeos::VoidDBusMethodCallback callback) override {
// TODO(wvk): Support mini ARC.
VLOG(2) << "Mini ARCVM instance is not supported.";
// Save the parameters for the later call to UpgradeArc.
start_params_ = std::move(params);
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(
......@@ -490,6 +478,32 @@ class ArcVmClientAdapter : public ArcClientAdapter,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void UpgradeArc(UpgradeParams params,
chromeos::VoidDBusMethodCallback callback) override {
if (user_id_hash_.empty()) {
LOG(ERROR) << "User ID hash is not set";
StopArcInstanceInternal();
std::move(callback).Run(false);
return;
}
if (serial_number_.empty()) {
LOG(ERROR) << "Serial number is not set";
StopArcInstanceInternal();
std::move(callback).Run(false);
return;
}
// Stop the existing full-VM if any (e.g. in case of a chrome crash).
VLOG(1) << "Stopping the existing full-VM if any.";
vm_tools::concierge::StopVmRequest request;
request.set_name(kArcVmName);
request.set_owner_id(user_id_hash_);
GetConciergeClient()->StopVm(
request, base::BindOnce(&ArcVmClientAdapter::OnExistingFullVmStopped,
weak_factory_.GetWeakPtr(), std::move(params),
std::move(callback)));
}
void StopArcInstance(bool on_shutdown, bool should_backup_log) override {
if (on_shutdown) {
// Do nothing when |on_shutdown| is true because either vm_concierge.conf
......@@ -500,13 +514,7 @@ class ArcVmClientAdapter : public ArcClientAdapter,
<< "StopArcInstance is called during browser shutdown. Do nothing.";
return;
}
if (current_cid_ == kInvalidCid) {
// No VM is currently running, avoid calling ConciergeClient::StopVm().
// TODO(wvk): Once StartMiniArc() is implemented, use a DCHECK here
// instead.
OnArcInstanceStopped();
return;
}
DCHECK_NE(current_cid_, kInvalidCid) << "ARCVM is not running.";
if (should_backup_log) {
GetDebugDaemonClient()->BackupArcBugReport(
......@@ -568,9 +576,29 @@ class ArcVmClientAdapter : public ArcClientAdapter,
void StopArcInstanceInternal() {
VLOG(1) << "Stopping arcvm";
vm_tools::concierge::StopVmRequest request;
// This may be called before ARCVM has been upgraded and the proper VM id
// has been set. Since ConciergeClient::StopVm() returns successfully
// regardless of whether the VM exists, check to see which VM is actually
// running.
vm_tools::concierge::GetVmInfoRequest request;
request.set_name(kArcVmName);
request.set_owner_id(user_id_hash_);
GetConciergeClient()->GetVmInfo(
request, base::BindOnce(&ArcVmClientAdapter::OnGetVmReply,
weak_factory_.GetWeakPtr()));
}
void OnGetVmReply(
base::Optional<vm_tools::concierge::GetVmInfoResponse> reply) {
vm_tools::concierge::StopVmRequest request;
request.set_name(kArcVmName);
if (reply.has_value() && reply.value().success())
request.set_owner_id(user_id_hash_);
else
request.set_owner_id(kArcVmDefaultOwner);
GetConciergeClient()->StopVm(
request, base::BindOnce(&ArcVmClientAdapter::OnStopVmReply,
weak_factory_.GetWeakPtr()));
......@@ -599,7 +627,6 @@ class ArcVmClientAdapter : public ArcClientAdapter,
// called with true, it is ensured that the per-board features files
// exist.
JobDesc{kArcVmPerBoardFeaturesJobName, UpstartOperation::JOB_START, {}},
JobDesc{
kArcVmPostVmStartServicesJobName, UpstartOperation::JOB_STOP, {}},
JobDesc{kArcVmPostLoginServicesJobName, UpstartOperation::JOB_STOP, {}},
......@@ -622,6 +649,44 @@ class ArcVmClientAdapter : public ArcClientAdapter,
std::move(callback).Run(false);
return;
}
VLOG(1) << "Waiting for Concierge to be available";
GetConciergeClient()->WaitForServiceToBeAvailable(
base::BindOnce(&ArcVmClientAdapter::OnConciergeAvailable,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void OnConciergeAvailable(chromeos::VoidDBusMethodCallback callback,
bool service_available) {
if (!service_available) {
LOG(ERROR) << "Failed to wait for Concierge to be available";
std::move(callback).Run(false);
return;
}
// Stop the existing mini-VM if any (e.g. in case of a chrome crash).
VLOG(1) << "Stopping the existing mini-VM if any.";
vm_tools::concierge::StopVmRequest request;
request.set_name(kArcVmName);
request.set_owner_id(kArcVmDefaultOwner);
GetConciergeClient()->StopVm(
request,
base::BindOnce(&ArcVmClientAdapter::OnExistingMiniVmStopped,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void OnExistingMiniVmStopped(
chromeos::VoidDBusMethodCallback callback,
base::Optional<vm_tools::concierge::StopVmResponse> reply) {
// reply->success() returns true even when there was no VM running.
if (!reply.has_value() || !reply->success()) {
LOG(ERROR) << "StopVm failed: "
<< (reply.has_value() ? reply->failure_reason()
: "No D-Bus response.");
std::move(callback).Run(false);
return;
}
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&IsArcVmBootNotificationServerListening),
......@@ -638,62 +703,97 @@ class ArcVmClientAdapter : public ArcClientAdapter,
std::move(callback).Run(false);
return;
}
std::move(callback).Run(true);
// StartMiniArc() successful. Update the member variable here.
should_notify_observers_ = true;
}
void UpgradeArc(UpgradeParams params,
chromeos::VoidDBusMethodCallback callback) override {
VLOG(2) << "Checking file system status";
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&FileSystemStatus::GetFileSystemStatusBlocking),
base::BindOnce(&ArcVmClientAdapter::OnFileSystemStatus,
weak_factory_.GetWeakPtr(), std::move(params),
std::move(callback)));
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void OnFileSystemStatus(UpgradeParams params,
chromeos::VoidDBusMethodCallback callback,
void OnFileSystemStatus(chromeos::VoidDBusMethodCallback callback,
FileSystemStatus file_system_status) {
VLOG(2) << "Got file system status";
if (file_system_status_rewriter_for_testing_)
file_system_status_rewriter_for_testing_.Run(&file_system_status);
if (user_id_hash_.empty()) {
LOG(ERROR) << "User ID hash is not set";
file_system_status_has_adbd_json_ = file_system_status.has_adbd_json();
VLOG(2) << "Retrieving demo session apps path";
DCHECK(demo_mode_delegate_);
demo_mode_delegate_->EnsureOfflineResourcesLoaded(base::BindOnce(
&ArcVmClientAdapter::OnDemoResourcesLoaded, weak_factory_.GetWeakPtr(),
std::move(callback), std::move(file_system_status)));
}
void OnDemoResourcesLoaded(chromeos::VoidDBusMethodCallback callback,
FileSystemStatus file_system_status) {
const base::FilePath demo_session_apps_path =
demo_mode_delegate_->GetDemoAppsPath();
const int32_t cpus =
base::SysInfo::NumberOfProcessors() - start_params_.num_cores_disabled;
DCHECK_LT(0, cpus);
DCHECK(is_dev_mode_);
std::vector<std::string> kernel_cmdline = GenerateKernelCmdline(
start_params_, file_system_status, *is_dev_mode_, is_host_on_vm_,
GetChromeOsChannelFromLsbRelease());
auto start_request =
CreateStartArcVmRequest(cpus, demo_session_apps_path,
file_system_status, std::move(kernel_cmdline));
GetConciergeClient()->StartArcVm(
start_request,
base::BindOnce(&ArcVmClientAdapter::OnStartArcVmReply,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void OnStartArcVmReply(
chromeos::VoidDBusMethodCallback callback,
base::Optional<vm_tools::concierge::StartVmResponse> reply) {
if (!reply.has_value()) {
LOG(ERROR) << "Failed to start arcvm. Empty response.";
std::move(callback).Run(false);
return;
}
if (serial_number_.empty()) {
LOG(ERROR) << "Serial number is not set";
const vm_tools::concierge::StartVmResponse& response = reply.value();
if (response.status() != vm_tools::concierge::VM_STATUS_RUNNING) {
LOG(ERROR) << "Failed to start arcvm: status=" << response.status()
<< ", reason=" << response.failure_reason();
std::move(callback).Run(false);
return;
}
current_cid_ = response.vm_info().cid();
should_notify_observers_ = true;
VLOG(1) << "ARCVM started cid=" << current_cid_;
std::move(callback).Run(true);
}
std::vector<std::string> environment{
"CHROMEOS_USER=" +
cryptohome::CreateAccountIdentifierFromIdentification(
cryptohome_id_)
.account_id(),
"CHROMEOS_USER_ID_HASH=" + user_id_hash_};
std::deque<JobDesc> jobs{
JobDesc{kArcVmPostLoginServicesJobName, UpstartOperation::JOB_START,
std::move(environment)},
};
void OnExistingFullVmStopped(
UpgradeParams params,
chromeos::VoidDBusMethodCallback callback,
base::Optional<vm_tools::concierge::StopVmResponse> reply) {
// reply->success() returns true even when there was no VM running.
if (!reply.has_value() || !reply->success()) {
LOG(ERROR) << "StopVm failed: "
<< (reply.has_value() ? reply->failure_reason()
: "No D-Bus response.");
StopArcInstanceInternal();
std::move(callback).Run(false);
return;
}
VLOG(2) << "Checking adb sideload status";
VLOG(1) << "Checking adb sideload status";
chromeos::SessionManagerClient::Get()->QueryAdbSideload(base::BindOnce(
&ArcVmClientAdapter::OnCallQueryAdbSideloadAllowed,
weak_factory_.GetWeakPtr(), std::move(params), std::move(jobs),
std::move(file_system_status), std::move(callback)));
&ArcVmClientAdapter::OnQueryAdbSideload, weak_factory_.GetWeakPtr(),
std::move(params), std::move(callback)));
}
void OnCallQueryAdbSideloadAllowed(
void OnQueryAdbSideload(
UpgradeParams params,
std::deque<JobDesc> jobs,
FileSystemStatus file_system_status,
chromeos::VoidDBusMethodCallback callback,
chromeos::SessionManagerClient::AdbSideloadResponseCode response_code,
bool enabled) {
......@@ -703,6 +803,7 @@ class ArcVmClientAdapter : public ArcClientAdapter,
switch (response_code) {
case chromeos::SessionManagerClient::AdbSideloadResponseCode::FAILED:
LOG(ERROR) << "Failed response from QueryAdbSideload";
StopArcInstanceInternal();
std::move(callback).Run(false);
return;
case chromeos::SessionManagerClient::AdbSideloadResponseCode::
......@@ -714,105 +815,92 @@ class ArcVmClientAdapter : public ArcClientAdapter,
break;
}
VLOG(1) << "Starting upstart jobs for UpgradeArc()";
std::vector<std::string> environment{
"CHROMEOS_USER=" +
cryptohome::CreateAccountIdentifierFromIdentification(
cryptohome_id_)
.account_id(),
"CHROMEOS_USER_ID_HASH=" + user_id_hash_};
std::deque<JobDesc> jobs{
JobDesc{kArcVmPostLoginServicesJobName, UpstartOperation::JOB_START,
std::move(environment)},
};
ConfigureUpstartJobs(
std::move(jobs),
base::BindOnce(&ArcVmClientAdapter::OnConfigureUpstartJobsOnUpgradeArc,
weak_factory_.GetWeakPtr(), std::move(params),
std::move(file_system_status), std::move(callback)));
std::move(callback)));
}
void OnConfigureUpstartJobsOnUpgradeArc(
UpgradeParams params,
FileSystemStatus file_system_status,
chromeos::VoidDBusMethodCallback callback,
bool result) {
if (!result) {
LOG(ERROR) << "ConfigureUpstartJobs (on upgrading ARCVM) failed";
LOG(ERROR) << "ConfigureUpstartJobs (on upgrading ARCVM) failed. ";
StopArcInstanceInternal();
std::move(callback).Run(false);
return;
}
// Stop the existing VM if any (e.g. in case of a chrome crash).
VLOG(1) << "Stopping the existing VM if any.";
vm_tools::concierge::StopVmRequest request;
VLOG(1) << "Setting owner ID for mini-VM instance.";
vm_tools::concierge::SetVmIdRequest request;
request.set_name(kArcVmName);
request.set_owner_id(user_id_hash_);
GetConciergeClient()->StopVm(
request,
base::BindOnce(&ArcVmClientAdapter::OnExistingVmStopped,
weak_factory_.GetWeakPtr(), std::move(params),
std::move(file_system_status), std::move(callback)));
request.set_src_owner_id(kArcVmDefaultOwner);
request.set_dest_owner_id(user_id_hash_);
GetConciergeClient()->SetVmId(
request, base::BindOnce(&ArcVmClientAdapter::OnSetVmId,
weak_factory_.GetWeakPtr(), std::move(params),
std::move(callback)));
}
void OnExistingVmStopped(
UpgradeParams params,
FileSystemStatus file_system_status,
chromeos::VoidDBusMethodCallback callback,
base::Optional<vm_tools::concierge::StopVmResponse> reply) {
// reply->success() returns true even when there was no VM running.
if (!reply.has_value() || !reply->success()) {
LOG(ERROR) << "StopVm failed: "
<< (reply.has_value() ? reply->failure_reason()
: "No D-Bus response.");
void OnSetVmId(UpgradeParams params,
chromeos::VoidDBusMethodCallback callback,
base::Optional<vm_tools::concierge::SetVmIdResponse> reply) {
if (!reply.has_value()) {
LOG(ERROR) << "Failed to set VM ID. Empty response.";
StopArcInstanceInternal();
std::move(callback).Run(false);
return;
}
const int32_t cpus =
base::SysInfo::NumberOfProcessors() - start_params_.num_cores_disabled;
DCHECK_LT(0, cpus);
const vm_tools::concierge::SetVmIdResponse& response = reply.value();
if (!response.success()) {
LOG(ERROR) << "Failed to set VM ID. Failure reason="
<< response.failure_reason();
StopArcInstanceInternal();
std::move(callback).Run(false);
return;
}
DCHECK(is_dev_mode_);
std::vector<std::string> kernel_cmdline = GenerateKernelCmdline(
start_params_, params, file_system_status, *is_dev_mode_,
is_host_on_vm_, GetChromeOsChannelFromLsbRelease(), serial_number_);
auto start_request = CreateStartArcVmRequest(
user_id_hash_, cpus, params.demo_session_apps_path, file_system_status,
std::move(kernel_cmdline));
const bool should_start_adbd =
ShouldStartAdbd(*is_dev_mode_, is_host_on_vm_,
file_system_status.has_adbd_json(),
*is_adb_over_usb_disabled_) ||
g_enable_adb_over_usb_for_testing;
GetConciergeClient()->StartArcVm(
start_request, base::BindOnce(&ArcVmClientAdapter::OnStartArcVmReply,
weak_factory_.GetWeakPtr(),
should_start_adbd, std::move(callback)));
VLOG(2) << "Set VM id for default instance";
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&SendUpgradePropsToArcVmBootNotificationServer, params,
serial_number_),
base::BindOnce([](bool result) {
VLOG(1)
<< "Sending upgrade props to arcvm-boot-notification-server was "
<< (result ? "successful" : "unsuccessful");
}));
base::BindOnce(&SendUpgradePropsToArcVmBootNotificationServer,
std::move(params), serial_number_),
base::BindOnce(&ArcVmClientAdapter::OnUpgradePropsSent,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void OnStartArcVmReply(
bool should_start_adbd,
chromeos::VoidDBusMethodCallback callback,
base::Optional<vm_tools::concierge::StartVmResponse> reply) {
if (!reply.has_value()) {
LOG(ERROR) << "Failed to start arcvm. Empty response.";
std::move(callback).Run(false);
return;
}
const vm_tools::concierge::StartVmResponse& response = reply.value();
if (response.status() != vm_tools::concierge::VM_STATUS_RUNNING) {
LOG(ERROR) << "Failed to start arcvm: status=" << response.status()
<< ", reason=" << response.failure_reason();
void OnUpgradePropsSent(chromeos::VoidDBusMethodCallback callback,
bool result) {
if (!result) {
LOG(ERROR)
<< "Failed to send upgrade props to arcvm-boot-notification-server";
StopArcInstanceInternal();
std::move(callback).Run(false);
return;
}
current_cid_ = response.vm_info().cid();
VLOG(1) << "ARCVM started cid=" << current_cid_;
VLOG(1) << "Starting arcvm-post-vm-start-services.";
std::vector<std::string> environment;
bool should_start_adbd = ShouldStartAdbd(*is_dev_mode_, is_host_on_vm_,
file_system_status_has_adbd_json_,
*is_adb_over_usb_disabled_) ||
g_enable_adb_over_usb_for_testing;
if (should_start_adbd) {
environment.push_back("SERIALNUMBER=" + serial_number_);
environment.push_back(
......@@ -831,11 +919,14 @@ class ArcVmClientAdapter : public ArcClientAdapter,
chromeos::VoidDBusMethodCallback callback,
bool result) {
if (!result) {
LOG(ERROR) << "ConfigureUpstartJobs (after starting ARCVM) failed. "
"Stopping the VM..";
LOG(ERROR) << "ConfigureUpstartJobs (after starting ARCVM) failed.";
StopArcInstanceInternal();
std::move(callback).Run(false);
return;
}
std::move(callback).Run(result);
VLOG(1) << "ARCVM upgrade completed";
std::move(callback).Run(true);
}
void OnArcInstanceStopped() {
......@@ -859,9 +950,10 @@ class ArcVmClientAdapter : public ArcClientAdapter,
if (reply.has_value() && reply.value().success())
return;
// We likely tried to stop mini VM which doesn't exist today. Notify
// observers.
// TODO(wvk): Remove the fallback once we implement mini VM.
// StopVm always returns successfully, so the only case where this happens
// is if the reply is empty, which means Concierge isn't running and ARCVM
// isn't either.
LOG(ERROR) << "Failed to stop ARCVM: empty reply.";
OnArcInstanceStopped();
}
......@@ -882,6 +974,7 @@ class ArcVmClientAdapter : public ArcClientAdapter,
bool should_notify_observers_ = false;
int64_t current_cid_ = kInvalidCid;
bool file_system_status_has_adbd_json_ = false;
FileSystemStatusRewriter file_system_status_rewriter_for_testing_;
// The delegate is owned by ArcSessionRunner.
......
......@@ -56,6 +56,7 @@ constexpr char kArcVmPostLoginServicesJobName[] =
"arcvm_2dpost_2dlogin_2dservices";
constexpr char kArcVmPostVmStartServicesJobName[] =
"arcvm_2dpost_2dvm_2dstart_2dservices";
constexpr const char kArcVmDefaultOwner[] = "ARCVM_DEFAULT_OWNER";
constexpr const char kUserIdHash[] = "this_is_a_valid_user_id_hash";
constexpr const char kSerialNumber[] = "AAAABBBBCCCCDDDD1234";
......@@ -125,7 +126,10 @@ class TestConciergeClient : public chromeos::FakeConciergeClient {
chromeos::DBusMethodCallback<vm_tools::concierge::StopVmResponse>
callback) override {
++stop_vm_call_count_;
stop_vm_request_ = request;
chromeos::FakeConciergeClient::StopVm(request, std::move(callback));
if (on_stop_vm_callback_ && (stop_vm_call_count_ == callback_count_))
std::move(on_stop_vm_callback_).Run();
}
void StartArcVm(
......@@ -142,9 +146,24 @@ class TestConciergeClient : public chromeos::FakeConciergeClient {
return start_arc_vm_request_;
}
const vm_tools::concierge::StopVmRequest& stop_vm_request() const {
return stop_vm_request_;
}
// Set a callback to be run when stop_vm_call_count() == count.
void set_on_stop_vm_callback(base::OnceClosure callback, int count) {
on_stop_vm_callback_ = std::move(callback);
DCHECK_NE(0, count);
callback_count_ = count;
}
private:
int stop_vm_call_count_ = 0;
// When callback_count_ == 0, the on_stop_vm_callback_ is not run.
int callback_count_ = 0;
vm_tools::concierge::StartArcVmRequest start_arc_vm_request_;
vm_tools::concierge::StopVmRequest stop_vm_request_;
base::OnceClosure on_stop_vm_callback_;
DISALLOW_COPY_AND_ASSIGN(TestConciergeClient);
};
......@@ -229,6 +248,20 @@ class TestArcVmBootNotificationServer
base::OnceClosure callback_;
};
class FakeDemoModeDelegate : public ArcClientAdapter::DemoModeDelegate {
public:
FakeDemoModeDelegate() = default;
~FakeDemoModeDelegate() override = default;
FakeDemoModeDelegate(const FakeDemoModeDelegate&) = delete;
FakeDemoModeDelegate& operator=(const FakeDemoModeDelegate&) = delete;
void EnsureOfflineResourcesLoaded(base::OnceClosure callback) override {
std::move(callback).Run();
}
base::FilePath GetDemoAppsPath() override { return base::FilePath(); }
};
class ArcVmClientAdapterTest : public testing::Test,
public ArcClientAdapter::Observer {
public:
......@@ -286,6 +319,8 @@ class ArcVmClientAdapterTest : public testing::Test,
base::TimeDelta::FromMilliseconds(20));
chromeos::SessionManagerClient::InitializeFake();
adapter_->SetDemoModeDelegate(&demo_mode_delegate_);
}
void TearDown() override {
......@@ -311,6 +346,10 @@ class ArcVmClientAdapterTest : public testing::Test,
run_loop()->Quit();
}
void ExpectTrue(bool result) { EXPECT_TRUE(result); }
void ExpectFalse(bool result) { EXPECT_FALSE(result); }
protected:
void SetValidUserInfo() { SetUserInfo(kUserIdHash, kSerialNumber); }
......@@ -327,6 +366,7 @@ class ArcVmClientAdapterTest : public testing::Test,
? &ArcVmClientAdapterTest::ExpectTrueThenQuit
: &ArcVmClientAdapterTest::ExpectFalseThenQuit,
base::Unretained(this)));
run_loop()->Run();
RecreateRunLoop();
}
......@@ -342,6 +382,20 @@ class ArcVmClientAdapterTest : public testing::Test,
RecreateRunLoop();
}
void UpgradeArcWithParamsAndStopVmCount(bool expect_success,
UpgradeParams params,
int run_until_stop_vm_count) {
GetTestConciergeClient()->set_on_stop_vm_callback(run_loop()->QuitClosure(),
run_until_stop_vm_count);
adapter()->UpgradeArc(
std::move(params),
base::BindOnce(expect_success ? &ArcVmClientAdapterTest::ExpectTrue
: &ArcVmClientAdapterTest::ExpectFalse,
base::Unretained(this)));
run_loop()->Run();
RecreateRunLoop();
}
// Starts mini instance with the default StartParams.
void StartMiniArc() { StartMiniArcWithParams(true, {}); }
......@@ -431,6 +485,45 @@ class ArcVmClientAdapterTest : public testing::Test,
chromeos::FakeUpstartClient::StartStopJobCallback());
}
// Calls ArcVmClientAdapter::StopArcInstance().
// If |arc_upgraded| is false, we expect ConciergeClient::StopVm to have been
// called two times, once to clear a stale mini-VM in StartMiniArc(), and
// another on this call to StopArcInstance().
// If |arc_upgraded| is true, we expect StopVm() to have been called three
// times, to clear a stale mini-VM in StartMiniArc(), to clear a stale
// full-VM in UpgradeArc, and finally on this call to StopArcInstance();
void StopArcInstance(bool arc_upgraded) {
adapter()->StopArcInstance(/*on_shutdown=*/false,
/*should_backup_log=*/false);
run_loop()->RunUntilIdle();
EXPECT_EQ(arc_upgraded ? 3 : 2,
GetTestConciergeClient()->stop_vm_call_count());
EXPECT_FALSE(arc_instance_stopped_called());
RecreateRunLoop();
SendVmStoppedSignal();
run_loop()->Run();
EXPECT_TRUE(arc_instance_stopped_called());
}
// Checks that ArcVmClientAdapter has requested to stop the VM (after an
// error in UpgradeArc).
// If |stale_full_vm_stopped| is false, we expect ConciergeClient::StopVm to
// have been called two times, once to clear a stale mini-VM in
// StartMiniArc(), and another after some error condition. If
// |stale_full_vm_stopped| is true, we expect StopVm() to have been called
// three times, to clear a stale mini-VM in StartMiniArc(), to clear a stale
// full-VM in UpgradeArc, and finally after some error condition.
void ExpectArcStopped(bool stale_full_vm_stopped) {
EXPECT_EQ(stale_full_vm_stopped ? 3 : 2,
GetTestConciergeClient()->stop_vm_call_count());
EXPECT_FALSE(arc_instance_stopped_called());
RecreateRunLoop();
SendVmStoppedSignal();
run_loop()->Run();
EXPECT_TRUE(arc_instance_stopped_called());
}
void RecreateRunLoop() { run_loop_ = std::make_unique<base::RunLoop>(); }
base::RunLoop* run_loop() { return run_loop_.get(); }
......@@ -490,6 +583,8 @@ class ArcVmClientAdapterTest : public testing::Test,
std::unique_ptr<TestArcVmBootNotificationServer> boot_server_;
FakeDemoModeDelegate demo_mode_delegate_;
DISALLOW_COPY_AND_ASSIGN(ArcVmClientAdapterTest);
};
......@@ -501,12 +596,9 @@ TEST_F(ArcVmClientAdapterTest, SetUserInfo) {
// Tests that StartMiniArc() succeeds by default.
TEST_F(ArcVmClientAdapterTest, StartMiniArc) {
StartMiniArc();
// Confirm that no VM is started. ARCVM doesn't support mini ARC yet.
EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
// TODO(wvk): Once mini VM is supported, call StopArcInstance() and
// SendVmStoppedSignal() here, then verify arc_instance_stopped_called()
// becomes true. See StopArcInstance test for more details.
StopArcInstance(/*arc_upgraded=*/false);
}
// Tests that StartMiniArc() still succeeds even when Upstart fails to stop
......@@ -516,12 +608,9 @@ TEST_F(ArcVmClientAdapterTest, StartMiniArc_StopArcVmPostLoginServicesJobFail) {
InjectUpstartStopJobFailure(kArcVmPostLoginServicesJobName);
StartMiniArc();
// Confirm that no VM is started. ARCVM doesn't support mini ARC yet.
EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
// TODO(wvk): Once mini VM is supported, call StopArcInstance() here,
// then verify arc_instance_stopped_called() never becomes true. Same
// for other StartMiniArc_...Fail tests.
StopArcInstance(/*arc_upgraded=*/false);
}
// Tests that StartMiniArc() fails when Upstart fails to start the job.
......@@ -530,6 +619,7 @@ TEST_F(ArcVmClientAdapterTest, StartMiniArc_StartArcVmPerBoardFeaturesJobFail) {
InjectUpstartStartJobFailure(kArcVmPerBoardFeaturesJobName);
StartMiniArcWithParams(false, {});
// Confirm that no VM is started.
EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
}
......@@ -541,7 +631,6 @@ TEST_F(ArcVmClientAdapterTest, StartMiniArc_StartArcVmPreLoginServicesJobFail) {
InjectUpstartStartJobFailure(kArcVmPreLoginServicesJobName);
StartMiniArcWithParams(false, {});
// Confirm that no VM is started. ARCVM doesn't support mini ARC yet.
EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
}
......@@ -552,8 +641,9 @@ TEST_F(ArcVmClientAdapterTest, StartMiniArc_StopArcVmPreLoginServicesJobFail) {
InjectUpstartStopJobFailure(kArcVmPreLoginServicesJobName);
StartMiniArc();
// Confirm that no VM is started. ARCVM doesn't support mini ARC yet.
EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
StopArcInstance(/*arc_upgraded=*/false);
}
// Tests that StartMiniArc()'s JOB_STOP_AND_START for
......@@ -584,7 +674,7 @@ TEST_F(ArcVmClientAdapterTest, StopArcInstance) {
adapter()->StopArcInstance(/*on_shutdown=*/false,
/*should_backup_log=*/false);
run_loop()->RunUntilIdle();
EXPECT_EQ(2, GetTestConciergeClient()->stop_vm_call_count());
EXPECT_EQ(3, GetTestConciergeClient()->stop_vm_call_count());
// The callback for StopVm D-Bus reply does NOT call ArcInstanceStopped when
// the D-Bus call result is successful.
EXPECT_FALSE(arc_instance_stopped_called());
......@@ -628,6 +718,7 @@ TEST_F(ArcVmClientAdapterTest, DoesNotGetArcInstanceStoppedOnNestedInstance) {
nested_adapter_->SetUserInfo(
cryptohome::Identification(user_manager::StubAccountId()),
kUserIdHash, kSerialNumber);
nested_adapter_->SetDemoModeDelegate(&demo_mode_delegate_);
base::RunLoop* run_loop = run_loop_factory_.Run();
nested_adapter_->StartMiniArc({}, QuitClosure(run_loop));
......@@ -649,6 +740,7 @@ TEST_F(ArcVmClientAdapterTest, DoesNotGetArcInstanceStoppedOnNestedInstance) {
base::RepeatingCallback<base::RunLoop*()> const run_loop_factory_;
Observer* const child_observer_;
std::unique_ptr<ArcClientAdapter> nested_adapter_;
FakeDemoModeDelegate demo_mode_delegate_;
bool stopped_called_ = false;
};
......@@ -684,7 +776,7 @@ TEST_F(ArcVmClientAdapterTest, StopArcInstance_WithLogBackup) {
adapter()->StopArcInstance(/*on_shutdown=*/false, /*should_backup_log=*/true);
run_loop()->RunUntilIdle();
EXPECT_EQ(2, GetTestConciergeClient()->stop_vm_call_count());
EXPECT_EQ(3, GetTestConciergeClient()->stop_vm_call_count());
// The callback for StopVm D-Bus reply does NOT call ArcInstanceStopped when
// the D-Bus call result is successful.
EXPECT_FALSE(arc_instance_stopped_called());
......@@ -707,7 +799,7 @@ TEST_F(ArcVmClientAdapterTest, StopArcInstance_WithLogBackup_BackupFailed) {
adapter()->StopArcInstance(/*on_shutdown=*/false, /*should_backup_log=*/true);
run_loop()->RunUntilIdle();
EXPECT_EQ(2, GetTestConciergeClient()->stop_vm_call_count());
EXPECT_EQ(3, GetTestConciergeClient()->stop_vm_call_count());
// The callback for StopVm D-Bus reply does NOT call ArcInstanceStopped when
// the D-Bus call result is successful.
EXPECT_FALSE(arc_instance_stopped_called());
......@@ -730,7 +822,7 @@ TEST_F(ArcVmClientAdapterTest, StopArcInstance_OnShutdown) {
adapter()->StopArcInstance(/*on_shutdown=*/true, /*should_backup_log=*/false);
run_loop()->RunUntilIdle();
EXPECT_EQ(1, GetTestConciergeClient()->stop_vm_call_count());
EXPECT_EQ(2, GetTestConciergeClient()->stop_vm_call_count());
EXPECT_FALSE(arc_instance_stopped_called());
}
......@@ -747,13 +839,38 @@ TEST_F(ArcVmClientAdapterTest, StopArcInstance_Fail) {
adapter()->StopArcInstance(/*on_shutdown=*/false,
/*should_backup_log=*/false);
run_loop()->Run();
EXPECT_EQ(2, GetTestConciergeClient()->stop_vm_call_count());
EXPECT_EQ(3, GetTestConciergeClient()->stop_vm_call_count());
// The callback for StopVm D-Bus reply does call ArcInstanceStopped when
// the D-Bus call result is NOT successful.
EXPECT_TRUE(arc_instance_stopped_called());
}
// Test that StopArcInstance() stops the mini-VM if it cannot find a VM with
// the current user ID hash.
TEST_F(ArcVmClientAdapterTest, StopArcInstance_StopMiniVm) {
StartMiniArc();
SetValidUserInfo();
vm_tools::concierge::GetVmInfoResponse response;
response.set_success(false);
GetTestConciergeClient()->set_get_vm_info_response(response);
adapter()->StopArcInstance(/*on_shutdown=*/false,
/*should_backup_log*/ false);
run_loop()->RunUntilIdle();
EXPECT_TRUE(GetTestConciergeClient()->get_vm_info_called());
// Expect StopVm() to be called twice; once in StartMiniArc to clear stale
// mini-VM, and again on StopArcInstance().
EXPECT_EQ(2, GetTestConciergeClient()->stop_vm_call_count());
EXPECT_EQ(kArcVmDefaultOwner,
GetTestConciergeClient()->stop_vm_request().owner_id());
}
// Tests that UpgradeArc() handles arcvm-post-login-services startup failures
// properly.
TEST_F(ArcVmClientAdapterTest, UpgradeArc_StartArcVmPostLoginServicesFailure) {
......@@ -763,76 +880,54 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_StartArcVmPostLoginServicesFailure) {
// Inject failure to FakeUpstartClient.
InjectUpstartStartJobFailure(kArcVmPostLoginServicesJobName);
UpgradeArc(false);
EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
UpgradeArcWithParamsAndStopVmCount(false, {}, /*run_until_stop_vm_count=*/3);
// Try to stop the VM. No VM is running so StopVm() shouldn't be called.
adapter()->StopArcInstance(/*on_shutdown=*/false,
/*should_backup_log=*/false);
run_loop()->Run();
EXPECT_EQ(0, GetTestConciergeClient()->stop_vm_call_count());
EXPECT_TRUE(arc_instance_stopped_called());
ExpectArcStopped(/*stale_full_vm_stopped=*/true);
}
// Tests that UpgradeArc() handles arcvm-post-vm-start-services stop failures
// Tests that StartMiniArc() handles arcvm-post-vm-start-services stop failures
// properly.
TEST_F(ArcVmClientAdapterTest, UpgradeArc_StopArcVmPostVmStartServicesFailure) {
TEST_F(ArcVmClientAdapterTest,
StartMiniArc_StopArcVmPostVmStartServicesFailure) {
SetValidUserInfo();
StartMiniArc();
// Inject failure to FakeUpstartClient.
InjectUpstartStopJobFailure(kArcVmPostVmStartServicesJobName);
// Upgrade should still succeed.
UpgradeArc(true);
// StartMiniArc should still succeed.
StartMiniArc();
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
// Make sure StopVm() is not called.
// Make sure StopVm() is called only once, to stop existing VMs on
// StartMiniArc().
EXPECT_EQ(1, GetTestConciergeClient()->stop_vm_call_count());
}
// Tests that UpgradeArc() handles arcvm-post-vm-start-services startup failures
// properly.
// Tests that UpgradeArc() handles arcvm-post-vm-start-services startup
// failures properly.
TEST_F(ArcVmClientAdapterTest,
UpgradeArc_StartArcVmPostVmStartServicesFailure) {
SetValidUserInfo();
EnableAdbOverUsbForTesting();
StartMiniArc();
// Inject failure to FakeUpstartClient.
InjectUpstartStartJobFailure(kArcVmPostVmStartServicesJobName);
EnableAdbOverUsbForTesting();
UpgradeArc(false);
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
// Make sure StopVm() *is* called.
EXPECT_EQ(2, GetTestConciergeClient()->stop_vm_call_count());
// Run the loop and make sure the VM is stopped.
SendVmStoppedSignal();
run_loop()->Run();
EXPECT_TRUE(arc_instance_stopped_called());
// UpgradeArc should fail and the VM should be stoppped.
UpgradeArcWithParamsAndStopVmCount(false, {}, /*run_until_stop_vm_count=*/3);
ExpectArcStopped(/*stale_full_vm_stopped=*/true);
}
// Tests that "no user ID hash" failure is handled properly.
TEST_F(ArcVmClientAdapterTest, UpgradeArc_NoUserId) {
// Don't set the user id hash. Note that we cannot call StartArcVm() without
// it.
// Don't set the user id hash.
SetUserInfo(std::string(), kSerialNumber);
StartMiniArc();
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
UpgradeArc(false);
EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
// Try to stop the VM. No VM is running so StopVm() shouldn't be called.
adapter()->StopArcInstance(/*on_shutdown=*/false,
/*should_backup_log=*/false);
run_loop()->Run();
EXPECT_EQ(0, GetTestConciergeClient()->stop_vm_call_count());
EXPECT_TRUE(arc_instance_stopped_called());
UpgradeArcWithParamsAndStopVmCount(false, {}, /*run_until_stop_vm_count=*/2);
ExpectArcStopped(/*stale_full_vm_stopped=*/false);
}
// Tests that a "Failed Adb Sideload response" case is handled properly.
......@@ -843,16 +938,9 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_FailedAdbResponse) {
// Ask the Fake Session Manager to return a failed Adb Sideload response.
chromeos::FakeSessionManagerClient::Get()->set_adb_sideload_response(
chromeos::FakeSessionManagerClient::AdbSideloadResponseCode::FAILED);
UpgradeArc(false);
EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
// Try to stop the VM. No VM is running so StopVm() shouldn't be called.
adapter()->StopArcInstance(/*on_shutdown=*/false,
/*should_backup_log=*/false);
run_loop()->Run();
EXPECT_EQ(0, GetTestConciergeClient()->stop_vm_call_count());
EXPECT_TRUE(arc_instance_stopped_called());
UpgradeArcWithParamsAndStopVmCount(false, {}, /*run_until_stop_vm_count=*/3);
ExpectArcStopped(/*stale_full_vm_stopped=*/true);
}
// Tests that a "Need_Powerwash Adb Sideload response" case is handled properly.
......@@ -868,9 +956,8 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_NeedPowerwashAdbResponse) {
UpgradeArc(true);
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
EXPECT_TRUE(
base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
"androidboot.enable_adb_sideloading=0"));
EXPECT_TRUE(base::Contains(boot_notification_server()->received_data(),
"ro.boot.enable_adb_sideloading=0"));
}
// Tests that adb sideloading is disabled by default.
......@@ -881,9 +968,8 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_AdbSideloadingPropertyDefault) {
UpgradeArc(true);
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
EXPECT_TRUE(
base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
"androidboot.enable_adb_sideloading=0"));
EXPECT_TRUE(base::Contains(boot_notification_server()->received_data(),
"ro.boot.enable_adb_sideloading=0"));
}
// Tests that adb sideloading can be controlled via session_manager.
......@@ -895,9 +981,8 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_AdbSideloadingPropertyEnabled) {
UpgradeArc(true);
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
EXPECT_TRUE(
base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
"androidboot.enable_adb_sideloading=1"));
EXPECT_TRUE(base::Contains(boot_notification_server()->received_data(),
"ro.boot.enable_adb_sideloading=1"));
}
TEST_F(ArcVmClientAdapterTest, UpgradeArc_AdbSideloadingPropertyDisabled) {
......@@ -908,128 +993,139 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_AdbSideloadingPropertyDisabled) {
UpgradeArc(true);
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
EXPECT_TRUE(
base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
"androidboot.enable_adb_sideloading=0"));
EXPECT_TRUE(base::Contains(boot_notification_server()->received_data(),
"ro.boot.enable_adb_sideloading=0"));
}
// Tests that "no serial" failure is handled properly.
TEST_F(ArcVmClientAdapterTest, UpgradeArc_NoSerial) {
// Don't set the serial number. Note that we cannot call StartArcVm() without
// it.
// Don't set the serial number.
SetUserInfo(kUserIdHash, std::string());
StartMiniArc();
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
UpgradeArc(false);
EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
UpgradeArcWithParamsAndStopVmCount(false, {}, /*run_until_stop_vm_count=*/2);
ExpectArcStopped(/*stale_full_vm_stopped=*/false);
}
// Try to stop the VM. No VM is running so StopVm() shouldn't be called.
adapter()->StopArcInstance(/*on_shutdown=*/false,
/*should_backup_log=*/false);
run_loop()->Run();
EXPECT_EQ(0, GetTestConciergeClient()->stop_vm_call_count());
EXPECT_TRUE(arc_instance_stopped_called());
// Test that ConciergeClient::SetVmId() empty reply is handled properly.
TEST_F(ArcVmClientAdapterTest, UpgradeArc_SetVmIdEmptyReply) {
SetValidUserInfo();
StartMiniArc();
// Inject failure
GetTestConciergeClient()->set_set_vm_id_response(base::nullopt);
UpgradeArcWithParamsAndStopVmCount(false, {}, /*run_until_stop_vm_count=*/3);
ExpectArcStopped(/*stale_full_vm_stopped=*/true);
}
TEST_F(ArcVmClientAdapterTest, StopExistingVmFailure) {
// Test that ConciergeClient::SetVmId() unsuccessful reply is handled properly.
TEST_F(ArcVmClientAdapterTest, UpgradeArc_SetVmIdFailure) {
SetValidUserInfo();
StartMiniArc();
// Inject failure
vm_tools::concierge::SetVmIdResponse response;
response.set_success(false);
GetTestConciergeClient()->set_set_vm_id_response(response);
UpgradeArcWithParamsAndStopVmCount(false, {}, /*run_until_stop_vm_count=*/3);
ExpectArcStopped(/*stale_full_vm_stopped=*/true);
}
TEST_F(ArcVmClientAdapterTest, StartMiniArc_StopExistingVmFailure) {
// Inject failure.
vm_tools::concierge::StopVmResponse response;
response.set_success(false);
GetTestConciergeClient()->set_stop_vm_response(response);
UpgradeArc(false);
StartMiniArcWithParams(false, {});
EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
}
// Try to stop the VM. No VM is running so StopVm() shouldn't be called.
adapter()->StopArcInstance(/*on_shutdown=*/false,
/*should_backup_log=*/false);
run_loop()->Run();
EXPECT_EQ(1, GetTestConciergeClient()->stop_vm_call_count());
EXPECT_TRUE(arc_instance_stopped_called());
TEST_F(ArcVmClientAdapterTest, StartMiniArc_StopExistingVmFailureEmptyReply) {
// Inject failure.
GetTestConciergeClient()->set_stop_vm_response(base::nullopt);
StartMiniArcWithParams(false, {});
EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
}
TEST_F(ArcVmClientAdapterTest, UpgradeArc_StopExistingVmFailure) {
SetValidUserInfo();
StartMiniArc();
// Inject failure.
vm_tools::concierge::StopVmResponse response;
response.set_success(false);
GetTestConciergeClient()->set_stop_vm_response(response);
UpgradeArcWithParamsAndStopVmCount(false, {}, /*run_until_stop_vm_count=*/3);
ExpectArcStopped(/*stale_full_vm_stopped=*/true);
}
TEST_F(ArcVmClientAdapterTest, StopExistingVmFailureEmptyReply) {
TEST_F(ArcVmClientAdapterTest, UpgradeArc_StopExistingVmFailureEmptyReply) {
SetValidUserInfo();
StartMiniArc();
// Inject failure.
GetTestConciergeClient()->set_stop_vm_response(base::nullopt);
UpgradeArc(false);
UpgradeArcWithParamsAndStopVmCount(false, {}, /*run_until_stop_vm_count=*/3);
ExpectArcStopped(/*stale_full_vm_stopped=*/true);
}
// Tests that ConciergeClient::WaitForServiceToBeAvailable() failure is handled
// properly.
TEST_F(ArcVmClientAdapterTest, StartMiniArc_WaitForConciergeAvailableFailure) {
// Inject failure.
GetTestConciergeClient()->set_wait_for_service_to_be_available_response(
false);
StartMiniArcWithParams(false, {});
EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
// Try to stop the VM. No VM is running so StopVm() shouldn't be called.
adapter()->StopArcInstance(/*on_shutdown=*/false,
/*should_backup_log=*/false);
run_loop()->Run();
EXPECT_EQ(1, GetTestConciergeClient()->stop_vm_call_count());
EXPECT_TRUE(arc_instance_stopped_called());
}
// Tests that StartArcVm() failure is handled properly.
TEST_F(ArcVmClientAdapterTest, UpgradeArc_StartArcVmFailure) {
TEST_F(ArcVmClientAdapterTest, StartMiniArc_StartArcVmFailure) {
SetValidUserInfo();
StartMiniArc();
// Inject failure to StartArcVm().
vm_tools::concierge::StartVmResponse start_vm_response;
start_vm_response.set_status(vm_tools::concierge::VM_STATUS_UNKNOWN);
GetTestConciergeClient()->set_start_vm_response(start_vm_response);
UpgradeArc(false);
StartMiniArcWithParams(false, {});
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
// Try to stop the VM. No VM is running so StopVm() shouldn't be called.
adapter()->StopArcInstance(/*on_shutdown=*/false,
/*should_backup_log=*/false);
run_loop()->Run();
EXPECT_EQ(1, GetTestConciergeClient()->stop_vm_call_count());
EXPECT_TRUE(arc_instance_stopped_called());
}
TEST_F(ArcVmClientAdapterTest, UpgradeArc_StartArcVmFailureEmptyReply) {
TEST_F(ArcVmClientAdapterTest, StartMiniArc_StartArcVmFailureEmptyReply) {
SetValidUserInfo();
StartMiniArc();
// Inject failure to StartArcVm(). This emulates D-Bus timeout situations.
GetTestConciergeClient()->set_start_vm_response(base::nullopt);
UpgradeArc(false);
StartMiniArcWithParams(false, {});
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
// Try to stop the VM. No VM is running so StopVm() shouldn't be called.
adapter()->StopArcInstance(/*on_shutdown=*/false,
/*should_backup_log=*/false);
run_loop()->Run();
EXPECT_EQ(1, GetTestConciergeClient()->stop_vm_call_count());
EXPECT_TRUE(arc_instance_stopped_called());
}
// Tests that successful StartArcVm() call is handled properly.
TEST_F(ArcVmClientAdapterTest, UpgradeArc_Success) {
SetValidUserInfo();
StartMiniArc();
UpgradeArc(true);
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
UpgradeArc(true);
// Try to stop the VM.
adapter()->StopArcInstance(/*on_shutdown=*/false,
/*should_backup_log=*/false);
run_loop()->RunUntilIdle();
EXPECT_EQ(2, GetTestConciergeClient()->stop_vm_call_count());
EXPECT_FALSE(arc_instance_stopped_called());
RecreateRunLoop();
SendVmStoppedSignal();
run_loop()->Run();
EXPECT_TRUE(arc_instance_stopped_called());
StopArcInstance(/*arc_upgraded=*/true);
}
// Try to start and upgrade the instance with more params.
......@@ -1038,10 +1134,11 @@ TEST_F(ArcVmClientAdapterTest, StartUpgradeArc_VariousParams) {
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
UpgradeParams params(GetPopulatedUpgradeParams());
UpgradeArcWithParams(true, std::move(params));
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
UpgradeParams params(GetPopulatedUpgradeParams());
UpgradeArcWithParams(true, std::move(params));
}
// Try to start and upgrade the instance with slightly different params
......@@ -1055,6 +1152,9 @@ TEST_F(ArcVmClientAdapterTest, StartUpgradeArc_VariousParams2) {
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
UpgradeParams params(GetPopulatedUpgradeParams());
// Use slightly different params than StartUpgradeArc_VariousParams.
params.packages_cache_mode =
......@@ -1063,25 +1163,33 @@ TEST_F(ArcVmClientAdapterTest, StartUpgradeArc_VariousParams2) {
params.preferred_languages = {"en_US"};
UpgradeArcWithParams(true, std::move(params));
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
}
// Try to start and upgrade the instance with demo mode enabled.
TEST_F(ArcVmClientAdapterTest, StartUpgradeArc_DemoMode) {
constexpr char kDemoImage[] =
"/run/imageloader/demo-mode-resources/0.0.1.7/android_demo_apps.squash";
base::FilePath apps_path = base::FilePath(kDemoImage);
StartParams start_params(GetPopulatedStartParams());
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
class TestDemoDelegate : public ArcClientAdapter::DemoModeDelegate {
public:
TestDemoDelegate(base::FilePath apps_path) : apps_path_(apps_path) {}
~TestDemoDelegate() override = default;
UpgradeParams params(GetPopulatedUpgradeParams());
// Enable demo mode.
params.is_demo_session = true;
params.demo_session_apps_path = base::FilePath(kDemoImage);
void EnsureOfflineResourcesLoaded(base::OnceClosure callback) override {
std::move(callback).Run();
}
base::FilePath GetDemoAppsPath() override { return apps_path_; }
private:
base::FilePath apps_path_;
};
TestDemoDelegate delegate(apps_path);
adapter()->SetDemoModeDelegate(&delegate);
StartMiniArc();
UpgradeArcWithParams(true, std::move(params));
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
......@@ -1095,16 +1203,22 @@ TEST_F(ArcVmClientAdapterTest, StartUpgradeArc_DemoMode) {
}
return false;
}()));
EXPECT_TRUE(base::Contains(request.params(), "androidboot.arc_demo_mode=1"));
SetValidUserInfo();
UpgradeParams params(GetPopulatedUpgradeParams());
// Enable demo mode.
params.is_demo_session = true;
UpgradeArcWithParams(true, std::move(params));
EXPECT_TRUE(base::Contains(boot_notification_server()->received_data(),
"ro.boot.arc_demo_mode=1"));
}
TEST_F(ArcVmClientAdapterTest, StartUpgradeArc_DisableSystemDefaultApp) {
TEST_F(ArcVmClientAdapterTest, StartMiniArc_DisableSystemDefaultApp) {
StartParams start_params(GetPopulatedStartParams());
start_params.arc_disable_system_default_app = true;
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
UpgradeParams params(GetPopulatedUpgradeParams());
UpgradeArcWithParams(true, std::move(params));
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
EXPECT_TRUE(
......@@ -1113,16 +1227,14 @@ TEST_F(ArcVmClientAdapterTest, StartUpgradeArc_DisableSystemDefaultApp) {
}
// Tests that StartArcVm() is called with valid parameters.
TEST_F(ArcVmClientAdapterTest, UpgradeArc_StartArcVmParams) {
TEST_F(ArcVmClientAdapterTest, StartMiniArc_StartArcVmParams) {
SetValidUserInfo();
StartMiniArc();
UpgradeArc(true);
ASSERT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
// Verify parameters
const auto& params = GetTestConciergeClient()->start_arc_vm_request();
EXPECT_EQ("arcvm", params.name());
EXPECT_EQ(kUserIdHash, params.owner_id());
EXPECT_LT(0u, params.cpus());
EXPECT_FALSE(params.vm().kernel().empty());
// Make sure system.raw.img is passed.
......@@ -1136,9 +1248,9 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_StartArcVmParams) {
TEST_F(ArcVmClientAdapterTest, CrosvmCrash) {
SetValidUserInfo();
StartMiniArc();
UpgradeArc(true);
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
UpgradeArc(true);
// Kill crosvm and verify StopArcInstance is called.
SendVmStoppedSignal();
......@@ -1150,9 +1262,9 @@ TEST_F(ArcVmClientAdapterTest, CrosvmCrash) {
TEST_F(ArcVmClientAdapterTest, ConciergeCrash) {
SetValidUserInfo();
StartMiniArc();
UpgradeArc(true);
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
UpgradeArc(true);
// Kill vm_concierge and verify StopArcInstance is called.
SendNameOwnerChangedSignal();
......@@ -1164,9 +1276,9 @@ TEST_F(ArcVmClientAdapterTest, ConciergeCrash) {
TEST_F(ArcVmClientAdapterTest, CrosvmAndConciergeCrashes) {
SetValidUserInfo();
StartMiniArc();
UpgradeArc(true);
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
UpgradeArc(true);
// Kill crosvm and verify StopArcInstance is called.
SendVmStoppedSignal();
......@@ -1186,9 +1298,9 @@ TEST_F(ArcVmClientAdapterTest, CrosvmAndConciergeCrashes) {
TEST_F(ArcVmClientAdapterTest, VmStoppedSignal_UnknownCid) {
SetValidUserInfo();
StartMiniArc();
UpgradeArc(true);
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
EXPECT_FALSE(arc_instance_stopped_called());
UpgradeArc(true);
SendVmStoppedSignalForCid(42); // unknown CID
run_loop()->RunUntilIdle();
......@@ -1221,18 +1333,14 @@ TEST_F(ArcVmClientAdapterTest, VmStartedSignal) {
// Tests that ConciergeServiceStarted() doesn't crash.
TEST_F(ArcVmClientAdapterTest, TestConciergeServiceStarted) {
StartMiniArc();
for (auto& observer : GetTestConciergeClient()->observer_list())
observer.ConciergeServiceStarted();
GetTestConciergeClient()->NotifyConciergeStarted();
}
// Tests that the kernel parameter does not include "rw" by default.
TEST_F(ArcVmClientAdapterTest, KernelParam_RO) {
SetValidUserInfo();
StartMiniArc();
set_host_rootfs_writable(false);
set_system_image_ext_format(false);
UpgradeArc(true);
StartMiniArc();
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
// Check "rw" is not in |params|.
......@@ -1243,11 +1351,9 @@ TEST_F(ArcVmClientAdapterTest, KernelParam_RO) {
// Tests that the kernel parameter does include "rw" when '/' is writable and
// the image is in ext4.
TEST_F(ArcVmClientAdapterTest, KernelParam_RW) {
SetValidUserInfo();
StartMiniArc();
set_host_rootfs_writable(true);
set_system_image_ext_format(true);
UpgradeArc(true);
StartMiniArc();
EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
// Check "rw" is in |params|.
......@@ -1267,7 +1373,6 @@ TEST_F(ArcVmClientAdapterTest, ChromeOsChannelStable) {
StartParams start_params(GetPopulatedStartParams());
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
UpgradeArc(true);
EXPECT_TRUE(
base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
"androidboot.chromeos_channel=stable"));
......@@ -1280,7 +1385,6 @@ TEST_F(ArcVmClientAdapterTest, ChromeOsChannelUnknown) {
StartParams start_params(GetPopulatedStartParams());
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
UpgradeArc(true);
EXPECT_TRUE(
base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
"androidboot.chromeos_channel=unknown"));
......@@ -1331,7 +1435,6 @@ TEST_F(ArcVmClientAdapterTest, BintaryTranslationTypeNone) {
StartParams start_params(GetPopulatedStartParams());
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
UpgradeArc(true);
EXPECT_TRUE(
base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
"androidboot.native_bridge=0"));
......@@ -1345,7 +1448,6 @@ TEST_F(ArcVmClientAdapterTest, BintaryTranslationTypeHoudini) {
StartParams start_params(GetPopulatedStartParams());
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
UpgradeArc(true);
EXPECT_TRUE(
base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
"androidboot.native_bridge=libhoudini.so"));
......@@ -1359,7 +1461,6 @@ TEST_F(ArcVmClientAdapterTest, BintaryTranslationTypeHoudini64) {
StartParams start_params(GetPopulatedStartParams());
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
UpgradeArc(true);
EXPECT_TRUE(
base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
"androidboot.native_bridge=libhoudini.so"));
......@@ -1373,7 +1474,6 @@ TEST_F(ArcVmClientAdapterTest, BintaryTranslationTypeNdkTranslation) {
StartParams start_params(GetPopulatedStartParams());
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
UpgradeArc(true);
EXPECT_TRUE(
base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
"androidboot.native_bridge=libndk_translation.so"));
......@@ -1387,7 +1487,6 @@ TEST_F(ArcVmClientAdapterTest, BintaryTranslationTypeNdkTranslation64) {
StartParams start_params(GetPopulatedStartParams());
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
UpgradeArc(true);
EXPECT_TRUE(
base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
"androidboot.native_bridge=libndk_translation.so"));
......@@ -1403,7 +1502,6 @@ TEST_F(ArcVmClientAdapterTest, BintaryTranslationTypeNativeBridgeExperiment) {
start_params.native_bridge_experiment = true;
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
UpgradeArc(true);
EXPECT_TRUE(
base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
"androidboot.native_bridge=libndk_translation.so"));
......@@ -1419,7 +1517,6 @@ TEST_F(ArcVmClientAdapterTest, BintaryTranslationTypeNoNativeBridgeExperiment) {
start_params.native_bridge_experiment = false;
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
UpgradeArc(true);
EXPECT_TRUE(
base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
"androidboot.native_bridge=libhoudini.so"));
......@@ -1467,10 +1564,8 @@ TEST_F(ArcVmClientAdapterTest, TestBootNotificationServerIsNotListening) {
StartMiniArcWithParams(false, {});
}
// Tests that UpgradeArc() still succeeds even when sending the upgrade props
// Tests that UpgradeArc() fails when sending the upgrade props
// to the boot notification server fails.
// TODO(wvk): Once mini-VM is implemented, UpgradeArc(true) should be rewritten
// to UpgradeArc(false).
TEST_F(ArcVmClientAdapterTest, UpgradeArc_SendPropFail) {
SetValidUserInfo();
StartMiniArc();
......@@ -1478,13 +1573,12 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_SendPropFail) {
// Let ConnectToArcVmBootNotificationServer() return an invalid FD.
SetArcVmBootNotificationServerFdForTesting(-1);
UpgradeArc(true);
ASSERT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
UpgradeArcWithParamsAndStopVmCount(false, {}, /*run_until_stop_vm_count=*/3);
ExpectArcStopped(/*stale_full_vm_stopped=*/true);
}
// Tests that UpgradeArc() still succeeds even when sending the upgrade props
// Tests that UpgradeArc() fails when sending the upgrade props
// to the boot notification server fails.
// TODO(wvk): Rewrite this test too.
TEST_F(ArcVmClientAdapterTest, UpgradeArc_SendPropFailNotWritable) {
SetValidUserInfo();
StartMiniArc();
......@@ -1493,8 +1587,8 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_SendPropFailNotWritable) {
// is not writable.
SetArcVmBootNotificationServerFdForTesting(STDIN_FILENO);
UpgradeArc(true);
ASSERT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
UpgradeArcWithParamsAndStopVmCount(false, {}, /*run_until_stop_vm_count=*/3);
ExpectArcStopped(/*stale_full_vm_stopped=*/true);
}
struct DalvikMemoryProfileTestParam {
......@@ -1524,7 +1618,6 @@ TEST_P(ArcVmClientAdapterDalvikMemoryProfileTest, Profile) {
start_params.dalvik_memory_profile = test_param.profile;
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
UpgradeArcWithParams(true, GetPopulatedUpgradeParams());
auto request = GetTestConciergeClient()->start_arc_vm_request();
if (test_param.profile_name) {
EXPECT_TRUE(base::Contains(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment