Does C++ support parameterized function for testing purpose? - c++

I have a lengthy unit test code snippet that I want to run for two functions. I am wondering if there's a way to do this without copy and paste the code and only change the function name?
Say the test code looks like
int main(){
output1 = function(input1);
assert output1 == answer1;
output2 = function(input2);
assert output2 == answer2;
output3 = function(input3);
assert output3 == answer3;
......
outputN = function(inputN);
assert outputN == answerN;
}
Now say I have two function func1 and func2. I want to ran literally the same test for func1 and func2. I am wondering if there's a neat way to do this in C++ without involving some test framework? Thanks in advance for any help.

You can make a function template:
template <typename F, typename R, typename Args...>
void test_func(F f, R&& r, Args&&... args) {
auto output = f(std::forward<Args>(args)...);
assert(output == std::forward<R>(r));
}
then use it like
test_func(&func1, answer1, input1);
test_func(&func2, answer2, input2);
...
Additional explanations:
The parameters and return value are passed by forwarding reference, then their value categories will be reserved when being passed to the function (with the usage of std::forward).
The parameters is declared as parameter pack then you can pass multiple ones with any types.

C++ supports passing parameters to functions ;).
You can pass functions to functions. To keep it simple, I am assuming that all functions you want to test have the same signature. To avoid verbose syntax of function pointers I'd use a template:
template <typename F>
void test_function(F f, std::vector<input_type> input,std::vector<output_type> expected) {
for (size_t i = 0; i < input.size(); ++i) {
assert( f(input[i]) == expected[i]);
}
}
int main() {
test_function( func1, {1,2,3},{2,3,4} );
test_function( func2, {1,2,3},{6,7,8} );
}
PS: From my own experience I can tell you that it isn't worth to put much work into hand-written test facilities. You will find yourself wanting more and more features that a test framework offers out of the box (eg logging test reports). Googletest is something I can recommend.

A solution of C methed is to use fuction pointer. But I recommand lambda fuction pulished in c++11. u can use as follow:
template<typename Func>
void test(intput in, output out, Func func) {
answer = func(in);
assert(out == answer);
}
void main() {
intput intput1;
output output1;
test(input1, output1, [&](intput in)->output{return func1(in)});
test(input1, output1, [&](intput in)->output{return func2(in)});
}
After all, u should add compile para:-std=c++11 while using g++ compiler.

Here's my new take, this should compile. It's built in layers so you can see how to expand each layer as you see fit. It doesn't work exactly as your example does, there are copies being made of your input data and there is no assignment operation for the output. You should take these into account and adjust accordingly (if required).
// Example program
#include <functional>
#include <assert.h>
#include <vector>
#include <utility>
// function to test
int func1(int p_param)
{
return p_param;
}
// function to test
int func2(int p_param)
{
return p_param;
}
// Test runner base
template <typename TFunction, typename TInput, typename TOutput>
void test_runner(TFunction f, std::vector < std::pair<TInput, TOutput> > p_testparameters)
{
for (auto pair : p_testparameters)
{
assert(f(pair.first) == pair.second);
}
}
// Specific test 1
template <typename TFunction>
void test1(TFunction f)
{
test_runner<TFunction, int, int>(f, { {1,1},{2,2},{3,3} });
}
// Specific test 2
template <typename TFunction>
void test2(TFunction f)
{
test_runner<TFunction, int, int>(f, { {10,10},{20,20},{30,30} });
}
// Run tests for function
template <typename TFunction>
void runTests(TFunction f)
{
test1(f);
test2(f);
}
int main() {
runTests(func1);
runTests(func2);
return 0;
}

Related

Generate argument names from list of types to forward to another function

