chromium/third_party/ipcz/src/test/multinode_test.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 "test/multinode_test.h"

#include <cstring>
#include <map>
#include <optional>
#include <string>
#include <thread>

#include "ipcz/ipcz.h"
#include "reference_drivers/async_reference_driver.h"
#include "reference_drivers/sync_reference_driver.h"
#include "test_buildflags.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h"
#include "third_party/abseil-cpp/absl/base/macros.h"
#include "third_party/abseil-cpp/absl/strings/str_cat.h"
#include "third_party/abseil-cpp/absl/strings/str_split.h"
#include "third_party/abseil-cpp/absl/types/span.h"

#if BUILDFLAG(ENABLE_IPCZ_MULTIPROCESS_TESTS)
#include "reference_drivers/file_descriptor.h"
#include "reference_drivers/multiprocess_reference_driver.h"
#include "reference_drivers/socket_transport.h"
#include "test/test_child_launcher.h"
#endif

namespace ipcz::test {

namespace {

using TestDriverMap = std::map<std::string, TestDriver*>;
TestDriverMap& GetTestDrivers() {}

using TestNodeMap = std::map<std::string, TestNodeFactory>;
TestNodeMap& GetTestNodes() {}

using TestFeatureSetMap = std::map<std::string, std::vector<IpczFeature>>;
const TestFeatureSetMap& GetTestFeatureSets() {}

struct RegisteredMultinodeTest {};

std::vector<RegisteredMultinodeTest>& GetRegisteredMultinodeTests() {}

// Launches a new node on a dedicated thread within the same process. All
// connections use the synchronous single-process driver.
class InProcessTestNodeController : public TestNode::TestNodeController {};

class InProcessTestDriverBase : public TestDriver {};

class SyncTestDriver : public InProcessTestDriverBase {};

class AsyncTestDriver : public InProcessTestDriverBase {};

TestDriverRegistration<SyncTestDriver> kRegisterSyncDriver;
TestDriverRegistration<AsyncTestDriver> kRegisterAsyncDriver{
    internal::kAsyncTestDriverName, AsyncTestDriver::kDefault};
TestDriverRegistration<AsyncTestDriver> kRegisterAsyncDriverWithDelegatedAlloc{
    internal::kAsyncDelegatedAllocTestDriverName,
    AsyncTestDriver::kDelegateAllocation};
TestDriverRegistration<AsyncTestDriver> kRegisterAsyncDriverWithForcedBrokering{
    internal::kAsyncForcedBrokeringTestDriverName,
    AsyncTestDriver::kForceBrokering};
TestDriverRegistration<AsyncTestDriver>
    kRegisterAsyncDriverWithDelegatedAllocAndForcedBrokering{
        internal::kAsyncDelegatedAllocAndForcedBrokeringTestDriverName,
        AsyncTestDriver::kForceBrokeringAndDelegateAllocation};

#if BUILDFLAG(ENABLE_IPCZ_MULTIPROCESS_TESTS)
// Controls a node running within an isolated child process.
class ChildProcessTestNodeController : public TestNode::TestNodeController {
 public:
  ChildProcessTestNodeController(TestNode& source, pid_t pid)
      : source_(source), pid_(pid) {}
  ~ChildProcessTestNodeController() override {
    ABSL_ASSERT(result_.has_value());
  }

  // TestNode::TestNodeController:
  bool WaitForShutdown() override {
    if (result_.has_value()) {
      return *result_;
    }

    result_ = TestChildLauncher::WaitForSuccessfulProcessTermination(pid_);
    return *result_;
  }

  TransportPair CreateNewTransports() override {
    return source_.CreateTransports();
  }

  TestNode& source_;
  const pid_t pid_;
  std::optional<bool> result_;
};

class MultiprocessTestDriver : public TestDriver {
 public:
  const IpczDriver& GetIpczDriver() const override {
    return reference_drivers::kMultiprocessReferenceDriver;
  }

