tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

byte_io_unittest.cc (10154B)


      1 /*
      2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "modules/rtp_rtcp/source/byte_io.h"
     12 
     13 #include <cstdint>
     14 #include <limits>
     15 
     16 #include "test/gtest.h"
     17 
     18 namespace webrtc {
     19 namespace {
     20 
     21 class ByteIoTest : public ::testing::Test {
     22 protected:
     23  ByteIoTest() = default;
     24  ~ByteIoTest() override = default;
     25 
     26  enum { kAlignments = sizeof(uint64_t) - 1 };
     27 
     28  // Method to create a test value that is not the same when byte reversed.
     29  template <typename T>
     30  T CreateTestValue(bool negative, uint8_t num_bytes) {
     31    // Examples of output:
     32    // T = int32_t, negative = false, num_bytes = 4: 0x00010203
     33    // T = int32_t, negative = true, num_bytes = 4: 0xFFFEFDFC
     34    // T = int32_t, negative = false, num_bytes = 3: 0x000102
     35    // * T = int32_t, negative = true, num_bytes = 3: 0xFFFEFD
     36 
     37    T val = 0;
     38    for (uint8_t i = 0; i != num_bytes; ++i) {
     39      val = (val << 8) + (negative ? (0xFF - i) : (i + 1));
     40    }
     41 
     42    // This loop will create a sign extend mask if num_bytes if necessary.
     43    // For the last example (marked * above), the number needs to be sign
     44    // extended to be a valid int32_t. The sign extend mask is 0xFF000000.
     45    // Comments for each step with this example below.
     46    if (std::numeric_limits<T>::is_signed && negative &&
     47        num_bytes < sizeof(T)) {
     48      // Start with mask = 0xFFFFFFFF.
     49      T mask = static_cast<T>(-1);
     50      // Create a temporary for the lowest byte (0x000000FF).
     51      const T neg_byte = static_cast<T>(0xFF);
     52      for (int i = 0; i < num_bytes; ++i) {
     53        // And the inverse of the temporary and the mask:
     54        // 0xFFFFFFFF & 0xFFFFFF00 = 0xFFFFFF00.
     55        // 0xFFFFFF00 & 0xFFFF00FF = 0xFFFF0000.
     56        // 0xFFFF0000 & 0xFF00FFFF = 0xFF000000.
     57        mask &= ~(neg_byte << (i * 8));
     58      }
     59      // Add the sign extension mask to the actual value.
     60      val |= mask;
     61    }
     62    return val;
     63  }
     64 
     65  // Populate byte buffer with value, in big endian format.
     66  template <typename T>
     67  void PopulateTestData(uint8_t* data, T value, int num_bytes, bool bigendian) {
     68    if (bigendian) {
     69      for (int i = 0; i < num_bytes; ++i) {
     70        data[i] = (value >> ((num_bytes - i - 1) * 8)) & 0xFF;
     71      }
     72    } else {
     73      for (int i = 0; i < num_bytes; ++i) {
     74        data[i] = (value >> (i * 8)) & 0xFF;
     75      }
     76    }
     77  }
     78 
     79  // Test reading big endian numbers.
     80  // Template arguments: Type T, read method RM(buffer), B bytes of data.
     81  template <typename T, T (*RM)(const uint8_t*), int B>
     82  void TestRead(bool big_endian) {
     83    // Test both for values that are positive and negative (if signed)
     84    for (int neg = 0; neg < 2; ++neg) {
     85      bool negative = neg > 0;
     86 
     87      // Write test value to byte buffer, in big endian format.
     88      T test_value = CreateTestValue<T>(negative, B);
     89      uint8_t bytes[B + kAlignments];
     90 
     91      // Make one test for each alignment.
     92      for (int i = 0; i < kAlignments; ++i) {
     93        PopulateTestData(bytes + i, test_value, B, big_endian);
     94 
     95        // Check that test value is retrieved from buffer when used read method.
     96        EXPECT_EQ(test_value, RM(bytes + i));
     97      }
     98    }
     99  }
    100 
    101  // Test writing big endian numbers.
    102  // Template arguments: Type T, write method WM(buffer, value), B bytes of data
    103  template <typename T, void (*WM)(uint8_t*, T), int B>
    104  void TestWrite(bool big_endian) {
    105    // Test both for values that are positive and negative (if signed).
    106    for (int neg = 0; neg < 2; ++neg) {
    107      bool negative = neg > 0;
    108 
    109      // Write test value to byte buffer, in big endian format.
    110      T test_value = CreateTestValue<T>(negative, B);
    111      uint8_t expected_bytes[B + kAlignments];
    112      uint8_t bytes[B + kAlignments];
    113 
    114      // Make one test for each alignment.
    115      for (int i = 0; i < kAlignments; ++i) {
    116        PopulateTestData(expected_bytes + i, test_value, B, big_endian);
    117 
    118        // Zero initialize buffer and let WM populate it.
    119        memset(bytes, 0, B + kAlignments);
    120        WM(bytes + i, test_value);
    121 
    122        // Check that data produced by WM is big endian as expected.
    123        for (int j = 0; j < B; ++j) {
    124          EXPECT_EQ(expected_bytes[i + j], bytes[i + j]);
    125        }
    126      }
    127    }
    128  }
    129 };
    130 
    131 TEST_F(ByteIoTest, Test16UBitBigEndian) {
    132  TestRead<uint16_t, ByteReader<uint16_t>::ReadBigEndian, sizeof(uint16_t)>(
    133      true);
    134  TestWrite<uint16_t, ByteWriter<uint16_t>::WriteBigEndian, sizeof(uint16_t)>(
    135      true);
    136 }
    137 
    138 TEST_F(ByteIoTest, Test24UBitBigEndian) {
    139  TestRead<uint32_t, ByteReader<uint32_t, 3>::ReadBigEndian, 3>(true);
    140  TestWrite<uint32_t, ByteWriter<uint32_t, 3>::WriteBigEndian, 3>(true);
    141 }
    142 
    143 TEST_F(ByteIoTest, Test32UBitBigEndian) {
    144  TestRead<uint32_t, ByteReader<uint32_t>::ReadBigEndian, sizeof(uint32_t)>(
    145      true);
    146  TestWrite<uint32_t, ByteWriter<uint32_t>::WriteBigEndian, sizeof(uint32_t)>(
    147      true);
    148 }
    149 
    150 TEST_F(ByteIoTest, Test64UBitBigEndian) {
    151  TestRead<uint64_t, ByteReader<uint64_t>::ReadBigEndian, sizeof(uint64_t)>(
    152      true);
    153  TestWrite<uint64_t, ByteWriter<uint64_t>::WriteBigEndian, sizeof(uint64_t)>(
    154      true);
    155 }
    156 
    157 TEST_F(ByteIoTest, Test16SBitBigEndian) {
    158  TestRead<int16_t, ByteReader<int16_t>::ReadBigEndian, sizeof(int16_t)>(true);
    159  TestWrite<int16_t, ByteWriter<int16_t>::WriteBigEndian, sizeof(int16_t)>(
    160      true);
    161 }
    162 
    163 TEST_F(ByteIoTest, Test24SBitBigEndian) {
    164  TestRead<int32_t, ByteReader<int32_t, 3>::ReadBigEndian, 3>(true);
    165  TestWrite<int32_t, ByteWriter<int32_t, 3>::WriteBigEndian, 3>(true);
    166 }
    167 
    168 TEST_F(ByteIoTest, Test32SBitBigEndian) {
    169  TestRead<int32_t, ByteReader<int32_t>::ReadBigEndian, sizeof(int32_t)>(true);
    170  TestWrite<int32_t, ByteWriter<int32_t>::WriteBigEndian, sizeof(int32_t)>(
    171      true);
    172 }
    173 
    174 TEST_F(ByteIoTest, Test64SBitBigEndian) {
    175  TestRead<int64_t, ByteReader<int64_t>::ReadBigEndian, sizeof(int64_t)>(true);
    176  TestWrite<int64_t, ByteWriter<int64_t>::WriteBigEndian, sizeof(int64_t)>(
    177      true);
    178 }
    179 
    180 TEST_F(ByteIoTest, Test16UBitLittleEndian) {
    181  TestRead<uint16_t, ByteReader<uint16_t>::ReadLittleEndian, sizeof(uint16_t)>(
    182      false);
    183  TestWrite<uint16_t, ByteWriter<uint16_t>::WriteLittleEndian,
    184            sizeof(uint16_t)>(false);
    185 }
    186 
    187 TEST_F(ByteIoTest, Test24UBitLittleEndian) {
    188  TestRead<uint32_t, ByteReader<uint32_t, 3>::ReadLittleEndian, 3>(false);
    189  TestWrite<uint32_t, ByteWriter<uint32_t, 3>::WriteLittleEndian, 3>(false);
    190 }
    191 
    192 TEST_F(ByteIoTest, Test32UBitLittleEndian) {
    193  TestRead<uint32_t, ByteReader<uint32_t>::ReadLittleEndian, sizeof(uint32_t)>(
    194      false);
    195  TestWrite<uint32_t, ByteWriter<uint32_t>::WriteLittleEndian,
    196            sizeof(uint32_t)>(false);
    197 }
    198 
    199 TEST_F(ByteIoTest, Test64UBitLittleEndian) {
    200  TestRead<uint64_t, ByteReader<uint64_t>::ReadLittleEndian, sizeof(uint64_t)>(
    201      false);
    202  TestWrite<uint64_t, ByteWriter<uint64_t>::WriteLittleEndian,
    203            sizeof(uint64_t)>(false);
    204 }
    205 
    206 TEST_F(ByteIoTest, Test16SBitLittleEndian) {
    207  TestRead<int16_t, ByteReader<int16_t>::ReadLittleEndian, sizeof(int16_t)>(
    208      false);
    209  TestWrite<int16_t, ByteWriter<int16_t>::WriteLittleEndian, sizeof(int16_t)>(
    210      false);
    211 }
    212 
    213 TEST_F(ByteIoTest, Test24SBitLittleEndian) {
    214  TestRead<int32_t, ByteReader<int32_t, 3>::ReadLittleEndian, 3>(false);
    215  TestWrite<int32_t, ByteWriter<int32_t, 3>::WriteLittleEndian, 3>(false);
    216 }
    217 
    218 TEST_F(ByteIoTest, Test32SBitLittleEndian) {
    219  TestRead<int32_t, ByteReader<int32_t>::ReadLittleEndian, sizeof(int32_t)>(
    220      false);
    221  TestWrite<int32_t, ByteWriter<int32_t>::WriteLittleEndian, sizeof(int32_t)>(
    222      false);
    223 }
    224 
    225 TEST_F(ByteIoTest, Test64SBitLittleEndian) {
    226  TestRead<int64_t, ByteReader<int64_t>::ReadLittleEndian, sizeof(int64_t)>(
    227      false);
    228  TestWrite<int64_t, ByteWriter<int64_t>::WriteLittleEndian, sizeof(int64_t)>(
    229      false);
    230 }
    231 
    232 // Sets up a fixed byte array and converts N bytes from the array into a
    233 // uint64_t. Verifies the value with hard-coded reference.
    234 TEST(ByteIo, SanityCheckFixedByteArrayUnsignedReadBigEndian) {
    235  uint8_t data[8] = {0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88};
    236  uint64_t value = ByteReader<uint64_t, 2>::ReadBigEndian(data);
    237  EXPECT_EQ(static_cast<uint64_t>(0xFFEE), value);
    238  value = ByteReader<uint64_t, 3>::ReadBigEndian(data);
    239  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDD), value);
    240  value = ByteReader<uint64_t, 4>::ReadBigEndian(data);
    241  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDDCC), value);
    242  value = ByteReader<uint64_t, 5>::ReadBigEndian(data);
    243  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDDCCBB), value);
    244  value = ByteReader<uint64_t, 6>::ReadBigEndian(data);
    245  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDDCCBBAA), value);
    246  value = ByteReader<uint64_t, 7>::ReadBigEndian(data);
    247  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDDCCBBAA99), value);
    248  value = ByteReader<uint64_t, 8>::ReadBigEndian(data);
    249  EXPECT_EQ(static_cast<uint64_t>(0xFFEEDDCCBBAA9988), value);
    250 }
    251 
    252 // Same as above, but for little-endian reading.
    253 TEST(ByteIo, SanityCheckFixedByteArrayUnsignedReadLittleEndian) {
    254  uint8_t data[8] = {0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88};
    255  uint64_t value = ByteReader<uint64_t, 2>::ReadLittleEndian(data);
    256  EXPECT_EQ(static_cast<uint64_t>(0xEEFF), value);
    257  value = ByteReader<uint64_t, 3>::ReadLittleEndian(data);
    258  EXPECT_EQ(static_cast<uint64_t>(0xDDEEFF), value);
    259  value = ByteReader<uint64_t, 4>::ReadLittleEndian(data);
    260  EXPECT_EQ(static_cast<uint64_t>(0xCCDDEEFF), value);
    261  value = ByteReader<uint64_t, 5>::ReadLittleEndian(data);
    262  EXPECT_EQ(static_cast<uint64_t>(0xBBCCDDEEFF), value);
    263  value = ByteReader<uint64_t, 6>::ReadLittleEndian(data);
    264  EXPECT_EQ(static_cast<uint64_t>(0xAABBCCDDEEFF), value);
    265  value = ByteReader<uint64_t, 7>::ReadLittleEndian(data);
    266  EXPECT_EQ(static_cast<uint64_t>(0x99AABBCCDDEEFF), value);
    267  value = ByteReader<uint64_t, 8>::ReadLittleEndian(data);
    268  EXPECT_EQ(static_cast<uint64_t>(0x8899AABBCCDDEEFF), value);
    269 }
    270 }  // namespace
    271 }  // namespace webrtc