test/zserio/BitStreamReaderTest.cpp
Line | Count | Source |
1 | | #include <array> |
2 | | #include <cstring> |
3 | | |
4 | | #include "gtest/gtest.h" |
5 | | #include "zserio/BitStreamReader.h" |
6 | | #include "zserio/CppRuntimeException.h" |
7 | | |
8 | | namespace zserio |
9 | | { |
10 | | |
11 | | class BitStreamReaderTest : public ::testing::Test |
12 | | { |
13 | | public: |
14 | | BitStreamReaderTest() : |
15 | | m_byteBuffer(), |
16 | | m_reader(m_byteBuffer.data(), m_byteBuffer.size()) |
17 | 12 | { |
18 | 12 | m_byteBuffer.fill(0); |
19 | 12 | } |
20 | | |
21 | | protected: |
22 | | std::array<uint8_t, 16> m_byteBuffer; |
23 | | BitStreamReader m_reader; |
24 | | }; |
25 | | |
26 | | TEST_F(BitStreamReaderTest, spanConstructor) |
27 | 1 | { |
28 | 1 | const std::array<const uint8_t, 3> data = {0xAE, 0xEA, 0x80}; |
29 | 1 | const Span<const uint8_t> span(data); |
30 | 1 | BitStreamReader reader(span); |
31 | | |
32 | 1 | ASSERT_EQ(span.size() * 8, reader.getBufferBitSize()); |
33 | 1 | ASSERT_EQ(0xAEE, reader.readBits(12)); |
34 | 1 | ASSERT_EQ(0xA, reader.readBits(4)); |
35 | 1 | ASSERT_EQ(0x80, reader.readBits(8)); |
36 | | |
37 | 1 | ASSERT_THROW(reader.readBits(1), CppRuntimeException); |
38 | 1 | } |
39 | | |
40 | | TEST_F(BitStreamReaderTest, spanConstructorWithBitSize) |
41 | 1 | { |
42 | 1 | const std::array<const uint8_t, 3> data = {0xAE, 0xEA, 0x80}; |
43 | 1 | const Span<const uint8_t> span(data); |
44 | 1 | BitStreamReader reader(span, 23); |
45 | 1 | ASSERT_THROW(BitStreamReader wrongReader(span, 25), CppRuntimeException); |
46 | | |
47 | 1 | ASSERT_EQ(23, reader.getBufferBitSize()); |
48 | 1 | ASSERT_EQ(0xAEE, reader.readBits(12)); |
49 | 1 | ASSERT_EQ(0xA, reader.readBits(4)); |
50 | 1 | ASSERT_EQ(0x40, reader.readBits(7)); |
51 | | |
52 | 1 | ASSERT_THROW(reader.readBits(1), CppRuntimeException); |
53 | 1 | } |
54 | | |
55 | | TEST_F(BitStreamReaderTest, bitBufferConstructor) |
56 | 1 | { |
57 | 1 | const std::vector<uint8_t> data = {0xAE, 0xEA, 0x80}; |
58 | 1 | BitBuffer bitBuffer(data, 17); |
59 | 1 | BitStreamReader reader(bitBuffer); |
60 | | |
61 | 1 | ASSERT_EQ(bitBuffer.getBitSize(), reader.getBufferBitSize()); |
62 | 1 | ASSERT_EQ(0xAEE, reader.readBits(12)); |
63 | 1 | ASSERT_EQ(0xA, reader.readBits(4)); |
64 | 1 | ASSERT_EQ(1, reader.readBits(1)); |
65 | | |
66 | 1 | ASSERT_THROW(reader.readBits(1), CppRuntimeException); |
67 | | |
68 | 1 | ASSERT_THROW(BitStreamReader(nullptr, std::numeric_limits<size_t>::max() / 8), CppRuntimeException); |
69 | 1 | } |
70 | | |
71 | | TEST_F(BitStreamReaderTest, bitBufferConstructorOverflow) |
72 | 1 | { |
73 | 1 | const std::vector<uint8_t> data = {0xFF, 0xFF, 0xF0}; |
74 | 1 | BitBuffer bitBuffer(data, 19); |
75 | 1 | BitStreamReader reader(bitBuffer); |
76 | | |
77 | 1 | ASSERT_EQ(bitBuffer.getBitSize(), reader.getBufferBitSize()); |
78 | 1 | ASSERT_THROW(reader.readBits(20), CppRuntimeException); |
79 | 1 | } |
80 | | |
81 | | TEST_F(BitStreamReaderTest, readUnalignedData) |
82 | 1 | { |
83 | | // number expected to read at offset |
84 | 1 | const uint8_t testValue = 123; |
85 | | |
86 | 66 | for (uint8_t offset = 0; offset <= 64; ++offset65 ) |
87 | 65 | { |
88 | 65 | BitBuffer buffer(8 + offset); |
89 | | |
90 | | // write test value at offset to data buffer |
91 | 65 | buffer.getData()[offset / 8U] = static_cast<uint8_t>( |
92 | 65 | buffer.getData()[offset / 8U] | static_cast<uint8_t>(testValue >> (offset % 8U))); |
93 | 65 | if (offset % 8 != 0) // don't write behind the buffer |
94 | 56 | { |
95 | 56 | buffer.getData()[offset / 8U + 1] = static_cast<uint8_t>(buffer.getData()[offset / 8U + 1] | |
96 | 56 | static_cast<uint8_t>(testValue << (8U - (offset % 8U)))); |
97 | 56 | } |
98 | | |
99 | 65 | BitStreamReader reader(buffer); |
100 | | |
101 | | // read offset bits |
102 | 65 | ASSERT_EQ(0, reader.readBits64(offset)); |
103 | | |
104 | | // read magic number |
105 | 130 | ASSERT_EQ(testValue, reader.readBits(8)) << "Offset: " << offset; |
106 | | |
107 | | // check eof |
108 | 130 | ASSERT_THROW(reader.readBits(1), CppRuntimeException) << "Offset: " << offset; |
109 | 65 | } |
110 | 1 | } |
111 | | |
112 | | TEST_F(BitStreamReaderTest, readBits) |
113 | 1 | { |
114 | | // check invalid bitlength acceptance |
115 | 1 | ASSERT_THROW(m_reader.readBits(255), CppRuntimeException); |
116 | 1 | ASSERT_THROW(m_reader.readBits(33), CppRuntimeException); |
117 | | |
118 | | // return 0 for 0 bits |
119 | 1 | ASSERT_EQ(0, m_reader.readBits(0)); |
120 | 1 | } |
121 | | |
122 | | TEST_F(BitStreamReaderTest, readBits64) |
123 | 1 | { |
124 | | // check invalid bit length acceptance |
125 | 1 | ASSERT_THROW(m_reader.readBits64(255), CppRuntimeException); |
126 | 1 | ASSERT_THROW(m_reader.readBits64(65), CppRuntimeException); |
127 | | |
128 | | // return 0 for 0 bits |
129 | 1 | ASSERT_EQ(0, m_reader.readBits64(0)); |
130 | 1 | } |
131 | | |
132 | | TEST_F(BitStreamReaderTest, readSignedBits) |
133 | 1 | { |
134 | | // check invalid bit length acceptance |
135 | 1 | ASSERT_THROW(m_reader.readSignedBits(255), CppRuntimeException); |
136 | 1 | ASSERT_THROW(m_reader.readSignedBits(33), CppRuntimeException); |
137 | | |
138 | | // return 0 for 0 bits |
139 | 1 | ASSERT_EQ(0, m_reader.readSignedBits(0)); |
140 | 1 | } |
141 | | |
142 | | TEST_F(BitStreamReaderTest, readSignedBits64) |
143 | 1 | { |
144 | | // check invalid bit length acceptance |
145 | 1 | ASSERT_THROW(m_reader.readSignedBits64(255), CppRuntimeException); |
146 | 1 | ASSERT_THROW(m_reader.readSignedBits64(65), CppRuntimeException); |
147 | | |
148 | | // return 0 for 0 bits |
149 | 1 | ASSERT_EQ(0, m_reader.readSignedBits64(0)); |
150 | 1 | } |
151 | | |
152 | | TEST_F(BitStreamReaderTest, readVarSize) |
153 | 1 | { |
154 | 1 | { |
155 | | // overflow, 2^32 - 1 is too much ({ 0x83, 0xFF, 0xFF, 0xFF, 0xFF } is the maximum) |
156 | 1 | const std::array<uint8_t, 5> buffer = {0x87, 0xFF, 0xFF, 0xFF, 0xFF}; |
157 | 1 | zserio::BitStreamReader reader(buffer.data(), buffer.size()); |
158 | 1 | ASSERT_THROW(reader.readVarSize(), CppRuntimeException); |
159 | 1 | } |
160 | | |
161 | 1 | { |
162 | | // overflow, 2^36 - 1 is too much ({ 0x83, 0xFF, 0xFF, 0xFF, 0xFF } is the maximum) |
163 | 1 | const std::array<uint8_t, 5> buffer = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
164 | 1 | zserio::BitStreamReader reader(buffer.data(), buffer.size()); |
165 | 1 | ASSERT_THROW(reader.readVarSize(), CppRuntimeException); |
166 | 1 | } |
167 | 1 | } |
168 | | |
169 | | TEST_F(BitStreamReaderTest, getBitPosition) |
170 | 1 | { |
171 | 1 | ASSERT_EQ(0, m_reader.getBitPosition()); |
172 | 1 | m_reader.readBits(10); |
173 | 1 | ASSERT_EQ(10, m_reader.getBitPosition()); |
174 | 1 | } |
175 | | |
176 | | TEST_F(BitStreamReaderTest, getBufferBitSize) |
177 | 1 | { |
178 | 1 | ASSERT_EQ(m_byteBuffer.size() * 8, m_reader.getBufferBitSize()); |
179 | 1 | } |
180 | | |
181 | | } // namespace zserio |