Skip to content

Commit

Permalink
Unit test for CrostiniPackageService
Browse files Browse the repository at this point in the history
Add unit test for CrostiniPackageService. Also fixes a corner case found
by unit test (queuing uninstalls while install starts up).

BUG=822514
TEST=Ran unit test

Change-Id: Ieede7119febda6a2fb67ca9835e8d859ddf08400
Reviewed-on: https://chromium-review.googlesource.com/c/1401611
Commit-Queue: Ian Barkley-Yeung <iby@chromium.org>
Reviewed-by: Timothy Loh <timloh@chromium.org>
Reviewed-by: Steven Bennetts <stevenjb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#630485}
  • Loading branch information
ianby authored and Commit Bot committed Feb 8, 2019
1 parent eead273 commit 96b891c
Show file tree
Hide file tree
Showing 7 changed files with 1,914 additions and 9 deletions.
1 change: 1 addition & 0 deletions chrome/browser/chromeos/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -2214,6 +2214,7 @@ source_set("unit_tests") {
"child_accounts/usage_time_limit_processor_unittest.cc",
"child_accounts/usage_time_state_notifier_unittest.cc",
"crostini/crostini_manager_unittest.cc",
"crostini/crostini_package_service_unittest.cc",
"crostini/crostini_share_path_unittest.cc",
"crostini/crosvm_metrics_unittest.cc",
"crostini/crosvm_process_list_unittest.cc",
Expand Down
7 changes: 7 additions & 0 deletions chrome/browser/chromeos/crostini/crostini_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,13 @@ class CrostiniManager::CrostiniRestarter

void SetUpLxdContainerUserFinished(CrostiniResult result) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// The restarter shouldn't outlive the CrostiniManager but it can when
// skip_restart_for_testing is set.
if (!crostini_manager_) {
LOG(ERROR) << "CrostiniManager deleted";
return;
}

// Tell observers.
for (auto& observer : observer_list_) {
observer.OnContainerSetup(result);
Expand Down
29 changes: 25 additions & 4 deletions chrome/browser/chromeos/crostini/crostini_package_service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/no_destructor.h"
#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
Expand Down Expand Up @@ -117,6 +118,11 @@ void CrostiniPackageService::Shutdown() {
manager->RemoveLinuxPackageOperationProgressObserver(this);
}

void CrostiniPackageService::SetNotificationStateChangeCallbackForTesting(
StateChangeCallback state_change_callback) {
testing_state_change_callback_ = std::move(state_change_callback);
}

void CrostiniPackageService::NotificationCompleted(
CrostiniPackageNotification* notification) {
for (auto it = finished_notifications_.begin();
Expand Down Expand Up @@ -147,6 +153,9 @@ void CrostiniPackageService::InstallLinuxPackage(
const std::string& container_name,
const std::string& package_path,
CrostiniManager::InstallLinuxPackageCallback callback) {
const ContainerIdentifier container_id(vm_name, container_name);
containers_with_pending_installs_.insert(container_id);

CrostiniManager::GetForProfile(profile_)->InstallLinuxPackage(
vm_name, container_name, package_path,
base::BindOnce(&CrostiniPackageService::OnInstallLinuxPackage,
Expand Down Expand Up @@ -213,8 +222,8 @@ std::string CrostiniPackageService::ContainerIdentifierToString(

bool CrostiniPackageService::ContainerHasRunningOperation(
const ContainerIdentifier& container_id) const {
return running_notifications_.find(container_id) !=
running_notifications_.end();
return base::ContainsKey(running_notifications_, container_id) ||
base::ContainsKey(containers_with_pending_installs_, container_id);
}

void CrostiniPackageService::CreateRunningNotification(
Expand Down Expand Up @@ -279,6 +288,9 @@ void CrostiniPackageService::UpdatePackageOperationStatus(
StartQueuedUninstall(container_id);
}
}
if (testing_state_change_callback_) {
testing_state_change_callback_.Run(status);
}
}

void CrostiniPackageService::OnGetLinuxPackageInfo(
Expand All @@ -295,9 +307,18 @@ void CrostiniPackageService::OnInstallLinuxPackage(
CrostiniManager::InstallLinuxPackageCallback callback,
CrostiniResult result) {
std::move(callback).Run(result);
if (result != CrostiniResult::SUCCESS)
return;
const ContainerIdentifier container_id(vm_name, container_name);
containers_with_pending_installs_.erase(container_id);
if (result != CrostiniResult::SUCCESS) {
// We never show a notification for this failed install, so this is our only
// chance to kick off uninstalled queued behind the install.
auto queued_iter = queued_uninstalls_.find(container_id);
if (queued_iter != queued_uninstalls_.end() &&
!queued_iter->second.empty()) {
StartQueuedUninstall(container_id);
}
return;
}
CreateRunningNotification(
container_id,
CrostiniPackageNotification::NotificationType::PACKAGE_INSTALL,
Expand Down
18 changes: 18 additions & 0 deletions chrome/browser/chromeos/crostini/crostini_package_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
#include <map>
#include <memory>
#include <queue>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/crostini/crostini_manager.h"
#include "chrome/browser/chromeos/crostini/crostini_package_notification.h"
Expand All @@ -24,11 +26,19 @@ namespace crostini {
class CrostiniPackageService : public KeyedService,
public LinuxPackageOperationProgressObserver {
public:
using StateChangeCallback =
base::RepeatingCallback<void(PackageOperationStatus)>;

static CrostiniPackageService* GetForProfile(Profile* profile);

explicit CrostiniPackageService(Profile* profile);
~CrostiniPackageService() override;

// For testing: Set a callback that will be called each time a notification
// is set to a new state.
void SetNotificationStateChangeCallbackForTesting(
StateChangeCallback state_change_callback);

// KeyedService:
void Shutdown() override;

Expand Down Expand Up @@ -147,6 +157,11 @@ class CrostiniPackageService : public KeyedService,
std::map<ContainerIdentifier, std::unique_ptr<CrostiniPackageNotification>>
running_notifications_;

// Containers that have an install waiting for its initial response. We don't
// display notifications for these, but they still need to cause uninstalls
// to queue.
std::set<ContainerIdentifier> containers_with_pending_installs_;

// Uninstalls we want to run when the current one is done.
std::map<ContainerIdentifier, std::queue<QueuedUninstall>> queued_uninstalls_;

Expand All @@ -156,6 +171,9 @@ class CrostiniPackageService : public KeyedService,
std::vector<std::unique_ptr<CrostiniPackageNotification>>
finished_notifications_;

// Called each time a notification is set to a new state.
StateChangeCallback testing_state_change_callback_;

int next_notification_id_ = 0;

base::WeakPtrFactory<CrostiniPackageService> weak_ptr_factory_;
Expand Down
Loading

0 comments on commit 96b891c

Please sign in to comment.