| // 300-Gen-OwnGenerator.cpp |
| // Shows how to define a custom generator. |
| |
| // Specifically we will implement a random number generator for integers |
| // It will have infinite capacity and settable lower/upper bound |
| |
| #include <catch2/catch.hpp> |
| |
| #include <random> |
| |
| // This class shows how to implement a simple generator for Catch tests |
| class RandomIntGenerator : public Catch::Generators::IGenerator<int> { |
| std::minstd_rand m_rand; |
| std::uniform_int_distribution<> m_dist; |
| int current_number; |
| public: |
| |
| RandomIntGenerator(int low, int high): |
| m_rand(std::random_device{}()), |
| m_dist(low, high) |
| { |
| static_cast<void>(next()); |
| } |
| |
| int const& get() const override; |
| bool next() override { |
| current_number = m_dist(m_rand); |
| return true; |
| } |
| }; |
| |
| // Avoids -Wweak-vtables |
| int const& RandomIntGenerator::get() const { |
| return current_number; |
| } |
| |
| // This helper function provides a nicer UX when instantiating the generator |
| // Notice that it returns an instance of GeneratorWrapper<int>, which |
| // is a value-wrapper around std::unique_ptr<IGenerator<int>>. |
| Catch::Generators::GeneratorWrapper<int> random(int low, int high) { |
| return Catch::Generators::GeneratorWrapper<int>(std::unique_ptr<Catch::Generators::IGenerator<int>>(new RandomIntGenerator(low, high))); |
| } |
| |
| // The two sections in this test case are equivalent, but the first one |
| // is much more readable/nicer to use |
| TEST_CASE("Generating random ints", "[example][generator]") { |
| SECTION("Nice UX") { |
| auto i = GENERATE(take(100, random(-100, 100))); |
| REQUIRE(i >= -100); |
| REQUIRE(i <= 100); |
| } |
| SECTION("Creating the random generator directly") { |
| auto i = GENERATE(take(100, GeneratorWrapper<int>(std::unique_ptr<IGenerator<int>>(new RandomIntGenerator(-100, 100))))); |
| REQUIRE(i >= -100); |
| REQUIRE(i <= 100); |
| } |
| } |
| |
| // Compiling and running this file will result in 400 successful assertions |