Search code examples
c++bit-manipulationgoogletest

How to unit test bit manipulation logic


I have a method which converts RGBA to BGRA. Below is the method

unsigned int ConvertRGBAToBGRA(unsigned int v) {
    unsigned char r = (v)& 0xFF;
    unsigned char g = (v >> 8) & 0xFF;
    unsigned char b = (v >> 16) & 0xFF;
    unsigned char a = (v >> 24) & 0xFF;
    return (a << 24) | (r << 16) | (g << 8) | b;
};

How can I unit test this nicely? Is there a way I can read back the bits and unit test this method somehow?

I am using googletests


Solution

  • Inspired by @Yves Daoust's comment, why can't you just write a series of checks like below? You can use the nice formatting of C++14:

    unsigned int ConvertRGBAToBGRA(unsigned int v) {
      unsigned char r = (v)&0xFF;
      unsigned char g = (v >> 8) & 0xFF;
      unsigned char b = (v >> 16) & 0xFF;
      unsigned char a = (v >> 24) & 0xFF;
      return (a << 24) | (r << 16) | (g << 8) | b;
    };
    
    TEST(ConvertRGBAToBGRATest, Test1) {
      EXPECT_EQ(ConvertRGBAToBGRA(0x12'34'56'78), 0x12'78'56'34);
      EXPECT_EQ(ConvertRGBAToBGRA(0x12'78'56'34), 0x12'34'56'78);
      EXPECT_EQ(ConvertRGBAToBGRA(0x11'11'11'11), 0x11'11'11'11);
      EXPECT_EQ(ConvertRGBAToBGRA(0x00'00'00'00), 0x00'00'00'00);
      EXPECT_EQ(ConvertRGBAToBGRA(0xAa'Bb'Cc'Dd), 0xAa'Dd'Cc'Bb);
    
      EXPECT_EQ(ConvertRGBAToBGRA(ConvertRGBAToBGRA(0x12'34'56'78)), 0x12'34'56'78);
      EXPECT_EQ(ConvertRGBAToBGRA(ConvertRGBAToBGRA(0x12'78'56'34)), 0x12'78'56'34);
      EXPECT_EQ(ConvertRGBAToBGRA(ConvertRGBAToBGRA(0x11'11'11'11)), 0x11'11'11'11);
      EXPECT_EQ(ConvertRGBAToBGRA(ConvertRGBAToBGRA(0x00'00'00'00)), 0x00'00'00'00);
      EXPECT_EQ(ConvertRGBAToBGRA(ConvertRGBAToBGRA(0xAa'Bb'Cc'Dd)), 0xAa'Bb'Cc'Dd);
    }
    

    Live example: https://godbolt.org/z/eEajYYYsf

    You could also define a custom matcher and use EXPECT_THAT macro:

    // A custom matcher for comparing BGRA and RGBA.
    MATCHER_P(IsBgraOf, n, "") {
      return ((n & 0xFF000000) == (arg & 0xFF000000)) &&
             ((n & 0x00FF0000) == ((arg << 16) & 0x00FF0000)) &&
             ((n & 0x0000FF00) == (arg & 0x0000FF00));
    }
    
    
    TEST(ConvertRGBAToBGRATest, WithExpectThat) {
      EXPECT_THAT(ConvertRGBAToBGRA(0x12'34'56'78), IsBgraOf(0x12'34'56'78));
      EXPECT_THAT(ConvertRGBAToBGRA(0x12'78'56'34), IsBgraOf(0x12'78'56'34));
      EXPECT_THAT(ConvertRGBAToBGRA(0xAa'Bb'Cc'Dd), IsBgraOf(0xAa'Bb'Cc'Dd));
      EXPECT_THAT(ConvertRGBAToBGRA(0x00'00'00'00), IsBgraOf(0x00'00'00'00));
      EXPECT_THAT(ConvertRGBAToBGRA(0x11'11'11'11), IsBgraOf(0x11'11'11'11));
    }
    

    Live example: https://godbolt.org/z/P4EcW19s9