// 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/updater/test/integration_tests_mac.h"

#include <cstdint>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "base/apple/bridging.h"
#include "base/apple/foundation_util.h"
#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/file_version_info.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/notreached.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/test_timeouts.h"
#include "base/time/time.h"
#include "base/version.h"
#include "build/build_config.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/updater/activity.h"
#include "chrome/updater/constants.h"
#include "chrome/updater/external_constants_builder.h"
#import "chrome/updater/mac/client_lib/CRURegistration-Private.h"
#import "chrome/updater/mac/client_lib/CRURegistration.h"
#include "chrome/updater/mac/privileged_helper/service.h"
#include "chrome/updater/persisted_data.h"
#include "chrome/updater/prefs.h"
#include "chrome/updater/registration_data.h"
#include "chrome/updater/test/integration_tests_impl.h"
#include "chrome/updater/test/unit_test_util.h"
#include "chrome/updater/updater_branding.h"
#include "chrome/updater/updater_scope.h"
#import "chrome/updater/util/mac_util.h"
#include "chrome/updater/util/posix_util.h"
#include "chrome/updater/util/util.h"
#include "components/crx_file/crx_verifier.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/cleanup/cleanup.h"
#include "url/gurl.h"

namespace updater::test {
namespace {

base::FilePath GetExecutablePath() {
  base::FilePath out_dir;
  if (!base::PathService::Get(base::DIR_EXE, &out_dir)) {
    return base::FilePath();
  }
  return out_dir.Append(GetExecutableRelativePath());
}

std::optional<base::FilePath> GetActiveFile(UpdaterScope /*scope*/,
                                            const std::string& id) {
  // The active user is always managed in the updater scope for the user.
  const std::optional<base::FilePath> path =
      GetLibraryFolderPath(UpdaterScope::kUser);
  if (!path) {
    return std::nullopt;
  }

  return path->Append(COMPANY_SHORTNAME_STRING)
      .Append(COMPANY_SHORTNAME_STRING "SoftwareUpdate")
      .Append("Actives")
      .Append(id);
}

}  // namespace

base::FilePath GetSetupExecutablePath() {
  // There is no metainstaller on mac, use the main executable for setup.
  return GetExecutablePath();
}

base::TimeDelta GetOverinstallTimeoutForEnterTestMode() {
  return base::Seconds(5);
}

void Clean(UpdaterScope scope) {
  CleanProcesses();

  std::optional<base::FilePath> path = GetInstallDirectory(scope);
  EXPECT_TRUE(path);
  if (path) {
    EXPECT_TRUE(base::DeletePathRecursively(*path));
  }
  EXPECT_TRUE(base::DeleteFile(*GetWakeTaskPlistPath(scope)));

  path = GetInstallDirectory(scope);
  EXPECT_TRUE(path);
  if (path) {
    EXPECT_TRUE(base::DeletePathRecursively(*path));
  }

  std::optional<base::FilePath> keystone_path = GetKeystoneFolderPath(scope);
  EXPECT_TRUE(keystone_path);
  if (keystone_path) {
    EXPECT_TRUE(base::DeletePathRecursively(*keystone_path));
  }

  // TODO(crbug.com/394302692): Delete after CIPD updater versions are M136+.
  EXPECT_TRUE(base::DeletePathRecursively(
      base::FilePath("/Library/Caches/").Append(MAC_BUNDLE_IDENTIFIER_STRING)));

  EXPECT_TRUE(RemoveWakeJobFromLaunchd(scope));

  // Also clean up any other versions of the updater that are around.
  base::CommandLine launchctl(base::FilePath("/bin/launchctl"));
  launchctl.AppendArg("list");
  std::string out;
  ASSERT_TRUE(base::GetAppOutput(launchctl, &out));
  for (const auto& token : base::SplitStringPiece(out, base::kWhitespaceASCII,
                                                  base::TRIM_WHITESPACE,
                                                  base::SPLIT_WANT_NONEMPTY)) {
    if (base::StartsWith(token, MAC_BUNDLE_IDENTIFIER_STRING)) {
      std::string out_rm;
      base::CommandLine launchctl_rm(base::FilePath("/bin/launchctl"));
      launchctl_rm.AppendArg("remove");
      launchctl_rm.AppendArg(token);
      ASSERT_TRUE(base::GetAppOutput(launchctl_rm, &out_rm));
    }
  }

  if (IsSystemInstall(scope)) {
    ASSERT_NO_FATAL_FAILURE(UninstallEnterpriseCompanionApp());
  }
}

void DeleteLegacyUpdater(UpdaterScope scope) {
  std::optional<base::FilePath> keystone = GetKeystoneFolderPath(scope);
  ASSERT_TRUE(keystone);
  ASSERT_TRUE(base::DeletePathRecursively(*keystone));
}

void ExpectClean(UpdaterScope scope) {
  ExpectCleanProcesses();

  // Files must not exist on the file system.
  EXPECT_FALSE(base::PathExists(*GetWakeTaskPlistPath(scope)));

  std::optional<base::FilePath> path = GetInstallDirectory(scope);
  EXPECT_TRUE(path);
  if (path && base::PathExists(*path)) {
    // If the path exists, then expect only the log and json files to be
    // present.
    int count = CountDirectoryFiles(*path);
    for (const auto& file_name : {"updater.log", "prefs.json"}) {
      if (base::PathExists(path->Append(file_name))) {
        count -= 1;
      }
    }
    EXPECT_EQ(count, 0) << base::JoinString(
        [](const base::FilePath& dir) {
          std::vector<base::FilePath::StringType> files;
          base::FileEnumerator(dir, false, base::FileEnumerator::FILES)
              .ForEach([&files](const base::FilePath& name) {
                files.push_back(name.value());
              });
          return files;
        }(*path),
        FILE_PATH_LITERAL(","));
  }
  // Keystone must not exist on the file system.
  std::optional<base::FilePath> keystone_path = GetKeystoneFolderPath(scope);
  EXPECT_TRUE(keystone_path);
  if (keystone_path) {
    EXPECT_FALSE(
        base::PathExists(keystone_path->Append(KEYSTONE_NAME ".bundle")));
  }
  ASSERT_NO_FATAL_FAILURE(ExpectEnterpriseCompanionAppNotInstalled());
}

void ExpectInstalled(UpdaterScope scope) {
  std::optional<base::FilePath> keystone_path = GetKeystoneFolderPath(scope);
  ASSERT_TRUE(keystone_path);

  // Files must exist on the file system.
  for (const auto& path :
       {GetInstallDirectory(scope), keystone_path, GetKSAdminPath(scope)}) {
    ASSERT_TRUE(path) << path;
    EXPECT_TRUE(base::PathExists(*path)) << path;
  }

  EXPECT_TRUE(base::PathExists(*GetWakeTaskPlistPath(scope)));
}

std::optional<base::FilePath> GetInstalledExecutablePath(UpdaterScope scope) {
  return GetUpdaterExecutablePath(scope);
}

void ExpectCandidateUninstalled(UpdaterScope scope) {
  std::optional<base::FilePath> versioned_folder_path =
      GetVersionedInstallDirectory(scope);
  ASSERT_TRUE(versioned_folder_path);
  EXPECT_FALSE(base::PathExists(*versioned_folder_path));
}

void Uninstall(UpdaterScope scope) {
  std::optional<base::FilePath> path = GetExecutablePath();
  ASSERT_TRUE(path);
  base::CommandLine command_line(*path);
  command_line.AppendSwitch(kUninstallSwitch);
  int exit_code = -1;
  Run(scope, command_line, &exit_code);
  ASSERT_EQ(exit_code, 0);
}

void SetActive(UpdaterScope scope, const std::string& app_id) {
  const std::optional<base::FilePath> path = GetActiveFile(scope, app_id);
  ASSERT_TRUE(path);
  VLOG(0) << "Actives file: " << *path;
  base::File::Error err = base::File::FILE_OK;
  EXPECT_TRUE(base::CreateDirectoryAndGetError(path->DirName(), &err))
      << "Error: " << err;
  EXPECT_TRUE(base::WriteFile(*path, ""));
}

void ExpectActive(UpdaterScope scope, const std::string& app_id) {
  const std::optional<base::FilePath> path = GetActiveFile(scope, app_id);
  ASSERT_TRUE(path);
  EXPECT_TRUE(base::PathExists(*path));
  EXPECT_TRUE(base::PathIsWritable(*path));
}

void ExpectNotActive(UpdaterScope scope, const std::string& app_id) {
  const std::optional<base::FilePath> path = GetActiveFile(scope, app_id);
  ASSERT_TRUE(path);
  EXPECT_FALSE(base::PathExists(*path));
  EXPECT_FALSE(base::PathIsWritable(*path));
}

bool WaitForUpdaterExit() {
  std::string last_found;
  return WaitFor(
      [&] {
        std::string ps_stdout;
        EXPECT_TRUE(
            base::GetAppOutput({"ps", "ax", "-o", "command"}, &ps_stdout));
        std::vector<std::string_view> commands = base::SplitStringPiece(
            ps_stdout, "\n", base::WhitespaceHandling::TRIM_WHITESPACE,
            base::SplitResult::SPLIT_WANT_NONEMPTY);
        for (const auto& command : commands) {
          // Skip command lines referencing the symbol files, other processes
          // can safely have those open (and often do on ASAN bots).
          if (command.find(GetExecutablePath().BaseName().AsUTF8Unsafe()) !=
                  std::string::npos &&
              command.find(".dSYM") == std::string::npos) {
            last_found = command;
            return false;
          }
        }
        return true;
      },
      [&] { VLOG(0) << "Still waiting for updater to exit: " << last_found; });
}

std::vector<TestUpdaterVersion> GetRealUpdaterLowerVersions(
    const std::string& arch_suffix) {
  base::FilePath exe_path;
  EXPECT_TRUE(base::PathService::Get(base::DIR_EXE, &exe_path));
  base::FilePath old_updater_path =
      exe_path.Append(FILE_PATH_LITERAL("old_updater"));

  std::string arch;
#if BUILDFLAG(CHROMIUM_BRANDING)
#if defined(ARCH_CPU_ARM64)
  arch = "chromium_mac_arm64";
#elif defined(ARCH_CPU_X86_64)
  arch = "chromium_mac_amd64";
#endif
#elif BUILDFLAG(GOOGLE_CHROME_BRANDING)
  arch = "chrome_mac_universal";
#endif

  old_updater_path = old_updater_path.Append(base::StrCat({arch, arch_suffix}));

#if BUILDFLAG(CHROMIUM_BRANDING) || BUILDFLAG(GOOGLE_CHROME_BRANDING)
  old_updater_path = old_updater_path.Append("cipd");
#endif

  const base::FilePath updater_setup_path =
      old_updater_path.Append(PRODUCT_FULLNAME_STRING "_test.app")
          .Append("Contents")
          .Append("MacOS")
          .Append(PRODUCT_FULLNAME_STRING "_test");
  return {{updater_setup_path,
           base::Version(base::UTF16ToUTF8(
               FileVersionInfo::CreateFileVersionInfo(updater_setup_path)
                   ->file_version()))}};
}

void SetupFakeLegacyUpdater(UpdaterScope scope) {
  base::FilePath updater_test_data_path;
  ASSERT_TRUE(
      base::PathService::Get(chrome::DIR_TEST_DATA, &updater_test_data_path));
  updater_test_data_path =
      updater_test_data_path.Append(FILE_PATH_LITERAL("updater"));

  base::FilePath keystone_path = GetKeystoneFolderPath(scope).value();
  base::FilePath keystone_ticket_store_path =
      keystone_path.Append(FILE_PATH_LITERAL("TicketStore"));
  ASSERT_TRUE(base::CreateDirectory(keystone_ticket_store_path));
  ASSERT_TRUE(base::CopyFile(
      updater_test_data_path.Append("Keystone.legacy.ticketstore"),
      keystone_ticket_store_path.Append("Keystone.ticketstore")));
  ASSERT_TRUE(
      base::CopyFile(updater_test_data_path.Append("CountingMetrics.plist"),
                     keystone_path.Append("CountingMetrics.plist")));
}

void ExpectLegacyUpdaterMigrated(UpdaterScope scope) {
  scoped_refptr<GlobalPrefs> global_prefs = CreateGlobalPrefs(scope);
  auto persisted_data = base::MakeRefCounted<PersistedData>(
      scope, global_prefs->GetPrefService(), nullptr);

  // Keystone should not be migrated.
  EXPECT_FALSE(
      persisted_data->GetProductVersion(LEGACY_GOOGLE_UPDATE_APPID).IsValid());

  // Uninstalled app should be migrated.
  EXPECT_TRUE(
      persisted_data->GetProductVersion("com.chromium.NonExistApp").IsValid());

  // App Kipple.
  const std::string kKippleApp = "com.chromium.kipple";
  EXPECT_EQ(persisted_data->GetProductVersion(kKippleApp),
            base::Version("1.2.3.4"));
  EXPECT_EQ(persisted_data->GetExistenceCheckerPath(kKippleApp),
            base::FilePath("/"));
  EXPECT_TRUE(persisted_data->GetAP(kKippleApp).empty());
  EXPECT_TRUE(persisted_data->GetBrandCode(kKippleApp).empty());
  EXPECT_TRUE(persisted_data->GetBrandPath(kKippleApp).empty());
  EXPECT_TRUE(persisted_data->GetFingerprint(kKippleApp).empty());
  EXPECT_EQ(persisted_data->GetDateLastActive(kKippleApp), -1);
  EXPECT_EQ(persisted_data->GetDateLastRollCall(kKippleApp), -1);

  // App PopularApp.
  const std::string kPopularApp = "com.chromium.PopularApp";
  EXPECT_EQ(persisted_data->GetProductVersion(kPopularApp),
            base::Version("101.100.1000.9999"));
  EXPECT_EQ(persisted_data->GetExistenceCheckerPath(kPopularApp),
            base::FilePath("/"));
  EXPECT_EQ(persisted_data->GetAP(kPopularApp), "GOOG");
  EXPECT_TRUE(persisted_data->GetBrandCode(kPopularApp).empty());
  EXPECT_EQ(persisted_data->GetBrandPath(kPopularApp), base::FilePath("/"));
  EXPECT_TRUE(persisted_data->GetFingerprint(kPopularApp).empty());
  EXPECT_EQ(persisted_data->GetDateLastActive(kPopularApp), 5921);
  EXPECT_EQ(persisted_data->GetDateLastRollCall(kPopularApp), 5922);

  EXPECT_EQ(persisted_data->GetCohort(kPopularApp), "TestCohort");
  EXPECT_EQ(persisted_data->GetCohortName(kPopularApp), "TestCohortName");
  EXPECT_EQ(persisted_data->GetCohortHint(kPopularApp), "TestCohortHint");

  // App CorruptedApp (client-regulated counting data is corrupted).
  const std::string kCorruptedApp = "com.chromium.CorruptedApp";
  EXPECT_EQ(persisted_data->GetProductVersion(kCorruptedApp),
            base::Version("1.2.1"));
  EXPECT_EQ(persisted_data->GetExistenceCheckerPath(kCorruptedApp),
            base::FilePath("/"));
  EXPECT_EQ(persisted_data->GetAP(kCorruptedApp), "canary");
  EXPECT_EQ(persisted_data->GetDateLastActive(kCorruptedApp), -1);
  EXPECT_EQ(persisted_data->GetDateLastRollCall(kCorruptedApp), -1);
}

void InstallApp(UpdaterScope scope,
                const std::string& app_id,
                const base::Version& version) {
  RegistrationRequest registration;
  registration.app_id = app_id;
  registration.version = version;
  RegisterApp(scope, registration);
}

void UninstallApp(UpdaterScope scope, const std::string& app_id) {
  const base::FilePath& install_path =
      base::MakeRefCounted<PersistedData>(
          scope, CreateGlobalPrefs(scope)->GetPrefService(), nullptr)
          ->GetExistenceCheckerPath(app_id);
  VLOG(1) << "Deleting app install path: " << install_path;
  base::DeletePathRecursively(install_path);
  SetExistenceCheckerPath(scope, app_id,
                          base::FilePath(FILE_PATH_LITERAL("NONE")));
}

base::CommandLine MakeElevated(base::CommandLine command_line) {
  command_line.PrependWrapper("/usr/bin/sudo");
  return command_line;
}

void SetPlatformPolicies(const base::Value::Dict& values) {
  const CFStringRef domain = CFSTR(LEGACY_GOOGLE_UPDATE_APPID);

  // Synchronize just to be safe. Ignore spurious errors if the domain
  // does not yet exist.
  CFPreferencesSynchronize(domain, kCFPreferencesAnyUser,
                           kCFPreferencesCurrentHost);

  NSMutableDictionary* all_policies = [NSMutableDictionary dictionary];
  for (const auto [app_id, policies] : values) {
    ASSERT_TRUE(policies.is_dict());
    NSMutableDictionary* app_policies = [NSMutableDictionary dictionary];
    for (const auto [name, value] : policies.GetDict()) {
      NSString* key = base::SysUTF8ToNSString(name);
      if (value.is_string()) {
        app_policies[key] = base::SysUTF8ToNSString(value.GetString());
      } else if (value.is_int()) {
        app_policies[key] = [NSNumber numberWithInt:value.GetInt()];
      } else if (value.is_bool()) {
        app_policies[key] = [NSNumber numberWithInt:value.GetBool()];
      }
    }
    all_policies[base::SysUTF8ToNSString(app_id)] = app_policies;

    NSURL* const managed_preferences_url = base::apple::FilePathToNSURL(
        GetLibraryFolderPath(UpdaterScope::kSystem)
            ->Append("Managed Preferences")
            .Append(LEGACY_GOOGLE_UPDATE_APPID ".plist"));
    ASSERT_TRUE([[NSDictionary dictionaryWithObject:all_policies
                                             forKey:@"updatePolicies"]
        writeToURL:managed_preferences_url
             error:nil])
        << "Failed to write " << managed_preferences_url;
  }
  ASSERT_TRUE(CFPreferencesSynchronize(domain, kCFPreferencesAnyUser,
                                       kCFPreferencesCurrentHost));

  // Force flushing preferences cache by killing the defaults server.
  base::Process process = base::LaunchProcess({"killall", "cfprefsd"}, {});
  if (!process.IsValid()) {
    VLOG(2) << "Failed to launch the process to refresh preferences.";
  }
  // Exit code is not checked because it is not 0 when `cfprefsd` is not
  // found.
  EXPECT_TRUE(
      process.WaitForExitWithTimeout(TestTimeouts::action_timeout(), nullptr));
}

void PrivilegedHelperInstall(UpdaterScope scope) {
  ASSERT_EQ(scope, UpdaterScope::kSystem)
      << "The privileged helper only works at system scope.";
  base::FilePath src_dir;
  ASSERT_TRUE(base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &src_dir));
  base::ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  base::FilePath helpers_dir = temp_dir.GetPath().Append(
      "Contents/Frameworks/" BROWSER_PRODUCT_NAME_STRING
      " Framework.framework/Helpers/");
  ASSERT_TRUE(base::CreateDirectory(helpers_dir));
  ASSERT_TRUE(CopyDir(src_dir.Append("third_party")
                          .Append("updater")
                          .Append("chrome_mac_universal_prod")
                          .Append("cipd")
                          .Append(PRODUCT_FULLNAME_STRING ".app"),
                      helpers_dir, false));
  ASSERT_TRUE(
      base::WriteFile(temp_dir.GetPath().Append("Contents/Info.plist"),
                      R"(<?xml version="1.0" encoding="UTF-8"?>)"
                      R"(<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN")"
                      R"(    "http://www.apple.com/DTDs/PropertyList-1.0.dtd">)"
                      R"(<plist version="1.0">)"
                      R"(<dict>)"
                      R"(<key>KSProductID</key>)"
                      R"(<string>test1</string>)"
                      R"(<key>KSChannelID</key>)"
                      R"(<string>tag</string>)"
                      R"(<key>KSVersion</key>)"
                      R"(<string>1.2.3.4</string>)"
                      R"(</dict>)"
                      R"(</plist>)"));
  ASSERT_TRUE(VerifyUpdaterSignature(
      helpers_dir.Append(PRODUCT_FULLNAME_STRING ".app")));
  ASSERT_EQ(InstallUpdater(temp_dir.GetPath()), 0);
}

