1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.compress.utils;
20
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertThrows;
23
24 import java.io.ByteArrayInputStream;
25 import java.io.IOException;
26 import java.nio.ByteOrder;
27
28 import org.junit.jupiter.api.Test;
29
30 class BitInputStreamTest {
31
32 private ByteArrayInputStream getStream() {
33 return new ByteArrayInputStream(new byte[] { (byte) 0xF8,
34 0x40,
35 0x01,
36 0x2F });
37 }
38
39 @Test
40 void testAlignWithByteBoundaryWhenAtBoundary() throws Exception {
41 try (BitInputStream bis = new BitInputStream(getStream(), ByteOrder.LITTLE_ENDIAN)) {
42 assertEquals(0xF8, bis.readBits(8));
43 bis.alignWithByteBoundary();
44 assertEquals(0, bis.readBits(4));
45 }
46 }
47
48 @Test
49 void testAlignWithByteBoundaryWhenNotAtBoundary() throws Exception {
50 try (BitInputStream bis = new BitInputStream(getStream(), ByteOrder.LITTLE_ENDIAN)) {
51 assertEquals(0x08, bis.readBits(4));
52 assertEquals(4, bis.bitsCached());
53 bis.alignWithByteBoundary();
54 assertEquals(0, bis.bitsCached());
55 assertEquals(0, bis.readBits(4));
56 }
57 }
58
59 @Test
60 void testAvailableWithCache() throws Exception {
61 try (BitInputStream bis = new BitInputStream(getStream(), ByteOrder.LITTLE_ENDIAN)) {
62 assertEquals(0x08, bis.readBits(4));
63 assertEquals(28, bis.bitsAvailable());
64 }
65 }
66
67 @Test
68 void testAvailableWithoutCache() throws Exception {
69 try (BitInputStream bis = new BitInputStream(getStream(), ByteOrder.LITTLE_ENDIAN)) {
70 assertEquals(32, bis.bitsAvailable());
71 }
72 }
73
74 @Test
75 void testBigEndianWithOverflow() throws Exception {
76 final ByteArrayInputStream in = new ByteArrayInputStream(new byte[] { 87,
77 45,
78 66,
79 15,
80 90,
81 29,
82 88,
83 61,
84 33,
85 74
86 });
87 try (BitInputStream bin = new BitInputStream(in, ByteOrder.BIG_ENDIAN)) {
88 assertEquals(10,
89 bin.readBits(5));
90 assertEquals(8274274654740644818L,
91 bin.readBits(63));
92 assertEquals(330,
93 bin.readBits(12));
94 assertEquals(-1, bin.readBits(1));
95 }
96 }
97
98 @Test
99 void testClearBitCache() throws IOException {
100 try (BitInputStream bis = new BitInputStream(getStream(), ByteOrder.LITTLE_ENDIAN)) {
101 assertEquals(0x08, bis.readBits(4));
102 bis.clearBitCache();
103 assertEquals(0, bis.readBits(1));
104 }
105 }
106
107 @Test
108 void testEOF() throws IOException {
109 try (BitInputStream bis = new BitInputStream(getStream(), ByteOrder.LITTLE_ENDIAN)) {
110 assertEquals(0x2f0140f8, bis.readBits(30));
111 assertEquals(-1, bis.readBits(3));
112 }
113 }
114
115
116
117
118 @Test
119 void testLittleEndianWithOverflow() throws Exception {
120 final ByteArrayInputStream in = new ByteArrayInputStream(new byte[] { 87,
121 45,
122 66,
123 15,
124 90,
125 29,
126 88,
127 61,
128 33,
129 74
130 });
131 try (BitInputStream bin = new BitInputStream(in, ByteOrder.LITTLE_ENDIAN)) {
132 assertEquals(23,
133 bin.readBits(5));
134 assertEquals(714595605644185962L,
135 bin.readBits(63));
136 assertEquals(1186,
137 bin.readBits(12));
138 assertEquals(-1, bin.readBits(1));
139 }
140 }
141
142 @Test
143 void testReading17BitsInBigEndian() throws IOException {
144 try (BitInputStream bis = new BitInputStream(getStream(), ByteOrder.BIG_ENDIAN)) {
145
146 assertEquals(0x0001f080, bis.readBits(17));
147 }
148 }
149
150 @Test
151 void testReading17BitsInLittleEndian() throws IOException {
152 try (BitInputStream bis = new BitInputStream(getStream(), ByteOrder.LITTLE_ENDIAN)) {
153 assertEquals(0x000140f8, bis.readBits(17));
154 }
155 }
156
157 @Test
158 void testReading24BitsInBigEndian() throws IOException {
159 try (BitInputStream bis = new BitInputStream(getStream(), ByteOrder.BIG_ENDIAN)) {
160 assertEquals(0x00f84001, bis.readBits(24));
161 }
162 }
163
164 @Test
165 void testReading24BitsInLittleEndian() throws IOException {
166 try (BitInputStream bis = new BitInputStream(getStream(), ByteOrder.LITTLE_ENDIAN)) {
167 assertEquals(0x000140f8, bis.readBits(24));
168 }
169 }
170
171 @Test
172 void testReading30BitsInBigEndian() throws IOException {
173 try (BitInputStream bis = new BitInputStream(getStream(), ByteOrder.BIG_ENDIAN)) {
174
175 assertEquals(0x3e10004b, bis.readBits(30));
176 }
177 }
178
179 @Test
180 void testReading30BitsInLittleEndian() throws IOException {
181 try (BitInputStream bis = new BitInputStream(getStream(), ByteOrder.LITTLE_ENDIAN)) {
182 assertEquals(0x2f0140f8, bis.readBits(30));
183 }
184 }
185
186 @Test
187 void testReading31BitsInBigEndian() throws IOException {
188 try (BitInputStream bis = new BitInputStream(getStream(), ByteOrder.BIG_ENDIAN)) {
189
190 assertEquals(0x7c200097, bis.readBits(31));
191 }
192 }
193
194 @Test
195 void testReading31BitsInLittleEndian() throws IOException {
196 try (BitInputStream bis = new BitInputStream(getStream(), ByteOrder.LITTLE_ENDIAN)) {
197 assertEquals(0x2f0140f8, bis.readBits(31));
198 }
199 }
200
201 @Test
202 void testReadingOneBitFromEmptyStream() throws Exception {
203 try (BitInputStream bis = new BitInputStream(new ByteArrayInputStream(ByteUtils.EMPTY_BYTE_ARRAY), ByteOrder.LITTLE_ENDIAN)) {
204 assertEquals(-1, bis.readBit(), "next bit");
205 assertEquals(-1, bis.readBit(), "next bit");
206 assertEquals(-1, bis.readBit(), "next bit");
207 }
208 }
209
210 @Test
211 void testReadingOneBitInBigEndian() throws Exception {
212 try (BitInputStream bis = new BitInputStream(new ByteArrayInputStream(new byte[] { (byte) 0xEA, 0x03 }), ByteOrder.BIG_ENDIAN)) {
213
214 assertEquals(1, bis.readBit(), "bit 0");
215 assertEquals(1, bis.readBit(), "bit 1");
216 assertEquals(1, bis.readBit(), "bit 2");
217 assertEquals(0, bis.readBit(), "bit 3");
218 assertEquals(1, bis.readBit(), "bit 4");
219 assertEquals(0, bis.readBit(), "bit 5");
220 assertEquals(1, bis.readBit(), "bit 6");
221 assertEquals(0, bis.readBit(), "bit 7");
222
223 assertEquals(0, bis.readBit(), "bit 8");
224 assertEquals(0, bis.readBit(), "bit 9");
225 assertEquals(0, bis.readBit(), "bit 10");
226 assertEquals(0, bis.readBit(), "bit 11");
227 assertEquals(0, bis.readBit(), "bit 12");
228 assertEquals(0, bis.readBit(), "bit 13");
229 assertEquals(1, bis.readBit(), "bit 14");
230 assertEquals(1, bis.readBit(), "bit 15");
231
232 assertEquals(-1, bis.readBit(), "next bit");
233 }
234 }
235
236 @Test
237 void testReadingOneBitInLittleEndian() throws Exception {
238 try (BitInputStream bis = new BitInputStream(new ByteArrayInputStream(new byte[] { (byte) 0xEA, 0x03 }), ByteOrder.LITTLE_ENDIAN)) {
239
240 assertEquals(0, bis.readBit(), "bit 0");
241 assertEquals(1, bis.readBit(), "bit 1");
242 assertEquals(0, bis.readBit(), "bit 2");
243 assertEquals(1, bis.readBit(), "bit 3");
244 assertEquals(0, bis.readBit(), "bit 4");
245 assertEquals(1, bis.readBit(), "bit 5");
246 assertEquals(1, bis.readBit(), "bit 6");
247 assertEquals(1, bis.readBit(), "bit 7");
248
249 assertEquals(1, bis.readBit(), "bit 8");
250 assertEquals(1, bis.readBit(), "bit 9");
251 assertEquals(0, bis.readBit(), "bit 10");
252 assertEquals(0, bis.readBit(), "bit 11");
253 assertEquals(0, bis.readBit(), "bit 12");
254 assertEquals(0, bis.readBit(), "bit 13");
255 assertEquals(0, bis.readBit(), "bit 14");
256 assertEquals(0, bis.readBit(), "bit 15");
257
258 assertEquals(-1, bis.readBit(), "next bit");
259 }
260 }
261
262 @Test
263 void testShouldNotAllowReadingOfANegativeAmountOfBits() throws IOException {
264 try (BitInputStream bis = new BitInputStream(getStream(), ByteOrder.LITTLE_ENDIAN)) {
265 assertThrows(IOException.class, () -> bis.readBits(-1));
266 }
267 }
268
269 @Test
270 void testShouldNotAllowReadingOfMoreThan63BitsAtATime() throws IOException {
271 try (BitInputStream bis = new BitInputStream(getStream(), ByteOrder.LITTLE_ENDIAN)) {
272 assertThrows(IOException.class, () -> bis.readBits(64));
273 }
274 }
275
276 }