• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

DNKpp / mimicpp / 19786733300

29 Nov 2025 04:59PM UTC coverage: 90.47% (-7.8%) from 98.254%
19786733300

Pull #138

github

web-flow
Merge 104959d5a into 4e0d69781
Pull Request #138: CI: Use latest gcovr

1822 of 2223 branches covered (81.96%)

Branch coverage included in aggregate %.

2450 of 2499 relevant lines covered (98.04%)

7444.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.78
/include/mimic++/ExpectationBuilder.hpp
1
//          Copyright Dominic (DNKpp) Koepke 2024 - 2025.
2
// Distributed under the Boost Software License, Version 1.0.
3
//    (See accompanying file LICENSE_1_0.txt or copy at
4
//          https://www.boost.org/LICENSE_1_0.txt)
5

6
#ifndef MIMICPP_EXPECTATION_BUILDER_HPP
7
#define MIMICPP_EXPECTATION_BUILDER_HPP
8

9
#pragma once
10

11
#include "mimic++/Expectation.hpp"
12
#include "mimic++/Fwd.hpp"
13
#include "mimic++/Sequence.hpp"
14
#include "mimic++/config/Config.hpp"
15
#include "mimic++/macros/ScopedExpectation.hpp"
16
#include "mimic++/matchers/Common.hpp"
17
#include "mimic++/matchers/GeneralMatchers.hpp"
18
#include "mimic++/matchers/StringMatchers.hpp"
19
#include "mimic++/policies/ArgRequirementPolicies.hpp"
20
#include "mimic++/policies/ControlPolicies.hpp"
21
#include "mimic++/policies/GeneralPolicies.hpp"
22
#include "mimic++/reporting/TargetReport.hpp"
23
#include "mimic++/utilities/Concepts.hpp"
24
#include "mimic++/utilities/PriorityTag.hpp"
25
#include "mimic++/utilities/SourceLocation.hpp"
26

27
#ifndef MIMICPP_DETAIL_IS_MODULE
28
    #include <concepts>
29
    #include <memory>
30
    #include <tuple>
31
    #include <utility>
32
#endif
33

