Search code examples
c++googletestundefined-behavior

How to avoid C++ undefined behavior fooling GoogleTest


I'm writing tests for my container class, and many of those tests check query methods, which return true or false. Example:

myContainer.add(obj);
EXPECT_TRUE(myContainer.contains(obj));

The problem is that many of those tests pass even without a MyContainer implementation.

I think that I already found what is the cause of this, and it is demonstrated below (problem is that RealityTest.Sneaky passes):

TEST(RealityTest, True) {
  bool b = true;
  EXPECT_TRUE(b);
  EXPECT_FALSE(b);
}
TEST(RealityTest, False) {
  bool b = false;
  EXPECT_TRUE(b);
  EXPECT_FALSE(b);
}
TEST(RealityTest, RandomBool) {
  bool b = random_bool();
  EXPECT_TRUE(b);
  EXPECT_FALSE(b);
}
TEST(RealityTest, Sneaky) {
  bool b = sneaky();
  EXPECT_TRUE(b);
  EXPECT_FALSE(b);
}
TEST(RealityTest, NoBool) {
  bool b = no_bool();
  EXPECT_TRUE(b);
  EXPECT_FALSE(b);
}

With functions used in tests defined like this:

bool random_bool() {
  static std::random_device dev;
  static std::uniform_int_distribution dist(0, 1);
  return dist(dev);
};

bool sneaky() { cout << "brought to you by GCC (C++17)" << endl; }

bool no_bool() {}

How should I write tests so that this "sneaky" mechanism can't fool them because as of right now, if I were to implement only things like MyContainer::add, MyContainer::get and MyContainer::remove then all my tests would pass despite the fact that all those query methods are not working.

Note: I build everything (tests and MyContainer) without any compiler optimizations (Debug mode in Qt Creator).

Note 2: I use Qt Creator but not any of Qt modules/libs. Just plain C++17 with googletest and pthread (I'm on Linux).


Solution

  • Your compiler should warn you that there are paths in your function that do not return a value. If it does not, increase your warning level (e.g. -Wall and/or -Wextra) and make sure those warnings are not supressed.

    In case you (or your coworkers) are prone to ignoring those warnings, use -Werror to turn them (well, all warnings) into compile errors - this way your project won't compile if there are things that trip those warnings, e.g. having a path that doesn't return a value.

    That said, GoogleTest can't help you find those errors - it only works with the compiled objects, so it can't tell your bool sneaky() function doesn't have a proper return value... Remember: Undefined behavior can result in time travel.. or allow b to be TRUE and FALSE at the same time