chromium/chrome/updater/test/integration_tests_impl.cc

// Copyright 2021 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/updater/test/integration_tests_impl.h"

#include <cstdint>
#include <cstdlib>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/notreached.h"
#include "base/numerics/checked_math.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/process/process.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/test/bind.h"
#include "base/test/test_timeouts.h"
#include "base/time/time.h"
#include "base/values.h"
#include "base/version.h"
#include "build/build_config.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/enterprise_companion/device_management_storage/dm_storage.h"
#include "chrome/updater/activity.h"
#include "chrome/updater/constants.h"
#include "chrome/updater/device_management/dm_policy_builder_for_testing.h"
#include "chrome/updater/external_constants_builder.h"
#include "chrome/updater/external_constants_override.h"
#include "chrome/updater/persisted_data.h"
#include "chrome/updater/prefs.h"
#include "chrome/updater/protos/omaha_settings.pb.h"
#include "chrome/updater/registration_data.h"
#include "chrome/updater/service_proxy_factory.h"
#include "chrome/updater/test/request_matcher.h"
#include "chrome/updater/test/server.h"
#include "chrome/updater/test/test_scope.h"
#include "chrome/updater/test/unit_test_util.h"
#include "chrome/updater/update_service.h"
#include "chrome/updater/updater_branding.h"
#include "chrome/updater/updater_scope.h"
#include "chrome/updater/updater_version.h"
#include "chrome/updater/util/util.h"
#include "components/policy/proto/device_management_backend.pb.h"
#include "crypto/secure_hash.h"
#include "crypto/sha2.h"
#include "net/http/http_status_code.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/re2/src/re2/re2.h"
#include "url/gurl.h"

#if BUILDFLAG(IS_WIN)
#include "base/file_version_info_win.h"
#include "base/win/registry.h"
#include "chrome/updater/util/win_util.h"
#include "chrome/updater/win/test/test_executables.h"
#include "chrome/updater/win/win_constants.h"
#elif BUILDFLAG(IS_LINUX)
#include "chrome/updater/util/linux_util.h"
#include "chrome/updater/util/posix_util.h"
#endif

