]>
Commit | Line | Data |
---|---|---|
1d09f67e TL |
1 | /* |
2 | * Licensed to the Apache Software Foundation (ASF) under one or more | |
3 | * contributor license agreements. See the NOTICE file distributed with | |
4 | * this work for additional information regarding copyright ownership. | |
5 | * The ASF licenses this file to You under the Apache License, Version 2.0 | |
6 | * (the "License"); you may not use this file except in compliance with | |
7 | * the License. You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, software | |
12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | * See the License for the specific language governing permissions and | |
15 | * limitations under the License. | |
16 | */ | |
17 | ||
18 | package org.apache.arrow.memory.util; | |
19 | ||
20 | import static junit.framework.TestCase.assertEquals; | |
21 | import static junit.framework.TestCase.assertTrue; | |
22 | import static org.junit.jupiter.api.Assertions.assertFalse; | |
23 | ||
24 | import org.apache.arrow.memory.ArrowBuf; | |
25 | import org.apache.arrow.memory.BufferAllocator; | |
26 | import org.apache.arrow.memory.RootAllocator; | |
27 | import org.apache.arrow.memory.util.hash.ArrowBufHasher; | |
28 | import org.apache.arrow.memory.util.hash.SimpleHasher; | |
29 | import org.junit.After; | |
30 | import org.junit.Before; | |
31 | import org.junit.Test; | |
32 | ||
33 | /** | |
34 | * Test cases for {@link ArrowBufPointer}. | |
35 | */ | |
36 | public class TestArrowBufPointer { | |
37 | ||
38 | private final int BUFFER_LENGTH = 1024; | |
39 | ||
40 | private BufferAllocator allocator; | |
41 | ||
42 | @Before | |
43 | public void prepare() { | |
44 | allocator = new RootAllocator(1024 * 1024); | |
45 | } | |
46 | ||
47 | @After | |
48 | public void shutdown() { | |
49 | allocator.close(); | |
50 | } | |
51 | ||
52 | @Test | |
53 | public void testArrowBufPointersEqual() { | |
54 | try (ArrowBuf buf1 = allocator.buffer(BUFFER_LENGTH); | |
55 | ArrowBuf buf2 = allocator.buffer(BUFFER_LENGTH)) { | |
56 | for (int i = 0; i < BUFFER_LENGTH / 4; i++) { | |
57 | buf1.setInt(i * 4, i * 1234); | |
58 | buf2.setInt(i * 4, i * 1234); | |
59 | } | |
60 | ||
61 | ArrowBufPointer ptr1 = new ArrowBufPointer(null, 0, 100); | |
62 | ArrowBufPointer ptr2 = new ArrowBufPointer(null, 100, 5032); | |
63 | assertTrue(ptr1.equals(ptr2)); | |
64 | for (int i = 0; i < BUFFER_LENGTH / 4; i++) { | |
65 | ptr1.set(buf1, i * 4, 4); | |
66 | ptr2.set(buf2, i * 4, 4); | |
67 | assertTrue(ptr1.equals(ptr2)); | |
68 | } | |
69 | } | |
70 | } | |
71 | ||
72 | @Test | |
73 | public void testArrowBufPointersHashCode() { | |
74 | final int vectorLength = 100; | |
75 | try (ArrowBuf buf1 = allocator.buffer(vectorLength * 4); | |
76 | ArrowBuf buf2 = allocator.buffer(vectorLength * 4)) { | |
77 | for (int i = 0; i < vectorLength; i++) { | |
78 | buf1.setInt(i * 4, i); | |
79 | buf2.setInt(i * 4, i); | |
80 | } | |
81 | ||
82 | CounterHasher hasher1 = new CounterHasher(); | |
83 | CounterHasher hasher2 = new CounterHasher(); | |
84 | ||
85 | ArrowBufPointer pointer1 = new ArrowBufPointer(hasher1); | |
86 | assertEquals(ArrowBufPointer.NULL_HASH_CODE, pointer1.hashCode()); | |
87 | ||
88 | ArrowBufPointer pointer2 = new ArrowBufPointer(hasher2); | |
89 | assertEquals(ArrowBufPointer.NULL_HASH_CODE, pointer2.hashCode()); | |
90 | ||
91 | for (int i = 0; i < vectorLength; i++) { | |
92 | pointer1.set(buf1, i * 4, 4); | |
93 | pointer2.set(buf2, i * 4, 4); | |
94 | ||
95 | assertEquals(pointer1.hashCode(), pointer2.hashCode()); | |
96 | ||
97 | // verify that the hash codes have been re-computed | |
98 | assertEquals(hasher1.counter, i + 1); | |
99 | assertEquals(hasher2.counter, i + 1); | |
100 | } | |
101 | } | |
102 | } | |
103 | ||
104 | @Test | |
105 | public void testNullPointersHashCode() { | |
106 | ArrowBufPointer pointer = new ArrowBufPointer(); | |
107 | assertEquals(ArrowBufPointer.NULL_HASH_CODE, pointer.hashCode()); | |
108 | ||
109 | pointer.set(null, 0, 0); | |
110 | assertEquals(ArrowBufPointer.NULL_HASH_CODE, pointer.hashCode()); | |
111 | } | |
112 | ||
113 | @Test | |
114 | public void testReuseHashCode() { | |
115 | try (ArrowBuf buf = allocator.buffer(10)) { | |
116 | buf.setInt(0, 10); | |
117 | buf.setInt(4, 20); | |
118 | ||
119 | CounterHasher hasher = new CounterHasher(); | |
120 | ArrowBufPointer pointer = new ArrowBufPointer(hasher); | |
121 | ||
122 | pointer.set(buf, 0, 4); | |
123 | pointer.hashCode(); | |
124 | ||
125 | // hash code computed | |
126 | assertEquals(1, hasher.counter); | |
127 | ||
128 | // no hash code re-compute | |
129 | pointer.hashCode(); | |
130 | assertEquals(1, hasher.counter); | |
131 | ||
132 | // hash code re-computed | |
133 | pointer.set(buf, 4, 4); | |
134 | pointer.hashCode(); | |
135 | assertEquals(2, hasher.counter); | |
136 | } | |
137 | } | |
138 | ||
139 | @Test | |
140 | public void testHashersForEquality() { | |
141 | try (ArrowBuf buf = allocator.buffer(10)) { | |
142 | // pointer 1 uses the default hasher | |
143 | ArrowBufPointer pointer1 = new ArrowBufPointer(buf, 0, 10); | |
144 | ||
145 | // pointer 2 uses the counter hasher | |
146 | ArrowBufPointer pointer2 = new ArrowBufPointer(buf, 0, 10, new CounterHasher()); | |
147 | ||
148 | // the two pointers cannot be equal, since they have different hashers | |
149 | assertFalse(pointer1.equals(pointer2)); | |
150 | } | |
151 | } | |
152 | ||
153 | @Test | |
154 | public void testArrowBufPointersComparison() { | |
155 | final int vectorLength = 100; | |
156 | try (ArrowBuf buf1 = allocator.buffer(vectorLength); | |
157 | ArrowBuf buf2 = allocator.buffer(vectorLength)) { | |
158 | for (int i = 0; i < vectorLength; i++) { | |
159 | buf1.setByte(i, i); | |
160 | buf2.setByte(i, i); | |
161 | } | |
162 | ||
163 | ArrowBufPointer pointer1 = new ArrowBufPointer(); | |
164 | ArrowBufPointer pointer2 = new ArrowBufPointer(); | |
165 | ||
166 | pointer1.set(buf1, 0, 10); | |
167 | pointer2.set(buf2, 0, 10); | |
168 | assertEquals(0, pointer1.compareTo(pointer2)); | |
169 | ||
170 | pointer1.set(null, 0, 0); | |
171 | pointer2.set(null, 0, 0); | |
172 | assertEquals(0, pointer1.compareTo(pointer2)); | |
173 | ||
174 | pointer2.set(buf2, 0, 5); | |
175 | assertTrue(pointer1.compareTo(pointer2) < 0); | |
176 | ||
177 | pointer1.set(buf1, 0, 10); | |
178 | assertTrue(pointer1.compareTo(pointer2) > 0); | |
179 | ||
180 | pointer1.set(buf1, 1, 5); | |
181 | pointer2.set(buf2, 3, 8); | |
182 | assertTrue(pointer1.compareTo(pointer2) < 0); | |
183 | } | |
184 | } | |
185 | ||
186 | /** | |
187 | * Hasher with a counter that increments each time a hash code is calculated. | |
188 | * This is to validate that the hash code in {@link ArrowBufPointer} is reused. | |
189 | */ | |
190 | class CounterHasher implements ArrowBufHasher { | |
191 | ||
192 | protected int counter = 0; | |
193 | ||
194 | @Override | |
195 | public int hashCode(long address, long length) { | |
196 | counter += 1; | |
197 | return SimpleHasher.INSTANCE.hashCode(address, length); | |
198 | } | |
199 | ||
200 | @Override | |
201 | public int hashCode(ArrowBuf buf, long offset, long length) { | |
202 | counter += 1; | |
203 | return SimpleHasher.INSTANCE.hashCode(buf, offset, length); | |
204 | } | |
205 | ||
206 | @Override | |
207 | public int hashCode() { | |
208 | return super.hashCode(); | |
209 | } | |
210 | ||
211 | @Override | |
212 | public boolean equals(Object o) { | |
213 | return o != null && this.getClass() == o.getClass(); | |
214 | } | |
215 | } | |
216 | } |