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