chromium/chrome/enterprise_companion/test/integration_tests_win.cc

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

#include <optional>
#include <string>

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/process/process.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/task_environment.h"
#include "base/win/registry.h"
#include "base/win/windows_types.h"
#include "chrome/enterprise_companion/enterprise_companion.h"
#include "chrome/enterprise_companion/enterprise_companion_branding.h"
#include "chrome/enterprise_companion/enterprise_companion_version.h"
#include "chrome/enterprise_companion/installer.h"
#include "chrome/enterprise_companion/installer_paths.h"
#include "chrome/enterprise_companion/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace enterprise_companion {

namespace {

// The filename of the companion app binary under test.
constexpr char kTestExe[] = "enterprise_companion_test.exe";

}  // namespace

class InstallerTest : public ::testing::Test {
 public:
  void SetUp() override {
    std::optional<base::FilePath> install_dir = GetInstallDirectory();
    ASSERT_TRUE(install_dir);
    install_dir_ = *install_dir;
    GetTestMethods().Clean();
  }

  void TearDown() override { GetTestMethods().Clean(); }

 protected:
  base::test::TaskEnvironment environment_;
  // The install directory for the current process architecture.
  base::FilePath install_dir_;
  // If 64-on-64, the 32-bit install directory. If 32-on-64 the 64-bit install
  // directory. Otherwise nullopt.
  std::optional<base::FilePath> alt_install_dir_;

  // Run the installer and expect success or failure.
  void RunInstaller(bool expect_success) {
    base::FilePath installer_pkg_path =
        base::PathService::CheckedGet(base::DIR_EXE).AppendASCII(kTestExe);
    ASSERT_TRUE(base::PathExists(installer_pkg_path));

    base::CommandLine command_line(installer_pkg_path);
    command_line.AppendSwitch(kInstallSwitch);

    base::Process installer_process = base::LaunchProcess(command_line, {});

    int exit_code = WaitForProcess(installer_process);
    if (expect_success) {
      EXPECT_EQ(exit_code, 0);
    } else {
      EXPECT_NE(exit_code, 0);
    }
  }

  void SetUpdaterRegistration(const std::wstring version,
                              const std::wstring name) {
    base::win::RegKey app_key(HKEY_LOCAL_MACHINE, kAppRegKey,
                              KEY_WRITE | KEY_WOW64_32KEY);

    ASSERT_EQ(app_key.WriteValue(kRegValuePV, version.c_str()), ERROR_SUCCESS);
    ASSERT_EQ(app_key.WriteValue(kRegValueName, name.c_str()), ERROR_SUCCESS);
  }

 private:
};

TEST_F(InstallerTest, FirstInstall) {
  RunInstaller(true);

  ASSERT_TRUE(base::PathExists(install_dir_.AppendASCII(kExecutableName)));
  ASSERT_FALSE(alt_install_dir_ && base::PathExists(*alt_install_dir_));

  ExpectUpdaterRegistration();
}

TEST_F(InstallerTest, OverinstallSameArch) {
  SetUpdaterRegistration(L"0.0.0.1", L"Prehistoric Enterprise Companion");
  ASSERT_TRUE(base::CreateDirectory(install_dir_));
  ASSERT_TRUE(base::WriteFile(install_dir_.AppendASCII(kExecutableName), ""));

  RunInstaller(true);

  ASSERT_TRUE(base::PathExists(install_dir_.AppendASCII(kExecutableName)));
  ASSERT_FALSE(alt_install_dir_ && base::PathExists(*alt_install_dir_));

  int64_t exe_size = 0;
  ASSERT_TRUE(
      base::GetFileSize(install_dir_.AppendASCII(kExecutableName), &exe_size));
  EXPECT_GT(exe_size, 0);

  ExpectUpdaterRegistration();
}

TEST_F(InstallerTest, OverinstallDifferentArch) {
  if (!alt_install_dir_) {
    LOG(WARNING) << "OverinstallDifferentArch not implemented for x86 hosts.";
    return;
  }

  SetUpdaterRegistration(L"0.0.0.1", L"Prehistoric Enterprise Companion");
  ASSERT_TRUE(base::CreateDirectory(*alt_install_dir_));
  ASSERT_TRUE(
      base::WriteFile(alt_install_dir_->AppendASCII(kExecutableName), ""));

  RunInstaller(true);

  ASSERT_TRUE(base::PathExists(install_dir_.AppendASCII(kExecutableName)));
  ASSERT_FALSE(alt_install_dir_ && base::PathExists(*alt_install_dir_));

  EXPECT_FALSE(base::PathExists(*alt_install_dir_));

  ExpectUpdaterRegistration();
}

}  // namespace enterprise_companion