summaryrefslogtreecommitdiff
path: root/src/qdoc/catch_generators/src/catch_generators/utilities/semantics/generator_handler.h
diff options
context:
space:
mode:
authorLuca Di Sera <luca.disera@qt.io>2023-05-12 15:12:11 +0200
committerLuca Di Sera <luca.disera@qt.io>2023-05-15 13:02:08 +0200
commitac01635f461bd9f211d89f6eea833d9d928fd113 (patch)
tree4efbfd1fc2f551435605b1c72d93e372f2dbb90b /src/qdoc/catch_generators/src/catch_generators/utilities/semantics/generator_handler.h
parent7057d01fbb9f8f37c707b33e3b92c10a78919ddc (diff)
downloadqttools-ac01635f461bd9f211d89f6eea833d9d928fd113.tar.gz
QDoc: Move catch_generators under src
QDoc employs a support library, "catch_generators", to provide custom support for the data-generation that certain tests use or might want to use when using the Catch2 testing framework, which QDoc uses for some of its tests. "catch_generators" was currently kept under "tests/auto/qdoc" and its headers were included and used directly by related tests by relative paths. Due to a certain restructuring that is happening in QDoc, with one of the goals, among others, being to increase the locality of QDoc-related code under "src/qdoc", the "catch_generators" support library is now moved under "src/qdoc". To allow code that depended on it to keep their usages without requiring the addition of some relative paths from the "tests" directory to the "src" directory, a library target, "Qt::QDocCatchGeneratorsPrivate" was created for it. The target can be linked-to to gain access to the previously-directly-used headers, with include path "catch_generators/.*". To allow for this specific include path to work, the internal directory structure for "catch_generators" was slightly modified with the addition of some intermediate directories in between its root and the library headers. The root "CMakeLists.txt" file for the QDoc project was modified to add the moved "catch_generators" as a subdirectory, to include it in the build process. "catch_generators" contains its own test code under the subdirectory "tests". Previously the test target in "tests" included the relevant headers from the library by use of relative paths to its sources. Now that the library is exported as a target, the "CMakeLists.txt" file under "tests" was modified to rely on linking to the library itself to obtain access to the required headers. Similarly, targets under "tests/auto/qdoc" that used the dependency now link to it instead. Hence, their "CMakeLists.txt" files were modified to avoid using the dependency as an include directory and instead use "Qt::QDocCatcGeneratorsPrivate" as a library. The inclusions of the "catch_generators" headers in relevant sources was modified to respect the new "catch_generators/.*" path. Additionally, "catch_generators" exposed a top level header, "qdoc_catch_generators.h", including certain headers in the library that were expected to be commonly used by tests, so that the consumers did not have to include multiple headers when using various common generators. The header was removed in favor of including the library headers themselves now that they have a well-defined root provided by the exposed target. Sources that included the header were modified to include only their relevant headers from "catch_generators", respecting the additional granularity. Due to the Qt Project CI performing discovery of tests by configuring only the "tests" directory of the module; the moved "catch_generators", which contained its own testing code, will now escape the automated testing in CI for its own tests, as the relevant target does not reside under the "tests" directory of the repository. To avoid this issue, the "CMakeLists.txt" file under "tests/auto/qdoc", was modified to `include` the "CMakeLists.txt" file that describes "catch_generators"' test target, so as to "mirror" the test under the "tests" directory. To support working when included, the "CMakeLists.txt" file that describes "catch_generators"' test target was modified to refer to any relevant relative path by prefixing the value of `CMAKE_CURRENT_LIST_DIR`, so that the relative paths would not be incorrectly resolved when using `include`. Due to this "mirroring", the relevant test target would be configured twice when the whole repository was configured, resulting in an error. To ensure that this is not the case, the `include` directive was hidden behind `QT_BUILD_STANADALONE_TESTS`, which is not set during a general configuration of the repository but is set when CI performs test-discovery on the "tests" directory. Similarly, the "tests" directory of a repository is configured only when `QT_BUILD_TESTS` is `ON`, which further ensures that the required dependencies, such as `Qt::Test`, will be found before the directory is configured. By having moved the test declaration outside of the `tests` directory, the test will always be configured, failing to find its dependencies when this happens. To avoid the issue, the `add_subdirectory(tests)` directive in `src/qdoc/catch_generators/CMakeLists.txt` was conditioned over `QT_BUILD_TESTS`. Certain files that were missing an license header were enhanced with it, as the lack of an header will now be an issue outside the "tests" directory. Change-Id: I0bca477b7da75c121c24b8528fc9defa26a6123e Reviewed-by: Topi Reiniƶ <topi.reinio@qt.io>
Diffstat (limited to 'src/qdoc/catch_generators/src/catch_generators/utilities/semantics/generator_handler.h')
-rw-r--r--src/qdoc/catch_generators/src/catch_generators/utilities/semantics/generator_handler.h97
1 files changed, 97 insertions, 0 deletions
diff --git a/src/qdoc/catch_generators/src/catch_generators/utilities/semantics/generator_handler.h b/src/qdoc/catch_generators/src/catch_generators/utilities/semantics/generator_handler.h
new file mode 100644
index 000000000..328627512
--- /dev/null
+++ b/src/qdoc/catch_generators/src/catch_generators/utilities/semantics/generator_handler.h
@@ -0,0 +1,97 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#pragma once
+
+#include "../../namespaces.h"
+
+#include <catch/catch.hpp>
+
+#include <optional>
+#include <cassert>
+
+namespace QDOC_CATCH_GENERATORS_UTILITIES_ABSOLUTE_NAMESPACE {
+
+ template<typename T>
+ class GeneratorHandler : public Catch::Generators::IGenerator<T> {
+ public:
+
+ GeneratorHandler(Catch::Generators::GeneratorWrapper<T>&& generator)
+ : generator{std::move(generator)},
+ first_call{true}
+ {}
+
+ T const& get() const override {
+ assert(!first_call);
+ return generator.get();
+ }
+
+ bool next() override {
+ if (first_call) {
+ first_call = false;
+ return true;
+ }
+
+ return generator.next();
+ }
+
+ private:
+ Catch::Generators::GeneratorWrapper<T> generator;
+ bool first_call;
+ };
+
+
+ /*!
+ * Returns a generator wrapping \a generator that ensures that
+ * changes its semantics so that the first call to get should be
+ * preceded by a call to next.
+ *
+ * Catch generators require that is valid to call get and obtain a
+ * valid value on a generator that was just created.
+ * That is, generators should be non-empty and their first value
+ * should be initialized on construction.
+ *
+ * Normally, this is not a problem, and the next implementation of
+ * the generator can be simply called in the constructor.
+ * But when a generator depends on other generators, doing so will
+ * generally skip the first value that the generator
+ * produces, as the wrapping generator will need to advance the
+ * underlying generator, losing the value in the process.
+ * This is in particular, a problem, on generators that are finite
+ * or infinite and ordered.
+ *
+ * To solve the issue, the original value can be saved before
+ * advancing the generator or some code can be duplicated or
+ * abstracted so that what a new element can be generated without
+ * advancing the underlying generator.
+ *
+ * While this is acceptable, it can be error prone on more complex
+ * generators, generators that randomly access a collection of
+ * generators and so on.
+ *
+ * To simplify this process, this generator changes the semantics
+ * of the wrapped generator such that the first value of the
+ * generator is produced after the first call to next and the
+ * generator is considered in an invalid state before the first
+ * advancement.
+ *
+ * In this way, by wrapping all generators that a generator
+ * depends on, the implementation required for the first value is
+ * the same as the one required for all following values, with
+ * regards to the sequencing of next and get operations,
+ * simplifying the implementation of dependent generators.
+ *
+ * Do note that, while the generator returned by this function
+ * implments the generator interface that Catch2 requires, it
+ * cannot be normally used as a generator as it fails to comply
+ * with the first value semantics that a generator requires.
+ * Indeed, it should only be used as an intermediate wrapper for
+ * the implementation of generators that depends on other
+ * generators.
+ */
+ template<typename T>
+ inline Catch::Generators::GeneratorWrapper<T> handler(Catch::Generators::GeneratorWrapper<T>&& generator) {
+ return Catch::Generators::GeneratorWrapper<T>(std::unique_ptr<Catch::Generators::IGenerator<T>>(new GeneratorHandler(std::move(generator))));
+ }
+
+} // end QDOC_CATCH_GENERATORS_UTILITIES_ABSOLUTE_NAMESPACE