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