How to initialize constant string for multiple tests in google test? - tdd

I'm using google test and I have a cpp-file containing several tests. I would like to initialize a string with the current date and time when starting the first test. I would like to use this string in all other tests, too. How can I do this.
I've tried the following (m_string being a protected member of CnFirstTest), but it didn't work (since the constructor and SetUp will be called before each test):
CnFirstTest::CnFirstTest(void) {
m_string = currentDateTime();
}
void CnFirstTest::SetUp() {
}
TEST_F(CnFirstTest, Test1) {
// use m_string
}
TEST_F(CnFirstTest, Test2) {
// use m_string, too
}

You can use a gtest testing::Environment to achieve this:
#include <chrono>
#include <iostream>
#include "gtest/gtest.h"
std::string currentDateTime() {
return std::to_string(std::chrono::steady_clock::now().time_since_epoch().count());
}
class TestEnvironment : public ::testing::Environment {
public:
// Assume there's only going to be a single instance of this class, so we can just
// hold the timestamp as a const static local variable and expose it through a
// static member function
static std::string getStartTime() {
static const std::string timestamp = currentDateTime();
return timestamp;
}
// Initialise the timestamp.
virtual void SetUp() { getStartTime(); }
};
class CnFirstTest : public ::testing::Test {
protected:
virtual void SetUp() { m_string = currentDateTime(); }
std::string m_string;
};
TEST_F(CnFirstTest, Test1) {
std::cout << TestEnvironment::getStartTime() << std::endl;
std::cout << m_string << std::endl;
}
TEST_F(CnFirstTest, Test2) {
std::cout << TestEnvironment::getStartTime() << std::endl;
std::cout << m_string << std::endl;
}
int main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
// gtest takes ownership of the TestEnvironment ptr - we don't delete it.
::testing::AddGlobalTestEnvironment(new TestEnvironment);
return RUN_ALL_TESTS();
}

Related

copy constructor do not work in cpp template

I'm writing a test program about c++ type erasure, the code is put on the end.
when I run program , the test case 2 output as follow:
A default cstr...0x7ffe0fe5158f
obj_:0x7ffe0fe5158f objaaa 0x7ffe0fe5158f
Print A 0x7ffe0fe5158f
my machine: Linux x86-64, gcc 4.8
In my opinion, "Object obj2(a2);" makes a class Model by lvalue reference, so it should call A's copy constructor,
but actually it did not work, it makes me confused.
someone can give a explanation, thank you in advance.
the program is list as follow:
#include <memory>
#include <iostream>
class Object {
public:
template <typename T>
Object(T&& obj) : object_(std::make_shared<Model<T>>(std::forward<T>(obj))) {
}
void PrintName() {
object_->PrintName();
}
private:
class Concept {
public:
virtual void PrintName() = 0;
};
template <typename T>
class Model : public Concept {
public:
Model(T&& obj) : obj_(std::forward<T>(obj)) {
std::cout << "obj_:" << std::addressof(obj_) <<" objaaa " << std::addressof(obj) << std::endl;
}
void PrintName() {
obj_.PrintName();
}
private:
T obj_;
};
private:
std::shared_ptr<Concept> object_;
};
class A {
public:
A(A& a) {
std::cout<< "A copy cstr...a" << this << std::endl;
}
A(A&& a) {
std::cout << "A move cstr...." <<this<< std::endl;
}
A() {
std::cout << "A default cstr..." <<this<< std::endl;
}
void PrintName() {
std::cout << "Print A " << this << std::endl;
}
};
int main(void)
{
// test case 1
Object obj{A()};
obj.PrintName();
// test case 2
A a2;
Object obj2(a2);
obj2.PrintName();
return 0;
}
In Object obj2(a2);, no copy is made. T in the constructor of Object is deduced to be A&, so it instantiates Model<A&>, which stores a reference to the original a2 object as its obj_ member.
Observe that in your debug output, a2's constructor, Model's constructor and PrintName all print the same address. You can further confirm that this address is in fact &a2.

Future get() returns void for int returning member function

#include <functional>
#include <future>
#include <iostream>
class A
{
public:
int run(int a, const std::string& s)
{
std::cout << "a=" << a << ",s=" << s << std::endl;
return a+1;
}
};
int main()
{
A a;
auto f = std::bind(&A::run,&a,5,std::placeholders::_1);
std::packaged_task<int(const std::string&)> pt(std::move(f));
auto fut = std::async(std::move(pt),"test");
/// std::cout << fut.get() << std::endl; Does not compile
fut.get();
return 0;
}
Why fut.get() is returning void ? A::run is defined to return int and hence it should return int instead of void.
You are passing packaged_task instance to async, so return type for future is deduced based on:
std::packaged_task<R(Args...)>::operator()
void operator()( ArgTypes... args );
where void is returned.
If you want to get a result stored by packaged_task, you should read value stored by future returned by packaged_task::get_future:
A a;
auto f = std::bind(&A::run,&a,5,std::placeholders::_1);
std::packaged_task<int(const std::string&)> pt{std::move(f)};
std::future<int> fut = pt.get_future();
auto fut2 = std::async(std::move(pt),"test");
fut2.wait(); // wait until async's task is completed -> packaged_task was executed
std::cout << fut.get() << std::endl; // get result of packaged_task
Demo

