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

summaryrefslogtreecommitdiffhomepage
path: root/src/Progmasoft/Catch3/Generator.hpp
blob: 0e48aaa3812d4ffb3dec866c9a0d85f8481aa03f (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
// Copyright (c) 2026 Progmasoft.
// SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-1.1
#pragma once

#include <Progmasoft/Catch3/Random.hpp>

#include <functional>
#include <stdexcept>
#include <utility>
#include <vector>

namespace Progmasoft::Catch3 {

    /// A value source paired with an ordered sequence of simpler candidates.
    ///
    /// The property runner owns the shrinking policy; generators only describe
    /// which candidates are valid and which order is most useful for
    /// minimization.
    template <typename ValueType>
    class Generator final {
    public:
        using GenerationFunction = std::function<ValueType( Random& )>;
        using ShrinkingFunction =
            std::function<std::vector<ValueType>( const ValueType& )>;

        Generator( GenerationFunction generate, ShrinkingFunction shrink ):
            generate_( std::move( generate ) ), shrink_( std::move( shrink ) ) {
            if ( !generate_ || !shrink_ ) {
                throw std::invalid_argument(
                    "a generator requires both callbacks" );
            }
        }

        [[nodiscard]] ValueType Generate( Random& random ) const {
            return generate_( random );
        }

        [[nodiscard]] std::vector<ValueType>
        Shrink( const ValueType& value ) const {
            return shrink_( value );
        }

    private:
        GenerationFunction generate_;
        ShrinkingFunction shrink_;
    };

    /// Adapts user callables into a reusable generator.
    template <typename ValueType,
              typename GenerateFunction,
              typename ShrinkFunction>
    [[nodiscard]] Generator<ValueType>
    MakeGenerator( GenerateFunction&& generate, ShrinkFunction&& shrink ) {
        return Generator<ValueType>(
            typename Generator<ValueType>::GenerationFunction(
                std::forward<GenerateFunction>( generate ) ),
            typename Generator<ValueType>::ShrinkingFunction(
                std::forward<ShrinkFunction>( shrink ) ) );
    }

} // namespace Progmasoft::Catch3