void ExpectAppVersion(UpdaterScope scope,
                      const std::string& app_id,
                      const base::Version& version) {
  const base::Version app_version =
      base::MakeRefCounted<PersistedData>(
          scope, CreateGlobalPrefs(scope)->GetPrefService(), nullptr)
          ->GetProductVersion(app_id);
  if (version.IsValid()) {
    EXPECT_TRUE(app_version.IsValid());
    EXPECT_EQ(version, app_version);
  } else {
    EXPECT_FALSE(app_version.IsValid());
  }
}

void ExpectPrepareToRunBundleSuccess(const base::FilePath& bundle_path) {
  EXPECT_TRUE(PrepareToRunBundle(bundle_path));
}

void ExpectKSAdminResult(UpdaterScope scope,
                         bool elevate,
                         const std::map<std::string, std::string>& switches,
                         std::optional<std::string> want_stdout,
                         std::optional<int> want_exit_code) {
  const std::optional<base::FilePath> ksadmin_path = GetKSAdminPath(scope);
  ASSERT_TRUE(ksadmin_path && !ksadmin_path->empty());
  ASSERT_TRUE(base::PathExists(*ksadmin_path));

  base::CommandLine command_line(*ksadmin_path);
  for (const auto& [key, value] : switches) {
    command_line.AppendSwitchUTF8(key, value);
  }

  ExpectCliResult(command_line, elevate, std::move(want_stdout),
                  want_exit_code);
}

