1 package org.apache.lucene.facet.taxonomy;
3 import java.io.ByteArrayInputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.io.IOException;
6 import java.io.InputStreamReader;
7 import java.io.OutputStreamWriter;
11 import org.apache.lucene.util.LuceneTestCase;
12 import org.apache.lucene.facet.taxonomy.CategoryPath;
15 * Licensed to the Apache Software Foundation (ASF) under one or more
16 * contributor license agreements. See the NOTICE file distributed with
17 * this work for additional information regarding copyright ownership.
18 * The ASF licenses this file to You under the Apache License, Version 2.0
19 * (the "License"); you may not use this file except in compliance with
20 * the License. You may obtain a copy of the License at
22 * http://www.apache.org/licenses/LICENSE-2.0
24 * Unless required by applicable law or agreed to in writing, software
25 * distributed under the License is distributed on an "AS IS" BASIS,
26 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27 * See the License for the specific language governing permissions and
28 * limitations under the License.
31 public class TestCategoryPath extends LuceneTestCase {
34 public void testBasic() {
35 CategoryPath p = new CategoryPath(0,0);
36 assertEquals(0, p.length());
37 for (int i=0; i<1000; i++) {
39 assertEquals(i+1, p.length());
44 public void testConstructorCapacity() {
45 CategoryPath p = new CategoryPath(0,0);
46 assertEquals(0, p.capacityChars());
47 assertEquals(0, p.capacityComponents());
48 assertEquals(0, p.length());
49 p = new CategoryPath(5,18);
50 assertEquals(5, p.capacityChars());
51 assertEquals(18, p.capacityComponents());
52 assertEquals(0, p.length());
53 p = new CategoryPath(27,13);
54 assertEquals(27, p.capacityChars());
55 assertEquals(13, p.capacityComponents());
56 assertEquals(0, p.length());
60 public void testClear() {
61 CategoryPath p = new CategoryPath(0,0);
64 assertEquals(2, p.length());
66 assertEquals(0, p.length());
68 assertEquals(1, p.length());
72 public void testTrim() {
73 CategoryPath p = new CategoryPath(0,0);
82 assertEquals(8, p.length());
84 assertEquals(5, p.length());
86 assertEquals(5, p.length());
88 assertEquals(5, p.length());
90 assertEquals(4, p.length());
92 assertEquals(0, p.length());
94 assertEquals(1, p.length());
96 assertEquals(0, p.length());
100 public void testComponentsLimit() {
101 // Test that we can add up to 2^15-1 components
102 CategoryPath p = new CategoryPath(0,0);
103 for (int i=0; i<32767; i++) {
105 assertEquals(i+1, p.length());
107 // Also see that in the current implementation, this is actually
108 // the limit: if we add one more component, things break (because
109 // we used a short to hold ncomponents). See that it breaks in the
110 // way we expect it to:
111 p.add(""); // this still works, but...
112 assertEquals(-32768, p.length()); // now the length is wrong and negative
116 public void testCharsLimit() {
117 // Test that we can add up to 2^15-1 characters
118 CategoryPath p = new CategoryPath(0,0);
119 for (int i=0; i<8192; i++) {
122 // Also see that in the current implementation, this is actually the
123 // limit: If we add one more character, things break (because ends[]
124 // is an array of shorts), and we actually get an exception.
127 fail("Should have thrown an exception");
128 } catch (ArrayIndexOutOfBoundsException e) {
134 public void testToString() {
135 CategoryPath p = new CategoryPath(0,0);
136 // When the category is empty, we expect an empty string
137 assertEquals("", p.toString('/'));
138 // This is (deliberately, in our implementation) indistinguishable
139 // from the case of a single empty component:
141 assertEquals("", p.toString('/'));
142 // Check just one category (so no delimiter needed):
145 assertEquals("hello", p.toString('/'));
146 // Now for two categories:
150 assertEquals("hello/world", p.toString('/'));
151 // And for a thousand...
154 StringBuilder expected = new StringBuilder("0");
155 for (int i=1; i<1000; i++) {
156 String num = Integer.toString(i);
158 expected.append('/');
159 expected.append(num);
161 assertEquals(expected.toString(), p.toString('/'));
162 // Check that toString() without a parameter just defaults to '/':
163 assertEquals(expected.toString(), p.toString());
166 // testing toString() and its variants already test most of the appendTo()
167 // code, but not all of it (the "eclemma" code-coverage tool discovered
168 // this for us). Here we complete the coverage of the appendTo() methods:
170 public void testAppendTo() throws IOException {
171 CategoryPath p = new CategoryPath(0,0);
172 StringBuilder sb = new StringBuilder();
174 assertEquals(0, sb.length());
175 p.appendTo(sb, '/', -1);
176 assertEquals(0, sb.length());
177 p.appendTo(sb, '/', 1);
178 assertEquals(0, sb.length());
179 p.appendTo(sb, '/', -1, 1);
180 assertEquals(0, sb.length());
184 public void testLastComponent() {
185 CategoryPath p = new CategoryPath(1000,1000);
186 // When the category is empty, we expect a null
187 assertNull(p.lastComponent());
188 for (int i=0; i<=100; i++) {
189 String num = Integer.toString(i);
191 assertEquals(num, p.lastComponent());
196 public void testGetComponent() {
197 CategoryPath p = new CategoryPath(1000,1000);
198 // When the category is empty, we expect a null
199 assertNull(p.getComponent(0));
200 assertNull(p.getComponent(1));
201 assertNull(p.getComponent(-1));
202 for (int i=0; i<=100; i++) {
203 p.add(Integer.toString(i));
204 for (int j=0; j<=i; j++) {
205 assertEquals(j, Integer.parseInt(p.getComponent(j)));
207 assertNull(p.getComponent(-1));
208 assertNull(p.getComponent(i+1));
213 public void testToStringPrefix() {
214 CategoryPath p = new CategoryPath(0,0);
218 assertEquals("hi/there/man", p.toString('/'));
219 assertEquals("", p.toString('/', 0));
220 assertEquals("hi", p.toString('/', 1));
221 assertEquals("hi/there", p.toString('/', 2));
222 assertEquals("hi/there/man", p.toString('/', 3));
223 assertEquals("hi/there/man", p.toString('/', 4));
224 assertEquals("hi/there/man", p.toString('/', -1));
228 public void testToStringSubpath() {
229 CategoryPath p = new CategoryPath(0,0);
230 assertEquals("", p.toString('/', 0, 0));
234 assertEquals("", p.toString('/', 0, 0));
235 assertEquals("hi", p.toString('/', 0, 1));
236 assertEquals("hi/there", p.toString('/', 0, 2));
237 assertEquals("hi/there/man", p.toString('/', 0, 3));
238 assertEquals("hi/there/man", p.toString('/', 0, 4));
239 assertEquals("hi/there/man", p.toString('/', 0, -1));
240 assertEquals("hi/there/man", p.toString('/', -1, -1));
241 assertEquals("there/man", p.toString('/', 1, -1));
242 assertEquals("man", p.toString('/', 2, -1));
243 assertEquals("", p.toString('/', 3, -1));
244 assertEquals("there/man", p.toString('/', 1, 3));
245 assertEquals("there", p.toString('/', 1, 2));
246 assertEquals("", p.toString('/', 1, 1));
250 public void testDelimiterConstructor() {
251 // Test that the constructor that takes a string and a delimiter
252 // works correctly. Also check that it allocates exactly the needed
253 // needed size for the array - not more.
254 CategoryPath p = new CategoryPath("", '/');
255 assertEquals(p.length(), 0);
256 assertEquals(p.capacityChars(), 0);
257 assertEquals(p.capacityComponents(), 0);
258 p = new CategoryPath("hello", '/');
259 assertEquals(p.length(), 1);
260 assertEquals(p.capacityChars(), 5);
261 assertEquals(p.capacityComponents(), 1);
262 assertEquals(p.toString('@'), "hello");
263 p = new CategoryPath("hi/there", '/');
264 assertEquals(p.length(), 2);
265 assertEquals(p.capacityChars(), 7);
266 assertEquals(p.capacityComponents(), 2);
267 assertEquals(p.toString('@'), "hi@there");
268 p = new CategoryPath("how/are/you/doing?", '/');
269 assertEquals(p.length(), 4);
270 assertEquals(p.capacityChars(), 15);
271 assertEquals(p.capacityComponents(), 4);
272 assertEquals(p.toString('@'), "how@are@you@doing?");
276 public void testDefaultConstructor() {
277 // test that the default constructor (no parameters) currently
278 // defaults to creating an object with a 0 initial capacity.
279 // If we change this default later, we also need to change this
281 CategoryPath p = new CategoryPath();
282 assertEquals(0, p.capacityChars());
283 assertEquals(0, p.capacityComponents());
284 assertEquals(0, p.length());
285 assertEquals("", p.toString('/'));
289 public void testAddEmpty() {
290 // In the current implementation, p.add("") should add en empty
291 // component (which is, admitingly, not a useful case. On the other
292 // hand, p.add("", delimiter) should add no components at all.
294 CategoryPath p = new CategoryPath(0, 0);
296 assertEquals(1, p.length());
298 assertEquals(2, p.length());
300 assertEquals(2, p.length());
303 assertEquals(0, p.length());
307 public void testDelimiterAdd() {
308 // Test that the add() that takes a string and a delimiter
309 // works correctly. Note that unlike the constructor test above,
310 // we can't expect the capacity to grow to exactly the length of
311 // the given category, so we do not test this.
312 CategoryPath p = new CategoryPath(0, 0);
314 assertEquals(0, p.length());
315 assertEquals("", p.toString('@'), "");
318 assertEquals(p.length(), 1);
319 assertEquals(p.toString('@'), "hello");
321 p.add("hi/there", '/');
322 assertEquals(p.length(), 2);
323 assertEquals(p.toString('@'), "hi@there");
325 p.add("how/are/you/doing?", '/');
326 assertEquals(p.length(), 4);
327 assertEquals(p.toString('@'), "how@are@you@doing?");
328 // See that this is really an add, not replace:
330 p.add("hi/there", '/');
331 assertEquals(p.length(), 2);
332 assertEquals(p.toString('@'), "hi@there");
333 p.add("how/are/you/doing", '/');
334 assertEquals(p.length(), 6);
335 assertEquals(p.toString('@'), "hi@there@how@are@you@doing");
339 public void testCopyConstructor() {
340 CategoryPath p = new CategoryPath(0,0);
342 for (int i=0; i<1000; i++) {
343 CategoryPath clone = new CategoryPath(p);
344 assertEquals(p.length(), clone.length());
345 assertEquals(p.toString('/'), clone.toString('/'));
346 // verify that the newly created clone has exactly the right
347 // capacity, with no spare (while the original path p probably
349 assertEquals(i, clone.capacityComponents());
350 assertEquals(expectedchars, clone.capacityChars());
351 // Finally, add another component to the path, for the next
352 // round of this loop
353 String num = Integer.toString(i);
355 expectedchars+=num.length();
360 public void testPrefixCopyConstructor() {
361 CategoryPath p = new CategoryPath(0,0);
365 assertEquals(p.length(), 3);
367 CategoryPath p1 = new CategoryPath(p,2);
368 assertEquals(2, p1.length());
369 assertEquals("hi/there", p1.toString('/'));
370 // the new prefix object should only take the space it needs:
371 assertEquals(2, p1.capacityComponents());
372 assertEquals(7, p1.capacityChars());
374 p1 = new CategoryPath(p,1);
375 assertEquals(1, p1.length());
376 assertEquals("hi", p1.toString('/'));
377 assertEquals(1, p1.capacityComponents());
378 assertEquals(2, p1.capacityChars());
380 p1 = new CategoryPath(p,0);
381 assertEquals(0, p1.length());
382 assertEquals("", p1.toString('/'));
383 assertEquals(0, p1.capacityComponents());
384 assertEquals(0, p1.capacityChars());
386 // with all the following lengths, the prefix should be the whole path:
387 int[] lengths = { 3, -1, 4 };
388 for (int i=0; i<lengths.length; i++) {
389 p1 = new CategoryPath(p, lengths[i]);
390 assertEquals(3, p1.length());
391 assertEquals("hi/there/man", p1.toString('/'));
393 assertEquals(3, p1.capacityComponents());
394 assertEquals(10, p1.capacityChars());
399 public void testEquals() {
400 // check that two empty paths are equal, even if they have different
402 CategoryPath p1 = new CategoryPath(0,0);
403 CategoryPath p2 = new CategoryPath(1000,300);
404 assertEquals(true, p1.equals(p2));
405 // If we make p2 different, it is no longer equals:
407 assertEquals(false, p1.equals(p2));
408 // A categoryPath is definitely not equals to an object of some other
410 assertEquals(false, p1.equals(Integer.valueOf(3)));
411 // Build two paths separately, and compare them
418 assertEquals(true, p1.equals(p2));
419 // Check that comparison really don't look at old data which might
420 // be stored in the array
422 p1.add("averylongcategoryname");
427 assertEquals(true, p1.equals(p2));
428 // Being of the same length is obviously not enough to be equal
433 assertEquals(false, p1.equals(p2));
438 assertEquals(false, p1.equals(p2));
441 public void testHashCode() {
442 // Note: in this test, we assume that if two paths are not equal,
443 // their hash codes should come out differently. This is *not*
444 // always the case, but in the examples we use below, it comes out
445 // fine, and unless we have some really bad luck in changing our
446 // hash function, this should also remain true in the future.
448 // check that two empty paths are equal, even if they have different
450 CategoryPath p1 = new CategoryPath(0,0);
451 CategoryPath p2 = new CategoryPath(1000,300);
452 assertEquals(p1.hashCode(), p2.hashCode());
453 // If we make p2 different, it is no longer equals:
455 assertEquals(false, p1.hashCode()==p2.hashCode());
456 // Build two paths separately, and compare them
463 assertEquals(p1.hashCode(), p2.hashCode());
464 // Check that comparison really don't look at old data which might
465 // be stored in the array
467 p1.add("averylongcategoryname");
472 assertEquals(p1.hashCode(), p2.hashCode());
473 // Being of the same length is obviously not enough to be equal
478 assertEquals(false, p1.hashCode()==p2.hashCode());
483 assertEquals(false, p1.hashCode()==p2.hashCode());
487 public void testHashCodePrefix() {
488 // First, repeat the tests of testHashCode() using hashCode(-1)
489 // just to make sure nothing was broken in this variant:
490 CategoryPath p1 = new CategoryPath(0,0);
491 CategoryPath p2 = new CategoryPath(1000,300);
492 assertEquals(p1.hashCode(-1), p2.hashCode(-1));
494 assertEquals(false, p1.hashCode(-1)==p2.hashCode(-1));
501 assertEquals(p1.hashCode(-1), p2.hashCode(-1));
503 p1.add("averylongcategoryname");
508 assertEquals(p1.hashCode(-1), p2.hashCode(-1));
513 assertEquals(false, p1.hashCode(-1)==p2.hashCode(-1));
518 assertEquals(false, p1.hashCode(-1)==p2.hashCode(-1));
520 // Now move to testing prefixes:
521 CategoryPath p = new CategoryPath();
526 assertEquals(p.hashCode(), p.hashCode(4));
527 assertEquals(new CategoryPath().hashCode(), p.hashCode(0));
528 assertEquals(new CategoryPath(p, 1).hashCode(), p.hashCode(1));
529 assertEquals(new CategoryPath(p, 2).hashCode(), p.hashCode(2));
530 assertEquals(new CategoryPath(p, 3).hashCode(), p.hashCode(3));
534 public void testLongHashCode() {
535 // Note: in this test, we assume that if two paths are not equal,
536 // their hash codes should come out differently. This is *not*
537 // always the case, but in the examples we use below, it comes out
538 // fine, and unless we have some really bad luck in changing our
539 // hash function, this should also remain true in the future.
541 // check that two empty paths are equal, even if they have different
543 CategoryPath p1 = new CategoryPath(0,0);
544 CategoryPath p2 = new CategoryPath(1000,300);
545 assertEquals(p1.longHashCode(), p2.longHashCode());
546 // If we make p2 different, it is no longer equals:
548 assertEquals(false, p1.longHashCode()==p2.longHashCode());
549 // Build two paths separately, and compare them
556 assertEquals(p1.longHashCode(), p2.longHashCode());
557 // Check that comparison really don't look at old data which might
558 // be stored in the array
560 p1.add("averylongcategoryname");
565 assertEquals(p1.longHashCode(), p2.longHashCode());
566 // Being of the same length is obviously not enough to be equal
571 assertEquals(false, p1.longHashCode()==p2.longHashCode());
576 assertEquals(false, p1.longHashCode()==p2.longHashCode());
580 public void testLongHashCodePrefix() {
581 // First, repeat the tests of testLongHashCode() using longHashCode(-1)
582 // just to make sure nothing was broken in this variant:
584 // check that two empty paths are equal, even if they have different
586 CategoryPath p1 = new CategoryPath(0,0);
587 CategoryPath p2 = new CategoryPath(1000,300);
588 assertEquals(p1.longHashCode(-1), p2.longHashCode(-1));
589 // If we make p2 different, it is no longer equals:
591 assertEquals(false, p1.longHashCode(-1)==p2.longHashCode(-1));
592 // Build two paths separately, and compare them
599 assertEquals(p1.longHashCode(-1), p2.longHashCode(-1));
600 // Check that comparison really don't look at old data which might
601 // be stored in the array
603 p1.add("averylongcategoryname");
608 assertEquals(p1.longHashCode(-1), p2.longHashCode(-1));
609 // Being of the same length is obviously not enough to be equal
614 assertEquals(false, p1.longHashCode(-1)==p2.longHashCode(-1));
619 assertEquals(false, p1.longHashCode(-1)==p2.longHashCode(-1));
621 // Now move to testing prefixes:
622 CategoryPath p = new CategoryPath();
627 assertEquals(p.longHashCode(), p.longHashCode(4));
628 assertEquals(new CategoryPath().longHashCode(), p.longHashCode(0));
629 assertEquals(new CategoryPath(p, 1).longHashCode(), p.longHashCode(1));
630 assertEquals(new CategoryPath(p, 2).longHashCode(), p.longHashCode(2));
631 assertEquals(new CategoryPath(p, 3).longHashCode(), p.longHashCode(3));
635 public void testArrayConstructor() {
636 CategoryPath p = new CategoryPath("hello", "world", "yo");
637 assertEquals(3, p.length());
638 assertEquals(12, p.capacityChars());
639 assertEquals(3, p.capacityComponents());
640 assertEquals("hello/world/yo", p.toString('/'));
642 p = new CategoryPath(new String[0]);
643 assertEquals(0, p.length());
644 assertEquals(0, p.capacityChars());
645 assertEquals(0, p.capacityComponents());
649 public void testCharsNeededForFullPath() {
650 String[] components = { "hello", "world", "yo" };
651 CategoryPath p = new CategoryPath();
652 assertEquals(0, p.charsNeededForFullPath());
653 int expectedCharsNeeded = 0;
654 for (int i=0; i<components.length; i++) {
655 p.add(components[i]);
656 expectedCharsNeeded += components[i].length();
658 expectedCharsNeeded++;
660 assertEquals(expectedCharsNeeded, p.charsNeededForFullPath());
665 public void testCopyToCharArray() {
666 String[] components = { "hello", "world", "yo" };
667 CategoryPath p = new CategoryPath(components);
668 char[] charArray = new char[p.charsNeededForFullPath()];
669 int numCharsCopied = 0;
671 numCharsCopied = p.copyToCharArray(charArray, 0, 0, '.');
672 assertEquals(0, numCharsCopied);
673 assertEquals("", new String(charArray, 0, numCharsCopied));
675 numCharsCopied = p.copyToCharArray(charArray, 0, 1, '.');
676 assertEquals(5, numCharsCopied);
677 assertEquals("hello", new String(charArray, 0, numCharsCopied));
679 numCharsCopied = p.copyToCharArray(charArray, 0, 3, '.');
680 assertEquals(14, numCharsCopied);
681 assertEquals("hello.world.yo", new String(charArray, 0, numCharsCopied));
683 numCharsCopied = p.copyToCharArray(charArray, 0, -1, '.');
684 assertEquals(14, numCharsCopied);
685 assertEquals("hello.world.yo", new String(charArray, 0, numCharsCopied));
686 numCharsCopied = p.copyToCharArray(charArray, 0, 4, '.');
687 assertEquals(14, numCharsCopied);
688 assertEquals("hello.world.yo", new String(charArray, 0, numCharsCopied));
692 public void testCharSerialization() throws Exception {
693 CategoryPath[] testCategories = {
694 new CategoryPath("hi", "there", "man"),
695 new CategoryPath("hello"),
696 new CategoryPath("what's", "up"),
697 // See that an empty category, which generates a (char)0,
698 // doesn't cause any problems in the middle of the serialization:
700 new CategoryPath("another", "example"),
704 StringBuilder sb = new StringBuilder();
705 for (int i=0; i<testCategories.length; i++) {
706 testCategories[i].serializeAppendTo(sb);
709 CategoryPath tmp = new CategoryPath();
711 for (int i=0; i<testCategories.length; i++) {
712 // check equalsToSerialized, in a equal and non-equal case:
713 assertTrue(testCategories[i].equalsToSerialized(sb, offset));
714 assertFalse(new CategoryPath("Hello", "world").equalsToSerialized(sb, offset));
715 assertFalse(new CategoryPath("world").equalsToSerialized(sb, offset));
716 // and check hashCodeFromSerialized:
717 assertEquals(testCategories[i].hashCode(), CategoryPath.hashCodeOfSerialized(sb, offset));
718 // and check setFromSerialized:
719 offset = tmp.setFromSerialized(sb, offset);
720 assertEquals(testCategories[i], tmp);
722 assertEquals(offset, sb.length());
723 // A similar test, for a much longer path (though not larger than the
724 // 2^15-1 character limit that CategoryPath allows:
725 sb = new StringBuilder();
726 CategoryPath p = new CategoryPath();
727 for (int i=0; i<1000; i++) {
728 p.add(Integer.toString(i));
730 p.serializeAppendTo(sb);
731 p.serializeAppendTo(sb);
732 p.serializeAppendTo(sb);
734 assertTrue(p.equalsToSerialized(sb, offset));
735 assertEquals(p.hashCode(), CategoryPath.hashCodeOfSerialized(sb, offset));
736 offset = tmp.setFromSerialized(sb, offset);
737 assertEquals(p, tmp);
738 assertTrue(p.equalsToSerialized(sb, offset));
739 assertEquals(p.hashCode(), CategoryPath.hashCodeOfSerialized(sb, offset));
740 offset = tmp.setFromSerialized(sb, offset);
741 assertEquals(p, tmp);
742 assertTrue(p.equalsToSerialized(sb, offset));
743 assertEquals(p.hashCode(), CategoryPath.hashCodeOfSerialized(sb, offset));
744 offset = tmp.setFromSerialized(sb, offset);
745 assertEquals(p, tmp);
746 assertEquals(offset, sb.length());
748 // Test the serializeAppendTo variant with a prefixLen
749 p = new CategoryPath();
750 for (int i=0; i<783; i++) {
751 p.add(Integer.toString(i));
753 int[] prefixLengths = { 0, 574, 782, 783, 784, -1 };
754 for (int prefixLen : prefixLengths) {
755 sb = new StringBuilder();
756 p.serializeAppendTo(prefixLen, sb);
757 assertTrue(new CategoryPath(p, prefixLen).equalsToSerialized(sb, 0));
760 // Test the equalsToSerialized variant with a prefixLen
761 // We use p and prefixLengths set above.
762 for (int prefixLen : prefixLengths) {
763 sb = new StringBuilder();
764 new CategoryPath(p, prefixLen).serializeAppendTo(sb);
765 assertTrue(p.equalsToSerialized(prefixLen, sb, 0));
768 // Check also the false case of equalsToSerialized with prefixLen:
769 sb = new StringBuilder();
770 new CategoryPath().serializeAppendTo(sb);
771 assertTrue(new CategoryPath().equalsToSerialized(0, sb, 0));
772 assertTrue(new CategoryPath("a", "b").equalsToSerialized(0, sb, 0));
773 assertFalse(new CategoryPath("a", "b").equalsToSerialized(1, sb, 0));
774 sb = new StringBuilder();
775 new CategoryPath("a", "b").serializeAppendTo(sb);
776 assertFalse(new CategoryPath().equalsToSerialized(0, sb, 0));
777 assertFalse(new CategoryPath("a").equalsToSerialized(0, sb, 0));
778 assertFalse(new CategoryPath("a").equalsToSerialized(1, sb, 0));
779 assertFalse(new CategoryPath("a", "b").equalsToSerialized(0, sb, 0));
780 assertFalse(new CategoryPath("a", "b").equalsToSerialized(1, sb, 0));
781 assertTrue(new CategoryPath("a", "b").equalsToSerialized(2, sb, 0));
782 assertTrue(new CategoryPath("a", "b", "c").equalsToSerialized(2, sb, 0));
783 assertFalse(new CategoryPath("z", "b", "c").equalsToSerialized(2, sb, 0));
784 assertFalse(new CategoryPath("aa", "b", "c").equalsToSerialized(2, sb, 0));
788 public void testStreamWriterSerialization() throws Exception {
789 CategoryPath[] testPaths = {
790 new CategoryPath("hi", "there", "man"),
791 new CategoryPath("hello"),
792 new CategoryPath("date", "2009", "May", "13", "14", "59", "00"),
793 // See that an empty category, which generates a (char)0,
794 // doesn't cause any problems in the middle of the serialization:
796 new CategoryPath("another", "example")
798 ByteArrayOutputStream baos = new ByteArrayOutputStream();
799 OutputStreamWriter osw = new OutputStreamWriter(baos, "UTF-8"); // UTF-8 is always supported.
800 for (CategoryPath cp : testPaths) {
801 cp.serializeToStreamWriter(osw);
804 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
805 InputStreamReader isr = new InputStreamReader(bais, "UTF-8");
806 CategoryPath[] checkPaths = {
807 new CategoryPath(), new CategoryPath(), new CategoryPath(), new CategoryPath(), new CategoryPath()
809 for (int j = 0; j < checkPaths.length; j++) {
810 checkPaths[j].deserializeFromStreamReader(isr);
811 assertEquals("Paths not equal", testPaths[j], checkPaths[j]);
816 public void testCharSequenceCtor() throws Exception {
817 CategoryPath[] testPaths = {
818 new CategoryPath(new CS("hi"), new CS("there"), new CS("man")),
819 new CategoryPath(new CS("hello")),
820 new CategoryPath(new CS("date"), new CS("2009"), new CS("May"), new CS("13"),
821 new CS("14"), new CS("59"), new CS("00")),
823 new CategoryPath(new CS("another"), new CS("example"))
825 assertEquals("Wrong capacity", 10, testPaths[0].capacityChars());
826 assertEquals("Wrong capacity", 5, testPaths[1].capacityChars());
827 assertEquals("Wrong capacity", 19, testPaths[2].capacityChars());
828 assertEquals("Wrong capacity", 0, testPaths[3].capacityChars());
829 assertEquals("Wrong capacity", 14, testPaths[4].capacityChars());
831 assertEquals("Wrong component", "hi", testPaths[0].getComponent(0));
832 assertEquals("Wrong component", "there", testPaths[0].getComponent(1));
833 assertEquals("Wrong component", "man", testPaths[0].getComponent(2));
834 assertEquals("Wrong component", "hello", testPaths[1].getComponent(0));
835 assertEquals("Wrong component", "date", testPaths[2].getComponent(0));
836 assertEquals("Wrong component", "2009", testPaths[2].getComponent(1));
837 assertEquals("Wrong component", "May", testPaths[2].getComponent(2));
838 assertEquals("Wrong component", "13", testPaths[2].getComponent(3));
839 assertEquals("Wrong component", "14", testPaths[2].getComponent(4));
840 assertEquals("Wrong component", "59", testPaths[2].getComponent(5));
841 assertEquals("Wrong component", "00", testPaths[2].getComponent(6));
842 assertNull("Not null component", testPaths[3].getComponent(0));
843 assertEquals("Wrong component", "another", testPaths[4].getComponent(0));
844 assertEquals("Wrong component", "example", testPaths[4].getComponent(1));
848 public void testIsDescendantOf() throws Exception {
849 CategoryPath[] testPaths = {
850 new CategoryPath(new CS("hi"), new CS("there")),
851 new CategoryPath(new CS("hi"), new CS("there"), new CS("man")),
852 new CategoryPath(new CS("hithere"), new CS("man")),
853 new CategoryPath(new CS("hi"), new CS("there"), new CS("mano")),
856 assertTrue(testPaths[0].isDescendantOf(testPaths[0]));
857 assertTrue(testPaths[0].isDescendantOf(testPaths[4]));
858 assertFalse(testPaths[4].isDescendantOf(testPaths[0]));
859 assertTrue(testPaths[1].isDescendantOf(testPaths[0]));
860 assertTrue(testPaths[1].isDescendantOf(testPaths[1]));
861 assertTrue(testPaths[3].isDescendantOf(testPaths[0]));
862 assertFalse(testPaths[2].isDescendantOf(testPaths[0]));
863 assertFalse(testPaths[2].isDescendantOf(testPaths[1]));
864 assertFalse(testPaths[3].isDescendantOf(testPaths[1]));
868 public void testCompareTo() {
869 CategoryPath p = new CategoryPath("a/b/c/d", '/');
870 CategoryPath pother = new CategoryPath("a/b/c/d", '/');
871 assertTrue(pother.compareTo(p) == 0);
872 pother = new CategoryPath("", '/');
873 assertTrue(pother.compareTo(p) < 0);
874 pother = new CategoryPath("a/b_/c/d", '/');
875 assertTrue(pother.compareTo(p) > 0);
876 pother = new CategoryPath("a/b/c", '/');
877 assertTrue(pother.compareTo(p) < 0);
878 pother = new CategoryPath("a/b/c/e", '/');
879 assertTrue(pother.compareTo(p) > 0);
880 pother = new CategoryPath("a/b/c//e", '/');
881 assertTrue(pother.compareTo(p) < 0);
884 private static class CS implements CharSequence {
885 public CS(String s) {
886 this.ca = new char[s.length()];
887 s.getChars(0, s.length(), this.ca, 0);
889 public char charAt(int index) {
890 return this.ca[index];
892 public int length() {
893 return this.ca.length;
895 public CharSequence subSequence(int start, int end) {
896 return null; // not used.