Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/src/Progmasoft/Runner/Catalog.hpp
blob: 2a8e1039ee5c0bc905bae246da09ddad3b96064c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Copyright (c) 2026 Progmasoft.
// SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-2.0
#pragma once

#include <Progmasoft/Catch3/TestCaseInfo.hpp>
#include <chrono>
#include <cstddef>
#include <optional>
#include <string>
#include <vector>

#include "Expected.hpp"

namespace Catch
{
    class IConfig;
} // namespace Catch

namespace Progmasoft::Catch3::Runner
{
    /// One registered test and what its tags tell the runner.
    struct TestEntry final
    {
        /// The position in registration order, the same in every process
        /// started from one binary.
        std::size_t index = 0;
        /// A name that identifies the test across runs and builds: the test
        /// name, with its class when it has one, and its tags when another
        /// test has the same name.
        std::string key;
        std::string name;
        std::string className;
        std::string file;
        std::size_t line = 0;
        std::vector<std::string> tags;
        bool hidden = false;
        bool benchmark = false;
        bool mayFail = false;
        bool shouldFail = false;

        // From the tags the runner reserves.
        /// `[!serial]`: nothing else runs at the same time.
        bool serial = false;
        /// `[!isolated]`: runs in a process of its own.
        bool isolated = false;
        /// `[!quarantine]`: in quarantine whatever its history says.
        bool quarantined = false;
        /// `[!resource:NAME]`: tests sharing a resource never overlap.
        std::vector<std::string> resources;
        /// `[!depends:NAME]`: runs after these tests, and only if they pass.
        std::vector<std::string> dependsOn;
        /// `[!timeout:SECONDS]`.
        std::optional<std::chrono::milliseconds> timeout;
        /// `[!retries:N]`.
        std::optional<unsigned> retries;
    };

    /// The tests registered in this binary.
    class Catalog final
    {
    public:
        /// Reads the test registry. Problems with a reserved tag, such as a
        /// timeout that is not a number, are errors.
        [[nodiscard]] static Expected<Catalog>
        Load();

        /// A catalog of the given tests, without a registry behind it: the
        /// tests cannot run, but they can be planned. Each entry's index
        /// becomes its position, and an empty key becomes its name.
        [[nodiscard]] static Catalog
        FromEntries(std::vector<TestEntry> entries);

        [[nodiscard]] const std::vector<TestEntry> &
        Tests() const noexcept
        {
            return tests_;
        }

        [[nodiscard]] const std::vector<Catch::TestCaseHandle> &
        Handles() const noexcept
        {
            return handles_;
        }

        /// The test of a key or of a name; null when there is none.
        [[nodiscard]] const TestEntry *
        Find(const std::string &keyOrName) const;

        /// A digest of every key in order. A worker reports it, so the runner
        /// knows the worker sees the same tests.
        [[nodiscard]] const std::string &
        Identity() const noexcept
        {
            return identity_;
        }

        /// The tests the specs of `config` select, in registration order, as
        /// Catch2 selects them: hidden tests only when a spec names them.
        /// Specs that matched nothing are added to `unmatched`.
        [[nodiscard]] std::vector<std::size_t>
        Match(const Catch::IConfig &config,
              std::vector<std::string> &unmatched) const;

    private:
        std::vector<TestEntry> tests_;
        std::vector<Catch::TestCaseHandle> handles_;
        std::string identity_;
    };
} // namespace Progmasoft::Catch3::Runner