void ExpectKSAdminFetchTag(UpdaterScope scope,
                           bool elevate,
                           const std::string& product_id,
                           const base::FilePath& xc_path,
                           std::optional<UpdaterScope> store_flag,
                           std::optional<std::string> want_tag) {
  std::map<std::string, std::string> switches;
  switches["--print-tag"] = "";
  switches["--productid"] = product_id;
  if (!xc_path.empty()) {
    switches["--xcpath"] = xc_path.value();
  }
  if (store_flag) {
    switch (*store_flag) {
      case UpdaterScope::kSystem:
        switches["--system-store"] = "";
        break;
      case UpdaterScope::kUser:
        switches["--user-store"] = "";
        break;
    }
  }

  int want_exit = EXIT_FAILURE;
  if (want_tag) {
    *want_tag = base::StrCat({*want_tag, "\n"});
    want_exit = EXIT_SUCCESS;
  }

  ExpectKSAdminResult(scope, elevate, switches, std::move(want_tag), want_exit);
}

void ExpectKSAdminXattrBrand(UpdaterScope scope,
                             bool elevate,
                             const base::FilePath& path,
                             std::optional<std::string> want_brand) {
  int want_exit = EXIT_FAILURE;
  if (want_brand) {
    *want_brand = base::StrCat({*want_brand, "\n"});
    want_exit = EXIT_SUCCESS;
  }
  ExpectKSAdminResult(scope, elevate,
                      {{"--print-xattr-tag-brand", path.value()}},
                      std::move(want_brand), want_exit);
}

