Skip to content

Commit f4781f1

Browse files
committed
Add MultiBuffer tests
1 parent 8399567 commit f4781f1

File tree

1 file changed

+338
-0
lines changed

1 file changed

+338
-0
lines changed
Lines changed: 338 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,338 @@
1+
package com.maxmind.db;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
5+
import java.io.IOException;
6+
import java.io.RandomAccessFile;
7+
import java.nio.ByteBuffer;
8+
import java.nio.channels.FileChannel;
9+
import java.nio.charset.CharacterCodingException;
10+
import java.nio.charset.StandardCharsets;
11+
import java.nio.file.Files;
12+
import java.nio.file.Path;
13+
import java.nio.file.StandardOpenOption;
14+
15+
import org.junit.jupiter.api.Test;
16+
import org.junit.jupiter.api.io.TempDir;
17+
18+
public class MultiBufferTest {
19+
static MultiBuffer createBuffer(int chunkSize) {
20+
try {
21+
Path tmpFile = Files.createTempFile("test-data", ".bin");
22+
byte[] data = new byte[]{
23+
// uint16: 500
24+
(byte) 0xa2, 0x1, (byte) 0xf4,
25+
26+
// uint32: 10872
27+
(byte) 0xc2, 0x2a, 0x78,
28+
29+
// int32: 500
30+
0x2, 0x1, 0x1, (byte) 0xf4,
31+
32+
// boolean: true
33+
0x1, 0x7,
34+
35+
// double: 3.14159265359
36+
0x68, 0x40, 0x9, 0x21, (byte) 0xFB, 0x54, 0x44, 0x2E, (byte) 0xEA,
37+
38+
// float: 3.14f
39+
0x40, 0x48, (byte) 0xF5, (byte) 0xC3,
40+
41+
// string: "123"
42+
0x43, 0x31, 0x32, 0x33,
43+
44+
// pointer: 3017
45+
0x28, 0x3, (byte) 0xc9,
46+
47+
// array: ["Foo", "人"]
48+
0x2, 0x4,
49+
0x43, 0x46, 0x6f, 0x6f, // "Foo"
50+
0x43, (byte) 0xe4, (byte) 0xba, (byte) 0xba, // "人"
51+
52+
// map: {"en": "Foo", "zh": "人"}
53+
(byte) 0xe2,
54+
0x42, 0x65, 0x6e, // "en"
55+
0x43, 0x46, 0x6f, 0x6f, // "Foo"
56+
0x42, 0x7a, 0x68, // "zh"
57+
0x43, (byte) 0xe4, (byte) 0xba, (byte) 0xba, // "人"
58+
59+
// uint64: large value (2^16 - 1)
60+
0x2, 0x2, (byte) 0xff, (byte) 0xff,
61+
62+
// longer string: "123456789012345678901234567"
63+
0x5b, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30,
64+
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30,
65+
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
66+
};
67+
Files.write(tmpFile, data);
68+
69+
try (RandomAccessFile file = new RandomAccessFile(tmpFile.toFile(), "r");
70+
FileChannel channel = file.getChannel()) {
71+
72+
MultiBuffer buffer = new MultiBuffer(channel.size(), chunkSize);
73+
74+
buffer.readFrom(channel, chunkSize);
75+
buffer.position(0);
76+
buffer.limit(channel.size());
77+
78+
return buffer;
79+
}
80+
} catch (IOException e) {
81+
fail("Could not create test buffer: " + e.getMessage());
82+
return null;
83+
}
84+
}
85+
86+
@Test
87+
public void testPositionSetter() {
88+
MultiBuffer buffer = new MultiBuffer(1000);
89+
buffer.position(500);
90+
assertEquals(500, buffer.position());
91+
}
92+
93+
@Test
94+
public void testPositionSetterInvalidNegative() {
95+
MultiBuffer buffer = new MultiBuffer(1000);
96+
assertThrows(IllegalArgumentException.class, () -> buffer.position(-1));
97+
}
98+
99+
@Test
100+
public void testPositionSetterExceedsLimit() {
101+
MultiBuffer buffer = new MultiBuffer(1000);
102+
buffer.limit(500);
103+
assertThrows(IllegalArgumentException.class, () -> buffer.position(600));
104+
}
105+
106+
@Test
107+
public void testLimitSetter() {
108+
MultiBuffer buffer = new MultiBuffer(1000);
109+
buffer.limit(500);
110+
assertEquals(500, buffer.limit());
111+
}
112+
113+
@Test
114+
public void testLimitSetterInvalidNegative() {
115+
MultiBuffer buffer = new MultiBuffer(1000);
116+
assertThrows(IllegalArgumentException.class, () -> buffer.limit(-1));
117+
}
118+
119+
@Test
120+
public void testLimitSetterExceedsCapacity() {
121+
MultiBuffer buffer = new MultiBuffer(1000);
122+
assertThrows(IllegalArgumentException.class, () -> buffer.limit(1001));
123+
}
124+
125+
@Test
126+
public void testLimitSetterAdjustsPosition() {
127+
MultiBuffer buffer = new MultiBuffer(1000);
128+
buffer.position(800);
129+
buffer.limit(500);
130+
assertEquals(500, buffer.position());
131+
}
132+
133+
@Test
134+
public void testGetByIndex() {
135+
MultiBuffer buffer = createBuffer(24);
136+
assertEquals(0x2a, buffer.get(4));
137+
assertEquals(0x1, buffer.get(10));
138+
}
139+
140+
@Test
141+
public void testGetByIndexOutOfBounds() {
142+
MultiBuffer buffer = createBuffer(24);
143+
buffer.limit(50);
144+
assertThrows(IndexOutOfBoundsException.class, () -> buffer.get(50));
145+
assertThrows(IndexOutOfBoundsException.class, () -> buffer.get(-1));
146+
}
147+
148+
@Test
149+
public void testGetSingleByte() {
150+
MultiBuffer buffer = createBuffer(24);
151+
assertEquals((byte) 0xa2, buffer.get());
152+
assertEquals(1, buffer.position());
153+
}
154+
155+
@Test
156+
public void testGetByteArray() {
157+
MultiBuffer buffer = createBuffer(24);
158+
byte[] dst = new byte[10];
159+
buffer.position(32);
160+
buffer.get(dst);
161+
byte[] expectedBytes = new byte[]{
162+
0x2, 0x4,
163+
0x43, 0x46, 0x6f, 0x6f,
164+
0x43, (byte) 0xe4, (byte) 0xba, (byte) 0xba};
165+
assertArrayEquals(expectedBytes, dst);
166+
assertEquals(42, buffer.position());
167+
}
168+
169+
@Test
170+
public void testGetByteArrayExceedsLimit() {
171+
MultiBuffer buffer = new MultiBuffer(100);
172+
buffer.limit(5);
173+
byte[] dst = new byte[10];
174+
assertThrows(IndexOutOfBoundsException.class, () -> buffer.get(dst));
175+
}
176+
177+
@Test
178+
public void testGetByteArrayAcrossChunks() {
179+
MultiBuffer buffer = createBuffer(35);
180+
byte[] dst = new byte[10];
181+
buffer.position(32);
182+
buffer.get(dst);
183+
byte[] expectedBytes = new byte[]{
184+
0x2, 0x4,
185+
0x43, 0x46, 0x6f, 0x6f,
186+
0x43, (byte) 0xe4, (byte) 0xba, (byte) 0xba};
187+
assertArrayEquals(expectedBytes, dst);
188+
assertEquals(42, buffer.position());
189+
}
190+
191+
@Test
192+
public void testGetDouble() {
193+
MultiBuffer buffer = createBuffer(24);
194+
buffer.position(13);
195+
assertEquals(3.14159265359, buffer.getDouble());
196+
assertEquals(21, buffer.position());
197+
}
198+
199+
@Test
200+
public void testGetDoubleAcrossChunks() {
201+
MultiBuffer buffer = createBuffer(16);
202+
buffer.position(13);
203+
assertEquals(3.14159265359, buffer.getDouble());
204+
assertEquals(21, buffer.position());
205+
}
206+
207+
@Test
208+
public void testGetFloat() {
209+
MultiBuffer buffer = createBuffer(26);
210+
buffer.position(21);
211+
assertEquals(3.14f, buffer.getFloat());
212+
assertEquals(25, buffer.position());
213+
}
214+
215+
@Test
216+
public void testGetFloatAcrossChunks() {
217+
MultiBuffer buffer = createBuffer(22);
218+
buffer.position(21);
219+
assertEquals(3.14f, buffer.getFloat());
220+
assertEquals(25, buffer.position());
221+
}
222+
223+
@Test
224+
public void testDuplicate() {
225+
MultiBuffer original = new MultiBuffer(1000);
226+
original.position(100);
227+
original.limit(800);
228+
229+
MultiBuffer duplicate = (MultiBuffer) original.duplicate();
230+
231+
assertEquals(original.capacity(), duplicate.capacity());
232+
assertEquals(original.position(), duplicate.position());
233+
assertEquals(original.limit(), duplicate.limit());
234+
assertEquals(original.buffers.length, duplicate.buffers.length);
235+
236+
duplicate.position(200);
237+
assertEquals(100, original.position());
238+
assertEquals(200, duplicate.position());
239+
}
240+
241+
@Test
242+
public void testWrapValidChunks() {
243+
ByteBuffer[] chunks = new ByteBuffer[] {
244+
ByteBuffer.allocateDirect(MultiBuffer.DEFAULT_CHUNK_SIZE),
245+
ByteBuffer.allocateDirect(500)
246+
};
247+
248+
MultiBuffer buffer = MultiBuffer.wrap(chunks);
249+
assertEquals(MultiBuffer.DEFAULT_CHUNK_SIZE + 500, buffer.capacity());
250+
}
251+
252+
@Test
253+
public void testWrapInvalidChunkSize() {
254+
ByteBuffer[] chunks = new ByteBuffer[] {
255+
ByteBuffer.allocateDirect(500),
256+
ByteBuffer.allocateDirect(MultiBuffer.DEFAULT_CHUNK_SIZE)
257+
};
258+
259+
assertThrows(IllegalArgumentException.class, () -> MultiBuffer.wrap(chunks));
260+
}
261+
262+
@Test
263+
public void testReadFromFileChannel(@TempDir Path tempDir) throws IOException {
264+
// Create test file
265+
Path testFile = tempDir.resolve("test.dat");
266+
byte[] testData = new byte[]{
267+
(byte) 0xa2, 0x1, (byte) 0xf4,
268+
(byte) 0xc2, 0x2a, 0x78,
269+
0x2, 0x1, 0x1, (byte) 0xf4,
270+
0x1, 0x7,
271+
0x68, 0x40, 0x9, 0x21, (byte) 0xFB, 0x54, 0x44, 0x2E, (byte) 0xEA,
272+
};
273+
Files.write(testFile, testData);
274+
275+
try (FileChannel channel = FileChannel.open(testFile, StandardOpenOption.READ)) {
276+
MultiBuffer buffer = new MultiBuffer(testData.length);
277+
long bytesRead = buffer.readFrom(channel);
278+
assertEquals(21, bytesRead);
279+
assertEquals(21, buffer.position());
280+
}
281+
}
282+
283+
@Test
284+
public void testMapFromChannel(@TempDir Path tempDir) throws IOException {
285+
// Create test file
286+
Path testFile = tempDir.resolve("test.dat");
287+
byte[] testData = new byte[]{
288+
(byte) 0xa2, 0x1, (byte) 0xf4,
289+
(byte) 0xc2, 0x2a, 0x78,
290+
0x2, 0x1, 0x1, (byte) 0xf4,
291+
0x1, 0x7,
292+
0x68, 0x40, 0x9, 0x21, (byte) 0xFB, 0x54, 0x44, 0x2E, (byte) 0xEA,
293+
};
294+
Files.write(testFile, testData);
295+
296+
try (FileChannel channel = FileChannel.open(testFile, StandardOpenOption.READ)) {
297+
MultiBuffer buffer = MultiBuffer.mapFromChannel(channel);
298+
assertEquals(21, buffer.capacity());
299+
}
300+
}
301+
302+
@Test
303+
public void testMapFromEmptyChannel(@TempDir Path tempDir) throws IOException {
304+
Path emptyFile = tempDir.resolve("empty.dat");
305+
Files.createFile(emptyFile);
306+
307+
try (FileChannel channel = FileChannel.open(emptyFile, StandardOpenOption.READ)) {
308+
assertThrows(IllegalArgumentException.class, () -> MultiBuffer.mapFromChannel(channel));
309+
}
310+
}
311+
312+
@Test
313+
public void testDecodeString() throws CharacterCodingException {
314+
MultiBuffer buffer = createBuffer(22);
315+
buffer.position(26);
316+
buffer.limit(29);
317+
String result = buffer.decode(StandardCharsets.UTF_8.newDecoder());
318+
assertEquals("123", result);
319+
assertEquals(29, buffer.position());
320+
}
321+
322+
@Test
323+
public void testDecodeStringTooLarge() {
324+
MultiBuffer buffer = new MultiBuffer((long) Integer.MAX_VALUE + 1);
325+
assertThrows(IllegalStateException.class, () ->
326+
buffer.decode(StandardCharsets.UTF_8.newDecoder()));
327+
}
328+
329+
@Test
330+
public void testDecodeAcrossChunks() throws CharacterCodingException {
331+
MultiBuffer buffer = createBuffer(65);
332+
buffer.position(62);
333+
buffer.limit(89);
334+
String result = buffer.decode(StandardCharsets.UTF_8.newDecoder());
335+
assertEquals("123456789012345678901234567", result);
336+
assertEquals(89, buffer.position());
337+
}
338+
}

0 commit comments

Comments
 (0)