mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-04 05:59:32 +01:00 
			
		
		
		
	Add GENERATE_COPY and GENERATE_VAR capturing generator macros
This commit is contained in:
		@@ -8,41 +8,6 @@
 | 
			
		||||
 | 
			
		||||
#include <catch2/catch.hpp>
 | 
			
		||||
 | 
			
		||||
#include <random>
 | 
			
		||||
 | 
			
		||||
// Lets start by implementing a parametrizable double generator
 | 
			
		||||
class RandomDoubleGenerator : public Catch::Generators::IGenerator<double> {
 | 
			
		||||
    std::minstd_rand m_rand;
 | 
			
		||||
    std::uniform_real_distribution<> m_dist;
 | 
			
		||||
    double current_number;
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    RandomDoubleGenerator(double low, double high):
 | 
			
		||||
        m_rand(std::random_device{}()),
 | 
			
		||||
        m_dist(low, high)
 | 
			
		||||
    {
 | 
			
		||||
        static_cast<void>(next());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    double const& get() const override;
 | 
			
		||||
    bool next() override {
 | 
			
		||||
        current_number = m_dist(m_rand);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Avoids -Wweak-vtables
 | 
			
		||||
double const& RandomDoubleGenerator::get() const {
 | 
			
		||||
    return current_number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Also provide a nice shortcut for creating the generator
 | 
			
		||||
Catch::Generators::GeneratorWrapper<double> random(double low, double high) {
 | 
			
		||||
    return Catch::Generators::GeneratorWrapper<double>(std::unique_ptr<Catch::Generators::IGenerator<double>>(new RandomDoubleGenerator(low, high)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEST_CASE("Generate random doubles across different ranges",
 | 
			
		||||
          "[generator][example][advanced]") {
 | 
			
		||||
    // Workaround for old libstdc++
 | 
			
		||||
@@ -55,16 +20,12 @@ TEST_CASE("Generate random doubles across different ranges",
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
    // This will not compile (intentionally), because it accesses a variable
 | 
			
		||||
    // auto number = GENERATE(take(50, random(r.first, r.second)));
 | 
			
		||||
    
 | 
			
		||||
    // We have to manually register the generators instead
 | 
			
		||||
    // Notice that we are using value capture in the lambda, to avoid lifetime issues
 | 
			
		||||
    auto number = Catch::Generators::generate( CATCH_INTERNAL_LINEINFO,
 | 
			
		||||
        [=]{
 | 
			
		||||
            using namespace Catch::Generators;
 | 
			
		||||
            return makeGenerators(take(50, random(std::get<0>(r), std::get<1>(r))));
 | 
			
		||||
        }
 | 
			
		||||
    );
 | 
			
		||||
    // auto number = GENERATE(take(50, random(std::get<0>(r), std::get<1>(r))));
 | 
			
		||||
 | 
			
		||||
   // GENERATE_COPY copies all variables mentioned inside the expression
 | 
			
		||||
   // thus this will work.
 | 
			
		||||
    auto number = GENERATE_COPY(take(50, random(std::get<0>(r), std::get<1>(r))));
 | 
			
		||||
 | 
			
		||||
    REQUIRE(std::abs(number) > 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										41
									
								
								examples/311-Gen-CustomCapture.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								examples/311-Gen-CustomCapture.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
// 311-Gen-CustomCapture.cpp
 | 
			
		||||
// Shows how to provide custom capture list to the generator expression
 | 
			
		||||
 | 
			
		||||
// Note that using variables inside generators is dangerous and should
 | 
			
		||||
// be done only if you know what you are doing, because the generators
 | 
			
		||||
// _WILL_ outlive the variables. Also, even if you know what you are
 | 
			
		||||
// doing, you should probably use GENERATE_COPY or GENERATE_REF macros
 | 
			
		||||
// instead. However, if your use case requires having a
 | 
			
		||||
// per-variable custom capture list, this example shows how to achieve
 | 
			
		||||
// that.
 | 
			
		||||
 | 
			
		||||
#include <catch2/catch.hpp>
 | 
			
		||||
 | 
			
		||||
TEST_CASE("Generate random doubles across different ranges",
 | 
			
		||||
          "[generator][example][advanced]") {
 | 
			
		||||
    // Workaround for old libstdc++
 | 
			
		||||
    using record = std::tuple<double, double>;
 | 
			
		||||
    // Set up 3 ranges to generate numbers from
 | 
			
		||||
    auto r1 = GENERATE(table<double, double>({
 | 
			
		||||
        record{3, 4},
 | 
			
		||||
        record{-4, -3},
 | 
			
		||||
        record{10, 1000}
 | 
			
		||||
    }));
 | 
			
		||||
 | 
			
		||||
    auto r2(r1);
 | 
			
		||||
    
 | 
			
		||||
    // This will take r1 by reference and r2 by value.
 | 
			
		||||
    // Note that there are no advantages for doing so in this example,
 | 
			
		||||
    // it is done only for expository purposes.
 | 
			
		||||
    auto number = Catch::Generators::generate( CATCH_INTERNAL_LINEINFO,
 | 
			
		||||
        [&r1, r2]{
 | 
			
		||||
            using namespace Catch::Generators;
 | 
			
		||||
            return makeGenerators(take(50, random(std::get<0>(r1), std::get<1>(r2))));
 | 
			
		||||
        }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    REQUIRE(std::abs(number) > 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compiling and running this file will result in 150 successful assertions
 | 
			
		||||
 | 
			
		||||
@@ -47,6 +47,7 @@ set( SOURCES_IDIOMATIC_TESTS
 | 
			
		||||
    300-Gen-OwnGenerator.cpp
 | 
			
		||||
    301-Gen-MapTypeConversion.cpp
 | 
			
		||||
    310-Gen-VariablesInGenerators.cpp
 | 
			
		||||
    311-Gen-CustomCapture.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# main-s for reporter-specific test sources:
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user