void ExpectCRURegistrationCannotFindKSAdmin() {
  @autoreleasepool {
    CRURegistration* registration = [[CRURegistration alloc]
               initWithAppId:@"org.chromium.ChromiumUpdater.CannotFindKSAdmin"
        existenceCheckerPath:@"IGNORED during this test"];
    NSURL* got_ksadmin = [registration syncFindBestKSAdmin];
    EXPECT_FALSE(got_ksadmin)
        << "unexpectedly found ksadmin: "
        << base::SysNSStringToUTF8(got_ksadmin.absoluteString);
  }
}

void ExpectCRURegistrationFindsKSAdmin(UpdaterScope scope) {
  @autoreleasepool {
    CRURegistration* registration = [[CRURegistration alloc]
               initWithAppId:@"org.chromium.ChromiumUpdater.FindsKSAdmin"
        existenceCheckerPath:@"IGNORED during this test"];
    NSURL* got_ksadmin = [registration syncFindBestKSAdmin];
    EXPECT_TRUE(got_ksadmin);
    EXPECT_TRUE([got_ksadmin isFileURL]);
    base::FilePath got_ksadmin_path(base::apple::NSURLToFilePath(got_ksadmin));
    EXPECT_FALSE(got_ksadmin_path.empty());
    got_ksadmin_path = base::MakeAbsoluteFilePath(got_ksadmin_path);
    EXPECT_FALSE(got_ksadmin_path.empty());

    std::optional<base::FilePath> expected_ksadmin_path(GetKSAdminPath(scope));
    ASSERT_TRUE(expected_ksadmin_path);
    EXPECT_FALSE(expected_ksadmin_path->empty());

    EXPECT_TRUE(base::FilePath::CompareEqualIgnoreCase(
        expected_ksadmin_path->value(), got_ksadmin_path.value()))
        << "unexpected ksadmin path.\n\twant: "
        << expected_ksadmin_path->value()
        << "\n\t got: " << got_ksadmin_path.value();
  }
}

