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 <limits> 12 13#include "testing/gtest/include/gtest/gtest.h" 14#include "webrtc/modules/rtp_rtcp/source/byte_io.h" 15 16namespace webrtc { 17namespace { 18 19class ByteIoTest : public ::testing::Test { 20 protected: 21 ByteIoTest() {} 22 virtual ~ByteIoTest() {} 23 24 enum { kAlignments = sizeof(uint64_t) - 1 }; 25 26 // Method to create a test value that is not the same when byte reversed. 27 template <typename T> 28 T CreateTestValue(bool negative, uint8_t num_bytes) { 29 T val = 0; 30 for (uint8_t i = 0; i != num_bytes; ++i) { 31 val = (val << 8) + (negative ? (0xFF - i) : (i + 1)); 32 } 33 if (negative && std::numeric_limits<T>::is_signed) { 34 val |= static_cast<T>(-1) << (8 * num_bytes); 35 } 36 return val; 37 } 38 39 // Populate byte buffer with value, in big endian format. 40 template <typename T> 41 void PopulateTestData(uint8_t* data, T value, int num_bytes, bool bigendian) { 42 if (bigendian) { 43 for (int i = 0; i < num_bytes; ++i) { 44 data[i] = (value >> ((num_bytes - i - 1) * 8)) & 0xFF; 45 } 46 } else { 47 for (int i = 0; i < num_bytes; ++i) { 48 data[i] = (value >> (i * 8)) & 0xFF; 49 } 50 } 51 } 52 53 // Test reading big endian numbers. 54 // Template arguments: Type T, read method RM(buffer), B bytes of data. 55 template <typename T, T (*RM)(uint8_t*), int B> 56 void TestRead(bool big_endian) { 57 // Test both for values that are positive and negative (if signed) 58 for (int neg = 0; neg < 2; ++neg) { 59 bool negative = neg > 0; 60 61 // Write test value to byte buffer, in big endian format. 62 T test_value = CreateTestValue<T>(negative, B); 63 uint8_t bytes[B + kAlignments]; 64 65 // Make one test for each alignment. 66 for (int i = 0; i < kAlignments; ++i) { 67 PopulateTestData(bytes + i, test_value, B, big_endian); 68 69 // Check that test value is retrieved from buffer when used read method. 70 EXPECT_EQ(test_value, RM(bytes + i)); 71 } 72 } 73 } 74 75 // Test writing big endian numbers. 76 // Template arguments: Type T, write method WM(buffer, value), B bytes of data 77 template <typename T, void (*WM)(uint8_t*, T), int B> 78 void TestWrite(bool big_endian) { 79 // Test both for values that are positive and negative (if signed). 80 for (int neg = 0; neg < 2; ++neg) { 81 bool negative = neg > 0; 82 83 // Write test value to byte buffer, in big endian format. 84 T test_value = CreateTestValue<T>(negative, B); 85 uint8_t expected_bytes[B + kAlignments]; 86 uint8_t bytes[B + kAlignments]; 87 88 // Make one test for each alignment. 89 for (int i = 0; i < kAlignments; ++i) { 90 PopulateTestData(expected_bytes + i, test_value, B, big_endian); 91 92 // Zero initialize buffer and let WM populate it. 93 memset(bytes, 0, B + kAlignments); 94 WM(bytes + i, test_value); 95 96 // Check that data produced by WM is big endian as expected. 97 for (int j = 0; j < B; ++j) { 98 EXPECT_EQ(expected_bytes[i + j], bytes[i + j]); 99 } 100 } 101 } 102 } 103}; 104 105TEST_F(ByteIoTest, Test16UBitBigEndian) { 106 TestRead<uint16_t, ByteReader<uint16_t>::ReadBigEndian, 107 sizeof(uint16_t)>(true); 108 TestWrite<uint16_t, ByteWriter<uint16_t>::WriteBigEndian, 109 sizeof(uint16_t)>(true); 110} 111 112TEST_F(ByteIoTest, Test24UBitBigEndian) { 113 TestRead<uint32_t, ByteReader<uint32_t, 3>::ReadBigEndian, 3>(true); 114 TestWrite<uint32_t, ByteWriter<uint32_t, 3>::WriteBigEndian, 3>(true); 115} 116 117TEST_F(ByteIoTest, Test32UBitBigEndian) { 118 TestRead<uint32_t, ByteReader<uint32_t>::ReadBigEndian, 119 sizeof(uint32_t)>(true); 120 TestWrite<uint32_t, ByteWriter<uint32_t>::WriteBigEndian, 121 sizeof(uint32_t)>(true); 122} 123 124TEST_F(ByteIoTest, Test64UBitBigEndian) { 125 TestRead<uint64_t, ByteReader<uint64_t>::ReadBigEndian, 126 sizeof(uint64_t)>(true); 127 TestWrite<uint64_t, ByteWriter<uint64_t>::WriteBigEndian, 128 sizeof(uint64_t)>(true); 129} 130 131TEST_F(ByteIoTest, Test16SBitBigEndian) { 132 TestRead<int16_t, ByteReader<int16_t>::ReadBigEndian, 133 sizeof(int16_t)>(true); 134 TestWrite<int16_t, ByteWriter<int16_t>::WriteBigEndian, 135 sizeof(int16_t)>(true); 136} 137 138TEST_F(ByteIoTest, Test24SBitBigEndian) { 139 TestRead<int32_t, ByteReader<int32_t, 3>::ReadBigEndian, 3>(true); 140 TestWrite<int32_t, ByteWriter<int32_t, 3>::WriteBigEndian, 3>(true); 141} 142 143TEST_F(ByteIoTest, Test32SBitBigEndian) { 144 TestRead<int32_t, ByteReader<int32_t>::ReadBigEndian, 145 sizeof(int32_t)>(true); 146 TestWrite<int32_t, ByteWriter<int32_t>::WriteBigEndian, 147 sizeof(int32_t)>(true); 148} 149 150TEST_F(ByteIoTest, Test64SBitBigEndian) { 151 TestRead<int64_t, ByteReader<int64_t>::ReadBigEndian, 152 sizeof(int64_t)>(true); 153 TestWrite<int64_t, ByteWriter<int64_t>::WriteBigEndian, 154 sizeof(int64_t)>(true); 155} 156 157TEST_F(ByteIoTest, Test16UBitLittleEndian) { 158 TestRead<uint16_t, ByteReader<uint16_t>::ReadLittleEndian, 159 sizeof(uint16_t)>(false); 160 TestWrite<uint16_t, ByteWriter<uint16_t>::WriteLittleEndian, 161 sizeof(uint16_t)>(false); 162} 163 164TEST_F(ByteIoTest, Test24UBitLittleEndian) { 165 TestRead<uint32_t, ByteReader<uint32_t, 3>::ReadLittleEndian, 3>(false); 166 TestWrite<uint32_t, ByteWriter<uint32_t, 3>::WriteLittleEndian, 3>(false); 167} 168 169TEST_F(ByteIoTest, Test32UBitLittleEndian) { 170 TestRead<uint32_t, ByteReader<uint32_t>::ReadLittleEndian, 171 sizeof(uint32_t)>(false); 172 TestWrite<uint32_t, ByteWriter<uint32_t>::WriteLittleEndian, 173 sizeof(uint32_t)>(false); 174} 175 176TEST_F(ByteIoTest, Test64UBitLittleEndian) { 177 TestRead<uint64_t, ByteReader<uint64_t>::ReadLittleEndian, 178 sizeof(uint64_t)>(false); 179 TestWrite<uint64_t, ByteWriter<uint64_t>::WriteLittleEndian, 180 sizeof(uint64_t)>(false); 181} 182 183TEST_F(ByteIoTest, Test16SBitLittleEndian) { 184 TestRead<int16_t, ByteReader<int16_t>::ReadLittleEndian, 185 sizeof(int16_t)>(false); 186 TestWrite<int16_t, ByteWriter<int16_t>::WriteLittleEndian, 187 sizeof(int16_t)>(false); 188} 189 190TEST_F(ByteIoTest, Test24SBitLittleEndian) { 191 TestRead<int32_t, ByteReader<int32_t, 3>::ReadLittleEndian, 3>(false); 192 TestWrite<int32_t, ByteWriter<int32_t, 3>::WriteLittleEndian, 3>(false); 193} 194 195TEST_F(ByteIoTest, Test32SBitLittleEndian) { 196 TestRead<int32_t, ByteReader<int32_t>::ReadLittleEndian, 197 sizeof(int32_t)>(false); 198 TestWrite<int32_t, ByteWriter<int32_t>::WriteLittleEndian, 199 sizeof(int32_t)>(false); 200} 201 202TEST_F(ByteIoTest, Test64SBitLittleEndian) { 203 TestRead<int64_t, ByteReader<int64_t>::ReadLittleEndian, 204 sizeof(int64_t)>(false); 205 TestWrite<int64_t, ByteWriter<int64_t>::WriteLittleEndian, 206 sizeof(int64_t)>(false); 207} 208 209} // namespace 210} // namespace webrtc 211