1 package org.apache.lucene.util;
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 import java.nio.CharBuffer;
21 import java.nio.ByteBuffer;
23 public class TestIndexableBinaryStringTools extends LuceneTestCase {
24 private static final int NUM_RANDOM_TESTS = atLeast(200);
25 private static final int MAX_RANDOM_BINARY_LENGTH = atLeast(300);
27 /** @deprecated remove this test for Lucene 4.0 */
29 public void testSingleBinaryRoundTripNIO() {
30 byte[] binary = new byte[]
31 { (byte)0x23, (byte)0x98, (byte)0x13, (byte)0xE4, (byte)0x76, (byte)0x41,
32 (byte)0xB2, (byte)0xC9, (byte)0x7F, (byte)0x0A, (byte)0xA6, (byte)0xD8 };
34 ByteBuffer binaryBuf = ByteBuffer.wrap(binary);
35 CharBuffer encoded = IndexableBinaryStringTools.encode(binaryBuf);
36 ByteBuffer decoded = IndexableBinaryStringTools.decode(encoded);
37 assertEquals("Round trip decode/decode returned different results:"
38 + System.getProperty("line.separator")
39 + "original: " + binaryDumpNIO(binaryBuf)
40 + System.getProperty("line.separator")
41 + " encoded: " + charArrayDumpNIO(encoded)
42 + System.getProperty("line.separator")
43 + " decoded: " + binaryDumpNIO(decoded),
47 public void testSingleBinaryRoundTrip() {
48 byte[] binary = new byte[] { (byte) 0x23, (byte) 0x98, (byte) 0x13,
49 (byte) 0xE4, (byte) 0x76, (byte) 0x41, (byte) 0xB2, (byte) 0xC9,
50 (byte) 0x7F, (byte) 0x0A, (byte) 0xA6, (byte) 0xD8 };
52 int encodedLen = IndexableBinaryStringTools.getEncodedLength(binary, 0,
54 char encoded[] = new char[encodedLen];
55 IndexableBinaryStringTools.encode(binary, 0, binary.length, encoded, 0,
58 int decodedLen = IndexableBinaryStringTools.getDecodedLength(encoded, 0,
60 byte decoded[] = new byte[decodedLen];
61 IndexableBinaryStringTools.decode(encoded, 0, encoded.length, decoded, 0,
64 assertEquals("Round trip decode/decode returned different results:"
65 + System.getProperty("line.separator") + "original: "
66 + binaryDump(binary, binary.length)
67 + System.getProperty("line.separator") + " encoded: "
68 + charArrayDump(encoded, encoded.length)
69 + System.getProperty("line.separator") + " decoded: "
70 + binaryDump(decoded, decoded.length),
71 binaryDump(binary, binary.length), binaryDump(decoded, decoded.length));
74 /** @deprecated remove this test for Lucene 4.0 */
76 public void testEncodedSortabilityNIO() {
77 byte[] originalArray1 = new byte[MAX_RANDOM_BINARY_LENGTH];
78 ByteBuffer originalBuf1 = ByteBuffer.wrap(originalArray1);
79 char[] originalString1 = new char[MAX_RANDOM_BINARY_LENGTH];
80 CharBuffer originalStringBuf1 = CharBuffer.wrap(originalString1);
81 char[] encoded1 = new char[IndexableBinaryStringTools.getEncodedLength(originalBuf1)];
82 CharBuffer encodedBuf1 = CharBuffer.wrap(encoded1);
83 byte[] original2 = new byte[MAX_RANDOM_BINARY_LENGTH];
84 ByteBuffer originalBuf2 = ByteBuffer.wrap(original2);
85 char[] originalString2 = new char[MAX_RANDOM_BINARY_LENGTH];
86 CharBuffer originalStringBuf2 = CharBuffer.wrap(originalString2);
87 char[] encoded2 = new char[IndexableBinaryStringTools.getEncodedLength(originalBuf2)];
88 CharBuffer encodedBuf2 = CharBuffer.wrap(encoded2);
89 for (int testNum = 0 ; testNum < NUM_RANDOM_TESTS ; ++testNum) {
90 int numBytes1 = random.nextInt(MAX_RANDOM_BINARY_LENGTH - 1) + 1; // Min == 1
91 originalBuf1.limit(numBytes1);
92 originalStringBuf1.limit(numBytes1);
94 for (int byteNum = 0 ; byteNum < numBytes1 ; ++byteNum) {
95 int randomInt = random.nextInt(0x100);
96 originalArray1[byteNum] = (byte) randomInt;
97 originalString1[byteNum] = (char)randomInt;
100 int numBytes2 = random.nextInt(MAX_RANDOM_BINARY_LENGTH - 1) + 1; // Min == 1
101 originalBuf2.limit(numBytes2);
102 originalStringBuf2.limit(numBytes2);
103 for (int byteNum = 0 ; byteNum < numBytes2 ; ++byteNum) {
104 int randomInt = random.nextInt(0x100);
105 original2[byteNum] = (byte)randomInt;
106 originalString2[byteNum] = (char)randomInt;
108 int originalComparison = originalStringBuf1.compareTo(originalStringBuf2);
109 originalComparison = originalComparison < 0 ? -1 : originalComparison > 0 ? 1 : 0;
111 IndexableBinaryStringTools.encode(originalBuf1, encodedBuf1);
112 IndexableBinaryStringTools.encode(originalBuf2, encodedBuf2);
114 int encodedComparison = encodedBuf1.compareTo(encodedBuf2);
115 encodedComparison = encodedComparison < 0 ? -1 : encodedComparison > 0 ? 1 : 0;
117 assertEquals("Test #" + (testNum + 1)
118 + ": Original bytes and encoded chars compare differently:"
119 + System.getProperty("line.separator")
120 + " binary 1: " + binaryDumpNIO(originalBuf1)
121 + System.getProperty("line.separator")
122 + " binary 2: " + binaryDumpNIO(originalBuf2)
123 + System.getProperty("line.separator")
124 + "encoded 1: " + charArrayDumpNIO(encodedBuf1)
125 + System.getProperty("line.separator")
126 + "encoded 2: " + charArrayDumpNIO(encodedBuf2)
127 + System.getProperty("line.separator"),
128 originalComparison, encodedComparison);
132 public void testEncodedSortability() {
133 byte[] originalArray1 = new byte[MAX_RANDOM_BINARY_LENGTH];
134 char[] originalString1 = new char[MAX_RANDOM_BINARY_LENGTH];
135 char[] encoded1 = new char[MAX_RANDOM_BINARY_LENGTH * 10];
136 byte[] original2 = new byte[MAX_RANDOM_BINARY_LENGTH];
137 char[] originalString2 = new char[MAX_RANDOM_BINARY_LENGTH];
138 char[] encoded2 = new char[MAX_RANDOM_BINARY_LENGTH * 10];
140 for (int testNum = 0; testNum < NUM_RANDOM_TESTS; ++testNum) {
141 int numBytes1 = random.nextInt(MAX_RANDOM_BINARY_LENGTH - 1) + 1; // Min == 1
143 for (int byteNum = 0; byteNum < numBytes1; ++byteNum) {
144 int randomInt = random.nextInt(0x100);
145 originalArray1[byteNum] = (byte) randomInt;
146 originalString1[byteNum] = (char) randomInt;
149 int numBytes2 = random.nextInt(MAX_RANDOM_BINARY_LENGTH - 1) + 1; // Min == 1
151 for (int byteNum = 0; byteNum < numBytes2; ++byteNum) {
152 int randomInt = random.nextInt(0x100);
153 original2[byteNum] = (byte) randomInt;
154 originalString2[byteNum] = (char) randomInt;
156 int originalComparison = new String(originalString1, 0, numBytes1)
157 .compareTo(new String(originalString2, 0, numBytes2));
158 originalComparison = originalComparison < 0 ? -1
159 : originalComparison > 0 ? 1 : 0;
161 int encodedLen1 = IndexableBinaryStringTools.getEncodedLength(
162 originalArray1, 0, numBytes1);
163 if (encodedLen1 > encoded1.length)
164 encoded1 = new char[ArrayUtil.oversize(encodedLen1, RamUsageEstimator.NUM_BYTES_CHAR)];
165 IndexableBinaryStringTools.encode(originalArray1, 0, numBytes1, encoded1,
168 int encodedLen2 = IndexableBinaryStringTools.getEncodedLength(original2,
170 if (encodedLen2 > encoded2.length)
171 encoded2 = new char[ArrayUtil.oversize(encodedLen2, RamUsageEstimator.NUM_BYTES_CHAR)];
172 IndexableBinaryStringTools.encode(original2, 0, numBytes2, encoded2, 0,
175 int encodedComparison = new String(encoded1, 0, encodedLen1)
176 .compareTo(new String(encoded2, 0, encodedLen2));
177 encodedComparison = encodedComparison < 0 ? -1
178 : encodedComparison > 0 ? 1 : 0;
180 assertEquals("Test #" + (testNum + 1)
181 + ": Original bytes and encoded chars compare differently:"
182 + System.getProperty("line.separator") + " binary 1: "
183 + binaryDump(originalArray1, numBytes1)
184 + System.getProperty("line.separator") + " binary 2: "
185 + binaryDump(original2, numBytes2)
186 + System.getProperty("line.separator") + "encoded 1: "
187 + charArrayDump(encoded1, encodedLen1)
188 + System.getProperty("line.separator") + "encoded 2: "
189 + charArrayDump(encoded2, encodedLen2)
190 + System.getProperty("line.separator"), originalComparison,
195 /** @deprecated remove this test for Lucene 4.0 */
197 public void testEmptyInputNIO() {
198 byte[] binary = new byte[0];
199 CharBuffer encoded = IndexableBinaryStringTools.encode(ByteBuffer.wrap(binary));
200 ByteBuffer decoded = IndexableBinaryStringTools.decode(encoded);
201 assertNotNull("decode() returned null", decoded);
202 assertEquals("decoded empty input was not empty", decoded.limit(), 0);
205 public void testEmptyInput() {
206 byte[] binary = new byte[0];
208 int encodedLen = IndexableBinaryStringTools.getEncodedLength(binary, 0,
210 char[] encoded = new char[encodedLen];
211 IndexableBinaryStringTools.encode(binary, 0, binary.length, encoded, 0,
214 int decodedLen = IndexableBinaryStringTools.getDecodedLength(encoded, 0,
216 byte[] decoded = new byte[decodedLen];
217 IndexableBinaryStringTools.decode(encoded, 0, encoded.length, decoded, 0,
220 assertEquals("decoded empty input was not empty", decoded.length, 0);
223 /** @deprecated remove this test for Lucene 4.0 */
225 public void testAllNullInputNIO() {
226 byte[] binary = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
227 ByteBuffer binaryBuf = ByteBuffer.wrap(binary);
228 CharBuffer encoded = IndexableBinaryStringTools.encode(binaryBuf);
229 assertNotNull("encode() returned null", encoded);
230 ByteBuffer decodedBuf = IndexableBinaryStringTools.decode(encoded);
231 assertNotNull("decode() returned null", decodedBuf);
232 assertEquals("Round trip decode/decode returned different results:"
233 + System.getProperty("line.separator")
234 + " original: " + binaryDumpNIO(binaryBuf)
235 + System.getProperty("line.separator")
236 + "decodedBuf: " + binaryDumpNIO(decodedBuf),
237 binaryBuf, decodedBuf);
240 public void testAllNullInput() {
241 byte[] binary = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
243 int encodedLen = IndexableBinaryStringTools.getEncodedLength(binary, 0,
245 char encoded[] = new char[encodedLen];
246 IndexableBinaryStringTools.encode(binary, 0, binary.length, encoded, 0,
249 int decodedLen = IndexableBinaryStringTools.getDecodedLength(encoded, 0,
251 byte[] decoded = new byte[decodedLen];
252 IndexableBinaryStringTools.decode(encoded, 0, encoded.length, decoded, 0,
255 assertEquals("Round trip decode/decode returned different results:"
256 + System.getProperty("line.separator") + " original: "
257 + binaryDump(binary, binary.length)
258 + System.getProperty("line.separator") + "decodedBuf: "
259 + binaryDump(decoded, decoded.length),
260 binaryDump(binary, binary.length), binaryDump(decoded, decoded.length));
263 /** @deprecated remove this test for Lucene 4.0 */
265 public void testRandomBinaryRoundTripNIO() {
266 byte[] binary = new byte[MAX_RANDOM_BINARY_LENGTH];
267 ByteBuffer binaryBuf = ByteBuffer.wrap(binary);
268 char[] encoded = new char[IndexableBinaryStringTools.getEncodedLength(binaryBuf)];
269 CharBuffer encodedBuf = CharBuffer.wrap(encoded);
270 byte[] decoded = new byte[MAX_RANDOM_BINARY_LENGTH];
271 ByteBuffer decodedBuf = ByteBuffer.wrap(decoded);
272 for (int testNum = 0 ; testNum < NUM_RANDOM_TESTS ; ++testNum) {
273 int numBytes = random.nextInt(MAX_RANDOM_BINARY_LENGTH - 1) + 1 ; // Min == 1
274 binaryBuf.limit(numBytes);
275 for (int byteNum = 0 ; byteNum < numBytes ; ++byteNum) {
276 binary[byteNum] = (byte)random.nextInt(0x100);
278 IndexableBinaryStringTools.encode(binaryBuf, encodedBuf);
279 IndexableBinaryStringTools.decode(encodedBuf, decodedBuf);
280 assertEquals("Test #" + (testNum + 1)
281 + ": Round trip decode/decode returned different results:"
282 + System.getProperty("line.separator")
283 + " original: " + binaryDumpNIO(binaryBuf)
284 + System.getProperty("line.separator")
285 + "encodedBuf: " + charArrayDumpNIO(encodedBuf)
286 + System.getProperty("line.separator")
287 + "decodedBuf: " + binaryDumpNIO(decodedBuf),
288 binaryBuf, decodedBuf);
292 public void testRandomBinaryRoundTrip() {
293 byte[] binary = new byte[MAX_RANDOM_BINARY_LENGTH];
294 char[] encoded = new char[MAX_RANDOM_BINARY_LENGTH * 10];
295 byte[] decoded = new byte[MAX_RANDOM_BINARY_LENGTH];
296 for (int testNum = 0; testNum < NUM_RANDOM_TESTS; ++testNum) {
297 int numBytes = random.nextInt(MAX_RANDOM_BINARY_LENGTH - 1) + 1; // Min == 1
299 for (int byteNum = 0; byteNum < numBytes; ++byteNum) {
300 binary[byteNum] = (byte) random.nextInt(0x100);
303 int encodedLen = IndexableBinaryStringTools.getEncodedLength(binary, 0,
305 if (encoded.length < encodedLen)
306 encoded = new char[ArrayUtil.oversize(encodedLen, RamUsageEstimator.NUM_BYTES_CHAR)];
307 IndexableBinaryStringTools.encode(binary, 0, numBytes, encoded, 0,
310 int decodedLen = IndexableBinaryStringTools.getDecodedLength(encoded, 0,
312 IndexableBinaryStringTools.decode(encoded, 0, encodedLen, decoded, 0,
315 assertEquals("Test #" + (testNum + 1)
316 + ": Round trip decode/decode returned different results:"
317 + System.getProperty("line.separator") + " original: "
318 + binaryDump(binary, numBytes) + System.getProperty("line.separator")
319 + "encodedBuf: " + charArrayDump(encoded, encodedLen)
320 + System.getProperty("line.separator") + "decodedBuf: "
321 + binaryDump(decoded, decodedLen), binaryDump(binary, numBytes),
322 binaryDump(decoded, decodedLen));
326 /** @deprecated remove this method for Lucene 4.0 */
328 public String binaryDumpNIO(ByteBuffer binaryBuf) {
329 return binaryDump(binaryBuf.array(),
330 binaryBuf.limit() - binaryBuf.arrayOffset());
333 public String binaryDump(byte[] binary, int numBytes) {
334 StringBuilder buf = new StringBuilder();
335 for (int byteNum = 0 ; byteNum < numBytes ; ++byteNum) {
336 String hex = Integer.toHexString(binary[byteNum] & 0xFF);
337 if (hex.length() == 1) {
340 buf.append(hex.toUpperCase());
341 if (byteNum < numBytes - 1) {
345 return buf.toString();
347 /** @deprecated remove this method for Lucene 4.0 */
349 public String charArrayDumpNIO(CharBuffer charBuf) {
350 return charArrayDump(charBuf.array(),
351 charBuf.limit() - charBuf.arrayOffset());
354 public String charArrayDump(char[] charArray, int numBytes) {
355 StringBuilder buf = new StringBuilder();
356 for (int charNum = 0 ; charNum < numBytes ; ++charNum) {
357 String hex = Integer.toHexString(charArray[charNum]);
358 for (int digit = 0 ; digit < 4 - hex.length() ; ++digit) {
361 buf.append(hex.toUpperCase());
362 if (charNum < numBytes - 1) {
366 return buf.toString();