Context
I am writing a function which calculates some exponential value for a timer application. It simply takes 2^x until some threshold maxVal, in which case the threshold should be returned. Also, in all cases, edge cases should be accepted.
util.cpp:
#include "util.h"
#include <iostream>
int calculateExponentialBackoffDelay(int x, int maxVal)
{
int y;
if(x <= 0 || maxVal <= 0) return maxVal;
else if (x > maxVal) return maxVal;
y = std::pow(2, x);
std::cout << "y = " << y << std::endl;
if(y > maxVal) return maxVal;
else if(y < 0) return maxVal;
else return y;
}
Now I make a CMake configuration with a GoogleTest dependency fetch.
CMakeLists.txt:
cmake_minimum_required(VERSION 3.14)
project(my_project)
# GoogleTest requires at least C++14
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_BUILD_TYPE Release)
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.12.1
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
enable_testing()
include_directories(
${CMAKE_CURRENT_LIST_DIR}/
)
# Add the main source compilation units
add_executable(
test_calc
test_calc.cpp
util.cpp
)
target_link_libraries(
test_calc
GTest::gtest_main
)
include(GoogleTest)
gtest_discover_tests(test_calc)
I run a test on the function that I have written which tests some boundary conditions. One of which is testing that if 2^x > maxVal, then maxVal should just be returned (because the result of the 2^x is above the maximum value). This is the threshold.
test_calc.cpp:
#include "util.h"
#include <climits>
#include <gtest/gtest.h>
TEST(util_tests, ExponentialBackoff)
{
int x, maxVal, res;
// Test x = maxVal and maxVal = 1000
// Expected output: 1000
maxVal = 1000;
x = maxVal;
EXPECT_EQ(maxVal, calculateExponentialBackoffDelay(x, maxVal));
}
When I set x and maxVal to 1000, 2^(1000) is calculated and because it's such a big number, there is an overflow / wraparound to a really negative number (-2147
483`648). That is expected, and therefore my test will expect the result of x=1000, maxVal=1000 to be < 0.
Problem
This is where things go unexpectedly. I run ctest inside my build directory and all test cases pass. Then I change one line in CMakeLists.txt from ... :
set(CMAKE_BUILD_TYPE Debug)
... to ...
set(CMAKE_BUILD_TYPE Release)
... and that test case fails:
1: Expected equality of these values:
1: maxVal
1: Which is: 1000
1: calculateExponentialBackoffDelay(x, maxVal)
1: Which is: -2147483648
So for some reason, the case where y < 0 inside the function body is not being reached and instead, we are returning the wraparound result.
Why is this? What am I doing wrong? I tried using the Linux strip -s test_calc
to check if it was a symbols thing while keeping the debug configuration in CMake, only to find that test cases still pass. What else does CMake do to change the comparison behaviour of the resulting binary?