  const char* GetName() const override {
    return internal::kMultiprocessTestDriverName;
  }

  TransportPair CreateTransports(TestNode& source,
                                 bool for_broker_target) const override {
    TransportPair transports;
    const IpczResult result = GetIpczDriver().CreateTransports(
        IPCZ_INVALID_DRIVER_HANDLE, IPCZ_INVALID_DRIVER_HANDLE, IPCZ_NO_FLAGS,
        nullptr, &transports.ours, &transports.theirs);
    ABSL_ASSERT(result == IPCZ_RESULT_OK);
    return transports;
  }

  Ref<TestNode::TestNodeController> SpawnTestNode(
      TestNode& source,
      const TestNodeDetails& details,
      const std::string& feature_set,
      IpczDriverHandle our_transport,
      IpczDriverHandle their_transport) override {
    reference_drivers::FileDescriptor socket =
        reference_drivers::TakeMultiprocessTransportDescriptor(their_transport);
    return MakeRefCounted<ChildProcessTestNodeController>(
        source,
        child_launcher_.Launch(details.name, feature_set, std::move(socket)));
  }

  IpczConnectNodeFlags GetExtraClientConnectNodeFlags() const override {
    return IPCZ_NO_FLAGS;
  }

  IpczDriverHandle GetClientTestNodeTransport() override {
    auto transport = MakeRefCounted<reference_drivers::SocketTransport>(
        TestChildLauncher::TakeChildSocketDescriptor());
    return reference_drivers::CreateMultiprocessTransport(std::move(transport));
  }

 private:
  TestChildLauncher child_launcher_;
};

TestDriverRegistration<MultiprocessTestDriver> kRegisterMultiprocessDriver;

#endif

}  // namespace

namespace internal {

const char kSyncTestDriverName[] =;
const char kAsyncTestDriverName[] =;
const char kAsyncDelegatedAllocTestDriverName[] =;
const char kAsyncForcedBrokeringTestDriverName[] =;
const char kAsyncDelegatedAllocAndForcedBrokeringTestDriverName[] =;
const char kMultiprocessTestDriverName[] =;

}  // namespace internal

TestDriverRegistrationImpl::TestDriverRegistrationImpl(TestDriver& driver) {}

TestNode::~TestNode() {}

const IpczDriver& TestNode::GetDriver() const {}

void TestNode::Initialize(TestDriver* test_driver,
                          const std::string& feature_set) {}

void TestNode::ConnectToParent(absl::Span<IpczHandle> portals,
                               IpczConnectNodeFlags flags) {}

void TestNode::ConnectToBroker(absl::Span<IpczHandle> portals) {}

IpczHandle TestNode::ConnectToParent(IpczConnectNodeFlags flags) {}

IpczHandle TestNode::ConnectToBroker() {}

std::pair<IpczHandle, IpczHandle> TestNode::OpenPortals() {}

IpczHandle TestNode::BoxBlob(std::string_view contents) {}

std::string TestNode::UnboxBlob(IpczHandle box) {}

void TestNode::CloseThisNode() {}

Ref<TestNode::TestNodeController> TestNode::SpawnTestNodeImpl(
    const TestNodeDetails& details,
    IpczDriverHandle& our_transport) {}

TransportPair TestNode::CreateTransports() {}

TransportPair TestNode::CreateBrokerToBrokerTransports() {}

void TestNode::SetTransport(IpczDriverHandle transport) {}

int TestNode::RunAsChild(TestDriver* test_driver,
                         const std::string& feature_set) {}

void RegisterMultinodeTestNode(std::string_view node_name,
                               TestNodeFactory factory) {}

void RegisterMultinodeTest(const char* test_suite_name,
                           const char* test_name,
                           const char* filename,
                           int line,
                           MultinodeTestFactory factory) {}

int RunChildProcessTest(const std::string& test_name) {}

void RegisterMultinodeTests() {}

}  // namespace ipcz::test