I would like to generate a function that forwards its arguments to another function. I know that std::function does it somehow, but I cannot seem to find the right syntax myself.
It would be ok for my usecase to use som kind of template magic, but i want
the user to be able to get information on the calling types when they use the function, like std::function does.
My usecase uses class member functions, so a solution that only works in that context is accepted. I tried to created the smallest example code possible.
#include <iostream>
// Macro usage cannot be changed
#define ARGS int, int
void otherFunction(int x, int y) {
std::cout << x << "," << y << "\n";
}
// This is the behaviour i want
void expectedImplementation(int _1, int _2) {
otherFunction(_1, _2);
}
// This works, but it prevents the user to view the expected
// types in their IDE
template <typename ...Args>
void templateVersion(Args ... args) {
otherFunction(args...);
}
// This is the version I cannot get to work
// It does not need to look like this, but it needs to get
// its argument types from
//void func(ARGS) {
// otherFunction(/*how?*/);
//}
int main() {
expectedImplementation(1, 2);
templateVersion(1, 2);
//func(1, 2);
}
godbolt
How do I accomplish this?
Edit:
The function that needs to be forwarded to is also different for each instance of the function.
Edit 2:
Ok, It seems like it's hard to specify the context without the context. Here is the actual code that I want to generalize. Here Is the template magick stuff where it should fit in. No memory should be used, otherwise I would just use the solution I have now with template parameter packs.
Edit 3:
A better example:
#include <iostream>
#define ARGS int, int
struct Inner {
void otherFunction(int x, int y) {
std::cout << x << y << std::endl;
}
};
struct Wrapper {
Inner inner;
// This works, but it prevents the user to view the expected
// types in their ide
template <typename ...Args>
void templateVersion(Args ... args) {
inner.otherFunction(args...);
}
// The concept I try to figure out
void function(ARGS) { // It does not need to look exactly like this
// , but functionally it needs to be somithing like it
// Forward the arguments to the `ìnner` class
}
};
int main() {
auto wrapper = Wrapper{};
wrapper.templateVersion(10, 20);
}
Your macro ARGS does not define named arguments. You cannot forward the type of unnamed arguments. That's a limitation of the language.
Either forget about using macros, and change your function definiton:
void func(int a, int b) {
otherFunction(a, b);
}
Or change the definition of the macro:
#define ARGS int a, int b
void func(ARGS) {
otherFunction(a, b);
}
That said, nothing beats the template solution. Make sure you use perfect forwarding.
template <typename ...Args>
void templateVersion(Args&& ... args) {
otherFunction(std::forward<Args>(args)...);
}

Is it possible to implement log once in C++20 without macros?