Error in storing outer class object in inner class C++

I was implementing the ring buffer and have encountered an error. What does it mean to store a reference of outer class(class ring) object(m_ring) in inner class(class iterator) and when I remove the reference(&) the program compiles correctly but crashes. Please explain what is happening.(See the comment in Ring.h) Sorry for bad English.
// Ring.h
#ifndef RING.H
#define RING.H
#include <iostream>
using namespace std;
template<class T>
class ring {
unsigned int m_size;
int m_pos;
T *m_values;
public:
class iterator;
public:
ring(unsigned int size) : m_size(size), m_pos(0)
{
m_values = new T[m_size];
}
~ring()
{
delete[] m_values;
}
void add(const T &val)
{
m_values[m_pos] = val;
m_pos++;
m_pos %= m_size;
}
T& get(int pos)
{
return m_values[pos];
}
iterator begin()
{
return iterator(0, *this);
}
iterator end()
{
return iterator(m_size, *this);
}
};
template<class T>
class ring<T>::iterator {
int m_pos;
ring &m_ring; // Removing & gives garbage output.
public:
iterator(int pos, ring& aRing) : m_pos(pos), m_ring(aRing){}
bool operator!=(const iterator &other) const
{
return other.m_pos != m_pos;
}
iterator &operator++(int)
{
m_pos++;
return *this;
}
iterator &operator++()
{
m_pos++;
return *this;
}
T &operator*()
{
// return m_ring.m_values[m_pos];
return m_ring.get(m_pos);
}
};
#endif // RING
Driver program :
// Ring_Buffer_Class.cpp
#include <iostream>
#include "ring.h"
using namespace std;
int main()
{
ring<string> textring(3);
textring.add("one");
textring.add("two");
textring.add("three");
textring.add("four");
// C++ 98
for(ring<string>::iterator it = textring.begin(); it != textring.end(); it++)
{
cout << *it << endl;
}
cout << endl;
// C++11
for(string value : textring)
{
cout << value << endl;
}
return 0;
}
I also observed that removing ~ring() (Destructor) results into correct output.
Expected output :
four
two
three
four
two
three

What is the best way to pass callback function to std::map?

I was trying to work on the below code but the program crashes:
#include <iostream>
#include <string>
#include <map>
using namespace std;
typedef void (*callBackMethod)(string);
class CTest
{
private:
map<string, callBackMethod> mapMethod;
void testMethod(string msg)
{
cout << msg << endl;
}
public:
CTest()
{
addFunction("AA", (callBackMethod) &CTest::testMethod);
}
void addFunction(string funName, callBackMethod methodName)
{
mapMethod[funName] = methodName;
}
callBackMethod getMethod(string funName)
{
auto fun = mapMethod.find(funName);
if(fun == mapMethod.end()) { return nullptr; }
return fun->second;
}
void runFunction(string funName)
{
getMethod(funName)("test");
}
};
int main()
{
CTest test;
test.runFunction("AA");
return 0;
}
I have a requirement where I need to pass private methods to a map. The program compiles with warning:
converting from 'void (CTest::*)(std::__cxx11::string) {aka void (CTest::*)(std::__cxx11::basic_string<char>)}' to 'callBackMethod {aka void (*)(std::__cxx11::basic_string<char>)}'
and when I execute this, it crashes.
When I move the callback method outside of the class it works. My requirement is to make the program flow this was (hide the methods from external call which needs to be added to a map).
Looking forward to your comments.
If you need to point to both CTest member functions and free functions, then you can use std::function<void(std::string)>.
#include <iostream>
#include <string>
#include <map>
#include <functional>
using namespace std;
using callBackFunction = std::function<void(string)>;
void testFunction(string msg)
{
cout << "[" << __PRETTY_FUNCTION__ << "] " << msg << endl;
}
class CTest
{
private:
map<string, callBackFunction> mapMethod;
void testMethod(string msg)
{
cout << "[" << __PRETTY_FUNCTION__ << "] " << msg << endl;
}
public:
CTest()
{
addFreeFunction("AA", testFunction);
addMemberFunction("BB", &CTest::testMethod);
}
void addMemberFunction(string funName, void(CTest::*methodName)(string))
{
using std::placeholders::_1;
mapMethod[funName] = std::bind(methodName, this, _1);
}
void addFreeFunction(string funName, void(*methodName)(string))
{
mapMethod[funName] = methodName;
}
callBackFunction getMethod(string funName)
{
auto fun = mapMethod.find(funName);
if(fun == mapMethod.end()) { return nullptr; }
return fun->second;
}
void runFunction(string funName)
{
getMethod(funName)("test");
}
};
int main()
{
CTest test;
test.runFunction("AA");
test.runFunction("BB");
return 0;
}
Notice that CTest must insert elements into the map in a different way depending on what type of function you are passing, since for member functions you must provide the object for which it is to be invoked, this in this example. This is achived by using std::bind.
Since you want to use member variables you need to specify the signature differently in your typedef:
In C++ Builder the following can be done:
typedef void(__closure *callBackMethod)(string);
If you do that, I do suggest that you keep a smart pointer to the object that the member belongs to so that you can check if the object is still valid before calling the function otherwise it will crash the application.
The __closure keyword is a C++ Builder extension to work around the requirement to use fully qualified member names source
To handle both global and member functions we have the following:
typedef void(__closure *callBackMethodMember)(string);
typedef void (*callBackMethodGlobal)(string);
/* And then on 2 overloaded functions */
void addFunction(string funName, callBackMethodMember methodName) {}
void addFunction(string funName, callBackMethodGlobal methodName) {}