/**
 * InvokeCRURegistrationAndWait creates a CRURegistration and a semaphore, hands
 * them off to a test-specific block, and waits for the semaphore to signal
 * or times out after ten seconds. It returns whether the semaphore was
 * successfully signaled. This factors out the common logic for converting
 * CRURegistration's asynchronous operations to something functionally
 * synchronous for test purposes. The test thread blocks while waiting.
 *
 * The `impl` block is responsible for invoking the (asynchronous) method
 * under test on the provided `CRURegistration` and providing a reply block
 * to it that stores results from CRURegistration, then signals the semaphore.
 *
 * Mishandling the semaphore in `impl`, or ignoring a `false` result from this
 * function and subsequently attempting to access fields `impl` set up the
 * CRURegistration reply block to write to, will cause a data race, which is
 * undefined behavior in C.
 */
[[nodiscard]] bool InvokeCRURegistrationAndWait(
    const std::string& app_id,
    const base::FilePath& xc_path,
    void (^impl)(CRURegistration*, dispatch_semaphore_t)) {
  if (!impl) {
    ADD_FAILURE() << "test issue - no impl provided";
    return false;
  }
  NSString* ns_xc_path = @"NOT PROVIDED FOR THIS TEST";
  if (!xc_path.empty()) {
    ns_xc_path = base::apple::FilePathToNSString(xc_path);
  }
  if (!ns_xc_path) {
    ADD_FAILURE() << "test issue - xc_path could not be converted to NSString";
    return false;
  }
  CRURegistration* registration =
      [[CRURegistration alloc] initWithAppId:base::SysUTF8ToNSString(app_id)
                        existenceCheckerPath:ns_xc_path];

  dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
  impl(registration, semaphore);

  dispatch_time_t limit = dispatch_time(DISPATCH_TIME_NOW, 10L * NSEC_PER_SEC);
  return !dispatch_semaphore_wait(semaphore, limit);
}

