How to check if the test failed in Google Test TearDown()? - googletest

At the end of every "file based integration" test, I want to clear a temp folder of associated files.
If the test fails, I want to leave the files there, so I can review the unexpected output.
Is there a way in the Google Test TearDown to check if the test has failed?

Is there a way in the Google Test TearDown to check if the test has failed?
Yes, you can do that be querying ::testing::Test::HasFailure() in
the test cases of your fixture and using the result to tally failures in a counter member of
the fixture that can be queried in its TearDown(). An elementary example:
#include <gtest/gtest.h>
#include <iostream>
struct Fixture : public ::testing::Test {
virtual void SetUp() {
fails = 0;
}
virtual void TearDown() {
if (fails > 0) {
std::cerr << "Fixture::TearDown sees failures" << std::endl;
}
}
unsigned fails;
};
TEST_F(Fixture, foo) {
EXPECT_EQ(1,0);
fails += ::testing::Test::HasFailure();
}
TEST_F(Fixture, bar) {
EXPECT_EQ(1,1);
fails += ::testing::Test::HasFailure();
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
And output:
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from Fixture
[ RUN ] Fixture.foo
/home/imk/dev/so/gtest/main.cpp:19: Failure
Expected: 1
To be equal to: 0
Fixture::TearDown sees failures
[ FAILED ] Fixture.foo (0 sec)
[ RUN ] Fixture.bar
[ OK ] Fixture.bar (0 sec)
[----------] 2 tests from Fixture (0.001 sec total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (1 ms total)
[ PASSED ] 1 test.
[ FAILED ] 1 test, listed below:
[ FAILED ] Fixture.foo
1 FAILED TEST

Simplified and updated version of #mike-kinghan's answer.
Still using the ::testing::Test::HasFailure() but without the counter (it will always evaluate to 1 since the HasFailure() retuens a boolean)
#include <gtest/gtest.h>
#include <iostream>
struct Fixture : public ::testing::Test {
virtual void SetUp() {}
virtual void TearDown() {
if (::testing::Test::HasFailure()) {
std::cerr << "Fixture::TearDown sees failures" << std::endl;
} else {
std::cout << "Fixture::TearDown sees NO failures" << std::endl;
}
}
};
TEST_F(Fixture, foo) { EXPECT_EQ(0, 0); }
TEST_F(Fixture, bar) { EXPECT_EQ(1, 0); }
TEST_F(Fixture, car) { EXPECT_EQ(2, 2); }
TEST_F(Fixture, tar) { EXPECT_EQ(3, 0); }
Output:

Related

How to co_await for a change in a variable using boost coroutine ts?

Context
I build a webserver using boost coroutine ts, boost asio and boost beast.
There is a coroutine for reading and one for writing.
There is a message_to_send queue where messages get pushed to send to the user.
The writing coroutine checks if there is something in the message_to_send queue and sends it.
After sending the writing coroutine suspends itself for 100 milliseconds and checks again for something to write.
Problem
The writing coroutine is polling the message queue every 100 milliseconds. I like to find a solution without polling after some timer has fired.
Posible solution
Maybe ther is a solution to co_await the change of a variable. Maybe creating a async_wait_for_callback with "async_initiate"?
Code example
You can clone the project. Or use the complete example code posted here:
#include <algorithm>
#include <boost/asio.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/system_timer.hpp>
#include <boost/beast.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/bind/bind.hpp>
#include <boost/optional.hpp>
#include <chrono>
#include <cstddef>
#include <deque>
#include <exception>
#include <iostream>
#include <list>
#include <memory>
#include <set>
#include <stdexcept>
#include <string>
// TODO use cmake to find out if the compiler is gcc or clang
#include <coroutine> // enable if build with gcc
// #include <experimental/coroutine> //enable if build with clang
using namespace boost::beast;
using namespace boost::asio;
typedef boost::asio::use_awaitable_t<>::as_default_on_t<boost::asio::basic_waitable_timer<boost::asio::chrono::system_clock>> CoroTimer;
typedef boost::beast::websocket::stream<boost::beast::tcp_stream> Websocket;
using namespace boost::beast;
using namespace boost::asio;
using boost::asio::ip::tcp;
using tcp_acceptor = use_awaitable_t<>::as_default_on_t<tcp::acceptor>;
struct User
{
boost::asio::awaitable<void> writeToClient (std::weak_ptr<Websocket> &connection);
std::deque<std::string> msgQueue{};
std::shared_ptr<CoroTimer> timer{};
};
void
handleMessage (std::string const &msg, std::list<std::shared_ptr<User>> &users, std::shared_ptr<User> user)
{
std::cout << "please implement handle message" << std::endl;
user->msgQueue.push_back ("please implement handle message");
user->timer->cancel ();
}
boost::asio::awaitable<void>
User::writeToClient (std::weak_ptr<Websocket> &connection)
{
try
{
while (not connection.expired ())
{
timer = std::make_shared<CoroTimer> (CoroTimer{ co_await this_coro::executor });
timer->expires_after (std::chrono::system_clock::time_point::max () - std::chrono::system_clock::now ());
try
{
co_await timer->async_wait ();
}
catch (boost::system::system_error &e)
{
using namespace boost::system::errc;
if (operation_canceled == e.code ())
{
// swallow cancel
}
else
{
std::cout << "error in timer boost::system::errc: " << e.code () << std::endl;
abort ();
}
}
while (not msgQueue.empty () && not connection.expired ())
{
auto tmpMsg = std::move (msgQueue.front ());
std::cout << " msg: " << tmpMsg << std::endl;
msgQueue.pop_front ();
co_await connection.lock ()->async_write (buffer (tmpMsg), use_awaitable);
}
}
}
catch (std::exception &e)
{
std::cout << "write Exception: " << e.what () << std::endl;
}
}
class Server
{
public:
Server (boost::asio::ip::tcp::endpoint const &endpoint);
boost::asio::awaitable<void> listener ();
private:
void removeUser (std::list<std::shared_ptr<User>>::iterator user);
boost::asio::awaitable<std::string> my_read (Websocket &ws_);
boost::asio::awaitable<void> readFromClient (std::list<std::shared_ptr<User>>::iterator user, Websocket &connection);
boost::asio::ip::tcp::endpoint _endpoint{};
std::list<std::shared_ptr<User>> users{};
};
namespace this_coro = boost::asio::this_coro;
Server::Server (boost::asio::ip::tcp::endpoint const &endpoint) : _endpoint{ endpoint } {}
awaitable<std::string>
Server::my_read (Websocket &ws_)
{
std::cout << "read" << std::endl;
flat_buffer buffer;
co_await ws_.async_read (buffer, use_awaitable);
auto msg = buffers_to_string (buffer.data ());
std::cout << "number of letters '" << msg.size () << "' msg: '" << msg << "'" << std::endl;
co_return msg;
}
awaitable<void>
Server::readFromClient (std::list<std::shared_ptr<User>>::iterator user, Websocket &connection)
{
try
{
for (;;)
{
auto readResult = co_await my_read (connection);
handleMessage (readResult, users, *user);
}
}
catch (std::exception &e)
{
removeUser (user);
std::cout << "read Exception: " << e.what () << std::endl;
}
}
void
Server::removeUser (std::list<std::shared_ptr<User>>::iterator user)
{
users.erase (user);
}
awaitable<void>
Server::listener ()
{
auto executor = co_await this_coro::executor;
tcp_acceptor acceptor (executor, _endpoint);
for (;;)
{
try
{
auto socket = co_await acceptor.async_accept ();
auto connection = std::make_shared<Websocket> (std::move (socket));
users.emplace_back (std::make_shared<User> ());
std::list<std::shared_ptr<User>>::iterator user = std::next (users.end (), -1);
connection->set_option (websocket::stream_base::timeout::suggested (role_type::server));
connection->set_option (websocket::stream_base::decorator ([] (websocket::response_type &res) { res.set (http::field::server, std::string (BOOST_BEAST_VERSION_STRING) + " websocket-server-async"); }));
co_await connection->async_accept (use_awaitable);
co_spawn (
executor, [connection, this, &user] () mutable { return readFromClient (user, *connection); }, detached);
co_spawn (
executor, [connectionWeakPointer = std::weak_ptr<Websocket>{ connection }, &user] () mutable { return user->get ()->writeToClient (connectionWeakPointer); }, detached);
}
catch (std::exception &e)
{
std::cout << "Server::listener () connect Exception : " << e.what () << std::endl;
}
}
}
auto const DEFAULT_PORT = u_int16_t{ 55555 };
int
main ()
{
try
{
using namespace boost::asio;
io_context io_context (1);
signal_set signals (io_context, SIGINT, SIGTERM);
signals.async_wait ([&] (auto, auto) { io_context.stop (); });
auto server = Server{ { ip::tcp::v4 (), DEFAULT_PORT } };
co_spawn (
io_context, [&server] { return server.listener (); }, detached);
io_context.run ();
}
catch (std::exception &e)
{
std::printf ("Exception: %s\n", e.what ());
}
return 0;
}
EDIT: updated code based on sehe's idea which is marked as answer.
The classical threading solution would be a condition variable. Of course, that's not what you want - I see you even explicitly disabled ASIO threading. Good.
One way - short of providing an Asio service to implement this behaviour - would be to use timers to emulate condition variables. You could use timer that "never" expires (deadline is at timepoint::max()) and manually reset it to timepoint::min() (canceling any async_wait) or any time in the past to signify the condition. Then you can use Timer::async_wait with use_awaitable like you already know how.
Note that you still need to "manually" signal the change. This is what you want because anything else requires kernel process tracing support/hardware debugger facilities which require massive priviliges and tend to be very slow.
You might want to know about associating the use_awaitable as the default completion token for the executor bound to your timer. See e.g. the examples: https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/example/cpp17/coroutines_ts/echo_server_with_default.cpp (the HTML docs do NOT link these examples)

Member of b object can't write in SystemC

I got this error on SystemC, and I don't understand why. The error is:
'write': is not a member of
'sc_core::sc_in' ConsoleApplication1
'write': is not a member of 'sc_core::sc_in'
class "sc_core::sc_in" has no member "write"
class "sc_core::sc_in" has no member "write"
Here I put together the code.
#include<systemc.h>
SC_MODULE(prin) {
sc_in<bool> a;
void print() {
cout << "Hello World\n";
}
SC_CTOR(prin) {
SC_METHOD(print);
sensitive << a;
}
};
SC_MODULE(input) {
prin b;
void in() {
b.a.write(false);
wait();
b.a.write(true);
wait();
}
SC_CTOR(input) : b("sds"){
SC_THREAD(in);
}
};
int sc_main(int argc, char* argv[]) {
input prin1("pint");
sc_start();
return 0;
}
If the error seems confusing, here I put together the picture of my error:
The port "a" is an input port so cannot be written to. If you make it an output port then you can write to it. Also, the port is not bound so you will also get an error for that so I have bound a signal to it just so it compiles.
#include <systemc.h>
SC_MODULE(prin) {
sc_out<bool> a; //output port
sc_signal<bool> sig; //something to bind port a to
void print() {
cout << "Hello World\n";
}
SC_CTOR(prin) {
SC_METHOD(print);
sensitive << a;
a(sig); //bind port a to s signal
}
};
SC_MODULE(input) {
prin b;
void in() {
b.a.write(false);
wait();
b.a.write(true);
wait();
}
SC_CTOR(input) : b("sds"){
SC_THREAD(in);
}
};
int sc_main(int argc, char* argv[]) {
input prin1("pint");
sc_start();
return 0;
}
Then
g++ -file.cpp -lsystemc
./a.out
Gives me the output
SystemC 2.3.2-Accellera --- Apr 16 2018 00:15:03
Copyright (c) 1996-2017 by all Contributors,
ALL RIGHTS RESERVED
Hello World

Changing signal on every posedge of clock in SC_THREAD

I want to implement module, which when is called to work changes signal x the way below:
1 clk pos.edge : x = 0 // 1st phase
2 clk pos.edge : x = 0 // 2nd phase
3 clk pos.edge : x = 1 // 3rd phase
And then stops until called again.
I have function foo() in my module, which is called from main and allows thread work_foo() to execute on the posedge of clock.
I tried to do it this way (with wait()), and in some simple test it gives right wave, but it is an inappropriate way: my_module.h:
#include "systemc.h"
SC_MODULE (my_module)
{
sc_in <bool> clk;
sc_out <sc_logic> x;
sc_signal <bool> valid;
void foo()
{
valid = 1;
return;
}
void work_foo()
{
while (true)
{
if (valid == 1)
{ // foo() was called
if (phase == 0)
{
x = SC_LOGIC_0;
wait(); // waiting for the next tick
x = SC_LOGIC_0;
wait(); // waiting for the next tick
x = SC_LOGIC_1;
wait(); // waiting for the next tick
}
else
{
valid=0;
wait();
}
}
}
SC_HAS_PROCESS(my_module);
my_module(sc_module_name name):
sc_module(name),
clk("clk"), x("x"), valid("valid")
{
SC_THREAD(work_foo);
//dont_initialize();
sensitive<<clk.pos();
valid=0;
}
};
main.cpp:
#include "systemc.h"
#include "my_module.h"
int sc_main (int argc, char* argv[])
{
sc_clock clock("clock", 10, SC_NS);
sc_signal<sc_logic > x;
my_module mm("my_mod");
mm.clk(clock);
mm.x(x);
mm.foo ();
sc_start(200, SC_NS);
sc_stop();
return 0;
}
And now I'm trying to implement it another way. I was advised to use additional sc_signal (or variable) in my module, which indicates the incrementing number of the phase. The problem is what this gets looped at the very start. How can I solve this?
#include "systemc.h"
SC_MODULE (my_module)
{
sc_in <bool> clk;
sc_out <sc_logic> x;
sc_signal <bool> valid;
sc_signal <uint> phase;
void foo()
{
valid = 1;
return;
}
void work_foo()
{
while (true)
{
if (valid == 1)
{
if (phase == 0)
{
x = SC_LOGIC_0;
phase=phase+1;
}
else if (phase == 1)
{
x = SC_LOGIC_0;
phase=phase+1;
}
else if (phase == 2)
{
x = SC_LOGIC_1;
phase=phase+1;
}
}
else
{
phase=0;
valid=0;
wait();
}
}
}
SC_HAS_PROCESS(my_module);
my_module(sc_module_name name):
sc_module(name),
clk("clk"), x("x"), valid("valid")
{
SC_THREAD(work_foo);
//dont_initialize();
sensitive<<clk.pos();
valid=0;
phase=0;
}
};

Is MOCK_METHOD* not enough?

Inspired by that Google doc "ForDummies" :), I am trying a simple Google Mock with Google Test example as follows:
#include <gtest/gtest.h>
#include <gmock/gmock.h>
using ::testing::_;
class A
{
public:
A()
{
std::cout << "A()" << std::endl;
}
virtual ~A()
{
std::cout << "~A()" << std::endl;
}
virtual int incVirtual(int i)
{
return i + 1;
}
};
class MockA: public A
{
public:
MOCK_METHOD1(incVirtual, int(int));
};
TEST(Test, IncTest) {
MockA a;
EXPECT_CALL(a, incVirtual(_));
printf("n == %d\n", a.incVirtual(0));
}
int main(int argc, char **argv)
{
::testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}
When I run it, I get n == 0:
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from Test
[ RUN ] Test.IncTest
A()
n == 0
~A()
whereas I expect it to be n == 1. So I wonder if just defining MOCK_METHODx in the mock class is not enough for mocking the base class method and something additional needs to be done to make MockA::incVirtual call A::incVirtual?
This is behaving the way it should. By mocking your function, the MockA class has essentially overridden the A class implementation with a "do nothing" implementation.
If you want to call A::incVirtual() when calling MockA::incVirtual(), try the following
EXPECT_CALL(a, incVirtual(_)).WillOnce(Invoke(&a, &A::incVirtual));

DBus client and server in the same process

When I create a D-Bus server (via g_bus_own_name()) and the client to it (using g_dbus_proxy_new()) in the same process and then call g_dbus_proxy_call_sync(), it never returns. However, if server and client are in separate processes, everything is ok.
The following code illustrates my problem (I am using giomm C++ bindings here):
file main.cc:
#include <giomm.h>
#include <thread>
int server_main();
int client_main();
int main() {
Gio::init();
std::thread thr_server([](){ server_main(); });
sleep(1); // give some time to server to register
std::thread thr_client([](){ client_main(); });
sleep(10); // wait for the client to finish
}
file server.cc:
#include <giomm.h>
#include <iostream>
namespace {
static Glib::RefPtr<Gio::DBus::NodeInfo> introspection_data;
static Glib::ustring introspection_xml =
"<node name='/org/glibmm/DBusExample'>"
" <interface name='org.glibmm.DBusExample'>"
" <method name='Method'>"
" </method>"
" </interface>"
"</node>";
guint registered_id = 0;
}
static void on_method_call(const Glib::RefPtr<Gio::DBus::Connection>& /* connection */,
const Glib::ustring& /* sender */, const Glib::ustring& /* object_path */,
const Glib::ustring& /* interface_name */, const Glib::ustring& method_name,
const Glib::VariantContainerBase& parameters,
const Glib::RefPtr<Gio::DBus::MethodInvocation>& invocation)
{
if(method_name == "Method") {
std::cout << "Method was called\n";
}
}
const Gio::DBus::InterfaceVTable interface_vtable(sigc::ptr_fun(&on_method_call));
void on_bus_acquired(const Glib::RefPtr<Gio::DBus::Connection>& connection, const Glib::ustring& /* name */)
{
std::cout << "on_bus_acquired\n";
try {
registered_id = connection->register_object("/org/glibmm/DBusExample",
introspection_data->lookup_interface(),
interface_vtable);
}
catch(const Glib::Error& ex) {
std::cerr << "Registration of object failed." << std::endl;
}
return;
}
void on_name_acquired(const Glib::RefPtr<Gio::DBus::Connection>& /* connection */, const Glib::ustring& /* name */)
{}
void on_name_lost(const Glib::RefPtr<Gio::DBus::Connection>& connection, const Glib::ustring& /* name */) {
connection->unregister_object(registered_id);
}
int server_main()
{
try {
introspection_data = Gio::DBus::NodeInfo::create_for_xml(introspection_xml);
}
catch(const Glib::Error& ex) {
std::cerr << "Unable to create introspection data: " << ex.what() <<
"." << std::endl;
return 1;
}
const guint id = Gio::DBus::own_name(Gio::DBus::BUS_TYPE_SESSION,
"org.glibmm.DBusExample",
sigc::ptr_fun(&on_bus_acquired),
sigc::ptr_fun(&on_name_acquired),
sigc::ptr_fun(&on_name_lost));
//Keep the service running
auto loop = Glib::MainLoop::create();
loop->run();
Gio::DBus::unown_name(id);
return EXIT_SUCCESS;
}
file client.cc:
#include <giomm.h>
#include <iostream>
Glib::RefPtr<Glib::MainLoop> loop;
// A main loop idle callback to quit when the main loop is idle.
bool on_main_loop_idle() {
std::cout << "loop_idle\n";
loop->quit();
return false;
}
void on_dbus_proxy_available(Glib::RefPtr<Gio::AsyncResult>& result)
{
auto proxy = Gio::DBus::Proxy::create_finish(result);
if(!proxy) {
std::cerr << "The proxy to the user's session bus was not successfully "
"created." << std::endl;
loop->quit();
return;
}
try {
std::cout << "Calling...\n";
proxy->call_sync("Method");
std::cout << "It works!\n";
}
catch(const Glib::Error& error) {
std::cerr << "Got an error: '" << error.what() << "'." << std::endl;
}
// Connect an idle callback to the main loop to quit when the main loop is
// idle now that the method call is finished.
Glib::signal_idle().connect(sigc::ptr_fun(&on_main_loop_idle));
}
int client_main() {
loop = Glib::MainLoop::create();
auto connection =
Gio::DBus::Connection::get_sync(Gio::DBus::BUS_TYPE_SESSION);
if(!connection) {
std::cerr << "The user's session bus is not available." << std::endl;
return 1;
}
// Create the proxy to the bus asynchronously.
Gio::DBus::Proxy::create(connection, "org.glibmm.DBusExample",
"/org/glibmm/DBusExample", "org.glibmm.DBusExample",
sigc::ptr_fun(&on_dbus_proxy_available));
loop->run();
return EXIT_SUCCESS;
}
I compile the test with g++ -O2 -std=c++0x main.cc server.cc client.cc -o test $(pkg-config --cflags --libs giomm-2.4) and run:
./test
on_bus_acquired
Calling...
<it hangs>
However, when I change main.cc:
#include <giomm.h>
int server_main();
int client_main();
int main() {
Gio::init();
auto childid = fork();
if (childid == 0) {
server_main();
} else {
sleep(1);
client_main();
}
}
I get:
./test
on_bus_acquired
Calling...
Method was called
It works!
So call_sync() returns successfully.
I tried to exclude loops from server and client, and use a single-threaded main.cc:
#include <giomm.h>
#include <thread>
int server_main();
int client_main();
int main() {
Gio::init();
server_main();
client_main();
auto loop = Glib::MainLoop::create();
loop->run();
}
Nothing helps. The question is, what am I doing wrong? I want to use my d-bus server and client in one process.
I figured it out, the trick is to execute
Glib::VariantContainerBase result;
invocation->return_value(result);
in the end of on_method_call.