chromium/chrome/browser/ash/borealis/borealis_app_launcher_unittest.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/borealis/borealis_app_launcher.h"

#include <memory>

#include "base/base64.h"
#include "base/functional/bind.h"
#include "base/test/bind.h"
#include "chrome/browser/ash/borealis/borealis_context.h"
#include "chrome/browser/ash/borealis/borealis_util.h"
#include "chrome/browser/ash/borealis/testing/apps.h"
#include "chrome/browser/ash/borealis/testing/callback_factory.h"
#include "chrome/browser/ash/guest_os/dbus_test_helper.h"
#include "chrome/browser/ash/guest_os/guest_os_registry_service.h"
#include "chrome/browser/ash/guest_os/guest_os_registry_service_factory.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/ash/components/dbus/cicerone/cicerone_client.h"
#include "chromeos/ash/components/dbus/cicerone/fake_cicerone_client.h"
#include "chromeos/ash/components/dbus/concierge/concierge_client.h"
#include "chromeos/ash/components/dbus/dbus_thread_manager.h"
#include "chromeos/ash/components/dbus/seneschal/seneschal_client.h"
#include "chromeos/ash/components/dbus/vm_applications/apps.pb.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace borealis {
namespace {

using CallbackFactory =
    StrictCallbackFactory<void(BorealisAppLauncher::LaunchResult)>;

class BorealisAppLauncherTest : public testing::Test,
                                protected guest_os::FakeVmServicesHelper {
 public:
  BorealisAppLauncherTest()
      : ctx_(BorealisContext::CreateBorealisContextForTesting(&profile_)) {
    ctx_->set_vm_name("borealis");
    ctx_->set_container_name("penguin");
  }

 protected:
  const BorealisContext& Context() { return *ctx_; }

  Profile* profile() { return &profile_; }

  // Sets up the registry with a single app. Returns its app id.
  std::string SetDummyApp(const std::string& desktop_file_id) {
    CreateFakeApp(profile(), desktop_file_id, /*exec=*/{});
    return FakeAppId(desktop_file_id);
  }

 private:
  content::BrowserTaskEnvironment task_environment_;
  TestingProfile profile_;
  std::unique_ptr<BorealisContext> ctx_;
};

TEST_F(BorealisAppLauncherTest, LauncherAppLaunchesMainApp) {
  CallbackFactory callback_check;
  CreateFakeMainApp(profile());

  EXPECT_CALL(callback_check,
              Call(BorealisAppLauncher::LaunchResult::kSuccess));
  FakeCiceroneClient()->SetOnLaunchContainerApplicationCallback(
      base::BindLambdaForTesting(
          [&](const vm_tools::cicerone::LaunchContainerApplicationRequest&
                  request,
              chromeos::DBusMethodCallback<
                  vm_tools::cicerone::LaunchContainerApplicationResponse>
                  callback) {
            vm_tools::cicerone::LaunchContainerApplicationResponse response;
            response.set_success(true);
            std::move(callback).Run(response);
          }));
  BorealisAppLauncher::Launch(Context(), kInstallerAppId,
                              callback_check.BindOnce());
}

TEST_F(BorealisAppLauncherTest, UnknownAppCausesError) {
  CallbackFactory callback_check;
  EXPECT_CALL(callback_check,
              Call(BorealisAppLauncher::LaunchResult::kUnknownApp));
  BorealisAppLauncher::Launch(Context(), "non_existent_app",
                              callback_check.BindOnce());
}

TEST_F(BorealisAppLauncherTest, NoResponseCausesError) {
  CallbackFactory callback_check;
  EXPECT_CALL(callback_check,
              Call(BorealisAppLauncher::LaunchResult::kNoResponse));
  std::string baz_id = SetDummyApp("foo.desktop");
  FakeCiceroneClient()->SetOnLaunchContainerApplicationCallback(
      base::BindLambdaForTesting(
          [&](const vm_tools::cicerone::LaunchContainerApplicationRequest&
                  request,
              chromeos::DBusMethodCallback<
                  vm_tools::cicerone::LaunchContainerApplicationResponse>
                  callback) {
            EXPECT_EQ(request.desktop_file_id(), "foo.desktop");
            std::move(callback).Run({});
          }));
  BorealisAppLauncher::Launch(Context(), baz_id, callback_check.BindOnce());
}

TEST_F(BorealisAppLauncherTest, ErrorResponseIsPropagated) {
  CallbackFactory callback_check;
  EXPECT_CALL(callback_check, Call(BorealisAppLauncher::LaunchResult::kError));
  std::string baz_id = SetDummyApp("bar.desktop");
  FakeCiceroneClient()->SetOnLaunchContainerApplicationCallback(
      base::BindLambdaForTesting(
          [&](const vm_tools::cicerone::LaunchContainerApplicationRequest&
                  request,
              chromeos::DBusMethodCallback<
                  vm_tools::cicerone::LaunchContainerApplicationResponse>
                  callback) {
            EXPECT_EQ(request.desktop_file_id(), "bar.desktop");
            vm_tools::cicerone::LaunchContainerApplicationResponse response;
            response.set_success(false);
            std::move(callback).Run(response);
          }));
  BorealisAppLauncher::Launch(Context(), baz_id, callback_check.BindOnce());
}

TEST_F(BorealisAppLauncherTest, SuccessfulLaunchHasSuccessResponse) {
  CallbackFactory callback_check;
  EXPECT_CALL(callback_check,
              Call(BorealisAppLauncher::LaunchResult::kSuccess));
  std::string baz_id = SetDummyApp("baz.desktop");
  FakeCiceroneClient()->SetOnLaunchContainerApplicationCallback(
      base::BindLambdaForTesting(
          [&](const vm_tools::cicerone::LaunchContainerApplicationRequest&
                  request,
              chromeos::DBusMethodCallback<
                  vm_tools::cicerone::LaunchContainerApplicationResponse>
                  callback) {
            EXPECT_EQ(request.desktop_file_id(), "baz.desktop");
            vm_tools::cicerone::LaunchContainerApplicationResponse response;
            response.set_success(true);
            std::move(callback).Run(response);
          }));
  BorealisAppLauncher::Launch(Context(), baz_id, callback_check.BindOnce());
}

TEST_F(BorealisAppLauncherTest, ApplicationIsRunWithGivenArgs) {
  CallbackFactory callback_check;
  EXPECT_CALL(callback_check,
              Call(BorealisAppLauncher::LaunchResult::kSuccess));
  std::string baz_id = SetDummyApp("baz.desktop");
  FakeCiceroneClient()->SetOnLaunchContainerApplicationCallback(
      base::BindLambdaForTesting(
          [&](const vm_tools::cicerone::LaunchContainerApplicationRequest&
                  request,
              chromeos::DBusMethodCallback<
                  vm_tools::cicerone::LaunchContainerApplicationResponse>
                  callback) {
            EXPECT_EQ(request.desktop_file_id(), "baz.desktop");
            EXPECT_THAT(
                request.files(),
                testing::Pointwise(testing::Eq(),
                                   {"these", "are", "some", "arguments"}));
            vm_tools::cicerone::LaunchContainerApplicationResponse response;
            response.set_success(true);
            std::move(callback).Run(response);
          }));
  BorealisAppLauncher::Launch(Context(), baz_id,
                              {"these", "are", "some", "arguments"},
                              callback_check.BindOnce());
}

}  // namespace
}  // namespace borealis