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