34
MIMICPP_DETAIL_MODULE_EXPORT namespace mimicpp
35
{
36
    template <
37
        bool timesConfigured,
38
        typename SequenceConfig,
39
        typename Signature,
40
        typename FinalizePolicy,
41
        expectation_policy_for<Signature>... Policies>
42
    class BasicExpectationBuilder
43
    {
44
    public:
45
        using StorageT = ExpectationCollection<Signature>;
46
        using PolicyListT = std::tuple<Policies...>;
47
        using ReturnT = typename Expectation<Signature>::ReturnT;
48

49
        ~BasicExpectationBuilder() = default;
50

51
        template <typename FinalizePolicyArg, typename PolicyListArg>
52
            requires std::constructible_from<FinalizePolicy, FinalizePolicyArg>
53
                      && std::constructible_from<PolicyListT, PolicyListArg>
54
        [[nodiscard]]
55
        explicit constexpr BasicExpectationBuilder(
56
            std::shared_ptr<StorageT> storage,
57
            reporting::TargetReport target,
58
            detail::TimesConfig timesConfig,
59
            SequenceConfig sequenceConfig,
60
            FinalizePolicyArg&& finalizePolicyArg,
61
            PolicyListArg&& policyListArg) noexcept
62
            : m_Storage{std::move(storage)},
178,936✔
63
              m_TargetReport{std::move(target)},
178,936✔
64
              m_TimesConfig{std::move(timesConfig)},
89,468✔
65
              m_SequenceConfig{std::move(sequenceConfig)},
110,194✔
66
              m_FinalizePolicy{std::forward<FinalizePolicyArg>(finalizePolicyArg)},
89,484✔
67
              m_ExpectationPolicies{std::forward<PolicyListArg>(policyListArg)}
157,856✔
68
        {
69
            MIMICPP_ASSERT(m_Storage, "Storage is nullptr.");
70
        }
89,468✔
71

72
        BasicExpectationBuilder(const BasicExpectationBuilder&) = delete;
73
        BasicExpectationBuilder& operator=(const BasicExpectationBuilder&) = delete;
74

75
        [[nodiscard]]
76
        BasicExpectationBuilder(BasicExpectationBuilder&&) = default;
77
        BasicExpectationBuilder& operator=(BasicExpectationBuilder&&) = default;
78

79
        template <typename Policy>
80
            requires finalize_policy_for<std::remove_cvref_t<Policy>, Signature>
81
        [[nodiscard]]
82
        friend constexpr auto operator&&(BasicExpectationBuilder&& builder, Policy&& policy)
83
        {
84
            static_assert(
85
                !std::same_as<expectation_policies::InitFinalize, std::remove_cvref_t<Policy>>,
86
                "Explicitly specifying the `expectation_policies::InitFinalize` is disallowed.");
87

88
            static_assert(
89
                std::same_as<expectation_policies::InitFinalize, FinalizePolicy>,
90
                "Only one finalize-policy may be specified per expectation. "
91
                "See: https://dnkpp.github.io/mimicpp/db/d7a/group___e_x_p_e_c_t_a_t_i_o_n___f_i_n_a_l_i_z_e_r.html#details");
92

93
            using Builder = BasicExpectationBuilder<
94
                timesConfigured,
95
                SequenceConfig,
96
                Signature,
97
                std::remove_cvref_t<Policy>,
98
                Policies...>;
99

100
            return Builder{
101
                std::move(builder.m_Storage),
94✔
102
                std::move(builder.m_TargetReport),
94✔
103
                std::move(builder.m_TimesConfig),
94✔
104
                std::move(builder.m_SequenceConfig),
98✔
105
                std::forward<Policy>(policy),
106
                std::move(builder.m_ExpectationPolicies)};
474✔
107
        }
108

109
        template <typename Policy>
110
            requires expectation_policy_for<std::remove_cvref_t<Policy>, Signature>
111
        [[nodiscard]]
112
        friend constexpr auto operator&&(BasicExpectationBuilder&& builder, Policy&& policy)
113
        {
114
            using ExtendedExpectationBuilderT = BasicExpectationBuilder<
115
                timesConfigured,
116
                SequenceConfig,
117
                Signature,
118
                FinalizePolicy,
119
                Policies...,
120
                std::remove_cvref_t<Policy>>;
121

122
            return ExtendedExpectationBuilderT{
123
                std::move(builder.m_Storage),
47,515✔
124
                std::move(builder.m_TargetReport),
47,515✔
125
                std::move(builder.m_TimesConfig),
47,515✔
126
                std::move(builder.m_SequenceConfig),
95,030✔
127
                std::move(builder.m_FinalizePolicy),
95,030✔
128
                std::tuple_cat(
1,490✔
129
                    std::move(builder.m_ExpectationPolicies),
95,030✔
130
                    std::forward_as_tuple(std::forward<Policy>(policy)))};
239,065✔
131
        }
132

133
        [[nodiscard]]
134
        friend constexpr auto operator&&(BasicExpectationBuilder&& builder, detail::TimesConfig&& config)
135
        {
136
            static_assert(
137
                !timesConfigured,
138
                "Only one times-policy may be specified per expectation. "
139
                "See: https://dnkpp.github.io/mimicpp/d7/d32/group___e_x_p_e_c_t_a_t_i_o_n___t_i_m_e_s.html#details");
140

141
            using Builder = BasicExpectationBuilder<
142
                true,
143
                SequenceConfig,
144
                Signature,
145
                FinalizePolicy,
146
                Policies...>;
147

148
            return Builder{
149
                std::move(builder.m_Storage),
84✔
150
                std::move(builder.m_TargetReport),
84✔
151
                std::move(config),
84✔
152
                std::move(builder.m_SequenceConfig),
168✔
153
                std::move(builder.m_FinalizePolicy),
84✔
154
                std::move(builder.m_ExpectationPolicies)};
422✔
155
        }
156

157
        template <typename... Sequences>
158
        [[nodiscard]]
159
        friend constexpr auto operator&&(BasicExpectationBuilder&& builder, sequence::detail::Config<Sequences...>&& config)
160
        {
161
            sequence::detail::Config newConfig = builder.m_SequenceConfig.concat(std::move(config));
41,440✔
162

163
            using ExtendedExpectationBuilderT = BasicExpectationBuilder<
164
                timesConfigured,
165
                decltype(newConfig),
166
                Signature,
167
                FinalizePolicy,
168
                Policies...>;
169

170
            return ExtendedExpectationBuilderT{
171
                std::move(builder.m_Storage),
20,720✔
172
                std::move(builder.m_TargetReport),
20,720✔
173
                std::move(builder.m_TimesConfig),
20,720✔
174
                std::move(newConfig),
20,720✔
175
                std::move(builder.m_FinalizePolicy),
20,720✔
176
                std::move(builder.m_ExpectationPolicies)};
145,040✔
177
        }
20,720✔
178

179
        [[nodiscard]]
180
        ScopedExpectation finalize(util::SourceLocation sourceLocation) &&
181
        {
182
            static_assert(
183
                finalize_policy_for<FinalizePolicy, Signature>,
184
                "For non-void return types, a finalize-policy must be specified. "
185
                "See: https://dnkpp.github.io/mimicpp/db/d7a/group___e_x_p_e_c_t_a_t_i_o_n___f_i_n_a_l_i_z_e_r.html#details");
186

187
            return ScopedExpectation{
188
                std::move(m_Storage),
21,055✔
189
                std::apply(
42,110✔
190
                    [&](auto&... policies) {
×
191
                        ControlPolicy controlPolicy{
21,052✔
192
                            sourceLocation,
193
                            std::move(m_TimesConfig),
21,055✔
194
                            std::move(m_SequenceConfig)};
42,110✔
195

196
                        using Expectation = BasicExpectation<
197
                            Signature,
198
                            decltype(controlPolicy),
199
                            FinalizePolicy,
200
                            Policies...>;
201

202
                        return std::make_unique<Expectation>(
203
                            std::move(sourceLocation),
21,055✔
204
                            std::move(m_TargetReport),
42,110✔
205
                            std::move(controlPolicy),
21,055✔
206
                            std::move(m_FinalizePolicy),
21,070✔
207
                            std::move(policies)...);
110,680✔
208
                    },
20,719✔
209
                    m_ExpectationPolicies)};
63,165✔
210
        }
211

212
    private:
213
        std::shared_ptr<StorageT> m_Storage;
214
        reporting::TargetReport m_TargetReport;
215
        detail::TimesConfig m_TimesConfig{};
216
        SequenceConfig m_SequenceConfig{};
217
        FinalizePolicy m_FinalizePolicy{};
218
        PolicyListT m_ExpectationPolicies{};
219
    };
220
}
221

