1

I have a following test case where I want to compare bytes in google test. In Unity unit test frame work we have

TEST_ASSERT_BYTES_EQUAL(0xaa, output[4]);

Is similar ASSERT available in google test. I have following code in google test and test case failing.

TEST(sprintf, NoBufferOverRunsForNoFormatOperations) {
    char output[5];
    memset(output, 0xaa, sizeof output);
    ASSERT_EQ(3, sprintf_s(output, "hey"));
    ASSERT_STREQ("hey", output);
    ASSERT_THAT(0xaa, output[4]);
}

Failed log

[ RUN      ] sprintf.NoBufferOverRunsForNoFormatOperations
 Value of: 0xaa
Expected: is equal to -86
  Actual: 170 (of type int)
[  FAILED  ] sprintf.NoBufferOverRunsForNoFormatOperations (0 ms)

Any clues and help are welcome.

venkysmarty
  • 11,099
  • 25
  • 101
  • 184
  • Your char is signed, can hold values in the range [-128, 127], 0xaa is signed value overflow and UB. – 273K May 06 '22 at 05:34

1 Answers1

1

The problem is that you are comparing 0xaa, a literal of type int with a value of decimal 170, with the value of output[4] which is itself of type char. char is a signed type in C and C++. You wrote 0xaa or binary 10101010 into the byte in question. Because it is interpreted as a signed number, the leading 1 is considered as the sign bit in two's complement (which is undefined behavior up until C++20 I think) which gives it a value of -86 = 170 - 256.

Jonas Greitemann
  • 1,011
  • 10
  • 25
  • Thanks @Jonas for explanation. Are you aware how can I overcome this problem in google test framework. – venkysmarty May 06 '22 at 05:40
  • If it wasn't clear, this problem is not a problem with Google Test. The same problem would occur when comparing the two values in an if statement. You can avoid this problem by doing an `reinterpret_cast` to tell the compiler that you really want to view the memory pointed to by `output` as if it was a pointer to `unsigned char`. Here's an example: https://godbolt.org/z/cTnMYdsv1 – Jonas Greitemann May 06 '22 at 05:53
  • Thanks @Jonas Greitemann for your explanation and time. – venkysmarty May 06 '22 at 06:37
  • Note: char is **not** always signed. It is implementation defined if it is signed or unsigned. E.g. GCC let's you choose which one you want. See e.g. this post: https://stackoverflow.com/q/2054939/3740047 – Sedenion May 06 '22 at 16:16