chromium/third_party/ipcz/src/test/multinode_test.h

// 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.

#ifndef IPCZ_SRC_TEST_MULTINODE_TEST_H_
#define IPCZ_SRC_TEST_MULTINODE_TEST_H_

#include <memory>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include <vector>

#include "ipcz/ipcz.h"
#include "test/test_base.h"
#include "test_buildflags.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/base/macros.h"
#include "third_party/abseil-cpp/absl/types/span.h"
#include "util/ref_counted.h"

namespace ipcz::test {

class TestNode;

template <typename TestNodeType>
class MultinodeTest;

namespace internal {

template <typename TestNodeType>
std::unique_ptr<TestNode> MakeTestNode() {}

IsValidTestNodeType;

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

}  // namespace internal

class TestDriver;

using TestNodeFactory = std::unique_ptr<TestNode> (*)();

struct TransportPair {};

// Type used to package metadata about a MULTINODE_TEST_NODE() or
// MULTINODE_TEST() invocation.
struct TestNodeDetails {};

// Base class to support tests which exercise behavior across multiple ipcz
// nodes. These may be single-process on a synchronous driver, single-process on
// an asynchronous (e.g. multiprocess) driver, or fully multiprocess.
//
// This class provides convenience methods for creating and connecting nodes
// in various useful configurations. Note that it does NOT inherit from GTest's
// Test class, as multiple instances may run in parallel for a single test, and
// GTest's Test class is not compatible with that behavior.
//
// Instead, while MULTINODE_TEST_NODE() invocations should be based directly on
// TestNode or a derivative thereof. MULTINODE_TEST() invocations for multinode
// tests should be based on derivatives of MultinodeTest<T> (see below this
// class), where T itself is a TestNode or some derivative thereof.
//
// This arrangement allows the main test body and its related
// MULTINODE_TEST_NODE() invocations to be based on the same essential type,
// making multinode tests easier to read and write.
class TestNode : public internal::TestBase {};

// Actual parameterized GTest Test fixture for multinode tests. This or a
// subclass of it is required for MULTINODE_TEST() invocations to function as
// proper multinode tests.
template <typename TestNodeType = TestNode>
class MultinodeTest : public TestNodeType, public ::testing::Test {};

// TestDriver specifies an IpczDriver implementation to use for multinode tests.
// It also implements launching and joining of other test nodes. A TestDriver
// can be registered by statically initializing a corresponding
// TestDriverRegistration. All multinode tests are run against all registered
// TestDrivers.
class TestDriver {};

// Registers a TestDriver globally so that all MULTINODE_TEST() invocations are
// parameterized over it.
class TestDriverRegistrationImpl {};

template <typename TestDriverType>
class TestDriverRegistration {};

void RegisterMultinodeTestNode(std::string_view node_name,
                               TestNodeFactory factory);

template <typename NodeType>
class MultinodeTestNodeRegistration {};

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

// Registers a MULTINODE_TEST() test to be run when all tests are run. This
// registers a unique instance of the test for each registered test driver.
template <typename Test>
class MultinodeTestRegistration {};

// Must be called before RUN_ALL_TESTS() is invoked in order for any defined
// multinode tests to be run.
void RegisterMultinodeTests();

}  // namespace ipcz::test

// Defines the main body of a non-broker test node for a multinode test. The
// named node can be spawned by another node using SpawnTestNode<T> where T is
// the unique name given by `node_name` here. `fixture` must be
/// ipcz::test::TestNode or a subclass thereof.
#define MULTINODE_TEST_NODE_IMPL(fixture, node_name, is_broker_value)

#define MULTINODE_TEST_NODE(fixture, node_name)

#define MULTINODE_TEST_BROKER_NODE(fixture, node_name)

#define MULTINODE_TEST_NAME(name)
#define MULTINODE_TEST_CLASS_NAME(name)
#define MULTINODE_TEST_REGISTRATION_NAME(name)

#define MULTINODE_TEST(fixture, test_name)

#endif  // IPCZ_SRC_TEST_MULTINODE_TEST_H_