What I am looking for is the log function that will log message, but only once per call site.
It would be useful to log first occurrence of an error, timeout, etc, without spamming the cout/log files.
Traditionally it has been implemented with macros(where they expand to some static bool/counter, you can see LOG_FIRST_N in glog for details), but I wonder if in C++20 it can be done without macros.
What I have tried:
Use std::source_location as template param, based on this answer, does not work since magic of std::source_location::current() does not work as I want it to work.
note: I know I can have one static std::set/std::unordered_set of call sites, but I am interested in solutions that is as efficient as the evil MACRO solution.
As every lambda expression is of different type, you can use lambda expressions to tag calls to the same function.
For example this:
#include <iostream>
template <typename T,typename F>
void once(T t, F f){
static bool first = true;
if (first) {
f();
first = false;
}
}
int main(){
for (int i=0; i <1000; ++i){
once([](){},[](){ std::cout << "A";});
}
for (int i=0; i <1000; ++i){
once([](){},[](){ std::cout << "B";});
}
}
Prints
AB
However, once([](){},... is a bit unwieldy and it is still tempting to use a macro.
PS: As mentioned in a comment, since C++20 the lambda can be used as default argument for the template and even before you can do:
#include <iostream>
template <typename F,typename T>
void once_impl(F f, T t){
static bool first = true;
if (first) {
f();
first = false;
}
}
template <typename F>
void once(F f) { once_impl(f,[](){});}
int main(){
for (int i=0; i <1000; ++i){
once([](){ std::cout << "A";});
}
for (int i=0; i <1000; ++i){
once([](){ std::cout << "B";});
}
}
if(error)
static const bool error_logged=error_log << "message\n";
the first time error is true, the stream will be written to. Every other time, nothing. It is thread safe; if 2 threads both have the error, it is guaranteed exactly one runs the log code.
error_logged will store true if the write worked, false otherwise.
C++ does not have a way to inject state to the calling location from within a function call (barring coroutines, which are not zero cost). So the state -- "have I called this before, here" -- must be at the calling site.
The amount of state required is minimal; as you can see above, a branch plus a static local is enough.
The evil macros are usually more complex because they want to be usable in more complicated structures, like:
return a?b:(log("error!"), c);
You might wrap the logic in template, and in C++20, lambda can be used as default template argument:
So you might do
template <typename F, typename Tag = decltype([](){})>
// or template <typename F, auto Tag = [](){}>
void simple_do_once(F f /*, Tag={}*/ )
{
static std::once_flag flag;
std::call_once(flag, f);
}
Demo

How to initialize a boost rolling window accumulator?

I would like to initialize a boost rolling window accumulator without having to do an assignment inside a function call.
This is what I see everyone do:
boost::accumulators::accumulator_set<double, boost::accumulators::stats<boost::accumulators::tag::rolling_mean>> acc(boost::accumulators::tag::rolling_window::window_size = 10);
How could I make the same accumulator without having the assignment inside the constructor call above?
It's not an assignment, it's a named-argument idiom. C++ doesn't have that, really, so this why it looks like an assignment: it's an Expression Template
You could of course figure out the type and use it, but that would not make any difference and just make it harder to use the library correctly:
boost::parameter::aux::tagged_argument_list_of_1<
boost::parameter::aux::tagged_argument<
boost::accumulators::tag::rolling_window_size_<0>, const int>>
init(10);
ba::accumulator_set<double, ba::stats<ba::tag::rolling_mean>> acc(init);
I don't know about you, but I prefer the named-argument expression.
You can obviously write a helper function to remove the library details:
auto make_accum(int window) {
return ba::accumulator_set<
double,
ba::stats<ba::tag::rolling_mean>> (ba::tag::rolling_window::window_size = window);
}
int main() {
auto acc = make_accum(10);
}
This simply made the named argument into a positional argument using the knowledge about the statistics in in your set.
If you're worried about generic code, just pass the expression as the initializer in generic cases. That's how the library istelf is implemented:
template <typename Stats, typename... Init> auto generic_accum(Init const&... init) {
return ba::accumulator_set<double, Stats> (init...);
}
Demo All 3 Approaches
Live On Coliru
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
#include <boost/accumulators/statistics/rolling_mean.hpp>
namespace ba = boost::accumulators;
template <typename Stats, typename... Init> auto generic_accum(Init const&... init) {
return ba::accumulator_set<double, Stats> (init...);
}
auto make_accum(int window) {
return ba::accumulator_set<
double,
ba::stats<ba::tag::rolling_mean>> (ba::tag::rolling_window::window_size = window);
}
int main() {
{
boost::parameter::aux::tagged_argument_list_of_1<
boost::parameter::aux::tagged_argument<
boost::accumulators::tag::rolling_window_size_<0>, const int>>
init(10);
ba::accumulator_set<double, ba::stats<ba::tag::rolling_mean>>
acc(init);
}
{
auto acc = make_accum(10);
}
{
auto acc = generic_accum<ba::stats<ba::tag::rolling_mean>>(ba::tag::rolling_window::window_size = 10);
}
}

get analysis result with LLVM LegacyPassManager

I'm currently writing a program that uses LLVM but is not a pass itself. For that, I want to utilize several analysis passes but not from a pass context.
As a concrete example I want to use the RegionInfo information that the RegionInfoPass can give me.
Now I have seen that LLVM has two PassManagers, a new one and an old one. If I get it right, the extraction of the RegionInfo -- given the new PassManager -- should be working with the following code (more less) (source):
void called_from_out_of_llvm(llvm::Function& f) {
llvm::PassBuilder pb;
llvm::FunctionAnalysisManager fam;
pb.registerFunctionAnalyses(fam);
llvm::RegionInfo& ri = fam.getResult<llvm::RegionInfoPass>(f);
}
However, this does not work since RegionInfoPass is an old pass so it has to be used with the old PassManager.
As far as I can see, the only way to retrieve analysis results with the old PassManager is to call getAnalysis<Pass> within another pass. Therefore I tried to create a wrapper pass and call it:
#include <llvm/Analysis/RegionInfo.h>
#include <llvm/IR/LegacyPassManager.h>
#include <cassert>
template <typename P, typename Result>
class AnalysisResult;
/* This implements a dummy pass that retrieves the requested analysis and
* "leaks" it to the AnalysisResult instances which creates the pass.
*/
template <typename P, typename Result>
struct Extractor : public llvm::FunctionPass {
AnalysisResult<P, Result>& result;
std::function<Result&(P*)> analysis_func;
static char ID;
Extractor(AnalysisResult<P, Result>& result, std::function<Result&(P*)> analysis_func) : llvm::FunctionPass(ID), result(result), analysis_func(analysis_func) {}
virtual void getAnalysisUsage(llvm::AnalysisUsage& au) const override { au.addRequired<P>(); }
bool runOnFunction(llvm::Function& func) override {
P& p = getAnalysis<P>();
Result& res = analysis_func(&p);
result.result = &res;
return false;
}
};
template <typename P, typename Result>
char Extractor<P, Result>::ID = 0;
/* This constructs the legacy PassManager, add the dummy pass from above and runs it. */
template <typename P, typename Result>
struct AnalysisResult {
llvm::legacy::FunctionPassManager fpm;
std::function<Result&(P*)> analysis_func;
Result* result = nullptr;
AnalysisResult(llvm::Function& func, std::function<Result&(P*)> f) : fpm(func.getParent()), analysis_func(f) {
fpm.add(new Extractor<P, Result>(*this, analysis_func));
fpm.doInitialization();
fpm.run(func);
}
~AnalysisResult() { fpm.doFinalization(); }
Result& get_result() {
assert(result != nullptr);
return *result;
}
};
/* This is just a convenience function that tries to mimic the interface of the new PassManager */
template <typename P, typename Result>
AnalysisResult<P, Result> getLLVMAnalysis(llvm::Function& func, std::function<Result&(P*)> f) {
// afaik this moves implicitly
return AnalysisResult<P, Result>(func, f);
}
/* getRegionInfo is overloaded so provide this as wrapper to
* make the function pointer cast to std::function possible
*/
RegionInfo& dummy_function(RegionInfoPass* rip) {
return rip->getRegionInfo();
}
/* The actual program function that uses all of the above helper constructs. */
void called_from_out_of_llvm(llvm::Function& f) {
llvm::PassRegistry& registry = *llvm::PassRegistry::getPassRegistry();
initializeAnalysis(registry);
AnalysisResult<RegionInfoPass, RegionInfo> ar = getLLVMAnalysis<RegionInfoPass, RegionInfo>(f, dummy_function);
RegionInfo& ri = ar.get_result();
ri.view(); // this segfaults
}
The problem with this code is that it segfaults when I want to use the analysis result. I'm not really sure why this happens, but it seems that the analysis result gets deleted directly in the fpm.run() function. However, replacing fpm.run() is not trivial (I thought of subclassing) because it is implemented with PImpl in an non public subclass.
Can you give me a hint if it is possible to run an analysis pass and use the result out of a pass context?

boost::bind with null function pointers

If the function pointer embedded in a boost::bind return object is NULL/nullptr/0, I need to take action other than calling it. How can I determine if the object contains a null function pointer?
Addenda
I don't believe I can use and compare boost::functions as the boost::bind return object is used with varying call signatures in a template function.
Simplified example:
template <typename BRO>
Retval do_stuff(BRO func, enum Fallback fallback)
{
if (func == NULL)
{
return do_fallback(fallback);
}
else
{
return use_retval(func());
}
}
do_stuff(boost::bind(FuncPtrThatMightBeNull, var1, var2), fallback);
Solution
Since the arity of the function in the callee does not change, I can "cast" the bind return object into a boost::function and call .empty()
Retval do_stuff(boost::function<Retval()> func, enum Fallback fallback)
{
if (func.empty())
return do_fallback(fallback);
else
return use_retval(func());
}
You can either bind to a dummy function:
void dummy() { /* has differing behaviour */ }
// ...
boost::bind(&dummy)();
... or, assuming you're using Boost.Bind together with Boost.Function, return a default constructed function object and check for empty() before calling it:
typedef boost::function<void (void)> F;
F create() { return F(); }
void use() {
F f = create();
if(f.empty()) {
/* ... */
}
}
Regarding the update:
I still don't see what the problem with binding to a different function like the following would be:
template <typename BRO>
Retval do_stuff(BRO func)
{
return func();
}
if(funcPtr) {
do_stuff(boost::bind(&use_retval, boost::bind(funcPtr, a, b)));
} else {
do_stuff(boost::bind(&do_fallback, fallback));
}
If you'd want to move that handling out of the calling code, you could emulate variadic template function to support variable arities:
template<class R, class T1>
boost::function<R (T1)>
bind_wrap(R (*fnPtr)(), T1& t1, Fallback fallback) {
if(fnPtr) return boost::bind(&use_retval, boost::bind(funcPtr, t1));
else return boost::bind(&do_fallback, fallback);
}
template<class R, class T1, class T2>
boost::function<R (T1, T2)>
bind_wrap(R (*fnPtr)(T1, T2), T1& t1, T2& t2, Fallback fallback) {
if(fnPtr) return boost::bind(&use_retval, boost::bind(funcPtr, t1, t2));
else return boost::bind(&do_fallback, fallback);
}
// ... etc. for all needed arities
do_stuff(bind_wrap(funcPtr, var1, var2, fallback));
... or you use the approach above to generate boost::function<> objects or your own wrappers and check for functor.empty() or similar in do_stuff().
I'd create a wrapper object to do this. Something like the following
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
int aFunction(int i, int j)
{
std::cout<<"In a Function"<<std::endl;
return i+j;
}
struct DefaultingFromFnPtr : public boost::function< int(int,int) >
{
explicit DefaultingFromFnPtr( int(*fn)(int,int) ) : fn_(fn) {}
int operator()(int i, int j) const
{
if (fn_!=NULL) return fn_(i, j);
return 7;
}
int(*fn_)(int,int);
};
template<typename T>
void do_stuff( T t )
{
std::cout<<"RETURNED "<<t()<<std::endl;
}
int main( int argv, const char** argc)
{
int(*mightBeNullFnPtr)(int,int) = NULL;
if( argv>1)
{
mightBeNullFnPtr = & aFunction;
}
int var1 = 10;
int var2 = 20;
do_stuff( boost::bind( DefaultingFromFnPtr( mightBeNullFnPtr ), var1, var2 ) );
}
Compile this and run it with no arguments and it sets mightBeNullFnPtr to NULL and calls do_stuff with a wrapper class, and so prints out 7. Run it with an argument and it will set mightByNullFnPtr to aFunction and calls do_stuff with that, printing out 30.
If you want more genericity you will need to template the DefaultingFromFnPtr wrapper class, but that should be pretty easy to do.
I'm pretty sure calling boost::bind with a null pointer (= the creation of the bind object) should be considered undefined behavior, even if the crash only happens when calling it.
You're going to have to hack boost.
boost::bind returns unspecified-n-n. The only thing valid to do with these classes is operator(). The only other thing you know is that they are copy constructable, and have a typedef for result_type (which, by the way, means you don't need a template for result type).
You want something else - so you'll need to find the definition of unspecified-n-n in boost (there maybe several), hack them to have a is_null() member function which checks for the conditions you want, then call that as your test.
This is, of course, assuming you are certain you'll always get a boost::bind'ed object in your template function. If someone tries passing in a regular function pointer, it won't compile. Working around this will require some template magic.