namespace updater::test {
namespace {

constexpr char kSelfUpdateCRXName[] =;
#if BUILDFLAG(IS_MAC)
constexpr char kSelfUpdateCRXRun[] = PRODUCT_FULLNAME_STRING "_test.app";
constexpr char kDoNothingCRXName[] = "updater_qualification_app_dmg.crx";
constexpr char kDoNothingCRXRun[] = "updater_qualification_app_dmg.dmg";
#elif BUILDFLAG(IS_WIN)
constexpr char kSelfUpdateCRXRun[] = "UpdaterSetup_test.exe";
constexpr char kDoNothingCRXName[] = "updater_qualification_app_exe.crx";
constexpr char kDoNothingCRXRun[] = "qualification_app.exe";
#elif BUILDFLAG(IS_LINUX)
constexpr char kSelfUpdateCRXRun[] =;
constexpr char kDoNothingCRXName[] =;
constexpr char kDoNothingCRXRun[] =;
#endif

std::string GetHashHex(const base::FilePath& file) {}

std::string GetUpdateResponseForApp(
    const std::string& app_id,
    const std::string& install_data_index,
    const std::string& codebase,
    const base::Version& version,
    const base::FilePath& update_file,
    const std::string& run_action,
    const std::string& arguments,
    const std::optional<std::string>& file_hash = std::nullopt,
    const std::optional<std::string>& status = std::nullopt) {}

std::string GetUpdateResponse(const std::vector<std::string>& app_responses) {}

std::string GetUpdateResponse(const std::string& app_id,
                              const std::string& install_data_index,
                              const std::string& codebase,
                              const base::Version& version,
                              const base::FilePath& update_file,
                              const std::string& run_action,
                              const std::string& arguments,
                              const std::string& file_hash) {}

std::string GetUpdateResponse(const std::string& app_id,
                              const std::string& install_data_index,
                              const std::string& codebase,
                              const base::Version& version,
                              const base::FilePath& update_file,
                              const std::string& run_action,
                              const std::string& arguments) {}

void RunUpdaterWithSwitches(const base::Version& version,
                            UpdaterScope scope,
                            const std::vector<std::string>& switches,
                            std::optional<int> expected_exit_code) {}

void ExpectUpdateCheckSequence(UpdaterScope scope,
                               ScopedServer* test_server,
                               const std::string& app_id,
                               UpdateService::Priority priority,
                               int event_type,
                               const base::Version& from_version,
                               const base::Version& to_version) {}

void ExpectUpdateSequence(UpdaterScope scope,
                          ScopedServer* test_server,
                          const std::string& app_id,
                          const std::string& install_data_index,
                          UpdateService::Priority priority,
                          int event_type,
                          const base::Version& from_version,
                          const base::Version& to_version,
                          bool do_fault_injection) {}

void ExpectDeviceManagementRequest(ScopedServer* test_server,
                                   const std::string& request_type,
                                   const std::string& authorization_type,
                                   const std::string& authorization_token,
                                   net::HttpStatusCode response_status,
                                   const std::string& response,
                                   std::optional<GURL> target_url = {}

}  // namespace

AppUpdateExpectation::AppUpdateExpectation(
    const std::string& args,
    const std::string& app_id,
    const base::Version& from_version,
    const base::Version& to_version,
    bool is_install,
    bool should_update,
    bool allow_rollback,
    const std::string& target_version_prefix,
    const std::string& target_channel,
    const base::FilePath& crx_relative_path,
    bool always_serve_crx,
    const UpdateService::ErrorCategory error_category,
    const int error_code,
    const int event_type,
    const std::string& custom_app_response,
    const std::string& response_status)
    :{}
AppUpdateExpectation::AppUpdateExpectation(const AppUpdateExpectation&) =
    default;
AppUpdateExpectation::~AppUpdateExpectation() = default;

void ExitTestMode(UpdaterScope scope) {}

int CountDirectoryFiles(const base::FilePath& dir) {}

void RegisterApp(UpdaterScope scope, const RegistrationRequest& registration) {}

void RegisterAppByValue(UpdaterScope scope, const base::Value::Dict& value) {}

void SetGroupPolicies(const base::Value::Dict& values) {}

void SetMachineManaged(bool is_managed_device) {}

void ExpectVersionActive(UpdaterScope scope, const std::string& version) {}

void ExpectVersionNotActive(UpdaterScope scope, const std::string& version) {}

void Install(UpdaterScope scope, const base::Value::List& switches) {}

void InstallUpdaterAndApp(UpdaterScope scope,
                          const std::string& app_id,
                          const bool is_silent_install,
                          const std::string& tag,
                          const std::string& child_window_text_to_find,
                          const bool always_launch_cmd,
                          const bool verify_app_logo_loaded,
                          const bool expect_success,
                          const bool wait_for_the_installer) {}

void PrintFile(const base::FilePath& file) {}

std::vector<base::FilePath> GetUpdaterLogFilesInTmp() {}

void PrintLog(UpdaterScope scope) {}

// Copies the updater log file present in `src_dir` or `%TMP%` to a
// test-specific directory name in Swarming/Isolate. Avoids overwriting the
// destination log file if other instances of it exist in the destination
// directory. Swarming retries each failed test. It is useful to capture a few
// logs from previous failures instead of the log of the last run only. Logs
// labeled with different (optional) infixes are numbered independently. The
// infix is applied only to the output log file name; the retrieved log is
// always `updater.log`.
void CopyLog(const base::FilePath& src_dir, const std::string& infix) {}

void ExpectNoCrashes(UpdaterScope scope) {}

void ExpectAppsUpdateSequence(UpdaterScope scope,
                              ScopedServer* test_server,
                              const base::Value::Dict& request_attributes,
                              const std::vector<AppUpdateExpectation>& apps) {}

void RunWake(UpdaterScope scope, int expected_exit_code) {}

void RunWakeAll(UpdaterScope scope) {}

void RunWakeActive(UpdaterScope scope, int expected_exit_code) {}

void RunCrashMe(UpdaterScope scope) {}

void RunServer(UpdaterScope scope, int expected_exit_code, bool internal) {}

void CheckForUpdate(UpdaterScope scope, const std::string& app_id) {}

void Update(UpdaterScope scope,
            const std::string& app_id,
            const std::string& install_data_index) {}

void UpdateAll(UpdaterScope scope) {}

void InstallAppViaService(UpdaterScope scope,
                          const std::string& appid,
                          const base::Value::Dict& expected_final_values) {}

void GetAppStates(UpdaterScope updater_scope,
                  const base::Value::Dict& expected_app_states) {}

void DeleteUpdaterDirectory(UpdaterScope scope) {}

void DeleteActiveUpdaterExecutable(UpdaterScope scope) {}

void DeleteFile(UpdaterScope /*scope*/, const base::FilePath& path) {}

void SetupFakeUpdaterLowerVersion(UpdaterScope scope) {}

void SetupFakeUpdaterHigherVersion(UpdaterScope scope) {}

void SetExistenceCheckerPath(UpdaterScope scope,
                             const std::string& app_id,
                             const base::FilePath& path) {}

void SetServerStarts(UpdaterScope scope, int value) {}

void FillLog(UpdaterScope scope) {}

void ExpectLogRotated(UpdaterScope scope) {}

void ExpectRegistered(UpdaterScope scope, const std::string& app_id) {}

void ExpectNotRegistered(UpdaterScope scope, const std::string& app_id) {}

void ExpectAppTag(UpdaterScope scope,
                  const std::string& app_id,
                  const std::string& tag) {}

void SetAppTag(UpdaterScope scope,
               const std::string& app_id,
               const std::string& tag) {}

void Run(UpdaterScope scope, base::CommandLine command_line, int* exit_code) {}

void ExpectCliResult(base::CommandLine command_line,
                     bool elevate,
                     std::optional<std::string> want_stdout,
                     std::optional<int> want_exit_code) {}

void SetupRealUpdaterLowerVersion(UpdaterScope scope) {}

void ExpectPing(UpdaterScope scope,
                ScopedServer* test_server,
                int event_type,
                std::optional<GURL> target_url) {}

void ExpectAppCommandPing(UpdaterScope scope,
                          ScopedServer* test_server,
                          const std::string& appid,
                          const std::string& appcommandid,
                          int errorcode,
                          int eventresult,
                          int event_type,
                          const base::Version& version) {}

void ExpectSelfUpdateSequence(UpdaterScope scope, ScopedServer* test_server) {}

void ExpectUpdateCheckRequest(UpdaterScope scope, ScopedServer* test_server) {}

void ExpectUpdateCheckSequence(UpdaterScope scope,
                               ScopedServer* test_server,
                               const std::string& app_id,
                               UpdateService::Priority priority,
                               const base::Version& from_version,
                               const base::Version& to_version) {}

void ExpectUpdateSequence(UpdaterScope scope,
                          ScopedServer* test_server,
                          const std::string& app_id,
                          const std::string& install_data_index,
                          UpdateService::Priority priority,
                          const base::Version& from_version,
                          const base::Version& to_version,
                          bool do_fault_injection) {}

void ExpectUpdateSequenceBadHash(UpdaterScope scope,
                                 ScopedServer* test_server,
                                 const std::string& app_id,
                                 const std::string& install_data_index,
                                 UpdateService::Priority priority,
                                 const base::Version& from_version,
                                 const base::Version& to_version) {}

void ExpectInstallSequence(UpdaterScope scope,
                           ScopedServer* test_server,
                           const std::string& app_id,
                           const std::string& install_data_index,
                           UpdateService::Priority priority,
                           const base::Version& from_version,
                           const base::Version& to_version,
                           bool do_fault_injection) {}

// Runs multiple cycles of instantiating the update service, calling
// `GetVersion()`, then releasing the service interface.
void StressUpdateService(UpdaterScope scope) {}

void CallServiceUpdate(UpdaterScope updater_scope,
                       const std::string& app_id,
                       const std::string& install_data_index,
                       bool same_version_update_allowed) {}

void RunRecoveryComponent(UpdaterScope scope,
                          const std::string& app_id,
                          const base::Version& version) {}

void SetLastChecked(UpdaterScope updater_scope, const base::Time& time) {}

void ExpectLastChecked(UpdaterScope updater_scope) {}

void ExpectLastStarted(UpdaterScope updater_scope) {}

std::set<base::FilePath::StringType> GetTestProcessNames() {}

#if BUILDFLAG(IS_WIN)
VersionProcessFilter::VersionProcessFilter()
    : this_version_(base::Version(kUpdaterVersion)), older_version_([] {
        const std::unique_ptr<FileVersionInfoWin> version_info =
            FileVersionInfoWin::CreateFileVersionInfoWin(
                GetRealUpdaterLowerVersionPath());
        CHECK(version_info);
        const base::Version version(
            base::UTF16ToUTF8(version_info->file_version()));
        CHECK(version.IsValid());
        return version;
      }()) {}

bool VersionProcessFilter::Includes(const base::ProcessEntry& entry) const {
  const base::Process process(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,
                                            false, entry.th32ProcessID));
  if (!process.IsValid()) {
    return false;
  }

  DWORD path_len = MAX_PATH;
  std::wstring path(path_len, '\0');
  if (!::QueryFullProcessImageName(process.Handle(), 0, path.data(),
                                   &path_len)) {
    return false;
  }

  const std::unique_ptr<FileVersionInfoWin> version_info =
      FileVersionInfoWin::CreateFileVersionInfoWin(base::FilePath(path));
  if (!version_info) {
    return false;
  }
  const base::Version version(base::UTF16ToUTF8(version_info->file_version()));
  return version.IsValid() &&
         (version == this_version_ || version == older_version_);
}
#endif  // BUILDFLAG(IS_WIN)

void CleanProcesses() {}

void ExpectCleanProcesses() {}

// Standalone installers are supported for Windows only.
#if !BUILDFLAG(IS_WIN)
void RunOfflineInstall(UpdaterScope scope,
                       bool is_legacy_install,
                       bool is_silent_install) {}

void RunOfflineInstallOsNotSupported(UpdaterScope scope,
                                     bool is_legacy_install,
                                     bool is_silent_install) {}
#endif  // !BUILDFLAG(IS_WIN)

void DMPushEnrollmentToken(const std::string& enrollment_token) {}

void DMDeregisterDevice(UpdaterScope scope) {}

void DMCleanup(UpdaterScope scope) {}

void ExpectDeviceManagementRegistrationRequest(
    ScopedServer* test_server,
    const std::string& enrollment_token,
    const std::string& dm_token) {}

void ExpectDeviceManagementPolicyFetchRequest(
    ScopedServer* test_server,
    const std::string& dm_token,
    const ::wireless_android_enterprise_devicemanagement::
        OmahaSettingsClientProto& omaha_settings,
    bool first_request,
    bool rotate_public_key,
    std::optional<GURL> target_url) {}

void ExpectDeviceManagementPolicyFetchWithNewPublicKeyRequest(
    ScopedServer* test_server,
    const std::string& dm_token,
    const ::wireless_android_enterprise_devicemanagement::
        OmahaSettingsClientProto& omaha_settings) {}

void ExpectDeviceManagementTokenDeletionRequest(ScopedServer* test_server,
                                                const std::string& dm_token,
                                                bool invalidate_token) {}

void ExpectDeviceManagementPolicyValidationRequest(
    ScopedServer* test_server,
    const std::string& dm_token) {}

void ExpectProxyPacScriptRequest(ScopedServer* test_server) {}

}  // namespace updater::test