300-Gen-OwnGenerator.cpp
1 2 // Copyright Catch2 Authors 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE.txt or copy at 5 // https://www.boost.org/LICENSE_1_0.txt) 6 7 // SPDX-License-Identifier: BSL-1.0 8 9 // 300-Gen-OwnGenerator.cpp 10 // Shows how to define a custom generator. 11 12 // Specifically we will implement a random number generator for integers 13 // It will have infinite capacity and settable lower/upper bound 14 15 #include <catch2/catch_test_macros.hpp> 16 #include <catch2/generators/catch_generators.hpp> 17 #include <catch2/generators/catch_generators_adapters.hpp> 18 19 #include <random> 20 21 namespace { 22 23 // This class shows how to implement a simple generator for Catch tests 24 class RandomIntGenerator : public Catch::Generators::IGenerator<int> { 25 std::minstd_rand m_rand; 26 std::uniform_int_distribution<> m_dist; 27 int current_number; 28 public: 29 30 RandomIntGenerator(int low, int high): 31 m_rand(std::random_device{}()), 32 m_dist(low, high) 33 { 34 static_cast<void>(next()); 35 } 36 37 int const& get() const override; 38 bool next() override { 39 current_number = m_dist(m_rand); 40 return true; 41 } 42 }; 43 44 // Avoids -Wweak-vtables 45 int const& RandomIntGenerator::get() const { 46 return current_number; 47 } 48 49 // This helper function provides a nicer UX when instantiating the generator 50 // Notice that it returns an instance of GeneratorWrapper<int>, which 51 // is a value-wrapper around std::unique_ptr<IGenerator<int>>. 52 Catch::Generators::GeneratorWrapper<int> random(int low, int high) { 53 return Catch::Generators::GeneratorWrapper<int>( 54 new RandomIntGenerator(low, high) 55 // Another possibility: 56 // Catch::Detail::make_unique<RandomIntGenerator>(low, high) 57 ); 58 } 59 60 } // end anonymous namespaces 61 62 // The two sections in this test case are equivalent, but the first one 63 // is much more readable/nicer to use 64 TEST_CASE("Generating random ints", "[example][generator]") { 65 SECTION("Nice UX") { 66 auto i = GENERATE(take(100, random(-100, 100))); 67 REQUIRE(i >= -100); 68 REQUIRE(i <= 100); 69 } 70 SECTION("Creating the random generator directly") { 71 auto i = GENERATE(take(100, GeneratorWrapper<int>(Catch::Detail::make_unique<RandomIntGenerator>(-100, 100)))); 72 REQUIRE(i >= -100); 73 REQUIRE(i <= 100); 74 } 75 } 76 77 // Compiling and running this file will result in 400 successful assertions