You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sh...@apache.org on 2013/03/10 16:05:21 UTC

svn commit: r1454862 [24/49] - in /lucene/dev/branches/lucene4258: ./ dev-tools/ dev-tools/eclipse/ dev-tools/idea/.idea/ dev-tools/idea/.idea/libraries/ dev-tools/idea/lucene/demo/ dev-tools/idea/lucene/facet/ dev-tools/idea/lucene/highlighter/ dev-to...

Modified: lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestCategoryPath.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestCategoryPath.java?rev=1454862&r1=1454861&r2=1454862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestCategoryPath.java (original)
+++ lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestCategoryPath.java Sun Mar 10 15:04:57 2013
@@ -1,16 +1,10 @@
 package org.apache.lucene.facet.taxonomy;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
+import java.util.Arrays;
 
+import org.apache.lucene.facet.FacetTestCase;
 import org.junit.Test;
 
-import org.apache.lucene.util.LuceneTestCase;
-import org.apache.lucene.facet.taxonomy.CategoryPath;
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -28,877 +22,199 @@ import org.apache.lucene.facet.taxonomy.
  * limitations under the License.
  */
 
-public class TestCategoryPath extends LuceneTestCase {
+public class TestCategoryPath extends FacetTestCase {
   
   @Test 
   public void testBasic() {
-    CategoryPath p = new CategoryPath(0,0);
-    assertEquals(0, p.length());
-    for (int i=0; i<1000; i++) {
-      p.add("hello");
-      assertEquals(i+1, p.length());
-    }
-  }
-  
-  @Test 
-  public void testConstructorCapacity() {
-    CategoryPath p = new CategoryPath(0,0);
-    assertEquals(0, p.capacityChars());
-    assertEquals(0, p.capacityComponents());
-    assertEquals(0, p.length());
-    p = new CategoryPath(5,18);
-    assertEquals(5, p.capacityChars());
-    assertEquals(18, p.capacityComponents());
-    assertEquals(0, p.length());
-    p = new CategoryPath(27,13);
-    assertEquals(27, p.capacityChars());
-    assertEquals(13, p.capacityComponents());
-    assertEquals(0, p.length());
-  }
-  
-  @Test 
-  public void testClear() {
-    CategoryPath p = new CategoryPath(0,0);
-    p.add("hi");
-    p.add("there");
-    assertEquals(2, p.length());
-    p.clear();
-    assertEquals(0, p.length());
-    p.add("yo!");
-    assertEquals(1, p.length());
-  }
-
-  @Test 
-  public void testTrim() {
-    CategoryPath p = new CategoryPath(0,0);
-    p.add("this");
-    p.add("message");
-    p.add("will");
-    p.add("self");
-    p.add("destruct");
-    p.add("in");
-    p.add("five");
-    p.add("seconds");
-    assertEquals(8, p.length());
-    p.trim(3);
-    assertEquals(5, p.length());
-    p.trim(0); // no-op
-    assertEquals(5, p.length());
-    p.trim(-3);  // no-op
-    assertEquals(5, p.length());
-    p.trim(1);
-    assertEquals(4, p.length());
-    p.trim(8); // clear
-    assertEquals(0, p.length());
-    p.add("yo!");
-    assertEquals(1, p.length());
-    p.trim(1); // clear
-    assertEquals(0, p.length());
-  }
-
-  @Test 
-  public void testComponentsLimit() {
-    // Test that we can add up to 2^15-1 components
-    CategoryPath p = new CategoryPath(0,0);
-    for (int i=0; i<32767; i++) {
-      p.add("");
-      assertEquals(i+1, p.length());
-    }
-    // Also see that in the current implementation, this is actually
-    // the limit: if we add one more component, things break (because
-    // we used a short to hold ncomponents). See that it breaks in the
-    // way we expect it to:
-    p.add(""); // this still works, but...
-    assertEquals(-32768, p.length()); // now the length is wrong and negative
-  }
-  
-  @Test 
-  public void testCharsLimit() {
-    // Test that we can add up to 2^15-1 characters
-    CategoryPath p = new CategoryPath(0,0);
-    for (int i=0; i<8192; i++) {
-      p.add("aaaa");
-    }
-    // Also see that in the current implementation, this is actually the
-    // limit: If we add one more character, things break (because ends[]
-    // is an array of shorts), and we actually get an exception.
-    try {
-      p.add("a");
-      fail("Should have thrown an exception");
-    } catch (ArrayIndexOutOfBoundsException e) {
-      // good.
-    }
+    assertEquals(0, CategoryPath.EMPTY.length);
+    assertEquals(1, new CategoryPath("hello").length);
+    assertEquals(2, new CategoryPath("hello", "world").length);
   }
   
   @Test 
   public void testToString() {
-    CategoryPath p = new CategoryPath(0,0);
     // When the category is empty, we expect an empty string
-    assertEquals("", p.toString('/'));
-    // This is (deliberately, in our implementation) indistinguishable
-    // from the case of a single empty component:
-    p.add("");
-    assertEquals("", p.toString('/'));
-    // Check just one category (so no delimiter needed):
-    p.clear();
-    p.add("hello");
-    assertEquals("hello", p.toString('/'));
-    // Now for two categories:
-    p.clear();
-    p.add("hello");
-    p.add("world");
-    assertEquals("hello/world", p.toString('/'));
-    // And for a thousand...
-    p.clear();
-    p.add("0");
-    StringBuilder expected = new StringBuilder("0");
-    for (int i=1; i<1000; i++) {
-      String num = Integer.toString(i);
-      p.add(num);
-      expected.append('/');
-      expected.append(num);
-    }
-    assertEquals(expected.toString(), p.toString('/'));
-    // Check that toString() without a parameter just defaults to '/':
-    assertEquals(expected.toString(), p.toString());
-  }
-
-  // testing toString() and its variants already test most of the appendTo()
-  // code, but not all of it (the "eclemma" code-coverage tool discovered
-  // this for us). Here we complete the coverage of the appendTo() methods:
-  @Test 
-  public void testAppendTo() throws IOException {
-    CategoryPath p = new CategoryPath(0,0);
-    StringBuilder sb = new StringBuilder();
-    p.appendTo(sb, '/');
-    assertEquals(0, sb.length());
-    p.appendTo(sb, '/', -1);
-    assertEquals(0, sb.length());
-    p.appendTo(sb, '/', 1);
-    assertEquals(0, sb.length());
-    p.appendTo(sb, '/', -1, 1);
-    assertEquals(0, sb.length());
+    assertEquals("", CategoryPath.EMPTY.toString('/'));
+    // one category (so no delimiter needed)
+    assertEquals("hello", new CategoryPath("hello").toString('/'));
+    // more than one category (so no delimiter needed)
+    assertEquals("hello/world", new CategoryPath("hello", "world").toString('/'));
   }
-  
-  @Test 
-  public void testLastComponent() {
-    CategoryPath p = new CategoryPath(1000,1000);
-    // When the category is empty, we expect a null
-    assertNull(p.lastComponent());
-    for (int i=0; i<=100; i++) {
-      String num = Integer.toString(i);
-      p.add(num);
-      assertEquals(num, p.lastComponent());
-    }
-  }
-  
+
   @Test 
   public void testGetComponent() {
-    CategoryPath p = new CategoryPath(1000,1000);
-    // When the category is empty, we expect a null
-    assertNull(p.getComponent(0));
-    assertNull(p.getComponent(1));
-    assertNull(p.getComponent(-1));
-    for (int i=0; i<=100; i++) {
-      p.add(Integer.toString(i));
-      for (int j=0; j<=i; j++) {
-        assertEquals(j, Integer.parseInt(p.getComponent(j)));
-      }
-      assertNull(p.getComponent(-1));
-      assertNull(p.getComponent(i+1));
+    String[] components = new String[atLeast(10)];
+    for (int i = 0; i < components.length; i++) {
+      components[i] = Integer.toString(i);
+    }
+    CategoryPath cp = new CategoryPath(components);
+    for (int i = 0; i < components.length; i++) {
+      assertEquals(i, Integer.parseInt(cp.components[i]));
     }
   }
 
-  @Test 
-  public void testToStringPrefix() {
-    CategoryPath p = new CategoryPath(0,0);
-    p.add("hi");
-    p.add("there");
-    p.add("man");
-    assertEquals("hi/there/man", p.toString('/'));
-    assertEquals("", p.toString('/', 0));
-    assertEquals("hi", p.toString('/', 1));
-    assertEquals("hi/there", p.toString('/', 2));
-    assertEquals("hi/there/man", p.toString('/', 3));
-    assertEquals("hi/there/man", p.toString('/', 4));
-    assertEquals("hi/there/man", p.toString('/', -1));
-  }
-
-  @Test 
-  public void testToStringSubpath() {
-    CategoryPath p = new CategoryPath(0,0);
-    assertEquals("", p.toString('/', 0, 0));
-    p.add("hi");
-    p.add("there");
-    p.add("man");
-    assertEquals("", p.toString('/', 0, 0));
-    assertEquals("hi", p.toString('/', 0, 1));
-    assertEquals("hi/there", p.toString('/', 0, 2));
-    assertEquals("hi/there/man", p.toString('/', 0, 3));
-    assertEquals("hi/there/man", p.toString('/', 0, 4));
-    assertEquals("hi/there/man", p.toString('/', 0, -1));
-    assertEquals("hi/there/man", p.toString('/', -1, -1));
-    assertEquals("there/man", p.toString('/', 1, -1));
-    assertEquals("man", p.toString('/', 2, -1));
-    assertEquals("", p.toString('/', 3, -1));
-    assertEquals("there/man", p.toString('/', 1, 3));
-    assertEquals("there", p.toString('/', 1, 2));
-    assertEquals("", p.toString('/', 1, 1));
-  }
-
-  @Test 
+  @Test
   public void testDelimiterConstructor() {
-    // Test that the constructor that takes a string and a delimiter
-    // works correctly. Also check that it allocates exactly the needed
-    // needed size for the array - not more.
     CategoryPath p = new CategoryPath("", '/');
-    assertEquals(p.length(), 0);
-    assertEquals(p.capacityChars(), 0);
-    assertEquals(p.capacityComponents(), 0);
+    assertEquals(0, p.length);
     p = new CategoryPath("hello", '/');
-    assertEquals(p.length(), 1);
-    assertEquals(p.capacityChars(), 5);
-    assertEquals(p.capacityComponents(), 1);
+    assertEquals(p.length, 1);
     assertEquals(p.toString('@'), "hello");
     p = new CategoryPath("hi/there", '/');
-    assertEquals(p.length(), 2);
-    assertEquals(p.capacityChars(), 7);
-    assertEquals(p.capacityComponents(), 2);
+    assertEquals(p.length, 2);
     assertEquals(p.toString('@'), "hi@there");
     p = new CategoryPath("how/are/you/doing?", '/');
-    assertEquals(p.length(), 4);
-    assertEquals(p.capacityChars(), 15);
-    assertEquals(p.capacityComponents(), 4);
+    assertEquals(p.length, 4);
     assertEquals(p.toString('@'), "how@are@you@doing?");
   }
   
-  @Test 
+  @Test
   public void testDefaultConstructor() {
     // test that the default constructor (no parameters) currently
     // defaults to creating an object with a 0 initial capacity.
     // If we change this default later, we also need to change this
     // test.
-    CategoryPath p = new CategoryPath();
-    assertEquals(0, p.capacityChars());
-    assertEquals(0, p.capacityComponents());
-    assertEquals(0, p.length());
+    CategoryPath p = CategoryPath.EMPTY;
+    assertEquals(0, p.length);
     assertEquals("", p.toString('/'));
   }
   
   @Test 
-  public void testAddEmpty() {
-    // In the current implementation, p.add("") should add en empty
-    // component (which is, admitingly, not a useful case. On the other
-    // hand, p.add("", delimiter) should add no components at all.
-    // Verify this:
-    CategoryPath p = new CategoryPath(0, 0);
-    p.add("");
-    assertEquals(1, p.length());
-    p.add("");
-    assertEquals(2, p.length());
-    p.add("", '/');
-    assertEquals(2, p.length());
-    p.clear();
-    p.add("", '/');
-    assertEquals(0, p.length());
-  }
-  
-  @Test 
-  public void testDelimiterAdd() {
-    // Test that the add() that takes a string and a delimiter
-    // works correctly. Note that unlike the constructor test above,
-    // we can't expect the capacity to grow to exactly the length of
-    // the given category, so we do not test this.
-    CategoryPath p = new CategoryPath(0, 0);
-    p.add("", '/');
-    assertEquals(0, p.length());
-    assertEquals("", p.toString('@'), "");
-    p.clear();
-    p.add("hello", '/');
-    assertEquals(p.length(), 1);
-    assertEquals(p.toString('@'), "hello");
-    p.clear();
-    p.add("hi/there", '/');
-    assertEquals(p.length(), 2);
-    assertEquals(p.toString('@'), "hi@there");
-    p.clear();
-    p.add("how/are/you/doing?", '/');
-    assertEquals(p.length(), 4);
-    assertEquals(p.toString('@'), "how@are@you@doing?");
-    // See that this is really an add, not replace:
-    p.clear();
-    p.add("hi/there", '/');
-    assertEquals(p.length(), 2);
-    assertEquals(p.toString('@'), "hi@there");
-    p.add("how/are/you/doing", '/');
-    assertEquals(p.length(), 6);
-    assertEquals(p.toString('@'), "hi@there@how@are@you@doing");
-  }
-  
-  @Test 
-  public void testCopyConstructor() {
-    CategoryPath p = new CategoryPath(0,0);
-    int expectedchars=0;
-    for (int i=0; i<1000; i++) {
-      CategoryPath clone = new CategoryPath(p);
-      assertEquals(p.length(), clone.length());
-      assertEquals(p.toString('/'), clone.toString('/'));
-      // verify that the newly created clone has exactly the right
-      // capacity, with no spare (while the original path p probably
-      // does have spare)
-      assertEquals(i, clone.capacityComponents());
-      assertEquals(expectedchars, clone.capacityChars());
-      // Finally, add another component to the path, for the next
-      // round of this loop
-      String num = Integer.toString(i);
-      p.add(num);
-      expectedchars+=num.length();
-    }
-  }
-
-  @Test 
-  public void testPrefixCopyConstructor() {
-    CategoryPath p = new CategoryPath(0,0);
-    p.add("hi");
-    p.add("there");
-    p.add("man");
-    assertEquals(p.length(), 3);
+  public void testSubPath() {
+    final CategoryPath p = new CategoryPath("hi", "there", "man");
+    assertEquals(p.length, 3);
     
-    CategoryPath p1 = new CategoryPath(p,2);
-    assertEquals(2, p1.length());
+    CategoryPath p1 = p.subpath(2);
+    assertEquals(2, p1.length);
     assertEquals("hi/there", p1.toString('/'));
-    // the new prefix object should only take the space it needs: 
-    assertEquals(2, p1.capacityComponents());
-    assertEquals(7, p1.capacityChars());
 
-    p1 = new CategoryPath(p,1);
-    assertEquals(1, p1.length());
+    p1 = p.subpath(1);
+    assertEquals(1, p1.length);
     assertEquals("hi", p1.toString('/'));
-    assertEquals(1, p1.capacityComponents());
-    assertEquals(2, p1.capacityChars());
 
-    p1 = new CategoryPath(p,0);
-    assertEquals(0, p1.length());
+    p1 = p.subpath(0);
+    assertEquals(0, p1.length);
     assertEquals("", p1.toString('/'));
-    assertEquals(0, p1.capacityComponents());
-    assertEquals(0, p1.capacityChars());
 
-    // with all the following lengths, the prefix should be the whole path: 
+    // with all the following lengths, the prefix should be the whole path 
     int[] lengths = { 3, -1, 4 };
-    for (int i=0; i<lengths.length; i++) {
-      p1 = new CategoryPath(p, lengths[i]);
-      assertEquals(3, p1.length());
+    for (int i = 0; i < lengths.length; i++) {
+      p1 = p.subpath(lengths[i]);
+      assertEquals(3, p1.length);
       assertEquals("hi/there/man", p1.toString('/'));
       assertEquals(p, p1);
-      assertEquals(3, p1.capacityComponents());
-      assertEquals(10, p1.capacityChars());
     }
   }
 
   @Test 
   public void testEquals() {
-    // check that two empty paths are equal, even if they have different
-    // capacities:
-    CategoryPath p1 = new CategoryPath(0,0);
-    CategoryPath p2 = new CategoryPath(1000,300);
-    assertEquals(true, p1.equals(p2));
-    // If we make p2 different, it is no longer equals:
-    p2.add("hi");
-    assertEquals(false, p1.equals(p2));
-    // A categoryPath is definitely not equals to an object of some other
-    // type:
-    assertEquals(false, p1.equals(Integer.valueOf(3)));
-    // Build two paths separately, and compare them
-    p1.clear();
-    p1.add("hello");
-    p1.add("world");
-    p2.clear();
-    p2.add("hello");
-    p2.add("world");
-    assertEquals(true, p1.equals(p2));    
-    // Check that comparison really don't look at old data which might
-    // be stored in the array
-    p1.clear();
-    p1.add("averylongcategoryname");
-    p1.clear();
-    p1.add("hi");
-    p2.clear();
-    p2.add("hi");
-    assertEquals(true, p1.equals(p2));
-    // Being of the same length is obviously not enough to be equal
-    p1.clear();
-    p1.add("hi");
-    p2.clear();
-    p2.add("hello");
-    assertEquals(false, p1.equals(p2));
-    p1.clear();
-    p1.add("hi");
-    p2.clear();
-    p2.add("ho");
-    assertEquals(false, p1.equals(p2));
+    assertEquals(CategoryPath.EMPTY, CategoryPath.EMPTY);
+    assertFalse(CategoryPath.EMPTY.equals(new CategoryPath("hi")));
+    assertFalse(CategoryPath.EMPTY.equals(Integer.valueOf(3)));
+    assertEquals(new CategoryPath("hello", "world"), new CategoryPath("hello", "world"));    
   }
+  
   @Test 
   public void testHashCode() {
-    // Note: in this test, we assume that if two paths are not equal,
-    // their hash codes should come out differently. This is *not*
-    // always the case, but in the examples we use below, it comes out
-    // fine, and unless we have some really bad luck in changing our
-    // hash function, this should also remain true in the future.
-    
-    // check that two empty paths are equal, even if they have different
-    // capacities:
-    CategoryPath p1 = new CategoryPath(0,0);
-    CategoryPath p2 = new CategoryPath(1000,300);
-    assertEquals(p1.hashCode(), p2.hashCode());
-    // If we make p2 different, it is no longer equals:
-    p2.add("hi");
-    assertEquals(false, p1.hashCode()==p2.hashCode());
-    // Build two paths separately, and compare them
-    p1.clear();
-    p1.add("hello");
-    p1.add("world");
-    p2.clear();
-    p2.add("hello");
-    p2.add("world");
-    assertEquals(p1.hashCode(), p2.hashCode());
-    // Check that comparison really don't look at old data which might
-    // be stored in the array
-    p1.clear();
-    p1.add("averylongcategoryname");
-    p1.clear();
-    p1.add("hi");
-    p2.clear();
-    p2.add("hi");
-    assertEquals(p1.hashCode(), p2.hashCode());
-    // Being of the same length is obviously not enough to be equal
-    p1.clear();
-    p1.add("hi");
-    p2.clear();
-    p2.add("hello");
-    assertEquals(false, p1.hashCode()==p2.hashCode());
-    p1.clear();
-    p1.add("hi");
-    p2.clear();
-    p2.add("ho");
-    assertEquals(false, p1.hashCode()==p2.hashCode());
-  }
-  
-  @Test 
-  public void testHashCodePrefix() {
-    // First, repeat the tests of testHashCode() using hashCode(-1)
-    // just to make sure nothing was broken in this variant:
-    CategoryPath p1 = new CategoryPath(0,0);
-    CategoryPath p2 = new CategoryPath(1000,300);
-    assertEquals(p1.hashCode(-1), p2.hashCode(-1));
-    p2.add("hi");
-    assertEquals(false, p1.hashCode(-1)==p2.hashCode(-1));
-    p1.clear();
-    p1.add("hello");
-    p1.add("world");
-    p2.clear();
-    p2.add("hello");
-    p2.add("world");
-    assertEquals(p1.hashCode(-1), p2.hashCode(-1));
-    p1.clear();
-    p1.add("averylongcategoryname");
-    p1.clear();
-    p1.add("hi");
-    p2.clear();
-    p2.add("hi");
-    assertEquals(p1.hashCode(-1), p2.hashCode(-1));
-    p1.clear();
-    p1.add("hi");
-    p2.clear();
-    p2.add("hello");
-    assertEquals(false, p1.hashCode(-1)==p2.hashCode(-1));
-    p1.clear();
-    p1.add("hi");
-    p2.clear();
-    p2.add("ho");
-    assertEquals(false, p1.hashCode(-1)==p2.hashCode(-1));
-    
-    // Now move to testing prefixes:
-    CategoryPath p = new CategoryPath();
-    p.add("this");
-    p.add("is");
-    p.add("a");
-    p.add("test");
-    assertEquals(p.hashCode(), p.hashCode(4));
-    assertEquals(new CategoryPath().hashCode(), p.hashCode(0));
-    assertEquals(new CategoryPath(p, 1).hashCode(), p.hashCode(1));
-    assertEquals(new CategoryPath(p, 2).hashCode(), p.hashCode(2));
-    assertEquals(new CategoryPath(p, 3).hashCode(), p.hashCode(3));
-  }
-
-  @Test 
-  public void testLongHashCode() {
-    // Note: in this test, we assume that if two paths are not equal,
-    // their hash codes should come out differently. This is *not*
-    // always the case, but in the examples we use below, it comes out
-    // fine, and unless we have some really bad luck in changing our
-    // hash function, this should also remain true in the future.
-    
-    // check that two empty paths are equal, even if they have different
-    // capacities:
-    CategoryPath p1 = new CategoryPath(0,0);
-    CategoryPath p2 = new CategoryPath(1000,300);
-    assertEquals(p1.longHashCode(), p2.longHashCode());
-    // If we make p2 different, it is no longer equals:
-    p2.add("hi");
-    assertEquals(false, p1.longHashCode()==p2.longHashCode());
-    // Build two paths separately, and compare them
-    p1.clear();
-    p1.add("hello");
-    p1.add("world");
-    p2.clear();
-    p2.add("hello");
-    p2.add("world");
-    assertEquals(p1.longHashCode(), p2.longHashCode());
-    // Check that comparison really don't look at old data which might
-    // be stored in the array
-    p1.clear();
-    p1.add("averylongcategoryname");
-    p1.clear();
-    p1.add("hi");
-    p2.clear();
-    p2.add("hi");
-    assertEquals(p1.longHashCode(), p2.longHashCode());
-    // Being of the same length is obviously not enough to be equal
-    p1.clear();
-    p1.add("hi");
-    p2.clear();
-    p2.add("hello");
-    assertEquals(false, p1.longHashCode()==p2.longHashCode());
-    p1.clear();
-    p1.add("hi");
-    p2.clear();
-    p2.add("ho");
-    assertEquals(false, p1.longHashCode()==p2.longHashCode());
+    assertEquals(CategoryPath.EMPTY.hashCode(), CategoryPath.EMPTY.hashCode());
+    assertFalse(CategoryPath.EMPTY.hashCode() == new CategoryPath("hi").hashCode());
+    assertEquals(new CategoryPath("hello", "world").hashCode(), new CategoryPath("hello", "world").hashCode());
   }
   
   @Test 
-  public void testLongHashCodePrefix() {
-    // First, repeat the tests of testLongHashCode() using longHashCode(-1)
-    // just to make sure nothing was broken in this variant:
-    
-    // check that two empty paths are equal, even if they have different
-    // capacities:
-    CategoryPath p1 = new CategoryPath(0,0);
-    CategoryPath p2 = new CategoryPath(1000,300);
-    assertEquals(p1.longHashCode(-1), p2.longHashCode(-1));
-    // If we make p2 different, it is no longer equals:
-    p2.add("hi");
-    assertEquals(false, p1.longHashCode(-1)==p2.longHashCode(-1));
-    // Build two paths separately, and compare them
-    p1.clear();
-    p1.add("hello");
-    p1.add("world");
-    p2.clear();
-    p2.add("hello");
-    p2.add("world");
-    assertEquals(p1.longHashCode(-1), p2.longHashCode(-1));
-    // Check that comparison really don't look at old data which might
-    // be stored in the array
-    p1.clear();
-    p1.add("averylongcategoryname");
-    p1.clear();
-    p1.add("hi");
-    p2.clear();
-    p2.add("hi");
-    assertEquals(p1.longHashCode(-1), p2.longHashCode(-1));
-    // Being of the same length is obviously not enough to be equal
-    p1.clear();
-    p1.add("hi");
-    p2.clear();
-    p2.add("hello");
-    assertEquals(false, p1.longHashCode(-1)==p2.longHashCode(-1));
-    p1.clear();
-    p1.add("hi");
-    p2.clear();
-    p2.add("ho");
-    assertEquals(false, p1.longHashCode(-1)==p2.longHashCode(-1));
-    
-    // Now move to testing prefixes:
-    CategoryPath p = new CategoryPath();
-    p.add("this");
-    p.add("is");
-    p.add("a");
-    p.add("test");
-    assertEquals(p.longHashCode(), p.longHashCode(4));
-    assertEquals(new CategoryPath().longHashCode(), p.longHashCode(0));
-    assertEquals(new CategoryPath(p, 1).longHashCode(), p.longHashCode(1));
-    assertEquals(new CategoryPath(p, 2).longHashCode(), p.longHashCode(2));
-    assertEquals(new CategoryPath(p, 3).longHashCode(), p.longHashCode(3));
+  public void testLongHashCode() {
+    assertEquals(CategoryPath.EMPTY.longHashCode(), CategoryPath.EMPTY.longHashCode());
+    assertFalse(CategoryPath.EMPTY.longHashCode() == new CategoryPath("hi").longHashCode());
+    assertEquals(new CategoryPath("hello", "world").longHashCode(), new CategoryPath("hello", "world").longHashCode());
   }
   
   @Test 
   public void testArrayConstructor() {
     CategoryPath p = new CategoryPath("hello", "world", "yo");
-    assertEquals(3, p.length());
-    assertEquals(12, p.capacityChars());
-    assertEquals(3, p.capacityComponents());
+    assertEquals(3, p.length);
     assertEquals("hello/world/yo", p.toString('/'));
-    
-    p = new CategoryPath(new String[0]);
-    assertEquals(0, p.length());
-    assertEquals(0, p.capacityChars());
-    assertEquals(0, p.capacityComponents());
   }
   
   @Test 
   public void testCharsNeededForFullPath() {
+    assertEquals(0, CategoryPath.EMPTY.fullPathLength());
     String[] components = { "hello", "world", "yo" };
-    CategoryPath p = new CategoryPath();
-    assertEquals(0, p.charsNeededForFullPath());
+    CategoryPath cp = new CategoryPath(components);
     int expectedCharsNeeded = 0;
-    for (int i=0; i<components.length; i++) {
-      p.add(components[i]);
-      expectedCharsNeeded += components[i].length();
-      if (i>0) {
-        expectedCharsNeeded++;
-      }
-      assertEquals(expectedCharsNeeded, p.charsNeededForFullPath());
+    for (String comp : components) {
+      expectedCharsNeeded += comp.length();
     }
+    expectedCharsNeeded += cp.length - 1; // delimiter chars
+    assertEquals(expectedCharsNeeded, cp.fullPathLength());
   }
   
   @Test 
   public void testCopyToCharArray() {
-    String[] components = { "hello", "world", "yo" };
-    CategoryPath p = new CategoryPath(components);
-    char[] charArray = new char[p.charsNeededForFullPath()];
-    int numCharsCopied = 0;
-    
-    numCharsCopied = p.copyToCharArray(charArray, 0, 0, '.');
-    assertEquals(0, numCharsCopied);
-    assertEquals("", new String(charArray, 0, numCharsCopied));
-    
-    numCharsCopied = p.copyToCharArray(charArray, 0, 1, '.');
-    assertEquals(5, numCharsCopied);
-    assertEquals("hello", new String(charArray, 0, numCharsCopied));
-    
-    numCharsCopied = p.copyToCharArray(charArray, 0, 3, '.');
-    assertEquals(14, numCharsCopied);
-    assertEquals("hello.world.yo", new String(charArray, 0, numCharsCopied));
-    
-    numCharsCopied = p.copyToCharArray(charArray, 0, -1, '.');
-    assertEquals(14, numCharsCopied);
-    assertEquals("hello.world.yo", new String(charArray, 0, numCharsCopied));
-    numCharsCopied = p.copyToCharArray(charArray, 0, 4, '.');
-    assertEquals(14, numCharsCopied);
+    CategoryPath p = new CategoryPath("hello", "world", "yo");
+    char[] charArray = new char[p.fullPathLength()];
+    int numCharsCopied = p.copyFullPath(charArray, 0, '.');
+    assertEquals(p.fullPathLength(), numCharsCopied);
     assertEquals("hello.world.yo", new String(charArray, 0, numCharsCopied));
   }
   
   @Test 
-  public void testCharSerialization() throws Exception {
-    CategoryPath[] testCategories = {
-        new CategoryPath("hi", "there", "man"),
-        new CategoryPath("hello"),
-        new CategoryPath("what's", "up"),
-        // See that an empty category, which generates a (char)0,
-        // doesn't cause any problems in the middle of the serialization:
-        new CategoryPath(),
-        new CategoryPath("another", "example"),
-        new CategoryPath(),
-        new CategoryPath()
-    };
-    StringBuilder sb = new StringBuilder();
-    for (int i=0; i<testCategories.length; i++) {
-      testCategories[i].serializeAppendTo(sb);
-    }
-    
-    CategoryPath tmp = new CategoryPath();
-    int offset=0;
-    for (int i=0; i<testCategories.length; i++) {
-      // check equalsToSerialized, in a equal and non-equal case:
-      assertTrue(testCategories[i].equalsToSerialized(sb, offset));
-      assertFalse(new CategoryPath("Hello", "world").equalsToSerialized(sb, offset));
-      assertFalse(new CategoryPath("world").equalsToSerialized(sb, offset));
-      // and check hashCodeFromSerialized:
-      assertEquals(testCategories[i].hashCode(), CategoryPath.hashCodeOfSerialized(sb, offset));
-      // and check setFromSerialized:
-      offset = tmp.setFromSerialized(sb, offset);
-      assertEquals(testCategories[i], tmp);
-    }
-    assertEquals(offset, sb.length());
-    // A similar test, for a much longer path (though not larger than the
-    // 2^15-1 character limit that CategoryPath allows:
-    sb = new StringBuilder();
-    CategoryPath p = new CategoryPath();
-    for (int i=0; i<1000; i++) {
-      p.add(Integer.toString(i));
-    }
-    p.serializeAppendTo(sb);
-    p.serializeAppendTo(sb);
-    p.serializeAppendTo(sb);
-    offset=0;
-    assertTrue(p.equalsToSerialized(sb, offset));
-    assertEquals(p.hashCode(), CategoryPath.hashCodeOfSerialized(sb, offset));
-    offset = tmp.setFromSerialized(sb, offset);
-    assertEquals(p, tmp);
-    assertTrue(p.equalsToSerialized(sb, offset));
-    assertEquals(p.hashCode(), CategoryPath.hashCodeOfSerialized(sb, offset));
-    offset = tmp.setFromSerialized(sb, offset);
-    assertEquals(p, tmp);
-    assertTrue(p.equalsToSerialized(sb, offset));
-    assertEquals(p.hashCode(), CategoryPath.hashCodeOfSerialized(sb, offset));
-    offset = tmp.setFromSerialized(sb, offset);
-    assertEquals(p, tmp);
-    assertEquals(offset, sb.length());
-    
-    // Test the serializeAppendTo variant with a prefixLen
-    p = new CategoryPath();
-    for (int i=0; i<783; i++) {
-      p.add(Integer.toString(i));
-    }
-    int[] prefixLengths = { 0, 574, 782, 783, 784, -1 };
-    for (int prefixLen : prefixLengths) {
-      sb = new StringBuilder();
-      p.serializeAppendTo(prefixLen, sb);
-      assertTrue(new CategoryPath(p, prefixLen).equalsToSerialized(sb, 0));
-    }
-    
-    // Test the equalsToSerialized variant with a prefixLen
-    // We use p and prefixLengths set above.
-    for (int prefixLen : prefixLengths) {
-      sb = new StringBuilder();
-      new CategoryPath(p, prefixLen).serializeAppendTo(sb);
-      assertTrue(p.equalsToSerialized(prefixLen, sb, 0));
-    }
-    
-    // Check also the false case of equalsToSerialized with prefixLen:
-    sb = new StringBuilder();
-    new CategoryPath().serializeAppendTo(sb);
-    assertTrue(new CategoryPath().equalsToSerialized(0, sb, 0));
-    assertTrue(new CategoryPath("a", "b").equalsToSerialized(0, sb, 0));
-    assertFalse(new CategoryPath("a", "b").equalsToSerialized(1, sb, 0));
-    sb = new StringBuilder();
-    new CategoryPath("a", "b").serializeAppendTo(sb);
-    assertFalse(new CategoryPath().equalsToSerialized(0, sb, 0));
-    assertFalse(new CategoryPath("a").equalsToSerialized(0, sb, 0));
-    assertFalse(new CategoryPath("a").equalsToSerialized(1, sb, 0));
-    assertFalse(new CategoryPath("a", "b").equalsToSerialized(0, sb, 0));
-    assertFalse(new CategoryPath("a", "b").equalsToSerialized(1, sb, 0));
-    assertTrue(new CategoryPath("a", "b").equalsToSerialized(2, sb, 0));
-    assertTrue(new CategoryPath("a", "b", "c").equalsToSerialized(2, sb, 0));
-    assertFalse(new CategoryPath("z", "b", "c").equalsToSerialized(2, sb, 0));
-    assertFalse(new CategoryPath("aa", "b", "c").equalsToSerialized(2, sb, 0));
-  }
-
-  @Test 
-  public void testStreamWriterSerialization() throws Exception {
-    CategoryPath[] testPaths = {
-        new CategoryPath("hi", "there", "man"),
-        new CategoryPath("hello"),
-        new CategoryPath("date", "2009", "May", "13", "14", "59", "00"),
-        // See that an empty category, which generates a (char)0,
-        // doesn't cause any problems in the middle of the serialization:
-        new CategoryPath(),
-        new CategoryPath("another", "example")
-    };
-    ByteArrayOutputStream baos = new ByteArrayOutputStream();
-    OutputStreamWriter osw = new OutputStreamWriter(baos, "UTF-8");  // UTF-8 is always supported.
-    for (CategoryPath cp : testPaths) {
-      cp.serializeToStreamWriter(osw);
-    }
-    osw.flush();
-    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-    InputStreamReader isr = new InputStreamReader(bais, "UTF-8");
-    CategoryPath[] checkPaths = {
-        new CategoryPath(), new CategoryPath(), new CategoryPath(), new CategoryPath(), new CategoryPath()
-    };
-    for (int j = 0; j < checkPaths.length; j++) {
-      checkPaths[j].deserializeFromStreamReader(isr);
-      assertEquals("Paths not equal", testPaths[j], checkPaths[j]);
-    }
-  }
-
-  @Test 
-  public void testCharSequenceCtor() throws Exception {
-    CategoryPath[] testPaths = {
-        new CategoryPath(new CS("hi"), new CS("there"), new CS("man")),
-        new CategoryPath(new CS("hello")),
-        new CategoryPath(new CS("date"), new CS("2009"), new CS("May"), new CS("13"),
-            new CS("14"), new CS("59"), new CS("00")),
-        new CategoryPath(),
-        new CategoryPath(new CS("another"), new CS("example"))
-    };
-    assertEquals("Wrong capacity", 10, testPaths[0].capacityChars());
-    assertEquals("Wrong capacity", 5, testPaths[1].capacityChars());
-    assertEquals("Wrong capacity", 19, testPaths[2].capacityChars());
-    assertEquals("Wrong capacity", 0, testPaths[3].capacityChars());
-    assertEquals("Wrong capacity", 14, testPaths[4].capacityChars());
-
-    assertEquals("Wrong component", "hi", testPaths[0].getComponent(0));
-    assertEquals("Wrong component", "there", testPaths[0].getComponent(1));
-    assertEquals("Wrong component", "man", testPaths[0].getComponent(2));
-    assertEquals("Wrong component", "hello", testPaths[1].getComponent(0));
-    assertEquals("Wrong component", "date", testPaths[2].getComponent(0));
-    assertEquals("Wrong component", "2009", testPaths[2].getComponent(1));
-    assertEquals("Wrong component", "May", testPaths[2].getComponent(2));
-    assertEquals("Wrong component", "13", testPaths[2].getComponent(3));
-    assertEquals("Wrong component", "14", testPaths[2].getComponent(4));
-    assertEquals("Wrong component", "59", testPaths[2].getComponent(5));
-    assertEquals("Wrong component", "00", testPaths[2].getComponent(6));
-    assertNull("Not null component", testPaths[3].getComponent(0));
-    assertEquals("Wrong component", "another", testPaths[4].getComponent(0));
-    assertEquals("Wrong component", "example", testPaths[4].getComponent(1));
-  }
-
-  @Test 
-  public void testIsDescendantOf() throws Exception {
-    CategoryPath[] testPaths = {
-        new CategoryPath(new CS("hi"), new CS("there")),
-        new CategoryPath(new CS("hi"), new CS("there"), new CS("man")),
-        new CategoryPath(new CS("hithere"), new CS("man")),
-        new CategoryPath(new CS("hi"), new CS("there"), new CS("mano")),
-        new CategoryPath(),
-    };
-    assertTrue(testPaths[0].isDescendantOf(testPaths[0]));
-    assertTrue(testPaths[0].isDescendantOf(testPaths[4]));
-    assertFalse(testPaths[4].isDescendantOf(testPaths[0]));
-    assertTrue(testPaths[1].isDescendantOf(testPaths[0]));
-    assertTrue(testPaths[1].isDescendantOf(testPaths[1]));
-    assertTrue(testPaths[3].isDescendantOf(testPaths[0]));
-    assertFalse(testPaths[2].isDescendantOf(testPaths[0]));
-    assertFalse(testPaths[2].isDescendantOf(testPaths[1]));
-    assertFalse(testPaths[3].isDescendantOf(testPaths[1]));
-  }
-
-  @Test 
   public void testCompareTo() {
     CategoryPath p = new CategoryPath("a/b/c/d", '/');
     CategoryPath pother = new CategoryPath("a/b/c/d", '/');
-    assertTrue(pother.compareTo(p) == 0);
+    assertEquals(0, pother.compareTo(p));
+    assertEquals(0, p.compareTo(pother));
     pother = new CategoryPath("", '/');
     assertTrue(pother.compareTo(p) < 0);
+    assertTrue(p.compareTo(pother) > 0);
     pother = new CategoryPath("a/b_/c/d", '/');
     assertTrue(pother.compareTo(p) > 0);
+    assertTrue(p.compareTo(pother) < 0);
     pother = new CategoryPath("a/b/c", '/');
     assertTrue(pother.compareTo(p) < 0);
+    assertTrue(p.compareTo(pother) > 0);
     pother = new CategoryPath("a/b/c/e", '/');
     assertTrue(pother.compareTo(p) > 0);
-    pother = new CategoryPath("a/b/c//e", '/');
-    assertTrue(pother.compareTo(p) < 0);
+    assertTrue(p.compareTo(pother) < 0);
   }
-  
-  private static class CS implements CharSequence {
-    public CS(String s) {
-      this.ca = new char[s.length()];
-      s.getChars(0, s.length(), this.ca, 0);
-    }
-    @Override
-    public char charAt(int index) {
-      return this.ca[index];
-    }
-    @Override
-    public int length() {
-      return this.ca.length;
+
+  @Test
+  public void testEmptyNullComponents() throws Exception {
+    // LUCENE-4724: CategoryPath should not allow empty or null components
+    String[][] components_tests = new String[][] {
+      new String[] { "", "test" }, // empty in the beginning
+      new String[] { "test", "" }, // empty in the end
+      new String[] { "test", "", "foo" }, // empty in the middle
+      new String[] { null, "test" }, // null at the beginning
+      new String[] { "test", null }, // null in the end
+      new String[] { "test", null, "foo" }, // null in the middle
+    };
+
+    for (String[] components : components_tests) {
+      try {
+        assertNotNull(new CategoryPath(components));
+        fail("empty or null components should not be allowed: " + Arrays.toString(components));
+      } catch (IllegalArgumentException e) {
+        // ok
+      }
     }
-    @Override
-    public CharSequence subSequence(int start, int end) {
-      return null; // not used.
+    
+    String[] path_tests = new String[] {
+        "/test", // empty in the beginning
+        "test//foo", // empty in the middle
+    };
+    
+    for (String path : path_tests) {
+      try {
+        assertNotNull(new CategoryPath(path, '/'));
+        fail("empty or null components should not be allowed: " + path);
+      } catch (IllegalArgumentException e) {
+        // ok
+      }
     }
-    private char[] ca;
-  }
 
+    // a trailing path separator is produces only one component
+    assertNotNull(new CategoryPath("test/", '/'));
+    
+  }
+  
 }

Modified: lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyCombined.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyCombined.java?rev=1454862&r1=1454861&r2=1454862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyCombined.java (original)
+++ lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/TestTaxonomyCombined.java Sun Mar 10 15:04:57 2013
@@ -7,15 +7,15 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import org.apache.lucene.facet.FacetTestCase;
+import org.apache.lucene.facet.SlowRAMDirectory;
 import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader;
 import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter;
 import org.apache.lucene.facet.taxonomy.directory.ParallelTaxonomyArrays;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.LockObtainFailedException;
 import org.apache.lucene.store.RAMDirectory;
-import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.LuceneTestCase.SuppressCodecs;
-import org.apache.lucene.util.SlowRAMDirectory;
 import org.junit.Test;
 
 /*
@@ -37,7 +37,7 @@ import org.junit.Test;
 
 // TODO: remove this suppress if we fix the TaxoWriter Codec to a non-default (see todo in DirTW)
 @SuppressCodecs("SimpleText")
-public class TestTaxonomyCombined extends LuceneTestCase {
+public class TestTaxonomyCombined extends FacetTestCase {
 
   /**  The following categories will be added to the taxonomy by
     fillTaxonomy(), and tested by all tests below:
@@ -146,7 +146,7 @@ public class TestTaxonomyCombined extend
     if (path==null) {
       return "<null>";
     }
-    if (path.length()==0) {
+    if (path.length==0) {
       return "<empty>";
     }
     return "<"+path.toString('/')+">";
@@ -304,9 +304,9 @@ public class TestTaxonomyCombined extend
     tw.close();
     TaxonomyReader tr = new DirectoryTaxonomyReader(indexDir);
     assertEquals(1, tr.getSize());
-    assertEquals(0, tr.getPath(0).length());
+    assertEquals(0, tr.getPath(0).length);
     assertEquals(TaxonomyReader.INVALID_ORDINAL, tr.getParent(0));
-    assertEquals(0, tr.getOrdinal(new CategoryPath()));
+    assertEquals(0, tr.getOrdinal(CategoryPath.EMPTY));
     tr.close();
     indexDir.close();
   }
@@ -323,9 +323,9 @@ public class TestTaxonomyCombined extend
     tw.commit();
     TaxonomyReader tr = new DirectoryTaxonomyReader(indexDir);
     assertEquals(1, tr.getSize());
-    assertEquals(0, tr.getPath(0).length());
+    assertEquals(0, tr.getPath(0).length);
     assertEquals(TaxonomyReader.INVALID_ORDINAL, tr.getParent(0));
-    assertEquals(0, tr.getOrdinal(new CategoryPath()));
+    assertEquals(0, tr.getOrdinal(CategoryPath.EMPTY));
     tw.close();
     tr.close();
     indexDir.close();
@@ -353,7 +353,7 @@ public class TestTaxonomyCombined extend
     }
 
     // test TaxonomyReader.getCategory():
-    for (int i=0; i<tr.getSize(); i++) {
+    for (int i = 1; i < tr.getSize(); i++) {
       CategoryPath expectedCategory = new CategoryPath(expectedCategories[i]);
       CategoryPath category = tr.getPath(i);
       if (!expectedCategory.equals(category)) {
@@ -367,7 +367,7 @@ public class TestTaxonomyCombined extend
     assertNull(tr.getPath(TaxonomyReader.INVALID_ORDINAL));
 
     // test TaxonomyReader.getOrdinal():
-    for (int i=0; i<expectedCategories.length; i++) {
+    for (int i = 1; i < expectedCategories.length; i++) {
       int expectedOrdinal = i;
       int ordinal = tr.getOrdinal(new CategoryPath(expectedCategories[i]));
       if (expectedOrdinal != ordinal) {
@@ -416,7 +416,7 @@ public class TestTaxonomyCombined extend
         ", but this is not a valid category.");
       }
       // verify that the parent is indeed my parent, according to the strings
-      if (!new CategoryPath(me, me.length()-1).equals(parent)) {
+      if (!me.subpath(me.length-1).equals(parent)) {
         fail("Got parent "+parentOrdinal+" for ordinal "+ordinal+
             " but categories are "+showcat(parent)+" and "+showcat(me)+
             " respectively.");
@@ -506,7 +506,7 @@ public class TestTaxonomyCombined extend
       }
       // verify that the parent is indeed my parent, according to the
       // strings
-      if (!new CategoryPath(me, me.length() - 1).equals(parent)) {
+      if (!me.subpath(me.length - 1).equals(parent)) {
         fail("Got parent " + parentOrdinal + " for ordinal " + ordinal
             + " but categories are " + showcat(parent) + " and "
             + showcat(me) + " respectively.");

Modified: lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestAddTaxonomy.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestAddTaxonomy.java?rev=1454862&r1=1454861&r2=1454862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestAddTaxonomy.java (original)
+++ lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestAddTaxonomy.java Sun Mar 10 15:04:57 2013
@@ -5,13 +5,13 @@ import java.util.HashSet;
 import java.util.Random;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import org.apache.lucene.facet.FacetTestCase;
 import org.apache.lucene.facet.taxonomy.CategoryPath;
 import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter.DiskOrdinalMap;
 import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter.MemoryOrdinalMap;
 import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter.OrdinalMap;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.IOUtils;
-import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util._TestUtil;
 
 /*
@@ -31,7 +31,7 @@ import org.apache.lucene.util._TestUtil;
  * limitations under the License.
  */
 
-public class TestAddTaxonomy extends LuceneTestCase {
+public class TestAddTaxonomy extends FacetTestCase {
 
   private void dotest(int ncats, final int range) throws Exception {
     final AtomicInteger numCats = new AtomicInteger(ncats);
@@ -81,7 +81,6 @@ public class TestAddTaxonomy extends Luc
   }
 
   private void validate(Directory dest, Directory src, OrdinalMap ordMap) throws Exception {
-    CategoryPath cp = new CategoryPath();
     DirectoryTaxonomyReader destTR = new DirectoryTaxonomyReader(dest);
     try {
       final int destSize = destTR.getSize();
@@ -98,7 +97,7 @@ public class TestAddTaxonomy extends Luc
         // validate that all source categories exist in destination, and their
         // ordinals are as expected.
         for (int j = 1; j < srcSize; j++) {
-          srcTR.getPath(j, cp);
+          CategoryPath cp = srcTR.getPath(j);
           int destOrdinal = destTR.getOrdinal(cp);
           assertTrue(cp + " not found in destination", destOrdinal > 0);
           assertEquals(destOrdinal, map[j]);

Modified: lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestConcurrentFacetedIndexing.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestConcurrentFacetedIndexing.java?rev=1454862&r1=1454861&r2=1454862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestConcurrentFacetedIndexing.java (original)
+++ lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestConcurrentFacetedIndexing.java Sun Mar 10 15:04:57 2013
@@ -8,7 +8,8 @@ import java.util.concurrent.ConcurrentHa
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.facet.index.CategoryDocumentBuilder;
+import org.apache.lucene.facet.FacetTestCase;
+import org.apache.lucene.facet.index.FacetFields;
 import org.apache.lucene.facet.taxonomy.CategoryPath;
 import org.apache.lucene.facet.taxonomy.writercache.TaxonomyWriterCache;
 import org.apache.lucene.facet.taxonomy.writercache.cl2o.Cl2oTaxonomyWriterCache;
@@ -17,7 +18,6 @@ import org.apache.lucene.index.IndexWrit
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.IOUtils;
-import org.apache.lucene.util.LuceneTestCase;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -37,7 +37,7 @@ import org.apache.lucene.util.LuceneTest
  */
 
 /** Tests concurrent indexing with facets. */
-public class TestConcurrentFacetedIndexing extends LuceneTestCase {
+public class TestConcurrentFacetedIndexing extends FacetTestCase {
 
   // A No-Op TaxonomyWriterCache which always discards all given categories, and
   // always returns true in put(), to indicate some cache entries were cleared.
@@ -48,12 +48,8 @@ public class TestConcurrentFacetedIndexi
     @Override
     public int get(CategoryPath categoryPath) { return -1; }
     @Override
-    public int get(CategoryPath categoryPath, int length) { return -1; }
-    @Override
     public boolean put(CategoryPath categoryPath, int ordinal) { return true; }
     @Override
-    public boolean put(CategoryPath categoryPath, int prefixLen, int ordinal) { return true; }
-    @Override
     public boolean isFull() { return true; }
     @Override
     public void clear() {}
@@ -94,7 +90,7 @@ public class TestConcurrentFacetedIndexi
 
     for (int i = 0; i < indexThreads.length; i++) {
       indexThreads[i] = new Thread() {
-        private final CategoryDocumentBuilder cdb = new CategoryDocumentBuilder(tw);
+        private final FacetFields facetFields = new FacetFields(tw);
         
         @Override
         public void run() {
@@ -108,15 +104,14 @@ public class TestConcurrentFacetedIndexi
                 CategoryPath cp = newCategory();
                 cats.add(cp);
                 // add all prefixes to values
-                int level = cp.length();
+                int level = cp.length;
                 while (level > 0) {
-                  String s = cp.toString('/', level);
+                  String s = cp.subpath(level).toString('/');
                   values.put(s, s);
                   --level;
                 }
               }
-              cdb.setCategoryPaths(cats);
-              cdb.build(doc);
+              facetFields.addFields(doc, cats);
               iw.addDocument(doc);
             } catch (IOException e) {
               throw new RuntimeException(e);
@@ -135,11 +130,11 @@ public class TestConcurrentFacetedIndexi
     for (String cat : values.keySet()) {
       CategoryPath cp = new CategoryPath(cat, '/');
       assertTrue("category not found " + cp, tr.getOrdinal(cp) > 0);
-      int level = cp.length();
+      int level = cp.length;
       int parentOrd = 0; // for root, parent is always virtual ROOT (ord=0)
-      CategoryPath path = new CategoryPath();
+      CategoryPath path = CategoryPath.EMPTY;
       for (int i = 0; i < level; i++) {
-        path.add(cp.getComponent(i));
+        path = cp.subpath(i + 1);
         int ord = tr.getOrdinal(path);
         assertEquals("invalid parent for cp=" + path, parentOrd, parents[ord]);
         parentOrd = ord; // next level should have this parent

Modified: lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyReader.java?rev=1454862&r1=1454861&r2=1454862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyReader.java (original)
+++ lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyReader.java Sun Mar 10 15:04:57 2013
@@ -3,20 +3,20 @@ package org.apache.lucene.facet.taxonomy
 import java.io.IOException;
 import java.util.Random;
 
-import org.apache.lucene.analysis.core.KeywordAnalyzer;
+import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.facet.FacetTestCase;
 import org.apache.lucene.facet.taxonomy.CategoryPath;
 import org.apache.lucene.facet.taxonomy.TaxonomyReader;
 import org.apache.lucene.facet.taxonomy.TaxonomyWriter;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
-import org.apache.lucene.index.LogByteSizeMergePolicy;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
+import org.apache.lucene.index.LogByteSizeMergePolicy;
 import org.apache.lucene.index.LogMergePolicy;
 import org.apache.lucene.store.AlreadyClosedException;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.RAMDirectory;
 import org.apache.lucene.util.IOUtils;
-import org.apache.lucene.util.LuceneTestCase;
 import org.junit.Test;
 
 /*
@@ -36,7 +36,7 @@ import org.junit.Test;
  * limitations under the License.
  */
 
-public class TestDirectoryTaxonomyReader extends LuceneTestCase {
+public class TestDirectoryTaxonomyReader extends FacetTestCase {
 
   @Test
   public void testCloseAfterIncRef() throws Exception {
@@ -154,8 +154,8 @@ public class TestDirectoryTaxonomyReader
       for (int i=0; i<n; i++) {
         int k = random.nextInt(n);
         tw = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE);
-        for (int j=0; j<=k; j++) {
-          tw.addCategory(new CategoryPath(cp[j]));
+        for (int j = 0; j <= k; j++) {
+          tw.addCategory(cp[j]);
         }
         tw.close();
         if (closeReader) {
@@ -256,7 +256,7 @@ public class TestDirectoryTaxonomyReader
     // hold onto IW to forceMerge
     // note how we don't close it, since DTW will close it.
     final IndexWriter iw = new IndexWriter(dir,
-        new IndexWriterConfig(TEST_VERSION_CURRENT, new KeywordAnalyzer())
+        new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random()))
             .setMergePolicy(new LogByteSizeMergePolicy()));
     DirectoryTaxonomyWriter writer = new DirectoryTaxonomyWriter(dir) {
       @Override
@@ -299,7 +299,7 @@ public class TestDirectoryTaxonomyReader
     // hold onto IW to forceMerge
     // note how we don't close it, since DTW will close it.
     final IndexWriter iw = new IndexWriter(dir,
-        new IndexWriterConfig(TEST_VERSION_CURRENT, new KeywordAnalyzer())
+        new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random()))
             .setMergePolicy(new LogByteSizeMergePolicy()));
     DirectoryTaxonomyWriter writer = new DirectoryTaxonomyWriter(dir) {
       @Override

Modified: lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyWriter.java?rev=1454862&r1=1454861&r2=1454862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyWriter.java (original)
+++ lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/directory/TestDirectoryTaxonomyWriter.java Sun Mar 10 15:04:57 2013
@@ -7,6 +7,7 @@ import java.util.Random;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import org.apache.lucene.facet.FacetTestCase;
 import org.apache.lucene.facet.taxonomy.CategoryPath;
 import org.apache.lucene.facet.taxonomy.TaxonomyReader;
 import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter.MemoryOrdinalMap;
@@ -21,7 +22,6 @@ import org.apache.lucene.index.IndexWrit
 import org.apache.lucene.index.SegmentInfos;
 import org.apache.lucene.store.AlreadyClosedException;
 import org.apache.lucene.store.Directory;
-import org.apache.lucene.util.LuceneTestCase;
 import org.junit.Test;
 
 /*
@@ -41,7 +41,7 @@ import org.junit.Test;
  * limitations under the License.
  */
 
-public class TestDirectoryTaxonomyWriter extends LuceneTestCase {
+public class TestDirectoryTaxonomyWriter extends FacetTestCase {
 
   // A No-Op TaxonomyWriterCache which always discards all given categories, and
   // always returns true in put(), to indicate some cache entries were cleared.
@@ -52,12 +52,8 @@ public class TestDirectoryTaxonomyWriter
     @Override
     public int get(CategoryPath categoryPath) { return -1; }
     @Override
-    public int get(CategoryPath categoryPath, int length) { return -1; }
-    @Override
     public boolean put(CategoryPath categoryPath, int ordinal) { return true; }
     @Override
-    public boolean put(CategoryPath categoryPath, int prefixLen, int ordinal) { return true; }
-    @Override
     public boolean isFull() { return true; }
     @Override
     public void clear() {}
@@ -266,10 +262,10 @@ public class TestDirectoryTaxonomyWriter
                   Integer.toString(value / 100000), Integer.toString(value));
               int ord = tw.addCategory(cp);
               assertTrue("invalid parent for ordinal " + ord + ", category " + cp, tw.getParent(ord) != -1);
-              String l1 = cp.toString('/', 1);
-              String l2 = cp.toString('/', 2);
-              String l3 = cp.toString('/', 3);
-              String l4 = cp.toString('/', 4);
+              String l1 = cp.subpath(1).toString('/');
+              String l2 = cp.subpath(2).toString('/');
+              String l3 = cp.subpath(3).toString('/');
+              String l4 = cp.subpath(4).toString('/');
               values.put(l1, l1);
               values.put(l2, l2);
               values.put(l3, l3);
@@ -292,11 +288,11 @@ public class TestDirectoryTaxonomyWriter
     for (String cat : values.keySet()) {
       CategoryPath cp = new CategoryPath(cat, '/');
       assertTrue("category not found " + cp, dtr.getOrdinal(cp) > 0);
-      int level = cp.length();
+      int level = cp.length;
       int parentOrd = 0; // for root, parent is always virtual ROOT (ord=0)
-      CategoryPath path = new CategoryPath();
+      CategoryPath path = CategoryPath.EMPTY;
       for (int i = 0; i < level; i++) {
-        path.add(cp.getComponent(i));
+        path = cp.subpath(i + 1);
         int ord = dtr.getOrdinal(path);
         assertEquals("invalid parent for cp=" + path, parentOrd, parents[ord]);
         parentOrd = ord; // next level should have this parent

Modified: lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/writercache/cl2o/TestCharBlockArray.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/writercache/cl2o/TestCharBlockArray.java?rev=1454862&r1=1454861&r2=1454862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/writercache/cl2o/TestCharBlockArray.java (original)
+++ lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/writercache/cl2o/TestCharBlockArray.java Sun Mar 10 15:04:57 2013
@@ -9,11 +9,9 @@ import java.nio.ByteBuffer;
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CodingErrorAction;
 
-import org.junit.Test;
-
+import org.apache.lucene.facet.FacetTestCase;
 import org.apache.lucene.util.IOUtils;
-import org.apache.lucene.util.LuceneTestCase;
-import org.apache.lucene.facet.taxonomy.writercache.cl2o.CharBlockArray;
+import org.junit.Test;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -32,7 +30,7 @@ import org.apache.lucene.facet.taxonomy.
  * limitations under the License.
  */
 
-public class TestCharBlockArray extends LuceneTestCase {
+public class TestCharBlockArray extends FacetTestCase {
 
   @Test public void testArray() throws Exception {
     CharBlockArray array = new CharBlockArray();

Modified: lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/writercache/cl2o/TestCompactLabelToOrdinal.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/writercache/cl2o/TestCompactLabelToOrdinal.java?rev=1454862&r1=1454861&r2=1454862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/writercache/cl2o/TestCompactLabelToOrdinal.java (original)
+++ lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/taxonomy/writercache/cl2o/TestCompactLabelToOrdinal.java Sun Mar 10 15:04:57 2013
@@ -6,14 +6,13 @@ import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CodingErrorAction;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Random;
 
-import org.junit.Test;
-
-import org.apache.lucene.util.IOUtils;
-import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.facet.FacetTestCase;
 import org.apache.lucene.facet.taxonomy.CategoryPath;
-import org.apache.lucene.facet.taxonomy.writercache.cl2o.CompactLabelToOrdinal;
-import org.apache.lucene.facet.taxonomy.writercache.cl2o.LabelToOrdinal;
+import org.apache.lucene.util.IOUtils;
+import org.apache.lucene.util._TestUtil;
+import org.junit.Test;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -32,7 +31,7 @@ import org.apache.lucene.facet.taxonomy.
  * limitations under the License.
  */
 
-public class TestCompactLabelToOrdinal extends LuceneTestCase {
+public class TestCompactLabelToOrdinal extends FacetTestCase {
 
   @Test
   public void testL2O() throws Exception {
@@ -46,9 +45,10 @@ public class TestCompactLabelToOrdinal e
     String[] uniqueValues = new String[numUniqueValues];
     byte[] buffer = new byte[50];
 
+    Random random = random();
     for (int i = 0; i < numUniqueValues;) {
-      random().nextBytes(buffer);
-      int size = 1 + random().nextInt(50);
+      random.nextBytes(buffer);
+      int size = 1 + random.nextInt(buffer.length);
 
       // This test is turning random bytes into a string,
       // this is asking for trouble.
@@ -56,16 +56,22 @@ public class TestCompactLabelToOrdinal e
           .onUnmappableCharacter(CodingErrorAction.REPLACE)
           .onMalformedInput(CodingErrorAction.REPLACE);
       uniqueValues[i] = decoder.decode(ByteBuffer.wrap(buffer, 0, size)).toString();
-      if (uniqueValues[i].indexOf(CompactLabelToOrdinal.TerminatorChar) == -1) {
+      // we cannot have empty path components, so eliminate all prefix as well
+      // as middle consecuive delimiter chars.
+      uniqueValues[i] = uniqueValues[i].replaceAll("/+", "/");
+      if (uniqueValues[i].startsWith("/")) {
+        uniqueValues[i] = uniqueValues[i].substring(1);
+      }
+      if (uniqueValues[i].indexOf(CompactLabelToOrdinal.TERMINATOR_CHAR) == -1) {
         i++;
       }
     }
 
-    TEMP_DIR.mkdirs();
-    File f = new File(TEMP_DIR, "CompactLabelToOrdinalTest.tmp");
+    File tmpDir = _TestUtil.getTempDir("testLableToOrdinal");
+    File f = new File(tmpDir, "CompactLabelToOrdinalTest.tmp");
     int flushInterval = 10;
 
-    for (int i = 0; i < n * 10; i++) {
+    for (int i = 0; i < n; i++) {
       if (i > 0 && i % flushInterval == 0) {
         compact.flush(f);    
         compact = CompactLabelToOrdinal.open(f, 0.15f, 3);
@@ -75,19 +81,16 @@ public class TestCompactLabelToOrdinal e
         }
       }
 
-      int index = random().nextInt(numUniqueValues);
+      int index = random.nextInt(numUniqueValues);
       CategoryPath label = new CategoryPath(uniqueValues[index], '/');
 
       int ord1 = map.getOrdinal(label);
       int ord2 = compact.getOrdinal(label);
 
-      //System.err.println(ord1+" "+ord2);
-
       assertEquals(ord1, ord2);
 
-      if (ord1 == LabelToOrdinal.InvalidOrdinal) {
+      if (ord1 == LabelToOrdinal.INVALID_ORDINAL) {
         ord1 = compact.getNextOrdinal();
-
         map.addLabel(label, ord1);
         compact.addLabel(label, ord1);
       }
@@ -108,25 +111,15 @@ public class TestCompactLabelToOrdinal e
     
     @Override
     public void addLabel(CategoryPath label, int ordinal) {
-      map.put(new CategoryPath(label), ordinal);
-    }
-
-    @Override
-    public void addLabel(CategoryPath label, int prefixLen, int ordinal) {
-      map.put(new CategoryPath(label, prefixLen), ordinal);
+      map.put(label, ordinal);
     }
 
     @Override
     public int getOrdinal(CategoryPath label) {
       Integer value = map.get(label);
-      return (value != null) ? value.intValue() : LabelToOrdinal.InvalidOrdinal;
-    }
-
-    @Override
-    public int getOrdinal(CategoryPath label, int prefixLen) {
-      Integer value = map.get(new CategoryPath(label, prefixLen));
-      return (value != null) ? value.intValue() : LabelToOrdinal.InvalidOrdinal;
+      return (value != null) ? value.intValue() : LabelToOrdinal.INVALID_ORDINAL;
     }
 
   }
+
 }

Modified: lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/util/TestScoredDocIDsUtils.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/util/TestScoredDocIDsUtils.java?rev=1454862&r1=1454861&r2=1454862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/util/TestScoredDocIDsUtils.java (original)
+++ lucene/dev/branches/lucene4258/lucene/facet/src/test/org/apache/lucene/facet/util/TestScoredDocIDsUtils.java Sun Mar 10 15:04:57 2013
@@ -9,27 +9,19 @@ import org.apache.lucene.document.Docume
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.StringField;
+import org.apache.lucene.facet.FacetTestCase;
+import org.apache.lucene.facet.search.ScoredDocIDs;
+import org.apache.lucene.facet.search.ScoredDocIDsIterator;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.DocIdSet;
 import org.apache.lucene.search.DocIdSetIterator;
-import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.store.Directory;
-import org.apache.lucene.util.Bits;
-import org.apache.lucene.util.OpenBitSet;
-import org.apache.lucene.util.OpenBitSetDISI;
+import org.apache.lucene.util.FixedBitSet;
 import org.junit.Test;
 
-import org.apache.lucene.util.LuceneTestCase;
-import org.apache.lucene.facet.search.ScoredDocIDs;
-import org.apache.lucene.facet.search.ScoredDocIDsIterator;
-import org.apache.lucene.facet.search.ScoredDocIdCollector;
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -47,26 +39,26 @@ import org.apache.lucene.facet.search.Sc
  * limitations under the License.
  */
 
-public class TestScoredDocIDsUtils extends LuceneTestCase {
+public class TestScoredDocIDsUtils extends FacetTestCase {
 
   @Test
   public void testComplementIterator() throws Exception {
     final int n = atLeast(10000);
-    final OpenBitSet bits = new OpenBitSet(n);
-    for (int i = 0; i < 5 * n; i++) {
-      bits.flip(random().nextInt(n));
+    final FixedBitSet bits = new FixedBitSet(n);
+    Random random = random();
+    for (int i = 0; i < n; i++) {
+      int idx = random.nextInt(n);
+      bits.flip(idx, idx + 1);
     }
     
-    OpenBitSet verify = new OpenBitSet(n);
-    verify.or(bits);
+    FixedBitSet verify = new FixedBitSet(bits);
 
     ScoredDocIDs scoredDocIDs = ScoredDocIdsUtils.createScoredDocIds(bits, n); 
 
     Directory dir = newDirectory();
-    IndexReader reader = createReaderWithNDocs(random(), n, dir);
+    IndexReader reader = createReaderWithNDocs(random, n, dir);
     try { 
-      assertEquals(n - verify.cardinality(), ScoredDocIdsUtils.getComplementSet(scoredDocIDs, 
-        reader).size());
+      assertEquals(n - verify.cardinality(), ScoredDocIdsUtils.getComplementSet(scoredDocIDs, reader).size());
     } finally {
       reader.close();
       dir.close();
@@ -103,80 +95,6 @@ public class TestScoredDocIDsUtils exten
     }
   }
   
-  @Test
-  public void testWithDeletions() throws Exception {
-    int N_DOCS = 100;
-
-    DocumentFactory docFactory = new DocumentFactory(N_DOCS) {
-      @Override
-      public boolean markedDeleted(int docNum) {
-        return (docNum % 3 == 0 ||        // every 3rd documents, including first 
-            docNum == numDocs - 1 ||     // last document
-            docNum == numDocs / 2 ||     // 3 consecutive documents in the middle
-            docNum == 1 + numDocs / 2 ||
-            docNum == 2 + numDocs / 2);
-      }
-      
-      // every 6th document (starting from the 2nd) would contain 'alpha'
-      @Override
-      public boolean haveAlpha(int docNum) {
-        return (docNum % 6 == 1);
-      }
-    };
-    
-    Directory dir = newDirectory();
-    IndexReader reader = createReaderWithNDocs(random(), N_DOCS, docFactory, dir);
-    try {
-      ScoredDocIDs allDocs = ScoredDocIdsUtils.createAllDocsScoredDocIDs(reader);
-      ScoredDocIDsIterator it = allDocs.iterator();
-      int numIteratedDocs = 0;
-      while (it.next()) {
-        numIteratedDocs++;
-        int docNum = it.getDocID();
-        assertNull(
-            "Deleted docs must not appear in the allDocsScoredDocIds set: " + docNum, 
-            reader.document(docNum).getField("del"));
-      }
-
-      assertEquals("Wrong number of (live) documents", allDocs.size(), numIteratedDocs);
-
-      // Get all 'alpha' documents
-      ScoredDocIdCollector collector = ScoredDocIdCollector.create(reader.maxDoc(), false);
-      Query q = new TermQuery(new Term(DocumentFactory.field, DocumentFactory.alphaTxt));
-      IndexSearcher searcher = newSearcher(reader);
-      searcher.search(q, collector);
-
-      ScoredDocIDs scoredDocIds = collector.getScoredDocIDs();
-      OpenBitSet resultSet = new OpenBitSetDISI(scoredDocIds.getDocIDs().iterator(), reader.maxDoc());
-      
-      // Getting the complement set of the query result
-      ScoredDocIDs complementSet = ScoredDocIdsUtils.getComplementSet(scoredDocIds, reader);
-
-      assertEquals("Number of documents in complement set mismatch",
-          reader.numDocs() - scoredDocIds.size(), complementSet.size());
-
-      // now make sure the documents in the complement set are not deleted
-      // and not in the original result set
-      ScoredDocIDsIterator compIterator = complementSet.iterator();
-      Bits live = MultiFields.getLiveDocs(reader);
-      while (compIterator.next()) {
-        int docNum = compIterator.getDocID();
-        assertFalse(
-            "Complement-Set must not contain deleted documents (doc="+docNum+")",
-            live != null && !live.get(docNum));
-        assertNull(
-            "Complement-Set must not contain docs from the original set (doc="+ docNum+")",
-            reader.document(docNum).getField("del"));
-        assertFalse(
-            "Complement-Set must not contain docs from the original set (doc="+docNum+")",
-            resultSet.fastGet(docNum));
-      }
-    } finally {
-      reader.close();
-      dir.close();
-    }
-  }
-  
   /**
    * Creates an index with n documents, this method is meant for testing purposes ONLY
    */
@@ -192,10 +110,7 @@ public class TestScoredDocIDsUtils exten
     private final static Field deletionMark = new StringField(field, delTxt, Field.Store.NO);
     private final static Field alphaContent = new StringField(field, alphaTxt, Field.Store.NO);
     
-    protected final int numDocs;
-    
     public DocumentFactory(int totalNumDocs) {
-      this.numDocs = totalNumDocs;
     }
     
     public boolean markedDeleted(int docNum) {

Modified: lucene/dev/branches/lucene4258/lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java?rev=1454862&r1=1454861&r2=1454862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java (original)
+++ lucene/dev/branches/lucene4258/lucene/grouping/src/java/org/apache/lucene/search/grouping/GroupingSearch.java Sun Mar 10 15:04:57 2013
@@ -20,14 +20,8 @@ package org.apache.lucene.search.groupin
 import java.io.IOException;
 import java.util.*;
 
-import org.apache.lucene.document.DerefBytesDocValuesField;
-import org.apache.lucene.index.DocValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.search.*;
-import org.apache.lucene.search.grouping.dv.DVAllGroupHeadsCollector;
-import org.apache.lucene.search.grouping.dv.DVAllGroupsCollector;
-import org.apache.lucene.search.grouping.dv.DVFirstPassGroupingCollector;
-import org.apache.lucene.search.grouping.dv.DVSecondPassGroupingCollector;
 import org.apache.lucene.search.grouping.function.FunctionAllGroupHeadsCollector;
 import org.apache.lucene.search.grouping.function.FunctionAllGroupsCollector;
 import org.apache.lucene.search.grouping.function.FunctionFirstPassGroupingCollector;
@@ -51,8 +45,6 @@ public class GroupingSearch {
   private final ValueSource groupFunction;
   private final Map<?, ?> valueSourceContext;
   private final Filter groupEndDocs;
-  private final DocValues.Type docValuesType;
-  private final boolean diskResidentDocValues;
 
   private Sort groupSort = Sort.RELEVANCE;
   private Sort sortWithinGroup;
@@ -80,20 +72,7 @@ public class GroupingSearch {
    * @param groupField The name of the field to group by.
    */
   public GroupingSearch(String groupField) {
-    this(groupField, null, null, null, null, false);
-  }
-
-  /**
-   * Constructs a <code>GroupingSearch</code> instance that groups documents by doc values.
-   * This constructor can only be used when the groupField
-   * is a <code>*DocValuesField</code> (eg, {@link DerefBytesDocValuesField}.
-   *
-   * @param groupField            The name of the field to group by that contains doc values
-   * @param docValuesType         The doc values type of the specified groupField
-   * @param diskResidentDocValues Whether the values to group by should be disk resident
-   */
-  public GroupingSearch(String groupField, DocValues.Type docValuesType, boolean diskResidentDocValues) {
-    this(groupField, null, null, null, docValuesType, diskResidentDocValues);
+    this(groupField, null, null, null);
   }
 
   /**
@@ -104,7 +83,7 @@ public class GroupingSearch {
    * @param valueSourceContext The context of the specified groupFunction
    */
   public GroupingSearch(ValueSource groupFunction, Map<?, ?> valueSourceContext) {
-    this(null, groupFunction, valueSourceContext, null, null, false);
+    this(null, groupFunction, valueSourceContext, null);
   }
 
   /**
@@ -114,16 +93,14 @@ public class GroupingSearch {
    * @param groupEndDocs The filter that marks the last document in all doc blocks
    */
   public GroupingSearch(Filter groupEndDocs) {
-    this(null, null, null, groupEndDocs, null, false);
+    this(null, null, null, groupEndDocs);
   }
 
-  private GroupingSearch(String groupField, ValueSource groupFunction, Map<?, ?> valueSourceContext, Filter groupEndDocs, DocValues.Type docValuesType, boolean diskResidentDocValues) {
+  private GroupingSearch(String groupField, ValueSource groupFunction, Map<?, ?> valueSourceContext, Filter groupEndDocs) {
     this.groupField = groupField;
     this.groupFunction = groupFunction;
     this.valueSourceContext = valueSourceContext;
     this.groupEndDocs = groupEndDocs;
-    this.docValuesType = docValuesType;
-    this.diskResidentDocValues = diskResidentDocValues;
   }
 
   /**
@@ -180,18 +157,6 @@ public class GroupingSearch {
       } else {
         allGroupHeadsCollector = null;
       }
-    } else if (docValuesType != null) {
-      firstPassCollector = DVFirstPassGroupingCollector.create(groupSort, topN, groupField, docValuesType, diskResidentDocValues);
-      if (allGroups) {
-        allGroupsCollector = DVAllGroupsCollector.create(groupField, docValuesType, diskResidentDocValues, initialSize);
-      } else {
-        allGroupsCollector = null;
-      }
-      if (allGroupHeads) {
-        allGroupHeadsCollector = DVAllGroupHeadsCollector.create(groupField, sortWithinGroup, docValuesType, diskResidentDocValues);
-      } else {
-        allGroupHeadsCollector = null;
-      }
     } else {
       firstPassCollector = new TermFirstPassGroupingCollector(groupField, groupSort, topN);
       if (allGroups) {
@@ -253,8 +218,6 @@ public class GroupingSearch {
     AbstractSecondPassGroupingCollector secondPassCollector;
     if (groupFunction != null) {
       secondPassCollector = new FunctionSecondPassGroupingCollector((Collection) topSearchGroups, groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields, groupFunction, valueSourceContext);
-    } else if (docValuesType != null) {
-      secondPassCollector = DVSecondPassGroupingCollector.create(groupField, diskResidentDocValues, docValuesType, (Collection) topSearchGroups, groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields);
     } else {
       secondPassCollector = new TermSecondPassGroupingCollector(groupField, (Collection) topSearchGroups, groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields);
     }

Modified: lucene/dev/branches/lucene4258/lucene/grouping/src/java/org/apache/lucene/search/grouping/package.html
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4258/lucene/grouping/src/java/org/apache/lucene/search/grouping/package.html?rev=1454862&r1=1454861&r2=1454862&view=diff
==============================================================================
--- lucene/dev/branches/lucene4258/lucene/grouping/src/java/org/apache/lucene/search/grouping/package.html (original)
+++ lucene/dev/branches/lucene4258/lucene/grouping/src/java/org/apache/lucene/search/grouping/package.html Sun Mar 10 15:04:57 2013
@@ -80,8 +80,8 @@ field fall into a single group.</p>
 <p>Known limitations:</p>
 <ul>
   <li> For the two-pass grouping search, the group field must be a
-    single-valued indexed field.
-    {@link org.apache.lucene.search.FieldCache} is used to load the {@link org.apache.lucene.search.FieldCache.DocTermsIndex} for this field.
+    single-valued indexed field (or indexed as a {@link org.apache.lucene.document.SortedDocValuesField}).
+    {@link org.apache.lucene.search.FieldCache} is used to load the {@link org.apache.lucene.index.SortedDocValues} for this field.
   <li> Although Solr support grouping by function and this module has abstraction of what a group is, there are currently only
     implementations for grouping based on terms.
   <li> Sharding is not directly supported, though is not too
@@ -196,25 +196,5 @@ fields, <code>FieldCache</code>, etc.).
   <code>GroupingSearch</code> convenience utility
 </p>
 
-<p>
-  There are also DocValues based implementations available for the group collectors. There are factory methods
-  available for creating dv based instances. A typical example using dv based grouping with the
-  <code>GroupingSearch</code> convenience utility:
-</p>
-
-<pre class="prettyprint">
-  boolean diskResident = true; // Whether values should fetched directly from disk by passing the Java heap space.
-  DocValues.Type docValuesType = DocValues.Type.BYTES_VAR_SORTED;
-  GroupingSearch groupingSearch = new GroupingSearch("author", docValuesType, diskResident);
-  groupingSearch.setGroupSort(groupSort);
-  groupingSearch.setFillSortFields(fillFields);
-
-  TermQuery query = new TermQuery(new Term("content", searchTerm));
-  // The docValuesType variable decides the generic type. When float is used this Double and in case of int this is Long
-  TopGroups&lt;BytesRef&gt; result = groupingSearch.search(indexSearcher, query, groupOffset, groupLimit);
-
-  // Render groupsResult...
-</pre>
-
 </body>
 </html>