void ExpectCRURegistrationCannotFetchTag(const std::string& app_id,
                                         const base::FilePath& xc_path) {
  @autoreleasepool {
    __block NSString* got_tag = nil;
    __block NSError* got_error = nil;

    ASSERT_TRUE(InvokeCRURegistrationAndWait(
        app_id, xc_path,
        ^(CRURegistration* registration, dispatch_semaphore_t semaphore) {
          [registration fetchTagWithReply:^(NSString* tag, NSError* error) {
            got_tag = tag;
            got_error = error;
            dispatch_semaphore_signal(semaphore);
          }];
        }));

    EXPECT_FALSE(got_tag) << base::SysNSStringToUTF8(got_tag);
    EXPECT_TRUE(got_error);
  }
}

void ExpectCRURegistrationFetchesTag(const std::string& app_id,
                                     const base::FilePath& xc_path,
                                     const std::string& want_tag) {
  @autoreleasepool {
    __block NSString* got_tag = nil;
    __block NSError* got_error = nil;

    ASSERT_TRUE(InvokeCRURegistrationAndWait(
        app_id, xc_path,
        ^(CRURegistration* registration, dispatch_semaphore_t semaphore) {
          [registration fetchTagWithReply:^(NSString* tag, NSError* error) {
            got_tag = tag;
            got_error = error;
            dispatch_semaphore_signal(semaphore);
          }];
        }));

    EXPECT_FALSE(got_error) << base::SysNSStringToUTF8([got_error description]);
    ASSERT_TRUE(got_tag);
    EXPECT_EQ(want_tag, base::SysNSStringToUTF8(got_tag));
  }
}