222
namespace mimicpp::detail
223
{
224
    template <typename Param, typename... Canary, matcher_for<Param> Arg>
225
    [[nodiscard]]
226
    constexpr auto make_arg_matcher([[maybe_unused]] util::priority_tag<2> const, Arg arg)
227
    {
228
        return arg;
231✔
229
    }
230

231
    // if the param is a character-pointer, there is no evidence, whether it denotes a null-terminated string or just an
232
    // actual pointer to a value.
233
    // But, the Mock user shall know it, thus if `Arg` is not a character-pointer, we enable this matcher.
234
    template <string Param, typename... Canary, string Arg>
235
        requires(!std::is_pointer_v<std::remove_reference_t<Param>>)
236
             || (!std::is_pointer_v<std::remove_reference_t<Arg>>)
237
    [[nodiscard]] //
238
    constexpr auto make_arg_matcher([[maybe_unused]] util::priority_tag<1> const, Arg&& arg)
239
    {
240
        return matches::str::eq(std::forward<Arg>(arg));
3,342✔
241
    }
242

243
    template <typename Param, typename... Canary, util::weakly_equality_comparable_with<Param> Arg>
244
    [[nodiscard]]
245
    constexpr auto make_arg_matcher([[maybe_unused]] util::priority_tag<0> const, Arg&& arg)
246
    {
247
        return matches::eq(std::forward<Arg>(arg));
1,839✔
248
    }
249

250
    inline constexpr util::priority_tag<2> maxMakeArgMatcherTag{};
251

252
    template <typename Arg, typename Target>
253
    concept requirement_for = requires {
254
        {
255
            detail::make_arg_matcher<Target>(maxMakeArgMatcherTag, std::declval<Arg>())
256
        } -> matcher_for<Target>;
257
    };
258

259
    template <
260
        typename Signature,
261
        std::size_t index,
262
        typename Arg,
263
        typename... Canary,
264
        typename Param = signature_param_type_t<index, Signature>>
265
        requires requirement_for<Arg, Param>
266
    constexpr auto make_arg_policy(Arg&& arg)
267
    {
268
        return expect::arg<index>(
269
            detail::make_arg_matcher<Param>(maxMakeArgMatcherTag, std::forward<Arg>(arg)));
5,412✔
270
    }
271

272
    template <typename Signature, typename Builder, std::size_t... indices, typename... Args>
273
    [[nodiscard]]
274
    constexpr auto extend_builder_with_arg_policies(
275
        Builder&& builder,
276
        [[maybe_unused]] std::index_sequence<indices...> const,
277
        Args&&... args)
278
    {
279
        return (
280
            std::forward<Builder>(builder)
281
            && ...
201✔
282
            && detail::make_arg_policy<Signature, indices>(std::forward<Args>(args)));
31,574✔
283
    }
284

285
    template <typename Signature, typename... Args>
286
    constexpr auto make_expectation_builder(
287
        std::shared_ptr<ExpectationCollection<Signature>> expectations,
288
        reporting::TargetReport target,
289
        Args&&... args)
290
    {
291
        using BaseBuilderT = BasicExpectationBuilder<
292
            false,
293
            sequence::detail::Config<>,
294
            Signature,
295
            expectation_policies::InitFinalize>;
296

297
        return detail::extend_builder_with_arg_policies<Signature>(
63,126✔
298
            BaseBuilderT{
299
                std::move(expectations),
21,042✔
300
                std::move(target),
21,042✔
301
                TimesConfig{},
21,042✔
302
                sequence::detail::Config<>{},
303
                expectation_policies::InitFinalize{},
304
                std::tuple{}},
21,042✔
305
            std::index_sequence_for<Args...>{},
306
            std::forward<Args>(args)...);
31,756✔
307
    }
308
}
309

310
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc