Reputation: 132
I am beginner to gtest. I trying to use ASSERT_THROW will compilation fail. Could anyone help on this:
class my_exp {};
int main(int argc, char *argv[])
{
EXPECT_THROW(throw my_exp(), my_exp); // this will pass
// This will through below compilation error
ASSERT_THROW(throw my_exp(), my_exp);
return 0;
}
Compilation output:
ERROR :
In file included from /usr/include/gtest/gtest.h:57:0,
from gtest.cpp:1:
gtest.cpp: In function ‘int main(int, char**)’:
gtest.cpp:12:3: error: void value not ignored as it ought to be
ASSERT_THROW(throw my_exp(), my_exp);
^
Upvotes: 6
Views: 10080
Reputation: 5958
Short version
You write test in the wrong way, to write test you should put assertion inside test (macro TEST
) or test fixtures (macro TEST_F
).
Long version
1 . What's really happens?
To find out the real problem is not easy because the Google Testing Framework use macros which hide real code. To see code after macro substitution is required to perform preprocessing, something like this:
g++ -E main.cpp -o main.p
The result of preprocessing when using ASSERT_THROW
will be looks like this (after formatting):
class my_exp {};
int main(int argc, char *argv[])
{
switch (0)
case 0:
default:
if (::testing::internal::ConstCharPtr gtest_msg = "") {
bool gtest_caught_expected = false;
try {
if (::testing::internal::AlwaysTrue () ) {
throw my_exp ();
};
} catch (my_exp const &) {
gtest_caught_expected = true;
} catch (...) {
gtest_msg.value = "Expected: throw my_exp() throws an exception of type my_exp.\n Actual: it throws a different type.";
goto gtest_label_testthrow_7;
} if (!gtest_caught_expected) {
gtest_msg.value = "Expected: throw my_exp() throws an exception of type my_exp.\n Actual: it throws nothing.";
goto gtest_label_testthrow_7;
}
}
else
gtest_label_testthrow_7:
return ::testing::internal::AssertHelper (::testing::TestPartResult::kFatalFailure, "main.cpp", 7, gtest_msg.value) = ::testing::Message ();
return 0;
}
For EXPECT_THROW
result will be the same except some difference:
else
gtest_label_testthrow_7:
::testing::internal::AssertHelper (::testing::TestPartResult::kNonFatalFailure, "main.cpp", 7, gtest_msg.value) = ::testing::Message ();
2 . OK, the reason of different behaviour is found, let's continue.
In the file src/gtest.cc can be found AssertHelper
class declaration including assignment operator which return void
:
void AssertHelper::operator=(const Message& message) const
So now reason of the compiler complain is clarified.
3 . But why this problem is caused is not clear. Try realise why for ASSERT_THROW
and EXPECT_THROW
different code was generated. The answer is the macro from file include/gtest/internal/gtest-internal.h
#define GTEST_FATAL_FAILURE_(message) \
return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
#define GTEST_NONFATAL_FAILURE_(message) \
GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
which contain return
for fatal case.
4 . But now is question why this assertions usually works well?
To answer of this question try investigate code snipped which written in correct way when assertion is placed inside test:
#include <gtest/gtest.h>
class my_exp {};
TEST (MyExp, ThrowMyExp)
{
ASSERT_THROW (throw my_exp (), my_exp);
}
To exclude pollution of the answer I just notice that in such case the return
statement for ASSERT_THROW
also exist, but it is placed inside method:
void MyExp_ThrowMyExp_Test::TestBody ()
which return void
! But in your example assertions are placed inside main
function which return int
. Looks like this is source of problem!
Try prove this point with simple snippet:
void f1 () {};
void f2 () {return f1();};
//int f2 () {return f1();}; // error here!
int main (int argc, char * argv [])
{
f2;
return 0;
}
5 . So the final answer is: the ASSERT_THROW
macro contain return statement for expression which evaluates to void
and when such expression is placed into function which return non void value the gcc complain about error.
P.S. But anyway I have no idea why for one case return is used but for other case is not.
Update: I've asked this question on GitHub and got the following answer:
ASSERT_XXX is used as a poor man's exception to allow it to work in environments where exceptions are disabled. It does a return; instead. It is meant to be used from within the TEST() methods, which return void.
Update: I've just realised that this question described in the official documentation:
By placing it in a non-void function you'll get a confusing compile error > like "error: void value not ignored as it ought to be".
Upvotes: 17