void ExpectCRURegistrationRegisters(const std::string& app_id,
                                    const base::FilePath& xc_path,
                                    const std::string& version_str) {
  @autoreleasepool {
    __block NSError* got_error = nil;

    ASSERT_TRUE(InvokeCRURegistrationAndWait(
        app_id, xc_path,
        ^(CRURegistration* registration, dispatch_semaphore_t semaphore) {
          [registration registerVersion:base::SysUTF8ToNSString(version_str)
                                  reply:^(NSError* error) {
                                    got_error = error;
                                    dispatch_semaphore_signal(semaphore);
                                  }];
        }));

    EXPECT_FALSE(got_error) << base::SysNSStringToUTF8([got_error description]);
  }
}

void ExpectCRURegistrationCannotRegister(const std::string& app_id,
                                         const base::FilePath& xc_path,
                                         const std::string& version_str) {
  @autoreleasepool {
    __block NSError* got_error = nil;

    ASSERT_TRUE(InvokeCRURegistrationAndWait(
        app_id, xc_path,
        ^(CRURegistration* registration, dispatch_semaphore_t semaphore) {
          [registration registerVersion:base::SysUTF8ToNSString(version_str)
                                  reply:^(NSError* error) {
                                    got_error = error;
                                    dispatch_semaphore_signal(semaphore);
                                  }];
        }));

    EXPECT_TRUE(got_error);
  }
}

