chromium/chrome/browser/ash/bruschetta/bruschetta_installer_impl_unittest.cc

// Copyright 2022 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/bruschetta/bruschetta_installer_impl.h"

#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/values.h"
#include "chrome/browser/ash/bruschetta/bruschetta_download.h"
#include "chrome/browser/ash/bruschetta/bruschetta_installer.h"
#include "chrome/browser/ash/bruschetta/bruschetta_pref_names.h"
#include "chrome/browser/ash/bruschetta/bruschetta_service.h"
#include "chrome/browser/ash/guest_os/dbus_test_helper.h"
#include "chrome/browser/profiles/profile_key.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/ash/components/dbus/attestation/attestation_client.h"
#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
#include "chromeos/ash/components/dbus/dlcservice/dlcservice.pb.h"
#include "chromeos/ash/components/dbus/dlcservice/fake_dlcservice_client.h"
#include "chromeos/ash/components/disks/disk_mount_manager.h"
#include "chromeos/ash/components/disks/mock_disk_mount_manager.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest-spi.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace bruschetta {

// Defined in bruschetta_installer_impl.cc
extern const char kInstallResultMetric[];

namespace {

using testing::_;
using testing::AnyNumber;
using testing::DoAll;
using testing::InvokeWithoutArgs;
using testing::Sequence;

// Total number of stopping points in ::ExpectStopOnStepN
constexpr int kMaxSteps = 26;

// Total number of stopping points in ::ExpectStopOnStepN when we don't install
// a pflash file.
constexpr int kMaxStepsNoPflash = kMaxSteps - 7;

const char kVmName[] = "vm-name";
const char kVmConfigId[] = "test-config-id";
const char kVmConfigName[] = "test vm config";
const char kVmConfigUrl[] = "https://example.com/";
const char kVmConfigHash[] =
    "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
const char kBadHash[] =
    "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210";

class MockObserver : public BruschettaInstaller::Observer {
 public:
  MOCK_METHOD(void,
              StateChanged,
              (BruschettaInstaller::State state),
              (override));
  MOCK_METHOD(void, Error, (BruschettaInstallResult), (override));
};

class StubDownload : public BruschettaDownload {
 public:
  StubDownload(base::FilePath path, std::string hash)
      : path_(std::move(path)), hash_(std::move(hash)) {}
  ~StubDownload() override = default;
  void StartDownload(
      Profile* profile,
      GURL url,
      base::OnceCallback<void(base::FilePath, std::string)> callback) override {
    std::move(callback).Run(path_, hash_);
  }
  base::FilePath path_;
  std::string hash_;
};

class BruschettaInstallerTest : public testing::TestWithParam<int>,
                                protected guest_os::FakeVmServicesHelper {
 public:
  BruschettaInstallerTest() = default;
  BruschettaInstallerTest(const BruschettaInstallerTest&) = delete;
  BruschettaInstallerTest& operator=(const BruschettaInstallerTest&) = delete;
  ~BruschettaInstallerTest() override = default;

 protected:
  void BuildPrefValues() {
    base::Value::Dict vtpm;
    vtpm.Set(prefs::kPolicyVTPMEnabledKey, true);
    vtpm.Set(prefs::kPolicyVTPMUpdateActionKey,
             static_cast<int>(
                 prefs::PolicyUpdateAction::FORCE_SHUTDOWN_IF_MORE_RESTRICTED));
    base::Value::Dict image;
    image.Set(prefs::kPolicyURLKey, kVmConfigUrl);
    image.Set(prefs::kPolicyHashKey, kVmConfigHash);
    base::Value::List oem_strings;
    oem_strings.Append("OEM string");

    base::Value::Dict config;

    config.Set(prefs::kPolicyEnabledKey,
               static_cast<int>(prefs::PolicyEnabledState::RUN_ALLOWED));
    config.Set(prefs::kPolicyNameKey, kVmConfigName);
    config.Set(prefs::kPolicyVTPMKey, vtpm.Clone());
    config.Set(prefs::kPolicyOEMStringsKey, oem_strings.Clone());
    prefs_not_installable_.Set(kVmConfigId, config.Clone());

    config.Set(prefs::kPolicyEnabledKey,
               static_cast<int>(prefs::PolicyEnabledState::INSTALL_ALLOWED));
    config.Set(prefs::kPolicyImageKey, image.Clone());
    prefs_installable_no_pflash_.Set(kVmConfigId, config.Clone());

    config.Set(prefs::kPolicyPflashKey, image.Clone());
    prefs_installable_.Set(kVmConfigId, config.Clone());
  }

  void SetUp() override {
    ash::AttestationClient::InitializeFake();

    BuildPrefValues();

    ASSERT_TRUE(base::CreateDirectory(
        profile_.GetPath().Append("MyFiles").Append("Downloads")));

    ash::disks::DiskMountManager::InitializeForTesting(&*disk_mount_manager_);

    installer_ = std::make_unique<BruschettaInstallerImpl>(
        &profile_, base::BindOnce(&BruschettaInstallerTest::CloseCallback,
                                  base::Unretained(this)));

    installer_->AddObserver(&observer_);
    ConfigureDownloadFactory(base::FilePath(), "");
  }

  // Configures the Bruschetta installer to use a fake downloader which
  // immediately completes returning |path| and |hash|.
  void ConfigureDownloadFactory(base::FilePath path, std::string hash) {
    installer_->SetDownloadFactoryForTesting(base::BindLambdaForTesting(
        [path = std::move(path), hash = std::move(hash)]() {
          std::unique_ptr<BruschettaDownload> d =
              std::make_unique<StubDownload>(std::move(path), std::move(hash));
          return d;
        }));
  }

  void TearDown() override {
    CheckVmRegistration();
    ash::disks::DiskMountManager::Shutdown();
    ash::AttestationClient::Shutdown();
  }

  void CheckVmRegistration() {
    const auto& running_vms =
        BruschettaService::GetForProfile(&profile_)->GetRunningVmsForTesting();
    if (expect_vm_registered_) {
      auto it = running_vms.find(kVmName);
      EXPECT_NE(it, running_vms.end());
      EXPECT_TRUE(it->second.vtpm_enabled);
    } else {
      EXPECT_FALSE(running_vms.contains(kVmName));
    }
  }

  // All these methods return anonymous lambdas because gmock doesn't accept
  // base::OnceCallbacks as callable objects in expectations.
  auto CancelCallback() {
    return [this]() { installer_->Cancel(); };
  }

  auto StopCallback() {
    return [this]() { run_loop_.Quit(); };
  }

  auto PrefsCallback(const base::Value::Dict& value) {
    return [this, &value]() {
      profile_.GetPrefs()->SetDict(prefs::kBruschettaVMConfiguration,
                                   value.Clone());
    };
  }

  auto DlcCallback(std::string error) {
    return
        [this, error]() { FakeDlcserviceClient()->set_install_error(error); };
  }

  auto DownloadErrorCallback(bool fail_at_start) {
    return [this]() { ConfigureDownloadFactory(base::FilePath(), ""); };
  }

  auto DownloadBadHashCallback() {
    return [this]() {
      base::FilePath path;
      base::CreateTemporaryFile(&path);
      ConfigureDownloadFactory(path, kBadHash);
    };
  }

  auto DownloadSuccessCallback() {
    return [this]() {
      base::FilePath path;
      base::CreateTemporaryFile(&path);
      ConfigureDownloadFactory(path, kVmConfigHash);
    };
  }

  auto DiskImageCallback(
      std::optional<vm_tools::concierge::DiskImageStatus> value) {
    return [this, value]() {
      if (value.has_value()) {
        vm_tools::concierge::CreateDiskImageResponse response;
        response.set_status(*value);
        FakeConciergeClient()->set_create_disk_image_response(
            std::move(response));
      } else {
        FakeConciergeClient()->set_create_disk_image_response(std::nullopt);
      }
    };
  }

  auto InstallPflashCallback(std::optional<bool> success) {
    return [this, success]() {
      if (success.has_value()) {
        vm_tools::concierge::InstallPflashResponse response;
        response.set_success(*success);
        FakeConciergeClient()->set_install_pflash_response(std::move(response));
      } else {
        FakeConciergeClient()->set_install_pflash_response(std::nullopt);
      }
    };
  }

  auto ClearVekCallback(bool success) {
    return [success]() {
      ash::AttestationClient::Get()->GetTestInterface()->set_delete_keys_status(
          success ? attestation::STATUS_SUCCESS
                  : attestation::STATUS_INVALID_PARAMETER);
    };
  }

  auto StartVmCallback(std::optional<bool> success) {
    return [this, success]() {
      if (success.has_value()) {
        vm_tools::concierge::StartVmResponse response;
        response.set_success(*success);
        FakeConciergeClient()->set_start_vm_response(std::move(response));
        this->expect_vm_registered_ = *success;
      } else {
        FakeConciergeClient()->set_start_vm_response(std::nullopt);
      }
    };
  }

  void ErrorExpectation(Sequence seq) {
    EXPECT_CALL(observer_, Error)
        .Times(1)
        .InSequence(seq)
        .WillOnce(StopCallback());
  }

  template <typename T, typename F>
  void MakeErrorPoint(T& expectation, Sequence seq, F callback) {
    expectation.WillOnce(InvokeWithoutArgs(callback));
    ErrorExpectation(seq);
  }

  template <typename T, typename F, typename G>
  void MakeErrorPoint(T& expectation, Sequence seq, F callback1, G callback2) {
    expectation.WillOnce(
        DoAll(InvokeWithoutArgs(callback1), InvokeWithoutArgs(callback2)));
    ErrorExpectation(seq);
  }

  // Generate expectations and actions for a test that runs the install and
  // stops at the nth point where stopping is possible, returning true if the
  // stop is due to an error and false if the stop is a cancel. Passing in
  // kMaxSteps means letting the install run to completion. If out_result is
  // passed in, will set it to the expected result (as reported to the observer
  // + metrics).
  //
  // Takes an optional Sequence to order these expectations before/after other
  // things.
  bool ExpectStopOnStepN(int n,
                         Sequence seq = {},
                         BruschettaInstallResult* out_result = nullptr,
                         bool use_pflash = true) {
    // Policy check step
    {
      if (out_result) {
        *out_result = BruschettaInstallResult::kInstallationProhibited;
      }
      auto& expectation =
          EXPECT_CALL(observer_,
                      StateChanged(BruschettaInstaller::State::kInstallStarted))
              .Times(1)
              .InSequence(seq);
      if (!n--) {
        MakeErrorPoint(expectation, seq, PrefsCallback(prefs_not_installable_));
        return true;
      }

      if (use_pflash) {
        expectation.WillOnce(
            InvokeWithoutArgs(PrefsCallback(prefs_installable_)));
      } else {
        expectation.WillOnce(
            InvokeWithoutArgs(PrefsCallback(prefs_installable_no_pflash_)));
      }
    }

    // Tools DLC install step
    {
      if (out_result) {
        *out_result = BruschettaInstallResult::kToolsDlcUnknownError;
      }
      auto& expectation =
          EXPECT_CALL(
              observer_,
              StateChanged(BruschettaInstaller::State::kToolsDlcInstall))
              .Times(1)
              .InSequence(seq);

      if (!n--) {
        expectation.WillOnce(CancelCallback());
        return false;
      }
      if (!n--) {
        MakeErrorPoint(expectation, seq, DlcCallback("Install Error"));
        return true;
      }

      expectation.WillOnce(
          InvokeWithoutArgs(DlcCallback(dlcservice::kErrorNone)));
    }

    // UEFI DLC install step
    {
      if (out_result) {
        *out_result = BruschettaInstallResult::kFirmwareDlcUnknownError;
      }
      auto& expectation =
          EXPECT_CALL(
              observer_,
              StateChanged(BruschettaInstaller::State::kFirmwareDlcInstall))
              .Times(1)
              .InSequence(seq);

      if (!n--) {
        expectation.WillOnce(CancelCallback());
        return false;
      }
      if (!n--) {
        MakeErrorPoint(expectation, seq, DlcCallback("Install Error"));
        return true;
      }

      expectation.WillOnce(
          InvokeWithoutArgs(DlcCallback(dlcservice::kErrorNone)));
    }

    // Boot disk download step
    {
      if (out_result) {
        *out_result = BruschettaInstallResult::kDownloadError;
      }
      auto& expectation =
          EXPECT_CALL(
              observer_,
              StateChanged(BruschettaInstaller::State::kBootDiskDownload))
              .Times(1)
              .InSequence(seq);

      if (!n--) {
        expectation.WillOnce(CancelCallback());
        return false;
      }
      if (!n--) {
        MakeErrorPoint(expectation, seq, DownloadErrorCallback(true));
        return true;
      }
      if (!n--) {
        MakeErrorPoint(expectation, seq, DownloadErrorCallback(false));
        return true;
      }
      if (out_result) {
        *out_result = BruschettaInstallResult::kInvalidBootDisk;
      }
      if (!n--) {
        MakeErrorPoint(expectation, seq, DownloadBadHashCallback());
        return true;
      }

      expectation.WillOnce(InvokeWithoutArgs(DownloadSuccessCallback()));
    }

    // pflash download step
    {
      if (out_result) {
        *out_result = BruschettaInstallResult::kDownloadError;
      }
      auto& expectation =
          EXPECT_CALL(observer_,
                      StateChanged(BruschettaInstaller::State::kPflashDownload))
              .Times(1)
              .InSequence(seq);

      if (use_pflash) {
        if (!n--) {
          expectation.WillOnce(CancelCallback());
          return false;
        }
        if (!n--) {
          MakeErrorPoint(expectation, seq, DownloadErrorCallback(true));
          return true;
        }
        if (!n--) {
          MakeErrorPoint(expectation, seq, DownloadErrorCallback(false));
          return true;
        }
        if (out_result) {
          *out_result = BruschettaInstallResult::kInvalidPflash;
        }
        if (!n--) {
          MakeErrorPoint(expectation, seq, DownloadBadHashCallback());
          return true;
        }

        expectation.WillOnce(InvokeWithoutArgs(DownloadSuccessCallback()));
      }
    }

    // Open files step
    {
      if (out_result) {
        *out_result = BruschettaInstallResult::kUnableToOpenImages;
      }
      auto& expectation =
          EXPECT_CALL(observer_,
                      StateChanged(BruschettaInstaller::State::kOpenFiles))
              .Times(1)
              .InSequence(seq);

      if (!n--) {
        expectation.WillOnce(CancelCallback());
        return false;
      }
    }

    // Create VM disk step
    {
      if (out_result) {
        *out_result = BruschettaInstallResult::kCreateDiskError;
      }
      auto& expectation =
          EXPECT_CALL(observer_,
                      StateChanged(BruschettaInstaller::State::kCreateVmDisk))
              .Times(1)
              .InSequence(seq);

      if (!n--) {
        expectation.WillOnce(CancelCallback());
        return false;
      }
      if (!n--) {
        MakeErrorPoint(expectation, seq, DiskImageCallback(std::nullopt));
        return true;
      }
      if (!n--) {
        MakeErrorPoint(
            expectation, seq,
            DiskImageCallback(
                vm_tools::concierge::DiskImageStatus::DISK_STATUS_FAILED));
        return true;
      }

      expectation.WillOnce(InvokeWithoutArgs(DiskImageCallback(
          vm_tools::concierge::DiskImageStatus::DISK_STATUS_CREATED)));
    }

    // Install pflash file step
    {
      if (out_result) {
        *out_result = BruschettaInstallResult::kInstallPflashError;
      }
      auto& expectation =
          EXPECT_CALL(observer_,
                      StateChanged(BruschettaInstaller::State::kInstallPflash))
              .Times(1)
              .InSequence(seq);

      if (use_pflash) {
        if (!n--) {
          expectation.WillOnce(CancelCallback());
          return false;
        }
        if (!n--) {
          MakeErrorPoint(expectation, seq, InstallPflashCallback(std::nullopt));
          return true;
        }
        if (!n--) {
          MakeErrorPoint(expectation, seq, InstallPflashCallback(false));
          return true;
        }

        expectation.WillOnce(InvokeWithoutArgs(InstallPflashCallback(true)));
      }
    }

    // Clear vEK step
    {
      if (out_result) {
        *out_result = BruschettaInstallResult::kClearVekFailed;
      }
      auto& expectation =
          EXPECT_CALL(observer_,
                      StateChanged(BruschettaInstaller::State::kClearVek))
              .Times(1)
              .InSequence(seq);

      if (!n--) {
        expectation.WillOnce(CancelCallback());
        return false;
      }
      if (!n--) {
        MakeErrorPoint(expectation, seq, ClearVekCallback(false));
        return true;
      }

      expectation.WillOnce(InvokeWithoutArgs(ClearVekCallback(true)));
    }

    // Start VM step
    {
      if (out_result) {
        *out_result = BruschettaInstallResult::kInstallationProhibited;
      }
      auto& expectation =
          EXPECT_CALL(observer_,
                      StateChanged(BruschettaInstaller::State::kStartVm))
              .Times(1)
              .InSequence(seq);

      if (!n--) {
        expectation.WillOnce(CancelCallback());
        return false;
      }
      if (!n--) {
        MakeErrorPoint(expectation, seq, PrefsCallback(prefs_not_installable_));
        return true;
      }
      if (out_result) {
        *out_result = BruschettaInstallResult::kStartVmFailed;
      }
      if (!n--) {
        MakeErrorPoint(expectation, seq, StartVmCallback(std::nullopt));
        return true;
      }
      if (!n--) {
        MakeErrorPoint(expectation, seq, StartVmCallback(false));
        return true;
      }

      expectation.WillOnce(InvokeWithoutArgs(StartVmCallback(true)));
    }

    // Open terminal step
    EXPECT_CALL(observer_,
                StateChanged(BruschettaInstaller::State::kLaunchTerminal))
        .Times(1)
        .InSequence(seq);
    // Dialog closes after this without further action from us

    // Make sure all input steps other then kMaxSteps got handled earlier.
    if (n != 0) {
      ADD_FAILURE() << "Steps input is too high, try setting kMaxSteps to "
                    << kMaxSteps - n;
    }

    // Like a cancellation, finishing the install closes the installer.
    return false;
  }

  content::BrowserTaskEnvironment task_environment_{
      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
  base::RunLoop run_loop_, run_loop_2_;

  base::Value::Dict prefs_installable_no_pflash_, prefs_installable_,
      prefs_not_installable_;

  TestingProfile profile_;
  std::unique_ptr<BruschettaInstallerImpl> installer_;

  MockObserver observer_;
  // Pointer owned by DiskMountManager
  const raw_ref<ash::disks::MockDiskMountManager, DanglingUntriaged>
      disk_mount_manager_{*new ash::disks::MockDiskMountManager};

  bool destroy_installer_on_completion_ = true;
  base::HistogramTester histogram_tester_;

  bool expect_vm_registered_ = false;

 private:
  // Called when the installer exists, suitable for base::BindOnce.
  void CloseCallback() {
    if (destroy_installer_on_completion_) {
      // Delete the installer object after it requests closure so we can tell if
      // it does anything afterwards that assumes it hasn't been deleted yet.
      installer_.reset();
    }
    run_loop_.Quit();
    run_loop_2_.Quit();
  }
};

TEST_F(BruschettaInstallerTest, CloseOnPrompt) {
  installer_->Cancel();
  run_loop_.Run();

  EXPECT_FALSE(installer_);
}

TEST_F(BruschettaInstallerTest, InstallSuccess) {
  ExpectStopOnStepN(kMaxSteps);

  installer_->Install(kVmName, kVmConfigId);
  run_loop_.Run();

  histogram_tester_.ExpectBucketCount(kInstallResultMetric,
                                      BruschettaInstallResult::kSuccess, 1);
  EXPECT_FALSE(installer_);
}

TEST_F(BruschettaInstallerTest, InstallSuccessNoPflash) {
  ExpectStopOnStepN(kMaxStepsNoPflash, {}, nullptr, false);

  installer_->Install(kVmName, kVmConfigId);
  run_loop_.Run();

  histogram_tester_.ExpectBucketCount(kInstallResultMetric,
                                      BruschettaInstallResult::kSuccess, 1);
  EXPECT_FALSE(installer_);
}

TEST_F(BruschettaInstallerTest, TwoInstalls) {
  ExpectStopOnStepN(kMaxSteps);

  installer_->Install(kVmName, kVmConfigId);
  installer_->Install(kVmName, kVmConfigId);
  run_loop_.Run();

  EXPECT_FALSE(installer_);
}

TEST_F(BruschettaInstallerTest, MultipleCancelsNoOp) {
  destroy_installer_on_completion_ = false;
  // Should be safe to call cancel multiple times.
  installer_->Cancel();
  installer_->Cancel();
  run_loop_.Run();
  installer_->Cancel();
  installer_->Cancel();
  run_loop_2_.Run();
}

TEST_P(BruschettaInstallerTest, StopDuringInstall) {
  BruschettaInstallResult expected_result;
  bool is_error = ExpectStopOnStepN(GetParam(), {}, &expected_result);

  installer_->Install(kVmName, kVmConfigId);
  run_loop_.Run();

  if (is_error) {
    // Installer should remain open in error state, tell it to close.
    EXPECT_TRUE(installer_);
    installer_->Cancel();
    run_loop_2_.Run();

    histogram_tester_.ExpectBucketCount(kInstallResultMetric, expected_result,
                                        1);
  }
  EXPECT_FALSE(installer_);
}

TEST_P(BruschettaInstallerTest, StopDuringInstallNoPflash) {
  if (GetParam() > kMaxStepsNoPflash) {
    GTEST_SKIP();
  }

  BruschettaInstallResult expected_result;
  bool is_error = ExpectStopOnStepN(GetParam(), {}, &expected_result, false);

  installer_->Install(kVmName, kVmConfigId);
  run_loop_.Run();

  if (is_error) {
    // Installer should remain open in error state, tell it to close.
    EXPECT_TRUE(installer_);
    installer_->Cancel();
    run_loop_2_.Run();

    histogram_tester_.ExpectBucketCount(kInstallResultMetric, expected_result,
                                        1);
  }
  EXPECT_FALSE(installer_);
}

TEST_P(BruschettaInstallerTest, ErrorAndRetry) {
  Sequence seq;

  bool is_error = ExpectStopOnStepN(GetParam(), seq);
  if (is_error) {
    ExpectStopOnStepN(kMaxSteps, seq);
  }

  installer_->Install(kVmName, kVmConfigId);
  run_loop_.Run();

  if (!is_error) {
    return;
  }

  // Installer should remain open in error state, retry the install.
  EXPECT_TRUE(installer_);

  installer_->Install(kVmName, kVmConfigId);
  run_loop_2_.Run();

  EXPECT_FALSE(installer_);
}

INSTANTIATE_TEST_SUITE_P(All,
                         BruschettaInstallerTest,
                         testing::Range(0, kMaxSteps));

TEST_F(BruschettaInstallerTest, AllStepsTested) {
  // Meta-test to check that kMaxSteps is set correctly.

  // We generate a lot of gmock expectations just to ignore them, and taking
  // stack traces for all of them is really slow, so disable stack traces for
  // this test.
  GTEST_FLAG_SET(stack_trace_depth, 0);

  std::optional<int> new_max_steps;

  for (int i = 0; i < 1000; i++) {
    testing::TestPartResultArray failures;
    testing::ScopedFakeTestPartResultReporter test_reporter{
        testing::ScopedFakeTestPartResultReporter::
            INTERCEPT_ONLY_CURRENT_THREAD,
        &failures};

    ExpectStopOnStepN(i);

    if (failures.size() > 0) {
      new_max_steps = i - 1;
      break;
    }
  }
  if (new_max_steps.has_value()) {
    if (*new_max_steps != kMaxSteps) {
      ADD_FAILURE() << "kMaxSteps needs to be updated. Try setting it to "
                    << *new_max_steps;
    }
  } else {
    ADD_FAILURE() << "Was unable to find the correct value for kMaxSteps";
  }

  // Force the expectations we just set to be checked here so we can ignore all
  // the failures.
  {
    testing::TestPartResultArray failures;
    testing::ScopedFakeTestPartResultReporter test_reporter{
        testing::ScopedFakeTestPartResultReporter::
            INTERCEPT_ONLY_CURRENT_THREAD,
        &failures};

    testing::Mock::VerifyAndClearExpectations(&observer_);
    testing::Mock::VerifyAndClearExpectations(&*disk_mount_manager_);
  }
}

}  // namespace

}  // namespace bruschetta