std::bind not able to call the class member function: C++

I have to implement A valve Open function (for specified duration).
I am using boost::asio::deadline_timer
My class member function to open valve is:
bool Valves::valveOpen(ValveType type)
{
switch (type)
{
case eVentValve:
tblMap_.digitalInput[eVentValveK1].setBit();
if (tblMap_.digitalOutput[eOutK1VentValve].getBit())
{
isVentOpen_ = true;
}
return isVentOpen_;
case eVacuumPumpValve:
....
....
}
Class member function to close the valve is:
bool Valves::valveClose(ValveType type)
{
switch (type)
{
case eVentValve:
tblMap_.digitalInput[eVentValveK1].clearBit();
if (!tblMap_.digitalOutput[eOutK1VentValve].getBit())
{
isVentOpen_ = false;
}
return !isVentOpen_;
case eVacuumPumpValve:
....
....
}
I am trying to achieve the timer action as below
bool Valves::valveTimedOpen(ValveType type, int sec)
{
boost::asio::io_service io;
switch (type)
{
case eVentValve:
{
std::bind(&Valves::valveOpen, this, type); //Here
boost::asio::deadline_timer t(io, boost::posix_time::seconds(sec));
t.async_wait(std::bind(&Valves::valveClose, this, type));
boost::thread th(boost::bind(&boost::asio::io_service::run, &io));
return true;
}
case eVacuumPumpValve:
.....
.....
}
The code hits the line Here i.e.
std::bind(&Valves::valveOpen, this, type); but it does not go to bool Valves::valveOpen(ValveType type) function.
Can someone let me know the issue with this code?
Variables io and t go out of scope as soon as valveTimedOpen exits. You need to rethink the way you interact with the boost asio components e.g. the io_service could be a member of your class, and the timer could be dynamically allocated and needs to be deleted in the completion handler.
Also, keep in mind that if you plan on re-using an io_service object, you also need to reset it before calling run again.
auto fn = std::bind(&Test::Open, shared_from_this(), std::placeholders::_1);
fn(type);
Calls the Open() correctly.
io_service and boost::deadline_timer I have to make class member as suggested by #Ralf
Working Code:
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread.hpp>
#include <boost/asio.hpp>
class Test : public std::enable_shared_from_this <Test>
{
public:
Test() :io(), timer(io){}
void Open(int num);
void Close(int num);
void TimedOpen(int num, int dur);
void Run();
private:
boost::asio::io_service io;
boost::asio::deadline_timer timer;
};
void Test::Open(int num)
{
std::cout << "Open for Number : " << num << std::endl;
}
void Test::Close(int num)
{
std::cout << "Close for Number : " << num << std::endl;
}
void Test::TimedOpen(int num, int dur)
{
io.reset();
auto fn = std::bind(&Test::Open, shared_from_this(), std::placeholders::_1);
fn(num);
timer.expires_from_now( boost::posix_time::seconds(dur));
timer.async_wait(std::bind(&Test::Close, shared_from_this(), num));
Run();
std::cout << "Function Exiting" << std::endl;
}
void Test::Run()
{
boost::thread th(boost::bind(&boost::asio::io_service::run, &io));
}
int main()
{
auto t = std::make_shared<Test>();
t->TimedOpen(5, 5);
char line[128];
while (std::cin.getline(line, 128))
{
if (strcmp(line, "\n")) break;
}
return 0;
}

Resources