void ExpectCRURegistrationMarksActive(const std::string& app_id) {
  @autoreleasepool {
    __block NSError* got_error = nil;

    ASSERT_TRUE(InvokeCRURegistrationAndWait(
        app_id, {},
        ^(CRURegistration* registration, dispatch_semaphore_t semaphore) {
          [registration markActiveWithReply:^(NSError* error) {
            got_error = error;
            dispatch_semaphore_signal(semaphore);
          }];
        }));

    EXPECT_FALSE(got_error) << base::SysNSStringToUTF8([got_error description]);
  }
}

std::optional<base::FilePath> GetRegistrationTestAppPath() {
  base::FilePath exe_path;
  if (!base::PathService::Get(base::DIR_EXE, &exe_path)) {
    return std::nullopt;
  }
  const base::FilePath test_app_path =
      exe_path.Append("registration_test_app_bundle.app/Contents/MacOS/"
                      "registration_test_app_bundle");
  if (test_app_path.empty() || !base::PathExists(test_app_path)) {
    return std::nullopt;
  }
  return test_app_path;
}

void ExpectRegistrationTestAppSuccess(const std::string& arg) {
  std::optional<base::FilePath> test_app_path = GetRegistrationTestAppPath();
  ASSERT_TRUE(test_app_path);
  base::CommandLine command_line(*test_app_path);
  command_line.AppendArg(arg);

  ExpectCliResult(command_line, false, {}, 0);
}

void ExpectRegistrationTestAppUserUpdaterInstallSuccess() {
  ExpectRegistrationTestAppSuccess("--install");
}

void ExpectRegistrationTestAppRegisterSuccess() {
  ExpectRegistrationTestAppSuccess("--register");
}

void ExpectRegistrationTestAppInstallAndRegisterSuccess() {
  ExpectRegistrationTestAppSuccess("--install_and_register");
}

}  // namespace updater::test
