You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by sy...@apache.org on 2014/12/31 20:12:07 UTC

[01/14] lucenenet git commit: Moving Lucene.Net.Facet tests to their appropriate place

Repository: lucenenet
Updated Branches:
  refs/heads/master b47de89ef -> 56049f927


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/TestMultipleIndexFields.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/TestMultipleIndexFields.cs b/src/Lucene.Net.Tests/core/Facet/TestMultipleIndexFields.cs
deleted file mode 100644
index 086e608..0000000
--- a/src/Lucene.Net.Tests/core/Facet/TestMultipleIndexFields.cs
+++ /dev/null
@@ -1,300 +0,0 @@
-using System.Collections.Generic;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet
-{
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-
-    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
-    using MockTokenizer = Lucene.Net.Analysis.MockTokenizer;
-    using Document = Lucene.Net.Documents.Document;
-    using Field = Lucene.Net.Documents.Field;
-    using TextField = Lucene.Net.Documents.TextField;
-    using TaxonomyReader = Lucene.Net.Facet.Taxonomy.TaxonomyReader;
-    using TaxonomyWriter = Lucene.Net.Facet.Taxonomy.TaxonomyWriter;
-    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
-    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
-    using AtomicReader = Lucene.Net.Index.AtomicReader;
-    using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
-    using IndexReader = Lucene.Net.Index.IndexReader;
-    using OpenMode = Lucene.Net.Index.IndexWriterConfig.OpenMode_e;
-    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
-    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
-    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
-    using Directory = Lucene.Net.Store.Directory;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-
-    public class TestMultipleIndexFields : FacetTestCase
-    {
-
-        private static readonly FacetField[] CATEGORIES = new FacetField[] { new FacetField("Author", "Mark Twain"), new FacetField("Author", "Stephen King"), new FacetField("Author", "Kurt Vonnegut"), new FacetField("Band", "Rock & Pop", "The Beatles"), new FacetField("Band", "Punk", "The Ramones"), new FacetField("Band", "Rock & Pop", "U2"), new FacetField("Band", "Rock & Pop", "REM"), new FacetField("Band", "Rock & Pop", "Dave Matthews Band"), new FacetField("Composer", "Bach") };
-
-        private FacetsConfig Config
-        {
-            get
-            {
-                FacetsConfig config = new FacetsConfig();
-                config.SetHierarchical("Band", true);
-                return config;
-            }
-        }
-
-        [Test]
-        public virtual void TestDefault()
-        {
-            Directory indexDir = NewDirectory();
-            Directory taxoDir = NewDirectory();
-
-            // create and open an index writer
-            var iw = new RandomIndexWriter(Random(), indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random(), MockTokenizer.WHITESPACE, false)));
-            // create and open a taxonomy writer
-            var tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE);
-            var config = Config;
-
-            seedIndex(tw, iw, config);
-
-            IndexReader ir = iw.Reader;
-            tw.Commit();
-
-            // prepare index reader and taxonomy.
-            var tr = new DirectoryTaxonomyReader(taxoDir);
-
-            // prepare searcher to search against
-            IndexSearcher searcher = NewSearcher(ir);
-
-            FacetsCollector sfc = PerformSearch(tr, ir, searcher);
-
-            // Obtain facets results and hand-test them
-            AssertCorrectResults(GetTaxonomyFacetCounts(tr, config, sfc));
-
-            assertOrdinalsExist("$facets", ir);
-
-            IOUtils.Close(tr, ir, iw, tw, indexDir, taxoDir);
-        }
-
-        [Test]
-        public virtual void TestCustom()
-        {
-            Directory indexDir = NewDirectory();
-            Directory taxoDir = NewDirectory();
-
-            // create and open an index writer
-            RandomIndexWriter iw = new RandomIndexWriter(Random(), indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random(), MockTokenizer.WHITESPACE, false)));
-            // create and open a taxonomy writer
-            var tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE);
-
-            FacetsConfig config = Config;
-            config.SetIndexFieldName("Author", "$author");
-            seedIndex(tw, iw, config);
-
-            IndexReader ir = iw.Reader;
-            tw.Commit();
-
-            // prepare index reader and taxonomy.
-            var tr = new DirectoryTaxonomyReader(taxoDir);
-
-            // prepare searcher to search against
-            IndexSearcher searcher = NewSearcher(ir);
-
-            FacetsCollector sfc = PerformSearch(tr, ir, searcher);
-
-            IDictionary<string, Facets> facetsMap = new Dictionary<string, Facets>();
-            facetsMap["Author"] = GetTaxonomyFacetCounts(tr, config, sfc, "$author");
-            Facets facets = new MultiFacets(facetsMap, GetTaxonomyFacetCounts(tr, config, sfc));
-
-            // Obtain facets results and hand-test them
-            AssertCorrectResults(facets);
-
-            assertOrdinalsExist("$facets", ir);
-            assertOrdinalsExist("$author", ir);
-
-            IOUtils.Close(tr, ir, iw, tw, indexDir, taxoDir);
-        }
-
-        [Test]
-        public virtual void TestTwoCustomsSameField()
-        {
-            Directory indexDir = NewDirectory();
-            Directory taxoDir = NewDirectory();
-
-            // create and open an index writer
-            RandomIndexWriter iw = new RandomIndexWriter(Random(), indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random(), MockTokenizer.WHITESPACE, false)));
-            // create and open a taxonomy writer
-            var tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE);
-
-            FacetsConfig config = Config;
-            config.SetIndexFieldName("Band", "$music");
-            config.SetIndexFieldName("Composer", "$music");
-            seedIndex(tw, iw, config);
-
-            IndexReader ir = iw.Reader;
-            tw.Commit();
-
-            // prepare index reader and taxonomy.
-            var tr = new DirectoryTaxonomyReader(taxoDir);
-
-            // prepare searcher to search against
-            IndexSearcher searcher = NewSearcher(ir);
-
-            FacetsCollector sfc = PerformSearch(tr, ir, searcher);
-
-            IDictionary<string, Facets> facetsMap = new Dictionary<string, Facets>();
-            Facets facets2 = GetTaxonomyFacetCounts(tr, config, sfc, "$music");
-            facetsMap["Band"] = facets2;
-            facetsMap["Composer"] = facets2;
-            Facets facets = new MultiFacets(facetsMap, GetTaxonomyFacetCounts(tr, config, sfc));
-
-            // Obtain facets results and hand-test them
-            AssertCorrectResults(facets);
-
-            assertOrdinalsExist("$facets", ir);
-            assertOrdinalsExist("$music", ir);
-            assertOrdinalsExist("$music", ir);
-
-            IOUtils.Close(tr, ir, iw, tw, indexDir, taxoDir);
-        }
-
-        private void assertOrdinalsExist(string field, IndexReader ir)
-        {
-            foreach (AtomicReaderContext context in ir.Leaves)
-            {
-                AtomicReader r = context.AtomicReader;
-                if (r.GetBinaryDocValues(field) != null)
-                {
-                    return; // not all segments must have this DocValues
-                }
-            }
-            Fail("no ordinals found for " + field);
-        }
-
-        [Test]
-        public virtual void TestDifferentFieldsAndText()
-        {
-            Directory indexDir = NewDirectory();
-            Directory taxoDir = NewDirectory();
-
-            // create and open an index writer
-            var iw = new RandomIndexWriter(Random(), indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random(), MockTokenizer.WHITESPACE, false)));
-            // create and open a taxonomy writer
-            var tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE);
-
-            FacetsConfig config = Config;
-            config.SetIndexFieldName("Band", "$bands");
-            config.SetIndexFieldName("Composer", "$composers");
-            seedIndex(tw, iw, config);
-
-            IndexReader ir = iw.Reader;
-            tw.Commit();
-
-            // prepare index reader and taxonomy.
-            var tr = new DirectoryTaxonomyReader(taxoDir);
-
-            // prepare searcher to search against
-            IndexSearcher searcher = NewSearcher(ir);
-
-            FacetsCollector sfc = PerformSearch(tr, ir, searcher);
-
-            IDictionary<string, Facets> facetsMap = new Dictionary<string, Facets>();
-            facetsMap["Band"] = GetTaxonomyFacetCounts(tr, config, sfc, "$bands");
-            facetsMap["Composer"] = GetTaxonomyFacetCounts(tr, config, sfc, "$composers");
-            Facets facets = new MultiFacets(facetsMap, GetTaxonomyFacetCounts(tr, config, sfc));
-
-            // Obtain facets results and hand-test them
-            AssertCorrectResults(facets);
-            assertOrdinalsExist("$facets", ir);
-            assertOrdinalsExist("$bands", ir);
-            assertOrdinalsExist("$composers", ir);
-
-            IOUtils.Close(tr, ir, iw, tw, indexDir, taxoDir);
-        }
-
-        [Test]
-        public virtual void TestSomeSameSomeDifferent()
-        {
-            Directory indexDir = NewDirectory();
-            Directory taxoDir = NewDirectory();
-
-            // create and open an index writer
-            RandomIndexWriter iw = new RandomIndexWriter(Random(), indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random(), MockTokenizer.WHITESPACE, false)));
-            // create and open a taxonomy writer
-            TaxonomyWriter tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE);
-
-            FacetsConfig config = Config;
-            config.SetIndexFieldName("Band", "$music");
-            config.SetIndexFieldName("Composer", "$music");
-            config.SetIndexFieldName("Author", "$literature");
-            seedIndex(tw, iw, config);
-
-            IndexReader ir = iw.Reader;
-            tw.Commit();
-
-            // prepare index reader and taxonomy.
-            var tr = new DirectoryTaxonomyReader(taxoDir);
-
-            // prepare searcher to search against
-            IndexSearcher searcher = NewSearcher(ir);
-
-            FacetsCollector sfc = PerformSearch(tr, ir, searcher);
-
-            IDictionary<string, Facets> facetsMap = new Dictionary<string, Facets>();
-            Facets facets2 = GetTaxonomyFacetCounts(tr, config, sfc, "$music");
-            facetsMap["Band"] = facets2;
-            facetsMap["Composer"] = facets2;
-            facetsMap["Author"] = GetTaxonomyFacetCounts(tr, config, sfc, "$literature");
-            Facets facets = new MultiFacets(facetsMap, GetTaxonomyFacetCounts(tr, config, sfc));
-
-            // Obtain facets results and hand-test them
-            AssertCorrectResults(facets);
-            assertOrdinalsExist("$music", ir);
-            assertOrdinalsExist("$literature", ir);
-
-            IOUtils.Close(tr, ir, iw, tw);
-            IOUtils.Close(indexDir, taxoDir);
-        }
-
-        
-        private void AssertCorrectResults(Facets facets)
-        {
-            Assert.AreEqual(5, facets.GetSpecificValue("Band"));
-            Assert.AreEqual("dim=Band path=[] value=5 childCount=2\n  Rock & Pop (4)\n  Punk (1)\n", facets.GetTopChildren(10, "Band").ToString());
-            Assert.AreEqual("dim=Band path=[Rock & Pop] value=4 childCount=4\n  The Beatles (1)\n  U2 (1)\n  REM (1)\n  Dave Matthews Band (1)\n", facets.GetTopChildren(10, "Band", "Rock & Pop").ToString());
-            Assert.AreEqual("dim=Author path=[] value=3 childCount=3\n  Mark Twain (1)\n  Stephen King (1)\n  Kurt Vonnegut (1)\n", facets.GetTopChildren(10, "Author").ToString());
-        }
-
-        
-        private static FacetsCollector PerformSearch(TaxonomyReader tr, IndexReader ir, IndexSearcher searcher)
-        {
-            FacetsCollector fc = new FacetsCollector();
-            FacetsCollector.Search(searcher, new MatchAllDocsQuery(), 10, fc);
-            return fc;
-        }
-
-        private static void seedIndex(TaxonomyWriter tw, RandomIndexWriter iw, FacetsConfig config)
-        {
-            foreach (FacetField ff in CATEGORIES)
-            {
-                Document doc = new Document();
-                doc.Add(ff);
-                doc.Add(new TextField("content", "alpha", Field.Store.YES));
-                iw.AddDocument(config.Build(tw, doc));
-            }
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/TestRandomSamplingFacetsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/TestRandomSamplingFacetsCollector.cs b/src/Lucene.Net.Tests/core/Facet/TestRandomSamplingFacetsCollector.cs
deleted file mode 100644
index afd46e5..0000000
--- a/src/Lucene.Net.Tests/core/Facet/TestRandomSamplingFacetsCollector.cs
+++ /dev/null
@@ -1,154 +0,0 @@
-using System;
-using System.Diagnostics;
-using Lucene.Net.Randomized.Generators;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet
-{
-
-    using Document = Lucene.Net.Documents.Document;
-    using Store = Lucene.Net.Documents.Field.Store;
-    using StringField = Lucene.Net.Documents.StringField;
-    using MatchingDocs = Lucene.Net.Facet.FacetsCollector.MatchingDocs;
-    using FastTaxonomyFacetCounts = Lucene.Net.Facet.Taxonomy.FastTaxonomyFacetCounts;
-    using TaxonomyReader = Lucene.Net.Facet.Taxonomy.TaxonomyReader;
-    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
-    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
-    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
-    using Term = Lucene.Net.Index.Term;
-    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
-    using MultiCollector = Lucene.Net.Search.MultiCollector;
-    using TermQuery = Lucene.Net.Search.TermQuery;
-    using Directory = Lucene.Net.Store.Directory;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-    public class TestRandomSamplingFacetsCollector : FacetTestCase
-    {
-
-        [Test]
-        public virtual void TestRandomSampling()
-        {
-            Directory dir = NewDirectory();
-            Directory taxoDir = NewDirectory();
-
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            FacetsConfig config = new FacetsConfig();
-
-            int numDocs = AtLeast(10000);
-            for (int i = 0; i < numDocs; i++)
-            {
-                Document doc = new Document();
-                doc.Add(new StringField("EvenOdd", (i % 2 == 0) ? "even" : "odd", Store.NO));
-                doc.Add(new FacetField("iMod10", Convert.ToString(i % 10)));
-                writer.AddDocument(config.Build(taxoWriter, doc));
-            }
-            Random random = Random();
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-            IOUtils.Close(writer, taxoWriter);
-
-            // Test empty results
-            RandomSamplingFacetsCollector collectRandomZeroResults = new RandomSamplingFacetsCollector(numDocs / 10, random.NextLong());
-
-            // There should be no divisions by zero
-            searcher.Search(new TermQuery(new Term("EvenOdd", "NeverMatches")), collectRandomZeroResults);
-
-            // There should be no divisions by zero and no null result
-            Assert.NotNull(collectRandomZeroResults.GetMatchingDocs);
-
-            // There should be no results at all
-            foreach (MatchingDocs doc in collectRandomZeroResults.GetMatchingDocs)
-            {
-                Assert.AreEqual(0, doc.totalHits);
-            }
-
-            // Now start searching and retrieve results.
-
-            // Use a query to select half of the documents.
-            TermQuery query = new TermQuery(new Term("EvenOdd", "even"));
-
-            // there will be 5 facet values (0, 2, 4, 6 and 8), as only the even (i %
-            // 10) are hits.
-            // there is a REAL small chance that one of the 5 values will be missed when
-            // sampling.
-            // but is that 0.8 (chance not to take a value) ^ 2000 * 5 (any can be
-            // missing) ~ 10^-193
-            // so that is probably not going to happen.
-            int maxNumChildren = 5;
-
-            RandomSamplingFacetsCollector random100Percent = new RandomSamplingFacetsCollector(numDocs, random.NextLong()); // no sampling
-            RandomSamplingFacetsCollector random10Percent = new RandomSamplingFacetsCollector(numDocs / 10, random.NextLong()); // 10 % of total docs, 20% of the hits
-
-            FacetsCollector fc = new FacetsCollector();
-
-            searcher.Search(query, MultiCollector.Wrap(fc, random100Percent, random10Percent));
-
-            FastTaxonomyFacetCounts random10FacetCounts = new FastTaxonomyFacetCounts(taxoReader, config, random10Percent);
-            FastTaxonomyFacetCounts random100FacetCounts = new FastTaxonomyFacetCounts(taxoReader, config, random100Percent);
-            FastTaxonomyFacetCounts exactFacetCounts = new FastTaxonomyFacetCounts(taxoReader, config, fc);
-
-            FacetResult random10Result = random10Percent.AmortizeFacetCounts(random10FacetCounts.GetTopChildren(10, "iMod10"), config, searcher);
-            FacetResult random100Result = random100FacetCounts.GetTopChildren(10, "iMod10");
-            FacetResult exactResult = exactFacetCounts.GetTopChildren(10, "iMod10");
-
-            Assert.AreEqual(random100Result, exactResult);
-
-            // we should have five children, but there is a small chance we have less.
-            // (see above).
-            Assert.True(random10Result.ChildCount <= maxNumChildren);
-            // there should be one child at least.
-            Assert.True(random10Result.ChildCount >= 1);
-
-            // now calculate some statistics to determine if the sampled result is 'ok'.
-            // because random sampling is used, the results will vary each time.
-            int sum = 0;
-            foreach (LabelAndValue lav in random10Result.LabelValues)
-            {
-                sum += (int)lav.value;
-            }
-            float mu = (float)sum / (float)maxNumChildren;
-
-            float variance = 0;
-            foreach (LabelAndValue lav in random10Result.LabelValues)
-            {
-                variance += (float)Math.Pow((mu - (int)lav.value), 2);
-            }
-            variance = variance / maxNumChildren;
-            float sigma = (float)Math.Sqrt(variance);
-
-            // we query only half the documents and have 5 categories. The average
-            // number of docs in a category will thus be the total divided by 5*2
-            float targetMu = numDocs / (5.0f * 2.0f);
-
-            // the average should be in the range and the standard deviation should not
-            // be too great
-            Assert.True(sigma < 200);
-            Assert.True(targetMu - 3 * sigma < mu && mu < targetMu + 3 * sigma);
-
-            IOUtils.Close(searcher.IndexReader, taxoReader, dir, taxoDir);
-        }
-
-    }
-
-}
\ No newline at end of file


[14/14] lucenenet git commit: Adding Lucene.Net.Classification to the sln

Posted by sy...@apache.org.
Adding Lucene.Net.Classification to the sln


Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/56049f92
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/56049f92
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/56049f92

Branch: refs/heads/master
Commit: 56049f927c9e9acf69a3a28d05f8c75ec89cb12b
Parents: 68aa972
Author: Itamar Syn-Hershko <it...@code972.com>
Authored: Wed Dec 31 21:11:36 2014 +0200
Committer: Itamar Syn-Hershko <it...@code972.com>
Committed: Wed Dec 31 21:11:36 2014 +0200

----------------------------------------------------------------------
 Lucene.Net.sln                                  | 24 ++++++++++++++++++++
 .../Lucene.Net.Tests.Classification.csproj      |  7 +++---
 2 files changed, 28 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/56049f92/Lucene.Net.sln
----------------------------------------------------------------------
diff --git a/Lucene.Net.sln b/Lucene.Net.sln
index 2577faa..c3f9abe 100644
--- a/Lucene.Net.sln
+++ b/Lucene.Net.sln
@@ -15,6 +15,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene.Net.Facet", "src\Luc
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene.Net.Tests.Facet", "src\Lucene.Net.Tests.Facet\Lucene.Net.Tests.Facet.csproj", "{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene.Net.Classification", "src\Lucene.Net.Classification\Lucene.Net.Classification.csproj", "{E067B8BB-D8E7-4040-BEB8-EFF8BB4149BD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene.Net.Tests.Classification", "src\Lucene.Net.Tests.Classification\Lucene.Net.Tests.Classification.csproj", "{866723F4-E3A4-47C5-A49F-9A68ADD4CFAE}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -86,6 +90,26 @@ Global
 		{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
 		{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
 		{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}.Release|x86.ActiveCfg = Release|Any CPU
+		{E067B8BB-D8E7-4040-BEB8-EFF8BB4149BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{E067B8BB-D8E7-4040-BEB8-EFF8BB4149BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{E067B8BB-D8E7-4040-BEB8-EFF8BB4149BD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{E067B8BB-D8E7-4040-BEB8-EFF8BB4149BD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{E067B8BB-D8E7-4040-BEB8-EFF8BB4149BD}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{E067B8BB-D8E7-4040-BEB8-EFF8BB4149BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{E067B8BB-D8E7-4040-BEB8-EFF8BB4149BD}.Release|Any CPU.Build.0 = Release|Any CPU
+		{E067B8BB-D8E7-4040-BEB8-EFF8BB4149BD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{E067B8BB-D8E7-4040-BEB8-EFF8BB4149BD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{E067B8BB-D8E7-4040-BEB8-EFF8BB4149BD}.Release|x86.ActiveCfg = Release|Any CPU
+		{866723F4-E3A4-47C5-A49F-9A68ADD4CFAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{866723F4-E3A4-47C5-A49F-9A68ADD4CFAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{866723F4-E3A4-47C5-A49F-9A68ADD4CFAE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{866723F4-E3A4-47C5-A49F-9A68ADD4CFAE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{866723F4-E3A4-47C5-A49F-9A68ADD4CFAE}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{866723F4-E3A4-47C5-A49F-9A68ADD4CFAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{866723F4-E3A4-47C5-A49F-9A68ADD4CFAE}.Release|Any CPU.Build.0 = Release|Any CPU
+		{866723F4-E3A4-47C5-A49F-9A68ADD4CFAE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{866723F4-E3A4-47C5-A49F-9A68ADD4CFAE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{866723F4-E3A4-47C5-A49F-9A68ADD4CFAE}.Release|x86.ActiveCfg = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/56049f92/src/Lucene.Net.Tests.Classification/Lucene.Net.Tests.Classification.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Classification/Lucene.Net.Tests.Classification.csproj b/src/Lucene.Net.Tests.Classification/Lucene.Net.Tests.Classification.csproj
index 693aacd..62616fa 100644
--- a/src/Lucene.Net.Tests.Classification/Lucene.Net.Tests.Classification.csproj
+++ b/src/Lucene.Net.Tests.Classification/Lucene.Net.Tests.Classification.csproj
@@ -4,7 +4,7 @@
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}</ProjectGuid>
+    <ProjectGuid>{866723F4-E3A4-47C5-A49F-9A68ADD4CFAE}</ProjectGuid>
     <OutputType>Library</OutputType>
     <AppDesignerFolder>Properties</AppDesignerFolder>
     <RootNamespace>Lucene.Net.Tests.Classification</RootNamespace>
@@ -33,9 +33,9 @@
     <Reference Include="Lucene.Net.TestFramework">
       <HintPath>..\Lucene.Net.Tests\bin\Debug\Lucene.Net.TestFramework.dll</HintPath>
     </Reference>
-    <Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+    <Reference Include="nunit.framework, Version=2.6.3.13283, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
-      <HintPath>..\Lucene.Net.Classification\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+      <HintPath>..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
@@ -64,6 +64,7 @@
   </ItemGroup>
   <ItemGroup>
     <None Include="app.config" />
+    <None Include="packages.config" />
   </ItemGroup>
   <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />


[03/14] lucenenet git commit: Moving Lucene.Net.Facet tests to their appropriate place

Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyFacetCounts.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyFacetCounts.cs b/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyFacetCounts.cs
deleted file mode 100644
index 8038313..0000000
--- a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyFacetCounts.cs
+++ /dev/null
@@ -1,851 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using Lucene.Net.Randomized.Generators;
-using Lucene.Net.Support;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet.Taxonomy
-{
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-
-    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
-    using Document = Lucene.Net.Documents.Document;
-    using Field = Lucene.Net.Documents.Field;
-    using StringField = Lucene.Net.Documents.StringField;
-    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
-    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
-    using DirectoryReader = Lucene.Net.Index.DirectoryReader;
-    using IndexWriter = Lucene.Net.Index.IndexWriter;
-    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
-    using NoMergePolicy = Lucene.Net.Index.NoMergePolicy;
-    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
-    using Term = Lucene.Net.Index.Term;
-    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
-    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
-    using Query = Lucene.Net.Search.Query;
-    using TermQuery = Lucene.Net.Search.TermQuery;
-    using DefaultSimilarity = Lucene.Net.Search.Similarities.DefaultSimilarity;
-    using PerFieldSimilarityWrapper = Lucene.Net.Search.Similarities.PerFieldSimilarityWrapper;
-    using Similarity = Lucene.Net.Search.Similarities.Similarity;
-    using Directory = Lucene.Net.Store.Directory;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-    using TestUtil = Lucene.Net.Util.TestUtil;
-    [TestFixture]
-    public class TestTaxonomyFacetCounts : FacetTestCase
-    {
-
-        [Test]
-        public virtual void TestBasic()
-        {
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            // Writes facet ords to a separate directory from the
-            // main index:
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-
-            FacetsConfig config = new FacetsConfig();
-            config.SetHierarchical("Publish Date", true);
-
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            Document doc = new Document();
-            doc.Add(new FacetField("Author", "Bob"));
-            doc.Add(new FacetField("Publish Date", "2010", "10", "15"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new FacetField("Author", "Lisa"));
-            doc.Add(new FacetField("Publish Date", "2010", "10", "20"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new FacetField("Author", "Lisa"));
-            doc.Add(new FacetField("Publish Date", "2012", "1", "1"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new FacetField("Author", "Susan"));
-            doc.Add(new FacetField("Publish Date", "2012", "1", "7"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new FacetField("Author", "Frank"));
-            doc.Add(new FacetField("Publish Date", "1999", "5", "5"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-
-            // NRT open
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            // Aggregate the facet counts:
-            FacetsCollector c = new FacetsCollector();
-
-            // MatchAllDocsQuery is for "browsing" (counts facets
-            // for all non-deleted docs in the index); normally
-            // you'd use a "normal" query, and use MultiCollector to
-            // wrap collecting the "normal" hits and also facets:
-            searcher.Search(new MatchAllDocsQuery(), c);
-
-            Facets facets = new FastTaxonomyFacetCounts(taxoReader, config, c);
-
-            // Retrieve & verify results:
-            Assert.AreEqual("dim=Publish Date path=[] value=5 childCount=3\n  2010 (2)\n  2012 (2)\n  1999 (1)\n", facets.GetTopChildren(10, "Publish Date").ToString());
-            Assert.AreEqual("dim=Author path=[] value=5 childCount=4\n  Lisa (2)\n  Bob (1)\n  Susan (1)\n  Frank (1)\n", facets.GetTopChildren(10, "Author").ToString());
-
-            // Now user drills down on Publish Date/2010:
-            DrillDownQuery q2 = new DrillDownQuery(config);
-            q2.Add("Publish Date", "2010");
-            c = new FacetsCollector();
-            searcher.Search(q2, c);
-            facets = new FastTaxonomyFacetCounts(taxoReader, config, c);
-            Assert.AreEqual("dim=Author path=[] value=2 childCount=2\n  Bob (1)\n  Lisa (1)\n", facets.GetTopChildren(10, "Author").ToString());
-
-            Assert.AreEqual(1, facets.GetSpecificValue("Author", "Lisa"));
-
-            Assert.Null(facets.GetTopChildren(10, "Non exitent dim"));
-
-            // Smoke test PrintTaxonomyStats:
-            ByteArrayOutputStream bos = new ByteArrayOutputStream();
-            PrintTaxonomyStats.PrintStats(taxoReader, Console.Out, true);
-            string result = bos.ToString();
-            Assert.True(result.IndexOf("/Author: 4 immediate children; 5 total categories", StringComparison.Ordinal) != -1);
-            Assert.True(result.IndexOf("/Publish Date: 3 immediate children; 12 total categories", StringComparison.Ordinal) != -1);
-            // Make sure at least a few nodes of the tree came out:
-            Assert.True(result.IndexOf("  /1999", StringComparison.Ordinal) != -1);
-            Assert.True(result.IndexOf("  /2012", StringComparison.Ordinal) != -1);
-            Assert.True(result.IndexOf("      /20", StringComparison.Ordinal) != -1);
-
-            IOUtils.Close(writer, taxoWriter, searcher.IndexReader, taxoReader, taxoDir, dir);
-        }
-
-        // LUCENE-5333
-        [Test]
-        public virtual void TestSparseFacets()
-        {
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            // Writes facet ords to a separate directory from the
-            // main index:
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-            FacetsConfig config = new FacetsConfig();
-
-            Document doc = new Document();
-            doc.Add(new FacetField("a", "foo1"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            if (Random().NextBoolean())
-            {
-                writer.Commit();
-            }
-
-            doc = new Document();
-            doc.Add(new FacetField("a", "foo2"));
-            doc.Add(new FacetField("b", "bar1"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            if (Random().NextBoolean())
-            {
-                writer.Commit();
-            }
-
-            doc = new Document();
-            doc.Add(new FacetField("a", "foo3"));
-            doc.Add(new FacetField("b", "bar2"));
-            doc.Add(new FacetField("c", "baz1"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-
-            // NRT open
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            FacetsCollector c = new FacetsCollector();
-            searcher.Search(new MatchAllDocsQuery(), c);
-
-            Facets facets = GetTaxonomyFacetCounts(taxoReader, new FacetsConfig(), c);
-
-            // Ask for top 10 labels for any dims that have counts:
-            IList<FacetResult> results = facets.GetAllDims(10);
-
-            Assert.AreEqual(3, results.Count);
-            Assert.AreEqual("dim=a path=[] value=3 childCount=3\n  foo1 (1)\n  foo2 (1)\n  foo3 (1)\n", results[0].ToString());
-            Assert.AreEqual("dim=b path=[] value=2 childCount=2\n  bar1 (1)\n  bar2 (1)\n", results[1].ToString());
-            Assert.AreEqual("dim=c path=[] value=1 childCount=1\n  baz1 (1)\n", results[2].ToString());
-
-            IOUtils.Close(writer, taxoWriter, searcher.IndexReader, taxoReader, taxoDir, dir);
-        }
-
-        [Test]
-        public virtual void TestWrongIndexFieldName()
-        {
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            // Writes facet ords to a separate directory from the
-            // main index:
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-
-            FacetsConfig config = new FacetsConfig();
-            config.SetIndexFieldName("a", "$facets2");
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            Document doc = new Document();
-            doc.Add(new FacetField("a", "foo1"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-
-            // NRT open
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            FacetsCollector c = new FacetsCollector();
-            searcher.Search(new MatchAllDocsQuery(), c);
-
-            // Uses default $facets field:
-            Facets facets;
-            if (Random().NextBoolean())
-            {
-                facets = new FastTaxonomyFacetCounts(taxoReader, config, c);
-            }
-            else
-            {
-                OrdinalsReader ordsReader = new DocValuesOrdinalsReader();
-                if (Random().NextBoolean())
-                {
-                    ordsReader = new CachedOrdinalsReader(ordsReader);
-                }
-                facets = new TaxonomyFacetCounts(ordsReader, taxoReader, config, c);
-            }
-
-            // Ask for top 10 labels for any dims that have counts:
-            IList<FacetResult> results = facets.GetAllDims(10);
-            Assert.True(results.Count == 0);
-
-            try
-            {
-                facets.GetSpecificValue("a");
-                Fail("should have hit exc");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-
-            try
-            {
-                facets.GetTopChildren(10, "a");
-                Fail("should have hit exc");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-
-            IOUtils.Close(writer, taxoWriter, searcher.IndexReader, taxoReader, taxoDir, dir);
-        }
-
-        [Test]
-        public virtual void TestReallyNoNormsForDrillDown()
-        {
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-            IndexWriterConfig iwc = NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
-            iwc.SetSimilarity(new PerFieldSimilarityWrapperAnonymousInnerClassHelper(this));
-            TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir, iwc);
-            FacetsConfig config = new FacetsConfig();
-
-            Document doc = new Document();
-            doc.Add(NewTextField("field", "text", Field.Store.NO));
-            doc.Add(new FacetField("a", "path"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-            IOUtils.Close(writer, taxoWriter, dir, taxoDir);
-        }
-
-        private class PerFieldSimilarityWrapperAnonymousInnerClassHelper : PerFieldSimilarityWrapper
-        {
-            private readonly TestTaxonomyFacetCounts outerInstance;
-
-            public PerFieldSimilarityWrapperAnonymousInnerClassHelper(TestTaxonomyFacetCounts outerInstance)
-            {
-                this.outerInstance = outerInstance;
-                sim = new DefaultSimilarity();
-            }
-
-            internal readonly Similarity sim;
-
-            public override Similarity Get(string name)
-            {
-                Assert.AreEqual("field", name);
-                return sim;
-            }
-        }
-
-        [Test]
-        public virtual void TestMultiValuedHierarchy()
-        {
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-            FacetsConfig config = new FacetsConfig();
-            config.SetHierarchical("a", true);
-            config.SetMultiValued("a", true);
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            Document doc = new Document();
-            doc.Add(NewTextField("field", "text", Field.Store.NO));
-            doc.Add(new FacetField("a", "path", "x"));
-            doc.Add(new FacetField("a", "path", "y"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-
-            // NRT open
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            // Aggregate the facet counts:
-            FacetsCollector c = new FacetsCollector();
-
-            // MatchAllDocsQuery is for "browsing" (counts facets
-            // for all non-deleted docs in the index); normally
-            // you'd use a "normal" query, and use MultiCollector to
-            // wrap collecting the "normal" hits and also facets:
-            searcher.Search(new MatchAllDocsQuery(), c);
-            Facets facets = GetTaxonomyFacetCounts(taxoReader, config, c);
-
-            try
-            {
-                facets.GetSpecificValue("a");
-                Fail("didn't hit expected exception");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-
-            FacetResult result = facets.GetTopChildren(10, "a");
-            Assert.AreEqual(1, result.LabelValues.Length);
-            Assert.AreEqual(1, (int)result.LabelValues[0].value);
-
-            IOUtils.Close(writer, taxoWriter, searcher.IndexReader, taxoReader, dir, taxoDir);
-        }
-
-        [Test]
-        public virtual void TestLabelWithDelimiter()
-        {
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-
-            FacetsConfig config = new FacetsConfig();
-            config.SetMultiValued("dim", true);
-
-            Document doc = new Document();
-            doc.Add(NewTextField("field", "text", Field.Store.NO));
-            doc.Add(new FacetField("dim", "test\u001Fone"));
-            doc.Add(new FacetField("dim", "test\u001Etwo"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-
-            // NRT open
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            FacetsCollector c = new FacetsCollector();
-            searcher.Search(new MatchAllDocsQuery(), c);
-
-            Facets facets = GetTaxonomyFacetCounts(taxoReader, config, c);
-            Assert.AreEqual(1, facets.GetSpecificValue("dim", "test\u001Fone"));
-            Assert.AreEqual(1, facets.GetSpecificValue("dim", "test\u001Etwo"));
-
-            FacetResult result = facets.GetTopChildren(10, "dim");
-            Assert.AreEqual("dim=dim path=[] value=-1 childCount=2\n  test\u001Fone (1)\n  test\u001Etwo (1)\n", result.ToString());
-            IOUtils.Close(writer, taxoWriter, searcher.IndexReader, taxoReader, dir, taxoDir);
-        }
-
-        [Test]
-        public virtual void TestRequireDimCount()
-        {
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-
-            FacetsConfig config = new FacetsConfig();
-            config.SetRequireDimCount("dim", true);
-
-            config.SetMultiValued("dim2", true);
-            config.SetRequireDimCount("dim2", true);
-
-            config.SetMultiValued("dim3", true);
-            config.SetHierarchical("dim3", true);
-            config.SetRequireDimCount("dim3", true);
-
-            Document doc = new Document();
-            doc.Add(NewTextField("field", "text", Field.Store.NO));
-            doc.Add(new FacetField("dim", "a"));
-            doc.Add(new FacetField("dim2", "a"));
-            doc.Add(new FacetField("dim2", "b"));
-            doc.Add(new FacetField("dim3", "a", "b"));
-            doc.Add(new FacetField("dim3", "a", "c"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-
-            // NRT open
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            FacetsCollector c = new FacetsCollector();
-            searcher.Search(new MatchAllDocsQuery(), c);
-
-            Facets facets = GetTaxonomyFacetCounts(taxoReader, config, c);
-            Assert.AreEqual(1, facets.GetTopChildren(10, "dim").Value);
-            Assert.AreEqual(1, facets.GetTopChildren(10, "dim2").Value);
-            Assert.AreEqual(1, facets.GetTopChildren(10, "dim3").Value);
-            try
-            {
-                Assert.AreEqual(1, facets.GetSpecificValue("dim"));
-                Fail("didn't hit expected exception");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            Assert.AreEqual(1, facets.GetSpecificValue("dim2"));
-            Assert.AreEqual(1, facets.GetSpecificValue("dim3"));
-            IOUtils.Close(writer, taxoWriter, searcher.IndexReader, taxoReader, dir, taxoDir);
-        }
-
-        // LUCENE-4583: make sure if we require > 32 KB for one
-        // document, we don't hit exc when using Facet42DocValuesFormat
-        [Test]
-        public virtual void TestManyFacetsInOneDocument()
-        {
-            AssumeTrue("default Codec doesn't support huge BinaryDocValues", TestUtil.FieldSupportsHugeBinaryDocValues(FacetsConfig.DEFAULT_INDEX_FIELD_NAME));
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-            IndexWriterConfig iwc = NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir, iwc);
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-
-            FacetsConfig config = new FacetsConfig();
-            config.SetMultiValued("dim", true);
-
-            int numLabels = TestUtil.NextInt(Random(), 40000, 100000);
-
-            Document doc = new Document();
-            doc.Add(NewTextField("field", "text", Field.Store.NO));
-            for (int i = 0; i < numLabels; i++)
-            {
-                doc.Add(new FacetField("dim", "" + i));
-            }
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-
-            // NRT open
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            // Aggregate the facet counts:
-            FacetsCollector c = new FacetsCollector();
-
-            // MatchAllDocsQuery is for "browsing" (counts facets
-            // for all non-deleted docs in the index); normally
-            // you'd use a "normal" query, and use MultiCollector to
-            // wrap collecting the "normal" hits and also facets:
-            searcher.Search(new MatchAllDocsQuery(), c);
-            Facets facets = GetTaxonomyFacetCounts(taxoReader, config, c);
-
-            FacetResult result = facets.GetTopChildren(int.MaxValue, "dim");
-            Assert.AreEqual(numLabels, result.LabelValues.Length);
-            var allLabels = new HashSet<string>();
-            foreach (LabelAndValue labelValue in result.LabelValues)
-            {
-                allLabels.Add(labelValue.label);
-                Assert.AreEqual(1, (int)labelValue.value);
-            }
-            Assert.AreEqual(numLabels, allLabels.Count);
-
-            IOUtils.Close(searcher.IndexReader, taxoWriter, writer, taxoReader, dir, taxoDir);
-        }
-
-        // Make sure we catch when app didn't declare field as
-        // hierarchical but it was:
-        [Test]
-        public virtual void TestDetectHierarchicalField()
-        {
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-            var writer = new RandomIndexWriter(Random(), dir);
-            FacetsConfig config = new FacetsConfig();
-
-            Document doc = new Document();
-            doc.Add(NewTextField("field", "text", Field.Store.NO));
-            doc.Add(new FacetField("a", "path", "other"));
-            try
-            {
-                config.Build(taxoWriter, doc);
-                Fail("did not hit expected exception");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            IOUtils.Close(writer, taxoWriter, dir, taxoDir);
-        }
-
-        // Make sure we catch when app didn't declare field as
-        // multi-valued but it was:
-        [Test]
-        public virtual void TestDetectMultiValuedField()
-        {
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-            TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-            FacetsConfig config = new FacetsConfig();
-
-            Document doc = new Document();
-            doc.Add(NewTextField("field", "text", Field.Store.NO));
-            doc.Add(new FacetField("a", "path"));
-            doc.Add(new FacetField("a", "path2"));
-            try
-            {
-                config.Build(taxoWriter, doc);
-                Fail("did not hit expected exception");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            IOUtils.Close(writer, taxoWriter, dir, taxoDir);
-        }
-
-        [Test]
-        public virtual void TestSeparateIndexedFields()
-        {
-            Store.Directory indexDir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
-            FacetsConfig config = new FacetsConfig();
-            config.SetIndexFieldName("b", "$b");
-
-            for (int i = AtLeast(30); i > 0; --i)
-            {
-                Document doc = new Document();
-                doc.Add(new StringField("f", "v", Field.Store.NO));
-                doc.Add(new FacetField("a", "1"));
-                doc.Add(new FacetField("b", "1"));
-                iw.AddDocument(config.Build(taxoWriter, doc));
-            }
-
-            DirectoryReader r = DirectoryReader.Open(iw, true);
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            FacetsCollector sfc = new FacetsCollector();
-            NewSearcher(r).Search(new MatchAllDocsQuery(), sfc);
-            Facets facets1 = GetTaxonomyFacetCounts(taxoReader, config, sfc);
-            Facets facets2 = GetTaxonomyFacetCounts(taxoReader, config, sfc, "$b");
-            Assert.AreEqual(r.MaxDoc, (int)facets1.GetTopChildren(10, "a").Value);
-            Assert.AreEqual(r.MaxDoc, (int)facets2.GetTopChildren(10, "b").Value);
-            IOUtils.Close(taxoWriter, iw, taxoReader, taxoDir, r, indexDir);
-        }
-
-        [Test]
-        public virtual void TestCountRoot()
-        {
-            // LUCENE-4882: FacetsAccumulator threw NPE if a FacetRequest was defined on CP.EMPTY
-            Store.Directory indexDir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
-            FacetsConfig config = new FacetsConfig();
-            for (int i = AtLeast(30); i > 0; --i)
-            {
-                Document doc = new Document();
-                doc.Add(new FacetField("a", "1"));
-                doc.Add(new FacetField("b", "1"));
-                iw.AddDocument(config.Build(taxoWriter, doc));
-            }
-
-            DirectoryReader r = DirectoryReader.Open(iw, true);
-            DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            FacetsCollector sfc = new FacetsCollector();
-            NewSearcher(r).Search(new MatchAllDocsQuery(), sfc);
-            Facets facets = GetTaxonomyFacetCounts(taxoReader, config, sfc);
-            foreach (FacetResult result in facets.GetAllDims(10))
-            {
-                Assert.AreEqual(r.NumDocs, (int)result.Value);
-            }
-
-            IOUtils.Close(taxoWriter, iw, taxoReader, taxoDir, r, indexDir);
-        }
-
-        [Test]
-        public virtual void TestGetFacetResultsTwice()
-        {
-            // LUCENE-4893: counts were multiplied as many times as getFacetResults was called.
-            Store.Directory indexDir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
-            FacetsConfig config = new FacetsConfig();
-
-            Document doc = new Document();
-            doc.Add(new FacetField("a", "1"));
-            doc.Add(new FacetField("b", "1"));
-            iw.AddDocument(config.Build(taxoWriter, doc));
-
-            DirectoryReader r = DirectoryReader.Open(iw, true);
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            FacetsCollector sfc = new FacetsCollector();
-            NewSearcher(r).Search(new MatchAllDocsQuery(), sfc);
-
-            Facets facets = GetTaxonomyFacetCounts(taxoReader, config, sfc);
-            IList<FacetResult> res1 = facets.GetAllDims(10);
-            IList<FacetResult> res2 = facets.GetAllDims(10);
-            Assert.AreEqual(res1, res2, "calling getFacetResults twice should return the .equals()=true result");
-
-            IOUtils.Close(taxoWriter, iw, taxoReader, taxoDir, r, indexDir);
-        }
-
-        [Test]
-        public virtual void TestChildCount()
-        {
-            // LUCENE-4885: FacetResult.numValidDescendants was not set properly by FacetsAccumulator
-            var indexDir = NewDirectory();
-            var taxoDir = NewDirectory();
-
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
-            FacetsConfig config = new FacetsConfig();
-            for (int i = 0; i < 10; i++)
-            {
-                Document doc = new Document();
-                doc.Add(new FacetField("a", Convert.ToString(i)));
-                iw.AddDocument(config.Build(taxoWriter, doc));
-            }
-
-            DirectoryReader r = DirectoryReader.Open(iw, true);
-            DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            FacetsCollector sfc = new FacetsCollector();
-            NewSearcher(r).Search(new MatchAllDocsQuery(), sfc);
-            Facets facets = GetTaxonomyFacetCounts(taxoReader, config, sfc);
-
-            Assert.AreEqual(10, facets.GetTopChildren(2, "a").ChildCount);
-
-            IOUtils.Close(taxoWriter, iw, taxoReader, taxoDir, r, indexDir);
-        }
-
-        private void indexTwoDocs(TaxonomyWriter taxoWriter, IndexWriter indexWriter, FacetsConfig config, bool withContent)
-        {
-            for (int i = 0; i < 2; i++)
-            {
-                Document doc = new Document();
-                if (withContent)
-                {
-                    doc.Add(new StringField("f", "a", Field.Store.NO));
-                }
-                if (config != null)
-                {
-                    doc.Add(new FacetField("A", Convert.ToString(i)));
-                    indexWriter.AddDocument(config.Build(taxoWriter, doc));
-                }
-                else
-                {
-                    indexWriter.AddDocument(doc);
-                }
-            }
-
-            indexWriter.Commit();
-        }
-
-        [Test]
-        public virtual void TestSegmentsWithoutCategoriesOrResults()
-        {
-            // tests the accumulator when there are segments with no results
-            var indexDir = NewDirectory();
-            var taxoDir = NewDirectory();
-
-            IndexWriterConfig iwc = NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
-            //iwc.MergePolicy = NoMergePolicy.INSTANCE; // prevent merges
-            IndexWriter indexWriter = new IndexWriter(indexDir, iwc);
-
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            FacetsConfig config = new FacetsConfig();
-            indexTwoDocs(taxoWriter, indexWriter, config, false); // 1st segment, no content, with categories
-            indexTwoDocs(taxoWriter, indexWriter, null, true); // 2nd segment, with content, no categories
-            indexTwoDocs(taxoWriter, indexWriter, config, true); // 3rd segment ok
-            indexTwoDocs(taxoWriter, indexWriter, null, false); // 4th segment, no content, or categories
-            indexTwoDocs(taxoWriter, indexWriter, null, true); // 5th segment, with content, no categories
-            indexTwoDocs(taxoWriter, indexWriter, config, true); // 6th segment, with content, with categories
-            indexTwoDocs(taxoWriter, indexWriter, null, true); // 7th segment, with content, no categories
-            IOUtils.Close(indexWriter, taxoWriter);
-
-            DirectoryReader indexReader = DirectoryReader.Open(indexDir);
-            var taxoReader = new DirectoryTaxonomyReader(taxoDir);
-            IndexSearcher indexSearcher = NewSearcher(indexReader);
-
-            // search for "f:a", only segments 1 and 3 should match results
-            Query q = new TermQuery(new Term("f", "a"));
-            FacetsCollector sfc = new FacetsCollector();
-            indexSearcher.Search(q, sfc);
-            Facets facets = GetTaxonomyFacetCounts(taxoReader, config, sfc);
-            FacetResult result = facets.GetTopChildren(10, "A");
-            Assert.AreEqual(2, result.LabelValues.Length, "wrong number of children");
-            foreach (LabelAndValue labelValue in result.LabelValues)
-            {
-                Assert.AreEqual(2, (int)labelValue.value, "wrong weight for child " + labelValue.label);
-            }
-
-            IOUtils.Close(indexReader, taxoReader, indexDir, taxoDir);
-        }
-
-        [Test]
-        public virtual void TestRandom()
-        {
-            string[] tokens = GetRandomTokens(10);
-            Store.Directory indexDir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            RandomIndexWriter w = new RandomIndexWriter(Random(), indexDir);
-            var tw = new DirectoryTaxonomyWriter(taxoDir);
-            FacetsConfig config = new FacetsConfig();
-            int numDocs = AtLeast(1000);
-            int numDims = TestUtil.NextInt(Random(), 1, 7);
-            IList<TestDoc> testDocs = GetRandomDocs(tokens, numDocs, numDims);
-            foreach (TestDoc testDoc in testDocs)
-            {
-                Document doc = new Document();
-                doc.Add(NewStringField("content", testDoc.content, Field.Store.NO));
-                for (int j = 0; j < numDims; j++)
-                {
-                    if (testDoc.dims[j] != null)
-                    {
-                        doc.Add(new FacetField("dim" + j, testDoc.dims[j]));
-                    }
-                }
-                w.AddDocument(config.Build(tw, doc));
-            }
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(w.Reader);
-
-            // NRT open
-            var tr = new DirectoryTaxonomyReader(tw);
-
-            int iters = AtLeast(100);
-            for (int iter = 0; iter < iters; iter++)
-            {
-                string searchToken = tokens[Random().Next(tokens.Length)];
-                if (VERBOSE)
-                {
-                    Console.WriteLine("\nTEST: iter content=" + searchToken);
-                }
-                FacetsCollector fc = new FacetsCollector();
-                FacetsCollector.Search(searcher, new TermQuery(new Term("content", searchToken)), 10, fc);
-                Facets facets = GetTaxonomyFacetCounts(tr, config, fc);
-
-                // Slow, yet hopefully bug-free, faceting:
-                var expectedCounts = new List<Dictionary<string, int?>>();
-                for (int i = 0; i < numDims; i++)
-                {
-                    expectedCounts[i] = new Dictionary<string, int?>();
-                }
-
-                foreach (TestDoc doc in testDocs)
-                {
-                    if (doc.content.Equals(searchToken))
-                    {
-                        for (int j = 0; j < numDims; j++)
-                        {
-                            if (doc.dims[j] != null)
-                            {
-                                int? v = expectedCounts[j][doc.dims[j]];
-                                if (v == null)
-                                {
-                                    expectedCounts[j][doc.dims[j]] = 1;
-                                }
-                                else
-                                {
-                                    expectedCounts[j][doc.dims[j]] = (int)v + 1;
-                                }
-                            }
-                        }
-                    }
-                }
-
-                IList<FacetResult> expected = new List<FacetResult>();
-                for (int i = 0; i < numDims; i++)
-                {
-                    IList<LabelAndValue> labelValues = new List<LabelAndValue>();
-                    int totCount = 0;
-                    foreach (KeyValuePair<string, int?> ent in expectedCounts[i])
-                    {
-                        labelValues.Add(new LabelAndValue(ent.Key, ent.Value.Value));
-                        totCount += ent.Value.Value;
-                    }
-                    SortLabelValues(labelValues);
-                    if (totCount > 0)
-                    {
-                        expected.Add(new FacetResult("dim" + i, new string[0], totCount, labelValues.ToArray(), labelValues.Count));
-                    }
-                }
-
-                // Sort by highest value, tie break by value:
-                SortFacetResults(expected);
-
-                IList<FacetResult> actual = facets.GetAllDims(10);
-
-                // Messy: fixup ties
-                SortTies(actual);
-
-                Assert.AreEqual(expected, actual);
-            }
-
-            IOUtils.Close(w, tw, searcher.IndexReader, tr, indexDir, taxoDir);
-        }
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyFacetCounts2.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyFacetCounts2.cs b/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyFacetCounts2.cs
deleted file mode 100644
index 865f993..0000000
--- a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyFacetCounts2.cs
+++ /dev/null
@@ -1,403 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Lucene.Net.Randomized.Generators;
-using Lucene.Net.Support;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet.Taxonomy
-{
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-
-    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
-    using Document = Lucene.Net.Documents.Document;
-    using Store = Lucene.Net.Documents.Field.Store;
-    using StringField = Lucene.Net.Documents.StringField;
-    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
-    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
-    using DirectoryReader = Lucene.Net.Index.DirectoryReader;
-    using IndexWriter = Lucene.Net.Index.IndexWriter;
-    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
-    using NoMergePolicy = Lucene.Net.Index.NoMergePolicy;
-    using Term = Lucene.Net.Index.Term;
-    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
-    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
-    using TermQuery = Lucene.Net.Search.TermQuery;
-    using Directory = Lucene.Net.Store.Directory;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-    [TestFixture]
-    public class TestTaxonomyFacetCounts2 : FacetTestCase
-    {
-
-        private static readonly Term A = new Term("f", "a");
-        private const string CP_A = "A", CP_B = "B";
-        private const string CP_C = "C", CP_D = "D"; // indexed w/ NO_PARENTS
-        private const int NUM_CHILDREN_CP_A = 5, NUM_CHILDREN_CP_B = 3;
-        private const int NUM_CHILDREN_CP_C = 5, NUM_CHILDREN_CP_D = 5;
-        private static readonly FacetField[] CATEGORIES_A, CATEGORIES_B;
-        private static readonly FacetField[] CATEGORIES_C, CATEGORIES_D;
-        static TestTaxonomyFacetCounts2()
-        {
-            CATEGORIES_A = new FacetField[NUM_CHILDREN_CP_A];
-            for (int i = 0; i < NUM_CHILDREN_CP_A; i++)
-            {
-                CATEGORIES_A[i] = new FacetField(CP_A, Convert.ToString(i));
-            }
-            CATEGORIES_B = new FacetField[NUM_CHILDREN_CP_B];
-            for (int i = 0; i < NUM_CHILDREN_CP_B; i++)
-            {
-                CATEGORIES_B[i] = new FacetField(CP_B, Convert.ToString(i));
-            }
-
-            // NO_PARENTS categories
-            CATEGORIES_C = new FacetField[NUM_CHILDREN_CP_C];
-            for (int i = 0; i < NUM_CHILDREN_CP_C; i++)
-            {
-                CATEGORIES_C[i] = new FacetField(CP_C, Convert.ToString(i));
-            }
-
-            // Multi-level categories
-            CATEGORIES_D = new FacetField[NUM_CHILDREN_CP_D];
-            for (int i = 0; i < NUM_CHILDREN_CP_D; i++)
-            {
-                string val = Convert.ToString(i);
-                CATEGORIES_D[i] = new FacetField(CP_D, val, val + val); // e.g. D/1/11, D/2/22...
-            }
-        }
-
-        private static Net.Store.Directory indexDir, taxoDir;
-        private static IDictionary<string, int?> allExpectedCounts, termExpectedCounts;
-
-        [TestFixtureTearDown]
-        public static void AfterClassCountingFacetsAggregatorTest()
-        {
-            IOUtils.Close(indexDir, taxoDir);
-        }
-
-        private static IList<FacetField> RandomCategories(Random random)
-        {
-            // add random categories from the two dimensions, ensuring that the same
-            // category is not added twice.
-            int numFacetsA = random.Next(3) + 1; // 1-3
-            int numFacetsB = random.Next(2) + 1; // 1-2
-            List<FacetField> categories_a = new List<FacetField>();
-            categories_a.AddRange(Arrays.AsList(CATEGORIES_A));
-            List<FacetField> categories_b = new List<FacetField>();
-            categories_b.AddRange(Arrays.AsList(CATEGORIES_B));
-            categories_a = CollectionsHelper.Shuffle(categories_a).ToList();
-            categories_b = CollectionsHelper.Shuffle(categories_b).ToList();
-
-            List<FacetField> categories = new List<FacetField>();
-            categories.AddRange(categories_a.SubList(0, numFacetsA));
-            categories.AddRange(categories_b.SubList(0, numFacetsB));
-
-            // add the NO_PARENT categories
-            categories.Add(CATEGORIES_C[Random().Next(NUM_CHILDREN_CP_C)]);
-            categories.Add(CATEGORIES_D[Random().Next(NUM_CHILDREN_CP_D)]);
-
-            return categories;
-        }
-
-        private static void AddField(Document doc)
-        {
-            doc.Add(new StringField(A.Field(), A.Text(), Store.NO));
-        }
-
-        private static void AddFacets(Document doc, FacetsConfig config, bool updateTermExpectedCounts)
-        {
-            IList<FacetField> docCategories = RandomCategories(Random());
-            foreach (FacetField ff in docCategories)
-            {
-                doc.Add(ff);
-                string cp = ff.dim + "/" + ff.path[0];
-                allExpectedCounts[cp] = allExpectedCounts[cp] + 1;
-                if (updateTermExpectedCounts)
-                {
-                    termExpectedCounts[cp] = termExpectedCounts[cp] + 1;
-                }
-            }
-            // add 1 to each NO_PARENTS dimension
-            allExpectedCounts[CP_B] = allExpectedCounts[CP_B] + 1;
-            allExpectedCounts[CP_C] = allExpectedCounts[CP_C] + 1;
-            allExpectedCounts[CP_D] = allExpectedCounts[CP_D] + 1;
-            if (updateTermExpectedCounts)
-            {
-                termExpectedCounts[CP_B] = termExpectedCounts[CP_B] + 1;
-                termExpectedCounts[CP_C] = termExpectedCounts[CP_C] + 1;
-                termExpectedCounts[CP_D] = termExpectedCounts[CP_D] + 1;
-            }
-        }
-
-        private static FacetsConfig Config
-        {
-            get
-            {
-                FacetsConfig config = new FacetsConfig();
-                config.SetMultiValued("A", true);
-                config.SetMultiValued("B", true);
-                config.SetRequireDimCount("B", true);
-                config.SetHierarchical("D", true);
-                return config;
-            }
-        }
-
-        private static void IndexDocsNoFacets(IndexWriter indexWriter)
-        {
-            int numDocs = AtLeast(2);
-            for (int i = 0; i < numDocs; i++)
-            {
-                Document doc = new Document();
-                AddField(doc);
-                indexWriter.AddDocument(doc);
-            }
-            indexWriter.Commit(); // flush a segment
-        }
-
-        private static void IndexDocsWithFacetsNoTerms(IndexWriter indexWriter, TaxonomyWriter taxoWriter, IDictionary<string, int?> expectedCounts)
-        {
-            Random random = Random();
-            int numDocs = AtLeast(random, 2);
-            FacetsConfig config = Config;
-            for (int i = 0; i < numDocs; i++)
-            {
-                Document doc = new Document();
-                AddFacets(doc, config, false);
-                indexWriter.AddDocument(config.Build(taxoWriter, doc));
-            }
-            indexWriter.Commit(); // flush a segment
-        }
-
-        private static void IndexDocsWithFacetsAndTerms(IndexWriter indexWriter, TaxonomyWriter taxoWriter, IDictionary<string, int?> expectedCounts)
-        {
-            Random random = Random();
-            int numDocs = AtLeast(random, 2);
-            FacetsConfig config = Config;
-            for (int i = 0; i < numDocs; i++)
-            {
-                Document doc = new Document();
-                AddFacets(doc, config, true);
-                AddField(doc);
-                indexWriter.AddDocument(config.Build(taxoWriter, doc));
-            }
-            indexWriter.Commit(); // flush a segment
-        }
-
-        private static void IndexDocsWithFacetsAndSomeTerms(IndexWriter indexWriter, TaxonomyWriter taxoWriter, IDictionary<string, int?> expectedCounts)
-        {
-            Random random = Random();
-            int numDocs = AtLeast(random, 2);
-            FacetsConfig config = Config;
-            for (int i = 0; i < numDocs; i++)
-            {
-                Document doc = new Document();
-                bool hasContent = random.NextBoolean();
-                if (hasContent)
-                {
-                    AddField(doc);
-                }
-                AddFacets(doc, config, hasContent);
-                indexWriter.AddDocument(config.Build(taxoWriter, doc));
-            }
-            indexWriter.Commit(); // flush a segment
-        }
-
-        // initialize expectedCounts w/ 0 for all categories
-        private static IDictionary<string, int?> newCounts()
-        {
-            IDictionary<string, int?> counts = new Dictionary<string, int?>();
-            counts[CP_A] = 0;
-            counts[CP_B] = 0;
-            counts[CP_C] = 0;
-            counts[CP_D] = 0;
-            foreach (FacetField ff in CATEGORIES_A)
-            {
-                counts[ff.dim + "/" + ff.path[0]] = 0;
-            }
-            foreach (FacetField ff in CATEGORIES_B)
-            {
-                counts[ff.dim + "/" + ff.path[0]] = 0;
-            }
-            foreach (FacetField ff in CATEGORIES_C)
-            {
-                counts[ff.dim + "/" + ff.path[0]] = 0;
-            }
-            foreach (FacetField ff in CATEGORIES_D)
-            {
-                counts[ff.dim + "/" + ff.path[0]] = 0;
-            }
-            return counts;
-        }
-
-        [TestFixtureSetUp]
-        public static void BeforeClassCountingFacetsAggregatorTest()
-        {
-            indexDir = NewDirectory();
-            taxoDir = NewDirectory();
-
-            // create an index which has:
-            // 1. Segment with no categories, but matching results
-            // 2. Segment w/ categories, but no results
-            // 3. Segment w/ categories and results
-            // 4. Segment w/ categories, but only some results
-
-            IndexWriterConfig conf = NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
-            //conf.MergePolicy = NoMergePolicy.INSTANCE; // prevent merges, so we can control the index segments
-            IndexWriter indexWriter = new IndexWriter(indexDir, conf);
-            TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-
-            allExpectedCounts = newCounts();
-            termExpectedCounts = newCounts();
-
-            // segment w/ no categories
-            IndexDocsNoFacets(indexWriter);
-
-            // segment w/ categories, no content
-            IndexDocsWithFacetsNoTerms(indexWriter, taxoWriter, allExpectedCounts);
-
-            // segment w/ categories and content
-            IndexDocsWithFacetsAndTerms(indexWriter, taxoWriter, allExpectedCounts);
-
-            // segment w/ categories and some content
-            IndexDocsWithFacetsAndSomeTerms(indexWriter, taxoWriter, allExpectedCounts);
-
-            IOUtils.Close(indexWriter, taxoWriter);
-        }
-
-        [Test]
-        public virtual void TestDifferentNumResults()
-        {
-            // test the collector w/ FacetRequests and different numResults
-            DirectoryReader indexReader = DirectoryReader.Open(indexDir);
-            var taxoReader = new DirectoryTaxonomyReader(taxoDir);
-            IndexSearcher searcher = NewSearcher(indexReader);
-
-            FacetsCollector sfc = new FacetsCollector();
-            TermQuery q = new TermQuery(A);
-            searcher.Search(q, sfc);
-            Facets facets = GetTaxonomyFacetCounts(taxoReader, Config, sfc);
-            FacetResult result = facets.GetTopChildren(NUM_CHILDREN_CP_A, CP_A);
-            Assert.AreEqual(-1, (int)result.Value);
-            foreach (LabelAndValue labelValue in result.LabelValues)
-            {
-                Assert.AreEqual(termExpectedCounts[CP_A + "/" + labelValue.label], labelValue.value);
-            }
-            result = facets.GetTopChildren(NUM_CHILDREN_CP_B, CP_B);
-            Assert.AreEqual(termExpectedCounts[CP_B], result.Value);
-            foreach (LabelAndValue labelValue in result.LabelValues)
-            {
-                Assert.AreEqual(termExpectedCounts[CP_B + "/" + labelValue.label], labelValue.value);
-            }
-
-            IOUtils.Close(indexReader, taxoReader);
-        }
-
-        [Test]
-        public virtual void TestAllCounts()
-        {
-            DirectoryReader indexReader = DirectoryReader.Open(indexDir);
-            var taxoReader = new DirectoryTaxonomyReader(taxoDir);
-            IndexSearcher searcher = NewSearcher(indexReader);
-
-            FacetsCollector sfc = new FacetsCollector();
-            searcher.Search(new MatchAllDocsQuery(), sfc);
-
-            Facets facets = GetTaxonomyFacetCounts(taxoReader, Config, sfc);
-
-            FacetResult result = facets.GetTopChildren(NUM_CHILDREN_CP_A, CP_A);
-            Assert.AreEqual(-1, (int)result.Value);
-            int prevValue = int.MaxValue;
-            foreach (LabelAndValue labelValue in result.LabelValues)
-            {
-                Assert.AreEqual(allExpectedCounts[CP_A + "/" + labelValue.label], labelValue.value);
-                Assert.True((int)labelValue.value <= prevValue, "wrong sort order of sub results: labelValue.value=" + labelValue.value + " prevValue=" + prevValue);
-                prevValue = (int)labelValue.value;
-            }
-
-            result = facets.GetTopChildren(NUM_CHILDREN_CP_B, CP_B);
-            Assert.AreEqual(allExpectedCounts[CP_B], result.Value);
-            prevValue = int.MaxValue;
-            foreach (LabelAndValue labelValue in result.LabelValues)
-            {
-                Assert.AreEqual(allExpectedCounts[CP_B + "/" + labelValue.label], labelValue.value);
-                Assert.True((int)labelValue.value <= prevValue, "wrong sort order of sub results: labelValue.value=" + labelValue.value + " prevValue=" + prevValue);
-                prevValue = (int)labelValue.value;
-            }
-
-            IOUtils.Close(indexReader, taxoReader);
-        }
-
-        [Test]
-        public virtual void TestBigNumResults()
-        {
-            DirectoryReader indexReader = DirectoryReader.Open(indexDir);
-            var taxoReader = new DirectoryTaxonomyReader(taxoDir);
-            IndexSearcher searcher = NewSearcher(indexReader);
-
-            FacetsCollector sfc = new FacetsCollector();
-            searcher.Search(new MatchAllDocsQuery(), sfc);
-
-            Facets facets = GetTaxonomyFacetCounts(taxoReader, Config, sfc);
-
-            FacetResult result = facets.GetTopChildren(int.MaxValue, CP_A);
-            Assert.AreEqual(-1, (int)result.Value);
-            foreach (LabelAndValue labelValue in result.LabelValues)
-            {
-                Assert.AreEqual(allExpectedCounts[CP_A + "/" + labelValue.label], labelValue.value);
-            }
-            result = facets.GetTopChildren(int.MaxValue, CP_B);
-            Assert.AreEqual(allExpectedCounts[CP_B], result.Value);
-            foreach (LabelAndValue labelValue in result.LabelValues)
-            {
-                Assert.AreEqual(allExpectedCounts[CP_B + "/" + labelValue.label], labelValue.value);
-            }
-
-            IOUtils.Close(indexReader, taxoReader);
-        }
-
-        [Test]
-        public virtual void TestNoParents()
-        {
-            DirectoryReader indexReader = DirectoryReader.Open(indexDir);
-            var taxoReader = new DirectoryTaxonomyReader(taxoDir);
-            IndexSearcher searcher = NewSearcher(indexReader);
-
-            var sfc = new FacetsCollector();
-            searcher.Search(new MatchAllDocsQuery(), sfc);
-
-            Facets facets = GetTaxonomyFacetCounts(taxoReader, Config, sfc);
-
-            FacetResult result = facets.GetTopChildren(NUM_CHILDREN_CP_C, CP_C);
-            Assert.AreEqual(allExpectedCounts[CP_C], result.Value);
-            foreach (LabelAndValue labelValue in result.LabelValues)
-            {
-                Assert.AreEqual(allExpectedCounts[CP_C + "/" + labelValue.label], labelValue.value);
-            }
-            result = facets.GetTopChildren(NUM_CHILDREN_CP_D, CP_D);
-            Assert.AreEqual(allExpectedCounts[CP_C], result.Value);
-            foreach (LabelAndValue labelValue in result.LabelValues)
-            {
-                Assert.AreEqual(allExpectedCounts[CP_D + "/" + labelValue.label], labelValue.value);
-            }
-
-            IOUtils.Close(indexReader, taxoReader);
-        }
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyFacetSumValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyFacetSumValueSource.cs b/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyFacetSumValueSource.cs
deleted file mode 100644
index d425a1a..0000000
--- a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyFacetSumValueSource.cs
+++ /dev/null
@@ -1,610 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using Lucene.Net.Randomized.Generators;
-
-namespace Lucene.Net.Facet.Taxonomy
-{
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-
-    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
-    using Document = Lucene.Net.Documents.Document;
-    using Field = Lucene.Net.Documents.Field;
-    using FloatDocValuesField = Lucene.Net.Documents.FloatDocValuesField;
-    using IntField = Lucene.Net.Documents.IntField;
-    using NumericDocValuesField = Lucene.Net.Documents.NumericDocValuesField;
-    using StringField = Lucene.Net.Documents.StringField;
-    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
-    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
-    using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
-    using DirectoryReader = Lucene.Net.Index.DirectoryReader;
-    using IndexWriter = Lucene.Net.Index.IndexWriter;
-    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
-    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
-    using Term = Lucene.Net.Index.Term;
-    using FunctionQuery = Lucene.Net.Queries.Function.FunctionQuery;
-    using FunctionValues = Lucene.Net.Queries.Function.FunctionValues;
-    using ValueSource = Lucene.Net.Queries.Function.ValueSource;
-    using DoubleDocValues = Lucene.Net.Queries.Function.DocValues.DoubleDocValues;
-    using FloatFieldSource = Lucene.Net.Queries.Function.ValueSources.FloatFieldSource;
-    using IntFieldSource = Lucene.Net.Queries.Function.ValueSources.IntFieldSource;
-    using LongFieldSource = Lucene.Net.Queries.Function.ValueSources.LongFieldSource;
-    using ConstantScoreQuery = Lucene.Net.Search.ConstantScoreQuery;
-    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
-    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
-    using Query = Lucene.Net.Search.Query;
-    using Scorer = Lucene.Net.Search.Scorer;
-    using TermQuery = Lucene.Net.Search.TermQuery;
-    using TopDocs = Lucene.Net.Search.TopDocs;
-    using Directory = Lucene.Net.Store.Directory;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-    using TestUtil = Lucene.Net.Util.TestUtil;
-    using NUnit.Framework;
-    [TestFixture]
-    public class TestTaxonomyFacetSumValueSource : FacetTestCase
-    {
-
-        [Test]
-        public virtual void TestBasic()
-        {
-
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            // Writes facet ords to a separate directory from the
-            // main index:
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-            FacetsConfig config = new FacetsConfig();
-
-            // Reused across documents, to add the necessary facet
-            // fields:
-            Document doc = new Document();
-            doc.Add(new IntField("num", 10, Field.Store.NO));
-            doc.Add(new FacetField("Author", "Bob"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new IntField("num", 20, Field.Store.NO));
-            doc.Add(new FacetField("Author", "Lisa"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new IntField("num", 30, Field.Store.NO));
-            doc.Add(new FacetField("Author", "Lisa"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new IntField("num", 40, Field.Store.NO));
-            doc.Add(new FacetField("Author", "Susan"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new IntField("num", 45, Field.Store.NO));
-            doc.Add(new FacetField("Author", "Frank"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-            writer.Dispose();
-
-            // NRT open
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-            taxoWriter.Dispose();
-
-            // Aggregate the facet counts:
-            FacetsCollector c = new FacetsCollector();
-
-            // MatchAllDocsQuery is for "browsing" (counts facets
-            // for all non-deleted docs in the index); normally
-            // you'd use a "normal" query and one of the
-            // Facets.search utility methods:
-            searcher.Search(new MatchAllDocsQuery(), c);
-
-            TaxonomyFacetSumValueSource facets = new TaxonomyFacetSumValueSource(taxoReader, new FacetsConfig(), c, new IntFieldSource("num"));
-
-            // Retrieve & verify results:
-            Assert.AreEqual("dim=Author path=[] value=145.0 childCount=4\n  Lisa (50.0)\n  Frank (45.0)\n  Susan (40.0)\n  Bob (10.0)\n", facets.GetTopChildren(10, "Author").ToString());
-
-            taxoReader.Dispose();
-            searcher.IndexReader.Dispose();
-            dir.Dispose();
-            taxoDir.Dispose();
-        }
-
-        // LUCENE-5333
-        [Test]
-        public virtual void TestSparseFacets()
-        {
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            // Writes facet ords to a separate directory from the
-            // main index:
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-            FacetsConfig config = new FacetsConfig();
-
-            Document doc = new Document();
-            doc.Add(new IntField("num", 10, Field.Store.NO));
-            doc.Add(new FacetField("a", "foo1"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            if (Random().NextBoolean())
-            {
-                writer.Commit();
-            }
-
-            doc = new Document();
-            doc.Add(new IntField("num", 20, Field.Store.NO));
-            doc.Add(new FacetField("a", "foo2"));
-            doc.Add(new FacetField("b", "bar1"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            if (Random().NextBoolean())
-            {
-                writer.Commit();
-            }
-
-            doc = new Document();
-            doc.Add(new IntField("num", 30, Field.Store.NO));
-            doc.Add(new FacetField("a", "foo3"));
-            doc.Add(new FacetField("b", "bar2"));
-            doc.Add(new FacetField("c", "baz1"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-            writer.Dispose();
-
-            // NRT open
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-            taxoWriter.Dispose();
-
-            FacetsCollector c = new FacetsCollector();
-            searcher.Search(new MatchAllDocsQuery(), c);
-
-            TaxonomyFacetSumValueSource facets = new TaxonomyFacetSumValueSource(taxoReader, new FacetsConfig(), c, new IntFieldSource("num"));
-
-            // Ask for top 10 labels for any dims that have counts:
-            IList<FacetResult> results = facets.GetAllDims(10);
-
-            Assert.AreEqual(3, results.Count);
-            Assert.AreEqual("dim=a path=[] value=60.0 childCount=3\n  foo3 (30.0)\n  foo2 (20.0)\n  foo1 (10.0)\n", results[0].ToString());
-            Assert.AreEqual("dim=b path=[] value=50.0 childCount=2\n  bar2 (30.0)\n  bar1 (20.0)\n", results[1].ToString());
-            Assert.AreEqual("dim=c path=[] value=30.0 childCount=1\n  baz1 (30.0)\n", results[2].ToString());
-
-            IOUtils.Close(searcher.IndexReader, taxoReader, dir, taxoDir);
-        }
-
-        [Test]
-        public virtual void TestWrongIndexFieldName()
-        {
-
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            // Writes facet ords to a separate directory from the
-            // main index:
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-
-            FacetsConfig config = new FacetsConfig();
-            config.SetIndexFieldName("a", "$facets2");
-
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            Document doc = new Document();
-            doc.Add(new IntField("num", 10, Field.Store.NO));
-            doc.Add(new FacetField("a", "foo1"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-            writer.Dispose();
-
-            // NRT open
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-            taxoWriter.Dispose();
-
-            FacetsCollector c = new FacetsCollector();
-            searcher.Search(new MatchAllDocsQuery(), c);
-
-            TaxonomyFacetSumValueSource facets = new TaxonomyFacetSumValueSource(taxoReader, config, c, new IntFieldSource("num"));
-
-            // Ask for top 10 labels for any dims that have counts:
-            IList<FacetResult> results = facets.GetAllDims(10);
-            Assert.True(results.Count == 0);
-
-            try
-            {
-                facets.GetSpecificValue("a");
-                Fail("should have hit exc");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-
-            try
-            {
-                facets.GetTopChildren(10, "a");
-                Fail("should have hit exc");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-
-            IOUtils.Close(searcher.IndexReader, taxoReader, dir, taxoDir);
-        }
-
-        [Test]
-        public virtual void TestSumScoreAggregator()
-        {
-            Store.Directory indexDir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
-
-            FacetsConfig config = new FacetsConfig();
-
-            for (int i = AtLeast(30); i > 0; --i)
-            {
-                Document doc = new Document();
-                if (Random().NextBoolean()) // don't match all documents
-                {
-                    doc.Add(new StringField("f", "v", Field.Store.NO));
-                }
-                doc.Add(new FacetField("dim", "a"));
-                iw.AddDocument(config.Build(taxoWriter, doc));
-            }
-
-            DirectoryReader r = DirectoryReader.Open(iw, true);
-            DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            FacetsCollector fc = new FacetsCollector(true);
-            ConstantScoreQuery csq = new ConstantScoreQuery(new MatchAllDocsQuery());
-            csq.Boost = 2.0f;
-
-            TopDocs td = FacetsCollector.Search(NewSearcher(r), csq, 10, fc);
-
-            Facets facets = new TaxonomyFacetSumValueSource(taxoReader, config, fc, new TaxonomyFacetSumValueSource.ScoreValueSource());
-
-            int expected = (int)(td.MaxScore * td.TotalHits);
-            Assert.AreEqual(expected, (int)facets.GetSpecificValue("dim", "a"));
-
-            IOUtils.Close(iw, taxoWriter, taxoReader, taxoDir, r, indexDir);
-        }
-
-        [Test]
-        public virtual void TestNoScore()
-        {
-            Store.Directory indexDir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
-            FacetsConfig config = new FacetsConfig();
-            for (int i = 0; i < 4; i++)
-            {
-                Document doc = new Document();
-                doc.Add(new NumericDocValuesField("price", (i + 1)));
-                doc.Add(new FacetField("a", Convert.ToString(i % 2)));
-                iw.AddDocument(config.Build(taxoWriter, doc));
-            }
-
-            DirectoryReader r = DirectoryReader.Open(iw, true);
-            DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            FacetsCollector sfc = new FacetsCollector();
-            NewSearcher(r).Search(new MatchAllDocsQuery(), sfc);
-            Facets facets = new TaxonomyFacetSumValueSource(taxoReader, config, sfc, new LongFieldSource("price"));
-            Assert.AreEqual("dim=a path=[] value=10.0 childCount=2\n  1 (6.0)\n  0 (4.0)\n", facets.GetTopChildren(10, "a").ToString());
-
-            IOUtils.Close(taxoWriter, iw, taxoReader, taxoDir, r, indexDir);
-        }
-
-        [Test]
-        public virtual void TestWithScore()
-        {
-            Store.Directory indexDir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
-
-            FacetsConfig config = new FacetsConfig();
-            for (int i = 0; i < 4; i++)
-            {
-                Document doc = new Document();
-                doc.Add(new NumericDocValuesField("price", (i + 1)));
-                doc.Add(new FacetField("a", Convert.ToString(i % 2)));
-                iw.AddDocument(config.Build(taxoWriter, doc));
-            }
-
-            DirectoryReader r = DirectoryReader.Open(iw, true);
-            DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            ValueSource valueSource = new ValueSourceAnonymousInnerClassHelper(this);
-
-            FacetsCollector fc = new FacetsCollector(true);
-            // score documents by their 'price' field - makes asserting the correct counts for the categories easier
-            Query q = new FunctionQuery(new LongFieldSource("price"));
-            FacetsCollector.Search(NewSearcher(r), q, 10, fc);
-            Facets facets = new TaxonomyFacetSumValueSource(taxoReader, config, fc, valueSource);
-
-            Assert.AreEqual("dim=a path=[] value=10.0 childCount=2\n  1 (6.0)\n  0 (4.0)\n", facets.GetTopChildren(10, "a").ToString());
-
-            IOUtils.Close(taxoWriter, iw, taxoReader, taxoDir, r, indexDir);
-        }
-
-        private class ValueSourceAnonymousInnerClassHelper : ValueSource
-        {
-            private readonly TestTaxonomyFacetSumValueSource outerInstance;
-
-            public ValueSourceAnonymousInnerClassHelper(TestTaxonomyFacetSumValueSource outerInstance)
-            {
-                this.outerInstance = outerInstance;
-            }
-
-            public override FunctionValues GetValues(IDictionary context, AtomicReaderContext readerContext)
-            {
-                Scorer scorer = (Scorer)context["scorer"];
-                Debug.Assert(scorer != null);
-                return new DoubleDocValuesAnonymousInnerClassHelper(this, scorer);
-            }
-
-            private class DoubleDocValuesAnonymousInnerClassHelper : DoubleDocValues
-            {
-                private readonly ValueSourceAnonymousInnerClassHelper outerInstance;
-
-                private Scorer scorer;
-
-                public DoubleDocValuesAnonymousInnerClassHelper(ValueSourceAnonymousInnerClassHelper outerInstance, Scorer scorer)
-                    : base(null) //todo: value source
-                {
-                    this.outerInstance = outerInstance;
-                    this.scorer = scorer;
-                }
-
-
-
-                public override double DoubleVal(int document)
-                {
-                    try
-                    {
-                        return scorer.Score();
-                    }
-                    catch (IOException exception)
-                    {
-                        throw new Exception(exception.Message, exception);
-                    }
-                }
-            }
-
-            public override bool Equals(object o)
-            {
-                return o == this;
-            }
-            public override int GetHashCode()
-            {
-                throw new NotImplementedException();
-            }
-
-            public override string Description
-            {
-                get
-                {
-                    return "score()";
-                }
-
-            }
-        }
-
-        [Test]
-        public virtual void TestRollupValues()
-        {
-            Store.Directory indexDir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
-            FacetsConfig config = new FacetsConfig();
-            config.SetHierarchical("a", true);
-            //config.setRequireDimCount("a", true);
-
-            for (int i = 0; i < 4; i++)
-            {
-                Document doc = new Document();
-                doc.Add(new NumericDocValuesField("price", (i + 1)));
-                doc.Add(new FacetField("a", Convert.ToString(i % 2), "1"));
-                iw.AddDocument(config.Build(taxoWriter, doc));
-            }
-
-            DirectoryReader r = DirectoryReader.Open(iw, true);
-            DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            ValueSource valueSource = new LongFieldSource("price");
-            FacetsCollector sfc = new FacetsCollector();
-            NewSearcher(r).Search(new MatchAllDocsQuery(), sfc);
-            Facets facets = new TaxonomyFacetSumValueSource(taxoReader, config, sfc, valueSource);
-
-            Assert.AreEqual("dim=a path=[] value=10.0 childCount=2\n  1 (6.0)\n  0 (4.0)\n", facets.GetTopChildren(10, "a").ToString());
-
-            IOUtils.Close(taxoWriter, iw, taxoReader, taxoDir, r, indexDir);
-        }
-
-        [Test]
-        public virtual void TestCountAndSumScore()
-        {
-            Store.Directory indexDir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
-            FacetsConfig config = new FacetsConfig();
-            config.SetIndexFieldName("b", "$b");
-
-            for (int i = AtLeast(30); i > 0; --i)
-            {
-                Document doc = new Document();
-                doc.Add(new StringField("f", "v", Field.Store.NO));
-                doc.Add(new FacetField("a", "1"));
-                doc.Add(new FacetField("b", "1"));
-                iw.AddDocument(config.Build(taxoWriter, doc));
-            }
-
-            DirectoryReader r = DirectoryReader.Open(iw, true);
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            FacetsCollector fc = new FacetsCollector(true);
-            FacetsCollector.Search(NewSearcher(r), new MatchAllDocsQuery(), 10, fc);
-
-            Facets facets1 = GetTaxonomyFacetCounts(taxoReader, config, fc);
-            Facets facets2 = new TaxonomyFacetSumValueSource(new DocValuesOrdinalsReader("$b"), taxoReader, config, fc, new TaxonomyFacetSumValueSource.ScoreValueSource());
-
-            Assert.AreEqual(r.MaxDoc, (int)facets1.GetTopChildren(10, "a").Value);
-            Assert.AreEqual(r.MaxDoc, (double)facets2.GetTopChildren(10, "b").Value, 1E-10);
-            IOUtils.Close(taxoWriter, iw, taxoReader, taxoDir, r, indexDir);
-        }
-
-        [Test]
-        public virtual void TestRandom()
-        {
-            string[] tokens = GetRandomTokens(10);
-            Store.Directory indexDir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            RandomIndexWriter w = new RandomIndexWriter(Random(), indexDir);
-            var tw = new DirectoryTaxonomyWriter(taxoDir);
-            FacetsConfig config = new FacetsConfig();
-            int numDocs = AtLeast(1000);
-            int numDims = TestUtil.NextInt(Random(), 1, 7);
-            IList<TestDoc> testDocs = GetRandomDocs(tokens, numDocs, numDims);
-            foreach (TestDoc testDoc in testDocs)
-            {
-                Document doc = new Document();
-                doc.Add(NewStringField("content", testDoc.content, Field.Store.NO));
-                testDoc.value = Random().NextFloat();
-                doc.Add(new FloatDocValuesField("value", testDoc.value));
-                for (int j = 0; j < numDims; j++)
-                {
-                    if (testDoc.dims[j] != null)
-                    {
-                        doc.Add(new FacetField("dim" + j, testDoc.dims[j]));
-                    }
-                }
-                w.AddDocument(config.Build(tw, doc));
-            }
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(w.Reader);
-
-            // NRT open
-            var tr = new DirectoryTaxonomyReader(tw);
-
-            ValueSource values = new FloatFieldSource("value");
-
-            int iters = AtLeast(100);
-            for (int iter = 0; iter < iters; iter++)
-            {
-                string searchToken = tokens[Random().Next(tokens.Length)];
-                if (VERBOSE)
-                {
-                    Console.WriteLine("\nTEST: iter content=" + searchToken);
-                }
-                FacetsCollector fc = new FacetsCollector();
-                FacetsCollector.Search(searcher, new TermQuery(new Term("content", searchToken)), 10, fc);
-                Facets facets = new TaxonomyFacetSumValueSource(tr, config, fc, values);
-
-                // Slow, yet hopefully bug-free, faceting:
-                var expectedValues = new List<Dictionary<string, float?>>();
-                for (int i = 0; i < numDims; i++)
-                {
-                    expectedValues[i] = new Dictionary<string, float?>();
-                }
-
-                foreach (TestDoc doc in testDocs)
-                {
-                    if (doc.content.Equals(searchToken))
-                    {
-                        for (int j = 0; j < numDims; j++)
-                        {
-                            if (doc.dims[j] != null)
-                            {
-                                float? v = expectedValues[j][doc.dims[j]];
-                                if (v == null)
-                                {
-                                    expectedValues[j][doc.dims[j]] = doc.value;
-                                }
-                                else
-                                {
-                                    expectedValues[j][doc.dims[j]] = (float)v + doc.value;
-                                }
-                            }
-                        }
-                    }
-                }
-
-                IList<FacetResult> expected = new List<FacetResult>();
-                for (int i = 0; i < numDims; i++)
-                {
-                    IList<LabelAndValue> labelValues = new List<LabelAndValue>();
-                    float totValue = 0;
-                    foreach (KeyValuePair<string, float?> ent in expectedValues[i])
-                    {
-                        labelValues.Add(new LabelAndValue(ent.Key, ent.Value.Value));
-                        totValue += ent.Value.Value;
-                    }
-                    SortLabelValues(labelValues);
-                    if (totValue > 0)
-                    {
-                        expected.Add(new FacetResult("dim" + i, new string[0], totValue, labelValues.ToArray(), labelValues.Count));
-                    }
-                }
-
-                // Sort by highest value, tie break by value:
-                SortFacetResults(expected);
-
-                IList<FacetResult> actual = facets.GetAllDims(10);
-
-                // Messy: fixup ties
-                SortTies(actual);
-
-                if (VERBOSE)
-                {
-                    Console.WriteLine("expected=\n" + expected.ToString());
-                    Console.WriteLine("actual=\n" + actual.ToString());
-                }
-
-                AssertFloatValuesEquals(expected, actual);
-            }
-
-            IOUtils.Close(w, tw, searcher.IndexReader, tr, indexDir, taxoDir);
-        }
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/Taxonomy/WriterCache/TestCharBlockArray.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/Taxonomy/WriterCache/TestCharBlockArray.cs b/src/Lucene.Net.Tests/core/Facet/Taxonomy/WriterCache/TestCharBlockArray.cs
deleted file mode 100644
index f4be988..0000000
--- a/src/Lucene.Net.Tests/core/Facet/Taxonomy/WriterCache/TestCharBlockArray.cs
+++ /dev/null
@@ -1,110 +0,0 @@
-using System.Text;
-using Lucene.Net.Support;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet.Taxonomy.WriterCache
-{
-
-
-    using TestUtil = Lucene.Net.Util.TestUtil;
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-    [TestFixture]
-    public class TestCharBlockArray : FacetTestCase
-    {
-
-        /* not finished yet because of missing charset decoder */
-
-        /*
-        public virtual void testArray()
-        {
-            CharBlockArray array = new CharBlockArray();
-            StringBuilder builder = new StringBuilder();
-
-            const int n = 100 * 1000;
-
-            byte[] buffer = new byte[50];
-
-            for (int i = 0; i < n; i++)
-            {
-                Random().NextBytes(buffer);
-                int size = 1 + Random().Next(50);
-                // This test is turning random bytes into a string,
-                // this is asking for trouble.
-
-                CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder().onUnmappableCharacter(CodingErrorAction.REPLACE).onMalformedInput(CodingErrorAction.REPLACE);
-                string s = decoder.Decode(ByteBuffer.Wrap(buffer, 0, size)).ToString();
-                array.append(s);
-                builder.Append(s);
-            }
-
-            for (int i = 0; i < n; i++)
-            {
-                Random().NextBytes(buffer);
-                int size = 1 + Random().Next(50);
-                // This test is turning random bytes into a string,
-                // this is asking for trouble.
-                CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder().onUnmappableCharacter(CodingErrorAction.REPLACE).onMalformedInput(CodingErrorAction.REPLACE);
-                string s = decoder.decode(ByteBuffer.Wrap(buffer, 0, size)).ToString();
-                array.append((CharSequence)s);
-                builder.Append(s);
-            }
-
-            for (int i = 0; i < n; i++)
-            {
-                Random().NextBytes(buffer);
-                int size = 1 + Random().Next(50);
-                // This test is turning random bytes into a string,
-                // this is asking for trouble.
-                CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder().onUnmappableCharacter(CodingErrorAction.REPLACE).onMalformedInput(CodingErrorAction.REPLACE);
-                string s = decoder.decode(ByteBuffer.Wrap(buffer, 0, size)).ToString();
-                for (int j = 0; j < s.Length; j++)
-                {
-                    array.append(s[j]);
-                }
-                builder.Append(s);
-            }
-
-            AssertEqualsInternal("GrowingCharArray<->StringBuilder mismatch.", builder, array);
-
-            File tempDir = CreateTempDir("growingchararray");
-            File f = new File(tempDir, "GrowingCharArrayTest.tmp");
-            BufferedOutputStream @out = new BufferedOutputStream(new FileOutputStream(f));
-            array.flush(@out);
-            @out.flush();
-            @out.Close();
-
-            BufferedInputStream @in = new BufferedInputStream(new FileInputStream(f));
-            array = CharBlockArray.open(@in);
-            AssertEqualsInternal("GrowingCharArray<->StringBuilder mismatch after flush/load.", builder, array);
-            @in.Close();
-            f.delete();
-        }
-
-        private static void AssertEqualsInternal(string msg, StringBuilder expected, CharBlockArray actual)
-        {
-            Assert.AreEqual(expected.Length, actual.Length, msg);
-            for (int i = 0; i < expected.Length; i++)
-            {
-                Assert.AreEqual(expected[i], actual.CharAt(i), msg);
-            }
-        }
-        */
-    }
-
-}
\ No newline at end of file


[05/14] lucenenet git commit: Moving Lucene.Net.Facet tests to their appropriate place

Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/Taxonomy/Directory/TestConcurrentFacetedIndexing.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/Taxonomy/Directory/TestConcurrentFacetedIndexing.cs b/src/Lucene.Net.Tests/core/Facet/Taxonomy/Directory/TestConcurrentFacetedIndexing.cs
deleted file mode 100644
index 5ee17a6..0000000
--- a/src/Lucene.Net.Tests/core/Facet/Taxonomy/Directory/TestConcurrentFacetedIndexing.cs
+++ /dev/null
@@ -1,228 +0,0 @@
-using System;
-using System.Collections.Concurrent;
-using System.IO;
-using System.Threading;
-using Lucene.Net.Support;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet.Taxonomy.Directory
-{
-
-
-    using Document = Lucene.Net.Documents.Document;
-    using TaxonomyWriterCache = Lucene.Net.Facet.Taxonomy.WriterCache.TaxonomyWriterCache;
-    using Cl2oTaxonomyWriterCache = Lucene.Net.Facet.Taxonomy.WriterCache.Cl2oTaxonomyWriterCache;
-    using LruTaxonomyWriterCache = Lucene.Net.Facet.Taxonomy.WriterCache.LruTaxonomyWriterCache;
-    using IndexWriter = Lucene.Net.Index.IndexWriter;
-    using OpenMode = Lucene.Net.Index.IndexWriterConfig.OpenMode_e;
-    using Directory = Lucene.Net.Store.Directory;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-    [TestFixture]
-    public class TestConcurrentFacetedIndexing : FacetTestCase
-    {
-
-        // A No-Op TaxonomyWriterCache which always discards all given categories, and
-        // always returns true in put(), to indicate some cache entries were cleared.
-        private static TaxonomyWriterCache NO_OP_CACHE = new TaxonomyWriterCacheAnonymousInnerClassHelper();
-
-        private class TaxonomyWriterCacheAnonymousInnerClassHelper : TaxonomyWriterCache
-        {
-            public TaxonomyWriterCacheAnonymousInnerClassHelper()
-            {
-            }
-
-
-            public virtual void Close()
-            {
-            }
-            public virtual int Get(FacetLabel categoryPath)
-            {
-                return -1;
-            }
-            public virtual bool Put(FacetLabel categoryPath, int ordinal)
-            {
-                return true;
-            }
-            public virtual bool Full
-            {
-                get
-                {
-                    return true;
-                }
-            }
-            public virtual void Clear()
-            {
-            }
-
-        }
-
-        internal static FacetField NewCategory()
-        {
-            Random r = Random();
-            string l1 = "l1." + r.Next(10); // l1.0-l1.9 (10 categories)
-            string l2 = "l2." + r.Next(30); // l2.0-l2.29 (30 categories)
-            string l3 = "l3." + r.Next(100); // l3.0-l3.99 (100 categories)
-            return new FacetField(l1, l2, l3);
-        }
-
-        internal static TaxonomyWriterCache NewTaxoWriterCache(int ndocs)
-        {
-            double d = Random().NextDouble();
-            if (d < 0.7)
-            {
-                // this is the fastest, yet most memory consuming
-                return new Cl2oTaxonomyWriterCache(1024, 0.15f, 3);
-            }
-            else if (TEST_NIGHTLY && d > 0.98)
-            {
-                // this is the slowest, but tests the writer concurrency when no caching is done.
-                // only pick it during NIGHTLY tests, and even then, with very low chances.
-                return NO_OP_CACHE;
-            }
-            else
-            {
-                // this is slower than CL2O, but less memory consuming, and exercises finding categories on disk too.
-                return new LruTaxonomyWriterCache(ndocs / 10);
-            }
-        }
-
-        [Test]
-        public virtual void TestConcurrency()
-        {
-            AtomicInteger numDocs = new AtomicInteger(AtLeast(10000));
-            Directory indexDir = NewDirectory();
-            Directory taxoDir = NewDirectory();
-            ConcurrentDictionary<string, string> values = new ConcurrentDictionary<string, string>();
-            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, null));
-            var tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE, NewTaxoWriterCache(numDocs.Get()));
-            ThreadClass[] indexThreads = new ThreadClass[AtLeast(4)];
-            FacetsConfig config = new FacetsConfig();
-            for (int i = 0; i < 10; i++)
-            {
-                config.SetHierarchical("l1." + i, true);
-                config.SetMultiValued("l1." + i, true);
-            }
-
-            for (int i = 0; i < indexThreads.Length; i++)
-            {
-                indexThreads[i] = new ThreadAnonymousInnerClassHelper(this, numDocs, values, iw, tw, config);
-            }
-
-            foreach (ThreadClass t in indexThreads)
-            {
-                t.Start();
-            }
-            foreach (ThreadClass t in indexThreads)
-            {
-                t.Join();
-            }
-
-            var tr = new DirectoryTaxonomyReader(tw);
-            // +1 for root category
-            if (values.Count + 1 != tr.Size)
-            {
-                foreach (string value in values.Keys)
-                {
-                    FacetLabel label = new FacetLabel(FacetsConfig.StringToPath(value));
-                    if (tr.GetOrdinal(label) == -1)
-                    {
-                        Console.WriteLine("FAIL: path=" + label + " not recognized");
-                    }
-                }
-                Fail("mismatch number of categories");
-            }
-            int[] parents = tr.ParallelTaxonomyArrays.Parents();
-            foreach (string cat in values.Keys)
-            {
-                FacetLabel cp = new FacetLabel(FacetsConfig.StringToPath(cat));
-                Assert.True(tr.GetOrdinal(cp) > 0, "category not found " + cp);
-                int level = cp.Length;
-                int parentOrd = 0; // for root, parent is always virtual ROOT (ord=0)
-                FacetLabel path = null;
-                for (int i = 0; i < level; i++)
-                {
-                    path = cp.Subpath(i + 1);
-                    int ord = tr.GetOrdinal(path);
-                    Assert.AreEqual(parentOrd, parents[ord], "invalid parent for cp=" + path);
-                    parentOrd = ord; // next level should have this parent
-                }
-            }
-
-            IOUtils.Close(tw, iw, tr, taxoDir, indexDir);
-        }
-
-        private class ThreadAnonymousInnerClassHelper : ThreadClass
-        {
-            private readonly TestConcurrentFacetedIndexing outerInstance;
-
-            private AtomicInteger numDocs;
-            private ConcurrentDictionary<string, string> values;
-            private IndexWriter iw;
-            private Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter tw;
-            private FacetsConfig config;
-
-            public ThreadAnonymousInnerClassHelper(TestConcurrentFacetedIndexing outerInstance, AtomicInteger numDocs, ConcurrentDictionary<string, string> values, IndexWriter iw, Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter tw, FacetsConfig config)
-            {
-                this.outerInstance = outerInstance;
-                this.numDocs = numDocs;
-                this.values = values;
-                this.iw = iw;
-                this.tw = tw;
-                this.config = config;
-            }
-
-
-            public override void Run()
-            {
-                Random random = Random();
-                while (numDocs.DecrementAndGet() > 0)
-                {
-                    try
-                    {
-                        Document doc = new Document();
-                        int numCats = random.Next(3) + 1; // 1-3
-                        while (numCats-- > 0)
-                        {
-                            FacetField ff = NewCategory();
-                            doc.Add(ff);
-
-                            FacetLabel label = new FacetLabel(ff.dim, ff.path);
-                            // add all prefixes to values
-                            int level = label.Length;
-                            while (level > 0)
-                            {
-                                string s = FacetsConfig.PathToString(label.Components, level);
-                                values[s] = s;
-                                --level;
-                            }
-                        }
-                        iw.AddDocument(config.Build(tw, doc));
-                    }
-                    catch (IOException e)
-                    {
-                        throw new Exception(e.Message, e);
-                    }
-                }
-            }
-        }
-
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/Taxonomy/Directory/TestDirectoryTaxonomyReader.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/Taxonomy/Directory/TestDirectoryTaxonomyReader.cs b/src/Lucene.Net.Tests/core/Facet/Taxonomy/Directory/TestDirectoryTaxonomyReader.cs
deleted file mode 100644
index 15f30df..0000000
--- a/src/Lucene.Net.Tests/core/Facet/Taxonomy/Directory/TestDirectoryTaxonomyReader.cs
+++ /dev/null
@@ -1,624 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Lucene.Net.Randomized.Generators;
-using Lucene.Net.Support;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet.Taxonomy.Directory
-{
-
-
-    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
-    using ChildrenIterator = Lucene.Net.Facet.Taxonomy.TaxonomyReader.ChildrenIterator;
-    using IndexWriter = Lucene.Net.Index.IndexWriter;
-    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
-    using OpenMode = Lucene.Net.Index.IndexWriterConfig.OpenMode_e;
-    using LogByteSizeMergePolicy = Lucene.Net.Index.LogByteSizeMergePolicy;
-    using LogMergePolicy = Lucene.Net.Index.LogMergePolicy;
-    using AlreadyClosedException = Lucene.Net.Store.AlreadyClosedException;
-    using Directory = Lucene.Net.Store.Directory;
-    using RAMDirectory = Lucene.Net.Store.RAMDirectory;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-    public class TestDirectoryTaxonomyReader : FacetTestCase
-    {
-
-        [Test]
-        public virtual void TestCloseAfterIncRef()
-        {
-            Directory dir = NewDirectory();
-            var ltw = new DirectoryTaxonomyWriter(dir);
-            ltw.AddCategory(new FacetLabel("a"));
-            ltw.Dispose();
-
-            DirectoryTaxonomyReader ltr = new DirectoryTaxonomyReader(dir);
-            ltr.IncRef();
-            ltr.Dispose();
-
-            // should not fail as we IncRef() before close
-            var tmpSie = ltr.Size;
-            ltr.DecRef();
-
-            dir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestCloseTwice()
-        {
-            Directory dir = NewDirectory();
-            var ltw = new DirectoryTaxonomyWriter(dir);
-            ltw.AddCategory(new FacetLabel("a"));
-            ltw.Dispose();
-
-            var ltr = new DirectoryTaxonomyReader(dir);
-            (ltr).Dispose();
-            (ltr).Dispose(); // no exception should be thrown
-
-            dir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestOpenIfChangedResult()
-        {
-            Directory dir = null;
-            DirectoryTaxonomyWriter ltw = null;
-            DirectoryTaxonomyReader ltr = null;
-
-            try
-            {
-                dir = NewDirectory();
-                ltw = new DirectoryTaxonomyWriter(dir);
-
-                ltw.AddCategory(new FacetLabel("a"));
-                ltw.Commit();
-
-                ltr = new DirectoryTaxonomyReader(dir);
-                Assert.Null(TaxonomyReader.OpenIfChanged(ltr), "Nothing has changed");
-
-                ltw.AddCategory(new FacetLabel("b"));
-                ltw.Commit();
-
-                DirectoryTaxonomyReader newtr = TaxonomyReader.OpenIfChanged(ltr);
-                Assert.NotNull(newtr, "changes were committed");
-                Assert.Null(TaxonomyReader.OpenIfChanged(newtr), "Nothing has changed");
-                (newtr).Dispose();
-            }
-            finally
-            {
-                IOUtils.Close(ltw, ltr, dir);
-            }
-        }
-
-        [Test]
-        public virtual void TestAlreadyClosed()
-        {
-            Directory dir = NewDirectory();
-            var ltw = new DirectoryTaxonomyWriter(dir);
-            ltw.AddCategory(new FacetLabel("a"));
-            ltw.Dispose();
-
-            var ltr = new DirectoryTaxonomyReader(dir);
-            ltr.Dispose();
-            try
-            {
-                var tmpSize = ltr.Size;
-                Fail("An AlreadyClosedException should have been thrown here");
-            }
-            catch (AlreadyClosedException)
-            {
-                // good!
-            }
-            dir.Dispose();
-        }
-
-        /// <summary>
-        /// recreating a taxonomy should work well with a freshly opened taxonomy reader 
-        /// </summary>
-        [Test]
-        public virtual void TestFreshReadRecreatedTaxonomy()
-        {
-            doTestReadRecreatedTaxonomy(Random(), true);
-        }
-
-        [Test]
-        public virtual void TestOpenIfChangedReadRecreatedTaxonomy()
-        {
-            doTestReadRecreatedTaxonomy(Random(), false);
-        }
-        
-        private void doTestReadRecreatedTaxonomy(Random random, bool closeReader)
-        {
-            Directory dir = null;
-            TaxonomyWriter tw = null;
-            TaxonomyReader tr = null;
-
-            // prepare a few categories
-            int n = 10;
-            FacetLabel[] cp = new FacetLabel[n];
-            for (int i = 0; i < n; i++)
-            {
-                cp[i] = new FacetLabel("a", Convert.ToString(i));
-            }
-
-            try
-            {
-                dir = NewDirectory();
-
-                tw = new DirectoryTaxonomyWriter(dir);
-                tw.AddCategory(new FacetLabel("a"));
-                tw.Dispose();
-
-                tr = new DirectoryTaxonomyReader(dir);
-                int baseNumCategories = tr.Size;
-
-                for (int i = 0; i < n; i++)
-                {
-                    int k = random.Next(n);
-                    tw = new DirectoryTaxonomyWriter(dir, IndexWriterConfig.OpenMode_e.CREATE);
-                    for (int j = 0; j <= k; j++)
-                    {
-                        tw.AddCategory(cp[j]);
-                    }
-                    tw.Dispose();
-                    if (closeReader)
-                    {
-                        tr.Dispose(true);
-                        tr = new DirectoryTaxonomyReader(dir);
-                    }
-                    else
-                    {
-                        var newtr = TaxonomyReader.OpenIfChanged(tr);
-                        Assert.NotNull(newtr);
-                        tr.Dispose(true);
-                        tr = newtr;
-                    }
-                    Assert.AreEqual(baseNumCategories + 1 + k, tr.Size, "Wrong #categories in taxonomy (i=" + i + ", k=" + k + ")");
-                }
-            }
-            finally
-            {
-                IOUtils.Close(tr as DirectoryTaxonomyReader, tw, dir);
-            }
-        }
-
-        [Test]
-        public virtual void TestOpenIfChangedAndRefCount()
-        {
-            Directory dir = new RAMDirectory(); // no need for random directories here
-
-            var taxoWriter = new DirectoryTaxonomyWriter(dir);
-            taxoWriter.AddCategory(new FacetLabel("a"));
-            taxoWriter.Commit();
-
-            var taxoReader = new DirectoryTaxonomyReader(dir);
-            Assert.AreEqual(1, taxoReader.RefCount, "wrong refCount");
-
-            taxoReader.IncRef();
-            Assert.AreEqual(2, taxoReader.RefCount, "wrong refCount");
-
-            taxoWriter.AddCategory(new FacetLabel("a", "b"));
-            taxoWriter.Commit();
-            var newtr = TaxonomyReader.OpenIfChanged(taxoReader);
-            Assert.NotNull(newtr);
-            taxoReader.Dispose();
-            taxoReader = newtr;
-            Assert.AreEqual(1, taxoReader.RefCount, "wrong refCount");
-
-            taxoWriter.Dispose();
-            taxoReader.Dispose();
-            dir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestOpenIfChangedManySegments()
-        {
-            // test openIfChanged() when the taxonomy contains many segments
-            Directory dir = NewDirectory();
-
-            DirectoryTaxonomyWriter writer = new DirectoryTaxonomyWriterAnonymousInnerClassHelper(this, dir);
-            var reader = new DirectoryTaxonomyReader(writer);
-
-            int numRounds = Random().Next(10) + 10;
-            int numCategories = 1; // one for root
-            for (int i = 0; i < numRounds; i++)
-            {
-                int numCats = Random().Next(4) + 1;
-                for (int j = 0; j < numCats; j++)
-                {
-                    writer.AddCategory(new FacetLabel(Convert.ToString(i), Convert.ToString(j)));
-                }
-                numCategories += numCats + 1; // one for round-parent
-                var newtr = TaxonomyReader.OpenIfChanged(reader);
-                Assert.NotNull(newtr);
-                reader.Dispose();
-                reader = newtr;
-
-                // assert categories
-                Assert.AreEqual(numCategories, reader.Size);
-                int roundOrdinal = reader.GetOrdinal(new FacetLabel(Convert.ToString(i)));
-                int[] parents = reader.ParallelTaxonomyArrays.Parents();
-                Assert.AreEqual(0, parents[roundOrdinal]); // round's parent is root
-                for (int j = 0; j < numCats; j++)
-                {
-                    int ord = reader.GetOrdinal(new FacetLabel(Convert.ToString(i), Convert.ToString(j)));
-                    Assert.AreEqual(roundOrdinal, parents[ord]); // round's parent is root
-                }
-            }
-
-            reader.Dispose();
-            writer.Dispose();
-            dir.Dispose();
-        }
-
-        private class DirectoryTaxonomyWriterAnonymousInnerClassHelper : DirectoryTaxonomyWriter
-        {
-            private readonly TestDirectoryTaxonomyReader outerInstance;
-
-            public DirectoryTaxonomyWriterAnonymousInnerClassHelper(TestDirectoryTaxonomyReader outerInstance, Directory dir)
-                : base(dir)
-            {
-                this.outerInstance = outerInstance;
-            }
-
-            protected override IndexWriterConfig CreateIndexWriterConfig(IndexWriterConfig.OpenMode_e openMode)
-            {
-                IndexWriterConfig conf = base.CreateIndexWriterConfig(openMode);
-                LogMergePolicy lmp = (LogMergePolicy)conf.MergePolicy;
-                lmp.MergeFactor = 2;
-                return conf;
-            }
-        }
-
-        [Test]
-        public virtual void TestOpenIfChangedMergedSegment()
-        {
-            // test openIfChanged() when all index segments were merged - used to be
-            // a bug in ParentArray, caught by testOpenIfChangedManySegments - only
-            // this test is not random
-            Directory dir = NewDirectory();
-
-            // hold onto IW to forceMerge
-            // note how we don't close it, since DTW will close it.
-            IndexWriter iw = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetMergePolicy(new LogByteSizeMergePolicy()));
-            var writer = new DirectoryTaxonomyWriterAnonymousInnerClassHelper2(this, dir, iw) as DirectoryTaxonomyWriter;
-
-            var reader = new DirectoryTaxonomyReader(writer);
-            Assert.AreEqual(1, reader.Size);
-            Assert.AreEqual(1, reader.ParallelTaxonomyArrays.Parents().Length);
-
-            // add category and call forceMerge -- this should flush IW and merge segments down to 1
-            // in ParentArray.initFromReader, this used to fail assuming there are no parents.
-            writer.AddCategory(new FacetLabel("1"));
-            iw.ForceMerge(1);
-
-            // now calling openIfChanged should trip on the bug
-            var newtr = TaxonomyReader.OpenIfChanged(reader);
-            Assert.NotNull(newtr);
-            reader.Dispose();
-            reader = newtr;
-            Assert.AreEqual(2, reader.Size);
-            Assert.AreEqual(2, reader.ParallelTaxonomyArrays.Parents().Length);
-
-            reader.Dispose();
-            writer.Dispose();
-            dir.Dispose();
-        }
-
-        private class DirectoryTaxonomyWriterAnonymousInnerClassHelper2 : DirectoryTaxonomyWriter
-        {
-            private readonly TestDirectoryTaxonomyReader outerInstance;
-
-            private IndexWriter iw;
-            private IndexWriterConfig config;
-
-            public DirectoryTaxonomyWriterAnonymousInnerClassHelper2(TestDirectoryTaxonomyReader outerInstance, Directory dir, IndexWriter iw) : base(dir)
-            {
-                this.outerInstance = outerInstance;
-                this.iw = iw;
-            }
-
-            protected override IndexWriter OpenIndexWriter(Directory directory, IndexWriterConfig config) 
-            {   
-                return iw;
-            }
-        }
-
-        [Test]
-        public virtual void TestOpenIfChangedNoChangesButSegmentMerges()
-        {
-            // test openIfChanged() when the taxonomy hasn't really changed, but segments
-            // were merged. The NRT reader will be reopened, and ParentArray used to assert
-            // that the new reader contains more ordinals than were given from the old
-            // TaxReader version
-            Directory dir = NewDirectory();
-
-            // hold onto IW to forceMerge
-            // note how we don't close it, since DTW will close it.
-            var iw = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetMergePolicy(new LogByteSizeMergePolicy()));
-            DirectoryTaxonomyWriter writer = new DirectoryTaxonomyWriterAnonymousInnerClassHelper3(this, dir, iw);
-
-
-            // add a category so that the following DTR open will cause a flush and 
-            // a new segment will be created
-            writer.AddCategory(new FacetLabel("a"));
-
-            var reader = new DirectoryTaxonomyReader(writer);
-            Assert.AreEqual(2, reader.Size);
-            Assert.AreEqual(2, reader.ParallelTaxonomyArrays.Parents().Length);
-
-            // merge all the segments so that NRT reader thinks there's a change 
-            iw.ForceMerge(1);
-
-            // now calling openIfChanged should trip on the wrong assert in ParetArray's ctor
-            var newtr = TaxonomyReader.OpenIfChanged(reader);
-            Assert.NotNull(newtr);
-            reader.Dispose();
-            reader = newtr;
-            Assert.AreEqual(2, reader.Size);
-            Assert.AreEqual(2, reader.ParallelTaxonomyArrays.Parents().Length);
-
-            reader.Dispose();
-            writer.Dispose();
-            dir.Dispose();
-        }
-
-        private class DirectoryTaxonomyWriterAnonymousInnerClassHelper3 : DirectoryTaxonomyWriter
-        {
-            private readonly TestDirectoryTaxonomyReader outerInstance;
-
-            private IndexWriter iw;
-
-            public DirectoryTaxonomyWriterAnonymousInnerClassHelper3(TestDirectoryTaxonomyReader outerInstance, Directory dir, IndexWriter iw)
-                : base(dir)
-            {
-                this.outerInstance = outerInstance;
-                this.iw = iw;
-            }
-
-            protected override IndexWriter OpenIndexWriter(Directory directory, IndexWriterConfig config)
-            {
-                return iw;
-            }
-        }
-
-        [Test]
-        public virtual void TestOpenIfChangedReuseAfterRecreate()
-        {
-            // tests that if the taxonomy is recreated, no data is reused from the previous taxonomy
-            Directory dir = NewDirectory();
-            DirectoryTaxonomyWriter writer = new DirectoryTaxonomyWriter(dir);
-            FacetLabel cp_a = new FacetLabel("a");
-            writer.AddCategory(cp_a);
-            writer.Dispose();
-
-            DirectoryTaxonomyReader r1 = new DirectoryTaxonomyReader(dir);
-            // fill r1's caches
-            Assert.AreEqual(1, r1.GetOrdinal(cp_a));
-            Assert.AreEqual(cp_a, r1.GetPath(1));
-
-            // now recreate, add a different category
-            writer = new DirectoryTaxonomyWriter(dir, IndexWriterConfig.OpenMode_e.CREATE);
-            FacetLabel cp_b = new FacetLabel("b");
-            writer.AddCategory(cp_b);
-            writer.Dispose();
-
-            DirectoryTaxonomyReader r2 = TaxonomyReader.OpenIfChanged(r1);
-            Assert.NotNull(r2);
-
-            // fill r2's caches
-            Assert.AreEqual(1, r2.GetOrdinal(cp_b));
-            Assert.AreEqual(cp_b, r2.GetPath(1));
-
-            // check that r1 doesn't see cp_b
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r1.GetOrdinal(cp_b));
-            Assert.AreEqual(cp_a, r1.GetPath(1));
-
-            // check that r2 doesn't see cp_a
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r2.GetOrdinal(cp_a));
-            Assert.AreEqual(cp_b, r2.GetPath(1));
-
-            (r2).Dispose();
-            (r1).Dispose();
-            dir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestOpenIfChangedReuse()
-        {
-            // test the reuse of data from the old DTR instance
-            foreach (bool nrt in new bool[] { false, true })
-            {
-                Directory dir = NewDirectory();
-                DirectoryTaxonomyWriter writer = new DirectoryTaxonomyWriter(dir);
-
-                FacetLabel cp_a = new FacetLabel("a");
-                writer.AddCategory(cp_a);
-                if (!nrt)
-                {
-                    writer.Commit();
-                }
-
-                DirectoryTaxonomyReader r1 = nrt ? new DirectoryTaxonomyReader(writer) : new DirectoryTaxonomyReader(dir);
-                // fill r1's caches
-                Assert.AreEqual(1, r1.GetOrdinal(cp_a));
-                Assert.AreEqual(cp_a, r1.GetPath(1));
-
-                FacetLabel cp_b = new FacetLabel("b");
-                writer.AddCategory(cp_b);
-                if (!nrt)
-                {
-                    writer.Commit();
-                }
-
-                DirectoryTaxonomyReader r2 = TaxonomyReader.OpenIfChanged(r1);
-                Assert.NotNull(r2);
-
-                // add r2's categories to the caches
-                Assert.AreEqual(2, r2.GetOrdinal(cp_b));
-                Assert.AreEqual(cp_b, r2.GetPath(2));
-
-                // check that r1 doesn't see cp_b
-                Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r1.GetOrdinal(cp_b));
-                Assert.Null(r1.GetPath(2));
-
-                (r1).Dispose();
-                (r2).Dispose();
-                writer.Dispose();
-                dir.Dispose();
-            }
-        }
-
-        [Test]
-        public virtual void TestOpenIfChangedReplaceTaxonomy()
-        {
-            // test openIfChanged when replaceTaxonomy is called, which is equivalent to recreate
-            // only can work with NRT as well
-            Directory src = NewDirectory();
-            DirectoryTaxonomyWriter w = new DirectoryTaxonomyWriter(src);
-            FacetLabel cp_b = new FacetLabel("b");
-            w.AddCategory(cp_b);
-            w.Dispose();
-
-            foreach (bool nrt in new bool[] { false, true })
-            {
-                Directory dir = NewDirectory();
-                var writer = new DirectoryTaxonomyWriter(dir);
-
-                FacetLabel cp_a = new FacetLabel("a");
-                writer.AddCategory(cp_a);
-                if (!nrt)
-                {
-                    writer.Commit();
-                }
-
-                DirectoryTaxonomyReader r1 = nrt ? new DirectoryTaxonomyReader(writer) : new DirectoryTaxonomyReader(dir);
-                // fill r1's caches
-                Assert.AreEqual(1, r1.GetOrdinal(cp_a));
-                Assert.AreEqual(cp_a, r1.GetPath(1));
-
-                // now replace taxonomy
-                writer.ReplaceTaxonomy(src);
-                if (!nrt)
-                {
-                    writer.Commit();
-                }
-
-                DirectoryTaxonomyReader r2 = TaxonomyReader.OpenIfChanged(r1);
-                Assert.NotNull(r2);
-
-                // fill r2's caches
-                Assert.AreEqual(1, r2.GetOrdinal(cp_b));
-                Assert.AreEqual(cp_b, r2.GetPath(1));
-
-                // check that r1 doesn't see cp_b
-                Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r1.GetOrdinal(cp_b));
-                Assert.AreEqual(cp_a, r1.GetPath(1));
-
-                // check that r2 doesn't see cp_a
-                Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r2.GetOrdinal(cp_a));
-                Assert.AreEqual(cp_b, r2.GetPath(1));
-
-                (r2).Dispose();
-                (r1).Dispose();
-                writer.Dispose();
-                dir.Dispose();
-            }
-
-            src.Dispose();
-        }
-
-        [Test]
-        public virtual void TestGetChildren()
-        {
-            Directory dir = NewDirectory();
-            var taxoWriter = new DirectoryTaxonomyWriter(dir);
-            int numCategories = AtLeast(10);
-            int numA = 0, numB = 0;
-            Random random = Random();
-            // add the two categories for which we'll also add children (so asserts are simpler)
-            taxoWriter.AddCategory(new FacetLabel("a"));
-            taxoWriter.AddCategory(new FacetLabel("b"));
-            for (int i = 0; i < numCategories; i++)
-            {
-                if (random.NextBoolean())
-                {
-                    taxoWriter.AddCategory(new FacetLabel("a", Convert.ToString(i)));
-                    ++numA;
-                }
-                else
-                {
-                    taxoWriter.AddCategory(new FacetLabel("b", Convert.ToString(i)));
-                    ++numB;
-                }
-            }
-            // add category with no children
-            taxoWriter.AddCategory(new FacetLabel("c"));
-            taxoWriter.Dispose();
-
-            var taxoReader = new DirectoryTaxonomyReader(dir);
-
-            // non existing category
-            TaxonomyReader.ChildrenIterator it = taxoReader.GetChildren(taxoReader.GetOrdinal(new FacetLabel("invalid")));
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, it.Next());
-
-            // a category with no children
-            it = taxoReader.GetChildren(taxoReader.GetOrdinal(new FacetLabel("c")));
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, it.Next());
-
-            // arbitrary negative ordinal
-            it = taxoReader.GetChildren(-2);
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, it.Next());
-
-            // root's children
-            var roots = new HashSet<string>(Arrays.AsList("a", "b", "c"));
-            it = taxoReader.GetChildren(TaxonomyReader.ROOT_ORDINAL);
-            while (roots.Count > 0)
-            {
-                FacetLabel root = taxoReader.GetPath(it.Next());
-                Assert.AreEqual(1, root.Length);
-                Assert.True(roots.Remove(root.Components[0]));
-            }
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, it.Next());
-
-            for (int i = 0; i < 2; i++)
-            {
-                FacetLabel cp = i == 0 ? new FacetLabel("a") : new FacetLabel("b");
-                int ordinal = taxoReader.GetOrdinal(cp);
-                it = taxoReader.GetChildren(ordinal);
-                int numChildren = 0;
-                int child;
-                while ((child = it.Next()) != TaxonomyReader.INVALID_ORDINAL)
-                {
-                    FacetLabel path = taxoReader.GetPath(child);
-                    Assert.AreEqual(2, path.Length);
-                    Assert.AreEqual(path.Components[0], i == 0 ? "a" : "b");
-                    ++numChildren;
-                }
-                int expected = i == 0 ? numA : numB;
-                Assert.AreEqual(expected, numChildren, "invalid num children");
-            }
-            taxoReader.Dispose();
-
-            dir.Dispose();
-        }
-
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/Taxonomy/Directory/TestDirectoryTaxonomyWriter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/Taxonomy/Directory/TestDirectoryTaxonomyWriter.cs b/src/Lucene.Net.Tests/core/Facet/Taxonomy/Directory/TestDirectoryTaxonomyWriter.cs
deleted file mode 100644
index f5ddd11..0000000
--- a/src/Lucene.Net.Tests/core/Facet/Taxonomy/Directory/TestDirectoryTaxonomyWriter.cs
+++ /dev/null
@@ -1,588 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.Concurrent;
-using System.IO;
-using System.Threading;
-using Lucene.Net.Support;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet.Taxonomy.Directory
-{
-
-
-    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
-    using Document = Lucene.Net.Documents.Document;
-    using MemoryOrdinalMap = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter.MemoryOrdinalMap;
-    using TaxonomyWriterCache = Lucene.Net.Facet.Taxonomy.WriterCache.TaxonomyWriterCache;
-    using Cl2oTaxonomyWriterCache = Lucene.Net.Facet.Taxonomy.WriterCache.Cl2oTaxonomyWriterCache;
-    using LruTaxonomyWriterCache = Lucene.Net.Facet.Taxonomy.WriterCache.LruTaxonomyWriterCache;
-    using DirectoryReader = Lucene.Net.Index.DirectoryReader;
-    using IndexReader = Lucene.Net.Index.IndexReader;
-    using IndexWriter = Lucene.Net.Index.IndexWriter;
-    using OpenMode = Lucene.Net.Index.IndexWriterConfig.OpenMode_e;
-    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
-    using SegmentInfos = Lucene.Net.Index.SegmentInfos;
-    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
-    using AlreadyClosedException = Lucene.Net.Store.AlreadyClosedException;
-    using Directory = Lucene.Net.Store.Directory;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-    using TestUtil = Lucene.Net.Util.TestUtil;
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-    public class TestDirectoryTaxonomyWriter : FacetTestCase
-    {
-
-        // A No-Op TaxonomyWriterCache which always discards all given categories, and
-        // always returns true in put(), to indicate some cache entries were cleared.
-        private static TaxonomyWriterCache NO_OP_CACHE = new TaxonomyWriterCacheAnonymousInnerClassHelper();
-
-        private class TaxonomyWriterCacheAnonymousInnerClassHelper : TaxonomyWriterCache
-        {
-            public TaxonomyWriterCacheAnonymousInnerClassHelper()
-            {
-            }
-
-
-            public virtual void Close()
-            {
-            }
-            public virtual int Get(FacetLabel categoryPath)
-            {
-                return -1;
-            }
-            public virtual bool Put(FacetLabel categoryPath, int ordinal)
-            {
-                return true;
-            }
-            public virtual bool Full
-            {
-                get
-                {
-                    return true;
-                }
-            }
-            public virtual void Clear()
-            {
-            }
-
-        }
-
-        [Test]
-        public virtual void TestCommit()
-        {
-            // Verifies that nothing is committed to the underlying Directory, if
-            // commit() wasn't called.
-            Directory dir = NewDirectory();
-            var ltw = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
-            Assert.False(DirectoryReader.IndexExists(dir));
-            ltw.Commit(); // first commit, so that an index will be created
-            ltw.AddCategory(new FacetLabel("a"));
-
-            IndexReader r = DirectoryReader.Open(dir);
-            Assert.AreEqual(1, r.NumDocs, "No categories should have been committed to the underlying directory");
-            r.Dispose();
-            ltw.Dispose();
-            dir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestCommitUserData()
-        {
-            // Verifies taxonomy commit data
-            Directory dir = NewDirectory();
-            var taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
-            taxoWriter.AddCategory(new FacetLabel("a"));
-            taxoWriter.AddCategory(new FacetLabel("b"));
-            IDictionary<string, string> userCommitData = new Dictionary<string, string>();
-            userCommitData["testing"] = "1 2 3";
-            taxoWriter.CommitData = userCommitData;
-            taxoWriter.Dispose();
-            var r = DirectoryReader.Open(dir);
-            Assert.AreEqual(3, r.NumDocs, "2 categories plus root should have been committed to the underlying directory");
-            var readUserCommitData = r.IndexCommit.UserData;
-            Assert.True("1 2 3".Equals(readUserCommitData["testing"]), "wrong value extracted from commit data");
-            Assert.NotNull(DirectoryTaxonomyWriter.INDEX_EPOCH + " not found in commitData", readUserCommitData[DirectoryTaxonomyWriter.INDEX_EPOCH]);
-            r.Dispose();
-
-            // open DirTaxoWriter again and commit, INDEX_EPOCH should still exist
-            // in the commit data, otherwise DirTaxoReader.refresh() might not detect
-            // that the taxonomy index has been recreated.
-            taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
-            taxoWriter.AddCategory(new FacetLabel("c")); // add a category so that commit will happen
-
-
-            taxoWriter.CommitData = new Dictionary<string, string>()
-		    {
-			    {"just", "data"}
-		    };
-            taxoWriter.Commit();
-
-            // verify taxoWriter.getCommitData()
-            Assert.NotNull(DirectoryTaxonomyWriter.INDEX_EPOCH + " not found in taoxWriter.commitData", taxoWriter.CommitData[DirectoryTaxonomyWriter.INDEX_EPOCH]);
-            taxoWriter.Dispose();
-
-            r = DirectoryReader.Open(dir);
-            readUserCommitData = r.IndexCommit.UserData;
-            Assert.NotNull(DirectoryTaxonomyWriter.INDEX_EPOCH + " not found in commitData", readUserCommitData[DirectoryTaxonomyWriter.INDEX_EPOCH]);
-            r.Dispose();
-
-            dir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestRollback()
-        {
-            // Verifies that if rollback is called, DTW is closed.
-            Directory dir = NewDirectory();
-            var dtw = new DirectoryTaxonomyWriter(dir);
-            dtw.AddCategory(new FacetLabel("a"));
-            dtw.Rollback();
-            try
-            {
-                dtw.AddCategory(new FacetLabel("a"));
-                Fail("should not have succeeded to add a category following rollback.");
-            }
-            catch (AlreadyClosedException)
-            {
-                // expected
-            }
-
-            dir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestRecreateRollback()
-        {
-            // Tests rollback with OpenMode.CREATE
-            Directory dir = NewDirectory();
-            (new DirectoryTaxonomyWriter(dir)).Dispose();
-            Assert.AreEqual(1, getEpoch(dir));
-            (new DirectoryTaxonomyWriter(dir, OpenMode.CREATE)).Rollback();
-            Assert.AreEqual(1, getEpoch(dir));
-
-            dir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestEnsureOpen()
-        {
-            // verifies that an exception is thrown if DTW was closed
-            Directory dir = NewDirectory();
-            DirectoryTaxonomyWriter dtw = new DirectoryTaxonomyWriter(dir);
-            dtw.Dispose();
-            try
-            {
-                dtw.AddCategory(new FacetLabel("a"));
-                Fail("should not have succeeded to add a category following close.");
-            }
-            catch (AlreadyClosedException)
-            {
-                // expected
-            }
-            dir.Dispose();
-        }
-
-        [Test]
-        private void TouchTaxo(DirectoryTaxonomyWriter taxoWriter, FacetLabel cp)
-        {
-            taxoWriter.AddCategory(cp);
-            taxoWriter.CommitData = new Dictionary<string, string>()
-		{
-			{"just", "data"}
-		};
-            taxoWriter.Commit();
-        }
-
-        [Test]
-        public virtual void TestRecreateAndRefresh()
-        {
-            // DirTaxoWriter lost the INDEX_EPOCH property if it was opened in
-            // CREATE_OR_APPEND (or commit(userData) called twice), which could lead to
-            // DirTaxoReader succeeding to refresh().
-            Directory dir = NewDirectory();
-
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
-            TouchTaxo(taxoWriter, new FacetLabel("a"));
-
-            var taxoReader = new DirectoryTaxonomyReader(dir);
-
-            TouchTaxo(taxoWriter, new FacetLabel("b"));
-
-            var newtr = TaxonomyReader.OpenIfChanged(taxoReader);
-            taxoReader.Dispose();
-            taxoReader = newtr;
-            Assert.AreEqual(1, Convert.ToInt32(taxoReader.CommitUserData[DirectoryTaxonomyWriter.INDEX_EPOCH]));
-
-            // now recreate the taxonomy, and check that the epoch is preserved after opening DirTW again.
-            taxoWriter.Dispose();
-            taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE, NO_OP_CACHE);
-            TouchTaxo(taxoWriter, new FacetLabel("c"));
-            taxoWriter.Dispose();
-
-            taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
-            TouchTaxo(taxoWriter, new FacetLabel("d"));
-            taxoWriter.Dispose();
-
-            newtr = TaxonomyReader.OpenIfChanged(taxoReader);
-            taxoReader.Dispose();
-            taxoReader = newtr;
-            Assert.AreEqual(2, Convert.ToInt32(taxoReader.CommitUserData[DirectoryTaxonomyWriter.INDEX_EPOCH]));
-
-            taxoReader.Dispose();
-            dir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestBackwardsCompatibility()
-        {
-            // tests that if the taxonomy index doesn't have the INDEX_EPOCH
-            // property (supports pre-3.6 indexes), all still works.
-            Directory dir = NewDirectory();
-
-            // create an empty index first, so that DirTaxoWriter initializes indexEpoch to 1.
-            (new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, null))).Dispose();
-
-            var taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
-            taxoWriter.Dispose();
-
-            var taxoReader = new DirectoryTaxonomyReader(dir);
-            Assert.AreEqual(1, Convert.ToInt32(taxoReader.CommitUserData[DirectoryTaxonomyWriter.INDEX_EPOCH]));
-            Assert.Null(TaxonomyReader.OpenIfChanged(taxoReader));
-            (taxoReader).Dispose();
-
-            dir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestConcurrency()
-        {
-            int ncats = AtLeast(100000); // add many categories
-            int range = ncats * 3; // affects the categories selection
-            AtomicInteger numCats = new AtomicInteger(ncats);
-            Directory dir = NewDirectory();
-            var values = new ConcurrentDictionary<string, string>();
-            double d = Random().NextDouble();
-            TaxonomyWriterCache cache;
-            if (d < 0.7)
-            {
-                // this is the fastest, yet most memory consuming
-                cache = new Cl2oTaxonomyWriterCache(1024, 0.15f, 3);
-            }
-            else if (TEST_NIGHTLY && d > 0.98)
-            {
-                // this is the slowest, but tests the writer concurrency when no caching is done.
-                // only pick it during NIGHTLY tests, and even then, with very low chances.
-                cache = NO_OP_CACHE;
-            }
-            else
-            {
-                // this is slower than CL2O, but less memory consuming, and exercises finding categories on disk too.
-                cache = new LruTaxonomyWriterCache(ncats / 10);
-            }
-            if (VERBOSE)
-            {
-                Console.WriteLine("TEST: use cache=" + cache);
-            }
-            var tw = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE, cache);
-            ThreadClass[] addThreads = new ThreadClass[AtLeast(4)];
-            for (int z = 0; z < addThreads.Length; z++)
-            {
-                addThreads[z] = new ThreadAnonymousInnerClassHelper(this, range, numCats, values, tw);
-            }
-
-            foreach (var t in addThreads)
-            {
-                t.Start();
-            }
-            foreach (var t in addThreads)
-            {
-                t.Join();
-            }
-            tw.Dispose();
-
-            DirectoryTaxonomyReader dtr = new DirectoryTaxonomyReader(dir);
-            // +1 for root category
-            if (values.Count + 1 != dtr.Size)
-            {
-                foreach (string value in values.Keys)
-                {
-                    FacetLabel label = new FacetLabel(FacetsConfig.StringToPath(value));
-                    if (dtr.GetOrdinal(label) == -1)
-                    {
-                        Console.WriteLine("FAIL: path=" + label + " not recognized");
-                    }
-                }
-                Fail("mismatch number of categories");
-            }
-
-            int[] parents = dtr.ParallelTaxonomyArrays.Parents();
-            foreach (string cat in values.Keys)
-            {
-                FacetLabel cp = new FacetLabel(FacetsConfig.StringToPath(cat));
-                Assert.True(dtr.GetOrdinal(cp) > 0, "category not found " + cp);
-                int level = cp.Length;
-                int parentOrd = 0; // for root, parent is always virtual ROOT (ord=0)
-                FacetLabel path = new FacetLabel();
-                for (int i = 0; i < level; i++)
-                {
-                    path = cp.Subpath(i + 1);
-                    int ord = dtr.GetOrdinal(path);
-                    Assert.AreEqual(parentOrd, parents[ord], "invalid parent for cp=" + path);
-                    parentOrd = ord; // next level should have this parent
-                }
-            }
-
-            IOUtils.Close(dtr, dir);
-        }
-
-        private class ThreadAnonymousInnerClassHelper : ThreadClass
-        {
-            private readonly TestDirectoryTaxonomyWriter outerInstance;
-
-            private int range;
-            private AtomicInteger numCats;
-            private ConcurrentDictionary<string, string> values;
-            private Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter tw;
-
-            public ThreadAnonymousInnerClassHelper(TestDirectoryTaxonomyWriter outerInstance, int range, AtomicInteger numCats, ConcurrentDictionary<string, string> values, Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter tw)
-            {
-                this.outerInstance = outerInstance;
-                this.range = range;
-                this.numCats = numCats;
-                this.values = values;
-                this.tw = tw;
-            }
-
-            public override void Run()
-            {
-                Random random = Random();
-                while (numCats.DecrementAndGet() > 0)
-                {
-                    try
-                    {
-                        int value = random.Next(range);
-                        FacetLabel cp = new FacetLabel(Convert.ToString(value / 1000), Convert.ToString(value / 10000), Convert.ToString(value / 100000), Convert.ToString(value));
-                        int ord = tw.AddCategory(cp);
-                        Assert.True(tw.GetParent(ord) != -1, "invalid parent for ordinal " + ord + ", category " + cp);
-                        string l1 = FacetsConfig.PathToString(cp.Components, 1);
-                        string l2 = FacetsConfig.PathToString(cp.Components, 2);
-                        string l3 = FacetsConfig.PathToString(cp.Components, 3);
-                        string l4 = FacetsConfig.PathToString(cp.Components, 4);
-                        values[l1] = l1;
-                        values[l2] = l2;
-                        values[l3] = l3;
-                        values[l4] = l4;
-                    }
-                    catch (IOException e)
-                    {
-                        throw new Exception(e.Message, e);
-                    }
-                }
-            }
-        }
-
-        private long getEpoch(Directory taxoDir)
-        {
-            SegmentInfos infos = new SegmentInfos();
-            infos.Read(taxoDir);
-            return Convert.ToInt64(infos.UserData[DirectoryTaxonomyWriter.INDEX_EPOCH]);
-        }
-
-        [Test]
-        public virtual void TestReplaceTaxonomy()
-        {
-            Directory input = NewDirectory();
-            var taxoWriter = new DirectoryTaxonomyWriter(input);
-            int ordA = taxoWriter.AddCategory(new FacetLabel("a"));
-            taxoWriter.Dispose();
-
-            Directory dir = NewDirectory();
-            taxoWriter = new DirectoryTaxonomyWriter(dir);
-            int ordB = taxoWriter.AddCategory(new FacetLabel("b"));
-            taxoWriter.AddCategory(new FacetLabel("c"));
-            taxoWriter.Commit();
-
-            long origEpoch = getEpoch(dir);
-
-            // replace the taxonomy with the input one
-            taxoWriter.ReplaceTaxonomy(input);
-
-            // LUCENE-4633: make sure that category "a" is not added again in any case
-            taxoWriter.AddTaxonomy(input, new MemoryOrdinalMap());
-            Assert.AreEqual(2, taxoWriter.Size, "no categories should have been added"); // root + 'a'
-            Assert.AreEqual(ordA, taxoWriter.AddCategory(new FacetLabel("a")), "category 'a' received new ordinal?");
-
-            // add the same category again -- it should not receive the same ordinal !
-            int newOrdB = taxoWriter.AddCategory(new FacetLabel("b"));
-            Assert.AreNotSame(ordB, newOrdB, "new ordinal cannot be the original ordinal");
-            Assert.AreEqual(2, newOrdB, "ordinal should have been 2 since only one category was added by replaceTaxonomy");
-
-            taxoWriter.Dispose();
-
-            long newEpoch = getEpoch(dir);
-            Assert.True(origEpoch < newEpoch, "index epoch should have been updated after replaceTaxonomy");
-
-            dir.Dispose();
-            input.Dispose();
-        }
-
-        [Test]
-        public virtual void TestReaderFreshness()
-        {
-            // ensures that the internal index reader is always kept fresh. Previously,
-            // this simple scenario failed, if the cache just evicted the category that
-            // is being added.
-            Directory dir = NewDirectory();
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE, NO_OP_CACHE);
-            int o1 = taxoWriter.AddCategory(new FacetLabel("a"));
-            int o2 = taxoWriter.AddCategory(new FacetLabel("a"));
-            Assert.True(o1 == o2, "ordinal for same category that is added twice should be the same !");
-            taxoWriter.Dispose();
-            dir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestCommitNoEmptyCommits()
-        {
-            // LUCENE-4972: DTW used to create empty commits even if no changes were made
-            Directory dir = NewDirectory();
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(dir);
-            taxoWriter.AddCategory(new FacetLabel("a"));
-            taxoWriter.Commit();
-
-            long gen1 = SegmentInfos.GetLastCommitGeneration(dir);
-            taxoWriter.Commit();
-            long gen2 = SegmentInfos.GetLastCommitGeneration(dir);
-            Assert.AreEqual(gen1, gen2, "empty commit should not have changed the index");
-
-            taxoWriter.Dispose();
-            dir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestCloseNoEmptyCommits()
-        {
-            // LUCENE-4972: DTW used to create empty commits even if no changes were made
-            Directory dir = NewDirectory();
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(dir);
-            taxoWriter.AddCategory(new FacetLabel("a"));
-            taxoWriter.Commit();
-
-            long gen1 = SegmentInfos.GetLastCommitGeneration(dir);
-            taxoWriter.Dispose();
-            long gen2 = SegmentInfos.GetLastCommitGeneration(dir);
-            Assert.AreEqual(gen1, gen2, "empty commit should not have changed the index");
-
-            taxoWriter.Dispose();
-            dir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestPrepareCommitNoEmptyCommits()
-        {
-            // LUCENE-4972: DTW used to create empty commits even if no changes were made
-            Directory dir = NewDirectory();
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(dir);
-            taxoWriter.AddCategory(new FacetLabel("a"));
-            taxoWriter.PrepareCommit();
-            taxoWriter.Commit();
-
-            long gen1 = SegmentInfos.GetLastCommitGeneration(dir);
-            taxoWriter.PrepareCommit();
-            taxoWriter.Commit();
-            long gen2 = SegmentInfos.GetLastCommitGeneration(dir);
-            Assert.AreEqual(gen1, gen2, "empty commit should not have changed the index");
-
-            taxoWriter.Dispose();
-            dir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestHugeLabel()
-        {
-            Directory indexDir = NewDirectory(), taxoDir = NewDirectory();
-            IndexWriter indexWriter = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE, new Cl2oTaxonomyWriterCache(2, 1f, 1));
-            FacetsConfig config = new FacetsConfig();
-
-            // Add one huge label:
-            string bigs = null;
-            int ordinal = -1;
-
-            int len = FacetLabel.MAX_CATEGORY_PATH_LENGTH - 4; // for the dimension and separator
-            bigs = TestUtil.RandomSimpleString(Random(), len, len);
-            FacetField ff = new FacetField("dim", bigs);
-            FacetLabel cp = new FacetLabel("dim", bigs);
-            ordinal = taxoWriter.AddCategory(cp);
-            Document doc = new Document();
-            doc.Add(ff);
-            indexWriter.AddDocument(config.Build(taxoWriter, doc));
-
-            // Add tiny ones to cause a re-hash
-            for (int i = 0; i < 3; i++)
-            {
-                string s = TestUtil.RandomSimpleString(Random(), 1, 10);
-                taxoWriter.AddCategory(new FacetLabel("dim", s));
-                doc = new Document();
-                doc.Add(new FacetField("dim", s));
-                indexWriter.AddDocument(config.Build(taxoWriter, doc));
-            }
-
-            // when too large components were allowed to be added, this resulted in a new added category
-            Assert.AreEqual(ordinal, taxoWriter.AddCategory(cp));
-
-            IOUtils.Close(indexWriter, taxoWriter);
-
-            DirectoryReader indexReader = DirectoryReader.Open(indexDir);
-            var taxoReader = new DirectoryTaxonomyReader(taxoDir);
-            IndexSearcher searcher = new IndexSearcher(indexReader);
-            DrillDownQuery ddq = new DrillDownQuery(new FacetsConfig());
-            ddq.Add("dim", bigs);
-            Assert.AreEqual(1, searcher.Search(ddq, 10).TotalHits);
-
-            IOUtils.Close(indexReader, taxoReader, indexDir, taxoDir);
-        }
-
-        [Test]
-        public virtual void TestReplaceTaxoWithLargeTaxonomy()
-        {
-            var srcTaxoDir = NewDirectory();
-            var targetTaxoDir = NewDirectory();
-
-            // build source, large, taxonomy
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(srcTaxoDir);
-            int ord = taxoWriter.AddCategory(new FacetLabel("A", "1", "1", "1", "1", "1", "1"));
-            taxoWriter.Dispose();
-
-            taxoWriter = new DirectoryTaxonomyWriter(targetTaxoDir);
-            int ordinal = taxoWriter.AddCategory(new FacetLabel("B", "1"));
-            Assert.AreEqual(1, taxoWriter.GetParent(ordinal)); // call getParent to initialize taxoArrays
-            taxoWriter.Commit();
-
-            taxoWriter.ReplaceTaxonomy(srcTaxoDir);
-            Assert.AreEqual(ord - 1, taxoWriter.GetParent(ord));
-            taxoWriter.Dispose();
-
-            srcTaxoDir.Dispose();
-            targetTaxoDir.Dispose();
-        }
-
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestCachedOrdinalsReader.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestCachedOrdinalsReader.cs b/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestCachedOrdinalsReader.cs
deleted file mode 100644
index d528276..0000000
--- a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestCachedOrdinalsReader.cs
+++ /dev/null
@@ -1,116 +0,0 @@
-using System;
-using System.IO;
-using System.Threading;
-using Lucene.Net.Support;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet.Taxonomy
-{
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
-    using Document = Lucene.Net.Documents.Document;
-    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
-    using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
-    using DirectoryReader = Lucene.Net.Index.DirectoryReader;
-    using IndexWriter = Lucene.Net.Index.IndexWriter;
-    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
-    using Directory = Lucene.Net.Store.Directory;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-    [TestFixture]
-    public class TestCachedOrdinalsReader : FacetTestCase
-    {
-
-        [Test]
-        public virtual void TestWithThreads()
-        {
-            // LUCENE-5303: OrdinalsCache used the ThreadLocal BinaryDV instead of reader.getCoreCacheKey().
-            Store.Directory indexDir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-            IndexWriterConfig conf = NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
-            IndexWriter writer = new IndexWriter(indexDir, conf);
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            FacetsConfig config = new FacetsConfig();
-
-            Document doc = new Document();
-            doc.Add(new FacetField("A", "1"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-            doc = new Document();
-            doc.Add(new FacetField("A", "2"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            var reader = DirectoryReader.Open(writer, true);
-            CachedOrdinalsReader ordsReader = new CachedOrdinalsReader(new DocValuesOrdinalsReader(FacetsConfig.DEFAULT_INDEX_FIELD_NAME));
-            ThreadClass[] threads = new ThreadClass[3];
-            for (int i = 0; i < threads.Length; i++)
-            {
-                threads[i] = new ThreadAnonymousInnerClassHelper(this, "CachedOrdsThread-" + i, reader, ordsReader);
-            }
-
-            long ramBytesUsed = 0;
-            foreach (ThreadClass t in threads)
-            {
-                t.Start();
-                t.Join();
-                if (ramBytesUsed == 0)
-                {
-                    ramBytesUsed = ordsReader.RamBytesUsed();
-                }
-                else
-                {
-                    Assert.AreEqual(ramBytesUsed, ordsReader.RamBytesUsed());
-                }
-            }
-
-            IOUtils.Close(writer, taxoWriter, reader, indexDir, taxoDir);
-        }
-
-        private class ThreadAnonymousInnerClassHelper : ThreadClass
-        {
-            private readonly TestCachedOrdinalsReader outerInstance;
-
-            private DirectoryReader reader;
-            private Lucene.Net.Facet.Taxonomy.CachedOrdinalsReader ordsReader;
-
-            public ThreadAnonymousInnerClassHelper(TestCachedOrdinalsReader outerInstance, string CachedOrdsThread, DirectoryReader reader, Lucene.Net.Facet.Taxonomy.CachedOrdinalsReader ordsReader)
-                : base("CachedOrdsThread-")
-            {
-                this.outerInstance = outerInstance;
-                this.reader = reader;
-                this.ordsReader = ordsReader;
-            }
-
-            public override void Run()
-            {
-                foreach (var context in reader.Leaves)
-                {
-                    try
-                    {
-                        ordsReader.GetReader(context);
-                    }
-                    catch (IOException e)
-                    {
-                        throw new Exception(e.Message, e);
-                    }
-                }
-            }
-        }
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestFacetLabel.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestFacetLabel.cs b/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestFacetLabel.cs
deleted file mode 100644
index 0226137..0000000
--- a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestFacetLabel.cs
+++ /dev/null
@@ -1,360 +0,0 @@
-using System;
-using Lucene.Net.Support;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet.Taxonomy
-{
-
-    using SortedSetDocValuesFacetField = Lucene.Net.Facet.SortedSet.SortedSetDocValuesFacetField;
-    using BytesRef = Lucene.Net.Util.BytesRef;
-    using TestUtil = Lucene.Net.Util.TestUtil;
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-    [TestFixture]
-    public class TestFacetLabel : FacetTestCase
-    {
-
-        [Test]
-        public virtual void TestBasic()
-        {
-            Assert.AreEqual(0, (new FacetLabel()).Length);
-            Assert.AreEqual(1, (new FacetLabel("hello")).Length);
-            Assert.AreEqual(2, (new FacetLabel("hello", "world")).Length);
-        }
-
-        [Test]
-        public virtual void TestToString()
-        {
-            // When the category is empty, we expect an empty string
-            Assert.AreEqual("FacetLabel: []", (new FacetLabel()).ToString());
-            // one category
-            Assert.AreEqual("FacetLabel: [hello]", (new FacetLabel("hello")).ToString());
-            // more than one category
-            Assert.AreEqual("FacetLabel: [hello, world]", (new FacetLabel("hello", "world")).ToString());
-        }
-
-        [Test]
-        public virtual void TestGetComponent()
-        {
-            string[] components = new string[AtLeast(10)];
-            for (int i = 0; i < components.Length; i++)
-            {
-                components[i] = Convert.ToString(i);
-            }
-            FacetLabel cp = new FacetLabel(components);
-            for (int i = 0; i < components.Length; i++)
-            {
-                Assert.AreEqual(i, Convert.ToInt32(cp.Components[i]));
-            }
-        }
-
-        [Test]
-        public virtual 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.
-            FacetLabel p = new FacetLabel();
-            Assert.AreEqual(0, p.Length);
-            Assert.AreEqual("FacetLabel: []", p.ToString());
-        }
-
-        [Test]
-        public virtual void TestSubPath()
-        {
-            FacetLabel p = new FacetLabel("hi", "there", "man");
-            Assert.AreEqual(p.Length, 3);
-
-            FacetLabel p1 = p.Subpath(2);
-            Assert.AreEqual(2, p1.Length);
-            Assert.AreEqual("FacetLabel: [hi, there]", p1.ToString());
-
-            p1 = p.Subpath(1);
-            Assert.AreEqual(1, p1.Length);
-            Assert.AreEqual("FacetLabel: [hi]", p1.ToString());
-
-            p1 = p.Subpath(0);
-            Assert.AreEqual(0, p1.Length);
-            Assert.AreEqual("FacetLabel: []", p1.ToString());
-
-            // with all the following lengths, the prefix should be the whole path 
-            int[] lengths = new int[] { 3, -1, 4 };
-            for (int i = 0; i < lengths.Length; i++)
-            {
-                p1 = p.Subpath(lengths[i]);
-                Assert.AreEqual(3, p1.Length);
-                Assert.AreEqual("FacetLabel: [hi, there, man]", p1.ToString());
-                Assert.AreEqual(p, p1);
-            }
-        }
-
-        [Test]
-        public virtual void TestEquals()
-        {
-            Assert.AreEqual(new FacetLabel(), new FacetLabel());
-            Assert.False((new FacetLabel()).Equals(new FacetLabel("hi")));
-            Assert.False((new FacetLabel()).Equals(Convert.ToInt32(3)));
-            Assert.AreEqual(new FacetLabel("hello", "world"), new FacetLabel("hello", "world"));
-        }
-
-        [Test]
-        public virtual void TestHashCode()
-        {
-            Assert.AreEqual((new FacetLabel()).GetHashCode(), (new FacetLabel()).GetHashCode());
-            Assert.False((new FacetLabel()).GetHashCode() == (new FacetLabel("hi")).GetHashCode());
-            Assert.AreEqual((new FacetLabel("hello", "world")).GetHashCode(), (new FacetLabel("hello", "world")).GetHashCode());
-        }
-
-        [Test]
-        public virtual void TestLongHashCode()
-        {
-            Assert.AreEqual((new FacetLabel()).LongHashCode(), (new FacetLabel()).LongHashCode());
-            Assert.False((new FacetLabel()).LongHashCode() == (new FacetLabel("hi")).LongHashCode());
-            Assert.AreEqual((new FacetLabel("hello", "world")).LongHashCode(), (new FacetLabel("hello", "world")).LongHashCode());
-        }
-
-        [Test]
-        public virtual void TestArrayConstructor()
-        {
-            FacetLabel p = new FacetLabel("hello", "world", "yo");
-            Assert.AreEqual(3, p.Length);
-            Assert.AreEqual("FacetLabel: [hello, world, yo]", p.ToString());
-        }
-
-        [Test]
-        public virtual void TestCompareTo()
-        {
-            FacetLabel p = new FacetLabel("a", "b", "c", "d");
-            FacetLabel pother = new FacetLabel("a", "b", "c", "d");
-            Assert.AreEqual(0, pother.CompareTo(p));
-            Assert.AreEqual(0, p.CompareTo(pother));
-            pother = new FacetLabel();
-            Assert.True(pother.CompareTo(p) < 0);
-            Assert.True(p.CompareTo(pother) > 0);
-            pother = new FacetLabel("a", "b_", "c", "d");
-            Assert.True(pother.CompareTo(p) > 0);
-            Assert.True(p.CompareTo(pother) < 0);
-            pother = new FacetLabel("a", "b", "c");
-            Assert.True(pother.CompareTo(p) < 0);
-            Assert.True(p.CompareTo(pother) > 0);
-            pother = new FacetLabel("a", "b", "c", "e");
-            Assert.True(pother.CompareTo(p) > 0);
-            Assert.True(p.CompareTo(pother) < 0);
-        }
-
-        [Test]
-        public virtual void TestEmptyNullComponents()
-        {
-            // LUCENE-4724: CategoryPath should not allow empty or null components
-            string[][] components_tests = new string[][]
-		{
-			new string[] {"", "test"},
-			new string[] {"test", ""},
-			new string[] {"test", "", "foo"},
-			new string[] {null, "test"},
-			new string[] {"test", null},
-			new string[] {"test", null, "foo"}
-		};
-
-            foreach (string[] components in components_tests)
-            {
-                try
-                {
-                    Assert.NotNull(new FacetLabel(components));
-                    Fail("empty or null components should not be allowed: " + Arrays.ToString(components));
-                }
-                catch (System.ArgumentException)
-                {
-                    // expected
-                }
-                try
-                {
-                    new FacetField("dim", components);
-                    Fail("empty or null components should not be allowed: " + Arrays.ToString(components));
-                }
-                catch (System.ArgumentException)
-                {
-                    // expected
-                }
-                try
-                {
-                    new AssociationFacetField(new BytesRef(), "dim", components);
-                    Fail("empty or null components should not be allowed: " + Arrays.ToString(components));
-                }
-                catch (System.ArgumentException)
-                {
-                    // expected
-                }
-                try
-                {
-                    new IntAssociationFacetField(17, "dim", components);
-                    Fail("empty or null components should not be allowed: " + Arrays.ToString(components));
-                }
-                catch (System.ArgumentException)
-                {
-                    // expected
-                }
-                try
-                {
-                    new FloatAssociationFacetField(17.0f, "dim", components);
-                    Fail("empty or null components should not be allowed: " + Arrays.ToString(components));
-                }
-                catch (System.ArgumentException)
-                {
-                    // expected
-                }
-            }
-            try
-            {
-                new FacetField(null, new string[] { "abc" });
-                Fail("empty or null components should not be allowed");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            try
-            {
-                new FacetField("", new string[] { "abc" });
-                Fail("empty or null components should not be allowed");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            try
-            {
-                new IntAssociationFacetField(17, null, new string[] { "abc" });
-                Fail("empty or null components should not be allowed");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            try
-            {
-                new IntAssociationFacetField(17, "", new string[] { "abc" });
-                Fail("empty or null components should not be allowed");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            try
-            {
-                new FloatAssociationFacetField(17.0f, null, new string[] { "abc" });
-                Fail("empty or null components should not be allowed");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            try
-            {
-                new FloatAssociationFacetField(17.0f, "", new string[] { "abc" });
-                Fail("empty or null components should not be allowed");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            try
-            {
-                new AssociationFacetField(new BytesRef(), null, new string[] { "abc" });
-                Fail("empty or null components should not be allowed");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            try
-            {
-                new AssociationFacetField(new BytesRef(), "", new string[] { "abc" });
-                Fail("empty or null components should not be allowed");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            try
-            {
-                new SortedSetDocValuesFacetField(null, "abc");
-                Fail("empty or null components should not be allowed");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            try
-            {
-                new SortedSetDocValuesFacetField("", "abc");
-                Fail("empty or null components should not be allowed");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            try
-            {
-                new SortedSetDocValuesFacetField("dim", null);
-                Fail("empty or null components should not be allowed");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            try
-            {
-                new SortedSetDocValuesFacetField("dim", "");
-                Fail("empty or null components should not be allowed");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-        }
-
-        [Test]
-        public virtual void TestLongPath()
-        {
-            string bigComp = null;
-            while (true)
-            {
-                int len = FacetLabel.MAX_CATEGORY_PATH_LENGTH;
-                bigComp = TestUtil.RandomSimpleString(Random(), len, len);
-                if (bigComp.IndexOf('\u001f') != -1)
-                {
-                    continue;
-                }
-                break;
-            }
-
-            try
-            {
-                Assert.NotNull(new FacetLabel("dim", bigComp));
-                Fail("long paths should not be allowed; len=" + bigComp.Length);
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-        }
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestLRUHashMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestLRUHashMap.cs b/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestLRUHashMap.cs
deleted file mode 100644
index 71b62c5..0000000
--- a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestLRUHashMap.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet.Taxonomy
-{
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-    using Lucene.Net.Facet.Taxonomy;
-    [TestFixture]
-    public class TestLRUHashMap : FacetTestCase
-    {
-        // testLRU() tests that the specified size limit is indeed honored, and
-        // the remaining objects in the map are indeed those that have been most
-        // recently used
-        [Test]
-        public virtual void TestLru()
-        {
-            LRUHashMap<string, string> lru = new LRUHashMap<string, string>(3,1);
-            Assert.AreEqual(0, lru.Size());
-            lru.Put("one", "Hello world");
-            Assert.AreEqual(1, lru.Size());
-            lru.Put("two", "Hi man");
-            Assert.AreEqual(2, lru.Size());
-            lru.Put("three", "Bonjour");
-            Assert.AreEqual(3, lru.Size());
-            lru.Put("four", "Shalom");
-            Assert.AreEqual(3, lru.Size());
-            Assert.NotNull(lru.Get("three"));
-            Assert.NotNull(lru.Get("two"));
-            Assert.NotNull(lru.Get("four"));
-            Assert.Null(lru.Get("one"));
-            lru.Put("five", "Yo!");
-            Assert.AreEqual(3, lru.Size());
-            Assert.Null(lru.Get("three")); // three was last used, so it got removed
-            Assert.NotNull(lru.Get("five"));
-            lru.Get("four");
-            lru.Put("six", "hi");
-            lru.Put("seven", "hey dude");
-            Assert.AreEqual(3, lru.Size());
-            Assert.Null(lru.Get("one"));
-            Assert.Null(lru.Get("two"));
-            Assert.Null(lru.Get("three"));
-            Assert.NotNull(lru.Get("four"));
-            Assert.Null(lru.Get("five"));
-            Assert.NotNull(lru.Get("six"));
-            Assert.NotNull(lru.Get("seven"));
-        }
-    }
-
-}
\ No newline at end of file


[04/14] lucenenet git commit: Moving Lucene.Net.Facet tests to their appropriate place

Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestSearcherTaxonomyManager.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestSearcherTaxonomyManager.cs b/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestSearcherTaxonomyManager.cs
deleted file mode 100644
index dd93d18..0000000
--- a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestSearcherTaxonomyManager.cs
+++ /dev/null
@@ -1,398 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading;
-using Apache.NMS;
-using Lucene.Net.Support;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet.Taxonomy
-{
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-
-    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
-    using Document = Lucene.Net.Documents.Document;
-    using SearcherAndTaxonomy = Lucene.Net.Facet.Taxonomy.SearcherTaxonomyManager.SearcherAndTaxonomy;
-    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
-    using IndexWriter = Lucene.Net.Index.IndexWriter;
-    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
-    using TieredMergePolicy = Lucene.Net.Index.TieredMergePolicy;
-    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
-    using Lucene.Net.Search;
-    using Directory = Lucene.Net.Store.Directory;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-    using TestUtil = Lucene.Net.Util.TestUtil;
-    [TestFixture]
-    public class TestSearcherTaxonomyManager : FacetTestCase
-    {
-
-        private class IndexerThread : ThreadClass
-        {
-
-            internal IndexWriter w;
-            internal FacetsConfig config;
-            internal TaxonomyWriter tw;
-            internal ReferenceManager<SearcherAndTaxonomy> mgr;
-            internal int ordLimit;
-            internal AtomicBoolean stop;
-
-            public IndexerThread(IndexWriter w, FacetsConfig config, TaxonomyWriter tw, ReferenceManager<SearcherAndTaxonomy> mgr, int ordLimit, AtomicBoolean stop)
-            {
-                this.w = w;
-                this.config = config;
-                this.tw = tw;
-                this.mgr = mgr;
-                this.ordLimit = ordLimit;
-                this.stop = stop;
-            }
-
-            public override void Run()
-            {
-                try
-                {
-                    var seen = new HashSet<string>();
-                    IList<string> paths = new List<string>();
-                    while (true)
-                    {
-                        Document doc = new Document();
-                        int numPaths = TestUtil.NextInt(Random(), 1, 5);
-                        for (int i = 0; i < numPaths; i++)
-                        {
-                            string path;
-                            if (paths.Count > 0 && Random().Next(5) != 4)
-                            {
-                                // Use previous path
-                                path = paths[Random().Next(paths.Count)];
-                            }
-                            else
-                            {
-                                // Create new path
-                                path = null;
-                                while (true)
-                                {
-                                    path = TestUtil.RandomRealisticUnicodeString(Random());
-                                    if (path.Length != 0 && !seen.Contains(path))
-                                    {
-                                        seen.Add(path);
-                                        paths.Add(path);
-                                        break;
-                                    }
-                                }
-                            }
-                            doc.Add(new FacetField("field", path));
-                        }
-                        try
-                        {
-                            w.AddDocument(config.Build(tw, doc));
-                            if (mgr != null && Random().NextDouble() < 0.02)
-                            {
-                                w.Commit();
-                                tw.Commit();
-                                mgr.MaybeRefresh();
-                            }
-                        }
-                        catch (IOException ioe)
-                        {
-                            throw new Exception(ioe.Message, ioe);
-                        }
-
-                        if (VERBOSE)
-                        {
-                            Console.WriteLine("TW size=" + tw.Size + " vs " + ordLimit);
-                        }
-
-                        if (tw.Size >= ordLimit)
-                        {
-                            break;
-                        }
-                    }
-                }
-                finally
-                {
-                    stop.Set(true);
-                }
-            }
-
-        }
-
-        [Test]
-        public virtual void TestNrt()
-        {
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-            IndexWriterConfig iwc = NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
-            // Don't allow tiny maxBufferedDocs; it can make this
-            // test too slow:
-            iwc.SetMaxBufferedDocs(Math.Max(500, iwc.MaxBufferedDocs));
-
-            // MockRandom/AlcololicMergePolicy are too slow:
-            TieredMergePolicy tmp = new TieredMergePolicy();
-            tmp.FloorSegmentMB = .001;
-            iwc.SetMergePolicy(tmp);
-            IndexWriter w = new IndexWriter(dir, iwc);
-            var tw = new DirectoryTaxonomyWriter(taxoDir);
-            FacetsConfig config = new FacetsConfig();
-            config.SetMultiValued("field", true);
-            AtomicBoolean stop = new AtomicBoolean();
-
-            // How many unique facets to index before stopping:
-            int ordLimit = TEST_NIGHTLY ? 100000 : 6000;
-
-            var indexer = new IndexerThread(w, config, tw, null, ordLimit, stop);
-
-            var mgr = new SearcherTaxonomyManager(w, true, null, tw);
-
-            var reopener = new ThreadAnonymousInnerClassHelper(this, stop, mgr);
-
-            reopener.Name = "reopener";
-            reopener.Start();
-
-            indexer.Name = "indexer";
-            indexer.Start();
-
-            try
-            {
-                while (!stop.Get())
-                {
-                    SearcherAndTaxonomy pair = mgr.Acquire();
-                    try
-                    {
-                        //System.out.println("search maxOrd=" + pair.taxonomyReader.getSize());
-                        FacetsCollector sfc = new FacetsCollector();
-                        pair.searcher.Search(new MatchAllDocsQuery(), sfc);
-                        Facets facets = GetTaxonomyFacetCounts(pair.taxonomyReader, config, sfc);
-                        FacetResult result = facets.GetTopChildren(10, "field");
-                        if (pair.searcher.IndexReader.NumDocs > 0)
-                        {
-                            //System.out.println(pair.taxonomyReader.getSize());
-                            Assert.True(result.ChildCount > 0);
-                            Assert.True(result.LabelValues.Length > 0);
-                        }
-
-                        //if (VERBOSE) {
-                        //System.out.println("TEST: facets=" + FacetTestUtils.toString(results.get(0)));
-                        //}
-                    }
-                    finally
-                    {
-                        mgr.Release(pair);
-                    }
-                }
-            }
-            finally
-            {
-                indexer.Join();
-                reopener.Join();
-            }
-
-            if (VERBOSE)
-            {
-                Console.WriteLine("TEST: now stop");
-            }
-
-            IOUtils.Close(mgr, tw, w, taxoDir, dir);
-        }
-
-        private class ThreadAnonymousInnerClassHelper : ThreadClass
-        {
-            private readonly TestSearcherTaxonomyManager outerInstance;
-
-            private AtomicBoolean stop;
-            private Lucene.Net.Facet.Taxonomy.SearcherTaxonomyManager mgr;
-
-            public ThreadAnonymousInnerClassHelper(TestSearcherTaxonomyManager outerInstance, AtomicBoolean stop, Lucene.Net.Facet.Taxonomy.SearcherTaxonomyManager mgr)
-            {
-                this.outerInstance = outerInstance;
-                this.stop = stop;
-                this.mgr = mgr;
-            }
-
-            public override void Run()
-            {
-                while (!stop.Get())
-                {
-                    try
-                    {
-                        // Sleep for up to 20 msec:
-                        Thread.Sleep(Random().Next(20));
-
-                        if (VERBOSE)
-                        {
-                            Console.WriteLine("TEST: reopen");
-                        }
-
-                        mgr.MaybeRefresh();
-
-                        if (VERBOSE)
-                        {
-                            Console.WriteLine("TEST: reopen done");
-                        }
-                    }
-                    catch (Exception ioe)
-                    {
-                        throw new Exception(ioe.Message, ioe);
-                    }
-                }
-            }
-        }
-
-        
-        [Test]
-        public virtual void TestDirectory()
-        {
-            Store.Directory indexDir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-            IndexWriter w = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
-            var tw = new DirectoryTaxonomyWriter(taxoDir);
-            // first empty commit
-            w.Commit();
-            tw.Commit();
-            var mgr = new SearcherTaxonomyManager(indexDir, taxoDir, null);
-            FacetsConfig config = new FacetsConfig();
-            config.SetMultiValued("field", true);
-            AtomicBoolean stop = new AtomicBoolean();
-
-            // How many unique facets to index before stopping:
-            int ordLimit = TEST_NIGHTLY ? 100000 : 6000;
-
-            var indexer = new IndexerThread(w, config, tw, mgr, ordLimit, stop);
-            indexer.Start();
-
-            try
-            {
-                while (!stop.Get())
-                {
-                    SearcherAndTaxonomy pair = mgr.Acquire();
-                    try
-                    {
-                        //System.out.println("search maxOrd=" + pair.taxonomyReader.getSize());
-                        FacetsCollector sfc = new FacetsCollector();
-                        pair.searcher.Search(new MatchAllDocsQuery(), sfc);
-                        Facets facets = GetTaxonomyFacetCounts(pair.taxonomyReader, config, sfc);
-                        FacetResult result = facets.GetTopChildren(10, "field");
-                        if (pair.searcher.IndexReader.NumDocs > 0)
-                        {
-                            //System.out.println(pair.taxonomyReader.getSize());
-                            Assert.True(result.ChildCount > 0);
-                            Assert.True(result.LabelValues.Length > 0);
-                        }
-
-                        //if (VERBOSE) {
-                        //System.out.println("TEST: facets=" + FacetTestUtils.toString(results.get(0)));
-                        //}
-                    }
-                    finally
-                    {
-                        mgr.Release(pair);
-                    }
-                }
-            }
-            finally
-            {
-                indexer.Join();
-            }
-
-            if (VERBOSE)
-            {
-                Console.WriteLine("TEST: now stop");
-            }
-
-            IOUtils.Close(mgr, tw, w, taxoDir, indexDir);
-        }
-
-        [Test]
-        public virtual void TestReplaceTaxonomyNrt()
-        {
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-            IndexWriter w = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
-            var tw = new DirectoryTaxonomyWriter(taxoDir);
-
-            Store.Directory taxoDir2 = NewDirectory();
-            var tw2 = new DirectoryTaxonomyWriter(taxoDir2);
-            tw2.Dispose();
-
-            var mgr = new SearcherTaxonomyManager(w, true, null, tw);
-            w.AddDocument(new Document());
-            tw.ReplaceTaxonomy(taxoDir2);
-            taxoDir2.Dispose();
-
-            try
-            {
-                mgr.MaybeRefresh();
-                Fail("should have hit exception");
-            }
-            catch (IllegalStateException)
-            {
-                // expected
-            }
-
-            IOUtils.Close(mgr, tw, w, taxoDir, dir);
-        }
-
-        [Test]
-        public virtual void TestReplaceTaxonomyDirectory()
-        {
-            Store.Directory indexDir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-            IndexWriter w = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
-            var tw = new DirectoryTaxonomyWriter(taxoDir);
-            w.Commit();
-            tw.Commit();
-
-            Store.Directory taxoDir2 = NewDirectory();
-            var tw2 = new DirectoryTaxonomyWriter(taxoDir2);
-            tw2.AddCategory(new FacetLabel("a", "b"));
-            tw2.Dispose();
-
-            var mgr = new SearcherTaxonomyManager(indexDir, taxoDir, null);
-            SearcherAndTaxonomy pair = mgr.Acquire();
-            try
-            {
-                Assert.AreEqual(1, pair.taxonomyReader.Size);
-            }
-            finally
-            {
-                mgr.Release(pair);
-            }
-
-            w.AddDocument(new Document());
-            tw.ReplaceTaxonomy(taxoDir2);
-            taxoDir2.Dispose();
-            w.Commit();
-            tw.Commit();
-
-            mgr.MaybeRefresh();
-            pair = mgr.Acquire();
-            try
-            {
-                Assert.AreEqual(3, pair.taxonomyReader.Size);
-            }
-            finally
-            {
-                mgr.Release(pair);
-            }
-
-            IOUtils.Close(mgr, tw, w, taxoDir, indexDir);
-        }
-
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyCombined.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyCombined.cs b/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyCombined.cs
deleted file mode 100644
index caf1f09..0000000
--- a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyCombined.cs
+++ /dev/null
@@ -1,1185 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using System.Threading;
-using Lucene.Net.Support;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet.Taxonomy
-{
-
-
-    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
-    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
-    using Directory = Lucene.Net.Store.Directory;
-    using LockObtainFailedException = Lucene.Net.Store.LockObtainFailedException;
-    using RAMDirectory = Lucene.Net.Store.RAMDirectory;
-    using SuppressCodecs = Lucene.Net.Util.LuceneTestCase.SuppressCodecs;
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-
-    [TestFixture]
-    [SuppressCodecs]
-    public class TestTaxonomyCombined : FacetTestCase
-    {
-
-        /// <summary>
-        ///  The following categories will be added to the taxonomy by
-        ///  fillTaxonomy(), and tested by all tests below:
-        /// </summary>
-        private static readonly string[][] categories = new string[][]
-	  {
-		  new string[] {"Author", "Tom Clancy"},
-		  new string[] {"Author", "Richard Dawkins"},
-		  new string[] {"Author", "Richard Adams"},
-		  new string[] {"Price", "10", "11"},
-		  new string[] {"Price", "10", "12"},
-		  new string[] {"Price", "20", "27"},
-		  new string[] {"Date", "2006", "05"},
-		  new string[] {"Date", "2005"},
-		  new string[] {"Date", "2006"},
-		  new string[] {"Subject", "Nonfiction", "Children", "Animals"},
-		  new string[] {"Author", "Stephen Jay Gould"},
-		  new string[] {"Author", "\u05e0\u05d3\u05d1\u3042\u0628"}
-	  };
-
-        /// <summary>
-        ///  When adding the above categories with TaxonomyWriter.AddCategory(), 
-        ///  the following paths are expected to be returned:
-        ///  (note that currently the full path is not returned, and therefore
-        ///  not tested - rather, just the last component, the ordinal, is returned
-        ///  and tested.
-        /// </summary>
-        private static readonly int[][] ExpectedPaths =
-        {
-            new int[] {1, 2},
-            new int[] {1, 3},
-            new int[] {1, 4},
-            new int[] {5, 6, 7},
-            new int[] {5, 6, 8},
-            new int[] {5, 9, 10},
-            new int[] {11, 12, 13},
-            new int[] {11, 14},
-            new int[] {11, 12},
-            new int[] {15, 16, 17, 18},
-            new int[] {1, 19},
-            new int[] {1, 20}
-        };
-
-        /// <summary>
-        ///  The taxonomy index is expected to then contain the following
-        ///  generated categories, with increasing ordinals (note how parent
-        ///  categories are be added automatically when subcategories are added).
-        /// </summary>
-        private static readonly string[][] ExpectedCategories = new string[][] { new string[] { }, new string[] { "Author" }, new string[] { "Author", "Tom Clancy" }, new string[] { "Author", "Richard Dawkins" }, new string[] { "Author", "Richard Adams" }, new string[] { "Price" }, new string[] { "Price", "10" }, new string[] { "Price", "10", "11" }, new string[] { "Price", "10", "12" }, new string[] { "Price", "20" }, new string[] { "Price", "20", "27" }, new string[] { "Date" }, new string[] { "Date", "2006" }, new string[] { "Date", "2006", "05" }, new string[] { "Date", "2005" }, new string[] { "Subject" }, new string[] { "Subject", "Nonfiction" }, new string[] { "Subject", "Nonfiction", "Children" }, new string[] { "Subject", "Nonfiction", "Children", "Animals" }, new string[] { "Author", "Stephen Jay Gould" }, new string[] { "Author", "\u05e0\u05d3\u05d1\u3042\u0628" } };
-
-        /// <summary>
-        ///  fillTaxonomy adds the categories in the categories[] array, and asserts
-        ///  that the additions return exactly the ordinals (in the past - paths)
-        ///  specified in expectedPaths[].
-        ///  Note that this assumes that fillTaxonomy() is called on an empty taxonomy
-        ///  index. Calling it after something else was already added to the taxonomy
-        ///  index will surely have this method fail.
-        /// </summary>
-
-        public static void FillTaxonomy(TaxonomyWriter tw)
-        {
-            for (int i = 0; i < categories.Length; i++)
-            {
-                int ordinal = tw.AddCategory(new FacetLabel(categories[i]));
-                int expectedOrdinal = ExpectedPaths[i][ExpectedPaths[i].Length - 1];
-                if (ordinal != expectedOrdinal)
-                {
-                    Fail("For category " + Showcat(categories[i]) + " expected ordinal " + expectedOrdinal + ", but got " + ordinal);
-                }
-            }
-        }
-
-        public static string Showcat(string[] path)
-        {
-            if (path == null)
-            {
-                return "<null>";
-            }
-            if (path.Length == 0)
-            {
-                return "<empty>";
-            }
-            if (path.Length == 1 && path[0].Length == 0)
-            {
-                return "<\"\">";
-            }
-            StringBuilder sb = new StringBuilder(path[0]);
-            for (int i = 1; i < path.Length; i++)
-            {
-                sb.Append('/');
-                sb.Append(path[i]);
-            }
-            return sb.ToString();
-        }
-
-        private string Showcat(FacetLabel path)
-        {
-            if (path == null)
-            {
-                return "<null>";
-            }
-            if (path.Length == 0)
-            {
-                return "<empty>";
-            }
-            return "<" + path.ToString() + ">";
-        }
-
-        /// <summary>
-        ///  Basic tests for TaxonomyWriter. Basically, we test that
-        ///  IndexWriter.AddCategory works, i.e. returns the expected ordinals
-        ///  (this is tested by calling the fillTaxonomy() method above).
-        ///  We do not test here that after writing the index can be read -
-        ///  this will be done in more tests below.
-        /// </summary>
-        [Test]
-        public virtual void TestWriter()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            FillTaxonomy(tw);
-            // Also check TaxonomyWriter.getSize() - see that the taxonomy's size
-            // is what we expect it to be.
-            Assert.AreEqual(ExpectedCategories.Length, tw.Size);
-            tw.Dispose();
-            indexDir.Dispose();
-        }
-
-        /// <summary>
-        ///  testWriterTwice is exactly like testWriter, except that after adding
-        ///  all the categories, we add them again, and see that we get the same
-        ///  old ids again - not new categories.
-        /// </summary>
-        [Test]
-        public virtual void TestWriterTwice()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            FillTaxonomy(tw);
-            // run fillTaxonomy again - this will try to add the same categories
-            // again, and check that we see the same ordinal paths again, not
-            // different ones. 
-            FillTaxonomy(tw);
-            // Let's check the number of categories again, to see that no
-            // extraneous categories were created:
-            Assert.AreEqual(ExpectedCategories.Length, tw.Size);
-            tw.Dispose();
-            indexDir.Dispose();
-        }
-
-        /// <summary>
-        ///  testWriterTwice2 is similar to testWriterTwice, except that the index
-        ///  is closed and reopened before attempting to write to it the same
-        ///  categories again. While testWriterTwice can get along with writing
-        ///  and reading correctly just to the cache, testWriterTwice2 checks also
-        ///  the actual disk read part of the writer:
-        /// </summary>
-        [Test]
-        public virtual void TestWriterTwice2()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            FillTaxonomy(tw);
-            tw.Dispose();
-            tw = new DirectoryTaxonomyWriter(indexDir);
-            // run fillTaxonomy again - this will try to add the same categories
-            // again, and check that we see the same ordinals again, not different
-            // ones, and that the number of categories hasn't grown by the new
-            // additions
-            FillTaxonomy(tw);
-            Assert.AreEqual(ExpectedCategories.Length, tw.Size);
-            tw.Dispose();
-            indexDir.Dispose();
-        }
-
-        /// <summary>
-        /// testWriterTwice3 is yet another test which tests creating a taxonomy
-        /// in two separate writing sessions. This test used to fail because of
-        /// a bug involving commit(), explained below, and now should succeed.
-        /// </summary>
-        [Test]
-        public virtual void TestWriterTwice3()
-        {
-            var indexDir = NewDirectory();
-            // First, create and fill the taxonomy
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            FillTaxonomy(tw);
-            tw.Dispose();
-            // Now, open the same taxonomy and add the same categories again.
-            // After a few categories, the LuceneTaxonomyWriter implementation
-            // will stop looking for each category on disk, and rather read them
-            // all into memory and close it's reader. The bug was that it closed
-            // the reader, but forgot that it did (because it didn't set the reader
-            // reference to null).
-            tw = new DirectoryTaxonomyWriter(indexDir);
-            FillTaxonomy(tw);
-            // Add one new category, just to make commit() do something:
-            tw.AddCategory(new FacetLabel("hi"));
-            // Do a commit(). Here was a bug - if tw had a reader open, it should
-            // be reopened after the commit. However, in our case the reader should
-            // not be open (as explained above) but because it was not set to null,
-            // we forgot that, tried to reopen it, and got an AlreadyClosedException.
-            tw.Commit();
-            Assert.AreEqual(ExpectedCategories.Length + 1, tw.Size);
-            tw.Dispose();
-            indexDir.Dispose();
-        }
-
-        /// <summary>
-        ///  Another set of tests for the writer, which don't use an array and
-        ///  try to distill the different cases, and therefore may be more helpful
-        ///  for debugging a problem than testWriter() which is hard to know why
-        ///  or where it failed. 
-        /// </summary>
-        [Test]
-        public virtual void TestWriterSimpler()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            Assert.AreEqual(1, tw.Size); // the root only
-            // Test that adding a new top-level category works
-            Assert.AreEqual(1, tw.AddCategory(new FacetLabel("a")));
-            Assert.AreEqual(2, tw.Size);
-            // Test that adding the same category again is noticed, and the
-            // same ordinal (and not a new one) is returned.
-            Assert.AreEqual(1, tw.AddCategory(new FacetLabel("a")));
-            Assert.AreEqual(2, tw.Size);
-            // Test that adding another top-level category returns a new ordinal,
-            // not the same one
-            Assert.AreEqual(2, tw.AddCategory(new FacetLabel("b")));
-            Assert.AreEqual(3, tw.Size);
-            // Test that adding a category inside one of the above adds just one
-            // new ordinal:
-            Assert.AreEqual(3, tw.AddCategory(new FacetLabel("a", "c")));
-            Assert.AreEqual(4, tw.Size);
-            // Test that adding the same second-level category doesn't do anything:
-            Assert.AreEqual(3, tw.AddCategory(new FacetLabel("a", "c")));
-            Assert.AreEqual(4, tw.Size);
-            // Test that adding a second-level category with two new components
-            // indeed adds two categories
-            Assert.AreEqual(5, tw.AddCategory(new FacetLabel("d", "e")));
-            Assert.AreEqual(6, tw.Size);
-            // Verify that the parents were added above in the order we expected
-            Assert.AreEqual(4, tw.AddCategory(new FacetLabel("d")));
-            // Similar, but inside a category that already exists:
-            Assert.AreEqual(7, tw.AddCategory(new FacetLabel("b", "d", "e")));
-            Assert.AreEqual(8, tw.Size);
-            // And now inside two levels of categories that already exist:
-            Assert.AreEqual(8, tw.AddCategory(new FacetLabel("b", "d", "f")));
-            Assert.AreEqual(9, tw.Size);
-
-            tw.Dispose();
-            indexDir.Dispose();
-        }
-
-        /// <summary>
-        ///  Test writing an empty index, and seeing that a reader finds in it
-        ///  the root category, and only it. We check all the methods on that
-        ///  root category return the expected results.
-        /// </summary>
-        [Test]
-        public virtual void TestRootOnly()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            // right after opening the index, it should already contain the
-            // root, so have size 1:
-            Assert.AreEqual(1, tw.Size);
-            tw.Dispose();
-            var tr = new DirectoryTaxonomyReader(indexDir);
-            Assert.AreEqual(1, tr.Size);
-            Assert.AreEqual(0, tr.GetPath(0).Length);
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.ParallelTaxonomyArrays.Parents()[0]);
-            Assert.AreEqual(0, tr.GetOrdinal(new FacetLabel()));
-            tr.Dispose(true);
-            indexDir.Dispose();
-        }
-
-        /// <summary>
-        ///  The following test is exactly the same as testRootOnly, except we
-        ///  do not close the writer before opening the reader. We want to see
-        ///  that the root is visible to the reader not only after the writer is
-        ///  closed, but immediately after it is created.
-        /// </summary>
-        [Test]
-        public virtual void TestRootOnly2()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            tw.Commit();
-            var tr = new DirectoryTaxonomyReader(indexDir);
-            Assert.AreEqual(1, tr.Size);
-            Assert.AreEqual(0, tr.GetPath(0).Length);
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.ParallelTaxonomyArrays.Parents()[0]);
-            Assert.AreEqual(0, tr.GetOrdinal(new FacetLabel()));
-            tw.Dispose();
-            tr.Dispose(true);
-            indexDir.Dispose();
-        }
-
-        /// <summary>
-        ///  Basic tests for TaxonomyReader's category <=> ordinal transformations
-        ///  (getSize(), getCategory() and getOrdinal()).
-        ///  We test that after writing the index, it can be read and all the
-        ///  categories and ordinals are there just as we expected them to be.
-        /// </summary>
-        [Test]
-        public virtual void TestReaderBasic()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            FillTaxonomy(tw);
-            tw.Dispose();
-            var tr = new DirectoryTaxonomyReader(indexDir);
-
-            // test TaxonomyReader.getSize():
-            Assert.AreEqual(ExpectedCategories.Length, tr.Size);
-
-            // test round trips of ordinal => category => ordinal
-            for (int i = 0; i < tr.Size; i++)
-            {
-                Assert.AreEqual(i, tr.GetOrdinal(tr.GetPath(i)));
-            }
-
-            // test TaxonomyReader.getCategory():
-            for (int i = 1; i < tr.Size; i++)
-            {
-                FacetLabel expectedCategory = new FacetLabel(ExpectedCategories[i]);
-                FacetLabel category = tr.GetPath(i);
-                if (!expectedCategory.Equals(category))
-                {
-                    Fail("For ordinal " + i + " expected category " + Showcat(expectedCategory) + ", but got " + Showcat(category));
-                }
-            }
-            //  (also test invalid ordinals:)
-            Assert.Null(tr.GetPath(-1));
-            Assert.Null(tr.GetPath(tr.Size));
-            Assert.Null(tr.GetPath(TaxonomyReader.INVALID_ORDINAL));
-
-            // test TaxonomyReader.GetOrdinal():
-            for (int i = 1; i < ExpectedCategories.Length; i++)
-            {
-                int expectedOrdinal = i;
-                int ordinal = tr.GetOrdinal(new FacetLabel(ExpectedCategories[i]));
-                if (expectedOrdinal != ordinal)
-                {
-                    Fail("For category " + Showcat(ExpectedCategories[i]) + " expected ordinal " + expectedOrdinal + ", but got " + ordinal);
-                }
-            }
-            // (also test invalid categories:)
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.GetOrdinal(new FacetLabel("non-existant")));
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.GetOrdinal(new FacetLabel("Author", "Jules Verne")));
-
-            tr.Dispose();
-            indexDir.Dispose();
-        }
-
-        /// <summary>
-        ///  Tests for TaxonomyReader's getParent() method.
-        ///  We check it by comparing its results to those we could have gotten by
-        ///  looking at the category string paths (where the parentage is obvious).
-        ///  Note that after testReaderBasic(), we already know we can trust the
-        ///  ordinal <=> category conversions.
-        ///  
-        ///  Note: At the moment, the parent methods in the reader are deprecated,
-        ///  but this does not mean they should not be tested! Until they are
-        ///  removed (*if* they are removed), these tests should remain to see
-        ///  that they still work correctly.
-        /// </summary>
-
-        [Test]
-        public virtual void TestReaderParent()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            FillTaxonomy(tw);
-            tw.Dispose();
-            var tr = new DirectoryTaxonomyReader(indexDir);
-
-            // check that the parent of the root ordinal is the invalid ordinal:
-            int[] parents = tr.ParallelTaxonomyArrays.Parents();
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, parents[0]);
-
-            // check parent of non-root ordinals:
-            for (int ordinal = 1; ordinal < tr.Size; ordinal++)
-            {
-                FacetLabel me = tr.GetPath(ordinal);
-                int parentOrdinal = parents[ordinal];
-                FacetLabel parent = tr.GetPath(parentOrdinal);
-                if (parent == null)
-                {
-                    Fail("Parent of " + ordinal + " is " + parentOrdinal + ", but this is not a valid category.");
-                }
-                // verify that the parent is indeed my parent, according to the strings
-                if (!me.Subpath(me.Length - 1).Equals(parent))
-                {
-                    Fail("Got parent " + parentOrdinal + " for ordinal " + ordinal + " but categories are " + Showcat(parent) + " and " + Showcat(me) + " respectively.");
-                }
-            }
-
-            tr.Dispose();
-            indexDir.Dispose();
-        }
-
-        /// <summary>
-        /// Tests for TaxonomyWriter's getParent() method. We check it by comparing
-        /// its results to those we could have gotten by looking at the category
-        /// string paths using a TaxonomyReader (where the parentage is obvious).
-        /// Note that after testReaderBasic(), we already know we can trust the
-        /// ordinal <=> category conversions from TaxonomyReader.
-        /// 
-        /// The difference between testWriterParent1 and testWriterParent2 is that
-        /// the former closes the taxonomy writer before reopening it, while the
-        /// latter does not.
-        /// 
-        /// This test code is virtually identical to that of testReaderParent().
-        /// </summary>
-        [Test]
-        public virtual void TestWriterParent1()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            FillTaxonomy(tw);
-            tw.Dispose();
-            tw = new DirectoryTaxonomyWriter(indexDir);
-            var tr = new DirectoryTaxonomyReader(indexDir);
-
-            CheckWriterParent(tr, tw);
-
-            tw.Dispose();
-            tr.Dispose();
-            indexDir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestWriterParent2()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            FillTaxonomy(tw);
-            tw.Commit();
-            var tr = new DirectoryTaxonomyReader(indexDir);
-
-            CheckWriterParent(tr, tw);
-
-            tw.Dispose();
-            tr.Dispose();
-            indexDir.Dispose();
-        }
-
-        private void CheckWriterParent(TaxonomyReader tr, TaxonomyWriter tw)
-        {
-            // check that the parent of the root ordinal is the invalid ordinal:
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tw.GetParent(0));
-
-            // check parent of non-root ordinals:
-            for (int ordinal = 1; ordinal < tr.Size; ordinal++)
-            {
-                FacetLabel me = tr.GetPath(ordinal);
-                int parentOrdinal = tw.GetParent(ordinal);
-                FacetLabel parent = tr.GetPath(parentOrdinal);
-                if (parent == null)
-                {
-                    Fail("Parent of " + ordinal + " is " + parentOrdinal + ", but this is not a valid category.");
-                }
-                // verify that the parent is indeed my parent, according to the
-                // strings
-                if (!me.Subpath(me.Length - 1).Equals(parent))
-                {
-                    Fail("Got parent " + parentOrdinal + " for ordinal " + ordinal + " but categories are " + Showcat(parent) + " and " + Showcat(me) + " respectively.");
-                }
-            }
-
-            // check parent of of invalid ordinals:
-            try
-            {
-                tw.GetParent(-1);
-                Fail("getParent for -1 should throw exception");
-            }
-            catch (System.IndexOutOfRangeException)
-            {
-                // ok
-            }
-            try
-            {
-                tw.GetParent(TaxonomyReader.INVALID_ORDINAL);
-                Fail("getParent for INVALID_ORDINAL should throw exception");
-            }
-            catch (System.IndexOutOfRangeException)
-            {
-                // ok
-            }
-            try
-            {
-                int parent = tw.GetParent(tr.Size);
-                Fail("getParent for getSize() should throw exception, but returned " + parent);
-            }
-            catch (System.IndexOutOfRangeException)
-            {
-                // ok
-            }
-        }
-
-        /// <summary>
-        /// Test TaxonomyReader's child browsing method, getChildrenArrays()
-        /// This only tests for correctness of the data on one example - we have
-        /// below further tests on data refresh etc.
-        /// </summary>
-        [Test]
-        public virtual void TestChildrenArrays()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            FillTaxonomy(tw);
-            tw.Dispose();
-            var tr = new DirectoryTaxonomyReader(indexDir);
-            ParallelTaxonomyArrays ca = tr.ParallelTaxonomyArrays;
-            int[] youngestChildArray = ca.Children();
-            Assert.AreEqual(tr.Size, youngestChildArray.Length);
-            int[] olderSiblingArray = ca.Siblings();
-            Assert.AreEqual(tr.Size, olderSiblingArray.Length);
-            for (int i = 0; i < ExpectedCategories.Length; i++)
-            {
-                // find expected children by looking at all expectedCategories
-                // for children
-                List<int?> expectedChildren = new List<int?>();
-                for (int j = ExpectedCategories.Length - 1; j >= 0; j--)
-                {
-                    if (ExpectedCategories[j].Length != ExpectedCategories[i].Length + 1)
-                    {
-                        continue; // not longer by 1, so can't be a child
-                    }
-                    bool ischild = true;
-                    for (int k = 0; k < ExpectedCategories[i].Length; k++)
-                    {
-                        if (!ExpectedCategories[j][k].Equals(ExpectedCategories[i][k]))
-                        {
-                            ischild = false;
-                            break;
-                        }
-                    }
-                    if (ischild)
-                    {
-                        expectedChildren.Add(j);
-                    }
-                }
-                // check that children and expectedChildren are the same, with the
-                // correct reverse (youngest to oldest) order:
-                if (expectedChildren.Count == 0)
-                {
-                    Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, youngestChildArray[i]);
-                }
-                else
-                {
-                    int child = youngestChildArray[i];
-                    Assert.AreEqual((int)expectedChildren[0], child);
-                    for (int j = 1; j < expectedChildren.Count; j++)
-                    {
-                        child = olderSiblingArray[child];
-                        Assert.AreEqual((int)expectedChildren[j], child);
-                        // if child is INVALID_ORDINAL we should stop, but
-                        // AssertEquals would fail in this case anyway.
-                    }
-                    // When we're done comparing, olderSiblingArray should now point
-                    // to INVALID_ORDINAL, saying there are no more children. If it
-                    // doesn't, we found too many children...
-                    Assert.AreEqual(-1, olderSiblingArray[child]);
-                }
-            }
-            tr.Dispose();
-            indexDir.Dispose();
-        }
-
-        /// <summary>
-        /// Similar to testChildrenArrays, except rather than look at
-        /// expected results, we test for several "invariants" that the results
-        /// should uphold, e.g., that a child of a category indeed has this category
-        /// as its parent. This sort of test can more easily be extended to larger
-        /// example taxonomies, because we do not need to build the expected list
-        /// of categories like we did in the above test.
-        /// </summary>
-        [Test]
-        public virtual void TestChildrenArraysInvariants()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            FillTaxonomy(tw);
-            tw.Dispose();
-            var tr = new DirectoryTaxonomyReader(indexDir);
-            ParallelTaxonomyArrays ca = tr.ParallelTaxonomyArrays;
-            int[] children = ca.Children();
-            Assert.AreEqual(tr.Size, children.Length);
-            int[] olderSiblingArray = ca.Siblings();
-            Assert.AreEqual(tr.Size, olderSiblingArray.Length);
-
-            // test that the "youngest child" of every category is indeed a child:
-            int[] parents = tr.ParallelTaxonomyArrays.Parents();
-            for (int i = 0; i < tr.Size; i++)
-            {
-                int youngestChild = children[i];
-                if (youngestChild != TaxonomyReader.INVALID_ORDINAL)
-                {
-                    Assert.AreEqual(i, parents[youngestChild]);
-                }
-            }
-
-            // test that the "older sibling" of every category is indeed older (lower)
-            // (it can also be INVALID_ORDINAL, which is lower than any ordinal)
-            for (int i = 0; i < tr.Size; i++)
-            {
-                Assert.True(olderSiblingArray[i] < i, "olderSiblingArray[" + i + "] should be <" + i);
-            }
-
-            // test that the "older sibling" of every category is indeed a sibling
-            // (they share the same parent)
-            for (int i = 0; i < tr.Size; i++)
-            {
-                int sibling = olderSiblingArray[i];
-                if (sibling == TaxonomyReader.INVALID_ORDINAL)
-                {
-                    continue;
-                }
-                Assert.AreEqual(parents[i], parents[sibling]);
-            }
-
-            // And now for slightly more complex (and less "invariant-like"...)
-            // tests:
-
-            // test that the "youngest child" is indeed the youngest (so we don't
-            // miss the first children in the chain)
-            for (int i = 0; i < tr.Size; i++)
-            {
-                // Find the really youngest child:
-                int j;
-                for (j = tr.Size - 1; j > i; j--)
-                {
-                    if (parents[j] == i)
-                    {
-                        break; // found youngest child
-                    }
-                }
-                if (j == i) // no child found
-                {
-                    j = TaxonomyReader.INVALID_ORDINAL;
-                }
-                Assert.AreEqual(j, children[i]);
-            }
-
-            // test that the "older sibling" is indeed the least oldest one - and
-            // not a too old one or -1 (so we didn't miss some children in the
-            // middle or the end of the chain).
-            for (int i = 0; i < tr.Size; i++)
-            {
-                // Find the youngest older sibling:
-                int j;
-                for (j = i - 1; j >= 0; j--)
-                {
-                    if (parents[j] == parents[i])
-                    {
-                        break; // found youngest older sibling
-                    }
-                }
-                if (j < 0) // no sibling found
-                {
-                    j = TaxonomyReader.INVALID_ORDINAL;
-                }
-                Assert.AreEqual(j, olderSiblingArray[i]);
-            }
-
-            tr.Dispose();
-            indexDir.Dispose();
-        }
-
-        /// <summary>
-        /// Test how getChildrenArrays() deals with the taxonomy's growth:
-        /// </summary>
-        [Test]
-        public virtual void TestChildrenArraysGrowth()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            tw.AddCategory(new FacetLabel("hi", "there"));
-            tw.Commit();
-            var tr = new DirectoryTaxonomyReader(indexDir);
-            ParallelTaxonomyArrays ca = tr.ParallelTaxonomyArrays;
-            Assert.AreEqual(3, tr.Size);
-            Assert.AreEqual(3, ca.Siblings().Length);
-            Assert.AreEqual(3, ca.Children().Length);
-            Assert.True(Arrays.Equals(new int[] { 1, 2, -1 }, ca.Children()));
-            Assert.True(Arrays.Equals(new int[] { -1, -1, -1 }, ca.Siblings()));
-            tw.AddCategory(new FacetLabel("hi", "ho"));
-            tw.AddCategory(new FacetLabel("hello"));
-            tw.Commit();
-            // Before refresh, nothing changed..
-            ParallelTaxonomyArrays newca = tr.ParallelTaxonomyArrays;
-            Assert.AreSame(newca, ca); // we got exactly the same object
-            Assert.AreEqual(3, tr.Size);
-            Assert.AreEqual(3, ca.Siblings().Length);
-            Assert.AreEqual(3, ca.Children().Length);
-            // After the refresh, things change:
-            var newtr = TaxonomyReader.OpenIfChanged(tr);
-            Assert.NotNull(newtr);
-            tr.Dispose();
-            tr = newtr;
-            ca = tr.ParallelTaxonomyArrays;
-            Assert.AreEqual(5, tr.Size);
-            Assert.AreEqual(5, ca.Siblings().Length);
-            Assert.AreEqual(5, ca.Children().Length);
-            Assert.True(Arrays.Equals(new int[] { 4, 3, -1, -1, -1 }, ca.Children()));
-            Assert.True(Arrays.Equals(new int[] { -1, -1, -1, 2, 1 }, ca.Siblings()));
-            tw.Dispose();
-            tr.Dispose();
-            indexDir.Dispose();
-        }
-
-        // Test that getParentArrays is valid when retrieved during refresh
-        [Test]
-        public virtual void TestTaxonomyReaderRefreshRaces()
-        {
-            // compute base child arrays - after first chunk, and after the other
-            var indexDirBase = NewDirectory();
-            var twBase = new DirectoryTaxonomyWriter(indexDirBase);
-            twBase.AddCategory(new FacetLabel("a", "0"));
-            FacetLabel abPath = new FacetLabel("a", "b");
-            twBase.AddCategory(abPath);
-            twBase.Commit();
-            var trBase = new DirectoryTaxonomyReader(indexDirBase);
-
-            ParallelTaxonomyArrays ca1 = trBase.ParallelTaxonomyArrays;
-
-            int abOrd = trBase.GetOrdinal(abPath);
-            int abYoungChildBase1 = ca1.Children()[abOrd];
-
-            int numCategories = AtLeast(800);
-            for (int i = 0; i < numCategories; i++)
-            {
-                twBase.AddCategory(new FacetLabel("a", "b", Convert.ToString(i)));
-            }
-            twBase.Dispose();
-
-            var newTaxoReader = TaxonomyReader.OpenIfChanged(trBase);
-            Assert.NotNull(newTaxoReader);
-            trBase.Dispose();
-            trBase = newTaxoReader;
-
-            ParallelTaxonomyArrays ca2 = trBase.ParallelTaxonomyArrays;
-            int abYoungChildBase2 = ca2.Children()[abOrd];
-
-            int numRetries = AtLeast(50);
-            for (int retry = 0; retry < numRetries; retry++)
-            {
-                AssertConsistentYoungestChild(abPath, abOrd, abYoungChildBase1, abYoungChildBase2, retry, numCategories);
-            }
-
-            trBase.Dispose();
-            indexDirBase.Dispose();
-        }
-
-        
-        private void AssertConsistentYoungestChild(FacetLabel abPath, int abOrd, int abYoungChildBase1, int abYoungChildBase2, int retry, int numCategories)
-        {
-            var indexDir = new SlowRAMDirectory(-1, null); // no slowness for intialization
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            tw.AddCategory(new FacetLabel("a", "0"));
-            tw.AddCategory(abPath);
-            tw.Commit();
-
-            
-            var tr = new DirectoryTaxonomyReader(indexDir);
-            for (int i = 0; i < numCategories; i++)
-            {
-                var cp = new FacetLabel("a", "b", Convert.ToString(i));
-                tw.AddCategory(cp);
-                Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.GetOrdinal(cp), "Ordinal of " + cp + " must be invalid until Taxonomy Reader was refreshed");
-            }
-            tw.Dispose();
-
-            
-            var stop = new AtomicBoolean(false);
-            Exception[] error = new Exception[] { null };
-            int[] retrieval = new int[] { 0 };
-
-            var thread = new ThreadAnonymousInnerClassHelper(this, abPath, abOrd, abYoungChildBase1, abYoungChildBase2, retry, tr, stop, error, retrieval);
-            thread.Start();
-
-            indexDir.SleepMillis = 1; // some delay for refresh
-            var newTaxoReader = TaxonomyReader.OpenIfChanged(tr);
-            if (newTaxoReader != null)
-            {
-                newTaxoReader.Dispose();
-            }
-
-            stop.Set(true);
-            thread.Join();
-            Assert.Null(error[0], "Unexpcted exception at retry " + retry + " retrieval " + retrieval[0] + ": \n" + stackTraceStr(error[0]));
-
-            tr.Dispose();
-        }
-
-        private class ThreadAnonymousInnerClassHelper : ThreadClass
-        {
-            private readonly TestTaxonomyCombined outerInstance;
-
-            private Lucene.Net.Facet.Taxonomy.FacetLabel abPath;
-            private int abOrd;
-            private int abYoungChildBase1;
-            private int abYoungChildBase2;
-            private int retry;
-            private DirectoryTaxonomyReader tr;
-            private AtomicBoolean stop;
-            private Exception[] error;
-            private int[] retrieval;
-
-            public ThreadAnonymousInnerClassHelper(TestTaxonomyCombined outerInstance, Lucene.Net.Facet.Taxonomy.FacetLabel abPath, int abOrd, int abYoungChildBase1, int abYoungChildBase2, int retry, DirectoryTaxonomyReader tr, AtomicBoolean stop, Exception[] error, int[] retrieval)
-                : base("Child Arrays Verifier")
-            {
-                this.outerInstance = outerInstance;
-                this.abPath = abPath;
-                this.abOrd = abOrd;
-                this.abYoungChildBase1 = abYoungChildBase1;
-                this.abYoungChildBase2 = abYoungChildBase2;
-                this.retry = retry;
-                this.tr = tr;
-                this.stop = stop;
-                this.error = error;
-                this.retrieval = retrieval;
-            }
-
-            public override void Run()
-            {
-                Priority = 1 + Priority;
-                try
-                {
-                    while (!stop.Get())
-                    {
-                        int lastOrd = tr.ParallelTaxonomyArrays.Parents().Length - 1;
-                        Assert.NotNull(tr.GetPath(lastOrd), "path of last-ord " + lastOrd + " is not found!");
-                        AssertChildrenArrays(tr.ParallelTaxonomyArrays, retry, retrieval[0]++);
-                        Thread.Sleep(10);// don't starve refresh()'s CPU, which sleeps every 50 bytes for 1 ms
-                    }
-                }
-                catch (Exception e)
-                {
-                    error[0] = e;
-                    stop.Set(true);
-                }
-            }
-
-            private void AssertChildrenArrays(ParallelTaxonomyArrays ca, int retry, int retrieval)
-            {
-                int abYoungChild = ca.Children()[abOrd];
-                Assert.True(abYoungChildBase1 == abYoungChild || abYoungChildBase2 == ca.Children()[abOrd], "Retry " + retry + ": retrieval: " + retrieval + ": wrong youngest child for category " + abPath + " (ord=" + abOrd + ") - must be either " + abYoungChildBase1 + " or " + abYoungChildBase2 + " but was: " + abYoungChild);
-            }
-        }
-
-        /// <summary>
-        /// Grab the stack trace into a string since the exception was thrown in a thread and we want the assert 
-        /// outside the thread to show the stack trace in case of failure.   
-        /// </summary>
-        private string stackTraceStr(Exception error)
-        {
-            if (error == null)
-            {
-                return "";
-            }
-
-            error.printStackTrace();
-            return error.StackTrace;
-        }
-
-        /// <summary>
-        ///  Test that if separate reader and writer objects are opened, new
-        ///  categories written into the writer are available to a reader only
-        ///  after a commit().
-        ///  Note that this test obviously doesn't cover all the different
-        ///  concurrency scenarios, all different methods, and so on. We may
-        ///  want to write more tests of this sort.
-        /// 
-        ///  This test simulates what would happen when there are two separate
-        ///  processes, one doing indexing, and the other searching, and each opens
-        ///  its own object (with obviously no connection between the objects) using
-        ///  the same disk files. Note, though, that this test does not test what
-        ///  happens when the two processes do their actual work at exactly the same
-        ///  time.
-        ///  It also doesn't test multi-threading.
-        /// </summary>
-        [Test]
-        public virtual void TestSeparateReaderAndWriter()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            tw.Commit();
-            var tr = new DirectoryTaxonomyReader(indexDir);
-
-            Assert.AreEqual(1, tr.Size); // the empty taxonomy has size 1 (the root)
-            tw.AddCategory(new FacetLabel("Author"));
-            Assert.AreEqual(1, tr.Size); // still root only...
-            Assert.Null(TaxonomyReader.OpenIfChanged(tr)); // this is not enough, because tw.Commit() hasn't been done yet
-            Assert.AreEqual(1, tr.Size); // still root only...
-            tw.Commit();
-            Assert.AreEqual(1, tr.Size); // still root only...
-            var newTaxoReader = TaxonomyReader.OpenIfChanged(tr);
-            Assert.NotNull(newTaxoReader);
-            tr.Dispose();
-            tr = newTaxoReader;
-
-            int author = 1;
-            try
-            {
-                Assert.AreEqual(TaxonomyReader.ROOT_ORDINAL, tr.ParallelTaxonomyArrays.Parents()[author]);
-                // ok
-            }
-            catch (System.IndexOutOfRangeException)
-            {
-                Fail("After category addition, commit() and refresh(), getParent for " + author + " should NOT throw exception");
-            }
-            Assert.AreEqual(2, tr.Size); // finally, see there are two categories
-
-            // now, add another category, and verify that after commit and refresh
-            // the parent of this category is correct (this requires the reader
-            // to correctly update its prefetched parent vector), and that the
-            // old information also wasn't ruined:
-            tw.AddCategory(new FacetLabel("Author", "Richard Dawkins"));
-            int dawkins = 2;
-            tw.Commit();
-            newTaxoReader = TaxonomyReader.OpenIfChanged(tr);
-            Assert.NotNull(newTaxoReader);
-            tr.Dispose();
-            tr = newTaxoReader;
-            int[] parents = tr.ParallelTaxonomyArrays.Parents();
-            Assert.AreEqual(author, parents[dawkins]);
-            Assert.AreEqual(TaxonomyReader.ROOT_ORDINAL, parents[author]);
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, parents[TaxonomyReader.ROOT_ORDINAL]);
-            Assert.AreEqual(3, tr.Size);
-            tw.Dispose();
-            tr.Dispose();
-            indexDir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestSeparateReaderAndWriter2()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            tw.Commit();
-            var tr = new DirectoryTaxonomyReader(indexDir);
-
-            // Test getOrdinal():
-            FacetLabel author = new FacetLabel("Author");
-
-            Assert.AreEqual(1, tr.Size); // the empty taxonomy has size 1 (the root)
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.GetOrdinal(author));
-            tw.AddCategory(author);
-            // before commit and refresh, no change:
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.GetOrdinal(author));
-            Assert.AreEqual(1, tr.Size); // still root only...
-            Assert.Null(TaxonomyReader.OpenIfChanged(tr)); // this is not enough, because tw.Commit() hasn't been done yet
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.GetOrdinal(author));
-            Assert.AreEqual(1, tr.Size); // still root only...
-            tw.Commit();
-            // still not enough before refresh:
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.GetOrdinal(author));
-            Assert.AreEqual(1, tr.Size); // still root only...
-            var newTaxoReader = TaxonomyReader.OpenIfChanged(tr);
-            Assert.NotNull(newTaxoReader);
-            tr.Dispose();
-            tr = newTaxoReader;
-            Assert.AreEqual(1, tr.GetOrdinal(author));
-            Assert.AreEqual(2, tr.Size);
-            tw.Dispose();
-            tr.Dispose();
-            indexDir.Dispose();
-        }
-
-        /// <summary>
-        /// Test what happens if we try to write to a locked taxonomy writer,
-        /// and see that we can unlock it and continue.
-        /// </summary>
-        [Test]
-        public virtual void TestWriterLock()
-        {
-            // native fslock impl gets angry if we use it, so use RAMDirectory explicitly.
-            var indexDir = new RAMDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            tw.AddCategory(new FacetLabel("hi", "there"));
-            tw.Commit();
-            // we deliberately not close the write now, and keep it open and
-            // locked.
-            // Verify that the writer worked:
-            var tr = new DirectoryTaxonomyReader(indexDir);
-            Assert.AreEqual(2, tr.GetOrdinal(new FacetLabel("hi", "there")));
-            // Try to open a second writer, with the first one locking the directory.
-            // We expect to get a LockObtainFailedException.
-            try
-            {
-                Assert.Null(new DirectoryTaxonomyWriter(indexDir));
-                Fail("should have failed to write in locked directory");
-            }
-            catch (LockObtainFailedException)
-            {
-                // this is what we expect to happen.
-            }
-            // Remove the lock, and now the open should succeed, and we can
-            // write to the new writer.
-            DirectoryTaxonomyWriter.Unlock(indexDir);
-            var tw2 = new DirectoryTaxonomyWriter(indexDir);
-            tw2.AddCategory(new FacetLabel("hey"));
-            tw2.Dispose();
-            // See that the writer indeed wrote:
-            var newtr = TaxonomyReader.OpenIfChanged(tr);
-            Assert.NotNull(newtr);
-            tr.Dispose();
-            tr = newtr;
-            Assert.AreEqual(3, tr.GetOrdinal(new FacetLabel("hey")));
-            tr.Dispose();
-            tw.Dispose();
-            indexDir.Dispose();
-        }
-
-        /// <summary>
-        /// fillTaxonomyCheckPaths adds the categories in the categories[] array,
-        /// and asserts that the additions return exactly paths specified in
-        /// expectedPaths[]. This is the same add fillTaxonomy() but also checks
-        /// the correctness of getParent(), not just addCategory().
-        /// Note that this assumes that fillTaxonomyCheckPaths() is called on an empty
-        /// taxonomy index. Calling it after something else was already added to the
-        /// taxonomy index will surely have this method fail.
-        /// </summary>
-        public static void FillTaxonomyCheckPaths(TaxonomyWriter tw)
-        {
-            for (int i = 0; i < categories.Length; i++)
-            {
-                int ordinal = tw.AddCategory(new FacetLabel(categories[i]));
-                int expectedOrdinal = ExpectedPaths[i][ExpectedPaths[i].Length - 1];
-                if (ordinal != expectedOrdinal)
-                {
-                    Fail("For category " + Showcat(categories[i]) + " expected ordinal " + expectedOrdinal + ", but got " + ordinal);
-                }
-                for (int j = ExpectedPaths[i].Length - 2; j >= 0; j--)
-                {
-                    ordinal = tw.GetParent(ordinal);
-                    expectedOrdinal = ExpectedPaths[i][j];
-                    if (ordinal != expectedOrdinal)
-                    {
-                        Fail("For category " + Showcat(categories[i]) + " expected ancestor level " + (ExpectedPaths[i].Length - 1 - j) + " was " + expectedOrdinal + ", but got " + ordinal);
-                    }
-                }
-            }
-        }
-
-        // After fillTaxonomy returned successfully, checkPaths() checks that
-        // the getParent() calls return as expected, from the table
-        public static void CheckPaths(TaxonomyWriter tw)
-        {
-            for (int i = 0; i < categories.Length; i++)
-            {
-                int ordinal = ExpectedPaths[i][ExpectedPaths[i].Length - 1];
-                for (int j = ExpectedPaths[i].Length - 2; j >= 0; j--)
-                {
-                    ordinal = tw.GetParent(ordinal);
-                    int expectedOrdinal = ExpectedPaths[i][j];
-                    if (ordinal != expectedOrdinal)
-                    {
-                        Fail("For category " + Showcat(categories[i]) + " expected ancestor level " + (ExpectedPaths[i].Length - 1 - j) + " was " + expectedOrdinal + ", but got " + ordinal);
-                    }
-                }
-                Assert.AreEqual(TaxonomyReader.ROOT_ORDINAL, tw.GetParent(ExpectedPaths[i][0]));
-            }
-            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tw.GetParent(TaxonomyReader.ROOT_ORDINAL));
-        }
-
-        /// <summary>
-        /// Basic test for TaxonomyWriter.getParent(). This is similar to testWriter
-        /// above, except we also check the parents of the added categories, not just
-        /// the categories themselves.
-        /// </summary>
-        [Test]
-        public virtual void TestWriterCheckPaths()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            FillTaxonomyCheckPaths(tw);
-            // Also check TaxonomyWriter.getSize() - see that the taxonomy's size
-            // is what we expect it to be.
-            Assert.AreEqual(ExpectedCategories.Length, tw.Size);
-            tw.Dispose();
-            indexDir.Dispose();
-        }
-
-        /// <summary>
-        /// testWriterCheckPaths2 is the path-checking variant of testWriterTwice
-        /// and testWriterTwice2. After adding all the categories, we add them again,
-        /// and see that we get the same old ids and paths. We repeat the path checking
-        /// yet again after closing and opening the index for writing again - to see
-        /// that the reading of existing data from disk works as well.
-        /// </summary>
-        [Test]
-        public virtual void TestWriterCheckPaths2()
-        {
-            var indexDir = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(indexDir);
-            FillTaxonomy(tw);
-            CheckPaths(tw);
-            FillTaxonomy(tw);
-            CheckPaths(tw);
-            tw.Dispose();
-
-            tw = new DirectoryTaxonomyWriter(indexDir);
-            CheckPaths(tw);
-            FillTaxonomy(tw);
-            CheckPaths(tw);
-            tw.Dispose();
-            indexDir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestNrt()
-        {
-            var dir = NewDirectory();
-            var writer = new DirectoryTaxonomyWriter(dir);
-            var reader = new DirectoryTaxonomyReader(writer);
-
-            FacetLabel cp = new FacetLabel("a");
-            writer.AddCategory(cp);
-            var newReader = TaxonomyReader.OpenIfChanged(reader);
-            Assert.NotNull(newReader, "expected a new instance");
-            Assert.AreEqual(2, newReader.Size);
-            Assert.AreNotSame(TaxonomyReader.INVALID_ORDINAL, newReader.GetOrdinal(cp));
-            reader.Dispose();
-            reader = newReader;
-
-            writer.Dispose();
-            reader.Dispose();
-
-            dir.Dispose();
-        }
-
-        //  TODO (Facet): test multiple readers, one writer. Have the multiple readers
-        //  using the same object (simulating threads) or different objects
-        //  (simulating processes).
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyFacetAssociations.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyFacetAssociations.cs b/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyFacetAssociations.cs
deleted file mode 100644
index 06057ce..0000000
--- a/src/Lucene.Net.Tests/core/Facet/Taxonomy/TestTaxonomyFacetAssociations.cs
+++ /dev/null
@@ -1,278 +0,0 @@
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet.Taxonomy
-{
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-
-    using Document = Lucene.Net.Documents.Document;
-    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
-    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
-    using IndexReader = Lucene.Net.Index.IndexReader;
-    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
-    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
-    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
-    using Directory = Lucene.Net.Store.Directory;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-
-    /// <summary>
-    /// Test for associations 
-    /// </summary>
-    [TestFixture]
-    public class TestTaxonomyFacetAssociations : FacetTestCase
-    {
-
-        private static Store.Directory dir;
-        private static IndexReader reader;
-        private static Store.Directory taxoDir;
-        private static TaxonomyReader taxoReader;
-
-        private static FacetsConfig config;
-
-
-        [TestFixtureSetUp]
-        public static void BeforeClass()
-        {
-            dir = NewDirectory();
-            taxoDir = NewDirectory();
-            // preparations - index, taxonomy, content
-
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-
-            // Cannot mix ints & floats in the same indexed field:
-            config = new FacetsConfig();
-            config.SetIndexFieldName("int", "$facets.int");
-            config.SetMultiValued("int", true);
-            config.SetIndexFieldName("float", "$facets.float");
-            config.SetMultiValued("float", true);
-
-            var writer = new RandomIndexWriter(Random(), dir);
-
-            // index documents, 50% have only 'b' and all have 'a'
-            for (int i = 0; i < 110; i++)
-            {
-                Document doc = new Document();
-                // every 11th document is added empty, this used to cause the association
-                // aggregators to go into an infinite loop
-                if (i % 11 != 0)
-                {
-                    doc.Add(new IntAssociationFacetField(2, "int", "a"));
-                    doc.Add(new FloatAssociationFacetField(0.5f, "float", "a"));
-                    if (i % 2 == 0) // 50
-                    {
-                        doc.Add(new IntAssociationFacetField(3, "int", "b"));
-                        doc.Add(new FloatAssociationFacetField(0.2f, "float", "b"));
-                    }
-                }
-                writer.AddDocument(config.Build(taxoWriter, doc));
-            }
-
-            taxoWriter.Dispose();
-            reader = writer.Reader;
-            writer.Dispose();
-            taxoReader = new DirectoryTaxonomyReader(taxoDir);
-        }
-
-        [TestFixtureTearDown]
-        public static void AfterClass()
-        {
-            reader.Dispose();
-            reader = null;
-            dir.Dispose();
-            dir = null;
-            taxoReader.Dispose(true);
-            taxoReader = null;
-            taxoDir.Dispose();
-            taxoDir = null;
-        }
-
-        [Test]
-        public virtual void TestIntSumAssociation()
-        {
-
-            FacetsCollector fc = new FacetsCollector();
-
-            IndexSearcher searcher = NewSearcher(reader);
-            searcher.Search(new MatchAllDocsQuery(), fc);
-
-            Facets facets = new TaxonomyFacetSumIntAssociations("$facets.int", taxoReader, config, fc);
-            Assert.AreEqual("dim=int path=[] value=-1 childCount=2\n  a (200)\n  b (150)\n", facets.GetTopChildren(10, "int").ToString());
-            Assert.AreEqual(200, (int)facets.GetSpecificValue("int", "a"), "Wrong count for category 'a'!");
-            Assert.AreEqual(150, (int)facets.GetSpecificValue("int", "b"), "Wrong count for category 'b'!");
-        }
-
-        [Test]
-        public virtual void TestFloatSumAssociation()
-        {
-            FacetsCollector fc = new FacetsCollector();
-
-            IndexSearcher searcher = NewSearcher(reader);
-            searcher.Search(new MatchAllDocsQuery(), fc);
-
-            Facets facets = new TaxonomyFacetSumFloatAssociations("$facets.float", taxoReader, config, fc);
-            Assert.AreEqual("dim=float path=[] value=-1.0 childCount=2\n  a (50.0)\n  b (9.999995)\n", facets.GetTopChildren(10, "float").ToString());
-            Assert.AreEqual(50f, (float)facets.GetSpecificValue("float", "a"), 0.00001, "Wrong count for category 'a'!");
-            Assert.AreEqual(10f, (float)facets.GetSpecificValue("float", "b"), 0.00001, "Wrong count for category 'b'!");
-        }
-
-        /// <summary>
-        /// Make sure we can test both int and float assocs in one
-        ///  index, as long as we send each to a different field. 
-        /// </summary>
-        [Test]
-        public virtual void TestIntAndFloatAssocation()
-        {
-            FacetsCollector fc = new FacetsCollector();
-
-            IndexSearcher searcher = NewSearcher(reader);
-            searcher.Search(new MatchAllDocsQuery(), fc);
-
-            Facets facets = new TaxonomyFacetSumFloatAssociations("$facets.float", taxoReader, config, fc);
-            Assert.AreEqual(50f, (float)facets.GetSpecificValue("float", "a"), 0.00001, "Wrong count for category 'a'!");
-            Assert.AreEqual(10f, (float)facets.GetSpecificValue("float", "b"), 0.00001, "Wrong count for category 'b'!");
-
-            facets = new TaxonomyFacetSumIntAssociations("$facets.int", taxoReader, config, fc);
-            Assert.AreEqual(200, (int)facets.GetSpecificValue("int", "a"), "Wrong count for category 'a'!");
-            Assert.AreEqual(150, (int)facets.GetSpecificValue("int", "b"), "Wrong count for category 'b'!");
-        }
-
-        
-        [Test]
-        public virtual void TestWrongIndexFieldName()
-        {
-            FacetsCollector fc = new FacetsCollector();
-
-            IndexSearcher searcher = NewSearcher(reader);
-            searcher.Search(new MatchAllDocsQuery(), fc);
-            Facets facets = new TaxonomyFacetSumFloatAssociations(taxoReader, config, fc);
-            try
-            {
-                facets.GetSpecificValue("float");
-                Fail("should have hit exc");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-
-            try
-            {
-                facets.GetTopChildren(10, "float");
-                Fail("should have hit exc");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-        }
-
-        [Test]
-        public virtual void TestMixedTypesInSameIndexField()
-        {
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            FacetsConfig config = new FacetsConfig();
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            Document doc = new Document();
-            doc.Add(new IntAssociationFacetField(14, "a", "x"));
-            doc.Add(new FloatAssociationFacetField(55.0f, "b", "y"));
-            try
-            {
-                writer.AddDocument(config.Build(taxoWriter, doc));
-                Fail("did not hit expected exception");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            IOUtils.Close(writer, taxoWriter, dir, taxoDir);
-        }
-
-        [Test]
-        public virtual void TestNoHierarchy()
-        {
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            FacetsConfig config = new FacetsConfig();
-            config.SetHierarchical("a", true);
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            Document doc = new Document();
-            doc.Add(new IntAssociationFacetField(14, "a", "x"));
-            try
-            {
-                writer.AddDocument(config.Build(taxoWriter, doc));
-                Fail("did not hit expected exception");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            IOUtils.Close(writer, taxoWriter, dir, taxoDir);
-        }
-
-        [Test]
-        public virtual void TestRequireDimCount()
-        {
-            Store.Directory dir = NewDirectory();
-            Store.Directory taxoDir = NewDirectory();
-
-            TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            FacetsConfig config = new FacetsConfig();
-            config.SetRequireDimCount("a", true);
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            Document doc = new Document();
-            doc.Add(new IntAssociationFacetField(14, "a", "x"));
-            try
-            {
-                writer.AddDocument(config.Build(taxoWriter, doc));
-                Fail("did not hit expected exception");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            IOUtils.Close(writer, taxoWriter, dir, taxoDir);
-        }
-
-        [Test]
-        public virtual void TestIntSumAssociationDrillDown()
-        {
-            FacetsCollector fc = new FacetsCollector();
-
-            IndexSearcher searcher = NewSearcher(reader);
-            DrillDownQuery q = new DrillDownQuery(config);
-            q.Add("int", "b");
-            searcher.Search(q, fc);
-
-            Facets facets = new TaxonomyFacetSumIntAssociations("$facets.int", taxoReader, config, fc);
-            Assert.AreEqual("dim=int path=[] value=-1 childCount=2\n  b (150)\n  a (100)\n", facets.GetTopChildren(10, "int").ToString());
-            Assert.AreEqual(100, (int)facets.GetSpecificValue("int", "a"), "Wrong count for category 'a'!");
-            Assert.AreEqual(150, (int)facets.GetSpecificValue("int", "b"), "Wrong count for category 'b'!");
-        }
-
-    }
-
-}
\ No newline at end of file


[06/14] lucenenet git commit: Moving Lucene.Net.Facet tests to their appropriate place

Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/Range/TestRangeFacetCounts.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/Range/TestRangeFacetCounts.cs b/src/Lucene.Net.Tests/core/Facet/Range/TestRangeFacetCounts.cs
deleted file mode 100644
index bb09c43..0000000
--- a/src/Lucene.Net.Tests/core/Facet/Range/TestRangeFacetCounts.cs
+++ /dev/null
@@ -1,1174 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.Collections;
-using System.Collections.Generic;
-using Lucene.Net.Facet.Range;
-using Lucene.Net.Randomized.Generators;
-using Lucene.Net.Support;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet.Range
-{
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-
-    using Document = Lucene.Net.Documents.Document;
-    using DoubleDocValuesField = Lucene.Net.Documents.DoubleDocValuesField;
-    using DoubleField = Lucene.Net.Documents.DoubleField;
-    using Field = Lucene.Net.Documents.Field;
-    using FloatDocValuesField = Lucene.Net.Documents.FloatDocValuesField;
-    using FloatField = Lucene.Net.Documents.FloatField;
-    using LongField = Lucene.Net.Documents.LongField;
-    using NumericDocValuesField = Lucene.Net.Documents.NumericDocValuesField;
-    using DrillSidewaysResult = Lucene.Net.Facet.DrillSideways.DrillSidewaysResult;
-    using TaxonomyReader = Lucene.Net.Facet.Taxonomy.TaxonomyReader;
-    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
-    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
-    using AtomicReader = Lucene.Net.Index.AtomicReader;
-    using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
-    using IndexReader = Lucene.Net.Index.IndexReader;
-    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
-    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
-    using FunctionValues = Lucene.Net.Queries.Function.FunctionValues;
-    using ValueSource = Lucene.Net.Queries.Function.ValueSource;
-    using DoubleDocValues = Lucene.Net.Queries.Function.DocValues.DoubleDocValues;
-    using DoubleFieldSource = Lucene.Net.Queries.Function.ValueSources.DoubleFieldSource;
-    using FloatFieldSource = Lucene.Net.Queries.Function.ValueSources.FloatFieldSource;
-    using LongFieldSource = Lucene.Net.Queries.Function.ValueSources.LongFieldSource;
-    using CachingWrapperFilter = Lucene.Net.Search.CachingWrapperFilter;
-    using DocIdSet = Lucene.Net.Search.DocIdSet;
-    using DocIdSetIterator = Lucene.Net.Search.DocIdSetIterator;
-    using Filter = Lucene.Net.Search.Filter;
-    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
-    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
-    using Lucene.Net.Search;
-    using QueryWrapperFilter = Lucene.Net.Search.QueryWrapperFilter;
-    using Directory = Lucene.Net.Store.Directory;
-    using FixedBitSet = Lucene.Net.Util.FixedBitSet;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-    using TestUtil = Lucene.Net.Util.TestUtil;
-
-    [TestFixture]
-    public class TestRangeFacetCounts : FacetTestCase
-    {
-
-        [Test]
-        public virtual void TestBasicLong()
-        {
-            Directory d = NewDirectory();
-            RandomIndexWriter w = new RandomIndexWriter(Random(), d);
-            Document doc = new Document();
-            NumericDocValuesField field = new NumericDocValuesField("field", 0L);
-            doc.Add(field);
-            for (long l = 0; l < 100; l++)
-            {
-                field.LongValue = l;
-                w.AddDocument(doc);
-            }
-
-            // Also add Long.MAX_VALUE
-            field.LongValue = long.MaxValue;
-            w.AddDocument(doc);
-
-            IndexReader r = w.Reader;
-            w.Dispose();
-
-            FacetsCollector fc = new FacetsCollector();
-            IndexSearcher s = NewSearcher(r);
-            s.Search(new MatchAllDocsQuery(), fc);
-
-            Facets facets = new LongRangeFacetCounts("field", fc, new LongRange("less than 10", 0L, true, 10L, false), new LongRange("less than or equal to 10", 0L, true, 10L, true), new LongRange("over 90", 90L, false, 100L, false), new LongRange("90 or above", 90L, true, 100L, false), new LongRange("over 1000", 1000L, false, long.MaxValue, true));
-
-            FacetResult result = facets.GetTopChildren(10, "field");
-
-            Assert.AreEqual("dim=field path=[] value=22 childCount=5\n  less than 10 (10)\n  less than or equal to 10 (11)\n  over 90 (9)\n  90 or above (10)\n  over 1000 (1)\n", result.ToString());
-
-            r.Dispose();
-            d.Dispose();
-        }
-
-        [Test]
-        public virtual void TestUselessRange()
-        {
-            try
-            {
-                new LongRange("useless", 7, true, 6, true);
-                Fail("did not hit expected exception");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            try
-            {
-                new LongRange("useless", 7, true, 7, false);
-                Fail("did not hit expected exception");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            try
-            {
-                new DoubleRange("useless", 7.0, true, 6.0, true);
-                Fail("did not hit expected exception");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-            try
-            {
-                new DoubleRange("useless", 7.0, true, 7.0, false);
-                Fail("did not hit expected exception");
-            }
-            catch (System.ArgumentException)
-            {
-                // expected
-            }
-        }
-
-        [Test]
-        public virtual void TestLongMinMax()
-        {
-
-            Directory d = NewDirectory();
-            RandomIndexWriter w = new RandomIndexWriter(Random(), d);
-            Document doc = new Document();
-            NumericDocValuesField field = new NumericDocValuesField("field", 0L);
-            doc.Add(field);
-            field.LongValue = long.MinValue;
-            w.AddDocument(doc);
-            field.LongValue = 0;
-            w.AddDocument(doc);
-            field.LongValue = long.MaxValue;
-            w.AddDocument(doc);
-
-            IndexReader r = w.Reader;
-            w.Dispose();
-
-            FacetsCollector fc = new FacetsCollector();
-            IndexSearcher s = NewSearcher(r);
-            s.Search(new MatchAllDocsQuery(), fc);
-
-            Facets facets = new LongRangeFacetCounts("field", fc, new LongRange("min", long.MinValue, true, long.MinValue, true), new LongRange("max", long.MaxValue, true, long.MaxValue, true), new LongRange("all0", long.MinValue, true, long.MaxValue, true), new LongRange("all1", long.MinValue, false, long.MaxValue, true), new LongRange("all2", long.MinValue, true, long.MaxValue, false), new LongRange("all3", long.MinValue, false, long.MaxValue, false));
-
-            FacetResult result = facets.GetTopChildren(10, "field");
-            Assert.AreEqual("dim=field path=[] value=3 childCount=6\n  min (1)\n  max (1)\n  all0 (3)\n  all1 (2)\n  all2 (2)\n  all3 (1)\n", result.ToString());
-
-            r.Dispose();
-            d.Dispose();
-        }
-
-        [Test]
-        public virtual void TestOverlappedEndStart()
-        {
-            Directory d = NewDirectory();
-            var w = new RandomIndexWriter(Random(), d);
-            Document doc = new Document();
-            NumericDocValuesField field = new NumericDocValuesField("field", 0L);
-            doc.Add(field);
-            for (long l = 0; l < 100; l++)
-            {
-                field.LongValue = l;
-                w.AddDocument(doc);
-            }
-            field.LongValue = long.MaxValue;
-            w.AddDocument(doc);
-
-            IndexReader r = w.Reader;
-            w.Dispose();
-
-            FacetsCollector fc = new FacetsCollector();
-            IndexSearcher s = NewSearcher(r);
-            s.Search(new MatchAllDocsQuery(), fc);
-
-            Facets facets = new LongRangeFacetCounts("field", fc, new LongRange("0-10", 0L, true, 10L, true), new LongRange("10-20", 10L, true, 20L, true), new LongRange("20-30", 20L, true, 30L, true), new LongRange("30-40", 30L, true, 40L, true));
-
-            FacetResult result = facets.GetTopChildren(10, "field");
-            Assert.AreEqual("dim=field path=[] value=41 childCount=4\n  0-10 (11)\n  10-20 (11)\n  20-30 (11)\n  30-40 (11)\n", result.ToString());
-
-            r.Dispose();
-            d.Dispose();
-        }
-
-        /// <summary>
-        /// Tests single request that mixes Range and non-Range
-        ///  faceting, with DrillSideways and taxonomy. 
-        /// </summary>
-        [Test]
-        public virtual void TestMixedRangeAndNonRangeTaxonomy()
-        {
-            Directory d = NewDirectory();
-            RandomIndexWriter w = new RandomIndexWriter(Random(), d);
-            Directory td = NewDirectory();
-            DirectoryTaxonomyWriter tw = new DirectoryTaxonomyWriter(td, IndexWriterConfig.OpenMode_e.CREATE);
-
-            FacetsConfig config = new FacetsConfig();
-
-            for (long l = 0; l < 100; l++)
-            {
-                Document doc = new Document();
-                // For computing range facet counts:
-                doc.Add(new NumericDocValuesField("field", l));
-                // For drill down by numeric range:
-                doc.Add(new LongField("field", l, Field.Store.NO));
-
-                if ((l & 3) == 0)
-                {
-                    doc.Add(new FacetField("dim", "a"));
-                }
-                else
-                {
-                    doc.Add(new FacetField("dim", "b"));
-                }
-                w.AddDocument(config.Build(tw, doc));
-            }
-
-            IndexReader r = w.Reader;
-
-            var tr = new DirectoryTaxonomyReader(tw);
-
-            IndexSearcher s = NewSearcher(r);
-
-            if (VERBOSE)
-            {
-                Console.WriteLine("TEST: searcher=" + s);
-            }
-
-            DrillSideways ds = new DrillSidewaysAnonymousInnerClassHelper(this, s, config, tr);
-
-            // First search, no drill downs:
-            DrillDownQuery ddq = new DrillDownQuery(config);
-            DrillSidewaysResult dsr = ds.Search(null, ddq, 10);
-
-            Assert.AreEqual(100, dsr.Hits.TotalHits);
-            Assert.AreEqual("dim=dim path=[] value=100 childCount=2\n  b (75)\n  a (25)\n", dsr.Facets.GetTopChildren(10, "dim").ToString());
-            Assert.AreEqual("dim=field path=[] value=21 childCount=5\n  less than 10 (10)\n  less than or equal to 10 (11)\n  over 90 (9)\n  90 or above (10)\n  over 1000 (0)\n", dsr.Facets.GetTopChildren(10, "field").ToString());
-
-            // Second search, drill down on dim=b:
-            ddq = new DrillDownQuery(config);
-            ddq.Add("dim", "b");
-            dsr = ds.Search(null, ddq, 10);
-
-            Assert.AreEqual(75, dsr.Hits.TotalHits);
-            Assert.AreEqual("dim=dim path=[] value=100 childCount=2\n  b (75)\n  a (25)\n", dsr.Facets.GetTopChildren(10, "dim").ToString());
-            Assert.AreEqual("dim=field path=[] value=16 childCount=5\n  less than 10 (7)\n  less than or equal to 10 (8)\n  over 90 (7)\n  90 or above (8)\n  over 1000 (0)\n", dsr.Facets.GetTopChildren(10, "field").ToString());
-
-            // Third search, drill down on "less than or equal to 10":
-            ddq = new DrillDownQuery(config);
-            ddq.Add("field", NumericRangeQuery.NewLongRange("field", 0L, 10L, true, true));
-            dsr = ds.Search(null, ddq, 10);
-
-            Assert.AreEqual(11, dsr.Hits.TotalHits);
-            Assert.AreEqual("dim=dim path=[] value=11 childCount=2\n  b (8)\n  a (3)\n", dsr.Facets.GetTopChildren(10, "dim").ToString());
-            Assert.AreEqual("dim=field path=[] value=21 childCount=5\n  less than 10 (10)\n  less than or equal to 10 (11)\n  over 90 (9)\n  90 or above (10)\n  over 1000 (0)\n", dsr.Facets.GetTopChildren(10, "field").ToString());
-            IOUtils.Close(tw, tr, td, w, r, d);
-        }
-
-        private class DrillSidewaysAnonymousInnerClassHelper : DrillSideways
-        {
-            private readonly TestRangeFacetCounts outerInstance;
-
-            private new FacetsConfig config;
-
-            public DrillSidewaysAnonymousInnerClassHelper(TestRangeFacetCounts outerInstance, IndexSearcher s, FacetsConfig config, TaxonomyReader tr)
-                : base(s, config, tr)
-            {
-                this.outerInstance = outerInstance;
-                this.config = config;
-            }
-
-            protected override Facets BuildFacetsResult(FacetsCollector drillDowns, FacetsCollector[] drillSideways, string[] drillSidewaysDims)
-            {
-                FacetsCollector dimFC = drillDowns;
-                FacetsCollector fieldFC = drillDowns;
-                if (drillSideways != null)
-                {
-                    for (int i = 0; i < drillSideways.Length; i++)
-                    {
-                        string dim = drillSidewaysDims[i];
-                        if (dim.Equals("field"))
-                        {
-                            fieldFC = drillSideways[i];
-                        }
-                        else
-                        {
-                            dimFC = drillSideways[i];
-                        }
-                    }
-                }
-
-                IDictionary<string, Facets> byDim = new Dictionary<string, Facets>();
-                byDim["field"] = new LongRangeFacetCounts("field", fieldFC, new LongRange("less than 10", 0L, true, 10L, false), new LongRange("less than or equal to 10", 0L, true, 10L, true), new LongRange("over 90", 90L, false, 100L, false), new LongRange("90 or above", 90L, true, 100L, false), new LongRange("over 1000", 1000L, false, long.MaxValue, false));
-                byDim["dim"] = outerInstance.GetTaxonomyFacetCounts(taxoReader, config, dimFC);
-                return new MultiFacets(byDim, null);
-            }
-
-            protected override bool ScoreSubDocsAtOnce()
-            {
-                return Random().NextBoolean();
-            }
-        }
-
-        [Test]
-        public virtual void TestBasicDouble()
-        {
-            Directory d = NewDirectory();
-            RandomIndexWriter w = new RandomIndexWriter(Random(), d);
-            Document doc = new Document();
-            DoubleDocValuesField field = new DoubleDocValuesField("field", 0.0);
-            doc.Add(field);
-            for (long l = 0; l < 100; l++)
-            {
-                field.DoubleValue = l;
-                w.AddDocument(doc);
-            }
-
-            IndexReader r = w.Reader;
-
-            FacetsCollector fc = new FacetsCollector();
-
-            IndexSearcher s = NewSearcher(r);
-            s.Search(new MatchAllDocsQuery(), fc);
-            Facets facets = new DoubleRangeFacetCounts("field", fc, new DoubleRange("less than 10", 0.0, true, 10.0, false), new DoubleRange("less than or equal to 10", 0.0, true, 10.0, true), new DoubleRange("over 90", 90.0, false, 100.0, false), new DoubleRange("90 or above", 90.0, true, 100.0, false), new DoubleRange("over 1000", 1000.0, false, double.PositiveInfinity, false));
-
-            Assert.AreEqual("dim=field path=[] value=21 childCount=5\n  less than 10 (10)\n  less than or equal to 10 (11)\n  over 90 (9)\n  90 or above (10)\n  over 1000 (0)\n", facets.GetTopChildren(10, "field").ToString());
-
-            IOUtils.Close(w, r, d);
-        }
-
-        [Test]
-        public virtual void TestBasicFloat()
-        {
-            Directory d = NewDirectory();
-            RandomIndexWriter w = new RandomIndexWriter(Random(), d);
-            Document doc = new Document();
-            FloatDocValuesField field = new FloatDocValuesField("field", 0.0f);
-            doc.Add(field);
-            for (long l = 0; l < 100; l++)
-            {
-                field.FloatValue = l;
-                w.AddDocument(doc);
-            }
-
-            IndexReader r = w.Reader;
-
-            FacetsCollector fc = new FacetsCollector();
-
-            IndexSearcher s = NewSearcher(r);
-            s.Search(new MatchAllDocsQuery(), fc);
-
-            Facets facets = new DoubleRangeFacetCounts("field", new FloatFieldSource("field"), fc, new DoubleRange("less than 10", 0.0f, true, 10.0f, false), new DoubleRange("less than or equal to 10", 0.0f, true, 10.0f, true), new DoubleRange("over 90", 90.0f, false, 100.0f, false), new DoubleRange("90 or above", 90.0f, true, 100.0f, false), new DoubleRange("over 1000", 1000.0f, false, double.PositiveInfinity, false));
-
-            Assert.AreEqual("dim=field path=[] value=21 childCount=5\n  less than 10 (10)\n  less than or equal to 10 (11)\n  over 90 (9)\n  90 or above (10)\n  over 1000 (0)\n", facets.GetTopChildren(10, "field").ToString());
-
-            IOUtils.Close(w, r, d);
-        }
-
-        [Test]
-        public virtual void TestRandomLongs()
-        {
-            Directory dir = NewDirectory();
-            var w = new RandomIndexWriter(Random(), dir);
-
-            int numDocs = AtLeast(1000);
-            if (VERBOSE)
-            {
-                Console.WriteLine("TEST: numDocs=" + numDocs);
-            }
-            long[] values = new long[numDocs];
-            long minValue = long.MaxValue;
-            long maxValue = long.MinValue;
-            for (int i = 0; i < numDocs; i++)
-            {
-                Document doc = new Document();
-                long v = Random().NextLong();
-                values[i] = v;
-                doc.Add(new NumericDocValuesField("field", v));
-                doc.Add(new LongField("field", v, Field.Store.NO));
-                w.AddDocument(doc);
-                minValue = Math.Min(minValue, v);
-                maxValue = Math.Max(maxValue, v);
-            }
-            IndexReader r = w.Reader;
-
-            IndexSearcher s = NewSearcher(r);
-            FacetsConfig config = new FacetsConfig();
-
-            int numIters = AtLeast(10);
-            for (int iter = 0; iter < numIters; iter++)
-            {
-                if (VERBOSE)
-                {
-                    Console.WriteLine("TEST: iter=" + iter);
-                }
-                int numRange = TestUtil.NextInt(Random(), 1, 100);
-                LongRange[] ranges = new LongRange[numRange];
-                int[] expectedCounts = new int[numRange];
-                long minAcceptedValue = long.MaxValue;
-                long maxAcceptedValue = long.MinValue;
-                for (int rangeID = 0; rangeID < numRange; rangeID++)
-                {
-                    long min;
-                    if (rangeID > 0 && Random().Next(10) == 7)
-                    {
-                        // Use an existing boundary:
-                        LongRange prevRange = ranges[Random().Next(rangeID)];
-                        if (Random().NextBoolean())
-                        {
-                            min = prevRange.min;
-                        }
-                        else
-                        {
-                            min = prevRange.max;
-                        }
-                    }
-                    else
-                    {
-                        min = Random().NextLong();
-                    }
-                    long max;
-                    if (rangeID > 0 && Random().Next(10) == 7)
-                    {
-                        // Use an existing boundary:
-                        LongRange prevRange = ranges[Random().Next(rangeID)];
-                        if (Random().NextBoolean())
-                        {
-                            max = prevRange.min;
-                        }
-                        else
-                        {
-                            max = prevRange.max;
-                        }
-                    }
-                    else
-                    {
-                        max = Random().NextLong();
-                    }
-
-                    if (min > max)
-                    {
-                        long x = min;
-                        min = max;
-                        max = x;
-                    }
-                    bool minIncl;
-                    bool maxIncl;
-                    if (min == max)
-                    {
-                        minIncl = true;
-                        maxIncl = true;
-                    }
-                    else
-                    {
-                        minIncl = Random().NextBoolean();
-                        maxIncl = Random().NextBoolean();
-                    }
-                    ranges[rangeID] = new LongRange("r" + rangeID, min, minIncl, max, maxIncl);
-                    if (VERBOSE)
-                    {
-                        Console.WriteLine("  range " + rangeID + ": " + ranges[rangeID]);
-                    }
-
-                    // Do "slow but hopefully correct" computation of
-                    // expected count:
-                    for (int i = 0; i < numDocs; i++)
-                    {
-                        bool accept = true;
-                        if (minIncl)
-                        {
-                            accept &= values[i] >= min;
-                        }
-                        else
-                        {
-                            accept &= values[i] > min;
-                        }
-                        if (maxIncl)
-                        {
-                            accept &= values[i] <= max;
-                        }
-                        else
-                        {
-                            accept &= values[i] < max;
-                        }
-                        if (accept)
-                        {
-                            expectedCounts[rangeID]++;
-                            minAcceptedValue = Math.Min(minAcceptedValue, values[i]);
-                            maxAcceptedValue = Math.Max(maxAcceptedValue, values[i]);
-                        }
-                    }
-                }
-
-                FacetsCollector sfc = new FacetsCollector();
-                s.Search(new MatchAllDocsQuery(), sfc);
-                Filter fastMatchFilter;
-                if (Random().NextBoolean())
-                {
-                    if (Random().NextBoolean())
-                    {
-                        fastMatchFilter = NumericRangeFilter.NewLongRange("field", minValue, maxValue, true, true);
-                    }
-                    else
-                    {
-                        fastMatchFilter = NumericRangeFilter.NewLongRange("field", minAcceptedValue, maxAcceptedValue, true, true);
-                    }
-                }
-                else
-                {
-                    fastMatchFilter = null;
-                }
-                ValueSource vs = new LongFieldSource("field");
-                Facets facets = new LongRangeFacetCounts("field", vs, sfc, fastMatchFilter, ranges);
-                FacetResult result = facets.GetTopChildren(10, "field");
-                Assert.AreEqual(numRange, result.LabelValues.Length);
-                for (int rangeID = 0; rangeID < numRange; rangeID++)
-                {
-                    if (VERBOSE)
-                    {
-                        Console.WriteLine("  range " + rangeID + " expectedCount=" + expectedCounts[rangeID]);
-                    }
-                    LabelAndValue subNode = result.LabelValues[rangeID];
-                    Assert.AreEqual("r" + rangeID, subNode.label);
-                    Assert.AreEqual(expectedCounts[rangeID], (int)subNode.value);
-
-                    LongRange range = ranges[rangeID];
-
-                    // Test drill-down:
-                    DrillDownQuery ddq = new DrillDownQuery(config);
-                    if (Random().NextBoolean())
-                    {
-                        if (Random().NextBoolean())
-                        {
-                            ddq.Add("field", NumericRangeFilter.NewLongRange("field", range.min, range.max, range.minInclusive, range.maxInclusive));
-                        }
-                        else
-                        {
-                            ddq.Add("field", NumericRangeQuery.NewLongRange("field", range.min, range.max, range.minInclusive, range.maxInclusive));
-                        }
-                    }
-                    else
-                    {
-                        ddq.Add("field", range.GetFilter(fastMatchFilter, vs));
-                    }
-                    Assert.AreEqual(expectedCounts[rangeID], s.Search(ddq, 10).TotalHits);
-                }
-            }
-
-            IOUtils.Close(w, r, dir);
-        }
-
-        [Test]
-        public virtual void TestRandomFloats()
-        {
-            Directory dir = NewDirectory();
-            RandomIndexWriter w = new RandomIndexWriter(Random(), dir);
-
-            int numDocs = AtLeast(1000);
-            float[] values = new float[numDocs];
-            float minValue = float.PositiveInfinity;
-            float maxValue = float.NegativeInfinity;
-            for (int i = 0; i < numDocs; i++)
-            {
-                Document doc = new Document();
-                float v = Random().NextFloat();
-                values[i] = v;
-                doc.Add(new FloatDocValuesField("field", v));
-                doc.Add(new FloatField("field", v, Field.Store.NO));
-                w.AddDocument(doc);
-                minValue = Math.Min(minValue, v);
-                maxValue = Math.Max(maxValue, v);
-            }
-            IndexReader r = w.Reader;
-
-            IndexSearcher s = NewSearcher(r);
-            FacetsConfig config = new FacetsConfig();
-
-            int numIters = AtLeast(10);
-            for (int iter = 0; iter < numIters; iter++)
-            {
-                if (VERBOSE)
-                {
-                    Console.WriteLine("TEST: iter=" + iter);
-                }
-                int numRange = TestUtil.NextInt(Random(), 1, 5);
-                DoubleRange[] ranges = new DoubleRange[numRange];
-                int[] expectedCounts = new int[numRange];
-                float minAcceptedValue = float.PositiveInfinity;
-                float maxAcceptedValue = float.NegativeInfinity;
-                if (VERBOSE)
-                {
-                    Console.WriteLine("TEST: " + numRange + " ranges");
-                }
-                for (int rangeID = 0; rangeID < numRange; rangeID++)
-                {
-                    double min;
-                    if (rangeID > 0 && Random().Next(10) == 7)
-                    {
-                        // Use an existing boundary:
-                        DoubleRange prevRange = ranges[Random().Next(rangeID)];
-                        if (Random().NextBoolean())
-                        {
-                            min = prevRange.Min;
-                        }
-                        else
-                        {
-                            min = prevRange.Max;
-                        }
-                    }
-                    else
-                    {
-                        min = Random().NextDouble();
-                    }
-                    double max;
-                    if (rangeID > 0 && Random().Next(10) == 7)
-                    {
-                        // Use an existing boundary:
-                        DoubleRange prevRange = ranges[Random().Next(rangeID)];
-                        if (Random().NextBoolean())
-                        {
-                            max = prevRange.Min;
-                        }
-                        else
-                        {
-                            max = prevRange.Max;
-                        }
-                    }
-                    else
-                    {
-                        max = Random().NextDouble();
-                    }
-
-                    if (min > max)
-                    {
-                        double x = min;
-                        min = max;
-                        max = x;
-                    }
-
-                    // Must truncate to float precision so that the
-                    // drill-down counts (which use NRQ.newFloatRange)
-                    // are correct:
-                    min = (float)min;
-                    max = (float)max;
-
-                    bool minIncl;
-                    bool maxIncl;
-                    if (min == max)
-                    {
-                        minIncl = true;
-                        maxIncl = true;
-                    }
-                    else
-                    {
-                        minIncl = Random().NextBoolean();
-                        maxIncl = Random().NextBoolean();
-                    }
-                    ranges[rangeID] = new DoubleRange("r" + rangeID, min, minIncl, max, maxIncl);
-
-                    if (VERBOSE)
-                    {
-                        Console.WriteLine("TEST:   range " + rangeID + ": " + ranges[rangeID]);
-                    }
-
-                    // Do "slow but hopefully correct" computation of
-                    // expected count:
-                    for (int i = 0; i < numDocs; i++)
-                    {
-                        bool accept = true;
-                        if (minIncl)
-                        {
-                            accept &= values[i] >= min;
-                        }
-                        else
-                        {
-                            accept &= values[i] > min;
-                        }
-                        if (maxIncl)
-                        {
-                            accept &= values[i] <= max;
-                        }
-                        else
-                        {
-                            accept &= values[i] < max;
-                        }
-                        if (VERBOSE)
-                        {
-                            Console.WriteLine("TEST:   check doc=" + i + " val=" + values[i] + " accept=" + accept);
-                        }
-                        if (accept)
-                        {
-                            expectedCounts[rangeID]++;
-                            minAcceptedValue = Math.Min(minAcceptedValue, values[i]);
-                            maxAcceptedValue = Math.Max(maxAcceptedValue, values[i]);
-                        }
-                    }
-                }
-
-                FacetsCollector sfc = new FacetsCollector();
-                s.Search(new MatchAllDocsQuery(), sfc);
-                Filter fastMatchFilter;
-                if (Random().NextBoolean())
-                {
-                    if (Random().NextBoolean())
-                    {
-                        fastMatchFilter = NumericRangeFilter.NewFloatRange("field", minValue, maxValue, true, true);
-                    }
-                    else
-                    {
-                        fastMatchFilter = NumericRangeFilter.NewFloatRange("field", minAcceptedValue, maxAcceptedValue, true, true);
-                    }
-                }
-                else
-                {
-                    fastMatchFilter = null;
-                }
-                ValueSource vs = new FloatFieldSource("field");
-                Facets facets = new DoubleRangeFacetCounts("field", vs, sfc, fastMatchFilter, ranges);
-                FacetResult result = facets.GetTopChildren(10, "field");
-                Assert.AreEqual(numRange, result.LabelValues.Length);
-                for (int rangeID = 0; rangeID < numRange; rangeID++)
-                {
-                    if (VERBOSE)
-                    {
-                        Console.WriteLine("TEST: verify range " + rangeID + " expectedCount=" + expectedCounts[rangeID]);
-                    }
-                    LabelAndValue subNode = result.LabelValues[rangeID];
-                    Assert.AreEqual("r" + rangeID, subNode.label);
-                    Assert.AreEqual(expectedCounts[rangeID], (int)subNode.value);
-
-                    DoubleRange range = ranges[rangeID];
-
-                    // Test drill-down:
-                    DrillDownQuery ddq = new DrillDownQuery(config);
-                    if (Random().NextBoolean())
-                    {
-                        if (Random().NextBoolean())
-                        {
-                            ddq.Add("field", NumericRangeFilter.NewFloatRange("field", (float)range.Min, (float)range.Max, range.MinInclusive, range.MaxInclusive));
-                        }
-                        else
-                        {
-                            ddq.Add("field", NumericRangeQuery.NewFloatRange("field", (float)range.Min, (float)range.Max, range.MinInclusive, range.MaxInclusive));
-                        }
-                    }
-                    else
-                    {
-                        ddq.Add("field", range.GetFilter(fastMatchFilter, vs));
-                    }
-                    Assert.AreEqual(expectedCounts[rangeID], s.Search(ddq, 10).TotalHits);
-                }
-            }
-
-            IOUtils.Close(w, r, dir);
-        }
-
-        [Test]
-        public virtual void TestRandomDoubles()
-        {
-            Directory dir = NewDirectory();
-            RandomIndexWriter w = new RandomIndexWriter(Random(), dir);
-
-            int numDocs = AtLeast(1000);
-            double[] values = new double[numDocs];
-            double minValue = double.PositiveInfinity;
-            double maxValue = double.NegativeInfinity;
-            for (int i = 0; i < numDocs; i++)
-            {
-                Document doc = new Document();
-                double v = Random().NextDouble();
-                values[i] = v;
-                doc.Add(new DoubleDocValuesField("field", v));
-                doc.Add(new DoubleField("field", v, Field.Store.NO));
-                w.AddDocument(doc);
-                minValue = Math.Min(minValue, v);
-                maxValue = Math.Max(maxValue, v);
-            }
-            IndexReader r = w.Reader;
-
-            IndexSearcher s = NewSearcher(r);
-            FacetsConfig config = new FacetsConfig();
-
-            int numIters = AtLeast(10);
-            for (int iter = 0; iter < numIters; iter++)
-            {
-                if (VERBOSE)
-                {
-                    Console.WriteLine("TEST: iter=" + iter);
-                }
-                int numRange = TestUtil.NextInt(Random(), 1, 5);
-                DoubleRange[] ranges = new DoubleRange[numRange];
-                int[] expectedCounts = new int[numRange];
-                double minAcceptedValue = double.PositiveInfinity;
-                double maxAcceptedValue = double.NegativeInfinity;
-                for (int rangeID = 0; rangeID < numRange; rangeID++)
-                {
-                    double min;
-                    if (rangeID > 0 && Random().Next(10) == 7)
-                    {
-                        // Use an existing boundary:
-                        DoubleRange prevRange = ranges[Random().Next(rangeID)];
-                        if (Random().NextBoolean())
-                        {
-                            min = prevRange.Min;
-                        }
-                        else
-                        {
-                            min = prevRange.Max;
-                        }
-                    }
-                    else
-                    {
-                        min = Random().NextDouble();
-                    }
-                    double max;
-                    if (rangeID > 0 && Random().Next(10) == 7)
-                    {
-                        // Use an existing boundary:
-                        DoubleRange prevRange = ranges[Random().Next(rangeID)];
-                        if (Random().NextBoolean())
-                        {
-                            max = prevRange.Min;
-                        }
-                        else
-                        {
-                            max = prevRange.Max;
-                        }
-                    }
-                    else
-                    {
-                        max = Random().NextDouble();
-                    }
-
-                    if (min > max)
-                    {
-                        double x = min;
-                        min = max;
-                        max = x;
-                    }
-
-                    bool minIncl;
-                    bool maxIncl;
-                    if (min == max)
-                    {
-                        minIncl = true;
-                        maxIncl = true;
-                    }
-                    else
-                    {
-                        minIncl = Random().NextBoolean();
-                        maxIncl = Random().NextBoolean();
-                    }
-                    ranges[rangeID] = new DoubleRange("r" + rangeID, min, minIncl, max, maxIncl);
-
-                    // Do "slow but hopefully correct" computation of
-                    // expected count:
-                    for (int i = 0; i < numDocs; i++)
-                    {
-                        bool accept = true;
-                        if (minIncl)
-                        {
-                            accept &= values[i] >= min;
-                        }
-                        else
-                        {
-                            accept &= values[i] > min;
-                        }
-                        if (maxIncl)
-                        {
-                            accept &= values[i] <= max;
-                        }
-                        else
-                        {
-                            accept &= values[i] < max;
-                        }
-                        if (accept)
-                        {
-                            expectedCounts[rangeID]++;
-                            minAcceptedValue = Math.Min(minAcceptedValue, values[i]);
-                            maxAcceptedValue = Math.Max(maxAcceptedValue, values[i]);
-                        }
-                    }
-                }
-
-                FacetsCollector sfc = new FacetsCollector();
-                s.Search(new MatchAllDocsQuery(), sfc);
-                Filter fastMatchFilter;
-                if (Random().NextBoolean())
-                {
-                    if (Random().NextBoolean())
-                    {
-                        fastMatchFilter = NumericRangeFilter.NewDoubleRange("field", minValue, maxValue, true, true);
-                    }
-                    else
-                    {
-                        fastMatchFilter = NumericRangeFilter.NewDoubleRange("field", minAcceptedValue, maxAcceptedValue, true, true);
-                    }
-                }
-                else
-                {
-                    fastMatchFilter = null;
-                }
-                ValueSource vs = new DoubleFieldSource("field");
-                Facets facets = new DoubleRangeFacetCounts("field", vs, sfc, fastMatchFilter, ranges);
-                FacetResult result = facets.GetTopChildren(10, "field");
-                Assert.AreEqual(numRange, result.LabelValues.Length);
-                for (int rangeID = 0; rangeID < numRange; rangeID++)
-                {
-                    if (VERBOSE)
-                    {
-                        Console.WriteLine("  range " + rangeID + " expectedCount=" + expectedCounts[rangeID]);
-                    }
-                    LabelAndValue subNode = result.LabelValues[rangeID];
-                    Assert.AreEqual("r" + rangeID, subNode.label);
-                    Assert.AreEqual(expectedCounts[rangeID], (int)subNode.value);
-
-                    DoubleRange range = ranges[rangeID];
-
-                    // Test drill-down:
-                    DrillDownQuery ddq = new DrillDownQuery(config);
-                    if (Random().NextBoolean())
-                    {
-                        if (Random().NextBoolean())
-                        {
-                            ddq.Add("field", NumericRangeFilter.NewDoubleRange("field", range.Min, range.Max, range.MinInclusive, range.MaxInclusive));
-                        }
-                        else
-                        {
-                            ddq.Add("field", NumericRangeQuery.NewDoubleRange("field", range.Min, range.Max, range.MinInclusive, range.MaxInclusive));
-                        }
-                    }
-                    else
-                    {
-                        ddq.Add("field", range.GetFilter(fastMatchFilter, vs));
-                    }
-
-                    Assert.AreEqual(expectedCounts[rangeID], s.Search(ddq, 10).TotalHits);
-                }
-            }
-
-            IOUtils.Close(w, r, dir);
-        }
-
-        // LUCENE-5178
-        [Test]
-        public virtual void TestMissingValues()
-        {
-            AssumeTrue("codec does not support docsWithField", DefaultCodecSupportsDocsWithField());
-            Directory d = NewDirectory();
-            RandomIndexWriter w = new RandomIndexWriter(Random(), d);
-            Document doc = new Document();
-            NumericDocValuesField field = new NumericDocValuesField("field", 0L);
-            doc.Add(field);
-            for (long l = 0; l < 100; l++)
-            {
-                if (l % 5 == 0)
-                {
-                    // Every 5th doc is missing the value:
-                    w.AddDocument(new Document());
-                    continue;
-                }
-                field.LongValue = l;
-                w.AddDocument(doc);
-            }
-
-            IndexReader r = w.Reader;
-
-            FacetsCollector fc = new FacetsCollector();
-
-            IndexSearcher s = NewSearcher(r);
-            s.Search(new MatchAllDocsQuery(), fc);
-            Facets facets = new LongRangeFacetCounts("field", fc, new LongRange("less than 10", 0L, true, 10L, false), new LongRange("less than or equal to 10", 0L, true, 10L, true), new LongRange("over 90", 90L, false, 100L, false), new LongRange("90 or above", 90L, true, 100L, false), new LongRange("over 1000", 1000L, false, long.MaxValue, false));
-
-            Assert.AreEqual("dim=field path=[] value=16 childCount=5\n  less than 10 (8)\n  less than or equal to 10 (8)\n  over 90 (8)\n  90 or above (8)\n  over 1000 (0)\n", facets.GetTopChildren(10, "field").ToString());
-
-            IOUtils.Close(w, r, d);
-        }
-
-        [Test]
-        public virtual void TestCustomDoublesValueSource()
-        {
-            Directory dir = NewDirectory();
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            Document doc = new Document();
-            writer.AddDocument(doc);
-            writer.AddDocument(doc);
-            writer.AddDocument(doc);
-
-            // Test wants 3 docs in one segment:
-            writer.ForceMerge(1);
-
-            var vs = new ValueSourceAnonymousInnerClassHelper(this, doc);
-
-            FacetsConfig config = new FacetsConfig();
-
-            FacetsCollector fc = new FacetsCollector();
-
-            IndexReader r = writer.Reader;
-            IndexSearcher s = NewSearcher(r);
-            s.Search(new MatchAllDocsQuery(), fc);
-
-            DoubleRange[] ranges = new DoubleRange[] { new DoubleRange("< 1", 0.0, true, 1.0, false), new DoubleRange("< 2", 0.0, true, 2.0, false), new DoubleRange("< 5", 0.0, true, 5.0, false), new DoubleRange("< 10", 0.0, true, 10.0, false), new DoubleRange("< 20", 0.0, true, 20.0, false), new DoubleRange("< 50", 0.0, true, 50.0, false) };
-
-            Filter fastMatchFilter;
-            AtomicBoolean filterWasUsed = new AtomicBoolean();
-            if (Random().NextBoolean())
-            {
-                // Sort of silly:
-                fastMatchFilter = new CachingWrapperFilterAnonymousInnerClassHelper(this, new QueryWrapperFilter(new MatchAllDocsQuery()), filterWasUsed);
-            }
-            else
-            {
-                fastMatchFilter = null;
-            }
-
-            if (VERBOSE)
-            {
-                Console.WriteLine("TEST: fastMatchFilter=" + fastMatchFilter);
-            }
-
-            Facets facets = new DoubleRangeFacetCounts("field", vs, fc, fastMatchFilter, ranges);
-
-            Assert.AreEqual("dim=field path=[] value=3 childCount=6\n  < 1 (0)\n  < 2 (1)\n  < 5 (3)\n  < 10 (3)\n  < 20 (3)\n  < 50 (3)\n", facets.GetTopChildren(10, "field").ToString());
-            Assert.True(fastMatchFilter == null || filterWasUsed.Get());
-
-            DrillDownQuery ddq = new DrillDownQuery(config);
-            ddq.Add("field", ranges[1].GetFilter(fastMatchFilter, vs));
-
-            // Test simple drill-down:
-            Assert.AreEqual(1, s.Search(ddq, 10).TotalHits);
-
-            // Test drill-sideways after drill-down
-            DrillSideways ds = new DrillSidewaysAnonymousInnerClassHelper2(this, s, config, (TaxonomyReader)null, vs, ranges, fastMatchFilter);
-
-
-            DrillSidewaysResult dsr = ds.Search(ddq, 10);
-            Assert.AreEqual(1, dsr.Hits.TotalHits);
-            Assert.AreEqual("dim=field path=[] value=3 childCount=6\n  < 1 (0)\n  < 2 (1)\n  < 5 (3)\n  < 10 (3)\n  < 20 (3)\n  < 50 (3)\n", dsr.Facets.GetTopChildren(10, "field").ToString());
-
-            IOUtils.Close(r, writer, dir);
-        }
-
-        private class ValueSourceAnonymousInnerClassHelper : ValueSource
-        {
-            private readonly TestRangeFacetCounts outerInstance;
-
-            private Document doc;
-
-            public ValueSourceAnonymousInnerClassHelper(TestRangeFacetCounts outerInstance, Document doc)
-            {
-                this.outerInstance = outerInstance;
-                this.doc = doc;
-            }
-
-            public override FunctionValues GetValues(IDictionary ignored, AtomicReaderContext ignored2)
-            {
-                return new DoubleDocValuesAnonymousInnerClassHelper(this);
-            }
-
-            private class DoubleDocValuesAnonymousInnerClassHelper : DoubleDocValues
-            {
-                private readonly ValueSourceAnonymousInnerClassHelper outerInstance;
-
-                public DoubleDocValuesAnonymousInnerClassHelper(ValueSourceAnonymousInnerClassHelper outerInstance)
-                    : base(null)
-                {
-                    this.outerInstance = outerInstance;
-                }
-
-                public override double DoubleVal(int doc)
-                {
-                    return doc + 1;
-                }
-            }
-
-            public override bool Equals(object o)
-            {
-                throw new System.NotSupportedException();
-            }
-
-            public override int GetHashCode()
-            {
-                throw new System.NotSupportedException();
-            }
-
-            public override string Description
-            {
-                get { throw new NotSupportedException(); }
-            }
-
-        }
-
-        private class CachingWrapperFilterAnonymousInnerClassHelper : CachingWrapperFilter
-        {
-            private readonly TestRangeFacetCounts outerInstance;
-
-            private AtomicBoolean filterWasUsed;
-
-            public CachingWrapperFilterAnonymousInnerClassHelper(TestRangeFacetCounts outerInstance, QueryWrapperFilter org, AtomicBoolean filterWasUsed)
-                : base(org)
-            {
-                this.outerInstance = outerInstance;
-                this.filterWasUsed = filterWasUsed;
-            }
-
-            protected override DocIdSet CacheImpl(DocIdSetIterator iterator, AtomicReader reader)
-            {
-                var cached = new FixedBitSet(reader.MaxDoc);
-                filterWasUsed.Set(true);
-                cached.Or(iterator);
-                return cached;
-            }
-        }
-
-        private class DrillSidewaysAnonymousInnerClassHelper2 : DrillSideways
-        {
-            private readonly TestRangeFacetCounts outerInstance;
-
-            private ValueSource vs;
-            private Lucene.Net.Facet.Range.DoubleRange[] ranges;
-            private Filter fastMatchFilter;
-
-
-            public DrillSidewaysAnonymousInnerClassHelper2(TestRangeFacetCounts testRangeFacetCounts, IndexSearcher indexSearcher, FacetsConfig facetsConfig, TaxonomyReader org, ValueSource valueSource, DoubleRange[] doubleRanges, Filter filter)
-                : base(indexSearcher, facetsConfig, org)
-            {
-                this.outerInstance = outerInstance;
-                this.vs = valueSource;
-                this.ranges = doubleRanges;
-                this.fastMatchFilter = filter;
-            }
-
-
-            protected override Facets BuildFacetsResult(FacetsCollector drillDowns, FacetsCollector[] drillSideways, string[] drillSidewaysDims)
-            {
-                Debug.Assert(drillSideways.Length == 1);
-                return new DoubleRangeFacetCounts("field", vs, drillSideways[0], fastMatchFilter, ranges);
-            }
-
-            protected override bool ScoreSubDocsAtOnce()
-            {
-                return Random().NextBoolean();
-            }
-        }
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/SlowRAMDirectory.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/SlowRAMDirectory.cs b/src/Lucene.Net.Tests/core/Facet/SlowRAMDirectory.cs
deleted file mode 100644
index 72de557..0000000
--- a/src/Lucene.Net.Tests/core/Facet/SlowRAMDirectory.cs
+++ /dev/null
@@ -1,261 +0,0 @@
-using System;
-using System.Threading;
-using Lucene.Net.Randomized.Generators;
-
-namespace Lucene.Net.Facet
-{
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-
-    using IOContext = Lucene.Net.Store.IOContext;
-    using IndexInput = Lucene.Net.Store.IndexInput;
-    using IndexOutput = Lucene.Net.Store.IndexOutput;
-    using RAMDirectory = Lucene.Net.Store.RAMDirectory;
-    using ThreadInterruptedException = Lucene.Net.Util.ThreadInterruptedException;
-
-    /// <summary>
-    /// Test utility - slow directory
-    /// </summary>
-    // TODO: move to test-framework and sometimes use in tests?
-    public class SlowRAMDirectory : RAMDirectory
-    {
-
-        private const int IO_SLEEP_THRESHOLD = 50;
-
-        internal Random random;
-        private int sleepMillis;
-
-        public virtual int SleepMillis
-        {
-            set
-            {
-                this.sleepMillis = value;
-            }
-        }
-
-        public SlowRAMDirectory(int sleepMillis, Random random)
-        {
-            this.sleepMillis = sleepMillis;
-            this.random = random;
-        }
-
-        public override IndexOutput CreateOutput(string name, IOContext context)
-        {
-            if (sleepMillis != -1)
-            {
-                return new SlowIndexOutput(this, base.CreateOutput(name, context));
-            }
-
-            return base.CreateOutput(name, context);
-        }
-
-        public override IndexInput OpenInput(string name, IOContext context)
-        {
-            if (sleepMillis != -1)
-            {
-                return new SlowIndexInput(this, base.OpenInput(name, context));
-            }
-            return base.OpenInput(name, context);
-        }
-
-        internal virtual void doSleep(Random random, int length)
-        {
-            int sTime = length < 10 ? sleepMillis : (int)(sleepMillis * Math.Log(length));
-            if (random != null)
-            {
-                sTime = random.Next(sTime);
-            }
-            try
-            {
-                Thread.Sleep(sTime);
-            }
-            catch (ThreadInterruptedException e)
-            {
-                throw new ThreadInterruptedException(e);
-            }
-        }
-
-        /// <summary>
-        /// Make a private random. </summary>
-        internal virtual Random forkRandom()
-        {
-            if (random == null)
-            {
-                return null;
-            }
-            return new Random((int)random.NextLong());
-        }
-
-        /// <summary>
-        /// Delegate class to wrap an IndexInput and delay reading bytes by some
-        /// specified time.
-        /// </summary>
-        private class SlowIndexInput : IndexInput
-        {
-            private readonly SlowRAMDirectory outerInstance;
-
-            internal IndexInput ii;
-            internal int numRead = 0;
-            internal Random rand;
-
-            public SlowIndexInput(SlowRAMDirectory outerInstance, IndexInput ii)
-                : base("SlowIndexInput(" + ii + ")")
-            {
-                this.outerInstance = outerInstance;
-                this.rand = outerInstance.forkRandom();
-                this.ii = ii;
-            }
-
-            public override byte ReadByte()
-            {
-                if (numRead >= IO_SLEEP_THRESHOLD)
-                {
-                    outerInstance.doSleep(rand, 0);
-                    numRead = 0;
-                }
-                ++numRead;
-                return ii.ReadByte();
-            }
-
-            public override void ReadBytes(byte[] b, int offset, int len)
-            {
-                if (numRead >= IO_SLEEP_THRESHOLD)
-                {
-                    outerInstance.doSleep(rand, len);
-                    numRead = 0;
-                }
-                numRead += len;
-                ii.ReadBytes(b, offset, len);
-            }
-
-
-            // TODO: is it intentional that clone doesnt wrap?
-            public override object Clone()
-            {
-                return ii.Clone();
-            }
-
-
-            public override void Dispose()
-            {
-                ii.Dispose();
-            }
-            public override bool Equals(object o)
-            {
-                return ii.Equals(o);
-            }
-            public override long FilePointer
-            {
-                get
-                {
-                    return ii.FilePointer;
-                }
-            }
-
-            public override void Seek(long pos)
-            {
-                ii.Seek(pos);
-            }
-
-
-            public override int GetHashCode()
-            {
-                return ii.GetHashCode();
-            }
-            public override long Length()
-            {
-                return ii.Length();
-            }
-
-        }
-
-        /// <summary>
-        /// Delegate class to wrap an IndexOutput and delay writing bytes by some
-        /// specified time.
-        /// </summary>
-        private class SlowIndexOutput : IndexOutput
-        {
-            private readonly SlowRAMDirectory outerInstance;
-
-
-            internal IndexOutput io;
-            internal int numWrote;
-            internal readonly Random rand;
-
-            public SlowIndexOutput(SlowRAMDirectory outerInstance, IndexOutput io)
-            {
-                this.outerInstance = outerInstance;
-                this.io = io;
-                this.rand = outerInstance.forkRandom();
-            }
-
-            public override void WriteByte(byte b)
-            {
-                if (numWrote >= IO_SLEEP_THRESHOLD)
-                {
-                    outerInstance.doSleep(rand, 0);
-                    numWrote = 0;
-                }
-                ++numWrote;
-                io.WriteByte(b);
-            }
-
-            public override void WriteBytes(byte[] b, int offset, int length)
-            {
-                if (numWrote >= IO_SLEEP_THRESHOLD)
-                {
-                    outerInstance.doSleep(rand, length);
-                    numWrote = 0;
-                }
-                numWrote += length;
-                io.WriteBytes(b, offset, length);
-            }
-
-            public override void Dispose()
-            {
-                io.Dispose();
-            }
-            public override void Flush()
-            {
-                io.Flush();
-            }
-            public override long FilePointer
-            {
-                get
-                {
-                    return io.FilePointer;
-                }
-            }
-            public override void Seek(long pos)
-            {
-                io.Seek(pos);
-            }
-
-            public override long Checksum
-            {
-                get
-                {
-                    return io.Checksum;
-                }
-            }
-        }
-
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/SortedSet/TestSortedSetDocValuesFacets.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/SortedSet/TestSortedSetDocValuesFacets.cs b/src/Lucene.Net.Tests/core/Facet/SortedSet/TestSortedSetDocValuesFacets.cs
deleted file mode 100644
index 091a2c8..0000000
--- a/src/Lucene.Net.Tests/core/Facet/SortedSet/TestSortedSetDocValuesFacets.cs
+++ /dev/null
@@ -1,394 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using Lucene.Net.Randomized;
-using Lucene.Net.Randomized.Generators;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet.SortedSet
-{
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-
-    using Document = Lucene.Net.Documents.Document;
-    using Field = Lucene.Net.Documents.Field;
-    using IndexReader = Lucene.Net.Index.IndexReader;
-    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
-    using SlowCompositeReaderWrapper = Lucene.Net.Index.SlowCompositeReaderWrapper;
-    using Term = Lucene.Net.Index.Term;
-    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
-    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
-    using TermQuery = Lucene.Net.Search.TermQuery;
-    using TopDocs = Lucene.Net.Search.TopDocs;
-    using Directory = Lucene.Net.Store.Directory;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-    using TestUtil = Lucene.Net.Util.TestUtil;
-    
-    [TestFixture]
-    public class TestSortedSetDocValuesFacets : FacetTestCase
-    {
-
-        // NOTE: TestDrillSideways.testRandom also sometimes
-        // randomly uses SortedSetDV
-        [Test]
-        public virtual void TestBasic()
-        {
-
-            AssumeTrue("Test requires SortedSetDV support", DefaultCodecSupportsSortedSet());
-            Directory dir = NewDirectory();
-
-            FacetsConfig config = new FacetsConfig();
-            config.SetMultiValued("a", true);
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            Document doc = new Document();
-            doc.Add(new SortedSetDocValuesFacetField("a", "foo"));
-            doc.Add(new SortedSetDocValuesFacetField("a", "bar"));
-            doc.Add(new SortedSetDocValuesFacetField("a", "zoo"));
-            doc.Add(new SortedSetDocValuesFacetField("b", "baz"));
-            writer.AddDocument(config.Build(doc));
-            if (Random().NextBoolean())
-            {
-                writer.Commit();
-            }
-
-            doc = new Document();
-            doc.Add(new SortedSetDocValuesFacetField("a", "foo"));
-            writer.AddDocument(config.Build(doc));
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-
-            // Per-top-reader state:
-            SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(searcher.IndexReader);
-
-            FacetsCollector c = new FacetsCollector();
-
-            searcher.Search(new MatchAllDocsQuery(), c);
-
-            SortedSetDocValuesFacetCounts facets = new SortedSetDocValuesFacetCounts(state, c);
-
-            Assert.AreEqual("dim=a path=[] value=4 childCount=3\n  foo (2)\n  bar (1)\n  zoo (1)\n", facets.GetTopChildren(10, "a").ToString());
-            Assert.AreEqual("dim=b path=[] value=1 childCount=1\n  baz (1)\n", facets.GetTopChildren(10, "b").ToString());
-
-            // DrillDown:
-            DrillDownQuery q = new DrillDownQuery(config);
-            q.Add("a", "foo");
-            q.Add("b", "baz");
-            TopDocs hits = searcher.Search(q, 1);
-            Assert.AreEqual(1, hits.TotalHits);
-
-            IOUtils.Close(writer, searcher.IndexReader, dir);
-        }
-
-        // LUCENE-5090
-        [Test]
-        public virtual void TestStaleState()
-        {
-            AssumeTrue("Test requires SortedSetDV support", DefaultCodecSupportsSortedSet());
-            Directory dir = NewDirectory();
-
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            FacetsConfig config = new FacetsConfig();
-
-            Document doc = new Document();
-            doc.Add(new SortedSetDocValuesFacetField("a", "foo"));
-            writer.AddDocument(config.Build(doc));
-
-            IndexReader r = writer.Reader;
-            SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(r);
-
-            doc = new Document();
-            doc.Add(new SortedSetDocValuesFacetField("a", "bar"));
-            writer.AddDocument(config.Build(doc));
-
-            doc = new Document();
-            doc.Add(new SortedSetDocValuesFacetField("a", "baz"));
-            writer.AddDocument(config.Build(doc));
-
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-
-            FacetsCollector c = new FacetsCollector();
-
-            searcher.Search(new MatchAllDocsQuery(), c);
-
-            try
-            {
-                new SortedSetDocValuesFacetCounts(state, c);
-                Fail("did not hit expected exception");
-            }
-            catch (IllegalStateException)
-            {
-                // expected
-            }
-
-            r.Dispose();
-            writer.Dispose();
-            searcher.IndexReader.Dispose();
-            dir.Dispose();
-        }
-
-        // LUCENE-5333
-        [Test]
-        public virtual void TestSparseFacets()
-        {
-            AssumeTrue("Test requires SortedSetDV support", DefaultCodecSupportsSortedSet());
-            Directory dir = NewDirectory();
-
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            FacetsConfig config = new FacetsConfig();
-
-            Document doc = new Document();
-            doc.Add(new SortedSetDocValuesFacetField("a", "foo1"));
-            writer.AddDocument(config.Build(doc));
-
-            if (Random().NextBoolean())
-            {
-                writer.Commit();
-            }
-
-            doc = new Document();
-            doc.Add(new SortedSetDocValuesFacetField("a", "foo2"));
-            doc.Add(new SortedSetDocValuesFacetField("b", "bar1"));
-            writer.AddDocument(config.Build(doc));
-
-            if (Random().NextBoolean())
-            {
-                writer.Commit();
-            }
-
-            doc = new Document();
-            doc.Add(new SortedSetDocValuesFacetField("a", "foo3"));
-            doc.Add(new SortedSetDocValuesFacetField("b", "bar2"));
-            doc.Add(new SortedSetDocValuesFacetField("c", "baz1"));
-            writer.AddDocument(config.Build(doc));
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-            writer.Dispose();
-
-            // Per-top-reader state:
-            SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(searcher.IndexReader);
-
-            FacetsCollector c = new FacetsCollector();
-            searcher.Search(new MatchAllDocsQuery(), c);
-            SortedSetDocValuesFacetCounts facets = new SortedSetDocValuesFacetCounts(state, c);
-
-            // Ask for top 10 labels for any dims that have counts:
-            IList<FacetResult> results = facets.GetAllDims(10);
-
-            Assert.AreEqual(3, results.Count);
-            Assert.AreEqual("dim=a path=[] value=3 childCount=3\n  foo1 (1)\n  foo2 (1)\n  foo3 (1)\n", results[0].ToString());
-            Assert.AreEqual("dim=b path=[] value=2 childCount=2\n  bar1 (1)\n  bar2 (1)\n", results[1].ToString());
-            Assert.AreEqual("dim=c path=[] value=1 childCount=1\n  baz1 (1)\n", results[2].ToString());
-
-            searcher.IndexReader.Dispose();
-            dir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestSomeSegmentsMissing()
-        {
-            AssumeTrue("Test requires SortedSetDV support", DefaultCodecSupportsSortedSet());
-            Directory dir = NewDirectory();
-
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            FacetsConfig config = new FacetsConfig();
-
-            Document doc = new Document();
-            doc.Add(new SortedSetDocValuesFacetField("a", "foo1"));
-            writer.AddDocument(config.Build(doc));
-            writer.Commit();
-
-            doc = new Document();
-            writer.AddDocument(config.Build(doc));
-            writer.Commit();
-
-            doc = new Document();
-            doc.Add(new SortedSetDocValuesFacetField("a", "foo2"));
-            writer.AddDocument(config.Build(doc));
-            writer.Commit();
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-            writer.Dispose();
-
-            // Per-top-reader state:
-            SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(searcher.IndexReader);
-
-            FacetsCollector c = new FacetsCollector();
-            searcher.Search(new MatchAllDocsQuery(), c);
-            SortedSetDocValuesFacetCounts facets = new SortedSetDocValuesFacetCounts(state, c);
-
-            // Ask for top 10 labels for any dims that have counts:
-            Assert.AreEqual("dim=a path=[] value=2 childCount=2\n  foo1 (1)\n  foo2 (1)\n", facets.GetTopChildren(10, "a").ToString());
-
-            searcher.IndexReader.Dispose();
-            dir.Dispose();
-        }
-
-        [Test]
-        public virtual void TestSlowCompositeReaderWrapper()
-        {
-            AssumeTrue("Test requires SortedSetDV support", DefaultCodecSupportsSortedSet());
-            Directory dir = NewDirectory();
-
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            FacetsConfig config = new FacetsConfig();
-
-            Document doc = new Document();
-            doc.Add(new SortedSetDocValuesFacetField("a", "foo1"));
-            writer.AddDocument(config.Build(doc));
-
-            writer.Commit();
-
-            doc = new Document();
-            doc.Add(new SortedSetDocValuesFacetField("a", "foo2"));
-            writer.AddDocument(config.Build(doc));
-
-            // NRT open
-            IndexSearcher searcher = new IndexSearcher(SlowCompositeReaderWrapper.Wrap(writer.Reader));
-
-            // Per-top-reader state:
-            SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(searcher.IndexReader);
-
-            FacetsCollector c = new FacetsCollector();
-            searcher.Search(new MatchAllDocsQuery(), c);
-            Facets facets = new SortedSetDocValuesFacetCounts(state, c);
-
-            // Ask for top 10 labels for any dims that have counts:
-            Assert.AreEqual("dim=a path=[] value=2 childCount=2\n  foo1 (1)\n  foo2 (1)\n", facets.GetTopChildren(10, "a").ToString());
-
-            IOUtils.Close(writer, searcher.IndexReader, dir);
-        }
-
-
-        [Test]
-        public virtual void TestRandom()
-        {
-            AssumeTrue("Test requires SortedSetDV support", DefaultCodecSupportsSortedSet());
-            string[] tokens = GetRandomTokens(10);
-            Directory indexDir = NewDirectory();
-            Directory taxoDir = NewDirectory();
-
-            RandomIndexWriter w = new RandomIndexWriter(Random(), indexDir);
-            FacetsConfig config = new FacetsConfig();
-            int numDocs = AtLeast(1000);
-            int numDims = TestUtil.NextInt(Random(), 1, 7);
-            IList<TestDoc> testDocs = GetRandomDocs(tokens, numDocs, numDims);
-            foreach (TestDoc testDoc in testDocs)
-            {
-                Document doc = new Document();
-                doc.Add(NewStringField("content", testDoc.content, Field.Store.NO));
-                for (int j = 0; j < numDims; j++)
-                {
-                    if (testDoc.dims[j] != null)
-                    {
-                        doc.Add(new SortedSetDocValuesFacetField("dim" + j, testDoc.dims[j]));
-                    }
-                }
-                w.AddDocument(config.Build(doc));
-            }
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(w.Reader);
-
-            // Per-top-reader state:
-            SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(searcher.IndexReader);
-
-            int iters = AtLeast(100);
-            for (int iter = 0; iter < iters; iter++)
-            {
-                string searchToken = tokens[Random().Next(tokens.Length)];
-                if (VERBOSE)
-                {
-                    Console.WriteLine("\nTEST: iter content=" + searchToken);
-                }
-                FacetsCollector fc = new FacetsCollector();
-                FacetsCollector.Search(searcher, new TermQuery(new Term("content", searchToken)), 10, fc);
-                Facets facets = new SortedSetDocValuesFacetCounts(state, fc);
-
-                // Slow, yet hopefully bug-free, faceting:
-                var expectedCounts = new List<Dictionary<string, int?>>();
-                for (int i = 0; i < numDims; i++)
-                {
-                    expectedCounts.Add(new Dictionary<string, int?>());
-                }
-
-                foreach (TestDoc doc in testDocs)
-                {
-                    if (doc.content.Equals(searchToken))
-                    {
-                        for (int j = 0; j < numDims; j++)
-                        {
-                            if (doc.dims[j] != null)
-                            {
-                                int? v; 
-                                
-                                if (!expectedCounts[j].TryGetValue(doc.dims[j],out v))
-                                {
-                                    expectedCounts[j][doc.dims[j]] = 1;
-                                }
-                                else
-                                {
-                                    expectedCounts[j][doc.dims[j]] = (int)v + 1;
-                                }
-                            }
-                        }
-                    }
-                }
-
-                IList<FacetResult> expected = new List<FacetResult>();
-                for (int i = 0; i < numDims; i++)
-                {
-                    IList<LabelAndValue> labelValues = new List<LabelAndValue>();
-                    int totCount = 0;
-                    foreach (KeyValuePair<string, int?> ent in expectedCounts[i])
-                    {
-                        labelValues.Add(new LabelAndValue(ent.Key, ent.Value.Value));
-                        totCount += ent.Value.Value;
-                    }
-                    SortLabelValues(labelValues);
-                    if (totCount > 0)
-                    {
-                        expected.Add(new FacetResult("dim" + i, new string[0], totCount, labelValues.ToArray(), labelValues.Count));
-                    }
-                }
-
-                // Sort by highest value, tie break by value:
-                SortFacetResults(expected);
-
-                IList<FacetResult> actual = facets.GetAllDims(10);
-
-                // Messy: fixup ties
-                //sortTies(actual);
-
-                Assert.AreEqual(expected, actual);
-            }
-
-            IOUtils.Close(w, searcher.IndexReader, indexDir, taxoDir);
-        }
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/Taxonomy/Directory/TestAddTaxonomy.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/Taxonomy/Directory/TestAddTaxonomy.cs b/src/Lucene.Net.Tests/core/Facet/Taxonomy/Directory/TestAddTaxonomy.cs
deleted file mode 100644
index df4f491..0000000
--- a/src/Lucene.Net.Tests/core/Facet/Taxonomy/Directory/TestAddTaxonomy.cs
+++ /dev/null
@@ -1,323 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-using Lucene.Net.Randomized.Generators;
-using Lucene.Net.Support;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet.Taxonomy.Directory
-{
-
-
-    using DiskOrdinalMap = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter.DiskOrdinalMap;
-    using MemoryOrdinalMap = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter.MemoryOrdinalMap;
-    using OrdinalMap = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter.OrdinalMap;
-    using Directory = Lucene.Net.Store.Directory;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-    using TestUtil = Lucene.Net.Util.TestUtil;
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-    [TestFixture]
-    public class TestAddTaxonomy : FacetTestCase
-    {
-        private void Dotest(int ncats, int range)
-        {
-            AtomicInteger numCats = new AtomicInteger(ncats);
-            Directory[] dirs = new Directory[2];
-            for (int i = 0; i < dirs.Length; i++)
-            {
-                dirs[i] = NewDirectory();
-                var tw = new DirectoryTaxonomyWriter(dirs[i]);
-                ThreadClass[] addThreads = new ThreadClass[4];
-                for (int j = 0; j < addThreads.Length; j++)
-                {
-                    addThreads[j] = new ThreadAnonymousInnerClassHelper(this, range, numCats, tw);
-                }
-
-                foreach (ThreadClass t in addThreads)
-                {
-                    t.Start();
-                }
-                foreach (ThreadClass t in addThreads)
-                {
-                    t.Join();
-                }
-
-                tw.Dispose();
-            }
-
-            var tw1 = new DirectoryTaxonomyWriter(dirs[0]);
-            OrdinalMap map = randomOrdinalMap();
-            tw1.AddTaxonomy(dirs[1], map);
-            tw1.Dispose();
-
-            validate(dirs[0], dirs[1], map);
-
-            IOUtils.Close(dirs);
-        }
-
-        private class ThreadAnonymousInnerClassHelper : ThreadClass
-        {
-            private readonly TestAddTaxonomy outerInstance;
-
-            private int range;
-            private AtomicInteger numCats;
-            private DirectoryTaxonomyWriter tw;
-
-            public ThreadAnonymousInnerClassHelper(TestAddTaxonomy outerInstance, int range, AtomicInteger numCats, DirectoryTaxonomyWriter tw)
-            {
-                this.outerInstance = outerInstance;
-                this.range = range;
-                this.numCats = numCats;
-                this.tw = tw;
-            }
-
-            public override void Run()
-            {
-                Random random = Random();
-                while (numCats.DecrementAndGet() > 0)
-                {
-                    string cat = Convert.ToString(random.Next(range));
-                    try
-                    {
-                        tw.AddCategory(new FacetLabel("a", cat));
-                    }
-                    catch (IOException e)
-                    {
-                        throw new Exception(e.Message, e);
-                    }
-                }
-            }
-        }
-
-
-        private OrdinalMap randomOrdinalMap()
-        {
-            if (Random().NextBoolean())
-            {
-                return new DiskOrdinalMap("taxoMap");
-            }
-            else
-            {
-                return new MemoryOrdinalMap();
-            }
-        }
-
-        private void validate(Directory dest, Directory src, OrdinalMap ordMap)
-        {
-            var destTr = new DirectoryTaxonomyReader(dest);
-            try
-            {
-                int destSize = destTr.Size;
-                var srcTR = new DirectoryTaxonomyReader(src);
-                try
-                {
-                    var map = ordMap.Map;
-
-                    // validate taxo sizes
-                    int srcSize = srcTR.Size;
-                    Assert.True(destSize >= srcSize, "destination taxonomy expected to be larger than source; dest=" + destSize + " src=" + srcSize);
-
-                    // validate that all source categories exist in destination, and their
-                    // ordinals are as expected.
-                    for (int j = 1; j < srcSize; j++)
-                    {
-                        FacetLabel cp = srcTR.GetPath(j);
-                        int destOrdinal = destTr.GetOrdinal(cp);
-                        Assert.True(destOrdinal > 0, cp + " not found in destination");
-                        Assert.AreEqual(destOrdinal, map[j]);
-                    }
-                }
-                finally
-                {
-                    ((TaxonomyReader)srcTR).Dispose(true);
-                }
-            }
-            finally
-            {
-                ((TaxonomyReader)destTr).Dispose(true);
-            }
-        }
-
-        [Test]
-        public virtual void TestAddEmpty()
-        {
-            Directory dest = NewDirectory();
-            var destTW = new DirectoryTaxonomyWriter(dest);
-            destTW.AddCategory(new FacetLabel("Author", "Rob Pike"));
-            destTW.AddCategory(new FacetLabel("Aardvarks", "Bob"));
-            destTW.Commit();
-
-            Directory src = NewDirectory();
-            (new DirectoryTaxonomyWriter(src)).Dispose(); // create an empty taxonomy
-
-            OrdinalMap map = randomOrdinalMap();
-            destTW.AddTaxonomy(src, map);
-            destTW.Dispose();
-
-            validate(dest, src, map);
-
-            IOUtils.Close(dest, src);
-        }
-
-        [Test]
-        public virtual void TestAddToEmpty()
-        {
-            Directory dest = NewDirectory();
-
-            Directory src = NewDirectory();
-            DirectoryTaxonomyWriter srcTW = new DirectoryTaxonomyWriter(src);
-            srcTW.AddCategory(new FacetLabel("Author", "Rob Pike"));
-            srcTW.AddCategory(new FacetLabel("Aardvarks", "Bob"));
-            srcTW.Dispose();
-
-            DirectoryTaxonomyWriter destTW = new DirectoryTaxonomyWriter(dest);
-            OrdinalMap map = randomOrdinalMap();
-            destTW.AddTaxonomy(src, map);
-            destTW.Dispose();
-
-            validate(dest, src, map);
-
-            IOUtils.Close(dest, src);
-        }
-
-        // A more comprehensive and big random test.
-        [Test]
-        public virtual void TestBig()
-        {
-            Dotest(200, 10000);
-            Dotest(1000, 20000);
-            Dotest(400000, 1000000);
-        }
-
-        // a reasonable random test
-        [Test]
-        public virtual void TestMedium()
-        {
-            Random random = Random();
-            int numTests = AtLeast(3);
-            for (int i = 0; i < numTests; i++)
-            {
-                Dotest(TestUtil.NextInt(random, 2, 100), TestUtil.NextInt(random, 100, 1000));
-            }
-        }
-
-        [Test]
-        public virtual void TestSimple()
-        {
-            Directory dest = NewDirectory();
-            var tw1 = new DirectoryTaxonomyWriter(dest);
-            tw1.AddCategory(new FacetLabel("Author", "Mark Twain"));
-            tw1.AddCategory(new FacetLabel("Animals", "Dog"));
-            tw1.AddCategory(new FacetLabel("Author", "Rob Pike"));
-
-            Directory src = NewDirectory();
-            var tw2 = new DirectoryTaxonomyWriter(src);
-            tw2.AddCategory(new FacetLabel("Author", "Rob Pike"));
-            tw2.AddCategory(new FacetLabel("Aardvarks", "Bob"));
-            tw2.Dispose();
-
-            OrdinalMap map = randomOrdinalMap();
-
-            tw1.AddTaxonomy(src, map);
-            tw1.Dispose();
-
-            validate(dest, src, map);
-
-            IOUtils.Close(dest, src);
-        }
-
-        [Test]
-        public virtual void TestConcurrency()
-        {
-            // tests that addTaxonomy and addCategory work in parallel
-            int numCategories = AtLeast(10000);
-
-            // build an input taxonomy index
-            Directory src = NewDirectory();
-            var tw = new DirectoryTaxonomyWriter(src);
-            for (int i = 0; i < numCategories; i++)
-            {
-                tw.AddCategory(new FacetLabel("a", Convert.ToString(i)));
-            }
-            tw.Dispose();
-
-            // now add the taxonomy to an empty taxonomy, while adding the categories
-            // again, in parallel -- in the end, no duplicate categories should exist.
-            Directory dest = NewDirectory();
-            var destTw = new DirectoryTaxonomyWriter(dest);
-            ThreadClass t = new ThreadAnonymousInnerClassHelper2(this, numCategories, destTw);
-            t.Start();
-
-            OrdinalMap map = new MemoryOrdinalMap();
-            destTw.AddTaxonomy(src, map);
-            t.Join();
-            destTw.Dispose();
-
-            // now validate
-
-            var dtr = new DirectoryTaxonomyReader(dest);
-            // +2 to account for the root category + "a"
-            Assert.AreEqual(numCategories + 2, dtr.Size);
-            var categories = new HashSet<FacetLabel>();
-            for (int i = 1; i < dtr.Size; i++)
-            {
-                FacetLabel cat = dtr.GetPath(i);
-                Assert.True(categories.Add(cat), "category " + cat + " already existed");
-            }
-            dtr.Dispose();
-
-            IOUtils.Close(src, dest);
-        }
-
-        private class ThreadAnonymousInnerClassHelper2 : ThreadClass
-        {
-            private readonly TestAddTaxonomy outerInstance;
-
-            private int numCategories;
-            private Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter destTW;
-
-            public ThreadAnonymousInnerClassHelper2(TestAddTaxonomy outerInstance, int numCategories, Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter destTW)
-            {
-                this.outerInstance = outerInstance;
-                this.numCategories = numCategories;
-                this.destTW = destTW;
-            }
-
-            public override void Run()
-            {
-                for (int i = 0; i < numCategories; i++)
-                {
-                    try
-                    {
-                        destTW.AddCategory(new FacetLabel("a", Convert.ToString(i)));
-                    }
-                    catch (IOException e)
-                    {
-                        // shouldn't happen - if it does, let the test fail on uncaught exception.
-                        throw new Exception(e.Message, e);
-                    }
-                }
-            }
-        }
-
-    }
-
-}
\ No newline at end of file


[08/14] lucenenet git commit: Moving Lucene.Net.Facet tests to their appropriate place

Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Taxonomy/WriterCache/TestCompactLabelToOrdinal.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Taxonomy/WriterCache/TestCompactLabelToOrdinal.cs b/src/Lucene.Net.Tests.Facet/Taxonomy/WriterCache/TestCompactLabelToOrdinal.cs
new file mode 100644
index 0000000..549bf09
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Taxonomy/WriterCache/TestCompactLabelToOrdinal.cs
@@ -0,0 +1,151 @@
+using System;
+using System.Collections.Generic;
+using Lucene.Net.Support;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet.Taxonomy.WriterCache
+{
+
+
+    using TestUtil = Lucene.Net.Util.TestUtil;
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+    [TestFixture]
+    public class TestCompactLabelToOrdinal : FacetTestCase
+    {
+        /* not finished to porting yet because of missing decoder implementation */
+        /*
+        public virtual void TestL2O()
+        {
+            LabelToOrdinal map = new LabelToOrdinalMap();
+
+            CompactLabelToOrdinal compact = new CompactLabelToOrdinal(2000000, 0.15f, 3);
+
+            int n = AtLeast(10 * 1000);
+            const int numUniqueValues = 50 * 1000;
+
+            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.Next(buffer.Length);
+
+                // This test is turning random bytes into a string,
+                // this is asking for trouble.
+                CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder().onUnmappableCharacter(CodingErrorAction.REPLACE).onMalformedInput(CodingErrorAction.REPLACE);
+                uniqueValues[i] = decoder.decode(ByteBuffer.Wrap(buffer, 0, size)).ToString();
+                // we cannot have empty path components, so eliminate all prefix as well
+                // as middle consecutive delimiter chars.
+                uniqueValues[i] = uniqueValues[i].replaceAll("/+", "/");
+                if (uniqueValues[i].StartsWith("/", StringComparison.Ordinal))
+                {
+                    uniqueValues[i] = uniqueValues[i].Substring(1);
+                }
+                if (uniqueValues[i].IndexOf(CompactLabelToOrdinal.TERMINATOR_CHAR) == -1)
+                {
+                    i++;
+                }
+            }
+
+            var tmpDir = CreateTempDir("testLableToOrdinal");
+            var f = new File(tmpDir, "CompactLabelToOrdinalTest.tmp");
+            int flushInterval = 10;
+
+            for (int i = 0; i < n; i++)
+            {
+                if (i > 0 && i % flushInterval == 0)
+                {
+                    compact.Flush(f);
+                    compact = CompactLabelToOrdinal.open(f, 0.15f, 3);
+                    Assert.True(f.delete());
+                    if (flushInterval < (n / 10))
+                    {
+                        flushInterval *= 10;
+                    }
+                }
+
+                int index = random.Next(numUniqueValues);
+                FacetLabel label;
+                string s = uniqueValues[index];
+                if (s.Length == 0)
+                {
+                    label = new FacetLabel();
+                }
+                else
+                {
+                    label = new FacetLabel(s.Split("/".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));
+                }
+
+                int ord1 = map.GetOrdinal(label);
+                int ord2 = compact.GetOrdinal(label);
+
+                Assert.AreEqual(ord1, ord2);
+
+                if (ord1 == LabelToOrdinal.INVALID_ORDINAL)
+                {
+                    ord1 = compact.NextOrdinal;
+                    map.AddLabel(label, ord1);
+                    compact.AddLabel(label, ord1);
+                }
+            }
+
+            for (int i = 0; i < numUniqueValues; i++)
+            {
+                FacetLabel label;
+                string s = uniqueValues[i];
+                if (s.Length == 0)
+                {
+                    label = new FacetLabel();
+                }
+                else
+                {
+                    label = new FacetLabel(s.Split("/".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));
+                }
+                int ord1 = map.GetOrdinal(label);
+                int ord2 = compact.GetOrdinal(label);
+                Assert.AreEqual(ord1, ord2);
+            }
+        }
+
+        private class LabelToOrdinalMap : LabelToOrdinal
+        {
+            internal IDictionary<FacetLabel, int?> map = new Dictionary<FacetLabel, int?>();
+
+            internal LabelToOrdinalMap()
+            {
+            }
+
+            public override void AddLabel(FacetLabel label, int ordinal)
+            {
+                map[label] = ordinal;
+            }
+
+            public override int GetOrdinal(FacetLabel label)
+            {
+                int? value = map[label];
+                return (value != null) ? (int)value : LabelToOrdinal.INVALID_ORDINAL;
+            }
+
+        } */
+
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/TestDrillDownQuery.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/TestDrillDownQuery.cs b/src/Lucene.Net.Tests.Facet/TestDrillDownQuery.cs
new file mode 100644
index 0000000..49ce90a
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/TestDrillDownQuery.cs
@@ -0,0 +1,282 @@
+using System;
+using System.Diagnostics;
+using Lucene.Net.Randomized.Generators;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet
+{
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+
+    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
+    using MockTokenizer = Lucene.Net.Analysis.MockTokenizer;
+    using Document = Lucene.Net.Documents.Document;
+    using Field = Lucene.Net.Documents.Field;
+    using TextField = Lucene.Net.Documents.TextField;
+    using TaxonomyWriter = Lucene.Net.Facet.Taxonomy.TaxonomyWriter;
+    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
+    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
+    using IndexReader = Lucene.Net.Index.IndexReader;
+    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
+    using Term = Lucene.Net.Index.Term;
+    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
+    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
+    using Query = Lucene.Net.Search.Query;
+    using QueryUtils = Lucene.Net.Search.QueryUtils;
+    using ScoreDoc = Lucene.Net.Search.ScoreDoc;
+    using TermQuery = Lucene.Net.Search.TermQuery;
+    using TopDocs = Lucene.Net.Search.TopDocs;
+    using Directory = Lucene.Net.Store.Directory;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+
+    [TestFixture]
+    public class TestDrillDownQuery : FacetTestCase
+    {
+
+        private static IndexReader reader;
+        private static DirectoryTaxonomyReader taxo;
+        private static Directory dir;
+        private static Directory taxoDir;
+        private static FacetsConfig config;
+
+      
+        [TestFixtureTearDown]
+        public static void AfterClassDrillDownQueryTest()
+        {
+            IOUtils.Close(reader, taxo, dir, taxoDir);
+            reader = null;
+            taxo = null;
+            dir = null;
+            taxoDir = null;
+            config = null;
+        }
+
+        [TestFixtureSetUp]
+        public static void BeforeClassDrillDownQueryTest()
+        {
+            dir = NewDirectory();
+            Random r = Random();
+            RandomIndexWriter writer = new RandomIndexWriter(r, dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(r, MockTokenizer.KEYWORD, false)));
+
+            taxoDir = NewDirectory();
+            TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            config = new FacetsConfig();
+
+            // Randomize the per-dim config:
+            config.SetHierarchical("a", Random().NextBoolean());
+            config.SetMultiValued("a", Random().NextBoolean());
+            if (Random().NextBoolean())
+            {
+                config.SetIndexFieldName("a", "$a");
+            }
+            config.SetRequireDimCount("a", true);
+
+            config.SetHierarchical("b", Random().NextBoolean());
+            config.SetMultiValued("b", Random().NextBoolean());
+            if (Random().NextBoolean())
+            {
+                config.SetIndexFieldName("b", "$b");
+            }
+            config.SetRequireDimCount("b", true);
+
+            for (int i = 0; i < 100; i++)
+            {
+                Document doc = new Document();
+                if (i % 2 == 0) // 50
+                {
+                    doc.Add(new TextField("content", "foo", Field.Store.NO));
+                }
+                if (i % 3 == 0) // 33
+                {
+                    doc.Add(new TextField("content", "bar", Field.Store.NO));
+                }
+                if (i % 4 == 0) // 25
+                {
+                    if (r.NextBoolean())
+                    {
+                        doc.Add(new FacetField("a", "1"));
+                    }
+                    else
+                    {
+                        doc.Add(new FacetField("a", "2"));
+                    }
+                }
+                if (i % 5 == 0) // 20
+                {
+                    doc.Add(new FacetField("b", "1"));
+                }
+                writer.AddDocument(config.Build(taxoWriter, doc));
+            }
+
+            taxoWriter.Dispose();
+            reader = writer.Reader;
+            writer.Dispose();
+
+            taxo = new DirectoryTaxonomyReader(taxoDir);
+        }
+
+        [Test]
+        public virtual void TestAndOrs()
+        {
+            IndexSearcher searcher = NewSearcher(reader);
+
+            // test (a/1 OR a/2) AND b/1
+            DrillDownQuery q = new DrillDownQuery(config);
+            q.Add("a", "1");
+            q.Add("a", "2");
+            q.Add("b", "1");
+            TopDocs docs = searcher.Search(q, 100);
+            Assert.AreEqual(5, docs.TotalHits);
+        }
+
+        [Test]
+        public virtual void TestQuery()
+        {
+            IndexSearcher searcher = NewSearcher(reader);
+
+            // Making sure the query yields 25 documents with the facet "a"
+            DrillDownQuery q = new DrillDownQuery(config);
+            q.Add("a");
+            QueryUtils.Check(q);
+            TopDocs docs = searcher.Search(q, 100);
+            Assert.AreEqual(25, docs.TotalHits);
+
+            // Making sure the query yields 5 documents with the facet "b" and the
+            // previous (facet "a") query as a base query
+            DrillDownQuery q2 = new DrillDownQuery(config, q);
+            q2.Add("b");
+            docs = searcher.Search(q2, 100);
+            Assert.AreEqual(5, docs.TotalHits);
+
+            // Making sure that a query of both facet "a" and facet "b" yields 5 results
+            DrillDownQuery q3 = new DrillDownQuery(config);
+            q3.Add("a");
+            q3.Add("b");
+            docs = searcher.Search(q3, 100);
+
+            Assert.AreEqual(5, docs.TotalHits);
+            // Check that content:foo (which yields 50% results) and facet/b (which yields 20%)
+            // would gather together 10 results (10%..) 
+            Query fooQuery = new TermQuery(new Term("content", "foo"));
+            DrillDownQuery q4 = new DrillDownQuery(config, fooQuery);
+            q4.Add("b");
+            docs = searcher.Search(q4, 100);
+            Assert.AreEqual(10, docs.TotalHits);
+        }
+
+        [Test]
+        public virtual void TestQueryImplicitDefaultParams()
+        {
+            IndexSearcher searcher = NewSearcher(reader);
+
+            // Create the base query to start with
+            DrillDownQuery q = new DrillDownQuery(config);
+            q.Add("a");
+
+            // Making sure the query yields 5 documents with the facet "b" and the
+            // previous (facet "a") query as a base query
+            DrillDownQuery q2 = new DrillDownQuery(config, q);
+            q2.Add("b");
+            TopDocs docs = searcher.Search(q2, 100);
+            Assert.AreEqual(5, docs.TotalHits);
+
+            // Check that content:foo (which yields 50% results) and facet/b (which yields 20%)
+            // would gather together 10 results (10%..) 
+            Query fooQuery = new TermQuery(new Term("content", "foo"));
+            DrillDownQuery q4 = new DrillDownQuery(config, fooQuery);
+            q4.Add("b");
+            docs = searcher.Search(q4, 100);
+            Assert.AreEqual(10, docs.TotalHits);
+        }
+
+        [Test]
+        public virtual void TestScoring()
+        {
+            // verify that drill-down queries do not modify scores
+            IndexSearcher searcher = NewSearcher(reader);
+
+            float[] scores = new float[reader.MaxDoc];
+
+            Query q = new TermQuery(new Term("content", "foo"));
+            TopDocs docs = searcher.Search(q, reader.MaxDoc); // fetch all available docs to this query
+            foreach (ScoreDoc sd in docs.ScoreDocs)
+            {
+                scores[sd.Doc] = sd.Score;
+            }
+
+            // create a drill-down query with category "a", scores should not change
+            DrillDownQuery q2 = new DrillDownQuery(config, q);
+            q2.Add("a");
+            docs = searcher.Search(q2, reader.MaxDoc); // fetch all available docs to this query
+            foreach (ScoreDoc sd in docs.ScoreDocs)
+            {
+                Assert.AreEqual(scores[sd.Doc], sd.Score, 0f, "score of doc=" + sd.Doc + " modified");
+            }
+        }
+
+        [Test]
+        public virtual void TestScoringNoBaseQuery()
+        {
+            // verify that drill-down queries (with no base query) returns 0.0 score
+            IndexSearcher searcher = NewSearcher(reader);
+
+            DrillDownQuery q = new DrillDownQuery(config);
+            q.Add("a");
+            TopDocs docs = searcher.Search(q, reader.MaxDoc); // fetch all available docs to this query
+            foreach (ScoreDoc sd in docs.ScoreDocs)
+            {
+                Assert.AreEqual(0f, sd.Score, 0f);
+            }
+        }
+
+        [Test]
+        public virtual void TestTermNonDefault()
+        {
+            string aField = config.GetDimConfig("a").IndexFieldName;
+            Term termA = DrillDownQuery.Term(aField, "a");
+            Assert.AreEqual(new Term(aField, "a"), termA);
+
+            string bField = config.GetDimConfig("b").IndexFieldName;
+            Term termB = DrillDownQuery.Term(bField, "b");
+            Assert.AreEqual(new Term(bField, "b"), termB);
+        }
+
+        [Test]
+        public virtual void TestClone()
+        {
+            var q = new DrillDownQuery(config, new MatchAllDocsQuery());
+            q.Add("a");
+
+            var clone = q.Clone() as DrillDownQuery;
+            Assert.NotNull(clone);
+            clone.Add("b");
+            Assert.False(q.ToString().Equals(clone.ToString()), "query wasn't cloned: source=" + q + " clone=" + clone);
+        }
+
+        [Test]
+        public virtual void TestNoDrillDown()
+        {
+            Query @base = new MatchAllDocsQuery();
+            DrillDownQuery q = new DrillDownQuery(config, @base);
+            Query rewrite = q.Rewrite(reader).Rewrite(reader);
+            Assert.AreSame(@base, rewrite);
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/TestDrillSideways.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/TestDrillSideways.cs b/src/Lucene.Net.Tests.Facet/TestDrillSideways.cs
new file mode 100644
index 0000000..00cb772
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/TestDrillSideways.cs
@@ -0,0 +1,1332 @@
+using System;
+using System.Diagnostics;
+using System.Collections.Generic;
+using System.Linq;
+using Lucene.Net.Randomized.Generators;
+using Lucene.Net.Support;
+
+namespace Lucene.Net.Facet
+{
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+
+    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
+    using Document = Lucene.Net.Documents.Document;
+    using Field = Lucene.Net.Documents.Field;
+    using StringField = Lucene.Net.Documents.StringField;
+    using DrillSidewaysResult = Lucene.Net.Facet.DrillSideways.DrillSidewaysResult;
+    using DefaultSortedSetDocValuesReaderState = Lucene.Net.Facet.SortedSet.DefaultSortedSetDocValuesReaderState;
+    using SortedSetDocValuesFacetField = Lucene.Net.Facet.SortedSet.SortedSetDocValuesFacetField;
+    using SortedSetDocValuesReaderState = Lucene.Net.Facet.SortedSet.SortedSetDocValuesReaderState;
+    using TaxonomyReader = Lucene.Net.Facet.Taxonomy.TaxonomyReader;
+    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
+    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
+    using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
+    using IndexReader = Lucene.Net.Index.IndexReader;
+    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
+    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
+    using Term = Lucene.Net.Index.Term;
+    using Collector = Lucene.Net.Search.Collector;
+    using DocIdSet = Lucene.Net.Search.DocIdSet;
+    using Filter = Lucene.Net.Search.Filter;
+    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
+    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
+    using Query = Lucene.Net.Search.Query;
+    using ScoreDoc = Lucene.Net.Search.ScoreDoc;
+    using Scorer = Lucene.Net.Search.Scorer;
+    using Sort = Lucene.Net.Search.Sort;
+    using SortField = Lucene.Net.Search.SortField;
+    using TermQuery = Lucene.Net.Search.TermQuery;
+    using TopDocs = Lucene.Net.Search.TopDocs;
+    using Directory = Lucene.Net.Store.Directory;
+    using Bits = Lucene.Net.Util.Bits;
+    using BytesRef = Lucene.Net.Util.BytesRef;
+    using FixedBitSet = Lucene.Net.Util.FixedBitSet;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+    using InPlaceMergeSorter = Lucene.Net.Util.InPlaceMergeSorter;
+    using InfoStream = Lucene.Net.Util.InfoStream;
+    using TestUtil = Lucene.Net.Util.TestUtil;
+    using NUnit.Framework;
+
+    [TestFixture]
+    public class TestDrillSideways : FacetTestCase
+    {
+
+        [Test]
+        public virtual void TestBasic()
+        {
+            Directory dir = NewDirectory();
+            Directory taxoDir = NewDirectory();
+
+            // Writes facet ords to a separate directory from the
+            // main index:
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+
+            FacetsConfig config = new FacetsConfig();
+            config.SetHierarchical("Publish Date", true);
+
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            Document doc = new Document();
+            doc.Add(new FacetField("Author", "Bob"));
+            doc.Add(new FacetField("Publish Date", "2010", "10", "15"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new FacetField("Author", "Lisa"));
+            doc.Add(new FacetField("Publish Date", "2010", "10", "20"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new FacetField("Author", "Lisa"));
+            doc.Add(new FacetField("Publish Date", "2012", "1", "1"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new FacetField("Author", "Susan"));
+            doc.Add(new FacetField("Publish Date", "2012", "1", "7"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new FacetField("Author", "Frank"));
+            doc.Add(new FacetField("Publish Date", "1999", "5", "5"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+
+            //System.out.println("searcher=" + searcher);
+
+            // NRT open
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            DrillSideways ds = new DrillSideways(searcher, config, taxoReader);
+
+            //  case: drill-down on a single field; in this
+            // case the drill-sideways + drill-down counts ==
+            // drill-down of just the query: 
+            DrillDownQuery ddq = new DrillDownQuery(config);
+            ddq.Add("Author", "Lisa");
+            DrillSidewaysResult r = ds.Search(null, ddq, 10);
+            Assert.AreEqual(2, r.Hits.TotalHits);
+            // Publish Date is only drill-down, and Lisa published
+            // one in 2012 and one in 2010:
+            Assert.AreEqual("dim=Publish Date path=[] value=2 childCount=2\n  2010 (1)\n  2012 (1)\n", r.Facets.GetTopChildren(10, "Publish Date").ToString());
+
+            // Author is drill-sideways + drill-down: Lisa
+            // (drill-down) published twice, and Frank/Susan/Bob
+            // published once:
+            Assert.AreEqual("dim=Author path=[] value=5 childCount=4\n  Lisa (2)\n  Bob (1)\n  Susan (1)\n  Frank (1)\n", r.Facets.GetTopChildren(10, "Author").ToString());
+
+            // Same simple case, but no baseQuery (pure browse):
+            // drill-down on a single field; in this case the
+            // drill-sideways + drill-down counts == drill-down of
+            // just the query:
+            ddq = new DrillDownQuery(config);
+            ddq.Add("Author", "Lisa");
+            r = ds.Search(null, ddq, 10);
+
+            Assert.AreEqual(2, r.Hits.TotalHits);
+            // Publish Date is only drill-down, and Lisa published
+            // one in 2012 and one in 2010:
+            Assert.AreEqual("dim=Publish Date path=[] value=2 childCount=2\n  2010 (1)\n  2012 (1)\n", r.Facets.GetTopChildren(10, "Publish Date").ToString());
+
+            // Author is drill-sideways + drill-down: Lisa
+            // (drill-down) published twice, and Frank/Susan/Bob
+            // published once:
+            Assert.AreEqual("dim=Author path=[] value=5 childCount=4\n  Lisa (2)\n  Bob (1)\n  Susan (1)\n  Frank (1)\n", r.Facets.GetTopChildren(10, "Author").ToString());
+
+            // Another simple case: drill-down on single fields
+            // but OR of two values
+            ddq = new DrillDownQuery(config);
+            ddq.Add("Author", "Lisa");
+            ddq.Add("Author", "Bob");
+            r = ds.Search(null, ddq, 10);
+            Assert.AreEqual(3, r.Hits.TotalHits);
+            // Publish Date is only drill-down: Lisa and Bob
+            // (drill-down) published twice in 2010 and once in 2012:
+            Assert.AreEqual("dim=Publish Date path=[] value=3 childCount=2\n  2010 (2)\n  2012 (1)\n", r.Facets.GetTopChildren(10, "Publish Date").ToString());
+            // Author is drill-sideways + drill-down: Lisa
+            // (drill-down) published twice, and Frank/Susan/Bob
+            // published once:
+            Assert.AreEqual("dim=Author path=[] value=5 childCount=4\n  Lisa (2)\n  Bob (1)\n  Susan (1)\n  Frank (1)\n", r.Facets.GetTopChildren(10, "Author").ToString());
+
+            Assert.True(r.Facets is MultiFacets);
+            IList<FacetResult> allResults = r.Facets.GetAllDims(10);
+            Assert.AreEqual(2, allResults.Count);
+            Assert.AreEqual("dim=Author path=[] value=5 childCount=4\n  Lisa (2)\n  Bob (1)\n  Susan (1)\n  Frank (1)\n", allResults[0].ToString());
+            Assert.AreEqual("dim=Publish Date path=[] value=3 childCount=2\n  2010 (2)\n  2012 (1)\n", allResults[1].ToString());
+
+            // More interesting case: drill-down on two fields
+            ddq = new DrillDownQuery(config);
+            ddq.Add("Author", "Lisa");
+            ddq.Add("Publish Date", "2010");
+            r = ds.Search(null, ddq, 10);
+            Assert.AreEqual(1, r.Hits.TotalHits);
+            // Publish Date is drill-sideways + drill-down: Lisa
+            // (drill-down) published once in 2010 and once in 2012:
+            Assert.AreEqual("dim=Publish Date path=[] value=2 childCount=2\n  2010 (1)\n  2012 (1)\n", r.Facets.GetTopChildren(10, "Publish Date").ToString());
+            // Author is drill-sideways + drill-down:
+            // only Lisa & Bob published (once each) in 2010:
+            Assert.AreEqual("dim=Author path=[] value=2 childCount=2\n  Bob (1)\n  Lisa (1)\n", r.Facets.GetTopChildren(10, "Author").ToString());
+
+            // Even more interesting case: drill down on two fields,
+            // but one of them is OR
+            ddq = new DrillDownQuery(config);
+
+            // Drill down on Lisa or Bob:
+            ddq.Add("Author", "Lisa");
+            ddq.Add("Publish Date", "2010");
+            ddq.Add("Author", "Bob");
+            r = ds.Search(null, ddq, 10);
+            Assert.AreEqual(2, r.Hits.TotalHits);
+            // Publish Date is both drill-sideways + drill-down:
+            // Lisa or Bob published twice in 2010 and once in 2012:
+            Assert.AreEqual("dim=Publish Date path=[] value=3 childCount=2\n  2010 (2)\n  2012 (1)\n", r.Facets.GetTopChildren(10, "Publish Date").ToString());
+            // Author is drill-sideways + drill-down:
+            // only Lisa & Bob published (once each) in 2010:
+            Assert.AreEqual("dim=Author path=[] value=2 childCount=2\n  Bob (1)\n  Lisa (1)\n", r.Facets.GetTopChildren(10, "Author").ToString());
+
+            // Test drilling down on invalid field:
+            ddq = new DrillDownQuery(config);
+            ddq.Add("Foobar", "Baz");
+            r = ds.Search(null, ddq, 10);
+            Assert.AreEqual(0, r.Hits.TotalHits);
+            Assert.Null(r.Facets.GetTopChildren(10, "Publish Date"));
+            Assert.Null(r.Facets.GetTopChildren(10, "Foobar"));
+
+            // Test drilling down on valid term or'd with invalid term:
+            ddq = new DrillDownQuery(config);
+            ddq.Add("Author", "Lisa");
+            ddq.Add("Author", "Tom");
+            r = ds.Search(null, ddq, 10);
+            Assert.AreEqual(2, r.Hits.TotalHits);
+            // Publish Date is only drill-down, and Lisa published
+            // one in 2012 and one in 2010:
+            Assert.AreEqual("dim=Publish Date path=[] value=2 childCount=2\n  2010 (1)\n  2012 (1)\n", r.Facets.GetTopChildren(10, "Publish Date").ToString());
+            // Author is drill-sideways + drill-down: Lisa
+            // (drill-down) published twice, and Frank/Susan/Bob
+            // published once:
+            Assert.AreEqual("dim=Author path=[] value=5 childCount=4\n  Lisa (2)\n  Bob (1)\n  Susan (1)\n  Frank (1)\n", r.Facets.GetTopChildren(10, "Author").ToString());
+
+            // LUCENE-4915: test drilling down on a dimension but
+            // NOT facet counting it:
+            ddq = new DrillDownQuery(config);
+            ddq.Add("Author", "Lisa");
+            ddq.Add("Author", "Tom");
+            r = ds.Search(null, ddq, 10);
+            Assert.AreEqual(2, r.Hits.TotalHits);
+            // Publish Date is only drill-down, and Lisa published
+            // one in 2012 and one in 2010:
+            Assert.AreEqual("dim=Publish Date path=[] value=2 childCount=2\n  2010 (1)\n  2012 (1)\n", r.Facets.GetTopChildren(10, "Publish Date").ToString());
+
+            // Test main query gets null scorer:
+            ddq = new DrillDownQuery(config, new TermQuery(new Term("foobar", "baz")));
+            ddq.Add("Author", "Lisa");
+            r = ds.Search(null, ddq, 10);
+
+            Assert.AreEqual(0, r.Hits.TotalHits);
+            Assert.Null(r.Facets.GetTopChildren(10, "Publish Date"));
+            Assert.Null(r.Facets.GetTopChildren(10, "Author"));
+            IOUtils.Close(searcher.IndexReader, taxoReader, writer, taxoWriter, dir, taxoDir);
+        }
+
+        [Test]
+        public virtual void TestSometimesInvalidDrillDown()
+        {
+            Directory dir = NewDirectory();
+            Directory taxoDir = NewDirectory();
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            // Writes facet ords to a separate directory from the
+            // main index:
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+
+            FacetsConfig config = new FacetsConfig();
+            config.SetHierarchical("Publish Date", true);
+
+            Document doc = new Document();
+            doc.Add(new FacetField("Author", "Bob"));
+            doc.Add(new FacetField("Publish Date", "2010", "10", "15"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new FacetField("Author", "Lisa"));
+            doc.Add(new FacetField("Publish Date", "2010", "10", "20"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            writer.Commit();
+
+            // 2nd segment has no Author:
+            doc = new Document();
+            doc.Add(new FacetField("Foobar", "Lisa"));
+            doc.Add(new FacetField("Publish Date", "2012", "1", "1"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+
+            //System.out.println("searcher=" + searcher);
+
+            // NRT open
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            DrillDownQuery ddq = new DrillDownQuery(config);
+            ddq.Add("Author", "Lisa");
+            DrillSidewaysResult r = (new DrillSideways(searcher, config, taxoReader)).Search(null, ddq, 10);
+
+            Assert.AreEqual(1, r.Hits.TotalHits);
+            // Publish Date is only drill-down, and Lisa published
+            // one in 2012 and one in 2010:
+            Assert.AreEqual("dim=Publish Date path=[] value=1 childCount=1\n  2010 (1)\n", r.Facets.GetTopChildren(10, "Publish Date").ToString());
+            // Author is drill-sideways + drill-down: Lisa
+            // (drill-down) published once, and Bob
+            // published once:
+            Assert.AreEqual("dim=Author path=[] value=2 childCount=2\n  Bob (1)\n  Lisa (1)\n", r.Facets.GetTopChildren(10, "Author").ToString());
+
+            IOUtils.Close(searcher.IndexReader, taxoReader, writer, taxoWriter, dir, taxoDir);
+        }
+
+        [Test]
+        public virtual void TestMultipleRequestsPerDim()
+        {
+            Directory dir = NewDirectory();
+            Directory taxoDir = NewDirectory();
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            // Writes facet ords to a separate directory from the
+            // main index:
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+
+            FacetsConfig config = new FacetsConfig();
+            config.SetHierarchical("dim", true);
+
+            Document doc = new Document();
+            doc.Add(new FacetField("dim", "a", "x"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new FacetField("dim", "a", "y"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new FacetField("dim", "a", "z"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new FacetField("dim", "b"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new FacetField("dim", "c"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new FacetField("dim", "d"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+
+            //System.out.println("searcher=" + searcher);
+
+            // NRT open
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            DrillDownQuery ddq = new DrillDownQuery(config);
+            ddq.Add("dim", "a");
+            DrillSidewaysResult r = (new DrillSideways(searcher, config, taxoReader)).Search(null, ddq, 10);
+
+            Assert.AreEqual(3, r.Hits.TotalHits);
+            Assert.AreEqual("dim=dim path=[] value=6 childCount=4\n  a (3)\n  b (1)\n  c (1)\n  d (1)\n", r.Facets.GetTopChildren(10, "dim").ToString());
+            Assert.AreEqual("dim=dim path=[a] value=3 childCount=3\n  x (1)\n  y (1)\n  z (1)\n", r.Facets.GetTopChildren(10, "dim", "a").ToString());
+
+            IOUtils.Close(searcher.IndexReader, taxoReader, writer, taxoWriter, dir, taxoDir);
+        }
+
+        internal class Doc : IComparable<Doc>
+        {
+            internal string id;
+            internal string contentToken;
+
+            public Doc()
+            {
+            }
+
+            // -1 if the doc is missing this dim, else the index
+            // -into the values for this dim:
+            internal int[] dims;
+
+            // 2nd value per dim for the doc (so we test
+            // multi-valued fields):
+            internal int[] dims2;
+            internal bool deleted;
+
+            public virtual int CompareTo(Doc other)
+            {
+                return id.CompareTo(other.id);
+            }
+        }
+
+        private double aChance, bChance, cChance;
+
+        private string randomContentToken(bool isQuery)
+        {
+            double d = Random().NextDouble();
+            if (isQuery)
+            {
+                if (d < 0.33)
+                {
+                    return "a";
+                }
+                else if (d < 0.66)
+                {
+                    return "b";
+                }
+                else
+                {
+                    return "c";
+                }
+            }
+            else
+            {
+                if (d <= aChance)
+                {
+                    return "a";
+                }
+                else if (d < aChance + bChance)
+                {
+                    return "b";
+                }
+                else
+                {
+                    return "c";
+                }
+            }
+        }
+
+        [Test]
+        public virtual void TestRandom()
+        {
+
+            bool canUseDV = DefaultCodecSupportsSortedSet();
+
+            while (aChance == 0.0)
+            {
+                aChance = Random().NextDouble();
+            }
+            while (bChance == 0.0)
+            {
+                bChance = Random().NextDouble();
+            }
+            while (cChance == 0.0)
+            {
+                cChance = Random().NextDouble();
+            }
+            //aChance = .01;
+            //bChance = 0.5;
+            //cChance = 1.0;
+            double sum = aChance + bChance + cChance;
+            aChance /= sum;
+            bChance /= sum;
+            cChance /= sum;
+
+            int numDims = TestUtil.NextInt(Random(), 2, 5);
+            //int numDims = 3;
+            int numDocs = AtLeast(3000);
+            //int numDocs = 20;
+            if (VERBOSE)
+            {
+                Console.WriteLine("numDims=" + numDims + " numDocs=" + numDocs + " aChance=" + aChance + " bChance=" + bChance + " cChance=" + cChance);
+            }
+            string[][] dimValues = new string[numDims][];
+            int valueCount = 2;
+
+            for (int dim = 0; dim < numDims; dim++)
+            {
+                var values = new HashSet<string>();
+                while (values.Count < valueCount)
+                {
+                    var str = TestUtil.RandomRealisticUnicodeString(Random());
+                    //String s = TestUtil.randomString(Random());
+                    if (str.Length > 0)
+                    {
+                        values.Add(str);
+                    }
+                }
+                dimValues[dim] = values.ToArray();
+                valueCount *= 2;
+            }
+
+            IList<Doc> docs = new List<Doc>();
+            for (int i = 0; i < numDocs; i++)
+            {
+                Doc doc = new Doc();
+                doc.id = "" + i;
+                doc.contentToken = randomContentToken(false);
+                doc.dims = new int[numDims];
+                doc.dims2 = new int[numDims];
+                for (int dim = 0; dim < numDims; dim++)
+                {
+                    if (Random().Next(5) == 3)
+                    {
+                        // This doc is missing this dim:
+                        doc.dims[dim] = -1;
+                    }
+                    else if (dimValues[dim].Length <= 4)
+                    {
+                        int dimUpto = 0;
+                        doc.dims[dim] = dimValues[dim].Length - 1;
+                        while (dimUpto < dimValues[dim].Length)
+                        {
+                            if (Random().NextBoolean())
+                            {
+                                doc.dims[dim] = dimUpto;
+                                break;
+                            }
+                            dimUpto++;
+                        }
+                    }
+                    else
+                    {
+                        doc.dims[dim] = Random().Next(dimValues[dim].Length);
+                    }
+
+                    if (Random().Next(5) == 3)
+                    {
+                        // 2nd value:
+                        doc.dims2[dim] = Random().Next(dimValues[dim].Length);
+                    }
+                    else
+                    {
+                        doc.dims2[dim] = -1;
+                    }
+                }
+                docs.Add(doc);
+            }
+
+            Directory d = NewDirectory();
+            Directory td = NewDirectory();
+
+            IndexWriterConfig iwc = NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
+            iwc.SetInfoStream(InfoStream.NO_OUTPUT);
+            var w = new RandomIndexWriter(Random(), d, iwc);
+            var tw = new DirectoryTaxonomyWriter(td, IndexWriterConfig.OpenMode_e.CREATE);
+            FacetsConfig config = new FacetsConfig();
+            for (int i = 0; i < numDims; i++)
+            {
+                config.SetMultiValued("dim" + i, true);
+            }
+
+            bool doUseDV = canUseDV && Random().NextBoolean();
+
+            foreach (Doc rawDoc in docs)
+            {
+                Document doc = new Document();
+                doc.Add(NewStringField("id", rawDoc.id, Field.Store.YES));
+                doc.Add(NewStringField("content", rawDoc.contentToken, Field.Store.NO));
+
+                if (VERBOSE)
+                {
+                    Console.WriteLine("  doc id=" + rawDoc.id + " token=" + rawDoc.contentToken);
+                }
+                for (int dim = 0; dim < numDims; dim++)
+                {
+                    int dimValue = rawDoc.dims[dim];
+                    if (dimValue != -1)
+                    {
+                        if (doUseDV)
+                        {
+                            doc.Add(new SortedSetDocValuesFacetField("dim" + dim, dimValues[dim][dimValue]));
+                        }
+                        else
+                        {
+                            doc.Add(new FacetField("dim" + dim, dimValues[dim][dimValue]));
+                        }
+                        doc.Add(new StringField("dim" + dim, dimValues[dim][dimValue], Field.Store.YES));
+                        if (VERBOSE)
+                        {
+                            Console.WriteLine("    dim" + dim + "=" + new BytesRef(dimValues[dim][dimValue]));
+                        }
+                    }
+                    int dimValue2 = rawDoc.dims2[dim];
+                    if (dimValue2 != -1)
+                    {
+                        if (doUseDV)
+                        {
+                            doc.Add(new SortedSetDocValuesFacetField("dim" + dim, dimValues[dim][dimValue2]));
+                        }
+                        else
+                        {
+                            doc.Add(new FacetField("dim" + dim, dimValues[dim][dimValue2]));
+                        }
+                        doc.Add(new StringField("dim" + dim, dimValues[dim][dimValue2], Field.Store.YES));
+                        if (VERBOSE)
+                        {
+                            Console.WriteLine("      dim" + dim + "=" + new BytesRef(dimValues[dim][dimValue2]));
+                        }
+                    }
+                }
+
+                w.AddDocument(config.Build(tw, doc));
+            }
+
+            if (Random().NextBoolean())
+            {
+                // Randomly delete a few docs:
+                int numDel = TestUtil.NextInt(Random(), 1, (int)(numDocs * 0.05));
+                if (VERBOSE)
+                {
+                    Console.WriteLine("delete " + numDel);
+                }
+                int delCount = 0;
+                while (delCount < numDel)
+                {
+                    Doc doc = docs[Random().Next(docs.Count)];
+                    if (!doc.deleted)
+                    {
+                        if (VERBOSE)
+                        {
+                            Console.WriteLine("  delete id=" + doc.id);
+                        }
+                        doc.deleted = true;
+                        w.DeleteDocuments(new Term("id", doc.id));
+                        delCount++;
+                    }
+                }
+            }
+
+            if (Random().NextBoolean())
+            {
+                if (VERBOSE)
+                {
+                    Console.WriteLine("TEST: forceMerge(1)...");
+                }
+                w.ForceMerge(1);
+            }
+            IndexReader r = w.Reader;
+
+            SortedSetDocValuesReaderState sortedSetDVState;
+            IndexSearcher s = NewSearcher(r);
+
+            if (doUseDV)
+            {
+                sortedSetDVState = new DefaultSortedSetDocValuesReaderState(s.IndexReader);
+            }
+            else
+            {
+                sortedSetDVState = null;
+            }
+
+            if (VERBOSE)
+            {
+                Console.WriteLine("r.numDocs() = " + r.NumDocs);
+            }
+
+            // NRT open
+            var tr = new DirectoryTaxonomyReader(tw);
+
+            int numIters = AtLeast(10);
+
+            for (int iter = 0; iter < numIters; iter++)
+            {
+
+                string contentToken = Random().Next(30) == 17 ? null : randomContentToken(true);
+                int numDrillDown = TestUtil.NextInt(Random(), 1, Math.Min(4, numDims));
+                if (VERBOSE)
+                {
+                    Console.WriteLine("\nTEST: iter=" + iter + " baseQuery=" + contentToken + " numDrillDown=" + numDrillDown + " useSortedSetDV=" + doUseDV);
+                }
+
+                string[][] drillDowns = new string[numDims][];
+
+                int count = 0;
+                bool anyMultiValuedDrillDowns = false;
+                while (count < numDrillDown)
+                {
+                    int dim = Random().Next(numDims);
+                    if (drillDowns[dim] == null)
+                    {
+                        if (Random().NextBoolean())
+                        {
+                            // Drill down on one value:
+                            drillDowns[dim] = new string[] { dimValues[dim][Random().Next(dimValues[dim].Length)] };
+                        }
+                        else
+                        {
+                            int orCount = TestUtil.NextInt(Random(), 1, Math.Min(5, dimValues[dim].Length));
+                            drillDowns[dim] = new string[orCount];
+                            anyMultiValuedDrillDowns |= orCount > 1;
+                            for (int i = 0; i < orCount; i++)
+                            {
+                                while (true)
+                                {
+                                    string value = dimValues[dim][Random().Next(dimValues[dim].Length)];
+                                    for (int j = 0; j < i; j++)
+                                    {
+                                        if (value.Equals(drillDowns[dim][j]))
+                                        {
+                                            value = null;
+                                            break;
+                                        }
+                                    }
+                                    if (value != null)
+                                    {
+                                        drillDowns[dim][i] = value;
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                        if (VERBOSE)
+                        {
+                            BytesRef[] values = new BytesRef[drillDowns[dim].Length];
+                            for (int i = 0; i < values.Length; i++)
+                            {
+                                values[i] = new BytesRef(drillDowns[dim][i]);
+                            }
+                            Console.WriteLine("  dim" + dim + "=" + Arrays.ToString(values));
+                        }
+                        count++;
+                    }
+                }
+
+                Query baseQuery;
+                if (contentToken == null)
+                {
+                    baseQuery = new MatchAllDocsQuery();
+                }
+                else
+                {
+                    baseQuery = new TermQuery(new Term("content", contentToken));
+                }
+
+                DrillDownQuery ddq = new DrillDownQuery(config, baseQuery);
+
+                for (int dim = 0; dim < numDims; dim++)
+                {
+                    if (drillDowns[dim] != null)
+                    {
+                        foreach (string value in drillDowns[dim])
+                        {
+                            ddq.Add("dim" + dim, value);
+                        }
+                    }
+                }
+
+                Filter filter;
+                if (Random().Next(7) == 6)
+                {
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine("  only-even filter");
+                    }
+                    filter = new FilterAnonymousInnerClassHelper(this);
+                }
+                else
+                {
+                    filter = null;
+                }
+
+                // Verify docs are always collected in order.  If we
+                // had an AssertingScorer it could catch it when
+                // Weight.scoresDocsOutOfOrder lies!:
+                (new DrillSideways(s, config, tr)).Search(ddq, new CollectorAnonymousInnerClassHelper(this, s));
+
+                // Also separately verify that DS respects the
+                // scoreSubDocsAtOnce method, to ensure that all
+                // subScorers are on the same docID:
+                if (!anyMultiValuedDrillDowns)
+                {
+                    // Can only do this test when there are no OR'd
+                    // drill-down values, because in that case it's
+                    // easily possible for one of the DD terms to be on
+                    // a future docID:
+                    new DrillSidewaysAnonymousInnerClassHelper(this, s, config, tr)
+                    .Search(ddq, new AssertingSubDocsAtOnceCollector());
+                }
+
+                TestFacetResult expected = slowDrillSidewaysSearch(s, docs, contentToken, drillDowns, dimValues, filter);
+
+                Sort sort = new Sort(new SortField("id", SortField.Type_e.STRING));
+                DrillSideways ds;
+                if (doUseDV)
+                {
+                    ds = new DrillSideways(s, config, sortedSetDVState);
+                }
+                else
+                {
+                    ds = new DrillSidewaysAnonymousInnerClassHelper2(this, s, config, tr, drillDowns);
+                }
+
+                // Retrieve all facets:
+                DrillSidewaysResult actual = ds.Search(ddq, filter, null, numDocs, sort, true, true);
+
+                TopDocs hits = s.Search(baseQuery, numDocs);
+                IDictionary<string, float?> scores = new Dictionary<string, float?>();
+                foreach (ScoreDoc sd in hits.ScoreDocs)
+                {
+                    scores[s.Doc(sd.Doc).Get("id")] = sd.Score;
+                }
+                if (VERBOSE)
+                {
+                    Console.WriteLine("  verify all facets");
+                }
+                VerifyEquals(dimValues, s, expected, actual, scores, doUseDV);
+
+                // Make sure drill down doesn't change score:
+                TopDocs ddqHits = s.Search(ddq, filter, numDocs);
+                Assert.AreEqual(expected.Hits.Count, ddqHits.TotalHits);
+                for (int i = 0; i < expected.Hits.Count; i++)
+                {
+                    // Score should be IDENTICAL:
+                    Assert.AreEqual(scores[expected.Hits[i].id], ddqHits.ScoreDocs[i].Score);
+                }
+            }
+
+            IOUtils.Close(r, tr, w, tw, d, td);
+        }
+
+        private class FilterAnonymousInnerClassHelper : Filter
+        {
+            private readonly TestDrillSideways outerInstance;
+
+            public FilterAnonymousInnerClassHelper(TestDrillSideways outerInstance)
+            {
+                this.outerInstance = outerInstance;
+            }
+
+            public override DocIdSet GetDocIdSet(AtomicReaderContext context, Bits acceptDocs)
+            {
+                int maxDoc = context.Reader.MaxDoc;
+                FixedBitSet bits = new FixedBitSet(maxDoc);
+                for (int docID = 0; docID < maxDoc; docID++)
+                {
+                    // Keeps only the even ids:
+                    if ((acceptDocs == null || acceptDocs.Get(docID)) && (Convert.ToInt32(context.Reader.Document(docID).Get("id")) & 1) == 0)
+                    {
+                        bits.Set(docID);
+                    }
+                }
+                return bits;
+            }
+        }
+
+        private class CollectorAnonymousInnerClassHelper : Collector
+        {
+            private readonly TestDrillSideways outerInstance;
+
+            private IndexSearcher s;
+
+            public CollectorAnonymousInnerClassHelper(TestDrillSideways outerInstance, IndexSearcher s)
+            {
+                this.outerInstance = outerInstance;
+                this.s = s;
+            }
+
+            internal int lastDocID;
+
+            public override Scorer Scorer
+            {
+                set
+                {
+                }
+            }
+
+            public override void Collect(int doc)
+            {
+                Debug.Assert(doc > lastDocID);
+                lastDocID = doc;
+            }
+
+            public override AtomicReaderContext NextReader
+            {
+                set
+                {
+                    lastDocID = -1;
+                }
+            }
+
+            public override bool AcceptsDocsOutOfOrder()
+            {
+                return false;
+            }
+        }
+
+        private class DrillSidewaysAnonymousInnerClassHelper : DrillSideways
+        {
+            private readonly TestDrillSideways outerInstance;
+
+            public DrillSidewaysAnonymousInnerClassHelper(TestDrillSideways outerInstance, IndexSearcher s, Lucene.Net.Facet.FacetsConfig config, TaxonomyReader tr)
+                : base(s, config, tr)
+            {
+                this.outerInstance = outerInstance;
+            }
+
+            protected override bool ScoreSubDocsAtOnce()
+            {
+                return true;
+            }
+        }
+
+        private class DrillSidewaysAnonymousInnerClassHelper2 : DrillSideways
+        {
+            private readonly TestDrillSideways outerInstance;
+
+            private new Lucene.Net.Facet.FacetsConfig config;
+            private string[][] drillDowns;
+
+            public DrillSidewaysAnonymousInnerClassHelper2(TestDrillSideways outerInstance, IndexSearcher s, Lucene.Net.Facet.FacetsConfig config, TaxonomyReader tr, string[][] drillDowns)
+                : base(s, config, tr)
+            {
+                this.outerInstance = outerInstance;
+                this.config = config;
+                this.drillDowns = drillDowns;
+            }
+
+            protected override Facets BuildFacetsResult(FacetsCollector drillDowns, FacetsCollector[] drillSideways, string[] drillSidewaysDims)
+            {
+                IDictionary<string, Facets> drillSidewaysFacets = new Dictionary<string, Facets>();
+                Facets drillDownFacets = outerInstance.GetTaxonomyFacetCounts(taxoReader, config, drillDowns);
+                if (drillSideways != null)
+                {
+                    for (int i = 0; i < drillSideways.Length; i++)
+                    {
+                        drillSidewaysFacets[drillSidewaysDims[i]] = outerInstance.GetTaxonomyFacetCounts(taxoReader, config, drillSideways[i]);
+                    }
+                }
+
+                if (drillSidewaysFacets.Count == 0)
+                {
+                    return drillDownFacets;
+                }
+                else
+                {
+                    return new MultiFacets(drillSidewaysFacets, drillDownFacets);
+                }
+
+            }
+        }
+
+        private class Counters
+        {
+            internal int[][] counts;
+
+            public Counters(string[][] dimValues)
+            {
+                counts = new int[dimValues.Length][];
+                for (int dim = 0; dim < dimValues.Length; dim++)
+                {
+                    counts[dim] = new int[dimValues[dim].Length];
+                }
+            }
+
+            public virtual void Inc(int[] dims, int[] dims2)
+            {
+                Inc(dims, dims2, -1);
+            }
+
+            public virtual void Inc(int[] dims, int[] dims2, int onlyDim)
+            {
+                Debug.Assert(dims.Length == counts.Length);
+                Debug.Assert(dims2.Length == counts.Length);
+                for (int dim = 0; dim < dims.Length; dim++)
+                {
+                    if (onlyDim == -1 || dim == onlyDim)
+                    {
+                        if (dims[dim] != -1)
+                        {
+                            counts[dim][dims[dim]]++;
+                        }
+                        if (dims2[dim] != -1 && dims2[dim] != dims[dim])
+                        {
+                            counts[dim][dims2[dim]]++;
+                        }
+                    }
+                }
+            }
+        }
+
+        internal class TestFacetResult
+        {
+            internal IList<Doc> Hits;
+            internal int[][] Counts;
+            internal int[] UniqueCounts;
+            public TestFacetResult()
+            {
+            }
+        }
+
+        private int[] GetTopNOrds(int[] counts, string[] values, int topN)
+        {
+            int[] ids = new int[counts.Length];
+            for (int i = 0; i < ids.Length; i++)
+            {
+                ids[i] = i;
+            }
+
+            // Naive (on purpose, to reduce bug in tester/gold):
+            // sort all ids, then return top N slice:
+            new InPlaceMergeSorterAnonymousInnerClassHelper(this, counts, values, ids).Sort(0, ids.Length);
+
+            if (topN > ids.Length)
+            {
+                topN = ids.Length;
+            }
+
+            int numSet = topN;
+            for (int i = 0; i < topN; i++)
+            {
+                if (counts[ids[i]] == 0)
+                {
+                    numSet = i;
+                    break;
+                }
+            }
+
+            int[] topNIDs = new int[numSet];
+            Array.Copy(ids, 0, topNIDs, 0, topNIDs.Length);
+            return topNIDs;
+        }
+
+        private class InPlaceMergeSorterAnonymousInnerClassHelper : InPlaceMergeSorter
+        {
+            private readonly TestDrillSideways outerInstance;
+
+            private int[] counts;
+            private string[] values;
+            private int[] ids;
+
+            public InPlaceMergeSorterAnonymousInnerClassHelper(TestDrillSideways outerInstance, int[] counts, string[] values, int[] ids)
+            {
+                this.outerInstance = outerInstance;
+                this.counts = counts;
+                this.values = values;
+                this.ids = ids;
+            }
+
+
+            protected override void Swap(int i, int j)
+            {
+                int id = ids[i];
+                ids[i] = ids[j];
+                ids[j] = id;
+            }
+
+            protected override int Compare(int i, int j)
+            {
+                int counti = counts[ids[i]];
+                int countj = counts[ids[j]];
+                // Sort by count descending...
+                if (counti > countj)
+                {
+                    return -1;
+                }
+                else if (counti < countj)
+                {
+                    return 1;
+                }
+                else
+                {
+                    // ... then by label ascending:
+                    return (new BytesRef(values[ids[i]])).CompareTo(new BytesRef(values[ids[j]]));
+                }
+            }
+
+        }
+
+        private TestFacetResult slowDrillSidewaysSearch(IndexSearcher s, IList<Doc> docs, string contentToken, string[][] drillDowns, string[][] dimValues, Filter onlyEven)
+        {
+            int numDims = dimValues.Length;
+
+            IList<Doc> hits = new List<Doc>();
+            Counters drillDownCounts = new Counters(dimValues);
+            Counters[] drillSidewaysCounts = new Counters[dimValues.Length];
+            for (int dim = 0; dim < numDims; dim++)
+            {
+                drillSidewaysCounts[dim] = new Counters(dimValues);
+            }
+
+            if (VERBOSE)
+            {
+                Console.WriteLine("  compute expected");
+            }
+
+            foreach (Doc doc in docs)
+            {
+                if (doc.deleted)
+                {
+                    continue;
+                }
+                if (onlyEven != null & (Convert.ToInt32(doc.id) & 1) != 0)
+                {
+                    continue;
+                }
+                if (contentToken == null || doc.contentToken.Equals(contentToken))
+                {
+                    int failDim = -1;
+                    for (int dim = 0; dim < numDims; dim++)
+                    {
+                        if (drillDowns[dim] != null)
+                        {
+                            string docValue = doc.dims[dim] == -1 ? null : dimValues[dim][doc.dims[dim]];
+                            string docValue2 = doc.dims2[dim] == -1 ? null : dimValues[dim][doc.dims2[dim]];
+                            bool matches = false;
+                            foreach (string value in drillDowns[dim])
+                            {
+                                if (value.Equals(docValue) || value.Equals(docValue2))
+                                {
+                                    matches = true;
+                                    break;
+                                }
+                            }
+                            if (!matches)
+                            {
+                                if (failDim == -1)
+                                {
+                                    // Doc could be a near-miss, if no other dim fails
+                                    failDim = dim;
+                                }
+                                else
+                                {
+                                    // Doc isn't a hit nor a near-miss
+                                    goto nextDocContinue;
+                                }
+                            }
+                        }
+                    }
+
+                    if (failDim == -1)
+                    {
+                        if (VERBOSE)
+                        {
+                            Console.WriteLine("    exp: id=" + doc.id + " is a hit");
+                        }
+                        // Hit:
+                        hits.Add(doc);
+                        drillDownCounts.Inc(doc.dims, doc.dims2);
+                        for (int dim = 0; dim < dimValues.Length; dim++)
+                        {
+                            drillSidewaysCounts[dim].Inc(doc.dims, doc.dims2);
+                        }
+                    }
+                    else
+                    {
+                        if (VERBOSE)
+                        {
+                            Console.WriteLine("    exp: id=" + doc.id + " is a near-miss on dim=" + failDim);
+                        }
+                        drillSidewaysCounts[failDim].Inc(doc.dims, doc.dims2, failDim);
+                    }
+                }
+            nextDocContinue: ;
+            }
+        nextDocBreak:
+
+            IDictionary<string, int?> idToDocID = new Dictionary<string, int?>();
+            for (int i = 0; i < s.IndexReader.MaxDoc; i++)
+            {
+                idToDocID[s.Doc(i).Get("id")] = i;
+            }
+
+            var hitsSorted = hits.ToArray();
+            Array.Sort(hitsSorted);
+            hits = hitsSorted.ToList();
+
+            TestFacetResult res = new TestFacetResult();
+            res.Hits = hits;
+            res.Counts = new int[numDims][];
+            res.UniqueCounts = new int[numDims];
+            for (int dim = 0; dim < numDims; dim++)
+            {
+                if (drillDowns[dim] != null)
+                {
+                    res.Counts[dim] = drillSidewaysCounts[dim].counts[dim];
+                }
+                else
+                {
+                    res.Counts[dim] = drillDownCounts.counts[dim];
+                }
+                int uniqueCount = 0;
+                for (int j = 0; j < res.Counts[dim].Length; j++)
+                {
+                    if (res.Counts[dim][j] != 0)
+                    {
+                        uniqueCount++;
+                    }
+                }
+                res.UniqueCounts[dim] = uniqueCount;
+            }
+
+            return res;
+        }
+
+        internal virtual void VerifyEquals(string[][] dimValues, IndexSearcher s, TestFacetResult expected, DrillSidewaysResult actual, IDictionary<string, float?> scores, bool isSortedSetDV)
+        {
+            if (VERBOSE)
+            {
+                Console.WriteLine("  verify totHits=" + expected.Hits.Count);
+            }
+            Assert.AreEqual(expected.Hits.Count, actual.Hits.TotalHits);
+            Assert.AreEqual(expected.Hits.Count, actual.Hits.ScoreDocs.Length);
+            for (int i = 0; i < expected.Hits.Count; i++)
+            {
+                if (VERBOSE)
+                {
+                    Console.WriteLine("    hit " + i + " expected=" + expected.Hits[i].id);
+                }
+                Assert.AreEqual(expected.Hits[i].id, s.Doc(actual.Hits.ScoreDocs[i].Doc).Get("id"));
+                // Score should be IDENTICAL:
+                Assert.AreEqual(scores[expected.Hits[i].id], actual.Hits.ScoreDocs[i].Score);
+            }
+
+            for (int dim = 0; dim < expected.Counts.Length; dim++)
+            {
+                int topN = Random().NextBoolean() ? dimValues[dim].Length : TestUtil.NextInt(Random(), 1, dimValues[dim].Length);
+                FacetResult fr = actual.Facets.GetTopChildren(topN, "dim" + dim);
+                if (VERBOSE)
+                {
+                    Console.WriteLine("    dim" + dim + " topN=" + topN + " (vs " + dimValues[dim].Length + " unique values)");
+                    Console.WriteLine("      actual");
+                }
+
+                int idx = 0;
+                IDictionary<string, int?> actualValues = new Dictionary<string, int?>();
+
+                if (fr != null)
+                {
+                    foreach (LabelAndValue labelValue in fr.LabelValues)
+                    {
+                        actualValues[labelValue.label] = (int)labelValue.value;
+                        if (VERBOSE)
+                        {
+                            Console.WriteLine("        " + idx + ": " + new BytesRef(labelValue.label) + ": " + labelValue.value);
+                            idx++;
+                        }
+                    }
+                    Assert.AreEqual(expected.UniqueCounts[dim], fr.ChildCount, "dim=" + dim);
+                }
+
+                if (topN < dimValues[dim].Length)
+                {
+                    int[] topNIDs = GetTopNOrds(expected.Counts[dim], dimValues[dim], topN);
+                    if (VERBOSE)
+                    {
+                        idx = 0;
+                        Console.WriteLine("      expected (sorted)");
+                        for (int i = 0; i < topNIDs.Length; i++)
+                        {
+                            int expectedOrd = topNIDs[i];
+                            string value = dimValues[dim][expectedOrd];
+                            Console.WriteLine("        " + idx + ": " + new BytesRef(value) + ": " + expected.Counts[dim][expectedOrd]);
+                            idx++;
+                        }
+                    }
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine("      topN=" + topN + " expectedTopN=" + topNIDs.Length);
+                    }
+
+                    if (fr != null)
+                    {
+                        Assert.AreEqual(topNIDs.Length, fr.LabelValues.Length);
+                    }
+                    else
+                    {
+                        Assert.AreEqual(0, topNIDs.Length);
+                    }
+                    for (int i = 0; i < topNIDs.Length; i++)
+                    {
+                        int expectedOrd = topNIDs[i];
+                        Assert.AreEqual(expected.Counts[dim][expectedOrd], (int)fr.LabelValues[i].value);
+                        if (isSortedSetDV)
+                        {
+                            // Tie-break facet labels are only in unicode
+                            // order with SortedSetDVFacets:
+                            Assert.AreEqual("value @ idx=" + i, dimValues[dim][expectedOrd], fr.LabelValues[i].label);
+                        }
+                    }
+                }
+                else
+                {
+
+                    if (VERBOSE)
+                    {
+                        idx = 0;
+                        Console.WriteLine("      expected (unsorted)");
+                        for (int i = 0; i < dimValues[dim].Length; i++)
+                        {
+                            string value = dimValues[dim][i];
+                            if (expected.Counts[dim][i] != 0)
+                            {
+                                Console.WriteLine("        " + idx + ": " + new BytesRef(value) + ": " + expected.Counts[dim][i]);
+                                idx++;
+                            }
+                        }
+                    }
+
+                    int setCount = 0;
+                    for (int i = 0; i < dimValues[dim].Length; i++)
+                    {
+                        string value = dimValues[dim][i];
+                        if (expected.Counts[dim][i] != 0)
+                        {
+                            Assert.True(actualValues.ContainsKey(value));
+                            Assert.AreEqual(expected.Counts[dim][i], (int)actualValues[value]);
+                            setCount++;
+                        }
+                        else
+                        {
+                            Assert.False(actualValues.ContainsKey(value));
+                        }
+                    }
+                    Assert.AreEqual(setCount, actualValues.Count);
+                }
+            }
+        }
+
+        [Test]
+        public virtual void TestEmptyIndex()
+        {
+            // LUCENE-5045: make sure DrillSideways works with an empty index
+            Directory dir = NewDirectory();
+            Directory taxoDir = NewDirectory();
+            var writer = new RandomIndexWriter(Random(), dir);
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            // Count "Author"
+            FacetsConfig config = new FacetsConfig();
+            DrillSideways ds = new DrillSideways(searcher, config, taxoReader);
+            DrillDownQuery ddq = new DrillDownQuery(config);
+            ddq.Add("Author", "Lisa");
+
+            DrillSidewaysResult r = ds.Search(ddq, 10); // this used to fail on IllegalArgEx
+            Assert.AreEqual(0, r.Hits.TotalHits);
+
+            r = ds.Search(ddq, null, null, 10, new Sort(new SortField("foo", SortField.Type_e.INT)), false, false); // this used to fail on IllegalArgEx
+            Assert.AreEqual(0, r.Hits.TotalHits);
+
+            IOUtils.Close(writer, taxoWriter, searcher.IndexReader, taxoReader, dir, taxoDir);
+        }
+    }
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/TestFacetsConfig.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/TestFacetsConfig.cs b/src/Lucene.Net.Tests.Facet/TestFacetsConfig.cs
new file mode 100644
index 0000000..9c14f79
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/TestFacetsConfig.cs
@@ -0,0 +1,131 @@
+using Lucene.Net.Support;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet
+{
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
+    using Document = Lucene.Net.Documents.Document;
+    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
+    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
+    using DirectoryReader = Lucene.Net.Index.DirectoryReader;
+    using IndexWriter = Lucene.Net.Index.IndexWriter;
+    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
+    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
+    using Directory = Lucene.Net.Store.Directory;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+    using TestUtil = Lucene.Net.Util.TestUtil;
+
+    public class TestFacetsConfig : FacetTestCase
+    {
+
+        [Test]
+        public virtual void TestPathToStringAndBack()
+        {
+            int iters = AtLeast(1000);
+            for (int i = 0; i < iters; i++)
+            {
+                int numParts = TestUtil.NextInt(Random(), 1, 6);
+                string[] parts = new string[numParts];
+                for (int j = 0; j < numParts; j++)
+                {
+                    string s;
+                    while (true)
+                    {
+                        s = TestUtil.RandomUnicodeString(Random());
+                        if (s.Length > 0)
+                        {
+                            break;
+                        }
+                    }
+                    parts[j] = s;
+                }
+
+                string s1 = FacetsConfig.PathToString(parts);
+                string[] parts2 = FacetsConfig.StringToPath(s1);
+                Assert.True(Arrays.Equals(parts, parts2));
+            }
+        }
+
+        [Test]
+        public virtual void TestAddSameDocTwice()
+        {
+            // LUCENE-5367: this was a problem with the previous code, making sure it
+            // works with the new code.
+            Directory indexDir = NewDirectory(), taxoDir = NewDirectory();
+            IndexWriter indexWriter = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            FacetsConfig facetsConfig = new FacetsConfig();
+            Document doc = new Document();
+            doc.Add(new FacetField("a", "b"));
+            doc = facetsConfig.Build(taxoWriter, doc);
+            // these two addDocument() used to fail
+            indexWriter.AddDocument(doc);
+            indexWriter.AddDocument(doc);
+            IOUtils.Close(indexWriter, taxoWriter);
+
+            DirectoryReader indexReader = DirectoryReader.Open(indexDir);
+            DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir);
+            IndexSearcher searcher = NewSearcher(indexReader);
+            FacetsCollector fc = new FacetsCollector();
+            searcher.Search(new MatchAllDocsQuery(), fc);
+
+            Facets facets = GetTaxonomyFacetCounts(taxoReader, facetsConfig, fc);
+            FacetResult res = facets.GetTopChildren(10, "a");
+            Assert.AreEqual(1, res.LabelValues.Length);
+            Assert.AreEqual(2, res.LabelValues[0].value);
+            IOUtils.Close(indexReader, taxoReader);
+
+            IOUtils.Close(indexDir, taxoDir);
+        }
+
+        /// <summary>
+        /// LUCENE-5479 
+        /// </summary>
+        [Test]
+        public virtual void TestCustomDefault()
+        {
+            FacetsConfig config = new FacetsConfigAnonymousInnerClassHelper(this);
+
+            Assert.True(config.GetDimConfig("foobar").Hierarchical);
+        }
+
+        private class FacetsConfigAnonymousInnerClassHelper : FacetsConfig
+        {
+            private readonly TestFacetsConfig outerInstance;
+
+            public FacetsConfigAnonymousInnerClassHelper(TestFacetsConfig outerInstance)
+            {
+                this.outerInstance = outerInstance;
+            }
+
+            protected override DimConfig DefaultDimConfig
+            {
+                get
+                {
+                    DimConfig config = new DimConfig();
+                    config.Hierarchical = true;
+                    return config;
+                }
+            }
+        }
+    }
+
+}
\ No newline at end of file


[12/14] lucenenet git commit: Moving Lucene.Net.Facet tests to their appropriate place

Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/SortedSet/TestSortedSetDocValuesFacets.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/SortedSet/TestSortedSetDocValuesFacets.cs b/src/Lucene.Net.Tests.Facet/SortedSet/TestSortedSetDocValuesFacets.cs
new file mode 100644
index 0000000..091a2c8
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/SortedSet/TestSortedSetDocValuesFacets.cs
@@ -0,0 +1,394 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using Lucene.Net.Randomized;
+using Lucene.Net.Randomized.Generators;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet.SortedSet
+{
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+
+    using Document = Lucene.Net.Documents.Document;
+    using Field = Lucene.Net.Documents.Field;
+    using IndexReader = Lucene.Net.Index.IndexReader;
+    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
+    using SlowCompositeReaderWrapper = Lucene.Net.Index.SlowCompositeReaderWrapper;
+    using Term = Lucene.Net.Index.Term;
+    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
+    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
+    using TermQuery = Lucene.Net.Search.TermQuery;
+    using TopDocs = Lucene.Net.Search.TopDocs;
+    using Directory = Lucene.Net.Store.Directory;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+    using TestUtil = Lucene.Net.Util.TestUtil;
+    
+    [TestFixture]
+    public class TestSortedSetDocValuesFacets : FacetTestCase
+    {
+
+        // NOTE: TestDrillSideways.testRandom also sometimes
+        // randomly uses SortedSetDV
+        [Test]
+        public virtual void TestBasic()
+        {
+
+            AssumeTrue("Test requires SortedSetDV support", DefaultCodecSupportsSortedSet());
+            Directory dir = NewDirectory();
+
+            FacetsConfig config = new FacetsConfig();
+            config.SetMultiValued("a", true);
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            Document doc = new Document();
+            doc.Add(new SortedSetDocValuesFacetField("a", "foo"));
+            doc.Add(new SortedSetDocValuesFacetField("a", "bar"));
+            doc.Add(new SortedSetDocValuesFacetField("a", "zoo"));
+            doc.Add(new SortedSetDocValuesFacetField("b", "baz"));
+            writer.AddDocument(config.Build(doc));
+            if (Random().NextBoolean())
+            {
+                writer.Commit();
+            }
+
+            doc = new Document();
+            doc.Add(new SortedSetDocValuesFacetField("a", "foo"));
+            writer.AddDocument(config.Build(doc));
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+
+            // Per-top-reader state:
+            SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(searcher.IndexReader);
+
+            FacetsCollector c = new FacetsCollector();
+
+            searcher.Search(new MatchAllDocsQuery(), c);
+
+            SortedSetDocValuesFacetCounts facets = new SortedSetDocValuesFacetCounts(state, c);
+
+            Assert.AreEqual("dim=a path=[] value=4 childCount=3\n  foo (2)\n  bar (1)\n  zoo (1)\n", facets.GetTopChildren(10, "a").ToString());
+            Assert.AreEqual("dim=b path=[] value=1 childCount=1\n  baz (1)\n", facets.GetTopChildren(10, "b").ToString());
+
+            // DrillDown:
+            DrillDownQuery q = new DrillDownQuery(config);
+            q.Add("a", "foo");
+            q.Add("b", "baz");
+            TopDocs hits = searcher.Search(q, 1);
+            Assert.AreEqual(1, hits.TotalHits);
+
+            IOUtils.Close(writer, searcher.IndexReader, dir);
+        }
+
+        // LUCENE-5090
+        [Test]
+        public virtual void TestStaleState()
+        {
+            AssumeTrue("Test requires SortedSetDV support", DefaultCodecSupportsSortedSet());
+            Directory dir = NewDirectory();
+
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            FacetsConfig config = new FacetsConfig();
+
+            Document doc = new Document();
+            doc.Add(new SortedSetDocValuesFacetField("a", "foo"));
+            writer.AddDocument(config.Build(doc));
+
+            IndexReader r = writer.Reader;
+            SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(r);
+
+            doc = new Document();
+            doc.Add(new SortedSetDocValuesFacetField("a", "bar"));
+            writer.AddDocument(config.Build(doc));
+
+            doc = new Document();
+            doc.Add(new SortedSetDocValuesFacetField("a", "baz"));
+            writer.AddDocument(config.Build(doc));
+
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+
+            FacetsCollector c = new FacetsCollector();
+
+            searcher.Search(new MatchAllDocsQuery(), c);
+
+            try
+            {
+                new SortedSetDocValuesFacetCounts(state, c);
+                Fail("did not hit expected exception");
+            }
+            catch (IllegalStateException)
+            {
+                // expected
+            }
+
+            r.Dispose();
+            writer.Dispose();
+            searcher.IndexReader.Dispose();
+            dir.Dispose();
+        }
+
+        // LUCENE-5333
+        [Test]
+        public virtual void TestSparseFacets()
+        {
+            AssumeTrue("Test requires SortedSetDV support", DefaultCodecSupportsSortedSet());
+            Directory dir = NewDirectory();
+
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            FacetsConfig config = new FacetsConfig();
+
+            Document doc = new Document();
+            doc.Add(new SortedSetDocValuesFacetField("a", "foo1"));
+            writer.AddDocument(config.Build(doc));
+
+            if (Random().NextBoolean())
+            {
+                writer.Commit();
+            }
+
+            doc = new Document();
+            doc.Add(new SortedSetDocValuesFacetField("a", "foo2"));
+            doc.Add(new SortedSetDocValuesFacetField("b", "bar1"));
+            writer.AddDocument(config.Build(doc));
+
+            if (Random().NextBoolean())
+            {
+                writer.Commit();
+            }
+
+            doc = new Document();
+            doc.Add(new SortedSetDocValuesFacetField("a", "foo3"));
+            doc.Add(new SortedSetDocValuesFacetField("b", "bar2"));
+            doc.Add(new SortedSetDocValuesFacetField("c", "baz1"));
+            writer.AddDocument(config.Build(doc));
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+            writer.Dispose();
+
+            // Per-top-reader state:
+            SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(searcher.IndexReader);
+
+            FacetsCollector c = new FacetsCollector();
+            searcher.Search(new MatchAllDocsQuery(), c);
+            SortedSetDocValuesFacetCounts facets = new SortedSetDocValuesFacetCounts(state, c);
+
+            // Ask for top 10 labels for any dims that have counts:
+            IList<FacetResult> results = facets.GetAllDims(10);
+
+            Assert.AreEqual(3, results.Count);
+            Assert.AreEqual("dim=a path=[] value=3 childCount=3\n  foo1 (1)\n  foo2 (1)\n  foo3 (1)\n", results[0].ToString());
+            Assert.AreEqual("dim=b path=[] value=2 childCount=2\n  bar1 (1)\n  bar2 (1)\n", results[1].ToString());
+            Assert.AreEqual("dim=c path=[] value=1 childCount=1\n  baz1 (1)\n", results[2].ToString());
+
+            searcher.IndexReader.Dispose();
+            dir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestSomeSegmentsMissing()
+        {
+            AssumeTrue("Test requires SortedSetDV support", DefaultCodecSupportsSortedSet());
+            Directory dir = NewDirectory();
+
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            FacetsConfig config = new FacetsConfig();
+
+            Document doc = new Document();
+            doc.Add(new SortedSetDocValuesFacetField("a", "foo1"));
+            writer.AddDocument(config.Build(doc));
+            writer.Commit();
+
+            doc = new Document();
+            writer.AddDocument(config.Build(doc));
+            writer.Commit();
+
+            doc = new Document();
+            doc.Add(new SortedSetDocValuesFacetField("a", "foo2"));
+            writer.AddDocument(config.Build(doc));
+            writer.Commit();
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+            writer.Dispose();
+
+            // Per-top-reader state:
+            SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(searcher.IndexReader);
+
+            FacetsCollector c = new FacetsCollector();
+            searcher.Search(new MatchAllDocsQuery(), c);
+            SortedSetDocValuesFacetCounts facets = new SortedSetDocValuesFacetCounts(state, c);
+
+            // Ask for top 10 labels for any dims that have counts:
+            Assert.AreEqual("dim=a path=[] value=2 childCount=2\n  foo1 (1)\n  foo2 (1)\n", facets.GetTopChildren(10, "a").ToString());
+
+            searcher.IndexReader.Dispose();
+            dir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestSlowCompositeReaderWrapper()
+        {
+            AssumeTrue("Test requires SortedSetDV support", DefaultCodecSupportsSortedSet());
+            Directory dir = NewDirectory();
+
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            FacetsConfig config = new FacetsConfig();
+
+            Document doc = new Document();
+            doc.Add(new SortedSetDocValuesFacetField("a", "foo1"));
+            writer.AddDocument(config.Build(doc));
+
+            writer.Commit();
+
+            doc = new Document();
+            doc.Add(new SortedSetDocValuesFacetField("a", "foo2"));
+            writer.AddDocument(config.Build(doc));
+
+            // NRT open
+            IndexSearcher searcher = new IndexSearcher(SlowCompositeReaderWrapper.Wrap(writer.Reader));
+
+            // Per-top-reader state:
+            SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(searcher.IndexReader);
+
+            FacetsCollector c = new FacetsCollector();
+            searcher.Search(new MatchAllDocsQuery(), c);
+            Facets facets = new SortedSetDocValuesFacetCounts(state, c);
+
+            // Ask for top 10 labels for any dims that have counts:
+            Assert.AreEqual("dim=a path=[] value=2 childCount=2\n  foo1 (1)\n  foo2 (1)\n", facets.GetTopChildren(10, "a").ToString());
+
+            IOUtils.Close(writer, searcher.IndexReader, dir);
+        }
+
+
+        [Test]
+        public virtual void TestRandom()
+        {
+            AssumeTrue("Test requires SortedSetDV support", DefaultCodecSupportsSortedSet());
+            string[] tokens = GetRandomTokens(10);
+            Directory indexDir = NewDirectory();
+            Directory taxoDir = NewDirectory();
+
+            RandomIndexWriter w = new RandomIndexWriter(Random(), indexDir);
+            FacetsConfig config = new FacetsConfig();
+            int numDocs = AtLeast(1000);
+            int numDims = TestUtil.NextInt(Random(), 1, 7);
+            IList<TestDoc> testDocs = GetRandomDocs(tokens, numDocs, numDims);
+            foreach (TestDoc testDoc in testDocs)
+            {
+                Document doc = new Document();
+                doc.Add(NewStringField("content", testDoc.content, Field.Store.NO));
+                for (int j = 0; j < numDims; j++)
+                {
+                    if (testDoc.dims[j] != null)
+                    {
+                        doc.Add(new SortedSetDocValuesFacetField("dim" + j, testDoc.dims[j]));
+                    }
+                }
+                w.AddDocument(config.Build(doc));
+            }
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(w.Reader);
+
+            // Per-top-reader state:
+            SortedSetDocValuesReaderState state = new DefaultSortedSetDocValuesReaderState(searcher.IndexReader);
+
+            int iters = AtLeast(100);
+            for (int iter = 0; iter < iters; iter++)
+            {
+                string searchToken = tokens[Random().Next(tokens.Length)];
+                if (VERBOSE)
+                {
+                    Console.WriteLine("\nTEST: iter content=" + searchToken);
+                }
+                FacetsCollector fc = new FacetsCollector();
+                FacetsCollector.Search(searcher, new TermQuery(new Term("content", searchToken)), 10, fc);
+                Facets facets = new SortedSetDocValuesFacetCounts(state, fc);
+
+                // Slow, yet hopefully bug-free, faceting:
+                var expectedCounts = new List<Dictionary<string, int?>>();
+                for (int i = 0; i < numDims; i++)
+                {
+                    expectedCounts.Add(new Dictionary<string, int?>());
+                }
+
+                foreach (TestDoc doc in testDocs)
+                {
+                    if (doc.content.Equals(searchToken))
+                    {
+                        for (int j = 0; j < numDims; j++)
+                        {
+                            if (doc.dims[j] != null)
+                            {
+                                int? v; 
+                                
+                                if (!expectedCounts[j].TryGetValue(doc.dims[j],out v))
+                                {
+                                    expectedCounts[j][doc.dims[j]] = 1;
+                                }
+                                else
+                                {
+                                    expectedCounts[j][doc.dims[j]] = (int)v + 1;
+                                }
+                            }
+                        }
+                    }
+                }
+
+                IList<FacetResult> expected = new List<FacetResult>();
+                for (int i = 0; i < numDims; i++)
+                {
+                    IList<LabelAndValue> labelValues = new List<LabelAndValue>();
+                    int totCount = 0;
+                    foreach (KeyValuePair<string, int?> ent in expectedCounts[i])
+                    {
+                        labelValues.Add(new LabelAndValue(ent.Key, ent.Value.Value));
+                        totCount += ent.Value.Value;
+                    }
+                    SortLabelValues(labelValues);
+                    if (totCount > 0)
+                    {
+                        expected.Add(new FacetResult("dim" + i, new string[0], totCount, labelValues.ToArray(), labelValues.Count));
+                    }
+                }
+
+                // Sort by highest value, tie break by value:
+                SortFacetResults(expected);
+
+                IList<FacetResult> actual = facets.GetAllDims(10);
+
+                // Messy: fixup ties
+                //sortTies(actual);
+
+                Assert.AreEqual(expected, actual);
+            }
+
+            IOUtils.Close(w, searcher.IndexReader, indexDir, taxoDir);
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Taxonomy/Directory/TestAddTaxonomy.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Taxonomy/Directory/TestAddTaxonomy.cs b/src/Lucene.Net.Tests.Facet/Taxonomy/Directory/TestAddTaxonomy.cs
new file mode 100644
index 0000000..df4f491
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Taxonomy/Directory/TestAddTaxonomy.cs
@@ -0,0 +1,323 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Lucene.Net.Randomized.Generators;
+using Lucene.Net.Support;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet.Taxonomy.Directory
+{
+
+
+    using DiskOrdinalMap = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter.DiskOrdinalMap;
+    using MemoryOrdinalMap = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter.MemoryOrdinalMap;
+    using OrdinalMap = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter.OrdinalMap;
+    using Directory = Lucene.Net.Store.Directory;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+    using TestUtil = Lucene.Net.Util.TestUtil;
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+    [TestFixture]
+    public class TestAddTaxonomy : FacetTestCase
+    {
+        private void Dotest(int ncats, int range)
+        {
+            AtomicInteger numCats = new AtomicInteger(ncats);
+            Directory[] dirs = new Directory[2];
+            for (int i = 0; i < dirs.Length; i++)
+            {
+                dirs[i] = NewDirectory();
+                var tw = new DirectoryTaxonomyWriter(dirs[i]);
+                ThreadClass[] addThreads = new ThreadClass[4];
+                for (int j = 0; j < addThreads.Length; j++)
+                {
+                    addThreads[j] = new ThreadAnonymousInnerClassHelper(this, range, numCats, tw);
+                }
+
+                foreach (ThreadClass t in addThreads)
+                {
+                    t.Start();
+                }
+                foreach (ThreadClass t in addThreads)
+                {
+                    t.Join();
+                }
+
+                tw.Dispose();
+            }
+
+            var tw1 = new DirectoryTaxonomyWriter(dirs[0]);
+            OrdinalMap map = randomOrdinalMap();
+            tw1.AddTaxonomy(dirs[1], map);
+            tw1.Dispose();
+
+            validate(dirs[0], dirs[1], map);
+
+            IOUtils.Close(dirs);
+        }
+
+        private class ThreadAnonymousInnerClassHelper : ThreadClass
+        {
+            private readonly TestAddTaxonomy outerInstance;
+
+            private int range;
+            private AtomicInteger numCats;
+            private DirectoryTaxonomyWriter tw;
+
+            public ThreadAnonymousInnerClassHelper(TestAddTaxonomy outerInstance, int range, AtomicInteger numCats, DirectoryTaxonomyWriter tw)
+            {
+                this.outerInstance = outerInstance;
+                this.range = range;
+                this.numCats = numCats;
+                this.tw = tw;
+            }
+
+            public override void Run()
+            {
+                Random random = Random();
+                while (numCats.DecrementAndGet() > 0)
+                {
+                    string cat = Convert.ToString(random.Next(range));
+                    try
+                    {
+                        tw.AddCategory(new FacetLabel("a", cat));
+                    }
+                    catch (IOException e)
+                    {
+                        throw new Exception(e.Message, e);
+                    }
+                }
+            }
+        }
+
+
+        private OrdinalMap randomOrdinalMap()
+        {
+            if (Random().NextBoolean())
+            {
+                return new DiskOrdinalMap("taxoMap");
+            }
+            else
+            {
+                return new MemoryOrdinalMap();
+            }
+        }
+
+        private void validate(Directory dest, Directory src, OrdinalMap ordMap)
+        {
+            var destTr = new DirectoryTaxonomyReader(dest);
+            try
+            {
+                int destSize = destTr.Size;
+                var srcTR = new DirectoryTaxonomyReader(src);
+                try
+                {
+                    var map = ordMap.Map;
+
+                    // validate taxo sizes
+                    int srcSize = srcTR.Size;
+                    Assert.True(destSize >= srcSize, "destination taxonomy expected to be larger than source; dest=" + destSize + " src=" + srcSize);
+
+                    // validate that all source categories exist in destination, and their
+                    // ordinals are as expected.
+                    for (int j = 1; j < srcSize; j++)
+                    {
+                        FacetLabel cp = srcTR.GetPath(j);
+                        int destOrdinal = destTr.GetOrdinal(cp);
+                        Assert.True(destOrdinal > 0, cp + " not found in destination");
+                        Assert.AreEqual(destOrdinal, map[j]);
+                    }
+                }
+                finally
+                {
+                    ((TaxonomyReader)srcTR).Dispose(true);
+                }
+            }
+            finally
+            {
+                ((TaxonomyReader)destTr).Dispose(true);
+            }
+        }
+
+        [Test]
+        public virtual void TestAddEmpty()
+        {
+            Directory dest = NewDirectory();
+            var destTW = new DirectoryTaxonomyWriter(dest);
+            destTW.AddCategory(new FacetLabel("Author", "Rob Pike"));
+            destTW.AddCategory(new FacetLabel("Aardvarks", "Bob"));
+            destTW.Commit();
+
+            Directory src = NewDirectory();
+            (new DirectoryTaxonomyWriter(src)).Dispose(); // create an empty taxonomy
+
+            OrdinalMap map = randomOrdinalMap();
+            destTW.AddTaxonomy(src, map);
+            destTW.Dispose();
+
+            validate(dest, src, map);
+
+            IOUtils.Close(dest, src);
+        }
+
+        [Test]
+        public virtual void TestAddToEmpty()
+        {
+            Directory dest = NewDirectory();
+
+            Directory src = NewDirectory();
+            DirectoryTaxonomyWriter srcTW = new DirectoryTaxonomyWriter(src);
+            srcTW.AddCategory(new FacetLabel("Author", "Rob Pike"));
+            srcTW.AddCategory(new FacetLabel("Aardvarks", "Bob"));
+            srcTW.Dispose();
+
+            DirectoryTaxonomyWriter destTW = new DirectoryTaxonomyWriter(dest);
+            OrdinalMap map = randomOrdinalMap();
+            destTW.AddTaxonomy(src, map);
+            destTW.Dispose();
+
+            validate(dest, src, map);
+
+            IOUtils.Close(dest, src);
+        }
+
+        // A more comprehensive and big random test.
+        [Test]
+        public virtual void TestBig()
+        {
+            Dotest(200, 10000);
+            Dotest(1000, 20000);
+            Dotest(400000, 1000000);
+        }
+
+        // a reasonable random test
+        [Test]
+        public virtual void TestMedium()
+        {
+            Random random = Random();
+            int numTests = AtLeast(3);
+            for (int i = 0; i < numTests; i++)
+            {
+                Dotest(TestUtil.NextInt(random, 2, 100), TestUtil.NextInt(random, 100, 1000));
+            }
+        }
+
+        [Test]
+        public virtual void TestSimple()
+        {
+            Directory dest = NewDirectory();
+            var tw1 = new DirectoryTaxonomyWriter(dest);
+            tw1.AddCategory(new FacetLabel("Author", "Mark Twain"));
+            tw1.AddCategory(new FacetLabel("Animals", "Dog"));
+            tw1.AddCategory(new FacetLabel("Author", "Rob Pike"));
+
+            Directory src = NewDirectory();
+            var tw2 = new DirectoryTaxonomyWriter(src);
+            tw2.AddCategory(new FacetLabel("Author", "Rob Pike"));
+            tw2.AddCategory(new FacetLabel("Aardvarks", "Bob"));
+            tw2.Dispose();
+
+            OrdinalMap map = randomOrdinalMap();
+
+            tw1.AddTaxonomy(src, map);
+            tw1.Dispose();
+
+            validate(dest, src, map);
+
+            IOUtils.Close(dest, src);
+        }
+
+        [Test]
+        public virtual void TestConcurrency()
+        {
+            // tests that addTaxonomy and addCategory work in parallel
+            int numCategories = AtLeast(10000);
+
+            // build an input taxonomy index
+            Directory src = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(src);
+            for (int i = 0; i < numCategories; i++)
+            {
+                tw.AddCategory(new FacetLabel("a", Convert.ToString(i)));
+            }
+            tw.Dispose();
+
+            // now add the taxonomy to an empty taxonomy, while adding the categories
+            // again, in parallel -- in the end, no duplicate categories should exist.
+            Directory dest = NewDirectory();
+            var destTw = new DirectoryTaxonomyWriter(dest);
+            ThreadClass t = new ThreadAnonymousInnerClassHelper2(this, numCategories, destTw);
+            t.Start();
+
+            OrdinalMap map = new MemoryOrdinalMap();
+            destTw.AddTaxonomy(src, map);
+            t.Join();
+            destTw.Dispose();
+
+            // now validate
+
+            var dtr = new DirectoryTaxonomyReader(dest);
+            // +2 to account for the root category + "a"
+            Assert.AreEqual(numCategories + 2, dtr.Size);
+            var categories = new HashSet<FacetLabel>();
+            for (int i = 1; i < dtr.Size; i++)
+            {
+                FacetLabel cat = dtr.GetPath(i);
+                Assert.True(categories.Add(cat), "category " + cat + " already existed");
+            }
+            dtr.Dispose();
+
+            IOUtils.Close(src, dest);
+        }
+
+        private class ThreadAnonymousInnerClassHelper2 : ThreadClass
+        {
+            private readonly TestAddTaxonomy outerInstance;
+
+            private int numCategories;
+            private Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter destTW;
+
+            public ThreadAnonymousInnerClassHelper2(TestAddTaxonomy outerInstance, int numCategories, Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter destTW)
+            {
+                this.outerInstance = outerInstance;
+                this.numCategories = numCategories;
+                this.destTW = destTW;
+            }
+
+            public override void Run()
+            {
+                for (int i = 0; i < numCategories; i++)
+                {
+                    try
+                    {
+                        destTW.AddCategory(new FacetLabel("a", Convert.ToString(i)));
+                    }
+                    catch (IOException e)
+                    {
+                        // shouldn't happen - if it does, let the test fail on uncaught exception.
+                        throw new Exception(e.Message, e);
+                    }
+                }
+            }
+        }
+
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Taxonomy/Directory/TestConcurrentFacetedIndexing.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Taxonomy/Directory/TestConcurrentFacetedIndexing.cs b/src/Lucene.Net.Tests.Facet/Taxonomy/Directory/TestConcurrentFacetedIndexing.cs
new file mode 100644
index 0000000..5ee17a6
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Taxonomy/Directory/TestConcurrentFacetedIndexing.cs
@@ -0,0 +1,228 @@
+using System;
+using System.Collections.Concurrent;
+using System.IO;
+using System.Threading;
+using Lucene.Net.Support;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet.Taxonomy.Directory
+{
+
+
+    using Document = Lucene.Net.Documents.Document;
+    using TaxonomyWriterCache = Lucene.Net.Facet.Taxonomy.WriterCache.TaxonomyWriterCache;
+    using Cl2oTaxonomyWriterCache = Lucene.Net.Facet.Taxonomy.WriterCache.Cl2oTaxonomyWriterCache;
+    using LruTaxonomyWriterCache = Lucene.Net.Facet.Taxonomy.WriterCache.LruTaxonomyWriterCache;
+    using IndexWriter = Lucene.Net.Index.IndexWriter;
+    using OpenMode = Lucene.Net.Index.IndexWriterConfig.OpenMode_e;
+    using Directory = Lucene.Net.Store.Directory;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+    [TestFixture]
+    public class TestConcurrentFacetedIndexing : FacetTestCase
+    {
+
+        // A No-Op TaxonomyWriterCache which always discards all given categories, and
+        // always returns true in put(), to indicate some cache entries were cleared.
+        private static TaxonomyWriterCache NO_OP_CACHE = new TaxonomyWriterCacheAnonymousInnerClassHelper();
+
+        private class TaxonomyWriterCacheAnonymousInnerClassHelper : TaxonomyWriterCache
+        {
+            public TaxonomyWriterCacheAnonymousInnerClassHelper()
+            {
+            }
+
+
+            public virtual void Close()
+            {
+            }
+            public virtual int Get(FacetLabel categoryPath)
+            {
+                return -1;
+            }
+            public virtual bool Put(FacetLabel categoryPath, int ordinal)
+            {
+                return true;
+            }
+            public virtual bool Full
+            {
+                get
+                {
+                    return true;
+                }
+            }
+            public virtual void Clear()
+            {
+            }
+
+        }
+
+        internal static FacetField NewCategory()
+        {
+            Random r = Random();
+            string l1 = "l1." + r.Next(10); // l1.0-l1.9 (10 categories)
+            string l2 = "l2." + r.Next(30); // l2.0-l2.29 (30 categories)
+            string l3 = "l3." + r.Next(100); // l3.0-l3.99 (100 categories)
+            return new FacetField(l1, l2, l3);
+        }
+
+        internal static TaxonomyWriterCache NewTaxoWriterCache(int ndocs)
+        {
+            double d = Random().NextDouble();
+            if (d < 0.7)
+            {
+                // this is the fastest, yet most memory consuming
+                return new Cl2oTaxonomyWriterCache(1024, 0.15f, 3);
+            }
+            else if (TEST_NIGHTLY && d > 0.98)
+            {
+                // this is the slowest, but tests the writer concurrency when no caching is done.
+                // only pick it during NIGHTLY tests, and even then, with very low chances.
+                return NO_OP_CACHE;
+            }
+            else
+            {
+                // this is slower than CL2O, but less memory consuming, and exercises finding categories on disk too.
+                return new LruTaxonomyWriterCache(ndocs / 10);
+            }
+        }
+
+        [Test]
+        public virtual void TestConcurrency()
+        {
+            AtomicInteger numDocs = new AtomicInteger(AtLeast(10000));
+            Directory indexDir = NewDirectory();
+            Directory taxoDir = NewDirectory();
+            ConcurrentDictionary<string, string> values = new ConcurrentDictionary<string, string>();
+            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, null));
+            var tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE, NewTaxoWriterCache(numDocs.Get()));
+            ThreadClass[] indexThreads = new ThreadClass[AtLeast(4)];
+            FacetsConfig config = new FacetsConfig();
+            for (int i = 0; i < 10; i++)
+            {
+                config.SetHierarchical("l1." + i, true);
+                config.SetMultiValued("l1." + i, true);
+            }
+
+            for (int i = 0; i < indexThreads.Length; i++)
+            {
+                indexThreads[i] = new ThreadAnonymousInnerClassHelper(this, numDocs, values, iw, tw, config);
+            }
+
+            foreach (ThreadClass t in indexThreads)
+            {
+                t.Start();
+            }
+            foreach (ThreadClass t in indexThreads)
+            {
+                t.Join();
+            }
+
+            var tr = new DirectoryTaxonomyReader(tw);
+            // +1 for root category
+            if (values.Count + 1 != tr.Size)
+            {
+                foreach (string value in values.Keys)
+                {
+                    FacetLabel label = new FacetLabel(FacetsConfig.StringToPath(value));
+                    if (tr.GetOrdinal(label) == -1)
+                    {
+                        Console.WriteLine("FAIL: path=" + label + " not recognized");
+                    }
+                }
+                Fail("mismatch number of categories");
+            }
+            int[] parents = tr.ParallelTaxonomyArrays.Parents();
+            foreach (string cat in values.Keys)
+            {
+                FacetLabel cp = new FacetLabel(FacetsConfig.StringToPath(cat));
+                Assert.True(tr.GetOrdinal(cp) > 0, "category not found " + cp);
+                int level = cp.Length;
+                int parentOrd = 0; // for root, parent is always virtual ROOT (ord=0)
+                FacetLabel path = null;
+                for (int i = 0; i < level; i++)
+                {
+                    path = cp.Subpath(i + 1);
+                    int ord = tr.GetOrdinal(path);
+                    Assert.AreEqual(parentOrd, parents[ord], "invalid parent for cp=" + path);
+                    parentOrd = ord; // next level should have this parent
+                }
+            }
+
+            IOUtils.Close(tw, iw, tr, taxoDir, indexDir);
+        }
+
+        private class ThreadAnonymousInnerClassHelper : ThreadClass
+        {
+            private readonly TestConcurrentFacetedIndexing outerInstance;
+
+            private AtomicInteger numDocs;
+            private ConcurrentDictionary<string, string> values;
+            private IndexWriter iw;
+            private Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter tw;
+            private FacetsConfig config;
+
+            public ThreadAnonymousInnerClassHelper(TestConcurrentFacetedIndexing outerInstance, AtomicInteger numDocs, ConcurrentDictionary<string, string> values, IndexWriter iw, Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter tw, FacetsConfig config)
+            {
+                this.outerInstance = outerInstance;
+                this.numDocs = numDocs;
+                this.values = values;
+                this.iw = iw;
+                this.tw = tw;
+                this.config = config;
+            }
+
+
+            public override void Run()
+            {
+                Random random = Random();
+                while (numDocs.DecrementAndGet() > 0)
+                {
+                    try
+                    {
+                        Document doc = new Document();
+                        int numCats = random.Next(3) + 1; // 1-3
+                        while (numCats-- > 0)
+                        {
+                            FacetField ff = NewCategory();
+                            doc.Add(ff);
+
+                            FacetLabel label = new FacetLabel(ff.dim, ff.path);
+                            // add all prefixes to values
+                            int level = label.Length;
+                            while (level > 0)
+                            {
+                                string s = FacetsConfig.PathToString(label.Components, level);
+                                values[s] = s;
+                                --level;
+                            }
+                        }
+                        iw.AddDocument(config.Build(tw, doc));
+                    }
+                    catch (IOException e)
+                    {
+                        throw new Exception(e.Message, e);
+                    }
+                }
+            }
+        }
+
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Taxonomy/Directory/TestDirectoryTaxonomyReader.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Taxonomy/Directory/TestDirectoryTaxonomyReader.cs b/src/Lucene.Net.Tests.Facet/Taxonomy/Directory/TestDirectoryTaxonomyReader.cs
new file mode 100644
index 0000000..15f30df
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Taxonomy/Directory/TestDirectoryTaxonomyReader.cs
@@ -0,0 +1,624 @@
+using System;
+using System.Collections.Generic;
+using Lucene.Net.Randomized.Generators;
+using Lucene.Net.Support;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet.Taxonomy.Directory
+{
+
+
+    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
+    using ChildrenIterator = Lucene.Net.Facet.Taxonomy.TaxonomyReader.ChildrenIterator;
+    using IndexWriter = Lucene.Net.Index.IndexWriter;
+    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
+    using OpenMode = Lucene.Net.Index.IndexWriterConfig.OpenMode_e;
+    using LogByteSizeMergePolicy = Lucene.Net.Index.LogByteSizeMergePolicy;
+    using LogMergePolicy = Lucene.Net.Index.LogMergePolicy;
+    using AlreadyClosedException = Lucene.Net.Store.AlreadyClosedException;
+    using Directory = Lucene.Net.Store.Directory;
+    using RAMDirectory = Lucene.Net.Store.RAMDirectory;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    public class TestDirectoryTaxonomyReader : FacetTestCase
+    {
+
+        [Test]
+        public virtual void TestCloseAfterIncRef()
+        {
+            Directory dir = NewDirectory();
+            var ltw = new DirectoryTaxonomyWriter(dir);
+            ltw.AddCategory(new FacetLabel("a"));
+            ltw.Dispose();
+
+            DirectoryTaxonomyReader ltr = new DirectoryTaxonomyReader(dir);
+            ltr.IncRef();
+            ltr.Dispose();
+
+            // should not fail as we IncRef() before close
+            var tmpSie = ltr.Size;
+            ltr.DecRef();
+
+            dir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestCloseTwice()
+        {
+            Directory dir = NewDirectory();
+            var ltw = new DirectoryTaxonomyWriter(dir);
+            ltw.AddCategory(new FacetLabel("a"));
+            ltw.Dispose();
+
+            var ltr = new DirectoryTaxonomyReader(dir);
+            (ltr).Dispose();
+            (ltr).Dispose(); // no exception should be thrown
+
+            dir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestOpenIfChangedResult()
+        {
+            Directory dir = null;
+            DirectoryTaxonomyWriter ltw = null;
+            DirectoryTaxonomyReader ltr = null;
+
+            try
+            {
+                dir = NewDirectory();
+                ltw = new DirectoryTaxonomyWriter(dir);
+
+                ltw.AddCategory(new FacetLabel("a"));
+                ltw.Commit();
+
+                ltr = new DirectoryTaxonomyReader(dir);
+                Assert.Null(TaxonomyReader.OpenIfChanged(ltr), "Nothing has changed");
+
+                ltw.AddCategory(new FacetLabel("b"));
+                ltw.Commit();
+
+                DirectoryTaxonomyReader newtr = TaxonomyReader.OpenIfChanged(ltr);
+                Assert.NotNull(newtr, "changes were committed");
+                Assert.Null(TaxonomyReader.OpenIfChanged(newtr), "Nothing has changed");
+                (newtr).Dispose();
+            }
+            finally
+            {
+                IOUtils.Close(ltw, ltr, dir);
+            }
+        }
+
+        [Test]
+        public virtual void TestAlreadyClosed()
+        {
+            Directory dir = NewDirectory();
+            var ltw = new DirectoryTaxonomyWriter(dir);
+            ltw.AddCategory(new FacetLabel("a"));
+            ltw.Dispose();
+
+            var ltr = new DirectoryTaxonomyReader(dir);
+            ltr.Dispose();
+            try
+            {
+                var tmpSize = ltr.Size;
+                Fail("An AlreadyClosedException should have been thrown here");
+            }
+            catch (AlreadyClosedException)
+            {
+                // good!
+            }
+            dir.Dispose();
+        }
+
+        /// <summary>
+        /// recreating a taxonomy should work well with a freshly opened taxonomy reader 
+        /// </summary>
+        [Test]
+        public virtual void TestFreshReadRecreatedTaxonomy()
+        {
+            doTestReadRecreatedTaxonomy(Random(), true);
+        }
+
+        [Test]
+        public virtual void TestOpenIfChangedReadRecreatedTaxonomy()
+        {
+            doTestReadRecreatedTaxonomy(Random(), false);
+        }
+        
+        private void doTestReadRecreatedTaxonomy(Random random, bool closeReader)
+        {
+            Directory dir = null;
+            TaxonomyWriter tw = null;
+            TaxonomyReader tr = null;
+
+            // prepare a few categories
+            int n = 10;
+            FacetLabel[] cp = new FacetLabel[n];
+            for (int i = 0; i < n; i++)
+            {
+                cp[i] = new FacetLabel("a", Convert.ToString(i));
+            }
+
+            try
+            {
+                dir = NewDirectory();
+
+                tw = new DirectoryTaxonomyWriter(dir);
+                tw.AddCategory(new FacetLabel("a"));
+                tw.Dispose();
+
+                tr = new DirectoryTaxonomyReader(dir);
+                int baseNumCategories = tr.Size;
+
+                for (int i = 0; i < n; i++)
+                {
+                    int k = random.Next(n);
+                    tw = new DirectoryTaxonomyWriter(dir, IndexWriterConfig.OpenMode_e.CREATE);
+                    for (int j = 0; j <= k; j++)
+                    {
+                        tw.AddCategory(cp[j]);
+                    }
+                    tw.Dispose();
+                    if (closeReader)
+                    {
+                        tr.Dispose(true);
+                        tr = new DirectoryTaxonomyReader(dir);
+                    }
+                    else
+                    {
+                        var newtr = TaxonomyReader.OpenIfChanged(tr);
+                        Assert.NotNull(newtr);
+                        tr.Dispose(true);
+                        tr = newtr;
+                    }
+                    Assert.AreEqual(baseNumCategories + 1 + k, tr.Size, "Wrong #categories in taxonomy (i=" + i + ", k=" + k + ")");
+                }
+            }
+            finally
+            {
+                IOUtils.Close(tr as DirectoryTaxonomyReader, tw, dir);
+            }
+        }
+
+        [Test]
+        public virtual void TestOpenIfChangedAndRefCount()
+        {
+            Directory dir = new RAMDirectory(); // no need for random directories here
+
+            var taxoWriter = new DirectoryTaxonomyWriter(dir);
+            taxoWriter.AddCategory(new FacetLabel("a"));
+            taxoWriter.Commit();
+
+            var taxoReader = new DirectoryTaxonomyReader(dir);
+            Assert.AreEqual(1, taxoReader.RefCount, "wrong refCount");
+
+            taxoReader.IncRef();
+            Assert.AreEqual(2, taxoReader.RefCount, "wrong refCount");
+
+            taxoWriter.AddCategory(new FacetLabel("a", "b"));
+            taxoWriter.Commit();
+            var newtr = TaxonomyReader.OpenIfChanged(taxoReader);
+            Assert.NotNull(newtr);
+            taxoReader.Dispose();
+            taxoReader = newtr;
+            Assert.AreEqual(1, taxoReader.RefCount, "wrong refCount");
+
+            taxoWriter.Dispose();
+            taxoReader.Dispose();
+            dir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestOpenIfChangedManySegments()
+        {
+            // test openIfChanged() when the taxonomy contains many segments
+            Directory dir = NewDirectory();
+
+            DirectoryTaxonomyWriter writer = new DirectoryTaxonomyWriterAnonymousInnerClassHelper(this, dir);
+            var reader = new DirectoryTaxonomyReader(writer);
+
+            int numRounds = Random().Next(10) + 10;
+            int numCategories = 1; // one for root
+            for (int i = 0; i < numRounds; i++)
+            {
+                int numCats = Random().Next(4) + 1;
+                for (int j = 0; j < numCats; j++)
+                {
+                    writer.AddCategory(new FacetLabel(Convert.ToString(i), Convert.ToString(j)));
+                }
+                numCategories += numCats + 1; // one for round-parent
+                var newtr = TaxonomyReader.OpenIfChanged(reader);
+                Assert.NotNull(newtr);
+                reader.Dispose();
+                reader = newtr;
+
+                // assert categories
+                Assert.AreEqual(numCategories, reader.Size);
+                int roundOrdinal = reader.GetOrdinal(new FacetLabel(Convert.ToString(i)));
+                int[] parents = reader.ParallelTaxonomyArrays.Parents();
+                Assert.AreEqual(0, parents[roundOrdinal]); // round's parent is root
+                for (int j = 0; j < numCats; j++)
+                {
+                    int ord = reader.GetOrdinal(new FacetLabel(Convert.ToString(i), Convert.ToString(j)));
+                    Assert.AreEqual(roundOrdinal, parents[ord]); // round's parent is root
+                }
+            }
+
+            reader.Dispose();
+            writer.Dispose();
+            dir.Dispose();
+        }
+
+        private class DirectoryTaxonomyWriterAnonymousInnerClassHelper : DirectoryTaxonomyWriter
+        {
+            private readonly TestDirectoryTaxonomyReader outerInstance;
+
+            public DirectoryTaxonomyWriterAnonymousInnerClassHelper(TestDirectoryTaxonomyReader outerInstance, Directory dir)
+                : base(dir)
+            {
+                this.outerInstance = outerInstance;
+            }
+
+            protected override IndexWriterConfig CreateIndexWriterConfig(IndexWriterConfig.OpenMode_e openMode)
+            {
+                IndexWriterConfig conf = base.CreateIndexWriterConfig(openMode);
+                LogMergePolicy lmp = (LogMergePolicy)conf.MergePolicy;
+                lmp.MergeFactor = 2;
+                return conf;
+            }
+        }
+
+        [Test]
+        public virtual void TestOpenIfChangedMergedSegment()
+        {
+            // test openIfChanged() when all index segments were merged - used to be
+            // a bug in ParentArray, caught by testOpenIfChangedManySegments - only
+            // this test is not random
+            Directory dir = NewDirectory();
+
+            // hold onto IW to forceMerge
+            // note how we don't close it, since DTW will close it.
+            IndexWriter iw = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetMergePolicy(new LogByteSizeMergePolicy()));
+            var writer = new DirectoryTaxonomyWriterAnonymousInnerClassHelper2(this, dir, iw) as DirectoryTaxonomyWriter;
+
+            var reader = new DirectoryTaxonomyReader(writer);
+            Assert.AreEqual(1, reader.Size);
+            Assert.AreEqual(1, reader.ParallelTaxonomyArrays.Parents().Length);
+
+            // add category and call forceMerge -- this should flush IW and merge segments down to 1
+            // in ParentArray.initFromReader, this used to fail assuming there are no parents.
+            writer.AddCategory(new FacetLabel("1"));
+            iw.ForceMerge(1);
+
+            // now calling openIfChanged should trip on the bug
+            var newtr = TaxonomyReader.OpenIfChanged(reader);
+            Assert.NotNull(newtr);
+            reader.Dispose();
+            reader = newtr;
+            Assert.AreEqual(2, reader.Size);
+            Assert.AreEqual(2, reader.ParallelTaxonomyArrays.Parents().Length);
+
+            reader.Dispose();
+            writer.Dispose();
+            dir.Dispose();
+        }
+
+        private class DirectoryTaxonomyWriterAnonymousInnerClassHelper2 : DirectoryTaxonomyWriter
+        {
+            private readonly TestDirectoryTaxonomyReader outerInstance;
+
+            private IndexWriter iw;
+            private IndexWriterConfig config;
+
+            public DirectoryTaxonomyWriterAnonymousInnerClassHelper2(TestDirectoryTaxonomyReader outerInstance, Directory dir, IndexWriter iw) : base(dir)
+            {
+                this.outerInstance = outerInstance;
+                this.iw = iw;
+            }
+
+            protected override IndexWriter OpenIndexWriter(Directory directory, IndexWriterConfig config) 
+            {   
+                return iw;
+            }
+        }
+
+        [Test]
+        public virtual void TestOpenIfChangedNoChangesButSegmentMerges()
+        {
+            // test openIfChanged() when the taxonomy hasn't really changed, but segments
+            // were merged. The NRT reader will be reopened, and ParentArray used to assert
+            // that the new reader contains more ordinals than were given from the old
+            // TaxReader version
+            Directory dir = NewDirectory();
+
+            // hold onto IW to forceMerge
+            // note how we don't close it, since DTW will close it.
+            var iw = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetMergePolicy(new LogByteSizeMergePolicy()));
+            DirectoryTaxonomyWriter writer = new DirectoryTaxonomyWriterAnonymousInnerClassHelper3(this, dir, iw);
+
+
+            // add a category so that the following DTR open will cause a flush and 
+            // a new segment will be created
+            writer.AddCategory(new FacetLabel("a"));
+
+            var reader = new DirectoryTaxonomyReader(writer);
+            Assert.AreEqual(2, reader.Size);
+            Assert.AreEqual(2, reader.ParallelTaxonomyArrays.Parents().Length);
+
+            // merge all the segments so that NRT reader thinks there's a change 
+            iw.ForceMerge(1);
+
+            // now calling openIfChanged should trip on the wrong assert in ParetArray's ctor
+            var newtr = TaxonomyReader.OpenIfChanged(reader);
+            Assert.NotNull(newtr);
+            reader.Dispose();
+            reader = newtr;
+            Assert.AreEqual(2, reader.Size);
+            Assert.AreEqual(2, reader.ParallelTaxonomyArrays.Parents().Length);
+
+            reader.Dispose();
+            writer.Dispose();
+            dir.Dispose();
+        }
+
+        private class DirectoryTaxonomyWriterAnonymousInnerClassHelper3 : DirectoryTaxonomyWriter
+        {
+            private readonly TestDirectoryTaxonomyReader outerInstance;
+
+            private IndexWriter iw;
+
+            public DirectoryTaxonomyWriterAnonymousInnerClassHelper3(TestDirectoryTaxonomyReader outerInstance, Directory dir, IndexWriter iw)
+                : base(dir)
+            {
+                this.outerInstance = outerInstance;
+                this.iw = iw;
+            }
+
+            protected override IndexWriter OpenIndexWriter(Directory directory, IndexWriterConfig config)
+            {
+                return iw;
+            }
+        }
+
+        [Test]
+        public virtual void TestOpenIfChangedReuseAfterRecreate()
+        {
+            // tests that if the taxonomy is recreated, no data is reused from the previous taxonomy
+            Directory dir = NewDirectory();
+            DirectoryTaxonomyWriter writer = new DirectoryTaxonomyWriter(dir);
+            FacetLabel cp_a = new FacetLabel("a");
+            writer.AddCategory(cp_a);
+            writer.Dispose();
+
+            DirectoryTaxonomyReader r1 = new DirectoryTaxonomyReader(dir);
+            // fill r1's caches
+            Assert.AreEqual(1, r1.GetOrdinal(cp_a));
+            Assert.AreEqual(cp_a, r1.GetPath(1));
+
+            // now recreate, add a different category
+            writer = new DirectoryTaxonomyWriter(dir, IndexWriterConfig.OpenMode_e.CREATE);
+            FacetLabel cp_b = new FacetLabel("b");
+            writer.AddCategory(cp_b);
+            writer.Dispose();
+
+            DirectoryTaxonomyReader r2 = TaxonomyReader.OpenIfChanged(r1);
+            Assert.NotNull(r2);
+
+            // fill r2's caches
+            Assert.AreEqual(1, r2.GetOrdinal(cp_b));
+            Assert.AreEqual(cp_b, r2.GetPath(1));
+
+            // check that r1 doesn't see cp_b
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r1.GetOrdinal(cp_b));
+            Assert.AreEqual(cp_a, r1.GetPath(1));
+
+            // check that r2 doesn't see cp_a
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r2.GetOrdinal(cp_a));
+            Assert.AreEqual(cp_b, r2.GetPath(1));
+
+            (r2).Dispose();
+            (r1).Dispose();
+            dir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestOpenIfChangedReuse()
+        {
+            // test the reuse of data from the old DTR instance
+            foreach (bool nrt in new bool[] { false, true })
+            {
+                Directory dir = NewDirectory();
+                DirectoryTaxonomyWriter writer = new DirectoryTaxonomyWriter(dir);
+
+                FacetLabel cp_a = new FacetLabel("a");
+                writer.AddCategory(cp_a);
+                if (!nrt)
+                {
+                    writer.Commit();
+                }
+
+                DirectoryTaxonomyReader r1 = nrt ? new DirectoryTaxonomyReader(writer) : new DirectoryTaxonomyReader(dir);
+                // fill r1's caches
+                Assert.AreEqual(1, r1.GetOrdinal(cp_a));
+                Assert.AreEqual(cp_a, r1.GetPath(1));
+
+                FacetLabel cp_b = new FacetLabel("b");
+                writer.AddCategory(cp_b);
+                if (!nrt)
+                {
+                    writer.Commit();
+                }
+
+                DirectoryTaxonomyReader r2 = TaxonomyReader.OpenIfChanged(r1);
+                Assert.NotNull(r2);
+
+                // add r2's categories to the caches
+                Assert.AreEqual(2, r2.GetOrdinal(cp_b));
+                Assert.AreEqual(cp_b, r2.GetPath(2));
+
+                // check that r1 doesn't see cp_b
+                Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r1.GetOrdinal(cp_b));
+                Assert.Null(r1.GetPath(2));
+
+                (r1).Dispose();
+                (r2).Dispose();
+                writer.Dispose();
+                dir.Dispose();
+            }
+        }
+
+        [Test]
+        public virtual void TestOpenIfChangedReplaceTaxonomy()
+        {
+            // test openIfChanged when replaceTaxonomy is called, which is equivalent to recreate
+            // only can work with NRT as well
+            Directory src = NewDirectory();
+            DirectoryTaxonomyWriter w = new DirectoryTaxonomyWriter(src);
+            FacetLabel cp_b = new FacetLabel("b");
+            w.AddCategory(cp_b);
+            w.Dispose();
+
+            foreach (bool nrt in new bool[] { false, true })
+            {
+                Directory dir = NewDirectory();
+                var writer = new DirectoryTaxonomyWriter(dir);
+
+                FacetLabel cp_a = new FacetLabel("a");
+                writer.AddCategory(cp_a);
+                if (!nrt)
+                {
+                    writer.Commit();
+                }
+
+                DirectoryTaxonomyReader r1 = nrt ? new DirectoryTaxonomyReader(writer) : new DirectoryTaxonomyReader(dir);
+                // fill r1's caches
+                Assert.AreEqual(1, r1.GetOrdinal(cp_a));
+                Assert.AreEqual(cp_a, r1.GetPath(1));
+
+                // now replace taxonomy
+                writer.ReplaceTaxonomy(src);
+                if (!nrt)
+                {
+                    writer.Commit();
+                }
+
+                DirectoryTaxonomyReader r2 = TaxonomyReader.OpenIfChanged(r1);
+                Assert.NotNull(r2);
+
+                // fill r2's caches
+                Assert.AreEqual(1, r2.GetOrdinal(cp_b));
+                Assert.AreEqual(cp_b, r2.GetPath(1));
+
+                // check that r1 doesn't see cp_b
+                Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r1.GetOrdinal(cp_b));
+                Assert.AreEqual(cp_a, r1.GetPath(1));
+
+                // check that r2 doesn't see cp_a
+                Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, r2.GetOrdinal(cp_a));
+                Assert.AreEqual(cp_b, r2.GetPath(1));
+
+                (r2).Dispose();
+                (r1).Dispose();
+                writer.Dispose();
+                dir.Dispose();
+            }
+
+            src.Dispose();
+        }
+
+        [Test]
+        public virtual void TestGetChildren()
+        {
+            Directory dir = NewDirectory();
+            var taxoWriter = new DirectoryTaxonomyWriter(dir);
+            int numCategories = AtLeast(10);
+            int numA = 0, numB = 0;
+            Random random = Random();
+            // add the two categories for which we'll also add children (so asserts are simpler)
+            taxoWriter.AddCategory(new FacetLabel("a"));
+            taxoWriter.AddCategory(new FacetLabel("b"));
+            for (int i = 0; i < numCategories; i++)
+            {
+                if (random.NextBoolean())
+                {
+                    taxoWriter.AddCategory(new FacetLabel("a", Convert.ToString(i)));
+                    ++numA;
+                }
+                else
+                {
+                    taxoWriter.AddCategory(new FacetLabel("b", Convert.ToString(i)));
+                    ++numB;
+                }
+            }
+            // add category with no children
+            taxoWriter.AddCategory(new FacetLabel("c"));
+            taxoWriter.Dispose();
+
+            var taxoReader = new DirectoryTaxonomyReader(dir);
+
+            // non existing category
+            TaxonomyReader.ChildrenIterator it = taxoReader.GetChildren(taxoReader.GetOrdinal(new FacetLabel("invalid")));
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, it.Next());
+
+            // a category with no children
+            it = taxoReader.GetChildren(taxoReader.GetOrdinal(new FacetLabel("c")));
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, it.Next());
+
+            // arbitrary negative ordinal
+            it = taxoReader.GetChildren(-2);
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, it.Next());
+
+            // root's children
+            var roots = new HashSet<string>(Arrays.AsList("a", "b", "c"));
+            it = taxoReader.GetChildren(TaxonomyReader.ROOT_ORDINAL);
+            while (roots.Count > 0)
+            {
+                FacetLabel root = taxoReader.GetPath(it.Next());
+                Assert.AreEqual(1, root.Length);
+                Assert.True(roots.Remove(root.Components[0]));
+            }
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, it.Next());
+
+            for (int i = 0; i < 2; i++)
+            {
+                FacetLabel cp = i == 0 ? new FacetLabel("a") : new FacetLabel("b");
+                int ordinal = taxoReader.GetOrdinal(cp);
+                it = taxoReader.GetChildren(ordinal);
+                int numChildren = 0;
+                int child;
+                while ((child = it.Next()) != TaxonomyReader.INVALID_ORDINAL)
+                {
+                    FacetLabel path = taxoReader.GetPath(child);
+                    Assert.AreEqual(2, path.Length);
+                    Assert.AreEqual(path.Components[0], i == 0 ? "a" : "b");
+                    ++numChildren;
+                }
+                int expected = i == 0 ? numA : numB;
+                Assert.AreEqual(expected, numChildren, "invalid num children");
+            }
+            taxoReader.Dispose();
+
+            dir.Dispose();
+        }
+
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Taxonomy/Directory/TestDirectoryTaxonomyWriter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Taxonomy/Directory/TestDirectoryTaxonomyWriter.cs b/src/Lucene.Net.Tests.Facet/Taxonomy/Directory/TestDirectoryTaxonomyWriter.cs
new file mode 100644
index 0000000..f5ddd11
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Taxonomy/Directory/TestDirectoryTaxonomyWriter.cs
@@ -0,0 +1,588 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using System.IO;
+using System.Threading;
+using Lucene.Net.Support;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet.Taxonomy.Directory
+{
+
+
+    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
+    using Document = Lucene.Net.Documents.Document;
+    using MemoryOrdinalMap = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter.MemoryOrdinalMap;
+    using TaxonomyWriterCache = Lucene.Net.Facet.Taxonomy.WriterCache.TaxonomyWriterCache;
+    using Cl2oTaxonomyWriterCache = Lucene.Net.Facet.Taxonomy.WriterCache.Cl2oTaxonomyWriterCache;
+    using LruTaxonomyWriterCache = Lucene.Net.Facet.Taxonomy.WriterCache.LruTaxonomyWriterCache;
+    using DirectoryReader = Lucene.Net.Index.DirectoryReader;
+    using IndexReader = Lucene.Net.Index.IndexReader;
+    using IndexWriter = Lucene.Net.Index.IndexWriter;
+    using OpenMode = Lucene.Net.Index.IndexWriterConfig.OpenMode_e;
+    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
+    using SegmentInfos = Lucene.Net.Index.SegmentInfos;
+    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
+    using AlreadyClosedException = Lucene.Net.Store.AlreadyClosedException;
+    using Directory = Lucene.Net.Store.Directory;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+    using TestUtil = Lucene.Net.Util.TestUtil;
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    public class TestDirectoryTaxonomyWriter : FacetTestCase
+    {
+
+        // A No-Op TaxonomyWriterCache which always discards all given categories, and
+        // always returns true in put(), to indicate some cache entries were cleared.
+        private static TaxonomyWriterCache NO_OP_CACHE = new TaxonomyWriterCacheAnonymousInnerClassHelper();
+
+        private class TaxonomyWriterCacheAnonymousInnerClassHelper : TaxonomyWriterCache
+        {
+            public TaxonomyWriterCacheAnonymousInnerClassHelper()
+            {
+            }
+
+
+            public virtual void Close()
+            {
+            }
+            public virtual int Get(FacetLabel categoryPath)
+            {
+                return -1;
+            }
+            public virtual bool Put(FacetLabel categoryPath, int ordinal)
+            {
+                return true;
+            }
+            public virtual bool Full
+            {
+                get
+                {
+                    return true;
+                }
+            }
+            public virtual void Clear()
+            {
+            }
+
+        }
+
+        [Test]
+        public virtual void TestCommit()
+        {
+            // Verifies that nothing is committed to the underlying Directory, if
+            // commit() wasn't called.
+            Directory dir = NewDirectory();
+            var ltw = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
+            Assert.False(DirectoryReader.IndexExists(dir));
+            ltw.Commit(); // first commit, so that an index will be created
+            ltw.AddCategory(new FacetLabel("a"));
+
+            IndexReader r = DirectoryReader.Open(dir);
+            Assert.AreEqual(1, r.NumDocs, "No categories should have been committed to the underlying directory");
+            r.Dispose();
+            ltw.Dispose();
+            dir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestCommitUserData()
+        {
+            // Verifies taxonomy commit data
+            Directory dir = NewDirectory();
+            var taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
+            taxoWriter.AddCategory(new FacetLabel("a"));
+            taxoWriter.AddCategory(new FacetLabel("b"));
+            IDictionary<string, string> userCommitData = new Dictionary<string, string>();
+            userCommitData["testing"] = "1 2 3";
+            taxoWriter.CommitData = userCommitData;
+            taxoWriter.Dispose();
+            var r = DirectoryReader.Open(dir);
+            Assert.AreEqual(3, r.NumDocs, "2 categories plus root should have been committed to the underlying directory");
+            var readUserCommitData = r.IndexCommit.UserData;
+            Assert.True("1 2 3".Equals(readUserCommitData["testing"]), "wrong value extracted from commit data");
+            Assert.NotNull(DirectoryTaxonomyWriter.INDEX_EPOCH + " not found in commitData", readUserCommitData[DirectoryTaxonomyWriter.INDEX_EPOCH]);
+            r.Dispose();
+
+            // open DirTaxoWriter again and commit, INDEX_EPOCH should still exist
+            // in the commit data, otherwise DirTaxoReader.refresh() might not detect
+            // that the taxonomy index has been recreated.
+            taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
+            taxoWriter.AddCategory(new FacetLabel("c")); // add a category so that commit will happen
+
+
+            taxoWriter.CommitData = new Dictionary<string, string>()
+		    {
+			    {"just", "data"}
+		    };
+            taxoWriter.Commit();
+
+            // verify taxoWriter.getCommitData()
+            Assert.NotNull(DirectoryTaxonomyWriter.INDEX_EPOCH + " not found in taoxWriter.commitData", taxoWriter.CommitData[DirectoryTaxonomyWriter.INDEX_EPOCH]);
+            taxoWriter.Dispose();
+
+            r = DirectoryReader.Open(dir);
+            readUserCommitData = r.IndexCommit.UserData;
+            Assert.NotNull(DirectoryTaxonomyWriter.INDEX_EPOCH + " not found in commitData", readUserCommitData[DirectoryTaxonomyWriter.INDEX_EPOCH]);
+            r.Dispose();
+
+            dir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestRollback()
+        {
+            // Verifies that if rollback is called, DTW is closed.
+            Directory dir = NewDirectory();
+            var dtw = new DirectoryTaxonomyWriter(dir);
+            dtw.AddCategory(new FacetLabel("a"));
+            dtw.Rollback();
+            try
+            {
+                dtw.AddCategory(new FacetLabel("a"));
+                Fail("should not have succeeded to add a category following rollback.");
+            }
+            catch (AlreadyClosedException)
+            {
+                // expected
+            }
+
+            dir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestRecreateRollback()
+        {
+            // Tests rollback with OpenMode.CREATE
+            Directory dir = NewDirectory();
+            (new DirectoryTaxonomyWriter(dir)).Dispose();
+            Assert.AreEqual(1, getEpoch(dir));
+            (new DirectoryTaxonomyWriter(dir, OpenMode.CREATE)).Rollback();
+            Assert.AreEqual(1, getEpoch(dir));
+
+            dir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestEnsureOpen()
+        {
+            // verifies that an exception is thrown if DTW was closed
+            Directory dir = NewDirectory();
+            DirectoryTaxonomyWriter dtw = new DirectoryTaxonomyWriter(dir);
+            dtw.Dispose();
+            try
+            {
+                dtw.AddCategory(new FacetLabel("a"));
+                Fail("should not have succeeded to add a category following close.");
+            }
+            catch (AlreadyClosedException)
+            {
+                // expected
+            }
+            dir.Dispose();
+        }
+
+        [Test]
+        private void TouchTaxo(DirectoryTaxonomyWriter taxoWriter, FacetLabel cp)
+        {
+            taxoWriter.AddCategory(cp);
+            taxoWriter.CommitData = new Dictionary<string, string>()
+		{
+			{"just", "data"}
+		};
+            taxoWriter.Commit();
+        }
+
+        [Test]
+        public virtual void TestRecreateAndRefresh()
+        {
+            // DirTaxoWriter lost the INDEX_EPOCH property if it was opened in
+            // CREATE_OR_APPEND (or commit(userData) called twice), which could lead to
+            // DirTaxoReader succeeding to refresh().
+            Directory dir = NewDirectory();
+
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
+            TouchTaxo(taxoWriter, new FacetLabel("a"));
+
+            var taxoReader = new DirectoryTaxonomyReader(dir);
+
+            TouchTaxo(taxoWriter, new FacetLabel("b"));
+
+            var newtr = TaxonomyReader.OpenIfChanged(taxoReader);
+            taxoReader.Dispose();
+            taxoReader = newtr;
+            Assert.AreEqual(1, Convert.ToInt32(taxoReader.CommitUserData[DirectoryTaxonomyWriter.INDEX_EPOCH]));
+
+            // now recreate the taxonomy, and check that the epoch is preserved after opening DirTW again.
+            taxoWriter.Dispose();
+            taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE, NO_OP_CACHE);
+            TouchTaxo(taxoWriter, new FacetLabel("c"));
+            taxoWriter.Dispose();
+
+            taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
+            TouchTaxo(taxoWriter, new FacetLabel("d"));
+            taxoWriter.Dispose();
+
+            newtr = TaxonomyReader.OpenIfChanged(taxoReader);
+            taxoReader.Dispose();
+            taxoReader = newtr;
+            Assert.AreEqual(2, Convert.ToInt32(taxoReader.CommitUserData[DirectoryTaxonomyWriter.INDEX_EPOCH]));
+
+            taxoReader.Dispose();
+            dir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestBackwardsCompatibility()
+        {
+            // tests that if the taxonomy index doesn't have the INDEX_EPOCH
+            // property (supports pre-3.6 indexes), all still works.
+            Directory dir = NewDirectory();
+
+            // create an empty index first, so that DirTaxoWriter initializes indexEpoch to 1.
+            (new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, null))).Dispose();
+
+            var taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE_OR_APPEND, NO_OP_CACHE);
+            taxoWriter.Dispose();
+
+            var taxoReader = new DirectoryTaxonomyReader(dir);
+            Assert.AreEqual(1, Convert.ToInt32(taxoReader.CommitUserData[DirectoryTaxonomyWriter.INDEX_EPOCH]));
+            Assert.Null(TaxonomyReader.OpenIfChanged(taxoReader));
+            (taxoReader).Dispose();
+
+            dir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestConcurrency()
+        {
+            int ncats = AtLeast(100000); // add many categories
+            int range = ncats * 3; // affects the categories selection
+            AtomicInteger numCats = new AtomicInteger(ncats);
+            Directory dir = NewDirectory();
+            var values = new ConcurrentDictionary<string, string>();
+            double d = Random().NextDouble();
+            TaxonomyWriterCache cache;
+            if (d < 0.7)
+            {
+                // this is the fastest, yet most memory consuming
+                cache = new Cl2oTaxonomyWriterCache(1024, 0.15f, 3);
+            }
+            else if (TEST_NIGHTLY && d > 0.98)
+            {
+                // this is the slowest, but tests the writer concurrency when no caching is done.
+                // only pick it during NIGHTLY tests, and even then, with very low chances.
+                cache = NO_OP_CACHE;
+            }
+            else
+            {
+                // this is slower than CL2O, but less memory consuming, and exercises finding categories on disk too.
+                cache = new LruTaxonomyWriterCache(ncats / 10);
+            }
+            if (VERBOSE)
+            {
+                Console.WriteLine("TEST: use cache=" + cache);
+            }
+            var tw = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE, cache);
+            ThreadClass[] addThreads = new ThreadClass[AtLeast(4)];
+            for (int z = 0; z < addThreads.Length; z++)
+            {
+                addThreads[z] = new ThreadAnonymousInnerClassHelper(this, range, numCats, values, tw);
+            }
+
+            foreach (var t in addThreads)
+            {
+                t.Start();
+            }
+            foreach (var t in addThreads)
+            {
+                t.Join();
+            }
+            tw.Dispose();
+
+            DirectoryTaxonomyReader dtr = new DirectoryTaxonomyReader(dir);
+            // +1 for root category
+            if (values.Count + 1 != dtr.Size)
+            {
+                foreach (string value in values.Keys)
+                {
+                    FacetLabel label = new FacetLabel(FacetsConfig.StringToPath(value));
+                    if (dtr.GetOrdinal(label) == -1)
+                    {
+                        Console.WriteLine("FAIL: path=" + label + " not recognized");
+                    }
+                }
+                Fail("mismatch number of categories");
+            }
+
+            int[] parents = dtr.ParallelTaxonomyArrays.Parents();
+            foreach (string cat in values.Keys)
+            {
+                FacetLabel cp = new FacetLabel(FacetsConfig.StringToPath(cat));
+                Assert.True(dtr.GetOrdinal(cp) > 0, "category not found " + cp);
+                int level = cp.Length;
+                int parentOrd = 0; // for root, parent is always virtual ROOT (ord=0)
+                FacetLabel path = new FacetLabel();
+                for (int i = 0; i < level; i++)
+                {
+                    path = cp.Subpath(i + 1);
+                    int ord = dtr.GetOrdinal(path);
+                    Assert.AreEqual(parentOrd, parents[ord], "invalid parent for cp=" + path);
+                    parentOrd = ord; // next level should have this parent
+                }
+            }
+
+            IOUtils.Close(dtr, dir);
+        }
+
+        private class ThreadAnonymousInnerClassHelper : ThreadClass
+        {
+            private readonly TestDirectoryTaxonomyWriter outerInstance;
+
+            private int range;
+            private AtomicInteger numCats;
+            private ConcurrentDictionary<string, string> values;
+            private Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter tw;
+
+            public ThreadAnonymousInnerClassHelper(TestDirectoryTaxonomyWriter outerInstance, int range, AtomicInteger numCats, ConcurrentDictionary<string, string> values, Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter tw)
+            {
+                this.outerInstance = outerInstance;
+                this.range = range;
+                this.numCats = numCats;
+                this.values = values;
+                this.tw = tw;
+            }
+
+            public override void Run()
+            {
+                Random random = Random();
+                while (numCats.DecrementAndGet() > 0)
+                {
+                    try
+                    {
+                        int value = random.Next(range);
+                        FacetLabel cp = new FacetLabel(Convert.ToString(value / 1000), Convert.ToString(value / 10000), Convert.ToString(value / 100000), Convert.ToString(value));
+                        int ord = tw.AddCategory(cp);
+                        Assert.True(tw.GetParent(ord) != -1, "invalid parent for ordinal " + ord + ", category " + cp);
+                        string l1 = FacetsConfig.PathToString(cp.Components, 1);
+                        string l2 = FacetsConfig.PathToString(cp.Components, 2);
+                        string l3 = FacetsConfig.PathToString(cp.Components, 3);
+                        string l4 = FacetsConfig.PathToString(cp.Components, 4);
+                        values[l1] = l1;
+                        values[l2] = l2;
+                        values[l3] = l3;
+                        values[l4] = l4;
+                    }
+                    catch (IOException e)
+                    {
+                        throw new Exception(e.Message, e);
+                    }
+                }
+            }
+        }
+
+        private long getEpoch(Directory taxoDir)
+        {
+            SegmentInfos infos = new SegmentInfos();
+            infos.Read(taxoDir);
+            return Convert.ToInt64(infos.UserData[DirectoryTaxonomyWriter.INDEX_EPOCH]);
+        }
+
+        [Test]
+        public virtual void TestReplaceTaxonomy()
+        {
+            Directory input = NewDirectory();
+            var taxoWriter = new DirectoryTaxonomyWriter(input);
+            int ordA = taxoWriter.AddCategory(new FacetLabel("a"));
+            taxoWriter.Dispose();
+
+            Directory dir = NewDirectory();
+            taxoWriter = new DirectoryTaxonomyWriter(dir);
+            int ordB = taxoWriter.AddCategory(new FacetLabel("b"));
+            taxoWriter.AddCategory(new FacetLabel("c"));
+            taxoWriter.Commit();
+
+            long origEpoch = getEpoch(dir);
+
+            // replace the taxonomy with the input one
+            taxoWriter.ReplaceTaxonomy(input);
+
+            // LUCENE-4633: make sure that category "a" is not added again in any case
+            taxoWriter.AddTaxonomy(input, new MemoryOrdinalMap());
+            Assert.AreEqual(2, taxoWriter.Size, "no categories should have been added"); // root + 'a'
+            Assert.AreEqual(ordA, taxoWriter.AddCategory(new FacetLabel("a")), "category 'a' received new ordinal?");
+
+            // add the same category again -- it should not receive the same ordinal !
+            int newOrdB = taxoWriter.AddCategory(new FacetLabel("b"));
+            Assert.AreNotSame(ordB, newOrdB, "new ordinal cannot be the original ordinal");
+            Assert.AreEqual(2, newOrdB, "ordinal should have been 2 since only one category was added by replaceTaxonomy");
+
+            taxoWriter.Dispose();
+
+            long newEpoch = getEpoch(dir);
+            Assert.True(origEpoch < newEpoch, "index epoch should have been updated after replaceTaxonomy");
+
+            dir.Dispose();
+            input.Dispose();
+        }
+
+        [Test]
+        public virtual void TestReaderFreshness()
+        {
+            // ensures that the internal index reader is always kept fresh. Previously,
+            // this simple scenario failed, if the cache just evicted the category that
+            // is being added.
+            Directory dir = NewDirectory();
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(dir, OpenMode.CREATE, NO_OP_CACHE);
+            int o1 = taxoWriter.AddCategory(new FacetLabel("a"));
+            int o2 = taxoWriter.AddCategory(new FacetLabel("a"));
+            Assert.True(o1 == o2, "ordinal for same category that is added twice should be the same !");
+            taxoWriter.Dispose();
+            dir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestCommitNoEmptyCommits()
+        {
+            // LUCENE-4972: DTW used to create empty commits even if no changes were made
+            Directory dir = NewDirectory();
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(dir);
+            taxoWriter.AddCategory(new FacetLabel("a"));
+            taxoWriter.Commit();
+
+            long gen1 = SegmentInfos.GetLastCommitGeneration(dir);
+            taxoWriter.Commit();
+            long gen2 = SegmentInfos.GetLastCommitGeneration(dir);
+            Assert.AreEqual(gen1, gen2, "empty commit should not have changed the index");
+
+            taxoWriter.Dispose();
+            dir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestCloseNoEmptyCommits()
+        {
+            // LUCENE-4972: DTW used to create empty commits even if no changes were made
+            Directory dir = NewDirectory();
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(dir);
+            taxoWriter.AddCategory(new FacetLabel("a"));
+            taxoWriter.Commit();
+
+            long gen1 = SegmentInfos.GetLastCommitGeneration(dir);
+            taxoWriter.Dispose();
+            long gen2 = SegmentInfos.GetLastCommitGeneration(dir);
+            Assert.AreEqual(gen1, gen2, "empty commit should not have changed the index");
+
+            taxoWriter.Dispose();
+            dir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestPrepareCommitNoEmptyCommits()
+        {
+            // LUCENE-4972: DTW used to create empty commits even if no changes were made
+            Directory dir = NewDirectory();
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(dir);
+            taxoWriter.AddCategory(new FacetLabel("a"));
+            taxoWriter.PrepareCommit();
+            taxoWriter.Commit();
+
+            long gen1 = SegmentInfos.GetLastCommitGeneration(dir);
+            taxoWriter.PrepareCommit();
+            taxoWriter.Commit();
+            long gen2 = SegmentInfos.GetLastCommitGeneration(dir);
+            Assert.AreEqual(gen1, gen2, "empty commit should not have changed the index");
+
+            taxoWriter.Dispose();
+            dir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestHugeLabel()
+        {
+            Directory indexDir = NewDirectory(), taxoDir = NewDirectory();
+            IndexWriter indexWriter = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE, new Cl2oTaxonomyWriterCache(2, 1f, 1));
+            FacetsConfig config = new FacetsConfig();
+
+            // Add one huge label:
+            string bigs = null;
+            int ordinal = -1;
+
+            int len = FacetLabel.MAX_CATEGORY_PATH_LENGTH - 4; // for the dimension and separator
+            bigs = TestUtil.RandomSimpleString(Random(), len, len);
+            FacetField ff = new FacetField("dim", bigs);
+            FacetLabel cp = new FacetLabel("dim", bigs);
+            ordinal = taxoWriter.AddCategory(cp);
+            Document doc = new Document();
+            doc.Add(ff);
+            indexWriter.AddDocument(config.Build(taxoWriter, doc));
+
+            // Add tiny ones to cause a re-hash
+            for (int i = 0; i < 3; i++)
+            {
+                string s = TestUtil.RandomSimpleString(Random(), 1, 10);
+                taxoWriter.AddCategory(new FacetLabel("dim", s));
+                doc = new Document();
+                doc.Add(new FacetField("dim", s));
+                indexWriter.AddDocument(config.Build(taxoWriter, doc));
+            }
+
+            // when too large components were allowed to be added, this resulted in a new added category
+            Assert.AreEqual(ordinal, taxoWriter.AddCategory(cp));
+
+            IOUtils.Close(indexWriter, taxoWriter);
+
+            DirectoryReader indexReader = DirectoryReader.Open(indexDir);
+            var taxoReader = new DirectoryTaxonomyReader(taxoDir);
+            IndexSearcher searcher = new IndexSearcher(indexReader);
+            DrillDownQuery ddq = new DrillDownQuery(new FacetsConfig());
+            ddq.Add("dim", bigs);
+            Assert.AreEqual(1, searcher.Search(ddq, 10).TotalHits);
+
+            IOUtils.Close(indexReader, taxoReader, indexDir, taxoDir);
+        }
+
+        [Test]
+        public virtual void TestReplaceTaxoWithLargeTaxonomy()
+        {
+            var srcTaxoDir = NewDirectory();
+            var targetTaxoDir = NewDirectory();
+
+            // build source, large, taxonomy
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(srcTaxoDir);
+            int ord = taxoWriter.AddCategory(new FacetLabel("A", "1", "1", "1", "1", "1", "1"));
+            taxoWriter.Dispose();
+
+            taxoWriter = new DirectoryTaxonomyWriter(targetTaxoDir);
+            int ordinal = taxoWriter.AddCategory(new FacetLabel("B", "1"));
+            Assert.AreEqual(1, taxoWriter.GetParent(ordinal)); // call getParent to initialize taxoArrays
+            taxoWriter.Commit();
+
+            taxoWriter.ReplaceTaxonomy(srcTaxoDir);
+            Assert.AreEqual(ord - 1, taxoWriter.GetParent(ord));
+            taxoWriter.Dispose();
+
+            srcTaxoDir.Dispose();
+            targetTaxoDir.Dispose();
+        }
+
+    }
+
+}
\ No newline at end of file


[02/14] lucenenet git commit: Moving Lucene.Net.Facet tests to their appropriate place

Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/Taxonomy/WriterCache/TestCompactLabelToOrdinal.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/Taxonomy/WriterCache/TestCompactLabelToOrdinal.cs b/src/Lucene.Net.Tests/core/Facet/Taxonomy/WriterCache/TestCompactLabelToOrdinal.cs
deleted file mode 100644
index 549bf09..0000000
--- a/src/Lucene.Net.Tests/core/Facet/Taxonomy/WriterCache/TestCompactLabelToOrdinal.cs
+++ /dev/null
@@ -1,151 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Lucene.Net.Support;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet.Taxonomy.WriterCache
-{
-
-
-    using TestUtil = Lucene.Net.Util.TestUtil;
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-    [TestFixture]
-    public class TestCompactLabelToOrdinal : FacetTestCase
-    {
-        /* not finished to porting yet because of missing decoder implementation */
-        /*
-        public virtual void TestL2O()
-        {
-            LabelToOrdinal map = new LabelToOrdinalMap();
-
-            CompactLabelToOrdinal compact = new CompactLabelToOrdinal(2000000, 0.15f, 3);
-
-            int n = AtLeast(10 * 1000);
-            const int numUniqueValues = 50 * 1000;
-
-            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.Next(buffer.Length);
-
-                // This test is turning random bytes into a string,
-                // this is asking for trouble.
-                CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder().onUnmappableCharacter(CodingErrorAction.REPLACE).onMalformedInput(CodingErrorAction.REPLACE);
-                uniqueValues[i] = decoder.decode(ByteBuffer.Wrap(buffer, 0, size)).ToString();
-                // we cannot have empty path components, so eliminate all prefix as well
-                // as middle consecutive delimiter chars.
-                uniqueValues[i] = uniqueValues[i].replaceAll("/+", "/");
-                if (uniqueValues[i].StartsWith("/", StringComparison.Ordinal))
-                {
-                    uniqueValues[i] = uniqueValues[i].Substring(1);
-                }
-                if (uniqueValues[i].IndexOf(CompactLabelToOrdinal.TERMINATOR_CHAR) == -1)
-                {
-                    i++;
-                }
-            }
-
-            var tmpDir = CreateTempDir("testLableToOrdinal");
-            var f = new File(tmpDir, "CompactLabelToOrdinalTest.tmp");
-            int flushInterval = 10;
-
-            for (int i = 0; i < n; i++)
-            {
-                if (i > 0 && i % flushInterval == 0)
-                {
-                    compact.Flush(f);
-                    compact = CompactLabelToOrdinal.open(f, 0.15f, 3);
-                    Assert.True(f.delete());
-                    if (flushInterval < (n / 10))
-                    {
-                        flushInterval *= 10;
-                    }
-                }
-
-                int index = random.Next(numUniqueValues);
-                FacetLabel label;
-                string s = uniqueValues[index];
-                if (s.Length == 0)
-                {
-                    label = new FacetLabel();
-                }
-                else
-                {
-                    label = new FacetLabel(s.Split("/".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));
-                }
-
-                int ord1 = map.GetOrdinal(label);
-                int ord2 = compact.GetOrdinal(label);
-
-                Assert.AreEqual(ord1, ord2);
-
-                if (ord1 == LabelToOrdinal.INVALID_ORDINAL)
-                {
-                    ord1 = compact.NextOrdinal;
-                    map.AddLabel(label, ord1);
-                    compact.AddLabel(label, ord1);
-                }
-            }
-
-            for (int i = 0; i < numUniqueValues; i++)
-            {
-                FacetLabel label;
-                string s = uniqueValues[i];
-                if (s.Length == 0)
-                {
-                    label = new FacetLabel();
-                }
-                else
-                {
-                    label = new FacetLabel(s.Split("/".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));
-                }
-                int ord1 = map.GetOrdinal(label);
-                int ord2 = compact.GetOrdinal(label);
-                Assert.AreEqual(ord1, ord2);
-            }
-        }
-
-        private class LabelToOrdinalMap : LabelToOrdinal
-        {
-            internal IDictionary<FacetLabel, int?> map = new Dictionary<FacetLabel, int?>();
-
-            internal LabelToOrdinalMap()
-            {
-            }
-
-            public override void AddLabel(FacetLabel label, int ordinal)
-            {
-                map[label] = ordinal;
-            }
-
-            public override int GetOrdinal(FacetLabel label)
-            {
-                int? value = map[label];
-                return (value != null) ? (int)value : LabelToOrdinal.INVALID_ORDINAL;
-            }
-
-        } */
-
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/TestDrillDownQuery.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/TestDrillDownQuery.cs b/src/Lucene.Net.Tests/core/Facet/TestDrillDownQuery.cs
deleted file mode 100644
index 49ce90a..0000000
--- a/src/Lucene.Net.Tests/core/Facet/TestDrillDownQuery.cs
+++ /dev/null
@@ -1,282 +0,0 @@
-using System;
-using System.Diagnostics;
-using Lucene.Net.Randomized.Generators;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet
-{
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-
-    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
-    using MockTokenizer = Lucene.Net.Analysis.MockTokenizer;
-    using Document = Lucene.Net.Documents.Document;
-    using Field = Lucene.Net.Documents.Field;
-    using TextField = Lucene.Net.Documents.TextField;
-    using TaxonomyWriter = Lucene.Net.Facet.Taxonomy.TaxonomyWriter;
-    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
-    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
-    using IndexReader = Lucene.Net.Index.IndexReader;
-    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
-    using Term = Lucene.Net.Index.Term;
-    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
-    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
-    using Query = Lucene.Net.Search.Query;
-    using QueryUtils = Lucene.Net.Search.QueryUtils;
-    using ScoreDoc = Lucene.Net.Search.ScoreDoc;
-    using TermQuery = Lucene.Net.Search.TermQuery;
-    using TopDocs = Lucene.Net.Search.TopDocs;
-    using Directory = Lucene.Net.Store.Directory;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-
-    [TestFixture]
-    public class TestDrillDownQuery : FacetTestCase
-    {
-
-        private static IndexReader reader;
-        private static DirectoryTaxonomyReader taxo;
-        private static Directory dir;
-        private static Directory taxoDir;
-        private static FacetsConfig config;
-
-      
-        [TestFixtureTearDown]
-        public static void AfterClassDrillDownQueryTest()
-        {
-            IOUtils.Close(reader, taxo, dir, taxoDir);
-            reader = null;
-            taxo = null;
-            dir = null;
-            taxoDir = null;
-            config = null;
-        }
-
-        [TestFixtureSetUp]
-        public static void BeforeClassDrillDownQueryTest()
-        {
-            dir = NewDirectory();
-            Random r = Random();
-            RandomIndexWriter writer = new RandomIndexWriter(r, dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(r, MockTokenizer.KEYWORD, false)));
-
-            taxoDir = NewDirectory();
-            TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            config = new FacetsConfig();
-
-            // Randomize the per-dim config:
-            config.SetHierarchical("a", Random().NextBoolean());
-            config.SetMultiValued("a", Random().NextBoolean());
-            if (Random().NextBoolean())
-            {
-                config.SetIndexFieldName("a", "$a");
-            }
-            config.SetRequireDimCount("a", true);
-
-            config.SetHierarchical("b", Random().NextBoolean());
-            config.SetMultiValued("b", Random().NextBoolean());
-            if (Random().NextBoolean())
-            {
-                config.SetIndexFieldName("b", "$b");
-            }
-            config.SetRequireDimCount("b", true);
-
-            for (int i = 0; i < 100; i++)
-            {
-                Document doc = new Document();
-                if (i % 2 == 0) // 50
-                {
-                    doc.Add(new TextField("content", "foo", Field.Store.NO));
-                }
-                if (i % 3 == 0) // 33
-                {
-                    doc.Add(new TextField("content", "bar", Field.Store.NO));
-                }
-                if (i % 4 == 0) // 25
-                {
-                    if (r.NextBoolean())
-                    {
-                        doc.Add(new FacetField("a", "1"));
-                    }
-                    else
-                    {
-                        doc.Add(new FacetField("a", "2"));
-                    }
-                }
-                if (i % 5 == 0) // 20
-                {
-                    doc.Add(new FacetField("b", "1"));
-                }
-                writer.AddDocument(config.Build(taxoWriter, doc));
-            }
-
-            taxoWriter.Dispose();
-            reader = writer.Reader;
-            writer.Dispose();
-
-            taxo = new DirectoryTaxonomyReader(taxoDir);
-        }
-
-        [Test]
-        public virtual void TestAndOrs()
-        {
-            IndexSearcher searcher = NewSearcher(reader);
-
-            // test (a/1 OR a/2) AND b/1
-            DrillDownQuery q = new DrillDownQuery(config);
-            q.Add("a", "1");
-            q.Add("a", "2");
-            q.Add("b", "1");
-            TopDocs docs = searcher.Search(q, 100);
-            Assert.AreEqual(5, docs.TotalHits);
-        }
-
-        [Test]
-        public virtual void TestQuery()
-        {
-            IndexSearcher searcher = NewSearcher(reader);
-
-            // Making sure the query yields 25 documents with the facet "a"
-            DrillDownQuery q = new DrillDownQuery(config);
-            q.Add("a");
-            QueryUtils.Check(q);
-            TopDocs docs = searcher.Search(q, 100);
-            Assert.AreEqual(25, docs.TotalHits);
-
-            // Making sure the query yields 5 documents with the facet "b" and the
-            // previous (facet "a") query as a base query
-            DrillDownQuery q2 = new DrillDownQuery(config, q);
-            q2.Add("b");
-            docs = searcher.Search(q2, 100);
-            Assert.AreEqual(5, docs.TotalHits);
-
-            // Making sure that a query of both facet "a" and facet "b" yields 5 results
-            DrillDownQuery q3 = new DrillDownQuery(config);
-            q3.Add("a");
-            q3.Add("b");
-            docs = searcher.Search(q3, 100);
-
-            Assert.AreEqual(5, docs.TotalHits);
-            // Check that content:foo (which yields 50% results) and facet/b (which yields 20%)
-            // would gather together 10 results (10%..) 
-            Query fooQuery = new TermQuery(new Term("content", "foo"));
-            DrillDownQuery q4 = new DrillDownQuery(config, fooQuery);
-            q4.Add("b");
-            docs = searcher.Search(q4, 100);
-            Assert.AreEqual(10, docs.TotalHits);
-        }
-
-        [Test]
-        public virtual void TestQueryImplicitDefaultParams()
-        {
-            IndexSearcher searcher = NewSearcher(reader);
-
-            // Create the base query to start with
-            DrillDownQuery q = new DrillDownQuery(config);
-            q.Add("a");
-
-            // Making sure the query yields 5 documents with the facet "b" and the
-            // previous (facet "a") query as a base query
-            DrillDownQuery q2 = new DrillDownQuery(config, q);
-            q2.Add("b");
-            TopDocs docs = searcher.Search(q2, 100);
-            Assert.AreEqual(5, docs.TotalHits);
-
-            // Check that content:foo (which yields 50% results) and facet/b (which yields 20%)
-            // would gather together 10 results (10%..) 
-            Query fooQuery = new TermQuery(new Term("content", "foo"));
-            DrillDownQuery q4 = new DrillDownQuery(config, fooQuery);
-            q4.Add("b");
-            docs = searcher.Search(q4, 100);
-            Assert.AreEqual(10, docs.TotalHits);
-        }
-
-        [Test]
-        public virtual void TestScoring()
-        {
-            // verify that drill-down queries do not modify scores
-            IndexSearcher searcher = NewSearcher(reader);
-
-            float[] scores = new float[reader.MaxDoc];
-
-            Query q = new TermQuery(new Term("content", "foo"));
-            TopDocs docs = searcher.Search(q, reader.MaxDoc); // fetch all available docs to this query
-            foreach (ScoreDoc sd in docs.ScoreDocs)
-            {
-                scores[sd.Doc] = sd.Score;
-            }
-
-            // create a drill-down query with category "a", scores should not change
-            DrillDownQuery q2 = new DrillDownQuery(config, q);
-            q2.Add("a");
-            docs = searcher.Search(q2, reader.MaxDoc); // fetch all available docs to this query
-            foreach (ScoreDoc sd in docs.ScoreDocs)
-            {
-                Assert.AreEqual(scores[sd.Doc], sd.Score, 0f, "score of doc=" + sd.Doc + " modified");
-            }
-        }
-
-        [Test]
-        public virtual void TestScoringNoBaseQuery()
-        {
-            // verify that drill-down queries (with no base query) returns 0.0 score
-            IndexSearcher searcher = NewSearcher(reader);
-
-            DrillDownQuery q = new DrillDownQuery(config);
-            q.Add("a");
-            TopDocs docs = searcher.Search(q, reader.MaxDoc); // fetch all available docs to this query
-            foreach (ScoreDoc sd in docs.ScoreDocs)
-            {
-                Assert.AreEqual(0f, sd.Score, 0f);
-            }
-        }
-
-        [Test]
-        public virtual void TestTermNonDefault()
-        {
-            string aField = config.GetDimConfig("a").IndexFieldName;
-            Term termA = DrillDownQuery.Term(aField, "a");
-            Assert.AreEqual(new Term(aField, "a"), termA);
-
-            string bField = config.GetDimConfig("b").IndexFieldName;
-            Term termB = DrillDownQuery.Term(bField, "b");
-            Assert.AreEqual(new Term(bField, "b"), termB);
-        }
-
-        [Test]
-        public virtual void TestClone()
-        {
-            var q = new DrillDownQuery(config, new MatchAllDocsQuery());
-            q.Add("a");
-
-            var clone = q.Clone() as DrillDownQuery;
-            Assert.NotNull(clone);
-            clone.Add("b");
-            Assert.False(q.ToString().Equals(clone.ToString()), "query wasn't cloned: source=" + q + " clone=" + clone);
-        }
-
-        [Test]
-        public virtual void TestNoDrillDown()
-        {
-            Query @base = new MatchAllDocsQuery();
-            DrillDownQuery q = new DrillDownQuery(config, @base);
-            Query rewrite = q.Rewrite(reader).Rewrite(reader);
-            Assert.AreSame(@base, rewrite);
-        }
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/TestDrillSideways.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/TestDrillSideways.cs b/src/Lucene.Net.Tests/core/Facet/TestDrillSideways.cs
deleted file mode 100644
index 00cb772..0000000
--- a/src/Lucene.Net.Tests/core/Facet/TestDrillSideways.cs
+++ /dev/null
@@ -1,1332 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.Collections.Generic;
-using System.Linq;
-using Lucene.Net.Randomized.Generators;
-using Lucene.Net.Support;
-
-namespace Lucene.Net.Facet
-{
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-
-    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
-    using Document = Lucene.Net.Documents.Document;
-    using Field = Lucene.Net.Documents.Field;
-    using StringField = Lucene.Net.Documents.StringField;
-    using DrillSidewaysResult = Lucene.Net.Facet.DrillSideways.DrillSidewaysResult;
-    using DefaultSortedSetDocValuesReaderState = Lucene.Net.Facet.SortedSet.DefaultSortedSetDocValuesReaderState;
-    using SortedSetDocValuesFacetField = Lucene.Net.Facet.SortedSet.SortedSetDocValuesFacetField;
-    using SortedSetDocValuesReaderState = Lucene.Net.Facet.SortedSet.SortedSetDocValuesReaderState;
-    using TaxonomyReader = Lucene.Net.Facet.Taxonomy.TaxonomyReader;
-    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
-    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
-    using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
-    using IndexReader = Lucene.Net.Index.IndexReader;
-    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
-    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
-    using Term = Lucene.Net.Index.Term;
-    using Collector = Lucene.Net.Search.Collector;
-    using DocIdSet = Lucene.Net.Search.DocIdSet;
-    using Filter = Lucene.Net.Search.Filter;
-    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
-    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
-    using Query = Lucene.Net.Search.Query;
-    using ScoreDoc = Lucene.Net.Search.ScoreDoc;
-    using Scorer = Lucene.Net.Search.Scorer;
-    using Sort = Lucene.Net.Search.Sort;
-    using SortField = Lucene.Net.Search.SortField;
-    using TermQuery = Lucene.Net.Search.TermQuery;
-    using TopDocs = Lucene.Net.Search.TopDocs;
-    using Directory = Lucene.Net.Store.Directory;
-    using Bits = Lucene.Net.Util.Bits;
-    using BytesRef = Lucene.Net.Util.BytesRef;
-    using FixedBitSet = Lucene.Net.Util.FixedBitSet;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-    using InPlaceMergeSorter = Lucene.Net.Util.InPlaceMergeSorter;
-    using InfoStream = Lucene.Net.Util.InfoStream;
-    using TestUtil = Lucene.Net.Util.TestUtil;
-    using NUnit.Framework;
-
-    [TestFixture]
-    public class TestDrillSideways : FacetTestCase
-    {
-
-        [Test]
-        public virtual void TestBasic()
-        {
-            Directory dir = NewDirectory();
-            Directory taxoDir = NewDirectory();
-
-            // Writes facet ords to a separate directory from the
-            // main index:
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-
-            FacetsConfig config = new FacetsConfig();
-            config.SetHierarchical("Publish Date", true);
-
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            Document doc = new Document();
-            doc.Add(new FacetField("Author", "Bob"));
-            doc.Add(new FacetField("Publish Date", "2010", "10", "15"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new FacetField("Author", "Lisa"));
-            doc.Add(new FacetField("Publish Date", "2010", "10", "20"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new FacetField("Author", "Lisa"));
-            doc.Add(new FacetField("Publish Date", "2012", "1", "1"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new FacetField("Author", "Susan"));
-            doc.Add(new FacetField("Publish Date", "2012", "1", "7"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new FacetField("Author", "Frank"));
-            doc.Add(new FacetField("Publish Date", "1999", "5", "5"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-
-            //System.out.println("searcher=" + searcher);
-
-            // NRT open
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            DrillSideways ds = new DrillSideways(searcher, config, taxoReader);
-
-            //  case: drill-down on a single field; in this
-            // case the drill-sideways + drill-down counts ==
-            // drill-down of just the query: 
-            DrillDownQuery ddq = new DrillDownQuery(config);
-            ddq.Add("Author", "Lisa");
-            DrillSidewaysResult r = ds.Search(null, ddq, 10);
-            Assert.AreEqual(2, r.Hits.TotalHits);
-            // Publish Date is only drill-down, and Lisa published
-            // one in 2012 and one in 2010:
-            Assert.AreEqual("dim=Publish Date path=[] value=2 childCount=2\n  2010 (1)\n  2012 (1)\n", r.Facets.GetTopChildren(10, "Publish Date").ToString());
-
-            // Author is drill-sideways + drill-down: Lisa
-            // (drill-down) published twice, and Frank/Susan/Bob
-            // published once:
-            Assert.AreEqual("dim=Author path=[] value=5 childCount=4\n  Lisa (2)\n  Bob (1)\n  Susan (1)\n  Frank (1)\n", r.Facets.GetTopChildren(10, "Author").ToString());
-
-            // Same simple case, but no baseQuery (pure browse):
-            // drill-down on a single field; in this case the
-            // drill-sideways + drill-down counts == drill-down of
-            // just the query:
-            ddq = new DrillDownQuery(config);
-            ddq.Add("Author", "Lisa");
-            r = ds.Search(null, ddq, 10);
-
-            Assert.AreEqual(2, r.Hits.TotalHits);
-            // Publish Date is only drill-down, and Lisa published
-            // one in 2012 and one in 2010:
-            Assert.AreEqual("dim=Publish Date path=[] value=2 childCount=2\n  2010 (1)\n  2012 (1)\n", r.Facets.GetTopChildren(10, "Publish Date").ToString());
-
-            // Author is drill-sideways + drill-down: Lisa
-            // (drill-down) published twice, and Frank/Susan/Bob
-            // published once:
-            Assert.AreEqual("dim=Author path=[] value=5 childCount=4\n  Lisa (2)\n  Bob (1)\n  Susan (1)\n  Frank (1)\n", r.Facets.GetTopChildren(10, "Author").ToString());
-
-            // Another simple case: drill-down on single fields
-            // but OR of two values
-            ddq = new DrillDownQuery(config);
-            ddq.Add("Author", "Lisa");
-            ddq.Add("Author", "Bob");
-            r = ds.Search(null, ddq, 10);
-            Assert.AreEqual(3, r.Hits.TotalHits);
-            // Publish Date is only drill-down: Lisa and Bob
-            // (drill-down) published twice in 2010 and once in 2012:
-            Assert.AreEqual("dim=Publish Date path=[] value=3 childCount=2\n  2010 (2)\n  2012 (1)\n", r.Facets.GetTopChildren(10, "Publish Date").ToString());
-            // Author is drill-sideways + drill-down: Lisa
-            // (drill-down) published twice, and Frank/Susan/Bob
-            // published once:
-            Assert.AreEqual("dim=Author path=[] value=5 childCount=4\n  Lisa (2)\n  Bob (1)\n  Susan (1)\n  Frank (1)\n", r.Facets.GetTopChildren(10, "Author").ToString());
-
-            Assert.True(r.Facets is MultiFacets);
-            IList<FacetResult> allResults = r.Facets.GetAllDims(10);
-            Assert.AreEqual(2, allResults.Count);
-            Assert.AreEqual("dim=Author path=[] value=5 childCount=4\n  Lisa (2)\n  Bob (1)\n  Susan (1)\n  Frank (1)\n", allResults[0].ToString());
-            Assert.AreEqual("dim=Publish Date path=[] value=3 childCount=2\n  2010 (2)\n  2012 (1)\n", allResults[1].ToString());
-
-            // More interesting case: drill-down on two fields
-            ddq = new DrillDownQuery(config);
-            ddq.Add("Author", "Lisa");
-            ddq.Add("Publish Date", "2010");
-            r = ds.Search(null, ddq, 10);
-            Assert.AreEqual(1, r.Hits.TotalHits);
-            // Publish Date is drill-sideways + drill-down: Lisa
-            // (drill-down) published once in 2010 and once in 2012:
-            Assert.AreEqual("dim=Publish Date path=[] value=2 childCount=2\n  2010 (1)\n  2012 (1)\n", r.Facets.GetTopChildren(10, "Publish Date").ToString());
-            // Author is drill-sideways + drill-down:
-            // only Lisa & Bob published (once each) in 2010:
-            Assert.AreEqual("dim=Author path=[] value=2 childCount=2\n  Bob (1)\n  Lisa (1)\n", r.Facets.GetTopChildren(10, "Author").ToString());
-
-            // Even more interesting case: drill down on two fields,
-            // but one of them is OR
-            ddq = new DrillDownQuery(config);
-
-            // Drill down on Lisa or Bob:
-            ddq.Add("Author", "Lisa");
-            ddq.Add("Publish Date", "2010");
-            ddq.Add("Author", "Bob");
-            r = ds.Search(null, ddq, 10);
-            Assert.AreEqual(2, r.Hits.TotalHits);
-            // Publish Date is both drill-sideways + drill-down:
-            // Lisa or Bob published twice in 2010 and once in 2012:
-            Assert.AreEqual("dim=Publish Date path=[] value=3 childCount=2\n  2010 (2)\n  2012 (1)\n", r.Facets.GetTopChildren(10, "Publish Date").ToString());
-            // Author is drill-sideways + drill-down:
-            // only Lisa & Bob published (once each) in 2010:
-            Assert.AreEqual("dim=Author path=[] value=2 childCount=2\n  Bob (1)\n  Lisa (1)\n", r.Facets.GetTopChildren(10, "Author").ToString());
-
-            // Test drilling down on invalid field:
-            ddq = new DrillDownQuery(config);
-            ddq.Add("Foobar", "Baz");
-            r = ds.Search(null, ddq, 10);
-            Assert.AreEqual(0, r.Hits.TotalHits);
-            Assert.Null(r.Facets.GetTopChildren(10, "Publish Date"));
-            Assert.Null(r.Facets.GetTopChildren(10, "Foobar"));
-
-            // Test drilling down on valid term or'd with invalid term:
-            ddq = new DrillDownQuery(config);
-            ddq.Add("Author", "Lisa");
-            ddq.Add("Author", "Tom");
-            r = ds.Search(null, ddq, 10);
-            Assert.AreEqual(2, r.Hits.TotalHits);
-            // Publish Date is only drill-down, and Lisa published
-            // one in 2012 and one in 2010:
-            Assert.AreEqual("dim=Publish Date path=[] value=2 childCount=2\n  2010 (1)\n  2012 (1)\n", r.Facets.GetTopChildren(10, "Publish Date").ToString());
-            // Author is drill-sideways + drill-down: Lisa
-            // (drill-down) published twice, and Frank/Susan/Bob
-            // published once:
-            Assert.AreEqual("dim=Author path=[] value=5 childCount=4\n  Lisa (2)\n  Bob (1)\n  Susan (1)\n  Frank (1)\n", r.Facets.GetTopChildren(10, "Author").ToString());
-
-            // LUCENE-4915: test drilling down on a dimension but
-            // NOT facet counting it:
-            ddq = new DrillDownQuery(config);
-            ddq.Add("Author", "Lisa");
-            ddq.Add("Author", "Tom");
-            r = ds.Search(null, ddq, 10);
-            Assert.AreEqual(2, r.Hits.TotalHits);
-            // Publish Date is only drill-down, and Lisa published
-            // one in 2012 and one in 2010:
-            Assert.AreEqual("dim=Publish Date path=[] value=2 childCount=2\n  2010 (1)\n  2012 (1)\n", r.Facets.GetTopChildren(10, "Publish Date").ToString());
-
-            // Test main query gets null scorer:
-            ddq = new DrillDownQuery(config, new TermQuery(new Term("foobar", "baz")));
-            ddq.Add("Author", "Lisa");
-            r = ds.Search(null, ddq, 10);
-
-            Assert.AreEqual(0, r.Hits.TotalHits);
-            Assert.Null(r.Facets.GetTopChildren(10, "Publish Date"));
-            Assert.Null(r.Facets.GetTopChildren(10, "Author"));
-            IOUtils.Close(searcher.IndexReader, taxoReader, writer, taxoWriter, dir, taxoDir);
-        }
-
-        [Test]
-        public virtual void TestSometimesInvalidDrillDown()
-        {
-            Directory dir = NewDirectory();
-            Directory taxoDir = NewDirectory();
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            // Writes facet ords to a separate directory from the
-            // main index:
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-
-            FacetsConfig config = new FacetsConfig();
-            config.SetHierarchical("Publish Date", true);
-
-            Document doc = new Document();
-            doc.Add(new FacetField("Author", "Bob"));
-            doc.Add(new FacetField("Publish Date", "2010", "10", "15"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new FacetField("Author", "Lisa"));
-            doc.Add(new FacetField("Publish Date", "2010", "10", "20"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            writer.Commit();
-
-            // 2nd segment has no Author:
-            doc = new Document();
-            doc.Add(new FacetField("Foobar", "Lisa"));
-            doc.Add(new FacetField("Publish Date", "2012", "1", "1"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-
-            //System.out.println("searcher=" + searcher);
-
-            // NRT open
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            DrillDownQuery ddq = new DrillDownQuery(config);
-            ddq.Add("Author", "Lisa");
-            DrillSidewaysResult r = (new DrillSideways(searcher, config, taxoReader)).Search(null, ddq, 10);
-
-            Assert.AreEqual(1, r.Hits.TotalHits);
-            // Publish Date is only drill-down, and Lisa published
-            // one in 2012 and one in 2010:
-            Assert.AreEqual("dim=Publish Date path=[] value=1 childCount=1\n  2010 (1)\n", r.Facets.GetTopChildren(10, "Publish Date").ToString());
-            // Author is drill-sideways + drill-down: Lisa
-            // (drill-down) published once, and Bob
-            // published once:
-            Assert.AreEqual("dim=Author path=[] value=2 childCount=2\n  Bob (1)\n  Lisa (1)\n", r.Facets.GetTopChildren(10, "Author").ToString());
-
-            IOUtils.Close(searcher.IndexReader, taxoReader, writer, taxoWriter, dir, taxoDir);
-        }
-
-        [Test]
-        public virtual void TestMultipleRequestsPerDim()
-        {
-            Directory dir = NewDirectory();
-            Directory taxoDir = NewDirectory();
-            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
-
-            // Writes facet ords to a separate directory from the
-            // main index:
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-
-            FacetsConfig config = new FacetsConfig();
-            config.SetHierarchical("dim", true);
-
-            Document doc = new Document();
-            doc.Add(new FacetField("dim", "a", "x"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new FacetField("dim", "a", "y"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new FacetField("dim", "a", "z"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new FacetField("dim", "b"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new FacetField("dim", "c"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            doc = new Document();
-            doc.Add(new FacetField("dim", "d"));
-            writer.AddDocument(config.Build(taxoWriter, doc));
-
-            // NRT open
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-
-            //System.out.println("searcher=" + searcher);
-
-            // NRT open
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            DrillDownQuery ddq = new DrillDownQuery(config);
-            ddq.Add("dim", "a");
-            DrillSidewaysResult r = (new DrillSideways(searcher, config, taxoReader)).Search(null, ddq, 10);
-
-            Assert.AreEqual(3, r.Hits.TotalHits);
-            Assert.AreEqual("dim=dim path=[] value=6 childCount=4\n  a (3)\n  b (1)\n  c (1)\n  d (1)\n", r.Facets.GetTopChildren(10, "dim").ToString());
-            Assert.AreEqual("dim=dim path=[a] value=3 childCount=3\n  x (1)\n  y (1)\n  z (1)\n", r.Facets.GetTopChildren(10, "dim", "a").ToString());
-
-            IOUtils.Close(searcher.IndexReader, taxoReader, writer, taxoWriter, dir, taxoDir);
-        }
-
-        internal class Doc : IComparable<Doc>
-        {
-            internal string id;
-            internal string contentToken;
-
-            public Doc()
-            {
-            }
-
-            // -1 if the doc is missing this dim, else the index
-            // -into the values for this dim:
-            internal int[] dims;
-
-            // 2nd value per dim for the doc (so we test
-            // multi-valued fields):
-            internal int[] dims2;
-            internal bool deleted;
-
-            public virtual int CompareTo(Doc other)
-            {
-                return id.CompareTo(other.id);
-            }
-        }
-
-        private double aChance, bChance, cChance;
-
-        private string randomContentToken(bool isQuery)
-        {
-            double d = Random().NextDouble();
-            if (isQuery)
-            {
-                if (d < 0.33)
-                {
-                    return "a";
-                }
-                else if (d < 0.66)
-                {
-                    return "b";
-                }
-                else
-                {
-                    return "c";
-                }
-            }
-            else
-            {
-                if (d <= aChance)
-                {
-                    return "a";
-                }
-                else if (d < aChance + bChance)
-                {
-                    return "b";
-                }
-                else
-                {
-                    return "c";
-                }
-            }
-        }
-
-        [Test]
-        public virtual void TestRandom()
-        {
-
-            bool canUseDV = DefaultCodecSupportsSortedSet();
-
-            while (aChance == 0.0)
-            {
-                aChance = Random().NextDouble();
-            }
-            while (bChance == 0.0)
-            {
-                bChance = Random().NextDouble();
-            }
-            while (cChance == 0.0)
-            {
-                cChance = Random().NextDouble();
-            }
-            //aChance = .01;
-            //bChance = 0.5;
-            //cChance = 1.0;
-            double sum = aChance + bChance + cChance;
-            aChance /= sum;
-            bChance /= sum;
-            cChance /= sum;
-
-            int numDims = TestUtil.NextInt(Random(), 2, 5);
-            //int numDims = 3;
-            int numDocs = AtLeast(3000);
-            //int numDocs = 20;
-            if (VERBOSE)
-            {
-                Console.WriteLine("numDims=" + numDims + " numDocs=" + numDocs + " aChance=" + aChance + " bChance=" + bChance + " cChance=" + cChance);
-            }
-            string[][] dimValues = new string[numDims][];
-            int valueCount = 2;
-
-            for (int dim = 0; dim < numDims; dim++)
-            {
-                var values = new HashSet<string>();
-                while (values.Count < valueCount)
-                {
-                    var str = TestUtil.RandomRealisticUnicodeString(Random());
-                    //String s = TestUtil.randomString(Random());
-                    if (str.Length > 0)
-                    {
-                        values.Add(str);
-                    }
-                }
-                dimValues[dim] = values.ToArray();
-                valueCount *= 2;
-            }
-
-            IList<Doc> docs = new List<Doc>();
-            for (int i = 0; i < numDocs; i++)
-            {
-                Doc doc = new Doc();
-                doc.id = "" + i;
-                doc.contentToken = randomContentToken(false);
-                doc.dims = new int[numDims];
-                doc.dims2 = new int[numDims];
-                for (int dim = 0; dim < numDims; dim++)
-                {
-                    if (Random().Next(5) == 3)
-                    {
-                        // This doc is missing this dim:
-                        doc.dims[dim] = -1;
-                    }
-                    else if (dimValues[dim].Length <= 4)
-                    {
-                        int dimUpto = 0;
-                        doc.dims[dim] = dimValues[dim].Length - 1;
-                        while (dimUpto < dimValues[dim].Length)
-                        {
-                            if (Random().NextBoolean())
-                            {
-                                doc.dims[dim] = dimUpto;
-                                break;
-                            }
-                            dimUpto++;
-                        }
-                    }
-                    else
-                    {
-                        doc.dims[dim] = Random().Next(dimValues[dim].Length);
-                    }
-
-                    if (Random().Next(5) == 3)
-                    {
-                        // 2nd value:
-                        doc.dims2[dim] = Random().Next(dimValues[dim].Length);
-                    }
-                    else
-                    {
-                        doc.dims2[dim] = -1;
-                    }
-                }
-                docs.Add(doc);
-            }
-
-            Directory d = NewDirectory();
-            Directory td = NewDirectory();
-
-            IndexWriterConfig iwc = NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
-            iwc.SetInfoStream(InfoStream.NO_OUTPUT);
-            var w = new RandomIndexWriter(Random(), d, iwc);
-            var tw = new DirectoryTaxonomyWriter(td, IndexWriterConfig.OpenMode_e.CREATE);
-            FacetsConfig config = new FacetsConfig();
-            for (int i = 0; i < numDims; i++)
-            {
-                config.SetMultiValued("dim" + i, true);
-            }
-
-            bool doUseDV = canUseDV && Random().NextBoolean();
-
-            foreach (Doc rawDoc in docs)
-            {
-                Document doc = new Document();
-                doc.Add(NewStringField("id", rawDoc.id, Field.Store.YES));
-                doc.Add(NewStringField("content", rawDoc.contentToken, Field.Store.NO));
-
-                if (VERBOSE)
-                {
-                    Console.WriteLine("  doc id=" + rawDoc.id + " token=" + rawDoc.contentToken);
-                }
-                for (int dim = 0; dim < numDims; dim++)
-                {
-                    int dimValue = rawDoc.dims[dim];
-                    if (dimValue != -1)
-                    {
-                        if (doUseDV)
-                        {
-                            doc.Add(new SortedSetDocValuesFacetField("dim" + dim, dimValues[dim][dimValue]));
-                        }
-                        else
-                        {
-                            doc.Add(new FacetField("dim" + dim, dimValues[dim][dimValue]));
-                        }
-                        doc.Add(new StringField("dim" + dim, dimValues[dim][dimValue], Field.Store.YES));
-                        if (VERBOSE)
-                        {
-                            Console.WriteLine("    dim" + dim + "=" + new BytesRef(dimValues[dim][dimValue]));
-                        }
-                    }
-                    int dimValue2 = rawDoc.dims2[dim];
-                    if (dimValue2 != -1)
-                    {
-                        if (doUseDV)
-                        {
-                            doc.Add(new SortedSetDocValuesFacetField("dim" + dim, dimValues[dim][dimValue2]));
-                        }
-                        else
-                        {
-                            doc.Add(new FacetField("dim" + dim, dimValues[dim][dimValue2]));
-                        }
-                        doc.Add(new StringField("dim" + dim, dimValues[dim][dimValue2], Field.Store.YES));
-                        if (VERBOSE)
-                        {
-                            Console.WriteLine("      dim" + dim + "=" + new BytesRef(dimValues[dim][dimValue2]));
-                        }
-                    }
-                }
-
-                w.AddDocument(config.Build(tw, doc));
-            }
-
-            if (Random().NextBoolean())
-            {
-                // Randomly delete a few docs:
-                int numDel = TestUtil.NextInt(Random(), 1, (int)(numDocs * 0.05));
-                if (VERBOSE)
-                {
-                    Console.WriteLine("delete " + numDel);
-                }
-                int delCount = 0;
-                while (delCount < numDel)
-                {
-                    Doc doc = docs[Random().Next(docs.Count)];
-                    if (!doc.deleted)
-                    {
-                        if (VERBOSE)
-                        {
-                            Console.WriteLine("  delete id=" + doc.id);
-                        }
-                        doc.deleted = true;
-                        w.DeleteDocuments(new Term("id", doc.id));
-                        delCount++;
-                    }
-                }
-            }
-
-            if (Random().NextBoolean())
-            {
-                if (VERBOSE)
-                {
-                    Console.WriteLine("TEST: forceMerge(1)...");
-                }
-                w.ForceMerge(1);
-            }
-            IndexReader r = w.Reader;
-
-            SortedSetDocValuesReaderState sortedSetDVState;
-            IndexSearcher s = NewSearcher(r);
-
-            if (doUseDV)
-            {
-                sortedSetDVState = new DefaultSortedSetDocValuesReaderState(s.IndexReader);
-            }
-            else
-            {
-                sortedSetDVState = null;
-            }
-
-            if (VERBOSE)
-            {
-                Console.WriteLine("r.numDocs() = " + r.NumDocs);
-            }
-
-            // NRT open
-            var tr = new DirectoryTaxonomyReader(tw);
-
-            int numIters = AtLeast(10);
-
-            for (int iter = 0; iter < numIters; iter++)
-            {
-
-                string contentToken = Random().Next(30) == 17 ? null : randomContentToken(true);
-                int numDrillDown = TestUtil.NextInt(Random(), 1, Math.Min(4, numDims));
-                if (VERBOSE)
-                {
-                    Console.WriteLine("\nTEST: iter=" + iter + " baseQuery=" + contentToken + " numDrillDown=" + numDrillDown + " useSortedSetDV=" + doUseDV);
-                }
-
-                string[][] drillDowns = new string[numDims][];
-
-                int count = 0;
-                bool anyMultiValuedDrillDowns = false;
-                while (count < numDrillDown)
-                {
-                    int dim = Random().Next(numDims);
-                    if (drillDowns[dim] == null)
-                    {
-                        if (Random().NextBoolean())
-                        {
-                            // Drill down on one value:
-                            drillDowns[dim] = new string[] { dimValues[dim][Random().Next(dimValues[dim].Length)] };
-                        }
-                        else
-                        {
-                            int orCount = TestUtil.NextInt(Random(), 1, Math.Min(5, dimValues[dim].Length));
-                            drillDowns[dim] = new string[orCount];
-                            anyMultiValuedDrillDowns |= orCount > 1;
-                            for (int i = 0; i < orCount; i++)
-                            {
-                                while (true)
-                                {
-                                    string value = dimValues[dim][Random().Next(dimValues[dim].Length)];
-                                    for (int j = 0; j < i; j++)
-                                    {
-                                        if (value.Equals(drillDowns[dim][j]))
-                                        {
-                                            value = null;
-                                            break;
-                                        }
-                                    }
-                                    if (value != null)
-                                    {
-                                        drillDowns[dim][i] = value;
-                                        break;
-                                    }
-                                }
-                            }
-                        }
-                        if (VERBOSE)
-                        {
-                            BytesRef[] values = new BytesRef[drillDowns[dim].Length];
-                            for (int i = 0; i < values.Length; i++)
-                            {
-                                values[i] = new BytesRef(drillDowns[dim][i]);
-                            }
-                            Console.WriteLine("  dim" + dim + "=" + Arrays.ToString(values));
-                        }
-                        count++;
-                    }
-                }
-
-                Query baseQuery;
-                if (contentToken == null)
-                {
-                    baseQuery = new MatchAllDocsQuery();
-                }
-                else
-                {
-                    baseQuery = new TermQuery(new Term("content", contentToken));
-                }
-
-                DrillDownQuery ddq = new DrillDownQuery(config, baseQuery);
-
-                for (int dim = 0; dim < numDims; dim++)
-                {
-                    if (drillDowns[dim] != null)
-                    {
-                        foreach (string value in drillDowns[dim])
-                        {
-                            ddq.Add("dim" + dim, value);
-                        }
-                    }
-                }
-
-                Filter filter;
-                if (Random().Next(7) == 6)
-                {
-                    if (VERBOSE)
-                    {
-                        Console.WriteLine("  only-even filter");
-                    }
-                    filter = new FilterAnonymousInnerClassHelper(this);
-                }
-                else
-                {
-                    filter = null;
-                }
-
-                // Verify docs are always collected in order.  If we
-                // had an AssertingScorer it could catch it when
-                // Weight.scoresDocsOutOfOrder lies!:
-                (new DrillSideways(s, config, tr)).Search(ddq, new CollectorAnonymousInnerClassHelper(this, s));
-
-                // Also separately verify that DS respects the
-                // scoreSubDocsAtOnce method, to ensure that all
-                // subScorers are on the same docID:
-                if (!anyMultiValuedDrillDowns)
-                {
-                    // Can only do this test when there are no OR'd
-                    // drill-down values, because in that case it's
-                    // easily possible for one of the DD terms to be on
-                    // a future docID:
-                    new DrillSidewaysAnonymousInnerClassHelper(this, s, config, tr)
-                    .Search(ddq, new AssertingSubDocsAtOnceCollector());
-                }
-
-                TestFacetResult expected = slowDrillSidewaysSearch(s, docs, contentToken, drillDowns, dimValues, filter);
-
-                Sort sort = new Sort(new SortField("id", SortField.Type_e.STRING));
-                DrillSideways ds;
-                if (doUseDV)
-                {
-                    ds = new DrillSideways(s, config, sortedSetDVState);
-                }
-                else
-                {
-                    ds = new DrillSidewaysAnonymousInnerClassHelper2(this, s, config, tr, drillDowns);
-                }
-
-                // Retrieve all facets:
-                DrillSidewaysResult actual = ds.Search(ddq, filter, null, numDocs, sort, true, true);
-
-                TopDocs hits = s.Search(baseQuery, numDocs);
-                IDictionary<string, float?> scores = new Dictionary<string, float?>();
-                foreach (ScoreDoc sd in hits.ScoreDocs)
-                {
-                    scores[s.Doc(sd.Doc).Get("id")] = sd.Score;
-                }
-                if (VERBOSE)
-                {
-                    Console.WriteLine("  verify all facets");
-                }
-                VerifyEquals(dimValues, s, expected, actual, scores, doUseDV);
-
-                // Make sure drill down doesn't change score:
-                TopDocs ddqHits = s.Search(ddq, filter, numDocs);
-                Assert.AreEqual(expected.Hits.Count, ddqHits.TotalHits);
-                for (int i = 0; i < expected.Hits.Count; i++)
-                {
-                    // Score should be IDENTICAL:
-                    Assert.AreEqual(scores[expected.Hits[i].id], ddqHits.ScoreDocs[i].Score);
-                }
-            }
-
-            IOUtils.Close(r, tr, w, tw, d, td);
-        }
-
-        private class FilterAnonymousInnerClassHelper : Filter
-        {
-            private readonly TestDrillSideways outerInstance;
-
-            public FilterAnonymousInnerClassHelper(TestDrillSideways outerInstance)
-            {
-                this.outerInstance = outerInstance;
-            }
-
-            public override DocIdSet GetDocIdSet(AtomicReaderContext context, Bits acceptDocs)
-            {
-                int maxDoc = context.Reader.MaxDoc;
-                FixedBitSet bits = new FixedBitSet(maxDoc);
-                for (int docID = 0; docID < maxDoc; docID++)
-                {
-                    // Keeps only the even ids:
-                    if ((acceptDocs == null || acceptDocs.Get(docID)) && (Convert.ToInt32(context.Reader.Document(docID).Get("id")) & 1) == 0)
-                    {
-                        bits.Set(docID);
-                    }
-                }
-                return bits;
-            }
-        }
-
-        private class CollectorAnonymousInnerClassHelper : Collector
-        {
-            private readonly TestDrillSideways outerInstance;
-
-            private IndexSearcher s;
-
-            public CollectorAnonymousInnerClassHelper(TestDrillSideways outerInstance, IndexSearcher s)
-            {
-                this.outerInstance = outerInstance;
-                this.s = s;
-            }
-
-            internal int lastDocID;
-
-            public override Scorer Scorer
-            {
-                set
-                {
-                }
-            }
-
-            public override void Collect(int doc)
-            {
-                Debug.Assert(doc > lastDocID);
-                lastDocID = doc;
-            }
-
-            public override AtomicReaderContext NextReader
-            {
-                set
-                {
-                    lastDocID = -1;
-                }
-            }
-
-            public override bool AcceptsDocsOutOfOrder()
-            {
-                return false;
-            }
-        }
-
-        private class DrillSidewaysAnonymousInnerClassHelper : DrillSideways
-        {
-            private readonly TestDrillSideways outerInstance;
-
-            public DrillSidewaysAnonymousInnerClassHelper(TestDrillSideways outerInstance, IndexSearcher s, Lucene.Net.Facet.FacetsConfig config, TaxonomyReader tr)
-                : base(s, config, tr)
-            {
-                this.outerInstance = outerInstance;
-            }
-
-            protected override bool ScoreSubDocsAtOnce()
-            {
-                return true;
-            }
-        }
-
-        private class DrillSidewaysAnonymousInnerClassHelper2 : DrillSideways
-        {
-            private readonly TestDrillSideways outerInstance;
-
-            private new Lucene.Net.Facet.FacetsConfig config;
-            private string[][] drillDowns;
-
-            public DrillSidewaysAnonymousInnerClassHelper2(TestDrillSideways outerInstance, IndexSearcher s, Lucene.Net.Facet.FacetsConfig config, TaxonomyReader tr, string[][] drillDowns)
-                : base(s, config, tr)
-            {
-                this.outerInstance = outerInstance;
-                this.config = config;
-                this.drillDowns = drillDowns;
-            }
-
-            protected override Facets BuildFacetsResult(FacetsCollector drillDowns, FacetsCollector[] drillSideways, string[] drillSidewaysDims)
-            {
-                IDictionary<string, Facets> drillSidewaysFacets = new Dictionary<string, Facets>();
-                Facets drillDownFacets = outerInstance.GetTaxonomyFacetCounts(taxoReader, config, drillDowns);
-                if (drillSideways != null)
-                {
-                    for (int i = 0; i < drillSideways.Length; i++)
-                    {
-                        drillSidewaysFacets[drillSidewaysDims[i]] = outerInstance.GetTaxonomyFacetCounts(taxoReader, config, drillSideways[i]);
-                    }
-                }
-
-                if (drillSidewaysFacets.Count == 0)
-                {
-                    return drillDownFacets;
-                }
-                else
-                {
-                    return new MultiFacets(drillSidewaysFacets, drillDownFacets);
-                }
-
-            }
-        }
-
-        private class Counters
-        {
-            internal int[][] counts;
-
-            public Counters(string[][] dimValues)
-            {
-                counts = new int[dimValues.Length][];
-                for (int dim = 0; dim < dimValues.Length; dim++)
-                {
-                    counts[dim] = new int[dimValues[dim].Length];
-                }
-            }
-
-            public virtual void Inc(int[] dims, int[] dims2)
-            {
-                Inc(dims, dims2, -1);
-            }
-
-            public virtual void Inc(int[] dims, int[] dims2, int onlyDim)
-            {
-                Debug.Assert(dims.Length == counts.Length);
-                Debug.Assert(dims2.Length == counts.Length);
-                for (int dim = 0; dim < dims.Length; dim++)
-                {
-                    if (onlyDim == -1 || dim == onlyDim)
-                    {
-                        if (dims[dim] != -1)
-                        {
-                            counts[dim][dims[dim]]++;
-                        }
-                        if (dims2[dim] != -1 && dims2[dim] != dims[dim])
-                        {
-                            counts[dim][dims2[dim]]++;
-                        }
-                    }
-                }
-            }
-        }
-
-        internal class TestFacetResult
-        {
-            internal IList<Doc> Hits;
-            internal int[][] Counts;
-            internal int[] UniqueCounts;
-            public TestFacetResult()
-            {
-            }
-        }
-
-        private int[] GetTopNOrds(int[] counts, string[] values, int topN)
-        {
-            int[] ids = new int[counts.Length];
-            for (int i = 0; i < ids.Length; i++)
-            {
-                ids[i] = i;
-            }
-
-            // Naive (on purpose, to reduce bug in tester/gold):
-            // sort all ids, then return top N slice:
-            new InPlaceMergeSorterAnonymousInnerClassHelper(this, counts, values, ids).Sort(0, ids.Length);
-
-            if (topN > ids.Length)
-            {
-                topN = ids.Length;
-            }
-
-            int numSet = topN;
-            for (int i = 0; i < topN; i++)
-            {
-                if (counts[ids[i]] == 0)
-                {
-                    numSet = i;
-                    break;
-                }
-            }
-
-            int[] topNIDs = new int[numSet];
-            Array.Copy(ids, 0, topNIDs, 0, topNIDs.Length);
-            return topNIDs;
-        }
-
-        private class InPlaceMergeSorterAnonymousInnerClassHelper : InPlaceMergeSorter
-        {
-            private readonly TestDrillSideways outerInstance;
-
-            private int[] counts;
-            private string[] values;
-            private int[] ids;
-
-            public InPlaceMergeSorterAnonymousInnerClassHelper(TestDrillSideways outerInstance, int[] counts, string[] values, int[] ids)
-            {
-                this.outerInstance = outerInstance;
-                this.counts = counts;
-                this.values = values;
-                this.ids = ids;
-            }
-
-
-            protected override void Swap(int i, int j)
-            {
-                int id = ids[i];
-                ids[i] = ids[j];
-                ids[j] = id;
-            }
-
-            protected override int Compare(int i, int j)
-            {
-                int counti = counts[ids[i]];
-                int countj = counts[ids[j]];
-                // Sort by count descending...
-                if (counti > countj)
-                {
-                    return -1;
-                }
-                else if (counti < countj)
-                {
-                    return 1;
-                }
-                else
-                {
-                    // ... then by label ascending:
-                    return (new BytesRef(values[ids[i]])).CompareTo(new BytesRef(values[ids[j]]));
-                }
-            }
-
-        }
-
-        private TestFacetResult slowDrillSidewaysSearch(IndexSearcher s, IList<Doc> docs, string contentToken, string[][] drillDowns, string[][] dimValues, Filter onlyEven)
-        {
-            int numDims = dimValues.Length;
-
-            IList<Doc> hits = new List<Doc>();
-            Counters drillDownCounts = new Counters(dimValues);
-            Counters[] drillSidewaysCounts = new Counters[dimValues.Length];
-            for (int dim = 0; dim < numDims; dim++)
-            {
-                drillSidewaysCounts[dim] = new Counters(dimValues);
-            }
-
-            if (VERBOSE)
-            {
-                Console.WriteLine("  compute expected");
-            }
-
-            foreach (Doc doc in docs)
-            {
-                if (doc.deleted)
-                {
-                    continue;
-                }
-                if (onlyEven != null & (Convert.ToInt32(doc.id) & 1) != 0)
-                {
-                    continue;
-                }
-                if (contentToken == null || doc.contentToken.Equals(contentToken))
-                {
-                    int failDim = -1;
-                    for (int dim = 0; dim < numDims; dim++)
-                    {
-                        if (drillDowns[dim] != null)
-                        {
-                            string docValue = doc.dims[dim] == -1 ? null : dimValues[dim][doc.dims[dim]];
-                            string docValue2 = doc.dims2[dim] == -1 ? null : dimValues[dim][doc.dims2[dim]];
-                            bool matches = false;
-                            foreach (string value in drillDowns[dim])
-                            {
-                                if (value.Equals(docValue) || value.Equals(docValue2))
-                                {
-                                    matches = true;
-                                    break;
-                                }
-                            }
-                            if (!matches)
-                            {
-                                if (failDim == -1)
-                                {
-                                    // Doc could be a near-miss, if no other dim fails
-                                    failDim = dim;
-                                }
-                                else
-                                {
-                                    // Doc isn't a hit nor a near-miss
-                                    goto nextDocContinue;
-                                }
-                            }
-                        }
-                    }
-
-                    if (failDim == -1)
-                    {
-                        if (VERBOSE)
-                        {
-                            Console.WriteLine("    exp: id=" + doc.id + " is a hit");
-                        }
-                        // Hit:
-                        hits.Add(doc);
-                        drillDownCounts.Inc(doc.dims, doc.dims2);
-                        for (int dim = 0; dim < dimValues.Length; dim++)
-                        {
-                            drillSidewaysCounts[dim].Inc(doc.dims, doc.dims2);
-                        }
-                    }
-                    else
-                    {
-                        if (VERBOSE)
-                        {
-                            Console.WriteLine("    exp: id=" + doc.id + " is a near-miss on dim=" + failDim);
-                        }
-                        drillSidewaysCounts[failDim].Inc(doc.dims, doc.dims2, failDim);
-                    }
-                }
-            nextDocContinue: ;
-            }
-        nextDocBreak:
-
-            IDictionary<string, int?> idToDocID = new Dictionary<string, int?>();
-            for (int i = 0; i < s.IndexReader.MaxDoc; i++)
-            {
-                idToDocID[s.Doc(i).Get("id")] = i;
-            }
-
-            var hitsSorted = hits.ToArray();
-            Array.Sort(hitsSorted);
-            hits = hitsSorted.ToList();
-
-            TestFacetResult res = new TestFacetResult();
-            res.Hits = hits;
-            res.Counts = new int[numDims][];
-            res.UniqueCounts = new int[numDims];
-            for (int dim = 0; dim < numDims; dim++)
-            {
-                if (drillDowns[dim] != null)
-                {
-                    res.Counts[dim] = drillSidewaysCounts[dim].counts[dim];
-                }
-                else
-                {
-                    res.Counts[dim] = drillDownCounts.counts[dim];
-                }
-                int uniqueCount = 0;
-                for (int j = 0; j < res.Counts[dim].Length; j++)
-                {
-                    if (res.Counts[dim][j] != 0)
-                    {
-                        uniqueCount++;
-                    }
-                }
-                res.UniqueCounts[dim] = uniqueCount;
-            }
-
-            return res;
-        }
-
-        internal virtual void VerifyEquals(string[][] dimValues, IndexSearcher s, TestFacetResult expected, DrillSidewaysResult actual, IDictionary<string, float?> scores, bool isSortedSetDV)
-        {
-            if (VERBOSE)
-            {
-                Console.WriteLine("  verify totHits=" + expected.Hits.Count);
-            }
-            Assert.AreEqual(expected.Hits.Count, actual.Hits.TotalHits);
-            Assert.AreEqual(expected.Hits.Count, actual.Hits.ScoreDocs.Length);
-            for (int i = 0; i < expected.Hits.Count; i++)
-            {
-                if (VERBOSE)
-                {
-                    Console.WriteLine("    hit " + i + " expected=" + expected.Hits[i].id);
-                }
-                Assert.AreEqual(expected.Hits[i].id, s.Doc(actual.Hits.ScoreDocs[i].Doc).Get("id"));
-                // Score should be IDENTICAL:
-                Assert.AreEqual(scores[expected.Hits[i].id], actual.Hits.ScoreDocs[i].Score);
-            }
-
-            for (int dim = 0; dim < expected.Counts.Length; dim++)
-            {
-                int topN = Random().NextBoolean() ? dimValues[dim].Length : TestUtil.NextInt(Random(), 1, dimValues[dim].Length);
-                FacetResult fr = actual.Facets.GetTopChildren(topN, "dim" + dim);
-                if (VERBOSE)
-                {
-                    Console.WriteLine("    dim" + dim + " topN=" + topN + " (vs " + dimValues[dim].Length + " unique values)");
-                    Console.WriteLine("      actual");
-                }
-
-                int idx = 0;
-                IDictionary<string, int?> actualValues = new Dictionary<string, int?>();
-
-                if (fr != null)
-                {
-                    foreach (LabelAndValue labelValue in fr.LabelValues)
-                    {
-                        actualValues[labelValue.label] = (int)labelValue.value;
-                        if (VERBOSE)
-                        {
-                            Console.WriteLine("        " + idx + ": " + new BytesRef(labelValue.label) + ": " + labelValue.value);
-                            idx++;
-                        }
-                    }
-                    Assert.AreEqual(expected.UniqueCounts[dim], fr.ChildCount, "dim=" + dim);
-                }
-
-                if (topN < dimValues[dim].Length)
-                {
-                    int[] topNIDs = GetTopNOrds(expected.Counts[dim], dimValues[dim], topN);
-                    if (VERBOSE)
-                    {
-                        idx = 0;
-                        Console.WriteLine("      expected (sorted)");
-                        for (int i = 0; i < topNIDs.Length; i++)
-                        {
-                            int expectedOrd = topNIDs[i];
-                            string value = dimValues[dim][expectedOrd];
-                            Console.WriteLine("        " + idx + ": " + new BytesRef(value) + ": " + expected.Counts[dim][expectedOrd]);
-                            idx++;
-                        }
-                    }
-                    if (VERBOSE)
-                    {
-                        Console.WriteLine("      topN=" + topN + " expectedTopN=" + topNIDs.Length);
-                    }
-
-                    if (fr != null)
-                    {
-                        Assert.AreEqual(topNIDs.Length, fr.LabelValues.Length);
-                    }
-                    else
-                    {
-                        Assert.AreEqual(0, topNIDs.Length);
-                    }
-                    for (int i = 0; i < topNIDs.Length; i++)
-                    {
-                        int expectedOrd = topNIDs[i];
-                        Assert.AreEqual(expected.Counts[dim][expectedOrd], (int)fr.LabelValues[i].value);
-                        if (isSortedSetDV)
-                        {
-                            // Tie-break facet labels are only in unicode
-                            // order with SortedSetDVFacets:
-                            Assert.AreEqual("value @ idx=" + i, dimValues[dim][expectedOrd], fr.LabelValues[i].label);
-                        }
-                    }
-                }
-                else
-                {
-
-                    if (VERBOSE)
-                    {
-                        idx = 0;
-                        Console.WriteLine("      expected (unsorted)");
-                        for (int i = 0; i < dimValues[dim].Length; i++)
-                        {
-                            string value = dimValues[dim][i];
-                            if (expected.Counts[dim][i] != 0)
-                            {
-                                Console.WriteLine("        " + idx + ": " + new BytesRef(value) + ": " + expected.Counts[dim][i]);
-                                idx++;
-                            }
-                        }
-                    }
-
-                    int setCount = 0;
-                    for (int i = 0; i < dimValues[dim].Length; i++)
-                    {
-                        string value = dimValues[dim][i];
-                        if (expected.Counts[dim][i] != 0)
-                        {
-                            Assert.True(actualValues.ContainsKey(value));
-                            Assert.AreEqual(expected.Counts[dim][i], (int)actualValues[value]);
-                            setCount++;
-                        }
-                        else
-                        {
-                            Assert.False(actualValues.ContainsKey(value));
-                        }
-                    }
-                    Assert.AreEqual(setCount, actualValues.Count);
-                }
-            }
-        }
-
-        [Test]
-        public virtual void TestEmptyIndex()
-        {
-            // LUCENE-5045: make sure DrillSideways works with an empty index
-            Directory dir = NewDirectory();
-            Directory taxoDir = NewDirectory();
-            var writer = new RandomIndexWriter(Random(), dir);
-            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
-            IndexSearcher searcher = NewSearcher(writer.Reader);
-            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
-
-            // Count "Author"
-            FacetsConfig config = new FacetsConfig();
-            DrillSideways ds = new DrillSideways(searcher, config, taxoReader);
-            DrillDownQuery ddq = new DrillDownQuery(config);
-            ddq.Add("Author", "Lisa");
-
-            DrillSidewaysResult r = ds.Search(ddq, 10); // this used to fail on IllegalArgEx
-            Assert.AreEqual(0, r.Hits.TotalHits);
-
-            r = ds.Search(ddq, null, null, 10, new Sort(new SortField("foo", SortField.Type_e.INT)), false, false); // this used to fail on IllegalArgEx
-            Assert.AreEqual(0, r.Hits.TotalHits);
-
-            IOUtils.Close(writer, taxoWriter, searcher.IndexReader, taxoReader, dir, taxoDir);
-        }
-    }
-
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/TestFacetsConfig.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/TestFacetsConfig.cs b/src/Lucene.Net.Tests/core/Facet/TestFacetsConfig.cs
deleted file mode 100644
index 9c14f79..0000000
--- a/src/Lucene.Net.Tests/core/Facet/TestFacetsConfig.cs
+++ /dev/null
@@ -1,131 +0,0 @@
-using Lucene.Net.Support;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet
-{
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
-    using Document = Lucene.Net.Documents.Document;
-    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
-    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
-    using DirectoryReader = Lucene.Net.Index.DirectoryReader;
-    using IndexWriter = Lucene.Net.Index.IndexWriter;
-    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
-    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
-    using Directory = Lucene.Net.Store.Directory;
-    using IOUtils = Lucene.Net.Util.IOUtils;
-    using TestUtil = Lucene.Net.Util.TestUtil;
-
-    public class TestFacetsConfig : FacetTestCase
-    {
-
-        [Test]
-        public virtual void TestPathToStringAndBack()
-        {
-            int iters = AtLeast(1000);
-            for (int i = 0; i < iters; i++)
-            {
-                int numParts = TestUtil.NextInt(Random(), 1, 6);
-                string[] parts = new string[numParts];
-                for (int j = 0; j < numParts; j++)
-                {
-                    string s;
-                    while (true)
-                    {
-                        s = TestUtil.RandomUnicodeString(Random());
-                        if (s.Length > 0)
-                        {
-                            break;
-                        }
-                    }
-                    parts[j] = s;
-                }
-
-                string s1 = FacetsConfig.PathToString(parts);
-                string[] parts2 = FacetsConfig.StringToPath(s1);
-                Assert.True(Arrays.Equals(parts, parts2));
-            }
-        }
-
-        [Test]
-        public virtual void TestAddSameDocTwice()
-        {
-            // LUCENE-5367: this was a problem with the previous code, making sure it
-            // works with the new code.
-            Directory indexDir = NewDirectory(), taxoDir = NewDirectory();
-            IndexWriter indexWriter = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
-            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
-            FacetsConfig facetsConfig = new FacetsConfig();
-            Document doc = new Document();
-            doc.Add(new FacetField("a", "b"));
-            doc = facetsConfig.Build(taxoWriter, doc);
-            // these two addDocument() used to fail
-            indexWriter.AddDocument(doc);
-            indexWriter.AddDocument(doc);
-            IOUtils.Close(indexWriter, taxoWriter);
-
-            DirectoryReader indexReader = DirectoryReader.Open(indexDir);
-            DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir);
-            IndexSearcher searcher = NewSearcher(indexReader);
-            FacetsCollector fc = new FacetsCollector();
-            searcher.Search(new MatchAllDocsQuery(), fc);
-
-            Facets facets = GetTaxonomyFacetCounts(taxoReader, facetsConfig, fc);
-            FacetResult res = facets.GetTopChildren(10, "a");
-            Assert.AreEqual(1, res.LabelValues.Length);
-            Assert.AreEqual(2, res.LabelValues[0].value);
-            IOUtils.Close(indexReader, taxoReader);
-
-            IOUtils.Close(indexDir, taxoDir);
-        }
-
-        /// <summary>
-        /// LUCENE-5479 
-        /// </summary>
-        [Test]
-        public virtual void TestCustomDefault()
-        {
-            FacetsConfig config = new FacetsConfigAnonymousInnerClassHelper(this);
-
-            Assert.True(config.GetDimConfig("foobar").Hierarchical);
-        }
-
-        private class FacetsConfigAnonymousInnerClassHelper : FacetsConfig
-        {
-            private readonly TestFacetsConfig outerInstance;
-
-            public FacetsConfigAnonymousInnerClassHelper(TestFacetsConfig outerInstance)
-            {
-                this.outerInstance = outerInstance;
-            }
-
-            protected override DimConfig DefaultDimConfig
-            {
-                get
-                {
-                    DimConfig config = new DimConfig();
-                    config.Hierarchical = true;
-                    return config;
-                }
-            }
-        }
-    }
-
-}
\ No newline at end of file


[07/14] lucenenet git commit: Moving Lucene.Net.Facet tests to their appropriate place

Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/TestMultipleIndexFields.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/TestMultipleIndexFields.cs b/src/Lucene.Net.Tests.Facet/TestMultipleIndexFields.cs
new file mode 100644
index 0000000..086e608
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/TestMultipleIndexFields.cs
@@ -0,0 +1,300 @@
+using System.Collections.Generic;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet
+{
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+
+    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
+    using MockTokenizer = Lucene.Net.Analysis.MockTokenizer;
+    using Document = Lucene.Net.Documents.Document;
+    using Field = Lucene.Net.Documents.Field;
+    using TextField = Lucene.Net.Documents.TextField;
+    using TaxonomyReader = Lucene.Net.Facet.Taxonomy.TaxonomyReader;
+    using TaxonomyWriter = Lucene.Net.Facet.Taxonomy.TaxonomyWriter;
+    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
+    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
+    using AtomicReader = Lucene.Net.Index.AtomicReader;
+    using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
+    using IndexReader = Lucene.Net.Index.IndexReader;
+    using OpenMode = Lucene.Net.Index.IndexWriterConfig.OpenMode_e;
+    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
+    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
+    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
+    using Directory = Lucene.Net.Store.Directory;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+
+    public class TestMultipleIndexFields : FacetTestCase
+    {
+
+        private static readonly FacetField[] CATEGORIES = new FacetField[] { new FacetField("Author", "Mark Twain"), new FacetField("Author", "Stephen King"), new FacetField("Author", "Kurt Vonnegut"), new FacetField("Band", "Rock & Pop", "The Beatles"), new FacetField("Band", "Punk", "The Ramones"), new FacetField("Band", "Rock & Pop", "U2"), new FacetField("Band", "Rock & Pop", "REM"), new FacetField("Band", "Rock & Pop", "Dave Matthews Band"), new FacetField("Composer", "Bach") };
+
+        private FacetsConfig Config
+        {
+            get
+            {
+                FacetsConfig config = new FacetsConfig();
+                config.SetHierarchical("Band", true);
+                return config;
+            }
+        }
+
+        [Test]
+        public virtual void TestDefault()
+        {
+            Directory indexDir = NewDirectory();
+            Directory taxoDir = NewDirectory();
+
+            // create and open an index writer
+            var iw = new RandomIndexWriter(Random(), indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random(), MockTokenizer.WHITESPACE, false)));
+            // create and open a taxonomy writer
+            var tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE);
+            var config = Config;
+
+            seedIndex(tw, iw, config);
+
+            IndexReader ir = iw.Reader;
+            tw.Commit();
+
+            // prepare index reader and taxonomy.
+            var tr = new DirectoryTaxonomyReader(taxoDir);
+
+            // prepare searcher to search against
+            IndexSearcher searcher = NewSearcher(ir);
+
+            FacetsCollector sfc = PerformSearch(tr, ir, searcher);
+
+            // Obtain facets results and hand-test them
+            AssertCorrectResults(GetTaxonomyFacetCounts(tr, config, sfc));
+
+            assertOrdinalsExist("$facets", ir);
+
+            IOUtils.Close(tr, ir, iw, tw, indexDir, taxoDir);
+        }
+
+        [Test]
+        public virtual void TestCustom()
+        {
+            Directory indexDir = NewDirectory();
+            Directory taxoDir = NewDirectory();
+
+            // create and open an index writer
+            RandomIndexWriter iw = new RandomIndexWriter(Random(), indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random(), MockTokenizer.WHITESPACE, false)));
+            // create and open a taxonomy writer
+            var tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE);
+
+            FacetsConfig config = Config;
+            config.SetIndexFieldName("Author", "$author");
+            seedIndex(tw, iw, config);
+
+            IndexReader ir = iw.Reader;
+            tw.Commit();
+
+            // prepare index reader and taxonomy.
+            var tr = new DirectoryTaxonomyReader(taxoDir);
+
+            // prepare searcher to search against
+            IndexSearcher searcher = NewSearcher(ir);
+
+            FacetsCollector sfc = PerformSearch(tr, ir, searcher);
+
+            IDictionary<string, Facets> facetsMap = new Dictionary<string, Facets>();
+            facetsMap["Author"] = GetTaxonomyFacetCounts(tr, config, sfc, "$author");
+            Facets facets = new MultiFacets(facetsMap, GetTaxonomyFacetCounts(tr, config, sfc));
+
+            // Obtain facets results and hand-test them
+            AssertCorrectResults(facets);
+
+            assertOrdinalsExist("$facets", ir);
+            assertOrdinalsExist("$author", ir);
+
+            IOUtils.Close(tr, ir, iw, tw, indexDir, taxoDir);
+        }
+
+        [Test]
+        public virtual void TestTwoCustomsSameField()
+        {
+            Directory indexDir = NewDirectory();
+            Directory taxoDir = NewDirectory();
+
+            // create and open an index writer
+            RandomIndexWriter iw = new RandomIndexWriter(Random(), indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random(), MockTokenizer.WHITESPACE, false)));
+            // create and open a taxonomy writer
+            var tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE);
+
+            FacetsConfig config = Config;
+            config.SetIndexFieldName("Band", "$music");
+            config.SetIndexFieldName("Composer", "$music");
+            seedIndex(tw, iw, config);
+
+            IndexReader ir = iw.Reader;
+            tw.Commit();
+
+            // prepare index reader and taxonomy.
+            var tr = new DirectoryTaxonomyReader(taxoDir);
+
+            // prepare searcher to search against
+            IndexSearcher searcher = NewSearcher(ir);
+
+            FacetsCollector sfc = PerformSearch(tr, ir, searcher);
+
+            IDictionary<string, Facets> facetsMap = new Dictionary<string, Facets>();
+            Facets facets2 = GetTaxonomyFacetCounts(tr, config, sfc, "$music");
+            facetsMap["Band"] = facets2;
+            facetsMap["Composer"] = facets2;
+            Facets facets = new MultiFacets(facetsMap, GetTaxonomyFacetCounts(tr, config, sfc));
+
+            // Obtain facets results and hand-test them
+            AssertCorrectResults(facets);
+
+            assertOrdinalsExist("$facets", ir);
+            assertOrdinalsExist("$music", ir);
+            assertOrdinalsExist("$music", ir);
+
+            IOUtils.Close(tr, ir, iw, tw, indexDir, taxoDir);
+        }
+
+        private void assertOrdinalsExist(string field, IndexReader ir)
+        {
+            foreach (AtomicReaderContext context in ir.Leaves)
+            {
+                AtomicReader r = context.AtomicReader;
+                if (r.GetBinaryDocValues(field) != null)
+                {
+                    return; // not all segments must have this DocValues
+                }
+            }
+            Fail("no ordinals found for " + field);
+        }
+
+        [Test]
+        public virtual void TestDifferentFieldsAndText()
+        {
+            Directory indexDir = NewDirectory();
+            Directory taxoDir = NewDirectory();
+
+            // create and open an index writer
+            var iw = new RandomIndexWriter(Random(), indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random(), MockTokenizer.WHITESPACE, false)));
+            // create and open a taxonomy writer
+            var tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE);
+
+            FacetsConfig config = Config;
+            config.SetIndexFieldName("Band", "$bands");
+            config.SetIndexFieldName("Composer", "$composers");
+            seedIndex(tw, iw, config);
+
+            IndexReader ir = iw.Reader;
+            tw.Commit();
+
+            // prepare index reader and taxonomy.
+            var tr = new DirectoryTaxonomyReader(taxoDir);
+
+            // prepare searcher to search against
+            IndexSearcher searcher = NewSearcher(ir);
+
+            FacetsCollector sfc = PerformSearch(tr, ir, searcher);
+
+            IDictionary<string, Facets> facetsMap = new Dictionary<string, Facets>();
+            facetsMap["Band"] = GetTaxonomyFacetCounts(tr, config, sfc, "$bands");
+            facetsMap["Composer"] = GetTaxonomyFacetCounts(tr, config, sfc, "$composers");
+            Facets facets = new MultiFacets(facetsMap, GetTaxonomyFacetCounts(tr, config, sfc));
+
+            // Obtain facets results and hand-test them
+            AssertCorrectResults(facets);
+            assertOrdinalsExist("$facets", ir);
+            assertOrdinalsExist("$bands", ir);
+            assertOrdinalsExist("$composers", ir);
+
+            IOUtils.Close(tr, ir, iw, tw, indexDir, taxoDir);
+        }
+
+        [Test]
+        public virtual void TestSomeSameSomeDifferent()
+        {
+            Directory indexDir = NewDirectory();
+            Directory taxoDir = NewDirectory();
+
+            // create and open an index writer
+            RandomIndexWriter iw = new RandomIndexWriter(Random(), indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random(), MockTokenizer.WHITESPACE, false)));
+            // create and open a taxonomy writer
+            TaxonomyWriter tw = new DirectoryTaxonomyWriter(taxoDir, OpenMode.CREATE);
+
+            FacetsConfig config = Config;
+            config.SetIndexFieldName("Band", "$music");
+            config.SetIndexFieldName("Composer", "$music");
+            config.SetIndexFieldName("Author", "$literature");
+            seedIndex(tw, iw, config);
+
+            IndexReader ir = iw.Reader;
+            tw.Commit();
+
+            // prepare index reader and taxonomy.
+            var tr = new DirectoryTaxonomyReader(taxoDir);
+
+            // prepare searcher to search against
+            IndexSearcher searcher = NewSearcher(ir);
+
+            FacetsCollector sfc = PerformSearch(tr, ir, searcher);
+
+            IDictionary<string, Facets> facetsMap = new Dictionary<string, Facets>();
+            Facets facets2 = GetTaxonomyFacetCounts(tr, config, sfc, "$music");
+            facetsMap["Band"] = facets2;
+            facetsMap["Composer"] = facets2;
+            facetsMap["Author"] = GetTaxonomyFacetCounts(tr, config, sfc, "$literature");
+            Facets facets = new MultiFacets(facetsMap, GetTaxonomyFacetCounts(tr, config, sfc));
+
+            // Obtain facets results and hand-test them
+            AssertCorrectResults(facets);
+            assertOrdinalsExist("$music", ir);
+            assertOrdinalsExist("$literature", ir);
+
+            IOUtils.Close(tr, ir, iw, tw);
+            IOUtils.Close(indexDir, taxoDir);
+        }
+
+        
+        private void AssertCorrectResults(Facets facets)
+        {
+            Assert.AreEqual(5, facets.GetSpecificValue("Band"));
+            Assert.AreEqual("dim=Band path=[] value=5 childCount=2\n  Rock & Pop (4)\n  Punk (1)\n", facets.GetTopChildren(10, "Band").ToString());
+            Assert.AreEqual("dim=Band path=[Rock & Pop] value=4 childCount=4\n  The Beatles (1)\n  U2 (1)\n  REM (1)\n  Dave Matthews Band (1)\n", facets.GetTopChildren(10, "Band", "Rock & Pop").ToString());
+            Assert.AreEqual("dim=Author path=[] value=3 childCount=3\n  Mark Twain (1)\n  Stephen King (1)\n  Kurt Vonnegut (1)\n", facets.GetTopChildren(10, "Author").ToString());
+        }
+
+        
+        private static FacetsCollector PerformSearch(TaxonomyReader tr, IndexReader ir, IndexSearcher searcher)
+        {
+            FacetsCollector fc = new FacetsCollector();
+            FacetsCollector.Search(searcher, new MatchAllDocsQuery(), 10, fc);
+            return fc;
+        }
+
+        private static void seedIndex(TaxonomyWriter tw, RandomIndexWriter iw, FacetsConfig config)
+        {
+            foreach (FacetField ff in CATEGORIES)
+            {
+                Document doc = new Document();
+                doc.Add(ff);
+                doc.Add(new TextField("content", "alpha", Field.Store.YES));
+                iw.AddDocument(config.Build(tw, doc));
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/TestRandomSamplingFacetsCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/TestRandomSamplingFacetsCollector.cs b/src/Lucene.Net.Tests.Facet/TestRandomSamplingFacetsCollector.cs
new file mode 100644
index 0000000..afd46e5
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/TestRandomSamplingFacetsCollector.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Diagnostics;
+using Lucene.Net.Randomized.Generators;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet
+{
+
+    using Document = Lucene.Net.Documents.Document;
+    using Store = Lucene.Net.Documents.Field.Store;
+    using StringField = Lucene.Net.Documents.StringField;
+    using MatchingDocs = Lucene.Net.Facet.FacetsCollector.MatchingDocs;
+    using FastTaxonomyFacetCounts = Lucene.Net.Facet.Taxonomy.FastTaxonomyFacetCounts;
+    using TaxonomyReader = Lucene.Net.Facet.Taxonomy.TaxonomyReader;
+    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
+    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
+    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
+    using Term = Lucene.Net.Index.Term;
+    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
+    using MultiCollector = Lucene.Net.Search.MultiCollector;
+    using TermQuery = Lucene.Net.Search.TermQuery;
+    using Directory = Lucene.Net.Store.Directory;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    public class TestRandomSamplingFacetsCollector : FacetTestCase
+    {
+
+        [Test]
+        public virtual void TestRandomSampling()
+        {
+            Directory dir = NewDirectory();
+            Directory taxoDir = NewDirectory();
+
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            FacetsConfig config = new FacetsConfig();
+
+            int numDocs = AtLeast(10000);
+            for (int i = 0; i < numDocs; i++)
+            {
+                Document doc = new Document();
+                doc.Add(new StringField("EvenOdd", (i % 2 == 0) ? "even" : "odd", Store.NO));
+                doc.Add(new FacetField("iMod10", Convert.ToString(i % 10)));
+                writer.AddDocument(config.Build(taxoWriter, doc));
+            }
+            Random random = Random();
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+            IOUtils.Close(writer, taxoWriter);
+
+            // Test empty results
+            RandomSamplingFacetsCollector collectRandomZeroResults = new RandomSamplingFacetsCollector(numDocs / 10, random.NextLong());
+
+            // There should be no divisions by zero
+            searcher.Search(new TermQuery(new Term("EvenOdd", "NeverMatches")), collectRandomZeroResults);
+
+            // There should be no divisions by zero and no null result
+            Assert.NotNull(collectRandomZeroResults.GetMatchingDocs);
+
+            // There should be no results at all
+            foreach (MatchingDocs doc in collectRandomZeroResults.GetMatchingDocs)
+            {
+                Assert.AreEqual(0, doc.totalHits);
+            }
+
+            // Now start searching and retrieve results.
+
+            // Use a query to select half of the documents.
+            TermQuery query = new TermQuery(new Term("EvenOdd", "even"));
+
+            // there will be 5 facet values (0, 2, 4, 6 and 8), as only the even (i %
+            // 10) are hits.
+            // there is a REAL small chance that one of the 5 values will be missed when
+            // sampling.
+            // but is that 0.8 (chance not to take a value) ^ 2000 * 5 (any can be
+            // missing) ~ 10^-193
+            // so that is probably not going to happen.
+            int maxNumChildren = 5;
+
+            RandomSamplingFacetsCollector random100Percent = new RandomSamplingFacetsCollector(numDocs, random.NextLong()); // no sampling
+            RandomSamplingFacetsCollector random10Percent = new RandomSamplingFacetsCollector(numDocs / 10, random.NextLong()); // 10 % of total docs, 20% of the hits
+
+            FacetsCollector fc = new FacetsCollector();
+
+            searcher.Search(query, MultiCollector.Wrap(fc, random100Percent, random10Percent));
+
+            FastTaxonomyFacetCounts random10FacetCounts = new FastTaxonomyFacetCounts(taxoReader, config, random10Percent);
+            FastTaxonomyFacetCounts random100FacetCounts = new FastTaxonomyFacetCounts(taxoReader, config, random100Percent);
+            FastTaxonomyFacetCounts exactFacetCounts = new FastTaxonomyFacetCounts(taxoReader, config, fc);
+
+            FacetResult random10Result = random10Percent.AmortizeFacetCounts(random10FacetCounts.GetTopChildren(10, "iMod10"), config, searcher);
+            FacetResult random100Result = random100FacetCounts.GetTopChildren(10, "iMod10");
+            FacetResult exactResult = exactFacetCounts.GetTopChildren(10, "iMod10");
+
+            Assert.AreEqual(random100Result, exactResult);
+
+            // we should have five children, but there is a small chance we have less.
+            // (see above).
+            Assert.True(random10Result.ChildCount <= maxNumChildren);
+            // there should be one child at least.
+            Assert.True(random10Result.ChildCount >= 1);
+
+            // now calculate some statistics to determine if the sampled result is 'ok'.
+            // because random sampling is used, the results will vary each time.
+            int sum = 0;
+            foreach (LabelAndValue lav in random10Result.LabelValues)
+            {
+                sum += (int)lav.value;
+            }
+            float mu = (float)sum / (float)maxNumChildren;
+
+            float variance = 0;
+            foreach (LabelAndValue lav in random10Result.LabelValues)
+            {
+                variance += (float)Math.Pow((mu - (int)lav.value), 2);
+            }
+            variance = variance / maxNumChildren;
+            float sigma = (float)Math.Sqrt(variance);
+
+            // we query only half the documents and have 5 categories. The average
+            // number of docs in a category will thus be the total divided by 5*2
+            float targetMu = numDocs / (5.0f * 2.0f);
+
+            // the average should be in the range and the standard deviation should not
+            // be too great
+            Assert.True(sigma < 200);
+            Assert.True(targetMu - 3 * sigma < mu && mu < targetMu + 3 * sigma);
+
+            IOUtils.Close(searcher.IndexReader, taxoReader, dir, taxoDir);
+        }
+
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/app.config
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/app.config b/src/Lucene.Net.Tests.Facet/app.config
new file mode 100644
index 0000000..6feedb0
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/app.config
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <runtime>
+    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+      <dependentAssembly>
+        <assemblyIdentity name="nunit.framework" publicKeyToken="96d09a1eb7f44a77" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-2.6.4.14350" newVersion="2.6.4.14350" />
+      </dependentAssembly>
+    </assemblyBinding>
+  </runtime>
+</configuration>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/packages.config
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/packages.config b/src/Lucene.Net.Tests.Facet/packages.config
new file mode 100644
index 0000000..d017a09
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Apache.NMS" version="1.6.0.3083" targetFramework="net451" />
+  <package id="NUnit" version="2.6.4" targetFramework="net451" />
+</packages>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/Lucene.Net.Tests.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Lucene.Net.Tests.csproj b/src/Lucene.Net.Tests/Lucene.Net.Tests.csproj
index cde24c1..da4ef05 100644
--- a/src/Lucene.Net.Tests/Lucene.Net.Tests.csproj
+++ b/src/Lucene.Net.Tests/Lucene.Net.Tests.csproj
@@ -157,31 +157,6 @@
     <Compile Include="core\Document\TestDateTools.cs" />
     <Compile Include="core\Document\TestDocument.cs" />
     <Compile Include="core\Document\TestField.cs" />
-    <Compile Include="core\Facet\AssertingSubDocsAtOnceCollector.cs" />
-    <Compile Include="core\Facet\FacetTestCase.cs" />
-    <Compile Include="core\Facet\Range\TestRangeFacetCounts.cs" />
-    <Compile Include="core\Facet\SlowRAMDirectory.cs" />
-    <Compile Include="core\Facet\SortedSet\TestSortedSetDocValuesFacets.cs" />
-    <Compile Include="core\Facet\Taxonomy\Directory\TestAddTaxonomy.cs" />
-    <Compile Include="core\Facet\Taxonomy\Directory\TestConcurrentFacetedIndexing.cs" />
-    <Compile Include="core\Facet\Taxonomy\Directory\TestDirectoryTaxonomyReader.cs" />
-    <Compile Include="core\Facet\Taxonomy\Directory\TestDirectoryTaxonomyWriter.cs" />
-    <Compile Include="core\Facet\Taxonomy\TestCachedOrdinalsReader.cs" />
-    <Compile Include="core\Facet\Taxonomy\TestFacetLabel.cs" />
-    <Compile Include="core\Facet\Taxonomy\TestLRUHashMap.cs" />
-    <Compile Include="core\Facet\Taxonomy\TestSearcherTaxonomyManager.cs" />
-    <Compile Include="core\Facet\Taxonomy\TestTaxonomyCombined.cs" />
-    <Compile Include="core\Facet\Taxonomy\TestTaxonomyFacetAssociations.cs" />
-    <Compile Include="core\Facet\Taxonomy\TestTaxonomyFacetCounts.cs" />
-    <Compile Include="core\Facet\Taxonomy\TestTaxonomyFacetCounts2.cs" />
-    <Compile Include="core\Facet\Taxonomy\TestTaxonomyFacetSumValueSource.cs" />
-    <Compile Include="core\Facet\Taxonomy\WriterCache\TestCharBlockArray.cs" />
-    <Compile Include="core\Facet\Taxonomy\WriterCache\TestCompactLabelToOrdinal.cs" />
-    <Compile Include="core\Facet\TestDrillDownQuery.cs" />
-    <Compile Include="core\Facet\TestDrillSideways.cs" />
-    <Compile Include="core\Facet\TestFacetsConfig.cs" />
-    <Compile Include="core\Facet\TestMultipleIndexFields.cs" />
-    <Compile Include="core\Facet\TestRandomSamplingFacetsCollector.cs" />
     <Compile Include="core\Index\BinaryTokenStream.cs" />
     <Compile Include="core\Index\Test2BBinaryDocValues.cs" />
     <Compile Include="core\Index\Test2BDocs.cs" />

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/AssertingSubDocsAtOnceCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/AssertingSubDocsAtOnceCollector.cs b/src/Lucene.Net.Tests/core/Facet/AssertingSubDocsAtOnceCollector.cs
deleted file mode 100644
index c3730df..0000000
--- a/src/Lucene.Net.Tests/core/Facet/AssertingSubDocsAtOnceCollector.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-using System.Collections.Generic;
-using Apache.NMS;
-
-namespace Lucene.Net.Facet
-{
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-
-    using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
-    using Collector = Lucene.Net.Search.Collector;
-    using ChildScorer = Lucene.Net.Search.Scorer.ChildScorer;
-    using Scorer = Lucene.Net.Search.Scorer;
-
-    /// <summary>
-    /// Verifies in collect() that all child subScorers are on
-    ///  the collected doc. 
-    /// </summary>
-    internal class AssertingSubDocsAtOnceCollector : Collector
-    {
-
-        // TODO: allow wrapping another Collector
-
-        internal IList<Scorer> allScorers;
-
-        public override Scorer Scorer
-        {
-            set
-            {
-                // Gathers all scorers, including value and "under":
-                allScorers = new List<Scorer>();
-                allScorers.Add(value);
-                int upto = 0;
-                while (upto < allScorers.Count)
-                {
-                    value = allScorers[upto++];
-                    foreach (ChildScorer sub in value.Children)
-                    {
-                        allScorers.Add(sub.Child);
-                    }
-                }
-            }
-        }
-
-        public override void Collect(int docID)
-        {
-            foreach (Scorer s in allScorers)
-            {
-                if (docID != s.DocID())
-                {
-                    throw new IllegalStateException("subScorer=" + s + " has docID=" + s.DocID() + " != collected docID=" + docID);
-                }
-            }
-        }
-
-        public override AtomicReaderContext NextReader
-        {
-            set
-            {
-            }
-        }
-
-        public override bool AcceptsDocsOutOfOrder()
-        {
-            return false;
-        }
-
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests/core/Facet/FacetTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Facet/FacetTestCase.cs b/src/Lucene.Net.Tests/core/Facet/FacetTestCase.cs
deleted file mode 100644
index 6c2e508..0000000
--- a/src/Lucene.Net.Tests/core/Facet/FacetTestCase.cs
+++ /dev/null
@@ -1,293 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.Collections.Generic;
-using System.Linq;
-using Lucene.Net.Facet;
-using Lucene.Net.Randomized.Generators;
-using Lucene.Net.Support;
-using NUnit.Framework;
-
-namespace Lucene.Net.Facet
-{
-
-    /*
-     * Licensed to the Apache Software Foundation (ASF) under one or more
-     * contributor license agreements.  See the NOTICE file distributed with
-     * this work for additional information regarding copyright ownership.
-     * The ASF licenses this file to You under the Apache License, Version 2.0
-     * (the "License"); you may not use this file except in compliance with
-     * the License.  You may obtain a copy of the License at
-     *
-     *     http://www.apache.org/licenses/LICENSE-2.0
-     *
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-
-
-    using CachedOrdinalsReader = Lucene.Net.Facet.Taxonomy.CachedOrdinalsReader;
-    using DocValuesOrdinalsReader = Lucene.Net.Facet.Taxonomy.DocValuesOrdinalsReader;
-    using FastTaxonomyFacetCounts = Lucene.Net.Facet.Taxonomy.FastTaxonomyFacetCounts;
-    using OrdinalsReader = Lucene.Net.Facet.Taxonomy.OrdinalsReader;
-    using TaxonomyFacetCounts = Lucene.Net.Facet.Taxonomy.TaxonomyFacetCounts;
-    using TaxonomyReader = Lucene.Net.Facet.Taxonomy.TaxonomyReader;
-    using BytesRef = Lucene.Net.Util.BytesRef;
-    using SuppressCodecs = Lucene.Net.Util.LuceneTestCase.SuppressCodecs;
-    using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
-    using TestUtil = Lucene.Net.Util.TestUtil;
-
-    [TestFixture]
-    public abstract class FacetTestCase : LuceneTestCase
-    {
-        public virtual Facets GetTaxonomyFacetCounts(TaxonomyReader taxoReader, FacetsConfig config, FacetsCollector c)
-        {
-            return GetTaxonomyFacetCounts(taxoReader, config, c, FacetsConfig.DEFAULT_INDEX_FIELD_NAME);
-        }
-        public virtual Facets GetTaxonomyFacetCounts(TaxonomyReader taxoReader, FacetsConfig config, FacetsCollector c, string indexFieldName)
-        {
-            Facets facets;
-            if (Random().NextBoolean())
-            {
-                facets = new FastTaxonomyFacetCounts(indexFieldName, taxoReader, config, c);
-            }
-            else
-            {
-                OrdinalsReader ordsReader = new DocValuesOrdinalsReader(indexFieldName);
-                if (Random().NextBoolean())
-                {
-                    ordsReader = new CachedOrdinalsReader(ordsReader);
-                }
-                facets = new TaxonomyFacetCounts(ordsReader, taxoReader, config, c);
-            }
-
-            return facets;
-        }
-
-        protected internal virtual string[] GetRandomTokens(int count)
-        {
-            string[] tokens = new string[count];
-            for (int i = 0; i < tokens.Length; i++)
-            {
-                tokens[i] = TestUtil.RandomRealisticUnicodeString(Random(), 1, 10);
-                //tokens[i] = TestUtil.RandomSimpleString(Random(), 1, 10);
-            }
-            return tokens;
-        }
-
-        protected internal virtual string PickToken(string[] tokens)
-        {
-            for (int i = 0; i < tokens.Length; i++)
-            {
-                if (Random().NextBoolean())
-                {
-                    return tokens[i];
-                }
-            }
-
-            // Move long tail onto first token:
-            return tokens[0];
-        }
-
-        protected internal class TestDoc
-        {
-            public string content;
-            public string[] dims;
-            public float value;
-        }
-
-        protected internal virtual IList<TestDoc> GetRandomDocs(string[] tokens, int count, int numDims)
-        {
-            IList<TestDoc> docs = new List<TestDoc>();
-            for (int i = 0; i < count; i++)
-            {
-                TestDoc doc = new TestDoc();
-                docs.Add(doc);
-                doc.content = PickToken(tokens);
-                doc.dims = new string[numDims];
-                for (int j = 0; j < numDims; j++)
-                {
-                    doc.dims[j] = PickToken(tokens);
-                    if (Random().Next(10) < 3)
-                    {
-                        break;
-                    }
-                }
-                if (VERBOSE)
-                {
-                    Console.WriteLine("  doc " + i + ": content=" + doc.content);
-                    for (int j = 0; j < numDims; j++)
-                    {
-                        if (doc.dims[j] != null)
-                        {
-                            Console.WriteLine("    dim[" + j + "]=" + doc.dims[j]);
-                        }
-                    }
-                }
-            }
-
-            return docs;
-        }
-
-        protected internal virtual void SortTies(IList<FacetResult> results)
-        {
-            foreach (FacetResult result in results)
-            {
-                SortTies(result.LabelValues);
-            }
-        }
-
-        protected internal virtual void SortTies(LabelAndValue[] labelValues)
-        {
-            double lastValue = -1;
-            int numInRow = 0;
-            int i = 0;
-            while (i <= labelValues.Length)
-            {
-                if (i < labelValues.Length && (double)labelValues[i].value == lastValue)
-                {
-                    numInRow++;
-                }
-                else
-                {
-                    if (numInRow > 1)
-                    {
-                        Array.Sort(labelValues, i - numInRow, i, new ComparatorAnonymousInnerClassHelper(this));
-                    }
-                    numInRow = 1;
-                    if (i < labelValues.Length)
-                    {
-                        lastValue = (double)labelValues[i].value;
-                    }
-                }
-                i++;
-            }
-        }
-
-        private class ComparatorAnonymousInnerClassHelper : IComparer<LabelAndValue>
-        {
-            private readonly FacetTestCase outerInstance;
-
-            public ComparatorAnonymousInnerClassHelper(FacetTestCase outerInstance)
-            {
-                this.outerInstance = outerInstance;
-            }
-
-            public virtual int Compare(LabelAndValue a, LabelAndValue b)
-            {
-                Debug.Assert((double)a.value == (double)b.value);
-                return (new BytesRef(a.label)).CompareTo(new BytesRef(b.label));
-            }
-        }
-
-        protected internal virtual void SortLabelValues(IList<LabelAndValue> labelValues)
-        {
-            var resArray = labelValues.ToArray();
-            Array.Sort(resArray,new ComparatorAnonymousInnerClassHelper2(this));
-            labelValues = resArray.ToList();
-        }
-
-        private class ComparatorAnonymousInnerClassHelper2 : IComparer<LabelAndValue>
-        {
-            private readonly FacetTestCase outerInstance;
-
-            public ComparatorAnonymousInnerClassHelper2(FacetTestCase outerInstance)
-            {
-                this.outerInstance = outerInstance;
-            }
-
-            public virtual int Compare(LabelAndValue a, LabelAndValue b)
-            {
-                if ((double)a.value > (double)b.value)
-                {
-                    return -1;
-                }
-                else if ((double)a.value < (double)b.value)
-                {
-                    return 1;
-                }
-                else
-                {
-                    return (new BytesRef(a.label)).CompareTo(new BytesRef(b.label));
-                }
-            }
-        }
-
-        protected internal virtual void SortFacetResults(IList<FacetResult> results)
-        {
-            var resArray = results.ToArray();
-            Array.Sort(resArray, new ComparatorAnonymousInnerClassHelper3(this));
-            results = resArray.ToList();
-        }
-
-        private class ComparatorAnonymousInnerClassHelper3 : IComparer<FacetResult>
-        {
-            private readonly FacetTestCase outerInstance;
-
-            public ComparatorAnonymousInnerClassHelper3(FacetTestCase outerInstance)
-            {
-                this.outerInstance = outerInstance;
-            }
-
-            public virtual int Compare(FacetResult a, FacetResult b)
-            {
-                if ((double)a.Value > (double)b.Value)
-                {
-                    return -1;
-                }
-                else if ((double)b.Value > (double)a.Value)
-                {
-                    return 1;
-                }
-                else
-                {
-                    return 0;
-                }
-            }
-        }
-
-        [Test]
-        protected internal virtual void AssertFloatValuesEquals(IList<FacetResult> a, IList<FacetResult> b)
-        {
-            Assert.AreEqual(a.Count, b.Count);
-            float lastValue = float.PositiveInfinity;
-            IDictionary<string, FacetResult> aByDim = new Dictionary<string, FacetResult>();
-            for (int i = 0; i < a.Count; i++)
-            {
-                Assert.True((float)a[i].Value <= lastValue);
-                lastValue = (float)a[i].Value;
-                aByDim[a[i].Dim] = a[i];
-            }
-            lastValue = float.PositiveInfinity;
-            IDictionary<string, FacetResult> bByDim = new Dictionary<string, FacetResult>();
-            for (int i = 0; i < b.Count; i++)
-            {
-                bByDim[b[i].Dim] = b[i];
-                Assert.True((float)b[i].Value <= lastValue);
-                lastValue = (float)b[i].Value;
-            }
-            foreach (string dim in aByDim.Keys)
-            {
-                AssertFloatValuesEquals(aByDim[dim], bByDim[dim]);
-            }
-        }
-
-        [Test]
-        protected internal virtual void AssertFloatValuesEquals(FacetResult a, FacetResult b)
-        {
-            Assert.AreEqual(a.Dim, b.Dim);
-            Assert.True(Arrays.Equals(a.Path, b.Path));
-            Assert.AreEqual(a.ChildCount, b.ChildCount);
-            Assert.AreEqual((float)a.Value, (float)b.Value, (float)a.Value / 1e5);
-            Assert.AreEqual(a.LabelValues.Length, b.LabelValues.Length);
-            for (int i = 0; i < a.LabelValues.Length; i++)
-            {
-                Assert.AreEqual(a.LabelValues[i].label, b.LabelValues[i].label);
-                Assert.AreEqual((float)a.LabelValues[i].value, (float)b.LabelValues[i].value, (float)a.LabelValues[i].value / 1e5);
-            }
-        }
-    }
-
-}
\ No newline at end of file


[11/14] lucenenet git commit: Moving Lucene.Net.Facet tests to their appropriate place

Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Taxonomy/TestCachedOrdinalsReader.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Taxonomy/TestCachedOrdinalsReader.cs b/src/Lucene.Net.Tests.Facet/Taxonomy/TestCachedOrdinalsReader.cs
new file mode 100644
index 0000000..d528276
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Taxonomy/TestCachedOrdinalsReader.cs
@@ -0,0 +1,116 @@
+using System;
+using System.IO;
+using System.Threading;
+using Lucene.Net.Support;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet.Taxonomy
+{
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
+    using Document = Lucene.Net.Documents.Document;
+    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
+    using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
+    using DirectoryReader = Lucene.Net.Index.DirectoryReader;
+    using IndexWriter = Lucene.Net.Index.IndexWriter;
+    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
+    using Directory = Lucene.Net.Store.Directory;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+    [TestFixture]
+    public class TestCachedOrdinalsReader : FacetTestCase
+    {
+
+        [Test]
+        public virtual void TestWithThreads()
+        {
+            // LUCENE-5303: OrdinalsCache used the ThreadLocal BinaryDV instead of reader.getCoreCacheKey().
+            Store.Directory indexDir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+            IndexWriterConfig conf = NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
+            IndexWriter writer = new IndexWriter(indexDir, conf);
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            FacetsConfig config = new FacetsConfig();
+
+            Document doc = new Document();
+            doc.Add(new FacetField("A", "1"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+            doc = new Document();
+            doc.Add(new FacetField("A", "2"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            var reader = DirectoryReader.Open(writer, true);
+            CachedOrdinalsReader ordsReader = new CachedOrdinalsReader(new DocValuesOrdinalsReader(FacetsConfig.DEFAULT_INDEX_FIELD_NAME));
+            ThreadClass[] threads = new ThreadClass[3];
+            for (int i = 0; i < threads.Length; i++)
+            {
+                threads[i] = new ThreadAnonymousInnerClassHelper(this, "CachedOrdsThread-" + i, reader, ordsReader);
+            }
+
+            long ramBytesUsed = 0;
+            foreach (ThreadClass t in threads)
+            {
+                t.Start();
+                t.Join();
+                if (ramBytesUsed == 0)
+                {
+                    ramBytesUsed = ordsReader.RamBytesUsed();
+                }
+                else
+                {
+                    Assert.AreEqual(ramBytesUsed, ordsReader.RamBytesUsed());
+                }
+            }
+
+            IOUtils.Close(writer, taxoWriter, reader, indexDir, taxoDir);
+        }
+
+        private class ThreadAnonymousInnerClassHelper : ThreadClass
+        {
+            private readonly TestCachedOrdinalsReader outerInstance;
+
+            private DirectoryReader reader;
+            private Lucene.Net.Facet.Taxonomy.CachedOrdinalsReader ordsReader;
+
+            public ThreadAnonymousInnerClassHelper(TestCachedOrdinalsReader outerInstance, string CachedOrdsThread, DirectoryReader reader, Lucene.Net.Facet.Taxonomy.CachedOrdinalsReader ordsReader)
+                : base("CachedOrdsThread-")
+            {
+                this.outerInstance = outerInstance;
+                this.reader = reader;
+                this.ordsReader = ordsReader;
+            }
+
+            public override void Run()
+            {
+                foreach (var context in reader.Leaves)
+                {
+                    try
+                    {
+                        ordsReader.GetReader(context);
+                    }
+                    catch (IOException e)
+                    {
+                        throw new Exception(e.Message, e);
+                    }
+                }
+            }
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Taxonomy/TestFacetLabel.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Taxonomy/TestFacetLabel.cs b/src/Lucene.Net.Tests.Facet/Taxonomy/TestFacetLabel.cs
new file mode 100644
index 0000000..0226137
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Taxonomy/TestFacetLabel.cs
@@ -0,0 +1,360 @@
+using System;
+using Lucene.Net.Support;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet.Taxonomy
+{
+
+    using SortedSetDocValuesFacetField = Lucene.Net.Facet.SortedSet.SortedSetDocValuesFacetField;
+    using BytesRef = Lucene.Net.Util.BytesRef;
+    using TestUtil = Lucene.Net.Util.TestUtil;
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+    [TestFixture]
+    public class TestFacetLabel : FacetTestCase
+    {
+
+        [Test]
+        public virtual void TestBasic()
+        {
+            Assert.AreEqual(0, (new FacetLabel()).Length);
+            Assert.AreEqual(1, (new FacetLabel("hello")).Length);
+            Assert.AreEqual(2, (new FacetLabel("hello", "world")).Length);
+        }
+
+        [Test]
+        public virtual void TestToString()
+        {
+            // When the category is empty, we expect an empty string
+            Assert.AreEqual("FacetLabel: []", (new FacetLabel()).ToString());
+            // one category
+            Assert.AreEqual("FacetLabel: [hello]", (new FacetLabel("hello")).ToString());
+            // more than one category
+            Assert.AreEqual("FacetLabel: [hello, world]", (new FacetLabel("hello", "world")).ToString());
+        }
+
+        [Test]
+        public virtual void TestGetComponent()
+        {
+            string[] components = new string[AtLeast(10)];
+            for (int i = 0; i < components.Length; i++)
+            {
+                components[i] = Convert.ToString(i);
+            }
+            FacetLabel cp = new FacetLabel(components);
+            for (int i = 0; i < components.Length; i++)
+            {
+                Assert.AreEqual(i, Convert.ToInt32(cp.Components[i]));
+            }
+        }
+
+        [Test]
+        public virtual 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.
+            FacetLabel p = new FacetLabel();
+            Assert.AreEqual(0, p.Length);
+            Assert.AreEqual("FacetLabel: []", p.ToString());
+        }
+
+        [Test]
+        public virtual void TestSubPath()
+        {
+            FacetLabel p = new FacetLabel("hi", "there", "man");
+            Assert.AreEqual(p.Length, 3);
+
+            FacetLabel p1 = p.Subpath(2);
+            Assert.AreEqual(2, p1.Length);
+            Assert.AreEqual("FacetLabel: [hi, there]", p1.ToString());
+
+            p1 = p.Subpath(1);
+            Assert.AreEqual(1, p1.Length);
+            Assert.AreEqual("FacetLabel: [hi]", p1.ToString());
+
+            p1 = p.Subpath(0);
+            Assert.AreEqual(0, p1.Length);
+            Assert.AreEqual("FacetLabel: []", p1.ToString());
+
+            // with all the following lengths, the prefix should be the whole path 
+            int[] lengths = new int[] { 3, -1, 4 };
+            for (int i = 0; i < lengths.Length; i++)
+            {
+                p1 = p.Subpath(lengths[i]);
+                Assert.AreEqual(3, p1.Length);
+                Assert.AreEqual("FacetLabel: [hi, there, man]", p1.ToString());
+                Assert.AreEqual(p, p1);
+            }
+        }
+
+        [Test]
+        public virtual void TestEquals()
+        {
+            Assert.AreEqual(new FacetLabel(), new FacetLabel());
+            Assert.False((new FacetLabel()).Equals(new FacetLabel("hi")));
+            Assert.False((new FacetLabel()).Equals(Convert.ToInt32(3)));
+            Assert.AreEqual(new FacetLabel("hello", "world"), new FacetLabel("hello", "world"));
+        }
+
+        [Test]
+        public virtual void TestHashCode()
+        {
+            Assert.AreEqual((new FacetLabel()).GetHashCode(), (new FacetLabel()).GetHashCode());
+            Assert.False((new FacetLabel()).GetHashCode() == (new FacetLabel("hi")).GetHashCode());
+            Assert.AreEqual((new FacetLabel("hello", "world")).GetHashCode(), (new FacetLabel("hello", "world")).GetHashCode());
+        }
+
+        [Test]
+        public virtual void TestLongHashCode()
+        {
+            Assert.AreEqual((new FacetLabel()).LongHashCode(), (new FacetLabel()).LongHashCode());
+            Assert.False((new FacetLabel()).LongHashCode() == (new FacetLabel("hi")).LongHashCode());
+            Assert.AreEqual((new FacetLabel("hello", "world")).LongHashCode(), (new FacetLabel("hello", "world")).LongHashCode());
+        }
+
+        [Test]
+        public virtual void TestArrayConstructor()
+        {
+            FacetLabel p = new FacetLabel("hello", "world", "yo");
+            Assert.AreEqual(3, p.Length);
+            Assert.AreEqual("FacetLabel: [hello, world, yo]", p.ToString());
+        }
+
+        [Test]
+        public virtual void TestCompareTo()
+        {
+            FacetLabel p = new FacetLabel("a", "b", "c", "d");
+            FacetLabel pother = new FacetLabel("a", "b", "c", "d");
+            Assert.AreEqual(0, pother.CompareTo(p));
+            Assert.AreEqual(0, p.CompareTo(pother));
+            pother = new FacetLabel();
+            Assert.True(pother.CompareTo(p) < 0);
+            Assert.True(p.CompareTo(pother) > 0);
+            pother = new FacetLabel("a", "b_", "c", "d");
+            Assert.True(pother.CompareTo(p) > 0);
+            Assert.True(p.CompareTo(pother) < 0);
+            pother = new FacetLabel("a", "b", "c");
+            Assert.True(pother.CompareTo(p) < 0);
+            Assert.True(p.CompareTo(pother) > 0);
+            pother = new FacetLabel("a", "b", "c", "e");
+            Assert.True(pother.CompareTo(p) > 0);
+            Assert.True(p.CompareTo(pother) < 0);
+        }
+
+        [Test]
+        public virtual void TestEmptyNullComponents()
+        {
+            // LUCENE-4724: CategoryPath should not allow empty or null components
+            string[][] components_tests = new string[][]
+		{
+			new string[] {"", "test"},
+			new string[] {"test", ""},
+			new string[] {"test", "", "foo"},
+			new string[] {null, "test"},
+			new string[] {"test", null},
+			new string[] {"test", null, "foo"}
+		};
+
+            foreach (string[] components in components_tests)
+            {
+                try
+                {
+                    Assert.NotNull(new FacetLabel(components));
+                    Fail("empty or null components should not be allowed: " + Arrays.ToString(components));
+                }
+                catch (System.ArgumentException)
+                {
+                    // expected
+                }
+                try
+                {
+                    new FacetField("dim", components);
+                    Fail("empty or null components should not be allowed: " + Arrays.ToString(components));
+                }
+                catch (System.ArgumentException)
+                {
+                    // expected
+                }
+                try
+                {
+                    new AssociationFacetField(new BytesRef(), "dim", components);
+                    Fail("empty or null components should not be allowed: " + Arrays.ToString(components));
+                }
+                catch (System.ArgumentException)
+                {
+                    // expected
+                }
+                try
+                {
+                    new IntAssociationFacetField(17, "dim", components);
+                    Fail("empty or null components should not be allowed: " + Arrays.ToString(components));
+                }
+                catch (System.ArgumentException)
+                {
+                    // expected
+                }
+                try
+                {
+                    new FloatAssociationFacetField(17.0f, "dim", components);
+                    Fail("empty or null components should not be allowed: " + Arrays.ToString(components));
+                }
+                catch (System.ArgumentException)
+                {
+                    // expected
+                }
+            }
+            try
+            {
+                new FacetField(null, new string[] { "abc" });
+                Fail("empty or null components should not be allowed");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            try
+            {
+                new FacetField("", new string[] { "abc" });
+                Fail("empty or null components should not be allowed");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            try
+            {
+                new IntAssociationFacetField(17, null, new string[] { "abc" });
+                Fail("empty or null components should not be allowed");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            try
+            {
+                new IntAssociationFacetField(17, "", new string[] { "abc" });
+                Fail("empty or null components should not be allowed");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            try
+            {
+                new FloatAssociationFacetField(17.0f, null, new string[] { "abc" });
+                Fail("empty or null components should not be allowed");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            try
+            {
+                new FloatAssociationFacetField(17.0f, "", new string[] { "abc" });
+                Fail("empty or null components should not be allowed");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            try
+            {
+                new AssociationFacetField(new BytesRef(), null, new string[] { "abc" });
+                Fail("empty or null components should not be allowed");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            try
+            {
+                new AssociationFacetField(new BytesRef(), "", new string[] { "abc" });
+                Fail("empty or null components should not be allowed");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            try
+            {
+                new SortedSetDocValuesFacetField(null, "abc");
+                Fail("empty or null components should not be allowed");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            try
+            {
+                new SortedSetDocValuesFacetField("", "abc");
+                Fail("empty or null components should not be allowed");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            try
+            {
+                new SortedSetDocValuesFacetField("dim", null);
+                Fail("empty or null components should not be allowed");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            try
+            {
+                new SortedSetDocValuesFacetField("dim", "");
+                Fail("empty or null components should not be allowed");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+        }
+
+        [Test]
+        public virtual void TestLongPath()
+        {
+            string bigComp = null;
+            while (true)
+            {
+                int len = FacetLabel.MAX_CATEGORY_PATH_LENGTH;
+                bigComp = TestUtil.RandomSimpleString(Random(), len, len);
+                if (bigComp.IndexOf('\u001f') != -1)
+                {
+                    continue;
+                }
+                break;
+            }
+
+            try
+            {
+                Assert.NotNull(new FacetLabel("dim", bigComp));
+                Fail("long paths should not be allowed; len=" + bigComp.Length);
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Taxonomy/TestLRUHashMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Taxonomy/TestLRUHashMap.cs b/src/Lucene.Net.Tests.Facet/Taxonomy/TestLRUHashMap.cs
new file mode 100644
index 0000000..71b62c5
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Taxonomy/TestLRUHashMap.cs
@@ -0,0 +1,65 @@
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet.Taxonomy
+{
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    using Lucene.Net.Facet.Taxonomy;
+    [TestFixture]
+    public class TestLRUHashMap : FacetTestCase
+    {
+        // testLRU() tests that the specified size limit is indeed honored, and
+        // the remaining objects in the map are indeed those that have been most
+        // recently used
+        [Test]
+        public virtual void TestLru()
+        {
+            LRUHashMap<string, string> lru = new LRUHashMap<string, string>(3,1);
+            Assert.AreEqual(0, lru.Size());
+            lru.Put("one", "Hello world");
+            Assert.AreEqual(1, lru.Size());
+            lru.Put("two", "Hi man");
+            Assert.AreEqual(2, lru.Size());
+            lru.Put("three", "Bonjour");
+            Assert.AreEqual(3, lru.Size());
+            lru.Put("four", "Shalom");
+            Assert.AreEqual(3, lru.Size());
+            Assert.NotNull(lru.Get("three"));
+            Assert.NotNull(lru.Get("two"));
+            Assert.NotNull(lru.Get("four"));
+            Assert.Null(lru.Get("one"));
+            lru.Put("five", "Yo!");
+            Assert.AreEqual(3, lru.Size());
+            Assert.Null(lru.Get("three")); // three was last used, so it got removed
+            Assert.NotNull(lru.Get("five"));
+            lru.Get("four");
+            lru.Put("six", "hi");
+            lru.Put("seven", "hey dude");
+            Assert.AreEqual(3, lru.Size());
+            Assert.Null(lru.Get("one"));
+            Assert.Null(lru.Get("two"));
+            Assert.Null(lru.Get("three"));
+            Assert.NotNull(lru.Get("four"));
+            Assert.Null(lru.Get("five"));
+            Assert.NotNull(lru.Get("six"));
+            Assert.NotNull(lru.Get("seven"));
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Taxonomy/TestSearcherTaxonomyManager.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Taxonomy/TestSearcherTaxonomyManager.cs b/src/Lucene.Net.Tests.Facet/Taxonomy/TestSearcherTaxonomyManager.cs
new file mode 100644
index 0000000..dd93d18
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Taxonomy/TestSearcherTaxonomyManager.cs
@@ -0,0 +1,398 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+using Apache.NMS;
+using Lucene.Net.Support;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet.Taxonomy
+{
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+
+    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
+    using Document = Lucene.Net.Documents.Document;
+    using SearcherAndTaxonomy = Lucene.Net.Facet.Taxonomy.SearcherTaxonomyManager.SearcherAndTaxonomy;
+    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
+    using IndexWriter = Lucene.Net.Index.IndexWriter;
+    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
+    using TieredMergePolicy = Lucene.Net.Index.TieredMergePolicy;
+    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
+    using Lucene.Net.Search;
+    using Directory = Lucene.Net.Store.Directory;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+    using TestUtil = Lucene.Net.Util.TestUtil;
+    [TestFixture]
+    public class TestSearcherTaxonomyManager : FacetTestCase
+    {
+
+        private class IndexerThread : ThreadClass
+        {
+
+            internal IndexWriter w;
+            internal FacetsConfig config;
+            internal TaxonomyWriter tw;
+            internal ReferenceManager<SearcherAndTaxonomy> mgr;
+            internal int ordLimit;
+            internal AtomicBoolean stop;
+
+            public IndexerThread(IndexWriter w, FacetsConfig config, TaxonomyWriter tw, ReferenceManager<SearcherAndTaxonomy> mgr, int ordLimit, AtomicBoolean stop)
+            {
+                this.w = w;
+                this.config = config;
+                this.tw = tw;
+                this.mgr = mgr;
+                this.ordLimit = ordLimit;
+                this.stop = stop;
+            }
+
+            public override void Run()
+            {
+                try
+                {
+                    var seen = new HashSet<string>();
+                    IList<string> paths = new List<string>();
+                    while (true)
+                    {
+                        Document doc = new Document();
+                        int numPaths = TestUtil.NextInt(Random(), 1, 5);
+                        for (int i = 0; i < numPaths; i++)
+                        {
+                            string path;
+                            if (paths.Count > 0 && Random().Next(5) != 4)
+                            {
+                                // Use previous path
+                                path = paths[Random().Next(paths.Count)];
+                            }
+                            else
+                            {
+                                // Create new path
+                                path = null;
+                                while (true)
+                                {
+                                    path = TestUtil.RandomRealisticUnicodeString(Random());
+                                    if (path.Length != 0 && !seen.Contains(path))
+                                    {
+                                        seen.Add(path);
+                                        paths.Add(path);
+                                        break;
+                                    }
+                                }
+                            }
+                            doc.Add(new FacetField("field", path));
+                        }
+                        try
+                        {
+                            w.AddDocument(config.Build(tw, doc));
+                            if (mgr != null && Random().NextDouble() < 0.02)
+                            {
+                                w.Commit();
+                                tw.Commit();
+                                mgr.MaybeRefresh();
+                            }
+                        }
+                        catch (IOException ioe)
+                        {
+                            throw new Exception(ioe.Message, ioe);
+                        }
+
+                        if (VERBOSE)
+                        {
+                            Console.WriteLine("TW size=" + tw.Size + " vs " + ordLimit);
+                        }
+
+                        if (tw.Size >= ordLimit)
+                        {
+                            break;
+                        }
+                    }
+                }
+                finally
+                {
+                    stop.Set(true);
+                }
+            }
+
+        }
+
+        [Test]
+        public virtual void TestNrt()
+        {
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+            IndexWriterConfig iwc = NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
+            // Don't allow tiny maxBufferedDocs; it can make this
+            // test too slow:
+            iwc.SetMaxBufferedDocs(Math.Max(500, iwc.MaxBufferedDocs));
+
+            // MockRandom/AlcololicMergePolicy are too slow:
+            TieredMergePolicy tmp = new TieredMergePolicy();
+            tmp.FloorSegmentMB = .001;
+            iwc.SetMergePolicy(tmp);
+            IndexWriter w = new IndexWriter(dir, iwc);
+            var tw = new DirectoryTaxonomyWriter(taxoDir);
+            FacetsConfig config = new FacetsConfig();
+            config.SetMultiValued("field", true);
+            AtomicBoolean stop = new AtomicBoolean();
+
+            // How many unique facets to index before stopping:
+            int ordLimit = TEST_NIGHTLY ? 100000 : 6000;
+
+            var indexer = new IndexerThread(w, config, tw, null, ordLimit, stop);
+
+            var mgr = new SearcherTaxonomyManager(w, true, null, tw);
+
+            var reopener = new ThreadAnonymousInnerClassHelper(this, stop, mgr);
+
+            reopener.Name = "reopener";
+            reopener.Start();
+
+            indexer.Name = "indexer";
+            indexer.Start();
+
+            try
+            {
+                while (!stop.Get())
+                {
+                    SearcherAndTaxonomy pair = mgr.Acquire();
+                    try
+                    {
+                        //System.out.println("search maxOrd=" + pair.taxonomyReader.getSize());
+                        FacetsCollector sfc = new FacetsCollector();
+                        pair.searcher.Search(new MatchAllDocsQuery(), sfc);
+                        Facets facets = GetTaxonomyFacetCounts(pair.taxonomyReader, config, sfc);
+                        FacetResult result = facets.GetTopChildren(10, "field");
+                        if (pair.searcher.IndexReader.NumDocs > 0)
+                        {
+                            //System.out.println(pair.taxonomyReader.getSize());
+                            Assert.True(result.ChildCount > 0);
+                            Assert.True(result.LabelValues.Length > 0);
+                        }
+
+                        //if (VERBOSE) {
+                        //System.out.println("TEST: facets=" + FacetTestUtils.toString(results.get(0)));
+                        //}
+                    }
+                    finally
+                    {
+                        mgr.Release(pair);
+                    }
+                }
+            }
+            finally
+            {
+                indexer.Join();
+                reopener.Join();
+            }
+
+            if (VERBOSE)
+            {
+                Console.WriteLine("TEST: now stop");
+            }
+
+            IOUtils.Close(mgr, tw, w, taxoDir, dir);
+        }
+
+        private class ThreadAnonymousInnerClassHelper : ThreadClass
+        {
+            private readonly TestSearcherTaxonomyManager outerInstance;
+
+            private AtomicBoolean stop;
+            private Lucene.Net.Facet.Taxonomy.SearcherTaxonomyManager mgr;
+
+            public ThreadAnonymousInnerClassHelper(TestSearcherTaxonomyManager outerInstance, AtomicBoolean stop, Lucene.Net.Facet.Taxonomy.SearcherTaxonomyManager mgr)
+            {
+                this.outerInstance = outerInstance;
+                this.stop = stop;
+                this.mgr = mgr;
+            }
+
+            public override void Run()
+            {
+                while (!stop.Get())
+                {
+                    try
+                    {
+                        // Sleep for up to 20 msec:
+                        Thread.Sleep(Random().Next(20));
+
+                        if (VERBOSE)
+                        {
+                            Console.WriteLine("TEST: reopen");
+                        }
+
+                        mgr.MaybeRefresh();
+
+                        if (VERBOSE)
+                        {
+                            Console.WriteLine("TEST: reopen done");
+                        }
+                    }
+                    catch (Exception ioe)
+                    {
+                        throw new Exception(ioe.Message, ioe);
+                    }
+                }
+            }
+        }
+
+        
+        [Test]
+        public virtual void TestDirectory()
+        {
+            Store.Directory indexDir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+            IndexWriter w = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+            var tw = new DirectoryTaxonomyWriter(taxoDir);
+            // first empty commit
+            w.Commit();
+            tw.Commit();
+            var mgr = new SearcherTaxonomyManager(indexDir, taxoDir, null);
+            FacetsConfig config = new FacetsConfig();
+            config.SetMultiValued("field", true);
+            AtomicBoolean stop = new AtomicBoolean();
+
+            // How many unique facets to index before stopping:
+            int ordLimit = TEST_NIGHTLY ? 100000 : 6000;
+
+            var indexer = new IndexerThread(w, config, tw, mgr, ordLimit, stop);
+            indexer.Start();
+
+            try
+            {
+                while (!stop.Get())
+                {
+                    SearcherAndTaxonomy pair = mgr.Acquire();
+                    try
+                    {
+                        //System.out.println("search maxOrd=" + pair.taxonomyReader.getSize());
+                        FacetsCollector sfc = new FacetsCollector();
+                        pair.searcher.Search(new MatchAllDocsQuery(), sfc);
+                        Facets facets = GetTaxonomyFacetCounts(pair.taxonomyReader, config, sfc);
+                        FacetResult result = facets.GetTopChildren(10, "field");
+                        if (pair.searcher.IndexReader.NumDocs > 0)
+                        {
+                            //System.out.println(pair.taxonomyReader.getSize());
+                            Assert.True(result.ChildCount > 0);
+                            Assert.True(result.LabelValues.Length > 0);
+                        }
+
+                        //if (VERBOSE) {
+                        //System.out.println("TEST: facets=" + FacetTestUtils.toString(results.get(0)));
+                        //}
+                    }
+                    finally
+                    {
+                        mgr.Release(pair);
+                    }
+                }
+            }
+            finally
+            {
+                indexer.Join();
+            }
+
+            if (VERBOSE)
+            {
+                Console.WriteLine("TEST: now stop");
+            }
+
+            IOUtils.Close(mgr, tw, w, taxoDir, indexDir);
+        }
+
+        [Test]
+        public virtual void TestReplaceTaxonomyNrt()
+        {
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+            IndexWriter w = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+            var tw = new DirectoryTaxonomyWriter(taxoDir);
+
+            Store.Directory taxoDir2 = NewDirectory();
+            var tw2 = new DirectoryTaxonomyWriter(taxoDir2);
+            tw2.Dispose();
+
+            var mgr = new SearcherTaxonomyManager(w, true, null, tw);
+            w.AddDocument(new Document());
+            tw.ReplaceTaxonomy(taxoDir2);
+            taxoDir2.Dispose();
+
+            try
+            {
+                mgr.MaybeRefresh();
+                Fail("should have hit exception");
+            }
+            catch (IllegalStateException)
+            {
+                // expected
+            }
+
+            IOUtils.Close(mgr, tw, w, taxoDir, dir);
+        }
+
+        [Test]
+        public virtual void TestReplaceTaxonomyDirectory()
+        {
+            Store.Directory indexDir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+            IndexWriter w = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+            var tw = new DirectoryTaxonomyWriter(taxoDir);
+            w.Commit();
+            tw.Commit();
+
+            Store.Directory taxoDir2 = NewDirectory();
+            var tw2 = new DirectoryTaxonomyWriter(taxoDir2);
+            tw2.AddCategory(new FacetLabel("a", "b"));
+            tw2.Dispose();
+
+            var mgr = new SearcherTaxonomyManager(indexDir, taxoDir, null);
+            SearcherAndTaxonomy pair = mgr.Acquire();
+            try
+            {
+                Assert.AreEqual(1, pair.taxonomyReader.Size);
+            }
+            finally
+            {
+                mgr.Release(pair);
+            }
+
+            w.AddDocument(new Document());
+            tw.ReplaceTaxonomy(taxoDir2);
+            taxoDir2.Dispose();
+            w.Commit();
+            tw.Commit();
+
+            mgr.MaybeRefresh();
+            pair = mgr.Acquire();
+            try
+            {
+                Assert.AreEqual(3, pair.taxonomyReader.Size);
+            }
+            finally
+            {
+                mgr.Release(pair);
+            }
+
+            IOUtils.Close(mgr, tw, w, taxoDir, indexDir);
+        }
+
+    }
+
+}
\ No newline at end of file


[09/14] lucenenet git commit: Moving Lucene.Net.Facet tests to their appropriate place

Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyFacetCounts.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyFacetCounts.cs b/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyFacetCounts.cs
new file mode 100644
index 0000000..8038313
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyFacetCounts.cs
@@ -0,0 +1,851 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Lucene.Net.Randomized.Generators;
+using Lucene.Net.Support;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet.Taxonomy
+{
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+
+    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
+    using Document = Lucene.Net.Documents.Document;
+    using Field = Lucene.Net.Documents.Field;
+    using StringField = Lucene.Net.Documents.StringField;
+    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
+    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
+    using DirectoryReader = Lucene.Net.Index.DirectoryReader;
+    using IndexWriter = Lucene.Net.Index.IndexWriter;
+    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
+    using NoMergePolicy = Lucene.Net.Index.NoMergePolicy;
+    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
+    using Term = Lucene.Net.Index.Term;
+    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
+    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
+    using Query = Lucene.Net.Search.Query;
+    using TermQuery = Lucene.Net.Search.TermQuery;
+    using DefaultSimilarity = Lucene.Net.Search.Similarities.DefaultSimilarity;
+    using PerFieldSimilarityWrapper = Lucene.Net.Search.Similarities.PerFieldSimilarityWrapper;
+    using Similarity = Lucene.Net.Search.Similarities.Similarity;
+    using Directory = Lucene.Net.Store.Directory;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+    using TestUtil = Lucene.Net.Util.TestUtil;
+    [TestFixture]
+    public class TestTaxonomyFacetCounts : FacetTestCase
+    {
+
+        [Test]
+        public virtual void TestBasic()
+        {
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            // Writes facet ords to a separate directory from the
+            // main index:
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+
+            FacetsConfig config = new FacetsConfig();
+            config.SetHierarchical("Publish Date", true);
+
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            Document doc = new Document();
+            doc.Add(new FacetField("Author", "Bob"));
+            doc.Add(new FacetField("Publish Date", "2010", "10", "15"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new FacetField("Author", "Lisa"));
+            doc.Add(new FacetField("Publish Date", "2010", "10", "20"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new FacetField("Author", "Lisa"));
+            doc.Add(new FacetField("Publish Date", "2012", "1", "1"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new FacetField("Author", "Susan"));
+            doc.Add(new FacetField("Publish Date", "2012", "1", "7"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new FacetField("Author", "Frank"));
+            doc.Add(new FacetField("Publish Date", "1999", "5", "5"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+
+            // NRT open
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            // Aggregate the facet counts:
+            FacetsCollector c = new FacetsCollector();
+
+            // MatchAllDocsQuery is for "browsing" (counts facets
+            // for all non-deleted docs in the index); normally
+            // you'd use a "normal" query, and use MultiCollector to
+            // wrap collecting the "normal" hits and also facets:
+            searcher.Search(new MatchAllDocsQuery(), c);
+
+            Facets facets = new FastTaxonomyFacetCounts(taxoReader, config, c);
+
+            // Retrieve & verify results:
+            Assert.AreEqual("dim=Publish Date path=[] value=5 childCount=3\n  2010 (2)\n  2012 (2)\n  1999 (1)\n", facets.GetTopChildren(10, "Publish Date").ToString());
+            Assert.AreEqual("dim=Author path=[] value=5 childCount=4\n  Lisa (2)\n  Bob (1)\n  Susan (1)\n  Frank (1)\n", facets.GetTopChildren(10, "Author").ToString());
+
+            // Now user drills down on Publish Date/2010:
+            DrillDownQuery q2 = new DrillDownQuery(config);
+            q2.Add("Publish Date", "2010");
+            c = new FacetsCollector();
+            searcher.Search(q2, c);
+            facets = new FastTaxonomyFacetCounts(taxoReader, config, c);
+            Assert.AreEqual("dim=Author path=[] value=2 childCount=2\n  Bob (1)\n  Lisa (1)\n", facets.GetTopChildren(10, "Author").ToString());
+
+            Assert.AreEqual(1, facets.GetSpecificValue("Author", "Lisa"));
+
+            Assert.Null(facets.GetTopChildren(10, "Non exitent dim"));
+
+            // Smoke test PrintTaxonomyStats:
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            PrintTaxonomyStats.PrintStats(taxoReader, Console.Out, true);
+            string result = bos.ToString();
+            Assert.True(result.IndexOf("/Author: 4 immediate children; 5 total categories", StringComparison.Ordinal) != -1);
+            Assert.True(result.IndexOf("/Publish Date: 3 immediate children; 12 total categories", StringComparison.Ordinal) != -1);
+            // Make sure at least a few nodes of the tree came out:
+            Assert.True(result.IndexOf("  /1999", StringComparison.Ordinal) != -1);
+            Assert.True(result.IndexOf("  /2012", StringComparison.Ordinal) != -1);
+            Assert.True(result.IndexOf("      /20", StringComparison.Ordinal) != -1);
+
+            IOUtils.Close(writer, taxoWriter, searcher.IndexReader, taxoReader, taxoDir, dir);
+        }
+
+        // LUCENE-5333
+        [Test]
+        public virtual void TestSparseFacets()
+        {
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            // Writes facet ords to a separate directory from the
+            // main index:
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+            FacetsConfig config = new FacetsConfig();
+
+            Document doc = new Document();
+            doc.Add(new FacetField("a", "foo1"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            if (Random().NextBoolean())
+            {
+                writer.Commit();
+            }
+
+            doc = new Document();
+            doc.Add(new FacetField("a", "foo2"));
+            doc.Add(new FacetField("b", "bar1"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            if (Random().NextBoolean())
+            {
+                writer.Commit();
+            }
+
+            doc = new Document();
+            doc.Add(new FacetField("a", "foo3"));
+            doc.Add(new FacetField("b", "bar2"));
+            doc.Add(new FacetField("c", "baz1"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+
+            // NRT open
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            FacetsCollector c = new FacetsCollector();
+            searcher.Search(new MatchAllDocsQuery(), c);
+
+            Facets facets = GetTaxonomyFacetCounts(taxoReader, new FacetsConfig(), c);
+
+            // Ask for top 10 labels for any dims that have counts:
+            IList<FacetResult> results = facets.GetAllDims(10);
+
+            Assert.AreEqual(3, results.Count);
+            Assert.AreEqual("dim=a path=[] value=3 childCount=3\n  foo1 (1)\n  foo2 (1)\n  foo3 (1)\n", results[0].ToString());
+            Assert.AreEqual("dim=b path=[] value=2 childCount=2\n  bar1 (1)\n  bar2 (1)\n", results[1].ToString());
+            Assert.AreEqual("dim=c path=[] value=1 childCount=1\n  baz1 (1)\n", results[2].ToString());
+
+            IOUtils.Close(writer, taxoWriter, searcher.IndexReader, taxoReader, taxoDir, dir);
+        }
+
+        [Test]
+        public virtual void TestWrongIndexFieldName()
+        {
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            // Writes facet ords to a separate directory from the
+            // main index:
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+
+            FacetsConfig config = new FacetsConfig();
+            config.SetIndexFieldName("a", "$facets2");
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            Document doc = new Document();
+            doc.Add(new FacetField("a", "foo1"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+
+            // NRT open
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            FacetsCollector c = new FacetsCollector();
+            searcher.Search(new MatchAllDocsQuery(), c);
+
+            // Uses default $facets field:
+            Facets facets;
+            if (Random().NextBoolean())
+            {
+                facets = new FastTaxonomyFacetCounts(taxoReader, config, c);
+            }
+            else
+            {
+                OrdinalsReader ordsReader = new DocValuesOrdinalsReader();
+                if (Random().NextBoolean())
+                {
+                    ordsReader = new CachedOrdinalsReader(ordsReader);
+                }
+                facets = new TaxonomyFacetCounts(ordsReader, taxoReader, config, c);
+            }
+
+            // Ask for top 10 labels for any dims that have counts:
+            IList<FacetResult> results = facets.GetAllDims(10);
+            Assert.True(results.Count == 0);
+
+            try
+            {
+                facets.GetSpecificValue("a");
+                Fail("should have hit exc");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+
+            try
+            {
+                facets.GetTopChildren(10, "a");
+                Fail("should have hit exc");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+
+            IOUtils.Close(writer, taxoWriter, searcher.IndexReader, taxoReader, taxoDir, dir);
+        }
+
+        [Test]
+        public virtual void TestReallyNoNormsForDrillDown()
+        {
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+            IndexWriterConfig iwc = NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
+            iwc.SetSimilarity(new PerFieldSimilarityWrapperAnonymousInnerClassHelper(this));
+            TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir, iwc);
+            FacetsConfig config = new FacetsConfig();
+
+            Document doc = new Document();
+            doc.Add(NewTextField("field", "text", Field.Store.NO));
+            doc.Add(new FacetField("a", "path"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+            IOUtils.Close(writer, taxoWriter, dir, taxoDir);
+        }
+
+        private class PerFieldSimilarityWrapperAnonymousInnerClassHelper : PerFieldSimilarityWrapper
+        {
+            private readonly TestTaxonomyFacetCounts outerInstance;
+
+            public PerFieldSimilarityWrapperAnonymousInnerClassHelper(TestTaxonomyFacetCounts outerInstance)
+            {
+                this.outerInstance = outerInstance;
+                sim = new DefaultSimilarity();
+            }
+
+            internal readonly Similarity sim;
+
+            public override Similarity Get(string name)
+            {
+                Assert.AreEqual("field", name);
+                return sim;
+            }
+        }
+
+        [Test]
+        public virtual void TestMultiValuedHierarchy()
+        {
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+            FacetsConfig config = new FacetsConfig();
+            config.SetHierarchical("a", true);
+            config.SetMultiValued("a", true);
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            Document doc = new Document();
+            doc.Add(NewTextField("field", "text", Field.Store.NO));
+            doc.Add(new FacetField("a", "path", "x"));
+            doc.Add(new FacetField("a", "path", "y"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+
+            // NRT open
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            // Aggregate the facet counts:
+            FacetsCollector c = new FacetsCollector();
+
+            // MatchAllDocsQuery is for "browsing" (counts facets
+            // for all non-deleted docs in the index); normally
+            // you'd use a "normal" query, and use MultiCollector to
+            // wrap collecting the "normal" hits and also facets:
+            searcher.Search(new MatchAllDocsQuery(), c);
+            Facets facets = GetTaxonomyFacetCounts(taxoReader, config, c);
+
+            try
+            {
+                facets.GetSpecificValue("a");
+                Fail("didn't hit expected exception");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+
+            FacetResult result = facets.GetTopChildren(10, "a");
+            Assert.AreEqual(1, result.LabelValues.Length);
+            Assert.AreEqual(1, (int)result.LabelValues[0].value);
+
+            IOUtils.Close(writer, taxoWriter, searcher.IndexReader, taxoReader, dir, taxoDir);
+        }
+
+        [Test]
+        public virtual void TestLabelWithDelimiter()
+        {
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+
+            FacetsConfig config = new FacetsConfig();
+            config.SetMultiValued("dim", true);
+
+            Document doc = new Document();
+            doc.Add(NewTextField("field", "text", Field.Store.NO));
+            doc.Add(new FacetField("dim", "test\u001Fone"));
+            doc.Add(new FacetField("dim", "test\u001Etwo"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+
+            // NRT open
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            FacetsCollector c = new FacetsCollector();
+            searcher.Search(new MatchAllDocsQuery(), c);
+
+            Facets facets = GetTaxonomyFacetCounts(taxoReader, config, c);
+            Assert.AreEqual(1, facets.GetSpecificValue("dim", "test\u001Fone"));
+            Assert.AreEqual(1, facets.GetSpecificValue("dim", "test\u001Etwo"));
+
+            FacetResult result = facets.GetTopChildren(10, "dim");
+            Assert.AreEqual("dim=dim path=[] value=-1 childCount=2\n  test\u001Fone (1)\n  test\u001Etwo (1)\n", result.ToString());
+            IOUtils.Close(writer, taxoWriter, searcher.IndexReader, taxoReader, dir, taxoDir);
+        }
+
+        [Test]
+        public virtual void TestRequireDimCount()
+        {
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+
+            FacetsConfig config = new FacetsConfig();
+            config.SetRequireDimCount("dim", true);
+
+            config.SetMultiValued("dim2", true);
+            config.SetRequireDimCount("dim2", true);
+
+            config.SetMultiValued("dim3", true);
+            config.SetHierarchical("dim3", true);
+            config.SetRequireDimCount("dim3", true);
+
+            Document doc = new Document();
+            doc.Add(NewTextField("field", "text", Field.Store.NO));
+            doc.Add(new FacetField("dim", "a"));
+            doc.Add(new FacetField("dim2", "a"));
+            doc.Add(new FacetField("dim2", "b"));
+            doc.Add(new FacetField("dim3", "a", "b"));
+            doc.Add(new FacetField("dim3", "a", "c"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+
+            // NRT open
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            FacetsCollector c = new FacetsCollector();
+            searcher.Search(new MatchAllDocsQuery(), c);
+
+            Facets facets = GetTaxonomyFacetCounts(taxoReader, config, c);
+            Assert.AreEqual(1, facets.GetTopChildren(10, "dim").Value);
+            Assert.AreEqual(1, facets.GetTopChildren(10, "dim2").Value);
+            Assert.AreEqual(1, facets.GetTopChildren(10, "dim3").Value);
+            try
+            {
+                Assert.AreEqual(1, facets.GetSpecificValue("dim"));
+                Fail("didn't hit expected exception");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            Assert.AreEqual(1, facets.GetSpecificValue("dim2"));
+            Assert.AreEqual(1, facets.GetSpecificValue("dim3"));
+            IOUtils.Close(writer, taxoWriter, searcher.IndexReader, taxoReader, dir, taxoDir);
+        }
+
+        // LUCENE-4583: make sure if we require > 32 KB for one
+        // document, we don't hit exc when using Facet42DocValuesFormat
+        [Test]
+        public virtual void TestManyFacetsInOneDocument()
+        {
+            AssumeTrue("default Codec doesn't support huge BinaryDocValues", TestUtil.FieldSupportsHugeBinaryDocValues(FacetsConfig.DEFAULT_INDEX_FIELD_NAME));
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+            IndexWriterConfig iwc = NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir, iwc);
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+
+            FacetsConfig config = new FacetsConfig();
+            config.SetMultiValued("dim", true);
+
+            int numLabels = TestUtil.NextInt(Random(), 40000, 100000);
+
+            Document doc = new Document();
+            doc.Add(NewTextField("field", "text", Field.Store.NO));
+            for (int i = 0; i < numLabels; i++)
+            {
+                doc.Add(new FacetField("dim", "" + i));
+            }
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+
+            // NRT open
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            // Aggregate the facet counts:
+            FacetsCollector c = new FacetsCollector();
+
+            // MatchAllDocsQuery is for "browsing" (counts facets
+            // for all non-deleted docs in the index); normally
+            // you'd use a "normal" query, and use MultiCollector to
+            // wrap collecting the "normal" hits and also facets:
+            searcher.Search(new MatchAllDocsQuery(), c);
+            Facets facets = GetTaxonomyFacetCounts(taxoReader, config, c);
+
+            FacetResult result = facets.GetTopChildren(int.MaxValue, "dim");
+            Assert.AreEqual(numLabels, result.LabelValues.Length);
+            var allLabels = new HashSet<string>();
+            foreach (LabelAndValue labelValue in result.LabelValues)
+            {
+                allLabels.Add(labelValue.label);
+                Assert.AreEqual(1, (int)labelValue.value);
+            }
+            Assert.AreEqual(numLabels, allLabels.Count);
+
+            IOUtils.Close(searcher.IndexReader, taxoWriter, writer, taxoReader, dir, taxoDir);
+        }
+
+        // Make sure we catch when app didn't declare field as
+        // hierarchical but it was:
+        [Test]
+        public virtual void TestDetectHierarchicalField()
+        {
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+            var writer = new RandomIndexWriter(Random(), dir);
+            FacetsConfig config = new FacetsConfig();
+
+            Document doc = new Document();
+            doc.Add(NewTextField("field", "text", Field.Store.NO));
+            doc.Add(new FacetField("a", "path", "other"));
+            try
+            {
+                config.Build(taxoWriter, doc);
+                Fail("did not hit expected exception");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            IOUtils.Close(writer, taxoWriter, dir, taxoDir);
+        }
+
+        // Make sure we catch when app didn't declare field as
+        // multi-valued but it was:
+        [Test]
+        public virtual void TestDetectMultiValuedField()
+        {
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+            TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+            FacetsConfig config = new FacetsConfig();
+
+            Document doc = new Document();
+            doc.Add(NewTextField("field", "text", Field.Store.NO));
+            doc.Add(new FacetField("a", "path"));
+            doc.Add(new FacetField("a", "path2"));
+            try
+            {
+                config.Build(taxoWriter, doc);
+                Fail("did not hit expected exception");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            IOUtils.Close(writer, taxoWriter, dir, taxoDir);
+        }
+
+        [Test]
+        public virtual void TestSeparateIndexedFields()
+        {
+            Store.Directory indexDir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+            FacetsConfig config = new FacetsConfig();
+            config.SetIndexFieldName("b", "$b");
+
+            for (int i = AtLeast(30); i > 0; --i)
+            {
+                Document doc = new Document();
+                doc.Add(new StringField("f", "v", Field.Store.NO));
+                doc.Add(new FacetField("a", "1"));
+                doc.Add(new FacetField("b", "1"));
+                iw.AddDocument(config.Build(taxoWriter, doc));
+            }
+
+            DirectoryReader r = DirectoryReader.Open(iw, true);
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            FacetsCollector sfc = new FacetsCollector();
+            NewSearcher(r).Search(new MatchAllDocsQuery(), sfc);
+            Facets facets1 = GetTaxonomyFacetCounts(taxoReader, config, sfc);
+            Facets facets2 = GetTaxonomyFacetCounts(taxoReader, config, sfc, "$b");
+            Assert.AreEqual(r.MaxDoc, (int)facets1.GetTopChildren(10, "a").Value);
+            Assert.AreEqual(r.MaxDoc, (int)facets2.GetTopChildren(10, "b").Value);
+            IOUtils.Close(taxoWriter, iw, taxoReader, taxoDir, r, indexDir);
+        }
+
+        [Test]
+        public virtual void TestCountRoot()
+        {
+            // LUCENE-4882: FacetsAccumulator threw NPE if a FacetRequest was defined on CP.EMPTY
+            Store.Directory indexDir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+            FacetsConfig config = new FacetsConfig();
+            for (int i = AtLeast(30); i > 0; --i)
+            {
+                Document doc = new Document();
+                doc.Add(new FacetField("a", "1"));
+                doc.Add(new FacetField("b", "1"));
+                iw.AddDocument(config.Build(taxoWriter, doc));
+            }
+
+            DirectoryReader r = DirectoryReader.Open(iw, true);
+            DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            FacetsCollector sfc = new FacetsCollector();
+            NewSearcher(r).Search(new MatchAllDocsQuery(), sfc);
+            Facets facets = GetTaxonomyFacetCounts(taxoReader, config, sfc);
+            foreach (FacetResult result in facets.GetAllDims(10))
+            {
+                Assert.AreEqual(r.NumDocs, (int)result.Value);
+            }
+
+            IOUtils.Close(taxoWriter, iw, taxoReader, taxoDir, r, indexDir);
+        }
+
+        [Test]
+        public virtual void TestGetFacetResultsTwice()
+        {
+            // LUCENE-4893: counts were multiplied as many times as getFacetResults was called.
+            Store.Directory indexDir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+            FacetsConfig config = new FacetsConfig();
+
+            Document doc = new Document();
+            doc.Add(new FacetField("a", "1"));
+            doc.Add(new FacetField("b", "1"));
+            iw.AddDocument(config.Build(taxoWriter, doc));
+
+            DirectoryReader r = DirectoryReader.Open(iw, true);
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            FacetsCollector sfc = new FacetsCollector();
+            NewSearcher(r).Search(new MatchAllDocsQuery(), sfc);
+
+            Facets facets = GetTaxonomyFacetCounts(taxoReader, config, sfc);
+            IList<FacetResult> res1 = facets.GetAllDims(10);
+            IList<FacetResult> res2 = facets.GetAllDims(10);
+            Assert.AreEqual(res1, res2, "calling getFacetResults twice should return the .equals()=true result");
+
+            IOUtils.Close(taxoWriter, iw, taxoReader, taxoDir, r, indexDir);
+        }
+
+        [Test]
+        public virtual void TestChildCount()
+        {
+            // LUCENE-4885: FacetResult.numValidDescendants was not set properly by FacetsAccumulator
+            var indexDir = NewDirectory();
+            var taxoDir = NewDirectory();
+
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+            FacetsConfig config = new FacetsConfig();
+            for (int i = 0; i < 10; i++)
+            {
+                Document doc = new Document();
+                doc.Add(new FacetField("a", Convert.ToString(i)));
+                iw.AddDocument(config.Build(taxoWriter, doc));
+            }
+
+            DirectoryReader r = DirectoryReader.Open(iw, true);
+            DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            FacetsCollector sfc = new FacetsCollector();
+            NewSearcher(r).Search(new MatchAllDocsQuery(), sfc);
+            Facets facets = GetTaxonomyFacetCounts(taxoReader, config, sfc);
+
+            Assert.AreEqual(10, facets.GetTopChildren(2, "a").ChildCount);
+
+            IOUtils.Close(taxoWriter, iw, taxoReader, taxoDir, r, indexDir);
+        }
+
+        private void indexTwoDocs(TaxonomyWriter taxoWriter, IndexWriter indexWriter, FacetsConfig config, bool withContent)
+        {
+            for (int i = 0; i < 2; i++)
+            {
+                Document doc = new Document();
+                if (withContent)
+                {
+                    doc.Add(new StringField("f", "a", Field.Store.NO));
+                }
+                if (config != null)
+                {
+                    doc.Add(new FacetField("A", Convert.ToString(i)));
+                    indexWriter.AddDocument(config.Build(taxoWriter, doc));
+                }
+                else
+                {
+                    indexWriter.AddDocument(doc);
+                }
+            }
+
+            indexWriter.Commit();
+        }
+
+        [Test]
+        public virtual void TestSegmentsWithoutCategoriesOrResults()
+        {
+            // tests the accumulator when there are segments with no results
+            var indexDir = NewDirectory();
+            var taxoDir = NewDirectory();
+
+            IndexWriterConfig iwc = NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
+            //iwc.MergePolicy = NoMergePolicy.INSTANCE; // prevent merges
+            IndexWriter indexWriter = new IndexWriter(indexDir, iwc);
+
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            FacetsConfig config = new FacetsConfig();
+            indexTwoDocs(taxoWriter, indexWriter, config, false); // 1st segment, no content, with categories
+            indexTwoDocs(taxoWriter, indexWriter, null, true); // 2nd segment, with content, no categories
+            indexTwoDocs(taxoWriter, indexWriter, config, true); // 3rd segment ok
+            indexTwoDocs(taxoWriter, indexWriter, null, false); // 4th segment, no content, or categories
+            indexTwoDocs(taxoWriter, indexWriter, null, true); // 5th segment, with content, no categories
+            indexTwoDocs(taxoWriter, indexWriter, config, true); // 6th segment, with content, with categories
+            indexTwoDocs(taxoWriter, indexWriter, null, true); // 7th segment, with content, no categories
+            IOUtils.Close(indexWriter, taxoWriter);
+
+            DirectoryReader indexReader = DirectoryReader.Open(indexDir);
+            var taxoReader = new DirectoryTaxonomyReader(taxoDir);
+            IndexSearcher indexSearcher = NewSearcher(indexReader);
+
+            // search for "f:a", only segments 1 and 3 should match results
+            Query q = new TermQuery(new Term("f", "a"));
+            FacetsCollector sfc = new FacetsCollector();
+            indexSearcher.Search(q, sfc);
+            Facets facets = GetTaxonomyFacetCounts(taxoReader, config, sfc);
+            FacetResult result = facets.GetTopChildren(10, "A");
+            Assert.AreEqual(2, result.LabelValues.Length, "wrong number of children");
+            foreach (LabelAndValue labelValue in result.LabelValues)
+            {
+                Assert.AreEqual(2, (int)labelValue.value, "wrong weight for child " + labelValue.label);
+            }
+
+            IOUtils.Close(indexReader, taxoReader, indexDir, taxoDir);
+        }
+
+        [Test]
+        public virtual void TestRandom()
+        {
+            string[] tokens = GetRandomTokens(10);
+            Store.Directory indexDir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            RandomIndexWriter w = new RandomIndexWriter(Random(), indexDir);
+            var tw = new DirectoryTaxonomyWriter(taxoDir);
+            FacetsConfig config = new FacetsConfig();
+            int numDocs = AtLeast(1000);
+            int numDims = TestUtil.NextInt(Random(), 1, 7);
+            IList<TestDoc> testDocs = GetRandomDocs(tokens, numDocs, numDims);
+            foreach (TestDoc testDoc in testDocs)
+            {
+                Document doc = new Document();
+                doc.Add(NewStringField("content", testDoc.content, Field.Store.NO));
+                for (int j = 0; j < numDims; j++)
+                {
+                    if (testDoc.dims[j] != null)
+                    {
+                        doc.Add(new FacetField("dim" + j, testDoc.dims[j]));
+                    }
+                }
+                w.AddDocument(config.Build(tw, doc));
+            }
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(w.Reader);
+
+            // NRT open
+            var tr = new DirectoryTaxonomyReader(tw);
+
+            int iters = AtLeast(100);
+            for (int iter = 0; iter < iters; iter++)
+            {
+                string searchToken = tokens[Random().Next(tokens.Length)];
+                if (VERBOSE)
+                {
+                    Console.WriteLine("\nTEST: iter content=" + searchToken);
+                }
+                FacetsCollector fc = new FacetsCollector();
+                FacetsCollector.Search(searcher, new TermQuery(new Term("content", searchToken)), 10, fc);
+                Facets facets = GetTaxonomyFacetCounts(tr, config, fc);
+
+                // Slow, yet hopefully bug-free, faceting:
+                var expectedCounts = new List<Dictionary<string, int?>>();
+                for (int i = 0; i < numDims; i++)
+                {
+                    expectedCounts[i] = new Dictionary<string, int?>();
+                }
+
+                foreach (TestDoc doc in testDocs)
+                {
+                    if (doc.content.Equals(searchToken))
+                    {
+                        for (int j = 0; j < numDims; j++)
+                        {
+                            if (doc.dims[j] != null)
+                            {
+                                int? v = expectedCounts[j][doc.dims[j]];
+                                if (v == null)
+                                {
+                                    expectedCounts[j][doc.dims[j]] = 1;
+                                }
+                                else
+                                {
+                                    expectedCounts[j][doc.dims[j]] = (int)v + 1;
+                                }
+                            }
+                        }
+                    }
+                }
+
+                IList<FacetResult> expected = new List<FacetResult>();
+                for (int i = 0; i < numDims; i++)
+                {
+                    IList<LabelAndValue> labelValues = new List<LabelAndValue>();
+                    int totCount = 0;
+                    foreach (KeyValuePair<string, int?> ent in expectedCounts[i])
+                    {
+                        labelValues.Add(new LabelAndValue(ent.Key, ent.Value.Value));
+                        totCount += ent.Value.Value;
+                    }
+                    SortLabelValues(labelValues);
+                    if (totCount > 0)
+                    {
+                        expected.Add(new FacetResult("dim" + i, new string[0], totCount, labelValues.ToArray(), labelValues.Count));
+                    }
+                }
+
+                // Sort by highest value, tie break by value:
+                SortFacetResults(expected);
+
+                IList<FacetResult> actual = facets.GetAllDims(10);
+
+                // Messy: fixup ties
+                SortTies(actual);
+
+                Assert.AreEqual(expected, actual);
+            }
+
+            IOUtils.Close(w, tw, searcher.IndexReader, tr, indexDir, taxoDir);
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyFacetCounts2.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyFacetCounts2.cs b/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyFacetCounts2.cs
new file mode 100644
index 0000000..865f993
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyFacetCounts2.cs
@@ -0,0 +1,403 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Lucene.Net.Randomized.Generators;
+using Lucene.Net.Support;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet.Taxonomy
+{
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+
+    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
+    using Document = Lucene.Net.Documents.Document;
+    using Store = Lucene.Net.Documents.Field.Store;
+    using StringField = Lucene.Net.Documents.StringField;
+    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
+    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
+    using DirectoryReader = Lucene.Net.Index.DirectoryReader;
+    using IndexWriter = Lucene.Net.Index.IndexWriter;
+    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
+    using NoMergePolicy = Lucene.Net.Index.NoMergePolicy;
+    using Term = Lucene.Net.Index.Term;
+    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
+    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
+    using TermQuery = Lucene.Net.Search.TermQuery;
+    using Directory = Lucene.Net.Store.Directory;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+    [TestFixture]
+    public class TestTaxonomyFacetCounts2 : FacetTestCase
+    {
+
+        private static readonly Term A = new Term("f", "a");
+        private const string CP_A = "A", CP_B = "B";
+        private const string CP_C = "C", CP_D = "D"; // indexed w/ NO_PARENTS
+        private const int NUM_CHILDREN_CP_A = 5, NUM_CHILDREN_CP_B = 3;
+        private const int NUM_CHILDREN_CP_C = 5, NUM_CHILDREN_CP_D = 5;
+        private static readonly FacetField[] CATEGORIES_A, CATEGORIES_B;
+        private static readonly FacetField[] CATEGORIES_C, CATEGORIES_D;
+        static TestTaxonomyFacetCounts2()
+        {
+            CATEGORIES_A = new FacetField[NUM_CHILDREN_CP_A];
+            for (int i = 0; i < NUM_CHILDREN_CP_A; i++)
+            {
+                CATEGORIES_A[i] = new FacetField(CP_A, Convert.ToString(i));
+            }
+            CATEGORIES_B = new FacetField[NUM_CHILDREN_CP_B];
+            for (int i = 0; i < NUM_CHILDREN_CP_B; i++)
+            {
+                CATEGORIES_B[i] = new FacetField(CP_B, Convert.ToString(i));
+            }
+
+            // NO_PARENTS categories
+            CATEGORIES_C = new FacetField[NUM_CHILDREN_CP_C];
+            for (int i = 0; i < NUM_CHILDREN_CP_C; i++)
+            {
+                CATEGORIES_C[i] = new FacetField(CP_C, Convert.ToString(i));
+            }
+
+            // Multi-level categories
+            CATEGORIES_D = new FacetField[NUM_CHILDREN_CP_D];
+            for (int i = 0; i < NUM_CHILDREN_CP_D; i++)
+            {
+                string val = Convert.ToString(i);
+                CATEGORIES_D[i] = new FacetField(CP_D, val, val + val); // e.g. D/1/11, D/2/22...
+            }
+        }
+
+        private static Net.Store.Directory indexDir, taxoDir;
+        private static IDictionary<string, int?> allExpectedCounts, termExpectedCounts;
+
+        [TestFixtureTearDown]
+        public static void AfterClassCountingFacetsAggregatorTest()
+        {
+            IOUtils.Close(indexDir, taxoDir);
+        }
+
+        private static IList<FacetField> RandomCategories(Random random)
+        {
+            // add random categories from the two dimensions, ensuring that the same
+            // category is not added twice.
+            int numFacetsA = random.Next(3) + 1; // 1-3
+            int numFacetsB = random.Next(2) + 1; // 1-2
+            List<FacetField> categories_a = new List<FacetField>();
+            categories_a.AddRange(Arrays.AsList(CATEGORIES_A));
+            List<FacetField> categories_b = new List<FacetField>();
+            categories_b.AddRange(Arrays.AsList(CATEGORIES_B));
+            categories_a = CollectionsHelper.Shuffle(categories_a).ToList();
+            categories_b = CollectionsHelper.Shuffle(categories_b).ToList();
+
+            List<FacetField> categories = new List<FacetField>();
+            categories.AddRange(categories_a.SubList(0, numFacetsA));
+            categories.AddRange(categories_b.SubList(0, numFacetsB));
+
+            // add the NO_PARENT categories
+            categories.Add(CATEGORIES_C[Random().Next(NUM_CHILDREN_CP_C)]);
+            categories.Add(CATEGORIES_D[Random().Next(NUM_CHILDREN_CP_D)]);
+
+            return categories;
+        }
+
+        private static void AddField(Document doc)
+        {
+            doc.Add(new StringField(A.Field(), A.Text(), Store.NO));
+        }
+
+        private static void AddFacets(Document doc, FacetsConfig config, bool updateTermExpectedCounts)
+        {
+            IList<FacetField> docCategories = RandomCategories(Random());
+            foreach (FacetField ff in docCategories)
+            {
+                doc.Add(ff);
+                string cp = ff.dim + "/" + ff.path[0];
+                allExpectedCounts[cp] = allExpectedCounts[cp] + 1;
+                if (updateTermExpectedCounts)
+                {
+                    termExpectedCounts[cp] = termExpectedCounts[cp] + 1;
+                }
+            }
+            // add 1 to each NO_PARENTS dimension
+            allExpectedCounts[CP_B] = allExpectedCounts[CP_B] + 1;
+            allExpectedCounts[CP_C] = allExpectedCounts[CP_C] + 1;
+            allExpectedCounts[CP_D] = allExpectedCounts[CP_D] + 1;
+            if (updateTermExpectedCounts)
+            {
+                termExpectedCounts[CP_B] = termExpectedCounts[CP_B] + 1;
+                termExpectedCounts[CP_C] = termExpectedCounts[CP_C] + 1;
+                termExpectedCounts[CP_D] = termExpectedCounts[CP_D] + 1;
+            }
+        }
+
+        private static FacetsConfig Config
+        {
+            get
+            {
+                FacetsConfig config = new FacetsConfig();
+                config.SetMultiValued("A", true);
+                config.SetMultiValued("B", true);
+                config.SetRequireDimCount("B", true);
+                config.SetHierarchical("D", true);
+                return config;
+            }
+        }
+
+        private static void IndexDocsNoFacets(IndexWriter indexWriter)
+        {
+            int numDocs = AtLeast(2);
+            for (int i = 0; i < numDocs; i++)
+            {
+                Document doc = new Document();
+                AddField(doc);
+                indexWriter.AddDocument(doc);
+            }
+            indexWriter.Commit(); // flush a segment
+        }
+
+        private static void IndexDocsWithFacetsNoTerms(IndexWriter indexWriter, TaxonomyWriter taxoWriter, IDictionary<string, int?> expectedCounts)
+        {
+            Random random = Random();
+            int numDocs = AtLeast(random, 2);
+            FacetsConfig config = Config;
+            for (int i = 0; i < numDocs; i++)
+            {
+                Document doc = new Document();
+                AddFacets(doc, config, false);
+                indexWriter.AddDocument(config.Build(taxoWriter, doc));
+            }
+            indexWriter.Commit(); // flush a segment
+        }
+
+        private static void IndexDocsWithFacetsAndTerms(IndexWriter indexWriter, TaxonomyWriter taxoWriter, IDictionary<string, int?> expectedCounts)
+        {
+            Random random = Random();
+            int numDocs = AtLeast(random, 2);
+            FacetsConfig config = Config;
+            for (int i = 0; i < numDocs; i++)
+            {
+                Document doc = new Document();
+                AddFacets(doc, config, true);
+                AddField(doc);
+                indexWriter.AddDocument(config.Build(taxoWriter, doc));
+            }
+            indexWriter.Commit(); // flush a segment
+        }
+
+        private static void IndexDocsWithFacetsAndSomeTerms(IndexWriter indexWriter, TaxonomyWriter taxoWriter, IDictionary<string, int?> expectedCounts)
+        {
+            Random random = Random();
+            int numDocs = AtLeast(random, 2);
+            FacetsConfig config = Config;
+            for (int i = 0; i < numDocs; i++)
+            {
+                Document doc = new Document();
+                bool hasContent = random.NextBoolean();
+                if (hasContent)
+                {
+                    AddField(doc);
+                }
+                AddFacets(doc, config, hasContent);
+                indexWriter.AddDocument(config.Build(taxoWriter, doc));
+            }
+            indexWriter.Commit(); // flush a segment
+        }
+
+        // initialize expectedCounts w/ 0 for all categories
+        private static IDictionary<string, int?> newCounts()
+        {
+            IDictionary<string, int?> counts = new Dictionary<string, int?>();
+            counts[CP_A] = 0;
+            counts[CP_B] = 0;
+            counts[CP_C] = 0;
+            counts[CP_D] = 0;
+            foreach (FacetField ff in CATEGORIES_A)
+            {
+                counts[ff.dim + "/" + ff.path[0]] = 0;
+            }
+            foreach (FacetField ff in CATEGORIES_B)
+            {
+                counts[ff.dim + "/" + ff.path[0]] = 0;
+            }
+            foreach (FacetField ff in CATEGORIES_C)
+            {
+                counts[ff.dim + "/" + ff.path[0]] = 0;
+            }
+            foreach (FacetField ff in CATEGORIES_D)
+            {
+                counts[ff.dim + "/" + ff.path[0]] = 0;
+            }
+            return counts;
+        }
+
+        [TestFixtureSetUp]
+        public static void BeforeClassCountingFacetsAggregatorTest()
+        {
+            indexDir = NewDirectory();
+            taxoDir = NewDirectory();
+
+            // create an index which has:
+            // 1. Segment with no categories, but matching results
+            // 2. Segment w/ categories, but no results
+            // 3. Segment w/ categories and results
+            // 4. Segment w/ categories, but only some results
+
+            IndexWriterConfig conf = NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
+            //conf.MergePolicy = NoMergePolicy.INSTANCE; // prevent merges, so we can control the index segments
+            IndexWriter indexWriter = new IndexWriter(indexDir, conf);
+            TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+
+            allExpectedCounts = newCounts();
+            termExpectedCounts = newCounts();
+
+            // segment w/ no categories
+            IndexDocsNoFacets(indexWriter);
+
+            // segment w/ categories, no content
+            IndexDocsWithFacetsNoTerms(indexWriter, taxoWriter, allExpectedCounts);
+
+            // segment w/ categories and content
+            IndexDocsWithFacetsAndTerms(indexWriter, taxoWriter, allExpectedCounts);
+
+            // segment w/ categories and some content
+            IndexDocsWithFacetsAndSomeTerms(indexWriter, taxoWriter, allExpectedCounts);
+
+            IOUtils.Close(indexWriter, taxoWriter);
+        }
+
+        [Test]
+        public virtual void TestDifferentNumResults()
+        {
+            // test the collector w/ FacetRequests and different numResults
+            DirectoryReader indexReader = DirectoryReader.Open(indexDir);
+            var taxoReader = new DirectoryTaxonomyReader(taxoDir);
+            IndexSearcher searcher = NewSearcher(indexReader);
+
+            FacetsCollector sfc = new FacetsCollector();
+            TermQuery q = new TermQuery(A);
+            searcher.Search(q, sfc);
+            Facets facets = GetTaxonomyFacetCounts(taxoReader, Config, sfc);
+            FacetResult result = facets.GetTopChildren(NUM_CHILDREN_CP_A, CP_A);
+            Assert.AreEqual(-1, (int)result.Value);
+            foreach (LabelAndValue labelValue in result.LabelValues)
+            {
+                Assert.AreEqual(termExpectedCounts[CP_A + "/" + labelValue.label], labelValue.value);
+            }
+            result = facets.GetTopChildren(NUM_CHILDREN_CP_B, CP_B);
+            Assert.AreEqual(termExpectedCounts[CP_B], result.Value);
+            foreach (LabelAndValue labelValue in result.LabelValues)
+            {
+                Assert.AreEqual(termExpectedCounts[CP_B + "/" + labelValue.label], labelValue.value);
+            }
+
+            IOUtils.Close(indexReader, taxoReader);
+        }
+
+        [Test]
+        public virtual void TestAllCounts()
+        {
+            DirectoryReader indexReader = DirectoryReader.Open(indexDir);
+            var taxoReader = new DirectoryTaxonomyReader(taxoDir);
+            IndexSearcher searcher = NewSearcher(indexReader);
+
+            FacetsCollector sfc = new FacetsCollector();
+            searcher.Search(new MatchAllDocsQuery(), sfc);
+
+            Facets facets = GetTaxonomyFacetCounts(taxoReader, Config, sfc);
+
+            FacetResult result = facets.GetTopChildren(NUM_CHILDREN_CP_A, CP_A);
+            Assert.AreEqual(-1, (int)result.Value);
+            int prevValue = int.MaxValue;
+            foreach (LabelAndValue labelValue in result.LabelValues)
+            {
+                Assert.AreEqual(allExpectedCounts[CP_A + "/" + labelValue.label], labelValue.value);
+                Assert.True((int)labelValue.value <= prevValue, "wrong sort order of sub results: labelValue.value=" + labelValue.value + " prevValue=" + prevValue);
+                prevValue = (int)labelValue.value;
+            }
+
+            result = facets.GetTopChildren(NUM_CHILDREN_CP_B, CP_B);
+            Assert.AreEqual(allExpectedCounts[CP_B], result.Value);
+            prevValue = int.MaxValue;
+            foreach (LabelAndValue labelValue in result.LabelValues)
+            {
+                Assert.AreEqual(allExpectedCounts[CP_B + "/" + labelValue.label], labelValue.value);
+                Assert.True((int)labelValue.value <= prevValue, "wrong sort order of sub results: labelValue.value=" + labelValue.value + " prevValue=" + prevValue);
+                prevValue = (int)labelValue.value;
+            }
+
+            IOUtils.Close(indexReader, taxoReader);
+        }
+
+        [Test]
+        public virtual void TestBigNumResults()
+        {
+            DirectoryReader indexReader = DirectoryReader.Open(indexDir);
+            var taxoReader = new DirectoryTaxonomyReader(taxoDir);
+            IndexSearcher searcher = NewSearcher(indexReader);
+
+            FacetsCollector sfc = new FacetsCollector();
+            searcher.Search(new MatchAllDocsQuery(), sfc);
+
+            Facets facets = GetTaxonomyFacetCounts(taxoReader, Config, sfc);
+
+            FacetResult result = facets.GetTopChildren(int.MaxValue, CP_A);
+            Assert.AreEqual(-1, (int)result.Value);
+            foreach (LabelAndValue labelValue in result.LabelValues)
+            {
+                Assert.AreEqual(allExpectedCounts[CP_A + "/" + labelValue.label], labelValue.value);
+            }
+            result = facets.GetTopChildren(int.MaxValue, CP_B);
+            Assert.AreEqual(allExpectedCounts[CP_B], result.Value);
+            foreach (LabelAndValue labelValue in result.LabelValues)
+            {
+                Assert.AreEqual(allExpectedCounts[CP_B + "/" + labelValue.label], labelValue.value);
+            }
+
+            IOUtils.Close(indexReader, taxoReader);
+        }
+
+        [Test]
+        public virtual void TestNoParents()
+        {
+            DirectoryReader indexReader = DirectoryReader.Open(indexDir);
+            var taxoReader = new DirectoryTaxonomyReader(taxoDir);
+            IndexSearcher searcher = NewSearcher(indexReader);
+
+            var sfc = new FacetsCollector();
+            searcher.Search(new MatchAllDocsQuery(), sfc);
+
+            Facets facets = GetTaxonomyFacetCounts(taxoReader, Config, sfc);
+
+            FacetResult result = facets.GetTopChildren(NUM_CHILDREN_CP_C, CP_C);
+            Assert.AreEqual(allExpectedCounts[CP_C], result.Value);
+            foreach (LabelAndValue labelValue in result.LabelValues)
+            {
+                Assert.AreEqual(allExpectedCounts[CP_C + "/" + labelValue.label], labelValue.value);
+            }
+            result = facets.GetTopChildren(NUM_CHILDREN_CP_D, CP_D);
+            Assert.AreEqual(allExpectedCounts[CP_C], result.Value);
+            foreach (LabelAndValue labelValue in result.LabelValues)
+            {
+                Assert.AreEqual(allExpectedCounts[CP_D + "/" + labelValue.label], labelValue.value);
+            }
+
+            IOUtils.Close(indexReader, taxoReader);
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyFacetSumValueSource.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyFacetSumValueSource.cs b/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyFacetSumValueSource.cs
new file mode 100644
index 0000000..d425a1a
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyFacetSumValueSource.cs
@@ -0,0 +1,610 @@
+using System;
+using System.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Lucene.Net.Randomized.Generators;
+
+namespace Lucene.Net.Facet.Taxonomy
+{
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+
+    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
+    using Document = Lucene.Net.Documents.Document;
+    using Field = Lucene.Net.Documents.Field;
+    using FloatDocValuesField = Lucene.Net.Documents.FloatDocValuesField;
+    using IntField = Lucene.Net.Documents.IntField;
+    using NumericDocValuesField = Lucene.Net.Documents.NumericDocValuesField;
+    using StringField = Lucene.Net.Documents.StringField;
+    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
+    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
+    using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
+    using DirectoryReader = Lucene.Net.Index.DirectoryReader;
+    using IndexWriter = Lucene.Net.Index.IndexWriter;
+    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
+    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
+    using Term = Lucene.Net.Index.Term;
+    using FunctionQuery = Lucene.Net.Queries.Function.FunctionQuery;
+    using FunctionValues = Lucene.Net.Queries.Function.FunctionValues;
+    using ValueSource = Lucene.Net.Queries.Function.ValueSource;
+    using DoubleDocValues = Lucene.Net.Queries.Function.DocValues.DoubleDocValues;
+    using FloatFieldSource = Lucene.Net.Queries.Function.ValueSources.FloatFieldSource;
+    using IntFieldSource = Lucene.Net.Queries.Function.ValueSources.IntFieldSource;
+    using LongFieldSource = Lucene.Net.Queries.Function.ValueSources.LongFieldSource;
+    using ConstantScoreQuery = Lucene.Net.Search.ConstantScoreQuery;
+    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
+    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
+    using Query = Lucene.Net.Search.Query;
+    using Scorer = Lucene.Net.Search.Scorer;
+    using TermQuery = Lucene.Net.Search.TermQuery;
+    using TopDocs = Lucene.Net.Search.TopDocs;
+    using Directory = Lucene.Net.Store.Directory;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+    using TestUtil = Lucene.Net.Util.TestUtil;
+    using NUnit.Framework;
+    [TestFixture]
+    public class TestTaxonomyFacetSumValueSource : FacetTestCase
+    {
+
+        [Test]
+        public virtual void TestBasic()
+        {
+
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            // Writes facet ords to a separate directory from the
+            // main index:
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+            FacetsConfig config = new FacetsConfig();
+
+            // Reused across documents, to add the necessary facet
+            // fields:
+            Document doc = new Document();
+            doc.Add(new IntField("num", 10, Field.Store.NO));
+            doc.Add(new FacetField("Author", "Bob"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new IntField("num", 20, Field.Store.NO));
+            doc.Add(new FacetField("Author", "Lisa"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new IntField("num", 30, Field.Store.NO));
+            doc.Add(new FacetField("Author", "Lisa"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new IntField("num", 40, Field.Store.NO));
+            doc.Add(new FacetField("Author", "Susan"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            doc = new Document();
+            doc.Add(new IntField("num", 45, Field.Store.NO));
+            doc.Add(new FacetField("Author", "Frank"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+            writer.Dispose();
+
+            // NRT open
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+            taxoWriter.Dispose();
+
+            // Aggregate the facet counts:
+            FacetsCollector c = new FacetsCollector();
+
+            // MatchAllDocsQuery is for "browsing" (counts facets
+            // for all non-deleted docs in the index); normally
+            // you'd use a "normal" query and one of the
+            // Facets.search utility methods:
+            searcher.Search(new MatchAllDocsQuery(), c);
+
+            TaxonomyFacetSumValueSource facets = new TaxonomyFacetSumValueSource(taxoReader, new FacetsConfig(), c, new IntFieldSource("num"));
+
+            // Retrieve & verify results:
+            Assert.AreEqual("dim=Author path=[] value=145.0 childCount=4\n  Lisa (50.0)\n  Frank (45.0)\n  Susan (40.0)\n  Bob (10.0)\n", facets.GetTopChildren(10, "Author").ToString());
+
+            taxoReader.Dispose();
+            searcher.IndexReader.Dispose();
+            dir.Dispose();
+            taxoDir.Dispose();
+        }
+
+        // LUCENE-5333
+        [Test]
+        public virtual void TestSparseFacets()
+        {
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            // Writes facet ords to a separate directory from the
+            // main index:
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+            FacetsConfig config = new FacetsConfig();
+
+            Document doc = new Document();
+            doc.Add(new IntField("num", 10, Field.Store.NO));
+            doc.Add(new FacetField("a", "foo1"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            if (Random().NextBoolean())
+            {
+                writer.Commit();
+            }
+
+            doc = new Document();
+            doc.Add(new IntField("num", 20, Field.Store.NO));
+            doc.Add(new FacetField("a", "foo2"));
+            doc.Add(new FacetField("b", "bar1"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            if (Random().NextBoolean())
+            {
+                writer.Commit();
+            }
+
+            doc = new Document();
+            doc.Add(new IntField("num", 30, Field.Store.NO));
+            doc.Add(new FacetField("a", "foo3"));
+            doc.Add(new FacetField("b", "bar2"));
+            doc.Add(new FacetField("c", "baz1"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+            writer.Dispose();
+
+            // NRT open
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+            taxoWriter.Dispose();
+
+            FacetsCollector c = new FacetsCollector();
+            searcher.Search(new MatchAllDocsQuery(), c);
+
+            TaxonomyFacetSumValueSource facets = new TaxonomyFacetSumValueSource(taxoReader, new FacetsConfig(), c, new IntFieldSource("num"));
+
+            // Ask for top 10 labels for any dims that have counts:
+            IList<FacetResult> results = facets.GetAllDims(10);
+
+            Assert.AreEqual(3, results.Count);
+            Assert.AreEqual("dim=a path=[] value=60.0 childCount=3\n  foo3 (30.0)\n  foo2 (20.0)\n  foo1 (10.0)\n", results[0].ToString());
+            Assert.AreEqual("dim=b path=[] value=50.0 childCount=2\n  bar2 (30.0)\n  bar1 (20.0)\n", results[1].ToString());
+            Assert.AreEqual("dim=c path=[] value=30.0 childCount=1\n  baz1 (30.0)\n", results[2].ToString());
+
+            IOUtils.Close(searcher.IndexReader, taxoReader, dir, taxoDir);
+        }
+
+        [Test]
+        public virtual void TestWrongIndexFieldName()
+        {
+
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            // Writes facet ords to a separate directory from the
+            // main index:
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir, IndexWriterConfig.OpenMode_e.CREATE);
+
+            FacetsConfig config = new FacetsConfig();
+            config.SetIndexFieldName("a", "$facets2");
+
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            Document doc = new Document();
+            doc.Add(new IntField("num", 10, Field.Store.NO));
+            doc.Add(new FacetField("a", "foo1"));
+            writer.AddDocument(config.Build(taxoWriter, doc));
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(writer.Reader);
+            writer.Dispose();
+
+            // NRT open
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+            taxoWriter.Dispose();
+
+            FacetsCollector c = new FacetsCollector();
+            searcher.Search(new MatchAllDocsQuery(), c);
+
+            TaxonomyFacetSumValueSource facets = new TaxonomyFacetSumValueSource(taxoReader, config, c, new IntFieldSource("num"));
+
+            // Ask for top 10 labels for any dims that have counts:
+            IList<FacetResult> results = facets.GetAllDims(10);
+            Assert.True(results.Count == 0);
+
+            try
+            {
+                facets.GetSpecificValue("a");
+                Fail("should have hit exc");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+
+            try
+            {
+                facets.GetTopChildren(10, "a");
+                Fail("should have hit exc");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+
+            IOUtils.Close(searcher.IndexReader, taxoReader, dir, taxoDir);
+        }
+
+        [Test]
+        public virtual void TestSumScoreAggregator()
+        {
+            Store.Directory indexDir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+
+            FacetsConfig config = new FacetsConfig();
+
+            for (int i = AtLeast(30); i > 0; --i)
+            {
+                Document doc = new Document();
+                if (Random().NextBoolean()) // don't match all documents
+                {
+                    doc.Add(new StringField("f", "v", Field.Store.NO));
+                }
+                doc.Add(new FacetField("dim", "a"));
+                iw.AddDocument(config.Build(taxoWriter, doc));
+            }
+
+            DirectoryReader r = DirectoryReader.Open(iw, true);
+            DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            FacetsCollector fc = new FacetsCollector(true);
+            ConstantScoreQuery csq = new ConstantScoreQuery(new MatchAllDocsQuery());
+            csq.Boost = 2.0f;
+
+            TopDocs td = FacetsCollector.Search(NewSearcher(r), csq, 10, fc);
+
+            Facets facets = new TaxonomyFacetSumValueSource(taxoReader, config, fc, new TaxonomyFacetSumValueSource.ScoreValueSource());
+
+            int expected = (int)(td.MaxScore * td.TotalHits);
+            Assert.AreEqual(expected, (int)facets.GetSpecificValue("dim", "a"));
+
+            IOUtils.Close(iw, taxoWriter, taxoReader, taxoDir, r, indexDir);
+        }
+
+        [Test]
+        public virtual void TestNoScore()
+        {
+            Store.Directory indexDir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+            FacetsConfig config = new FacetsConfig();
+            for (int i = 0; i < 4; i++)
+            {
+                Document doc = new Document();
+                doc.Add(new NumericDocValuesField("price", (i + 1)));
+                doc.Add(new FacetField("a", Convert.ToString(i % 2)));
+                iw.AddDocument(config.Build(taxoWriter, doc));
+            }
+
+            DirectoryReader r = DirectoryReader.Open(iw, true);
+            DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            FacetsCollector sfc = new FacetsCollector();
+            NewSearcher(r).Search(new MatchAllDocsQuery(), sfc);
+            Facets facets = new TaxonomyFacetSumValueSource(taxoReader, config, sfc, new LongFieldSource("price"));
+            Assert.AreEqual("dim=a path=[] value=10.0 childCount=2\n  1 (6.0)\n  0 (4.0)\n", facets.GetTopChildren(10, "a").ToString());
+
+            IOUtils.Close(taxoWriter, iw, taxoReader, taxoDir, r, indexDir);
+        }
+
+        [Test]
+        public virtual void TestWithScore()
+        {
+            Store.Directory indexDir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+
+            FacetsConfig config = new FacetsConfig();
+            for (int i = 0; i < 4; i++)
+            {
+                Document doc = new Document();
+                doc.Add(new NumericDocValuesField("price", (i + 1)));
+                doc.Add(new FacetField("a", Convert.ToString(i % 2)));
+                iw.AddDocument(config.Build(taxoWriter, doc));
+            }
+
+            DirectoryReader r = DirectoryReader.Open(iw, true);
+            DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            ValueSource valueSource = new ValueSourceAnonymousInnerClassHelper(this);
+
+            FacetsCollector fc = new FacetsCollector(true);
+            // score documents by their 'price' field - makes asserting the correct counts for the categories easier
+            Query q = new FunctionQuery(new LongFieldSource("price"));
+            FacetsCollector.Search(NewSearcher(r), q, 10, fc);
+            Facets facets = new TaxonomyFacetSumValueSource(taxoReader, config, fc, valueSource);
+
+            Assert.AreEqual("dim=a path=[] value=10.0 childCount=2\n  1 (6.0)\n  0 (4.0)\n", facets.GetTopChildren(10, "a").ToString());
+
+            IOUtils.Close(taxoWriter, iw, taxoReader, taxoDir, r, indexDir);
+        }
+
+        private class ValueSourceAnonymousInnerClassHelper : ValueSource
+        {
+            private readonly TestTaxonomyFacetSumValueSource outerInstance;
+
+            public ValueSourceAnonymousInnerClassHelper(TestTaxonomyFacetSumValueSource outerInstance)
+            {
+                this.outerInstance = outerInstance;
+            }
+
+            public override FunctionValues GetValues(IDictionary context, AtomicReaderContext readerContext)
+            {
+                Scorer scorer = (Scorer)context["scorer"];
+                Debug.Assert(scorer != null);
+                return new DoubleDocValuesAnonymousInnerClassHelper(this, scorer);
+            }
+
+            private class DoubleDocValuesAnonymousInnerClassHelper : DoubleDocValues
+            {
+                private readonly ValueSourceAnonymousInnerClassHelper outerInstance;
+
+                private Scorer scorer;
+
+                public DoubleDocValuesAnonymousInnerClassHelper(ValueSourceAnonymousInnerClassHelper outerInstance, Scorer scorer)
+                    : base(null) //todo: value source
+                {
+                    this.outerInstance = outerInstance;
+                    this.scorer = scorer;
+                }
+
+
+
+                public override double DoubleVal(int document)
+                {
+                    try
+                    {
+                        return scorer.Score();
+                    }
+                    catch (IOException exception)
+                    {
+                        throw new Exception(exception.Message, exception);
+                    }
+                }
+            }
+
+            public override bool Equals(object o)
+            {
+                return o == this;
+            }
+            public override int GetHashCode()
+            {
+                throw new NotImplementedException();
+            }
+
+            public override string Description
+            {
+                get
+                {
+                    return "score()";
+                }
+
+            }
+        }
+
+        [Test]
+        public virtual void TestRollupValues()
+        {
+            Store.Directory indexDir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+            FacetsConfig config = new FacetsConfig();
+            config.SetHierarchical("a", true);
+            //config.setRequireDimCount("a", true);
+
+            for (int i = 0; i < 4; i++)
+            {
+                Document doc = new Document();
+                doc.Add(new NumericDocValuesField("price", (i + 1)));
+                doc.Add(new FacetField("a", Convert.ToString(i % 2), "1"));
+                iw.AddDocument(config.Build(taxoWriter, doc));
+            }
+
+            DirectoryReader r = DirectoryReader.Open(iw, true);
+            DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            ValueSource valueSource = new LongFieldSource("price");
+            FacetsCollector sfc = new FacetsCollector();
+            NewSearcher(r).Search(new MatchAllDocsQuery(), sfc);
+            Facets facets = new TaxonomyFacetSumValueSource(taxoReader, config, sfc, valueSource);
+
+            Assert.AreEqual("dim=a path=[] value=10.0 childCount=2\n  1 (6.0)\n  0 (4.0)\n", facets.GetTopChildren(10, "a").ToString());
+
+            IOUtils.Close(taxoWriter, iw, taxoReader, taxoDir, r, indexDir);
+        }
+
+        [Test]
+        public virtual void TestCountAndSumScore()
+        {
+            Store.Directory indexDir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            IndexWriter iw = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+            FacetsConfig config = new FacetsConfig();
+            config.SetIndexFieldName("b", "$b");
+
+            for (int i = AtLeast(30); i > 0; --i)
+            {
+                Document doc = new Document();
+                doc.Add(new StringField("f", "v", Field.Store.NO));
+                doc.Add(new FacetField("a", "1"));
+                doc.Add(new FacetField("b", "1"));
+                iw.AddDocument(config.Build(taxoWriter, doc));
+            }
+
+            DirectoryReader r = DirectoryReader.Open(iw, true);
+            var taxoReader = new DirectoryTaxonomyReader(taxoWriter);
+
+            FacetsCollector fc = new FacetsCollector(true);
+            FacetsCollector.Search(NewSearcher(r), new MatchAllDocsQuery(), 10, fc);
+
+            Facets facets1 = GetTaxonomyFacetCounts(taxoReader, config, fc);
+            Facets facets2 = new TaxonomyFacetSumValueSource(new DocValuesOrdinalsReader("$b"), taxoReader, config, fc, new TaxonomyFacetSumValueSource.ScoreValueSource());
+
+            Assert.AreEqual(r.MaxDoc, (int)facets1.GetTopChildren(10, "a").Value);
+            Assert.AreEqual(r.MaxDoc, (double)facets2.GetTopChildren(10, "b").Value, 1E-10);
+            IOUtils.Close(taxoWriter, iw, taxoReader, taxoDir, r, indexDir);
+        }
+
+        [Test]
+        public virtual void TestRandom()
+        {
+            string[] tokens = GetRandomTokens(10);
+            Store.Directory indexDir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            RandomIndexWriter w = new RandomIndexWriter(Random(), indexDir);
+            var tw = new DirectoryTaxonomyWriter(taxoDir);
+            FacetsConfig config = new FacetsConfig();
+            int numDocs = AtLeast(1000);
+            int numDims = TestUtil.NextInt(Random(), 1, 7);
+            IList<TestDoc> testDocs = GetRandomDocs(tokens, numDocs, numDims);
+            foreach (TestDoc testDoc in testDocs)
+            {
+                Document doc = new Document();
+                doc.Add(NewStringField("content", testDoc.content, Field.Store.NO));
+                testDoc.value = Random().NextFloat();
+                doc.Add(new FloatDocValuesField("value", testDoc.value));
+                for (int j = 0; j < numDims; j++)
+                {
+                    if (testDoc.dims[j] != null)
+                    {
+                        doc.Add(new FacetField("dim" + j, testDoc.dims[j]));
+                    }
+                }
+                w.AddDocument(config.Build(tw, doc));
+            }
+
+            // NRT open
+            IndexSearcher searcher = NewSearcher(w.Reader);
+
+            // NRT open
+            var tr = new DirectoryTaxonomyReader(tw);
+
+            ValueSource values = new FloatFieldSource("value");
+
+            int iters = AtLeast(100);
+            for (int iter = 0; iter < iters; iter++)
+            {
+                string searchToken = tokens[Random().Next(tokens.Length)];
+                if (VERBOSE)
+                {
+                    Console.WriteLine("\nTEST: iter content=" + searchToken);
+                }
+                FacetsCollector fc = new FacetsCollector();
+                FacetsCollector.Search(searcher, new TermQuery(new Term("content", searchToken)), 10, fc);
+                Facets facets = new TaxonomyFacetSumValueSource(tr, config, fc, values);
+
+                // Slow, yet hopefully bug-free, faceting:
+                var expectedValues = new List<Dictionary<string, float?>>();
+                for (int i = 0; i < numDims; i++)
+                {
+                    expectedValues[i] = new Dictionary<string, float?>();
+                }
+
+                foreach (TestDoc doc in testDocs)
+                {
+                    if (doc.content.Equals(searchToken))
+                    {
+                        for (int j = 0; j < numDims; j++)
+                        {
+                            if (doc.dims[j] != null)
+                            {
+                                float? v = expectedValues[j][doc.dims[j]];
+                                if (v == null)
+                                {
+                                    expectedValues[j][doc.dims[j]] = doc.value;
+                                }
+                                else
+                                {
+                                    expectedValues[j][doc.dims[j]] = (float)v + doc.value;
+                                }
+                            }
+                        }
+                    }
+                }
+
+                IList<FacetResult> expected = new List<FacetResult>();
+                for (int i = 0; i < numDims; i++)
+                {
+                    IList<LabelAndValue> labelValues = new List<LabelAndValue>();
+                    float totValue = 0;
+                    foreach (KeyValuePair<string, float?> ent in expectedValues[i])
+                    {
+                        labelValues.Add(new LabelAndValue(ent.Key, ent.Value.Value));
+                        totValue += ent.Value.Value;
+                    }
+                    SortLabelValues(labelValues);
+                    if (totValue > 0)
+                    {
+                        expected.Add(new FacetResult("dim" + i, new string[0], totValue, labelValues.ToArray(), labelValues.Count));
+                    }
+                }
+
+                // Sort by highest value, tie break by value:
+                SortFacetResults(expected);
+
+                IList<FacetResult> actual = facets.GetAllDims(10);
+
+                // Messy: fixup ties
+                SortTies(actual);
+
+                if (VERBOSE)
+                {
+                    Console.WriteLine("expected=\n" + expected.ToString());
+                    Console.WriteLine("actual=\n" + actual.ToString());
+                }
+
+                AssertFloatValuesEquals(expected, actual);
+            }
+
+            IOUtils.Close(w, tw, searcher.IndexReader, tr, indexDir, taxoDir);
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Taxonomy/WriterCache/TestCharBlockArray.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Taxonomy/WriterCache/TestCharBlockArray.cs b/src/Lucene.Net.Tests.Facet/Taxonomy/WriterCache/TestCharBlockArray.cs
new file mode 100644
index 0000000..f4be988
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Taxonomy/WriterCache/TestCharBlockArray.cs
@@ -0,0 +1,110 @@
+using System.Text;
+using Lucene.Net.Support;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet.Taxonomy.WriterCache
+{
+
+
+    using TestUtil = Lucene.Net.Util.TestUtil;
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+    [TestFixture]
+    public class TestCharBlockArray : FacetTestCase
+    {
+
+        /* not finished yet because of missing charset decoder */
+
+        /*
+        public virtual void testArray()
+        {
+            CharBlockArray array = new CharBlockArray();
+            StringBuilder builder = new StringBuilder();
+
+            const int n = 100 * 1000;
+
+            byte[] buffer = new byte[50];
+
+            for (int i = 0; i < n; i++)
+            {
+                Random().NextBytes(buffer);
+                int size = 1 + Random().Next(50);
+                // This test is turning random bytes into a string,
+                // this is asking for trouble.
+
+                CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder().onUnmappableCharacter(CodingErrorAction.REPLACE).onMalformedInput(CodingErrorAction.REPLACE);
+                string s = decoder.Decode(ByteBuffer.Wrap(buffer, 0, size)).ToString();
+                array.append(s);
+                builder.Append(s);
+            }
+
+            for (int i = 0; i < n; i++)
+            {
+                Random().NextBytes(buffer);
+                int size = 1 + Random().Next(50);
+                // This test is turning random bytes into a string,
+                // this is asking for trouble.
+                CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder().onUnmappableCharacter(CodingErrorAction.REPLACE).onMalformedInput(CodingErrorAction.REPLACE);
+                string s = decoder.decode(ByteBuffer.Wrap(buffer, 0, size)).ToString();
+                array.append((CharSequence)s);
+                builder.Append(s);
+            }
+
+            for (int i = 0; i < n; i++)
+            {
+                Random().NextBytes(buffer);
+                int size = 1 + Random().Next(50);
+                // This test is turning random bytes into a string,
+                // this is asking for trouble.
+                CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder().onUnmappableCharacter(CodingErrorAction.REPLACE).onMalformedInput(CodingErrorAction.REPLACE);
+                string s = decoder.decode(ByteBuffer.Wrap(buffer, 0, size)).ToString();
+                for (int j = 0; j < s.Length; j++)
+                {
+                    array.append(s[j]);
+                }
+                builder.Append(s);
+            }
+
+            AssertEqualsInternal("GrowingCharArray<->StringBuilder mismatch.", builder, array);
+
+            File tempDir = CreateTempDir("growingchararray");
+            File f = new File(tempDir, "GrowingCharArrayTest.tmp");
+            BufferedOutputStream @out = new BufferedOutputStream(new FileOutputStream(f));
+            array.flush(@out);
+            @out.flush();
+            @out.Close();
+
+            BufferedInputStream @in = new BufferedInputStream(new FileInputStream(f));
+            array = CharBlockArray.open(@in);
+            AssertEqualsInternal("GrowingCharArray<->StringBuilder mismatch after flush/load.", builder, array);
+            @in.Close();
+            f.delete();
+        }
+
+        private static void AssertEqualsInternal(string msg, StringBuilder expected, CharBlockArray actual)
+        {
+            Assert.AreEqual(expected.Length, actual.Length, msg);
+            for (int i = 0; i < expected.Length; i++)
+            {
+                Assert.AreEqual(expected[i], actual.CharAt(i), msg);
+            }
+        }
+        */
+    }
+
+}
\ No newline at end of file


[10/14] lucenenet git commit: Moving Lucene.Net.Facet tests to their appropriate place

Posted by sy...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyCombined.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyCombined.cs b/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyCombined.cs
new file mode 100644
index 0000000..caf1f09
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyCombined.cs
@@ -0,0 +1,1185 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using Lucene.Net.Support;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet.Taxonomy
+{
+
+
+    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
+    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
+    using Directory = Lucene.Net.Store.Directory;
+    using LockObtainFailedException = Lucene.Net.Store.LockObtainFailedException;
+    using RAMDirectory = Lucene.Net.Store.RAMDirectory;
+    using SuppressCodecs = Lucene.Net.Util.LuceneTestCase.SuppressCodecs;
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+
+    [TestFixture]
+    [SuppressCodecs]
+    public class TestTaxonomyCombined : FacetTestCase
+    {
+
+        /// <summary>
+        ///  The following categories will be added to the taxonomy by
+        ///  fillTaxonomy(), and tested by all tests below:
+        /// </summary>
+        private static readonly string[][] categories = new string[][]
+	  {
+		  new string[] {"Author", "Tom Clancy"},
+		  new string[] {"Author", "Richard Dawkins"},
+		  new string[] {"Author", "Richard Adams"},
+		  new string[] {"Price", "10", "11"},
+		  new string[] {"Price", "10", "12"},
+		  new string[] {"Price", "20", "27"},
+		  new string[] {"Date", "2006", "05"},
+		  new string[] {"Date", "2005"},
+		  new string[] {"Date", "2006"},
+		  new string[] {"Subject", "Nonfiction", "Children", "Animals"},
+		  new string[] {"Author", "Stephen Jay Gould"},
+		  new string[] {"Author", "\u05e0\u05d3\u05d1\u3042\u0628"}
+	  };
+
+        /// <summary>
+        ///  When adding the above categories with TaxonomyWriter.AddCategory(), 
+        ///  the following paths are expected to be returned:
+        ///  (note that currently the full path is not returned, and therefore
+        ///  not tested - rather, just the last component, the ordinal, is returned
+        ///  and tested.
+        /// </summary>
+        private static readonly int[][] ExpectedPaths =
+        {
+            new int[] {1, 2},
+            new int[] {1, 3},
+            new int[] {1, 4},
+            new int[] {5, 6, 7},
+            new int[] {5, 6, 8},
+            new int[] {5, 9, 10},
+            new int[] {11, 12, 13},
+            new int[] {11, 14},
+            new int[] {11, 12},
+            new int[] {15, 16, 17, 18},
+            new int[] {1, 19},
+            new int[] {1, 20}
+        };
+
+        /// <summary>
+        ///  The taxonomy index is expected to then contain the following
+        ///  generated categories, with increasing ordinals (note how parent
+        ///  categories are be added automatically when subcategories are added).
+        /// </summary>
+        private static readonly string[][] ExpectedCategories = new string[][] { new string[] { }, new string[] { "Author" }, new string[] { "Author", "Tom Clancy" }, new string[] { "Author", "Richard Dawkins" }, new string[] { "Author", "Richard Adams" }, new string[] { "Price" }, new string[] { "Price", "10" }, new string[] { "Price", "10", "11" }, new string[] { "Price", "10", "12" }, new string[] { "Price", "20" }, new string[] { "Price", "20", "27" }, new string[] { "Date" }, new string[] { "Date", "2006" }, new string[] { "Date", "2006", "05" }, new string[] { "Date", "2005" }, new string[] { "Subject" }, new string[] { "Subject", "Nonfiction" }, new string[] { "Subject", "Nonfiction", "Children" }, new string[] { "Subject", "Nonfiction", "Children", "Animals" }, new string[] { "Author", "Stephen Jay Gould" }, new string[] { "Author", "\u05e0\u05d3\u05d1\u3042\u0628" } };
+
+        /// <summary>
+        ///  fillTaxonomy adds the categories in the categories[] array, and asserts
+        ///  that the additions return exactly the ordinals (in the past - paths)
+        ///  specified in expectedPaths[].
+        ///  Note that this assumes that fillTaxonomy() is called on an empty taxonomy
+        ///  index. Calling it after something else was already added to the taxonomy
+        ///  index will surely have this method fail.
+        /// </summary>
+
+        public static void FillTaxonomy(TaxonomyWriter tw)
+        {
+            for (int i = 0; i < categories.Length; i++)
+            {
+                int ordinal = tw.AddCategory(new FacetLabel(categories[i]));
+                int expectedOrdinal = ExpectedPaths[i][ExpectedPaths[i].Length - 1];
+                if (ordinal != expectedOrdinal)
+                {
+                    Fail("For category " + Showcat(categories[i]) + " expected ordinal " + expectedOrdinal + ", but got " + ordinal);
+                }
+            }
+        }
+
+        public static string Showcat(string[] path)
+        {
+            if (path == null)
+            {
+                return "<null>";
+            }
+            if (path.Length == 0)
+            {
+                return "<empty>";
+            }
+            if (path.Length == 1 && path[0].Length == 0)
+            {
+                return "<\"\">";
+            }
+            StringBuilder sb = new StringBuilder(path[0]);
+            for (int i = 1; i < path.Length; i++)
+            {
+                sb.Append('/');
+                sb.Append(path[i]);
+            }
+            return sb.ToString();
+        }
+
+        private string Showcat(FacetLabel path)
+        {
+            if (path == null)
+            {
+                return "<null>";
+            }
+            if (path.Length == 0)
+            {
+                return "<empty>";
+            }
+            return "<" + path.ToString() + ">";
+        }
+
+        /// <summary>
+        ///  Basic tests for TaxonomyWriter. Basically, we test that
+        ///  IndexWriter.AddCategory works, i.e. returns the expected ordinals
+        ///  (this is tested by calling the fillTaxonomy() method above).
+        ///  We do not test here that after writing the index can be read -
+        ///  this will be done in more tests below.
+        /// </summary>
+        [Test]
+        public virtual void TestWriter()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            FillTaxonomy(tw);
+            // Also check TaxonomyWriter.getSize() - see that the taxonomy's size
+            // is what we expect it to be.
+            Assert.AreEqual(ExpectedCategories.Length, tw.Size);
+            tw.Dispose();
+            indexDir.Dispose();
+        }
+
+        /// <summary>
+        ///  testWriterTwice is exactly like testWriter, except that after adding
+        ///  all the categories, we add them again, and see that we get the same
+        ///  old ids again - not new categories.
+        /// </summary>
+        [Test]
+        public virtual void TestWriterTwice()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            FillTaxonomy(tw);
+            // run fillTaxonomy again - this will try to add the same categories
+            // again, and check that we see the same ordinal paths again, not
+            // different ones. 
+            FillTaxonomy(tw);
+            // Let's check the number of categories again, to see that no
+            // extraneous categories were created:
+            Assert.AreEqual(ExpectedCategories.Length, tw.Size);
+            tw.Dispose();
+            indexDir.Dispose();
+        }
+
+        /// <summary>
+        ///  testWriterTwice2 is similar to testWriterTwice, except that the index
+        ///  is closed and reopened before attempting to write to it the same
+        ///  categories again. While testWriterTwice can get along with writing
+        ///  and reading correctly just to the cache, testWriterTwice2 checks also
+        ///  the actual disk read part of the writer:
+        /// </summary>
+        [Test]
+        public virtual void TestWriterTwice2()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            FillTaxonomy(tw);
+            tw.Dispose();
+            tw = new DirectoryTaxonomyWriter(indexDir);
+            // run fillTaxonomy again - this will try to add the same categories
+            // again, and check that we see the same ordinals again, not different
+            // ones, and that the number of categories hasn't grown by the new
+            // additions
+            FillTaxonomy(tw);
+            Assert.AreEqual(ExpectedCategories.Length, tw.Size);
+            tw.Dispose();
+            indexDir.Dispose();
+        }
+
+        /// <summary>
+        /// testWriterTwice3 is yet another test which tests creating a taxonomy
+        /// in two separate writing sessions. This test used to fail because of
+        /// a bug involving commit(), explained below, and now should succeed.
+        /// </summary>
+        [Test]
+        public virtual void TestWriterTwice3()
+        {
+            var indexDir = NewDirectory();
+            // First, create and fill the taxonomy
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            FillTaxonomy(tw);
+            tw.Dispose();
+            // Now, open the same taxonomy and add the same categories again.
+            // After a few categories, the LuceneTaxonomyWriter implementation
+            // will stop looking for each category on disk, and rather read them
+            // all into memory and close it's reader. The bug was that it closed
+            // the reader, but forgot that it did (because it didn't set the reader
+            // reference to null).
+            tw = new DirectoryTaxonomyWriter(indexDir);
+            FillTaxonomy(tw);
+            // Add one new category, just to make commit() do something:
+            tw.AddCategory(new FacetLabel("hi"));
+            // Do a commit(). Here was a bug - if tw had a reader open, it should
+            // be reopened after the commit. However, in our case the reader should
+            // not be open (as explained above) but because it was not set to null,
+            // we forgot that, tried to reopen it, and got an AlreadyClosedException.
+            tw.Commit();
+            Assert.AreEqual(ExpectedCategories.Length + 1, tw.Size);
+            tw.Dispose();
+            indexDir.Dispose();
+        }
+
+        /// <summary>
+        ///  Another set of tests for the writer, which don't use an array and
+        ///  try to distill the different cases, and therefore may be more helpful
+        ///  for debugging a problem than testWriter() which is hard to know why
+        ///  or where it failed. 
+        /// </summary>
+        [Test]
+        public virtual void TestWriterSimpler()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            Assert.AreEqual(1, tw.Size); // the root only
+            // Test that adding a new top-level category works
+            Assert.AreEqual(1, tw.AddCategory(new FacetLabel("a")));
+            Assert.AreEqual(2, tw.Size);
+            // Test that adding the same category again is noticed, and the
+            // same ordinal (and not a new one) is returned.
+            Assert.AreEqual(1, tw.AddCategory(new FacetLabel("a")));
+            Assert.AreEqual(2, tw.Size);
+            // Test that adding another top-level category returns a new ordinal,
+            // not the same one
+            Assert.AreEqual(2, tw.AddCategory(new FacetLabel("b")));
+            Assert.AreEqual(3, tw.Size);
+            // Test that adding a category inside one of the above adds just one
+            // new ordinal:
+            Assert.AreEqual(3, tw.AddCategory(new FacetLabel("a", "c")));
+            Assert.AreEqual(4, tw.Size);
+            // Test that adding the same second-level category doesn't do anything:
+            Assert.AreEqual(3, tw.AddCategory(new FacetLabel("a", "c")));
+            Assert.AreEqual(4, tw.Size);
+            // Test that adding a second-level category with two new components
+            // indeed adds two categories
+            Assert.AreEqual(5, tw.AddCategory(new FacetLabel("d", "e")));
+            Assert.AreEqual(6, tw.Size);
+            // Verify that the parents were added above in the order we expected
+            Assert.AreEqual(4, tw.AddCategory(new FacetLabel("d")));
+            // Similar, but inside a category that already exists:
+            Assert.AreEqual(7, tw.AddCategory(new FacetLabel("b", "d", "e")));
+            Assert.AreEqual(8, tw.Size);
+            // And now inside two levels of categories that already exist:
+            Assert.AreEqual(8, tw.AddCategory(new FacetLabel("b", "d", "f")));
+            Assert.AreEqual(9, tw.Size);
+
+            tw.Dispose();
+            indexDir.Dispose();
+        }
+
+        /// <summary>
+        ///  Test writing an empty index, and seeing that a reader finds in it
+        ///  the root category, and only it. We check all the methods on that
+        ///  root category return the expected results.
+        /// </summary>
+        [Test]
+        public virtual void TestRootOnly()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            // right after opening the index, it should already contain the
+            // root, so have size 1:
+            Assert.AreEqual(1, tw.Size);
+            tw.Dispose();
+            var tr = new DirectoryTaxonomyReader(indexDir);
+            Assert.AreEqual(1, tr.Size);
+            Assert.AreEqual(0, tr.GetPath(0).Length);
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.ParallelTaxonomyArrays.Parents()[0]);
+            Assert.AreEqual(0, tr.GetOrdinal(new FacetLabel()));
+            tr.Dispose(true);
+            indexDir.Dispose();
+        }
+
+        /// <summary>
+        ///  The following test is exactly the same as testRootOnly, except we
+        ///  do not close the writer before opening the reader. We want to see
+        ///  that the root is visible to the reader not only after the writer is
+        ///  closed, but immediately after it is created.
+        /// </summary>
+        [Test]
+        public virtual void TestRootOnly2()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            tw.Commit();
+            var tr = new DirectoryTaxonomyReader(indexDir);
+            Assert.AreEqual(1, tr.Size);
+            Assert.AreEqual(0, tr.GetPath(0).Length);
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.ParallelTaxonomyArrays.Parents()[0]);
+            Assert.AreEqual(0, tr.GetOrdinal(new FacetLabel()));
+            tw.Dispose();
+            tr.Dispose(true);
+            indexDir.Dispose();
+        }
+
+        /// <summary>
+        ///  Basic tests for TaxonomyReader's category <=> ordinal transformations
+        ///  (getSize(), getCategory() and getOrdinal()).
+        ///  We test that after writing the index, it can be read and all the
+        ///  categories and ordinals are there just as we expected them to be.
+        /// </summary>
+        [Test]
+        public virtual void TestReaderBasic()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            FillTaxonomy(tw);
+            tw.Dispose();
+            var tr = new DirectoryTaxonomyReader(indexDir);
+
+            // test TaxonomyReader.getSize():
+            Assert.AreEqual(ExpectedCategories.Length, tr.Size);
+
+            // test round trips of ordinal => category => ordinal
+            for (int i = 0; i < tr.Size; i++)
+            {
+                Assert.AreEqual(i, tr.GetOrdinal(tr.GetPath(i)));
+            }
+
+            // test TaxonomyReader.getCategory():
+            for (int i = 1; i < tr.Size; i++)
+            {
+                FacetLabel expectedCategory = new FacetLabel(ExpectedCategories[i]);
+                FacetLabel category = tr.GetPath(i);
+                if (!expectedCategory.Equals(category))
+                {
+                    Fail("For ordinal " + i + " expected category " + Showcat(expectedCategory) + ", but got " + Showcat(category));
+                }
+            }
+            //  (also test invalid ordinals:)
+            Assert.Null(tr.GetPath(-1));
+            Assert.Null(tr.GetPath(tr.Size));
+            Assert.Null(tr.GetPath(TaxonomyReader.INVALID_ORDINAL));
+
+            // test TaxonomyReader.GetOrdinal():
+            for (int i = 1; i < ExpectedCategories.Length; i++)
+            {
+                int expectedOrdinal = i;
+                int ordinal = tr.GetOrdinal(new FacetLabel(ExpectedCategories[i]));
+                if (expectedOrdinal != ordinal)
+                {
+                    Fail("For category " + Showcat(ExpectedCategories[i]) + " expected ordinal " + expectedOrdinal + ", but got " + ordinal);
+                }
+            }
+            // (also test invalid categories:)
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.GetOrdinal(new FacetLabel("non-existant")));
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.GetOrdinal(new FacetLabel("Author", "Jules Verne")));
+
+            tr.Dispose();
+            indexDir.Dispose();
+        }
+
+        /// <summary>
+        ///  Tests for TaxonomyReader's getParent() method.
+        ///  We check it by comparing its results to those we could have gotten by
+        ///  looking at the category string paths (where the parentage is obvious).
+        ///  Note that after testReaderBasic(), we already know we can trust the
+        ///  ordinal <=> category conversions.
+        ///  
+        ///  Note: At the moment, the parent methods in the reader are deprecated,
+        ///  but this does not mean they should not be tested! Until they are
+        ///  removed (*if* they are removed), these tests should remain to see
+        ///  that they still work correctly.
+        /// </summary>
+
+        [Test]
+        public virtual void TestReaderParent()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            FillTaxonomy(tw);
+            tw.Dispose();
+            var tr = new DirectoryTaxonomyReader(indexDir);
+
+            // check that the parent of the root ordinal is the invalid ordinal:
+            int[] parents = tr.ParallelTaxonomyArrays.Parents();
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, parents[0]);
+
+            // check parent of non-root ordinals:
+            for (int ordinal = 1; ordinal < tr.Size; ordinal++)
+            {
+                FacetLabel me = tr.GetPath(ordinal);
+                int parentOrdinal = parents[ordinal];
+                FacetLabel parent = tr.GetPath(parentOrdinal);
+                if (parent == null)
+                {
+                    Fail("Parent of " + ordinal + " is " + parentOrdinal + ", but this is not a valid category.");
+                }
+                // verify that the parent is indeed my parent, according to the strings
+                if (!me.Subpath(me.Length - 1).Equals(parent))
+                {
+                    Fail("Got parent " + parentOrdinal + " for ordinal " + ordinal + " but categories are " + Showcat(parent) + " and " + Showcat(me) + " respectively.");
+                }
+            }
+
+            tr.Dispose();
+            indexDir.Dispose();
+        }
+
+        /// <summary>
+        /// Tests for TaxonomyWriter's getParent() method. We check it by comparing
+        /// its results to those we could have gotten by looking at the category
+        /// string paths using a TaxonomyReader (where the parentage is obvious).
+        /// Note that after testReaderBasic(), we already know we can trust the
+        /// ordinal <=> category conversions from TaxonomyReader.
+        /// 
+        /// The difference between testWriterParent1 and testWriterParent2 is that
+        /// the former closes the taxonomy writer before reopening it, while the
+        /// latter does not.
+        /// 
+        /// This test code is virtually identical to that of testReaderParent().
+        /// </summary>
+        [Test]
+        public virtual void TestWriterParent1()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            FillTaxonomy(tw);
+            tw.Dispose();
+            tw = new DirectoryTaxonomyWriter(indexDir);
+            var tr = new DirectoryTaxonomyReader(indexDir);
+
+            CheckWriterParent(tr, tw);
+
+            tw.Dispose();
+            tr.Dispose();
+            indexDir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestWriterParent2()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            FillTaxonomy(tw);
+            tw.Commit();
+            var tr = new DirectoryTaxonomyReader(indexDir);
+
+            CheckWriterParent(tr, tw);
+
+            tw.Dispose();
+            tr.Dispose();
+            indexDir.Dispose();
+        }
+
+        private void CheckWriterParent(TaxonomyReader tr, TaxonomyWriter tw)
+        {
+            // check that the parent of the root ordinal is the invalid ordinal:
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tw.GetParent(0));
+
+            // check parent of non-root ordinals:
+            for (int ordinal = 1; ordinal < tr.Size; ordinal++)
+            {
+                FacetLabel me = tr.GetPath(ordinal);
+                int parentOrdinal = tw.GetParent(ordinal);
+                FacetLabel parent = tr.GetPath(parentOrdinal);
+                if (parent == null)
+                {
+                    Fail("Parent of " + ordinal + " is " + parentOrdinal + ", but this is not a valid category.");
+                }
+                // verify that the parent is indeed my parent, according to the
+                // strings
+                if (!me.Subpath(me.Length - 1).Equals(parent))
+                {
+                    Fail("Got parent " + parentOrdinal + " for ordinal " + ordinal + " but categories are " + Showcat(parent) + " and " + Showcat(me) + " respectively.");
+                }
+            }
+
+            // check parent of of invalid ordinals:
+            try
+            {
+                tw.GetParent(-1);
+                Fail("getParent for -1 should throw exception");
+            }
+            catch (System.IndexOutOfRangeException)
+            {
+                // ok
+            }
+            try
+            {
+                tw.GetParent(TaxonomyReader.INVALID_ORDINAL);
+                Fail("getParent for INVALID_ORDINAL should throw exception");
+            }
+            catch (System.IndexOutOfRangeException)
+            {
+                // ok
+            }
+            try
+            {
+                int parent = tw.GetParent(tr.Size);
+                Fail("getParent for getSize() should throw exception, but returned " + parent);
+            }
+            catch (System.IndexOutOfRangeException)
+            {
+                // ok
+            }
+        }
+
+        /// <summary>
+        /// Test TaxonomyReader's child browsing method, getChildrenArrays()
+        /// This only tests for correctness of the data on one example - we have
+        /// below further tests on data refresh etc.
+        /// </summary>
+        [Test]
+        public virtual void TestChildrenArrays()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            FillTaxonomy(tw);
+            tw.Dispose();
+            var tr = new DirectoryTaxonomyReader(indexDir);
+            ParallelTaxonomyArrays ca = tr.ParallelTaxonomyArrays;
+            int[] youngestChildArray = ca.Children();
+            Assert.AreEqual(tr.Size, youngestChildArray.Length);
+            int[] olderSiblingArray = ca.Siblings();
+            Assert.AreEqual(tr.Size, olderSiblingArray.Length);
+            for (int i = 0; i < ExpectedCategories.Length; i++)
+            {
+                // find expected children by looking at all expectedCategories
+                // for children
+                List<int?> expectedChildren = new List<int?>();
+                for (int j = ExpectedCategories.Length - 1; j >= 0; j--)
+                {
+                    if (ExpectedCategories[j].Length != ExpectedCategories[i].Length + 1)
+                    {
+                        continue; // not longer by 1, so can't be a child
+                    }
+                    bool ischild = true;
+                    for (int k = 0; k < ExpectedCategories[i].Length; k++)
+                    {
+                        if (!ExpectedCategories[j][k].Equals(ExpectedCategories[i][k]))
+                        {
+                            ischild = false;
+                            break;
+                        }
+                    }
+                    if (ischild)
+                    {
+                        expectedChildren.Add(j);
+                    }
+                }
+                // check that children and expectedChildren are the same, with the
+                // correct reverse (youngest to oldest) order:
+                if (expectedChildren.Count == 0)
+                {
+                    Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, youngestChildArray[i]);
+                }
+                else
+                {
+                    int child = youngestChildArray[i];
+                    Assert.AreEqual((int)expectedChildren[0], child);
+                    for (int j = 1; j < expectedChildren.Count; j++)
+                    {
+                        child = olderSiblingArray[child];
+                        Assert.AreEqual((int)expectedChildren[j], child);
+                        // if child is INVALID_ORDINAL we should stop, but
+                        // AssertEquals would fail in this case anyway.
+                    }
+                    // When we're done comparing, olderSiblingArray should now point
+                    // to INVALID_ORDINAL, saying there are no more children. If it
+                    // doesn't, we found too many children...
+                    Assert.AreEqual(-1, olderSiblingArray[child]);
+                }
+            }
+            tr.Dispose();
+            indexDir.Dispose();
+        }
+
+        /// <summary>
+        /// Similar to testChildrenArrays, except rather than look at
+        /// expected results, we test for several "invariants" that the results
+        /// should uphold, e.g., that a child of a category indeed has this category
+        /// as its parent. This sort of test can more easily be extended to larger
+        /// example taxonomies, because we do not need to build the expected list
+        /// of categories like we did in the above test.
+        /// </summary>
+        [Test]
+        public virtual void TestChildrenArraysInvariants()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            FillTaxonomy(tw);
+            tw.Dispose();
+            var tr = new DirectoryTaxonomyReader(indexDir);
+            ParallelTaxonomyArrays ca = tr.ParallelTaxonomyArrays;
+            int[] children = ca.Children();
+            Assert.AreEqual(tr.Size, children.Length);
+            int[] olderSiblingArray = ca.Siblings();
+            Assert.AreEqual(tr.Size, olderSiblingArray.Length);
+
+            // test that the "youngest child" of every category is indeed a child:
+            int[] parents = tr.ParallelTaxonomyArrays.Parents();
+            for (int i = 0; i < tr.Size; i++)
+            {
+                int youngestChild = children[i];
+                if (youngestChild != TaxonomyReader.INVALID_ORDINAL)
+                {
+                    Assert.AreEqual(i, parents[youngestChild]);
+                }
+            }
+
+            // test that the "older sibling" of every category is indeed older (lower)
+            // (it can also be INVALID_ORDINAL, which is lower than any ordinal)
+            for (int i = 0; i < tr.Size; i++)
+            {
+                Assert.True(olderSiblingArray[i] < i, "olderSiblingArray[" + i + "] should be <" + i);
+            }
+
+            // test that the "older sibling" of every category is indeed a sibling
+            // (they share the same parent)
+            for (int i = 0; i < tr.Size; i++)
+            {
+                int sibling = olderSiblingArray[i];
+                if (sibling == TaxonomyReader.INVALID_ORDINAL)
+                {
+                    continue;
+                }
+                Assert.AreEqual(parents[i], parents[sibling]);
+            }
+
+            // And now for slightly more complex (and less "invariant-like"...)
+            // tests:
+
+            // test that the "youngest child" is indeed the youngest (so we don't
+            // miss the first children in the chain)
+            for (int i = 0; i < tr.Size; i++)
+            {
+                // Find the really youngest child:
+                int j;
+                for (j = tr.Size - 1; j > i; j--)
+                {
+                    if (parents[j] == i)
+                    {
+                        break; // found youngest child
+                    }
+                }
+                if (j == i) // no child found
+                {
+                    j = TaxonomyReader.INVALID_ORDINAL;
+                }
+                Assert.AreEqual(j, children[i]);
+            }
+
+            // test that the "older sibling" is indeed the least oldest one - and
+            // not a too old one or -1 (so we didn't miss some children in the
+            // middle or the end of the chain).
+            for (int i = 0; i < tr.Size; i++)
+            {
+                // Find the youngest older sibling:
+                int j;
+                for (j = i - 1; j >= 0; j--)
+                {
+                    if (parents[j] == parents[i])
+                    {
+                        break; // found youngest older sibling
+                    }
+                }
+                if (j < 0) // no sibling found
+                {
+                    j = TaxonomyReader.INVALID_ORDINAL;
+                }
+                Assert.AreEqual(j, olderSiblingArray[i]);
+            }
+
+            tr.Dispose();
+            indexDir.Dispose();
+        }
+
+        /// <summary>
+        /// Test how getChildrenArrays() deals with the taxonomy's growth:
+        /// </summary>
+        [Test]
+        public virtual void TestChildrenArraysGrowth()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            tw.AddCategory(new FacetLabel("hi", "there"));
+            tw.Commit();
+            var tr = new DirectoryTaxonomyReader(indexDir);
+            ParallelTaxonomyArrays ca = tr.ParallelTaxonomyArrays;
+            Assert.AreEqual(3, tr.Size);
+            Assert.AreEqual(3, ca.Siblings().Length);
+            Assert.AreEqual(3, ca.Children().Length);
+            Assert.True(Arrays.Equals(new int[] { 1, 2, -1 }, ca.Children()));
+            Assert.True(Arrays.Equals(new int[] { -1, -1, -1 }, ca.Siblings()));
+            tw.AddCategory(new FacetLabel("hi", "ho"));
+            tw.AddCategory(new FacetLabel("hello"));
+            tw.Commit();
+            // Before refresh, nothing changed..
+            ParallelTaxonomyArrays newca = tr.ParallelTaxonomyArrays;
+            Assert.AreSame(newca, ca); // we got exactly the same object
+            Assert.AreEqual(3, tr.Size);
+            Assert.AreEqual(3, ca.Siblings().Length);
+            Assert.AreEqual(3, ca.Children().Length);
+            // After the refresh, things change:
+            var newtr = TaxonomyReader.OpenIfChanged(tr);
+            Assert.NotNull(newtr);
+            tr.Dispose();
+            tr = newtr;
+            ca = tr.ParallelTaxonomyArrays;
+            Assert.AreEqual(5, tr.Size);
+            Assert.AreEqual(5, ca.Siblings().Length);
+            Assert.AreEqual(5, ca.Children().Length);
+            Assert.True(Arrays.Equals(new int[] { 4, 3, -1, -1, -1 }, ca.Children()));
+            Assert.True(Arrays.Equals(new int[] { -1, -1, -1, 2, 1 }, ca.Siblings()));
+            tw.Dispose();
+            tr.Dispose();
+            indexDir.Dispose();
+        }
+
+        // Test that getParentArrays is valid when retrieved during refresh
+        [Test]
+        public virtual void TestTaxonomyReaderRefreshRaces()
+        {
+            // compute base child arrays - after first chunk, and after the other
+            var indexDirBase = NewDirectory();
+            var twBase = new DirectoryTaxonomyWriter(indexDirBase);
+            twBase.AddCategory(new FacetLabel("a", "0"));
+            FacetLabel abPath = new FacetLabel("a", "b");
+            twBase.AddCategory(abPath);
+            twBase.Commit();
+            var trBase = new DirectoryTaxonomyReader(indexDirBase);
+
+            ParallelTaxonomyArrays ca1 = trBase.ParallelTaxonomyArrays;
+
+            int abOrd = trBase.GetOrdinal(abPath);
+            int abYoungChildBase1 = ca1.Children()[abOrd];
+
+            int numCategories = AtLeast(800);
+            for (int i = 0; i < numCategories; i++)
+            {
+                twBase.AddCategory(new FacetLabel("a", "b", Convert.ToString(i)));
+            }
+            twBase.Dispose();
+
+            var newTaxoReader = TaxonomyReader.OpenIfChanged(trBase);
+            Assert.NotNull(newTaxoReader);
+            trBase.Dispose();
+            trBase = newTaxoReader;
+
+            ParallelTaxonomyArrays ca2 = trBase.ParallelTaxonomyArrays;
+            int abYoungChildBase2 = ca2.Children()[abOrd];
+
+            int numRetries = AtLeast(50);
+            for (int retry = 0; retry < numRetries; retry++)
+            {
+                AssertConsistentYoungestChild(abPath, abOrd, abYoungChildBase1, abYoungChildBase2, retry, numCategories);
+            }
+
+            trBase.Dispose();
+            indexDirBase.Dispose();
+        }
+
+        
+        private void AssertConsistentYoungestChild(FacetLabel abPath, int abOrd, int abYoungChildBase1, int abYoungChildBase2, int retry, int numCategories)
+        {
+            var indexDir = new SlowRAMDirectory(-1, null); // no slowness for intialization
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            tw.AddCategory(new FacetLabel("a", "0"));
+            tw.AddCategory(abPath);
+            tw.Commit();
+
+            
+            var tr = new DirectoryTaxonomyReader(indexDir);
+            for (int i = 0; i < numCategories; i++)
+            {
+                var cp = new FacetLabel("a", "b", Convert.ToString(i));
+                tw.AddCategory(cp);
+                Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.GetOrdinal(cp), "Ordinal of " + cp + " must be invalid until Taxonomy Reader was refreshed");
+            }
+            tw.Dispose();
+
+            
+            var stop = new AtomicBoolean(false);
+            Exception[] error = new Exception[] { null };
+            int[] retrieval = new int[] { 0 };
+
+            var thread = new ThreadAnonymousInnerClassHelper(this, abPath, abOrd, abYoungChildBase1, abYoungChildBase2, retry, tr, stop, error, retrieval);
+            thread.Start();
+
+            indexDir.SleepMillis = 1; // some delay for refresh
+            var newTaxoReader = TaxonomyReader.OpenIfChanged(tr);
+            if (newTaxoReader != null)
+            {
+                newTaxoReader.Dispose();
+            }
+
+            stop.Set(true);
+            thread.Join();
+            Assert.Null(error[0], "Unexpcted exception at retry " + retry + " retrieval " + retrieval[0] + ": \n" + stackTraceStr(error[0]));
+
+            tr.Dispose();
+        }
+
+        private class ThreadAnonymousInnerClassHelper : ThreadClass
+        {
+            private readonly TestTaxonomyCombined outerInstance;
+
+            private Lucene.Net.Facet.Taxonomy.FacetLabel abPath;
+            private int abOrd;
+            private int abYoungChildBase1;
+            private int abYoungChildBase2;
+            private int retry;
+            private DirectoryTaxonomyReader tr;
+            private AtomicBoolean stop;
+            private Exception[] error;
+            private int[] retrieval;
+
+            public ThreadAnonymousInnerClassHelper(TestTaxonomyCombined outerInstance, Lucene.Net.Facet.Taxonomy.FacetLabel abPath, int abOrd, int abYoungChildBase1, int abYoungChildBase2, int retry, DirectoryTaxonomyReader tr, AtomicBoolean stop, Exception[] error, int[] retrieval)
+                : base("Child Arrays Verifier")
+            {
+                this.outerInstance = outerInstance;
+                this.abPath = abPath;
+                this.abOrd = abOrd;
+                this.abYoungChildBase1 = abYoungChildBase1;
+                this.abYoungChildBase2 = abYoungChildBase2;
+                this.retry = retry;
+                this.tr = tr;
+                this.stop = stop;
+                this.error = error;
+                this.retrieval = retrieval;
+            }
+
+            public override void Run()
+            {
+                Priority = 1 + Priority;
+                try
+                {
+                    while (!stop.Get())
+                    {
+                        int lastOrd = tr.ParallelTaxonomyArrays.Parents().Length - 1;
+                        Assert.NotNull(tr.GetPath(lastOrd), "path of last-ord " + lastOrd + " is not found!");
+                        AssertChildrenArrays(tr.ParallelTaxonomyArrays, retry, retrieval[0]++);
+                        Thread.Sleep(10);// don't starve refresh()'s CPU, which sleeps every 50 bytes for 1 ms
+                    }
+                }
+                catch (Exception e)
+                {
+                    error[0] = e;
+                    stop.Set(true);
+                }
+            }
+
+            private void AssertChildrenArrays(ParallelTaxonomyArrays ca, int retry, int retrieval)
+            {
+                int abYoungChild = ca.Children()[abOrd];
+                Assert.True(abYoungChildBase1 == abYoungChild || abYoungChildBase2 == ca.Children()[abOrd], "Retry " + retry + ": retrieval: " + retrieval + ": wrong youngest child for category " + abPath + " (ord=" + abOrd + ") - must be either " + abYoungChildBase1 + " or " + abYoungChildBase2 + " but was: " + abYoungChild);
+            }
+        }
+
+        /// <summary>
+        /// Grab the stack trace into a string since the exception was thrown in a thread and we want the assert 
+        /// outside the thread to show the stack trace in case of failure.   
+        /// </summary>
+        private string stackTraceStr(Exception error)
+        {
+            if (error == null)
+            {
+                return "";
+            }
+
+            error.printStackTrace();
+            return error.StackTrace;
+        }
+
+        /// <summary>
+        ///  Test that if separate reader and writer objects are opened, new
+        ///  categories written into the writer are available to a reader only
+        ///  after a commit().
+        ///  Note that this test obviously doesn't cover all the different
+        ///  concurrency scenarios, all different methods, and so on. We may
+        ///  want to write more tests of this sort.
+        /// 
+        ///  This test simulates what would happen when there are two separate
+        ///  processes, one doing indexing, and the other searching, and each opens
+        ///  its own object (with obviously no connection between the objects) using
+        ///  the same disk files. Note, though, that this test does not test what
+        ///  happens when the two processes do their actual work at exactly the same
+        ///  time.
+        ///  It also doesn't test multi-threading.
+        /// </summary>
+        [Test]
+        public virtual void TestSeparateReaderAndWriter()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            tw.Commit();
+            var tr = new DirectoryTaxonomyReader(indexDir);
+
+            Assert.AreEqual(1, tr.Size); // the empty taxonomy has size 1 (the root)
+            tw.AddCategory(new FacetLabel("Author"));
+            Assert.AreEqual(1, tr.Size); // still root only...
+            Assert.Null(TaxonomyReader.OpenIfChanged(tr)); // this is not enough, because tw.Commit() hasn't been done yet
+            Assert.AreEqual(1, tr.Size); // still root only...
+            tw.Commit();
+            Assert.AreEqual(1, tr.Size); // still root only...
+            var newTaxoReader = TaxonomyReader.OpenIfChanged(tr);
+            Assert.NotNull(newTaxoReader);
+            tr.Dispose();
+            tr = newTaxoReader;
+
+            int author = 1;
+            try
+            {
+                Assert.AreEqual(TaxonomyReader.ROOT_ORDINAL, tr.ParallelTaxonomyArrays.Parents()[author]);
+                // ok
+            }
+            catch (System.IndexOutOfRangeException)
+            {
+                Fail("After category addition, commit() and refresh(), getParent for " + author + " should NOT throw exception");
+            }
+            Assert.AreEqual(2, tr.Size); // finally, see there are two categories
+
+            // now, add another category, and verify that after commit and refresh
+            // the parent of this category is correct (this requires the reader
+            // to correctly update its prefetched parent vector), and that the
+            // old information also wasn't ruined:
+            tw.AddCategory(new FacetLabel("Author", "Richard Dawkins"));
+            int dawkins = 2;
+            tw.Commit();
+            newTaxoReader = TaxonomyReader.OpenIfChanged(tr);
+            Assert.NotNull(newTaxoReader);
+            tr.Dispose();
+            tr = newTaxoReader;
+            int[] parents = tr.ParallelTaxonomyArrays.Parents();
+            Assert.AreEqual(author, parents[dawkins]);
+            Assert.AreEqual(TaxonomyReader.ROOT_ORDINAL, parents[author]);
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, parents[TaxonomyReader.ROOT_ORDINAL]);
+            Assert.AreEqual(3, tr.Size);
+            tw.Dispose();
+            tr.Dispose();
+            indexDir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestSeparateReaderAndWriter2()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            tw.Commit();
+            var tr = new DirectoryTaxonomyReader(indexDir);
+
+            // Test getOrdinal():
+            FacetLabel author = new FacetLabel("Author");
+
+            Assert.AreEqual(1, tr.Size); // the empty taxonomy has size 1 (the root)
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.GetOrdinal(author));
+            tw.AddCategory(author);
+            // before commit and refresh, no change:
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.GetOrdinal(author));
+            Assert.AreEqual(1, tr.Size); // still root only...
+            Assert.Null(TaxonomyReader.OpenIfChanged(tr)); // this is not enough, because tw.Commit() hasn't been done yet
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.GetOrdinal(author));
+            Assert.AreEqual(1, tr.Size); // still root only...
+            tw.Commit();
+            // still not enough before refresh:
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tr.GetOrdinal(author));
+            Assert.AreEqual(1, tr.Size); // still root only...
+            var newTaxoReader = TaxonomyReader.OpenIfChanged(tr);
+            Assert.NotNull(newTaxoReader);
+            tr.Dispose();
+            tr = newTaxoReader;
+            Assert.AreEqual(1, tr.GetOrdinal(author));
+            Assert.AreEqual(2, tr.Size);
+            tw.Dispose();
+            tr.Dispose();
+            indexDir.Dispose();
+        }
+
+        /// <summary>
+        /// Test what happens if we try to write to a locked taxonomy writer,
+        /// and see that we can unlock it and continue.
+        /// </summary>
+        [Test]
+        public virtual void TestWriterLock()
+        {
+            // native fslock impl gets angry if we use it, so use RAMDirectory explicitly.
+            var indexDir = new RAMDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            tw.AddCategory(new FacetLabel("hi", "there"));
+            tw.Commit();
+            // we deliberately not close the write now, and keep it open and
+            // locked.
+            // Verify that the writer worked:
+            var tr = new DirectoryTaxonomyReader(indexDir);
+            Assert.AreEqual(2, tr.GetOrdinal(new FacetLabel("hi", "there")));
+            // Try to open a second writer, with the first one locking the directory.
+            // We expect to get a LockObtainFailedException.
+            try
+            {
+                Assert.Null(new DirectoryTaxonomyWriter(indexDir));
+                Fail("should have failed to write in locked directory");
+            }
+            catch (LockObtainFailedException)
+            {
+                // this is what we expect to happen.
+            }
+            // Remove the lock, and now the open should succeed, and we can
+            // write to the new writer.
+            DirectoryTaxonomyWriter.Unlock(indexDir);
+            var tw2 = new DirectoryTaxonomyWriter(indexDir);
+            tw2.AddCategory(new FacetLabel("hey"));
+            tw2.Dispose();
+            // See that the writer indeed wrote:
+            var newtr = TaxonomyReader.OpenIfChanged(tr);
+            Assert.NotNull(newtr);
+            tr.Dispose();
+            tr = newtr;
+            Assert.AreEqual(3, tr.GetOrdinal(new FacetLabel("hey")));
+            tr.Dispose();
+            tw.Dispose();
+            indexDir.Dispose();
+        }
+
+        /// <summary>
+        /// fillTaxonomyCheckPaths adds the categories in the categories[] array,
+        /// and asserts that the additions return exactly paths specified in
+        /// expectedPaths[]. This is the same add fillTaxonomy() but also checks
+        /// the correctness of getParent(), not just addCategory().
+        /// Note that this assumes that fillTaxonomyCheckPaths() is called on an empty
+        /// taxonomy index. Calling it after something else was already added to the
+        /// taxonomy index will surely have this method fail.
+        /// </summary>
+        public static void FillTaxonomyCheckPaths(TaxonomyWriter tw)
+        {
+            for (int i = 0; i < categories.Length; i++)
+            {
+                int ordinal = tw.AddCategory(new FacetLabel(categories[i]));
+                int expectedOrdinal = ExpectedPaths[i][ExpectedPaths[i].Length - 1];
+                if (ordinal != expectedOrdinal)
+                {
+                    Fail("For category " + Showcat(categories[i]) + " expected ordinal " + expectedOrdinal + ", but got " + ordinal);
+                }
+                for (int j = ExpectedPaths[i].Length - 2; j >= 0; j--)
+                {
+                    ordinal = tw.GetParent(ordinal);
+                    expectedOrdinal = ExpectedPaths[i][j];
+                    if (ordinal != expectedOrdinal)
+                    {
+                        Fail("For category " + Showcat(categories[i]) + " expected ancestor level " + (ExpectedPaths[i].Length - 1 - j) + " was " + expectedOrdinal + ", but got " + ordinal);
+                    }
+                }
+            }
+        }
+
+        // After fillTaxonomy returned successfully, checkPaths() checks that
+        // the getParent() calls return as expected, from the table
+        public static void CheckPaths(TaxonomyWriter tw)
+        {
+            for (int i = 0; i < categories.Length; i++)
+            {
+                int ordinal = ExpectedPaths[i][ExpectedPaths[i].Length - 1];
+                for (int j = ExpectedPaths[i].Length - 2; j >= 0; j--)
+                {
+                    ordinal = tw.GetParent(ordinal);
+                    int expectedOrdinal = ExpectedPaths[i][j];
+                    if (ordinal != expectedOrdinal)
+                    {
+                        Fail("For category " + Showcat(categories[i]) + " expected ancestor level " + (ExpectedPaths[i].Length - 1 - j) + " was " + expectedOrdinal + ", but got " + ordinal);
+                    }
+                }
+                Assert.AreEqual(TaxonomyReader.ROOT_ORDINAL, tw.GetParent(ExpectedPaths[i][0]));
+            }
+            Assert.AreEqual(TaxonomyReader.INVALID_ORDINAL, tw.GetParent(TaxonomyReader.ROOT_ORDINAL));
+        }
+
+        /// <summary>
+        /// Basic test for TaxonomyWriter.getParent(). This is similar to testWriter
+        /// above, except we also check the parents of the added categories, not just
+        /// the categories themselves.
+        /// </summary>
+        [Test]
+        public virtual void TestWriterCheckPaths()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            FillTaxonomyCheckPaths(tw);
+            // Also check TaxonomyWriter.getSize() - see that the taxonomy's size
+            // is what we expect it to be.
+            Assert.AreEqual(ExpectedCategories.Length, tw.Size);
+            tw.Dispose();
+            indexDir.Dispose();
+        }
+
+        /// <summary>
+        /// testWriterCheckPaths2 is the path-checking variant of testWriterTwice
+        /// and testWriterTwice2. After adding all the categories, we add them again,
+        /// and see that we get the same old ids and paths. We repeat the path checking
+        /// yet again after closing and opening the index for writing again - to see
+        /// that the reading of existing data from disk works as well.
+        /// </summary>
+        [Test]
+        public virtual void TestWriterCheckPaths2()
+        {
+            var indexDir = NewDirectory();
+            var tw = new DirectoryTaxonomyWriter(indexDir);
+            FillTaxonomy(tw);
+            CheckPaths(tw);
+            FillTaxonomy(tw);
+            CheckPaths(tw);
+            tw.Dispose();
+
+            tw = new DirectoryTaxonomyWriter(indexDir);
+            CheckPaths(tw);
+            FillTaxonomy(tw);
+            CheckPaths(tw);
+            tw.Dispose();
+            indexDir.Dispose();
+        }
+
+        [Test]
+        public virtual void TestNrt()
+        {
+            var dir = NewDirectory();
+            var writer = new DirectoryTaxonomyWriter(dir);
+            var reader = new DirectoryTaxonomyReader(writer);
+
+            FacetLabel cp = new FacetLabel("a");
+            writer.AddCategory(cp);
+            var newReader = TaxonomyReader.OpenIfChanged(reader);
+            Assert.NotNull(newReader, "expected a new instance");
+            Assert.AreEqual(2, newReader.Size);
+            Assert.AreNotSame(TaxonomyReader.INVALID_ORDINAL, newReader.GetOrdinal(cp));
+            reader.Dispose();
+            reader = newReader;
+
+            writer.Dispose();
+            reader.Dispose();
+
+            dir.Dispose();
+        }
+
+        //  TODO (Facet): test multiple readers, one writer. Have the multiple readers
+        //  using the same object (simulating threads) or different objects
+        //  (simulating processes).
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyFacetAssociations.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyFacetAssociations.cs b/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyFacetAssociations.cs
new file mode 100644
index 0000000..06057ce
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Taxonomy/TestTaxonomyFacetAssociations.cs
@@ -0,0 +1,278 @@
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet.Taxonomy
+{
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+
+    using Document = Lucene.Net.Documents.Document;
+    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
+    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
+    using IndexReader = Lucene.Net.Index.IndexReader;
+    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
+    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
+    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
+    using Directory = Lucene.Net.Store.Directory;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+
+    /// <summary>
+    /// Test for associations 
+    /// </summary>
+    [TestFixture]
+    public class TestTaxonomyFacetAssociations : FacetTestCase
+    {
+
+        private static Store.Directory dir;
+        private static IndexReader reader;
+        private static Store.Directory taxoDir;
+        private static TaxonomyReader taxoReader;
+
+        private static FacetsConfig config;
+
+
+        [TestFixtureSetUp]
+        public static void BeforeClass()
+        {
+            dir = NewDirectory();
+            taxoDir = NewDirectory();
+            // preparations - index, taxonomy, content
+
+            var taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+
+            // Cannot mix ints & floats in the same indexed field:
+            config = new FacetsConfig();
+            config.SetIndexFieldName("int", "$facets.int");
+            config.SetMultiValued("int", true);
+            config.SetIndexFieldName("float", "$facets.float");
+            config.SetMultiValued("float", true);
+
+            var writer = new RandomIndexWriter(Random(), dir);
+
+            // index documents, 50% have only 'b' and all have 'a'
+            for (int i = 0; i < 110; i++)
+            {
+                Document doc = new Document();
+                // every 11th document is added empty, this used to cause the association
+                // aggregators to go into an infinite loop
+                if (i % 11 != 0)
+                {
+                    doc.Add(new IntAssociationFacetField(2, "int", "a"));
+                    doc.Add(new FloatAssociationFacetField(0.5f, "float", "a"));
+                    if (i % 2 == 0) // 50
+                    {
+                        doc.Add(new IntAssociationFacetField(3, "int", "b"));
+                        doc.Add(new FloatAssociationFacetField(0.2f, "float", "b"));
+                    }
+                }
+                writer.AddDocument(config.Build(taxoWriter, doc));
+            }
+
+            taxoWriter.Dispose();
+            reader = writer.Reader;
+            writer.Dispose();
+            taxoReader = new DirectoryTaxonomyReader(taxoDir);
+        }
+
+        [TestFixtureTearDown]
+        public static void AfterClass()
+        {
+            reader.Dispose();
+            reader = null;
+            dir.Dispose();
+            dir = null;
+            taxoReader.Dispose(true);
+            taxoReader = null;
+            taxoDir.Dispose();
+            taxoDir = null;
+        }
+
+        [Test]
+        public virtual void TestIntSumAssociation()
+        {
+
+            FacetsCollector fc = new FacetsCollector();
+
+            IndexSearcher searcher = NewSearcher(reader);
+            searcher.Search(new MatchAllDocsQuery(), fc);
+
+            Facets facets = new TaxonomyFacetSumIntAssociations("$facets.int", taxoReader, config, fc);
+            Assert.AreEqual("dim=int path=[] value=-1 childCount=2\n  a (200)\n  b (150)\n", facets.GetTopChildren(10, "int").ToString());
+            Assert.AreEqual(200, (int)facets.GetSpecificValue("int", "a"), "Wrong count for category 'a'!");
+            Assert.AreEqual(150, (int)facets.GetSpecificValue("int", "b"), "Wrong count for category 'b'!");
+        }
+
+        [Test]
+        public virtual void TestFloatSumAssociation()
+        {
+            FacetsCollector fc = new FacetsCollector();
+
+            IndexSearcher searcher = NewSearcher(reader);
+            searcher.Search(new MatchAllDocsQuery(), fc);
+
+            Facets facets = new TaxonomyFacetSumFloatAssociations("$facets.float", taxoReader, config, fc);
+            Assert.AreEqual("dim=float path=[] value=-1.0 childCount=2\n  a (50.0)\n  b (9.999995)\n", facets.GetTopChildren(10, "float").ToString());
+            Assert.AreEqual(50f, (float)facets.GetSpecificValue("float", "a"), 0.00001, "Wrong count for category 'a'!");
+            Assert.AreEqual(10f, (float)facets.GetSpecificValue("float", "b"), 0.00001, "Wrong count for category 'b'!");
+        }
+
+        /// <summary>
+        /// Make sure we can test both int and float assocs in one
+        ///  index, as long as we send each to a different field. 
+        /// </summary>
+        [Test]
+        public virtual void TestIntAndFloatAssocation()
+        {
+            FacetsCollector fc = new FacetsCollector();
+
+            IndexSearcher searcher = NewSearcher(reader);
+            searcher.Search(new MatchAllDocsQuery(), fc);
+
+            Facets facets = new TaxonomyFacetSumFloatAssociations("$facets.float", taxoReader, config, fc);
+            Assert.AreEqual(50f, (float)facets.GetSpecificValue("float", "a"), 0.00001, "Wrong count for category 'a'!");
+            Assert.AreEqual(10f, (float)facets.GetSpecificValue("float", "b"), 0.00001, "Wrong count for category 'b'!");
+
+            facets = new TaxonomyFacetSumIntAssociations("$facets.int", taxoReader, config, fc);
+            Assert.AreEqual(200, (int)facets.GetSpecificValue("int", "a"), "Wrong count for category 'a'!");
+            Assert.AreEqual(150, (int)facets.GetSpecificValue("int", "b"), "Wrong count for category 'b'!");
+        }
+
+        
+        [Test]
+        public virtual void TestWrongIndexFieldName()
+        {
+            FacetsCollector fc = new FacetsCollector();
+
+            IndexSearcher searcher = NewSearcher(reader);
+            searcher.Search(new MatchAllDocsQuery(), fc);
+            Facets facets = new TaxonomyFacetSumFloatAssociations(taxoReader, config, fc);
+            try
+            {
+                facets.GetSpecificValue("float");
+                Fail("should have hit exc");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+
+            try
+            {
+                facets.GetTopChildren(10, "float");
+                Fail("should have hit exc");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+        }
+
+        [Test]
+        public virtual void TestMixedTypesInSameIndexField()
+        {
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            FacetsConfig config = new FacetsConfig();
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            Document doc = new Document();
+            doc.Add(new IntAssociationFacetField(14, "a", "x"));
+            doc.Add(new FloatAssociationFacetField(55.0f, "b", "y"));
+            try
+            {
+                writer.AddDocument(config.Build(taxoWriter, doc));
+                Fail("did not hit expected exception");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            IOUtils.Close(writer, taxoWriter, dir, taxoDir);
+        }
+
+        [Test]
+        public virtual void TestNoHierarchy()
+        {
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            FacetsConfig config = new FacetsConfig();
+            config.SetHierarchical("a", true);
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            Document doc = new Document();
+            doc.Add(new IntAssociationFacetField(14, "a", "x"));
+            try
+            {
+                writer.AddDocument(config.Build(taxoWriter, doc));
+                Fail("did not hit expected exception");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            IOUtils.Close(writer, taxoWriter, dir, taxoDir);
+        }
+
+        [Test]
+        public virtual void TestRequireDimCount()
+        {
+            Store.Directory dir = NewDirectory();
+            Store.Directory taxoDir = NewDirectory();
+
+            TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+            FacetsConfig config = new FacetsConfig();
+            config.SetRequireDimCount("a", true);
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            Document doc = new Document();
+            doc.Add(new IntAssociationFacetField(14, "a", "x"));
+            try
+            {
+                writer.AddDocument(config.Build(taxoWriter, doc));
+                Fail("did not hit expected exception");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            IOUtils.Close(writer, taxoWriter, dir, taxoDir);
+        }
+
+        [Test]
+        public virtual void TestIntSumAssociationDrillDown()
+        {
+            FacetsCollector fc = new FacetsCollector();
+
+            IndexSearcher searcher = NewSearcher(reader);
+            DrillDownQuery q = new DrillDownQuery(config);
+            q.Add("int", "b");
+            searcher.Search(q, fc);
+
+            Facets facets = new TaxonomyFacetSumIntAssociations("$facets.int", taxoReader, config, fc);
+            Assert.AreEqual("dim=int path=[] value=-1 childCount=2\n  b (150)\n  a (100)\n", facets.GetTopChildren(10, "int").ToString());
+            Assert.AreEqual(100, (int)facets.GetSpecificValue("int", "a"), "Wrong count for category 'a'!");
+            Assert.AreEqual(150, (int)facets.GetSpecificValue("int", "b"), "Wrong count for category 'b'!");
+        }
+
+    }
+
+}
\ No newline at end of file


[13/14] lucenenet git commit: Moving Lucene.Net.Facet tests to their appropriate place

Posted by sy...@apache.org.
Moving Lucene.Net.Facet tests to their appropriate place


Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/68aa9728
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/68aa9728
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/68aa9728

Branch: refs/heads/master
Commit: 68aa9728012959d79a9118628678820b115d8620
Parents: b47de89
Author: Itamar Syn-Hershko <it...@code972.com>
Authored: Wed Dec 31 21:09:48 2014 +0200
Committer: Itamar Syn-Hershko <it...@code972.com>
Committed: Wed Dec 31 21:09:48 2014 +0200

----------------------------------------------------------------------
 Lucene.Net.sln                                  |   14 +-
 .../AssertingSubDocsAtOnceCollector.cs          |   85 ++
 src/Lucene.Net.Tests.Facet/FacetTestCase.cs     |  293 ++++
 .../Lucene.Net.Tests.Facet.csproj               |  100 ++
 .../Properties/AssemblyInfo.cs                  |   36 +
 .../Range/TestRangeFacetCounts.cs               | 1174 +++++++++++++++
 src/Lucene.Net.Tests.Facet/SlowRAMDirectory.cs  |  261 ++++
 .../SortedSet/TestSortedSetDocValuesFacets.cs   |  394 ++++++
 .../Taxonomy/Directory/TestAddTaxonomy.cs       |  323 +++++
 .../Directory/TestConcurrentFacetedIndexing.cs  |  228 +++
 .../Directory/TestDirectoryTaxonomyReader.cs    |  624 ++++++++
 .../Directory/TestDirectoryTaxonomyWriter.cs    |  588 ++++++++
 .../Taxonomy/TestCachedOrdinalsReader.cs        |  116 ++
 .../Taxonomy/TestFacetLabel.cs                  |  360 +++++
 .../Taxonomy/TestLRUHashMap.cs                  |   65 +
 .../Taxonomy/TestSearcherTaxonomyManager.cs     |  398 ++++++
 .../Taxonomy/TestTaxonomyCombined.cs            | 1185 ++++++++++++++++
 .../Taxonomy/TestTaxonomyFacetAssociations.cs   |  278 ++++
 .../Taxonomy/TestTaxonomyFacetCounts.cs         |  851 +++++++++++
 .../Taxonomy/TestTaxonomyFacetCounts2.cs        |  403 ++++++
 .../Taxonomy/TestTaxonomyFacetSumValueSource.cs |  610 ++++++++
 .../Taxonomy/WriterCache/TestCharBlockArray.cs  |  110 ++
 .../WriterCache/TestCompactLabelToOrdinal.cs    |  151 ++
 .../TestDrillDownQuery.cs                       |  282 ++++
 src/Lucene.Net.Tests.Facet/TestDrillSideways.cs | 1332 ++++++++++++++++++
 src/Lucene.Net.Tests.Facet/TestFacetsConfig.cs  |  131 ++
 .../TestMultipleIndexFields.cs                  |  300 ++++
 .../TestRandomSamplingFacetsCollector.cs        |  154 ++
 src/Lucene.Net.Tests.Facet/app.config           |   11 +
 src/Lucene.Net.Tests.Facet/packages.config      |    5 +
 src/Lucene.Net.Tests/Lucene.Net.Tests.csproj    |   25 -
 .../Facet/AssertingSubDocsAtOnceCollector.cs    |   85 --
 .../core/Facet/FacetTestCase.cs                 |  293 ----
 .../core/Facet/Range/TestRangeFacetCounts.cs    | 1174 ---------------
 .../core/Facet/SlowRAMDirectory.cs              |  261 ----
 .../SortedSet/TestSortedSetDocValuesFacets.cs   |  394 ------
 .../Facet/Taxonomy/Directory/TestAddTaxonomy.cs |  323 -----
 .../Directory/TestConcurrentFacetedIndexing.cs  |  228 ---
 .../Directory/TestDirectoryTaxonomyReader.cs    |  624 --------
 .../Directory/TestDirectoryTaxonomyWriter.cs    |  588 --------
 .../Facet/Taxonomy/TestCachedOrdinalsReader.cs  |  116 --
 .../core/Facet/Taxonomy/TestFacetLabel.cs       |  360 -----
 .../core/Facet/Taxonomy/TestLRUHashMap.cs       |   65 -
 .../Taxonomy/TestSearcherTaxonomyManager.cs     |  398 ------
 .../core/Facet/Taxonomy/TestTaxonomyCombined.cs | 1185 ----------------
 .../Taxonomy/TestTaxonomyFacetAssociations.cs   |  278 ----
 .../Facet/Taxonomy/TestTaxonomyFacetCounts.cs   |  851 -----------
 .../Facet/Taxonomy/TestTaxonomyFacetCounts2.cs  |  403 ------
 .../Taxonomy/TestTaxonomyFacetSumValueSource.cs |  610 --------
 .../Taxonomy/WriterCache/TestCharBlockArray.cs  |  110 --
 .../WriterCache/TestCompactLabelToOrdinal.cs    |  151 --
 .../core/Facet/TestDrillDownQuery.cs            |  282 ----
 .../core/Facet/TestDrillSideways.cs             | 1332 ------------------
 .../core/Facet/TestFacetsConfig.cs              |  131 --
 .../core/Facet/TestMultipleIndexFields.cs       |  300 ----
 .../Facet/TestRandomSamplingFacetsCollector.cs  |  154 --
 56 files changed, 10861 insertions(+), 10722 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/Lucene.Net.sln
----------------------------------------------------------------------
diff --git a/Lucene.Net.sln b/Lucene.Net.sln
index 9fb7415..2577faa 100644
--- a/Lucene.Net.sln
+++ b/Lucene.Net.sln
@@ -1,7 +1,7 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 2013
-VisualStudioVersion = 12.0.30723.0
+VisualStudioVersion = 12.0.30501.0
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene.Net", "src\Lucene.Net.Core\Lucene.Net.csproj", "{5D4AD9BE-1FFB-41AB-9943-25737971BF57}"
 EndProject
@@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene.Net.Queries", "src\L
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene.Net.Facet", "src\Lucene.Net.Facet\Lucene.Net.Facet.csproj", "{48F7884A-9454-4E88-8413-9D35992CB440}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lucene.Net.Tests.Facet", "src\Lucene.Net.Tests.Facet\Lucene.Net.Tests.Facet.csproj", "{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -74,6 +76,16 @@ Global
 		{48F7884A-9454-4E88-8413-9D35992CB440}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
 		{48F7884A-9454-4E88-8413-9D35992CB440}.Release|Mixed Platforms.Build.0 = Release|Any CPU
 		{48F7884A-9454-4E88-8413-9D35992CB440}.Release|x86.ActiveCfg = Release|Any CPU
+		{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}.Release|Any CPU.Build.0 = Release|Any CPU
+		{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}.Release|x86.ActiveCfg = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/AssertingSubDocsAtOnceCollector.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/AssertingSubDocsAtOnceCollector.cs b/src/Lucene.Net.Tests.Facet/AssertingSubDocsAtOnceCollector.cs
new file mode 100644
index 0000000..c3730df
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/AssertingSubDocsAtOnceCollector.cs
@@ -0,0 +1,85 @@
+using System.Collections.Generic;
+using Apache.NMS;
+
+namespace Lucene.Net.Facet
+{
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+
+    using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
+    using Collector = Lucene.Net.Search.Collector;
+    using ChildScorer = Lucene.Net.Search.Scorer.ChildScorer;
+    using Scorer = Lucene.Net.Search.Scorer;
+
+    /// <summary>
+    /// Verifies in collect() that all child subScorers are on
+    ///  the collected doc. 
+    /// </summary>
+    internal class AssertingSubDocsAtOnceCollector : Collector
+    {
+
+        // TODO: allow wrapping another Collector
+
+        internal IList<Scorer> allScorers;
+
+        public override Scorer Scorer
+        {
+            set
+            {
+                // Gathers all scorers, including value and "under":
+                allScorers = new List<Scorer>();
+                allScorers.Add(value);
+                int upto = 0;
+                while (upto < allScorers.Count)
+                {
+                    value = allScorers[upto++];
+                    foreach (ChildScorer sub in value.Children)
+                    {
+                        allScorers.Add(sub.Child);
+                    }
+                }
+            }
+        }
+
+        public override void Collect(int docID)
+        {
+            foreach (Scorer s in allScorers)
+            {
+                if (docID != s.DocID())
+                {
+                    throw new IllegalStateException("subScorer=" + s + " has docID=" + s.DocID() + " != collected docID=" + docID);
+                }
+            }
+        }
+
+        public override AtomicReaderContext NextReader
+        {
+            set
+            {
+            }
+        }
+
+        public override bool AcceptsDocsOutOfOrder()
+        {
+            return false;
+        }
+
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/FacetTestCase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/FacetTestCase.cs b/src/Lucene.Net.Tests.Facet/FacetTestCase.cs
new file mode 100644
index 0000000..6c2e508
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/FacetTestCase.cs
@@ -0,0 +1,293 @@
+using System;
+using System.Diagnostics;
+using System.Collections.Generic;
+using System.Linq;
+using Lucene.Net.Facet;
+using Lucene.Net.Randomized.Generators;
+using Lucene.Net.Support;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet
+{
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+
+    using CachedOrdinalsReader = Lucene.Net.Facet.Taxonomy.CachedOrdinalsReader;
+    using DocValuesOrdinalsReader = Lucene.Net.Facet.Taxonomy.DocValuesOrdinalsReader;
+    using FastTaxonomyFacetCounts = Lucene.Net.Facet.Taxonomy.FastTaxonomyFacetCounts;
+    using OrdinalsReader = Lucene.Net.Facet.Taxonomy.OrdinalsReader;
+    using TaxonomyFacetCounts = Lucene.Net.Facet.Taxonomy.TaxonomyFacetCounts;
+    using TaxonomyReader = Lucene.Net.Facet.Taxonomy.TaxonomyReader;
+    using BytesRef = Lucene.Net.Util.BytesRef;
+    using SuppressCodecs = Lucene.Net.Util.LuceneTestCase.SuppressCodecs;
+    using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
+    using TestUtil = Lucene.Net.Util.TestUtil;
+
+    [TestFixture]
+    public abstract class FacetTestCase : LuceneTestCase
+    {
+        public virtual Facets GetTaxonomyFacetCounts(TaxonomyReader taxoReader, FacetsConfig config, FacetsCollector c)
+        {
+            return GetTaxonomyFacetCounts(taxoReader, config, c, FacetsConfig.DEFAULT_INDEX_FIELD_NAME);
+        }
+        public virtual Facets GetTaxonomyFacetCounts(TaxonomyReader taxoReader, FacetsConfig config, FacetsCollector c, string indexFieldName)
+        {
+            Facets facets;
+            if (Random().NextBoolean())
+            {
+                facets = new FastTaxonomyFacetCounts(indexFieldName, taxoReader, config, c);
+            }
+            else
+            {
+                OrdinalsReader ordsReader = new DocValuesOrdinalsReader(indexFieldName);
+                if (Random().NextBoolean())
+                {
+                    ordsReader = new CachedOrdinalsReader(ordsReader);
+                }
+                facets = new TaxonomyFacetCounts(ordsReader, taxoReader, config, c);
+            }
+
+            return facets;
+        }
+
+        protected internal virtual string[] GetRandomTokens(int count)
+        {
+            string[] tokens = new string[count];
+            for (int i = 0; i < tokens.Length; i++)
+            {
+                tokens[i] = TestUtil.RandomRealisticUnicodeString(Random(), 1, 10);
+                //tokens[i] = TestUtil.RandomSimpleString(Random(), 1, 10);
+            }
+            return tokens;
+        }
+
+        protected internal virtual string PickToken(string[] tokens)
+        {
+            for (int i = 0; i < tokens.Length; i++)
+            {
+                if (Random().NextBoolean())
+                {
+                    return tokens[i];
+                }
+            }
+
+            // Move long tail onto first token:
+            return tokens[0];
+        }
+
+        protected internal class TestDoc
+        {
+            public string content;
+            public string[] dims;
+            public float value;
+        }
+
+        protected internal virtual IList<TestDoc> GetRandomDocs(string[] tokens, int count, int numDims)
+        {
+            IList<TestDoc> docs = new List<TestDoc>();
+            for (int i = 0; i < count; i++)
+            {
+                TestDoc doc = new TestDoc();
+                docs.Add(doc);
+                doc.content = PickToken(tokens);
+                doc.dims = new string[numDims];
+                for (int j = 0; j < numDims; j++)
+                {
+                    doc.dims[j] = PickToken(tokens);
+                    if (Random().Next(10) < 3)
+                    {
+                        break;
+                    }
+                }
+                if (VERBOSE)
+                {
+                    Console.WriteLine("  doc " + i + ": content=" + doc.content);
+                    for (int j = 0; j < numDims; j++)
+                    {
+                        if (doc.dims[j] != null)
+                        {
+                            Console.WriteLine("    dim[" + j + "]=" + doc.dims[j]);
+                        }
+                    }
+                }
+            }
+
+            return docs;
+        }
+
+        protected internal virtual void SortTies(IList<FacetResult> results)
+        {
+            foreach (FacetResult result in results)
+            {
+                SortTies(result.LabelValues);
+            }
+        }
+
+        protected internal virtual void SortTies(LabelAndValue[] labelValues)
+        {
+            double lastValue = -1;
+            int numInRow = 0;
+            int i = 0;
+            while (i <= labelValues.Length)
+            {
+                if (i < labelValues.Length && (double)labelValues[i].value == lastValue)
+                {
+                    numInRow++;
+                }
+                else
+                {
+                    if (numInRow > 1)
+                    {
+                        Array.Sort(labelValues, i - numInRow, i, new ComparatorAnonymousInnerClassHelper(this));
+                    }
+                    numInRow = 1;
+                    if (i < labelValues.Length)
+                    {
+                        lastValue = (double)labelValues[i].value;
+                    }
+                }
+                i++;
+            }
+        }
+
+        private class ComparatorAnonymousInnerClassHelper : IComparer<LabelAndValue>
+        {
+            private readonly FacetTestCase outerInstance;
+
+            public ComparatorAnonymousInnerClassHelper(FacetTestCase outerInstance)
+            {
+                this.outerInstance = outerInstance;
+            }
+
+            public virtual int Compare(LabelAndValue a, LabelAndValue b)
+            {
+                Debug.Assert((double)a.value == (double)b.value);
+                return (new BytesRef(a.label)).CompareTo(new BytesRef(b.label));
+            }
+        }
+
+        protected internal virtual void SortLabelValues(IList<LabelAndValue> labelValues)
+        {
+            var resArray = labelValues.ToArray();
+            Array.Sort(resArray,new ComparatorAnonymousInnerClassHelper2(this));
+            labelValues = resArray.ToList();
+        }
+
+        private class ComparatorAnonymousInnerClassHelper2 : IComparer<LabelAndValue>
+        {
+            private readonly FacetTestCase outerInstance;
+
+            public ComparatorAnonymousInnerClassHelper2(FacetTestCase outerInstance)
+            {
+                this.outerInstance = outerInstance;
+            }
+
+            public virtual int Compare(LabelAndValue a, LabelAndValue b)
+            {
+                if ((double)a.value > (double)b.value)
+                {
+                    return -1;
+                }
+                else if ((double)a.value < (double)b.value)
+                {
+                    return 1;
+                }
+                else
+                {
+                    return (new BytesRef(a.label)).CompareTo(new BytesRef(b.label));
+                }
+            }
+        }
+
+        protected internal virtual void SortFacetResults(IList<FacetResult> results)
+        {
+            var resArray = results.ToArray();
+            Array.Sort(resArray, new ComparatorAnonymousInnerClassHelper3(this));
+            results = resArray.ToList();
+        }
+
+        private class ComparatorAnonymousInnerClassHelper3 : IComparer<FacetResult>
+        {
+            private readonly FacetTestCase outerInstance;
+
+            public ComparatorAnonymousInnerClassHelper3(FacetTestCase outerInstance)
+            {
+                this.outerInstance = outerInstance;
+            }
+
+            public virtual int Compare(FacetResult a, FacetResult b)
+            {
+                if ((double)a.Value > (double)b.Value)
+                {
+                    return -1;
+                }
+                else if ((double)b.Value > (double)a.Value)
+                {
+                    return 1;
+                }
+                else
+                {
+                    return 0;
+                }
+            }
+        }
+
+        [Test]
+        protected internal virtual void AssertFloatValuesEquals(IList<FacetResult> a, IList<FacetResult> b)
+        {
+            Assert.AreEqual(a.Count, b.Count);
+            float lastValue = float.PositiveInfinity;
+            IDictionary<string, FacetResult> aByDim = new Dictionary<string, FacetResult>();
+            for (int i = 0; i < a.Count; i++)
+            {
+                Assert.True((float)a[i].Value <= lastValue);
+                lastValue = (float)a[i].Value;
+                aByDim[a[i].Dim] = a[i];
+            }
+            lastValue = float.PositiveInfinity;
+            IDictionary<string, FacetResult> bByDim = new Dictionary<string, FacetResult>();
+            for (int i = 0; i < b.Count; i++)
+            {
+                bByDim[b[i].Dim] = b[i];
+                Assert.True((float)b[i].Value <= lastValue);
+                lastValue = (float)b[i].Value;
+            }
+            foreach (string dim in aByDim.Keys)
+            {
+                AssertFloatValuesEquals(aByDim[dim], bByDim[dim]);
+            }
+        }
+
+        [Test]
+        protected internal virtual void AssertFloatValuesEquals(FacetResult a, FacetResult b)
+        {
+            Assert.AreEqual(a.Dim, b.Dim);
+            Assert.True(Arrays.Equals(a.Path, b.Path));
+            Assert.AreEqual(a.ChildCount, b.ChildCount);
+            Assert.AreEqual((float)a.Value, (float)b.Value, (float)a.Value / 1e5);
+            Assert.AreEqual(a.LabelValues.Length, b.LabelValues.Length);
+            for (int i = 0; i < a.LabelValues.Length; i++)
+            {
+                Assert.AreEqual(a.LabelValues[i].label, b.LabelValues[i].label);
+                Assert.AreEqual((float)a.LabelValues[i].value, (float)b.LabelValues[i].value, (float)a.LabelValues[i].value / 1e5);
+            }
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Lucene.Net.Tests.Facet.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Lucene.Net.Tests.Facet.csproj b/src/Lucene.Net.Tests.Facet/Lucene.Net.Tests.Facet.csproj
new file mode 100644
index 0000000..df0589f
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Lucene.Net.Tests.Facet.csproj
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{4D77E491-F50F-4A0C-9BD9-F9AB655720AD}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Lucene.Net.Tests.Classification</RootNamespace>
+    <AssemblyName>Lucene.Net.Tests.Classification</AssemblyName>
+    <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Apache.NMS">
+      <HintPath>..\..\packages\Apache.NMS.1.6.0.3083\lib\net40\Apache.NMS.dll</HintPath>
+    </Reference>
+    <Reference Include="Lucene.Net.TestFramework">
+      <HintPath>..\Lucene.Net.Tests\bin\Debug\Lucene.Net.TestFramework.dll</HintPath>
+    </Reference>
+    <Reference Include="nunit.framework">
+      <HintPath>..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="Microsoft.CSharp" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AssertingSubDocsAtOnceCollector.cs" />
+    <Compile Include="FacetTestCase.cs" />
+    <Compile Include="Range\TestRangeFacetCounts.cs" />
+    <Compile Include="SlowRAMDirectory.cs" />
+    <Compile Include="SortedSet\TestSortedSetDocValuesFacets.cs" />
+    <Compile Include="Taxonomy\Directory\TestAddTaxonomy.cs" />
+    <Compile Include="Taxonomy\Directory\TestConcurrentFacetedIndexing.cs" />
+    <Compile Include="Taxonomy\Directory\TestDirectoryTaxonomyReader.cs" />
+    <Compile Include="Taxonomy\Directory\TestDirectoryTaxonomyWriter.cs" />
+    <Compile Include="Taxonomy\TestCachedOrdinalsReader.cs" />
+    <Compile Include="Taxonomy\TestFacetLabel.cs" />
+    <Compile Include="Taxonomy\TestLRUHashMap.cs" />
+    <Compile Include="Taxonomy\TestSearcherTaxonomyManager.cs" />
+    <Compile Include="Taxonomy\TestTaxonomyCombined.cs" />
+    <Compile Include="Taxonomy\TestTaxonomyFacetAssociations.cs" />
+    <Compile Include="Taxonomy\TestTaxonomyFacetCounts.cs" />
+    <Compile Include="Taxonomy\TestTaxonomyFacetCounts2.cs" />
+    <Compile Include="Taxonomy\TestTaxonomyFacetSumValueSource.cs" />
+    <Compile Include="Taxonomy\WriterCache\TestCharBlockArray.cs" />
+    <Compile Include="Taxonomy\WriterCache\TestCompactLabelToOrdinal.cs" />
+    <Compile Include="TestDrillDownQuery.cs" />
+    <Compile Include="TestDrillSideways.cs" />
+    <Compile Include="TestFacetsConfig.cs" />
+    <Compile Include="TestMultipleIndexFields.cs" />
+    <Compile Include="TestRandomSamplingFacetsCollector.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Lucene.Net.Core\Lucene.Net.csproj">
+      <Project>{5D4AD9BE-1FFB-41AB-9943-25737971BF57}</Project>
+      <Name>Lucene.Net</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Lucene.Net.Facet\Lucene.Net.Facet.csproj">
+      <Project>{48f7884a-9454-4e88-8413-9d35992cb440}</Project>
+      <Name>Lucene.Net.Facet</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Lucene.Net.Queries\Lucene.Net.Queries.csproj">
+      <Project>{69d7956c-c2cc-4708-b399-a188fec384c4}</Project>
+      <Name>Lucene.Net.Queries</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="app.config" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Properties/AssemblyInfo.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Properties/AssemblyInfo.cs b/src/Lucene.Net.Tests.Facet/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e1a47e2
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Lucene.Net.Tests.Classification")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Lucene.Net.Tests.Classification")]
+[assembly: AssemblyCopyright("Copyright ©  2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("253246a8-7b09-4251-ab4c-7971d3b2be4a")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/Range/TestRangeFacetCounts.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/Range/TestRangeFacetCounts.cs b/src/Lucene.Net.Tests.Facet/Range/TestRangeFacetCounts.cs
new file mode 100644
index 0000000..bb09c43
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/Range/TestRangeFacetCounts.cs
@@ -0,0 +1,1174 @@
+using System;
+using System.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using Lucene.Net.Facet.Range;
+using Lucene.Net.Randomized.Generators;
+using Lucene.Net.Support;
+using NUnit.Framework;
+
+namespace Lucene.Net.Facet.Range
+{
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+
+    using Document = Lucene.Net.Documents.Document;
+    using DoubleDocValuesField = Lucene.Net.Documents.DoubleDocValuesField;
+    using DoubleField = Lucene.Net.Documents.DoubleField;
+    using Field = Lucene.Net.Documents.Field;
+    using FloatDocValuesField = Lucene.Net.Documents.FloatDocValuesField;
+    using FloatField = Lucene.Net.Documents.FloatField;
+    using LongField = Lucene.Net.Documents.LongField;
+    using NumericDocValuesField = Lucene.Net.Documents.NumericDocValuesField;
+    using DrillSidewaysResult = Lucene.Net.Facet.DrillSideways.DrillSidewaysResult;
+    using TaxonomyReader = Lucene.Net.Facet.Taxonomy.TaxonomyReader;
+    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
+    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
+    using AtomicReader = Lucene.Net.Index.AtomicReader;
+    using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
+    using IndexReader = Lucene.Net.Index.IndexReader;
+    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
+    using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
+    using FunctionValues = Lucene.Net.Queries.Function.FunctionValues;
+    using ValueSource = Lucene.Net.Queries.Function.ValueSource;
+    using DoubleDocValues = Lucene.Net.Queries.Function.DocValues.DoubleDocValues;
+    using DoubleFieldSource = Lucene.Net.Queries.Function.ValueSources.DoubleFieldSource;
+    using FloatFieldSource = Lucene.Net.Queries.Function.ValueSources.FloatFieldSource;
+    using LongFieldSource = Lucene.Net.Queries.Function.ValueSources.LongFieldSource;
+    using CachingWrapperFilter = Lucene.Net.Search.CachingWrapperFilter;
+    using DocIdSet = Lucene.Net.Search.DocIdSet;
+    using DocIdSetIterator = Lucene.Net.Search.DocIdSetIterator;
+    using Filter = Lucene.Net.Search.Filter;
+    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
+    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
+    using Lucene.Net.Search;
+    using QueryWrapperFilter = Lucene.Net.Search.QueryWrapperFilter;
+    using Directory = Lucene.Net.Store.Directory;
+    using FixedBitSet = Lucene.Net.Util.FixedBitSet;
+    using IOUtils = Lucene.Net.Util.IOUtils;
+    using TestUtil = Lucene.Net.Util.TestUtil;
+
+    [TestFixture]
+    public class TestRangeFacetCounts : FacetTestCase
+    {
+
+        [Test]
+        public virtual void TestBasicLong()
+        {
+            Directory d = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(Random(), d);
+            Document doc = new Document();
+            NumericDocValuesField field = new NumericDocValuesField("field", 0L);
+            doc.Add(field);
+            for (long l = 0; l < 100; l++)
+            {
+                field.LongValue = l;
+                w.AddDocument(doc);
+            }
+
+            // Also add Long.MAX_VALUE
+            field.LongValue = long.MaxValue;
+            w.AddDocument(doc);
+
+            IndexReader r = w.Reader;
+            w.Dispose();
+
+            FacetsCollector fc = new FacetsCollector();
+            IndexSearcher s = NewSearcher(r);
+            s.Search(new MatchAllDocsQuery(), fc);
+
+            Facets facets = new LongRangeFacetCounts("field", fc, new LongRange("less than 10", 0L, true, 10L, false), new LongRange("less than or equal to 10", 0L, true, 10L, true), new LongRange("over 90", 90L, false, 100L, false), new LongRange("90 or above", 90L, true, 100L, false), new LongRange("over 1000", 1000L, false, long.MaxValue, true));
+
+            FacetResult result = facets.GetTopChildren(10, "field");
+
+            Assert.AreEqual("dim=field path=[] value=22 childCount=5\n  less than 10 (10)\n  less than or equal to 10 (11)\n  over 90 (9)\n  90 or above (10)\n  over 1000 (1)\n", result.ToString());
+
+            r.Dispose();
+            d.Dispose();
+        }
+
+        [Test]
+        public virtual void TestUselessRange()
+        {
+            try
+            {
+                new LongRange("useless", 7, true, 6, true);
+                Fail("did not hit expected exception");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            try
+            {
+                new LongRange("useless", 7, true, 7, false);
+                Fail("did not hit expected exception");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            try
+            {
+                new DoubleRange("useless", 7.0, true, 6.0, true);
+                Fail("did not hit expected exception");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+            try
+            {
+                new DoubleRange("useless", 7.0, true, 7.0, false);
+                Fail("did not hit expected exception");
+            }
+            catch (System.ArgumentException)
+            {
+                // expected
+            }
+        }
+
+        [Test]
+        public virtual void TestLongMinMax()
+        {
+
+            Directory d = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(Random(), d);
+            Document doc = new Document();
+            NumericDocValuesField field = new NumericDocValuesField("field", 0L);
+            doc.Add(field);
+            field.LongValue = long.MinValue;
+            w.AddDocument(doc);
+            field.LongValue = 0;
+            w.AddDocument(doc);
+            field.LongValue = long.MaxValue;
+            w.AddDocument(doc);
+
+            IndexReader r = w.Reader;
+            w.Dispose();
+
+            FacetsCollector fc = new FacetsCollector();
+            IndexSearcher s = NewSearcher(r);
+            s.Search(new MatchAllDocsQuery(), fc);
+
+            Facets facets = new LongRangeFacetCounts("field", fc, new LongRange("min", long.MinValue, true, long.MinValue, true), new LongRange("max", long.MaxValue, true, long.MaxValue, true), new LongRange("all0", long.MinValue, true, long.MaxValue, true), new LongRange("all1", long.MinValue, false, long.MaxValue, true), new LongRange("all2", long.MinValue, true, long.MaxValue, false), new LongRange("all3", long.MinValue, false, long.MaxValue, false));
+
+            FacetResult result = facets.GetTopChildren(10, "field");
+            Assert.AreEqual("dim=field path=[] value=3 childCount=6\n  min (1)\n  max (1)\n  all0 (3)\n  all1 (2)\n  all2 (2)\n  all3 (1)\n", result.ToString());
+
+            r.Dispose();
+            d.Dispose();
+        }
+
+        [Test]
+        public virtual void TestOverlappedEndStart()
+        {
+            Directory d = NewDirectory();
+            var w = new RandomIndexWriter(Random(), d);
+            Document doc = new Document();
+            NumericDocValuesField field = new NumericDocValuesField("field", 0L);
+            doc.Add(field);
+            for (long l = 0; l < 100; l++)
+            {
+                field.LongValue = l;
+                w.AddDocument(doc);
+            }
+            field.LongValue = long.MaxValue;
+            w.AddDocument(doc);
+
+            IndexReader r = w.Reader;
+            w.Dispose();
+
+            FacetsCollector fc = new FacetsCollector();
+            IndexSearcher s = NewSearcher(r);
+            s.Search(new MatchAllDocsQuery(), fc);
+
+            Facets facets = new LongRangeFacetCounts("field", fc, new LongRange("0-10", 0L, true, 10L, true), new LongRange("10-20", 10L, true, 20L, true), new LongRange("20-30", 20L, true, 30L, true), new LongRange("30-40", 30L, true, 40L, true));
+
+            FacetResult result = facets.GetTopChildren(10, "field");
+            Assert.AreEqual("dim=field path=[] value=41 childCount=4\n  0-10 (11)\n  10-20 (11)\n  20-30 (11)\n  30-40 (11)\n", result.ToString());
+
+            r.Dispose();
+            d.Dispose();
+        }
+
+        /// <summary>
+        /// Tests single request that mixes Range and non-Range
+        ///  faceting, with DrillSideways and taxonomy. 
+        /// </summary>
+        [Test]
+        public virtual void TestMixedRangeAndNonRangeTaxonomy()
+        {
+            Directory d = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(Random(), d);
+            Directory td = NewDirectory();
+            DirectoryTaxonomyWriter tw = new DirectoryTaxonomyWriter(td, IndexWriterConfig.OpenMode_e.CREATE);
+
+            FacetsConfig config = new FacetsConfig();
+
+            for (long l = 0; l < 100; l++)
+            {
+                Document doc = new Document();
+                // For computing range facet counts:
+                doc.Add(new NumericDocValuesField("field", l));
+                // For drill down by numeric range:
+                doc.Add(new LongField("field", l, Field.Store.NO));
+
+                if ((l & 3) == 0)
+                {
+                    doc.Add(new FacetField("dim", "a"));
+                }
+                else
+                {
+                    doc.Add(new FacetField("dim", "b"));
+                }
+                w.AddDocument(config.Build(tw, doc));
+            }
+
+            IndexReader r = w.Reader;
+
+            var tr = new DirectoryTaxonomyReader(tw);
+
+            IndexSearcher s = NewSearcher(r);
+
+            if (VERBOSE)
+            {
+                Console.WriteLine("TEST: searcher=" + s);
+            }
+
+            DrillSideways ds = new DrillSidewaysAnonymousInnerClassHelper(this, s, config, tr);
+
+            // First search, no drill downs:
+            DrillDownQuery ddq = new DrillDownQuery(config);
+            DrillSidewaysResult dsr = ds.Search(null, ddq, 10);
+
+            Assert.AreEqual(100, dsr.Hits.TotalHits);
+            Assert.AreEqual("dim=dim path=[] value=100 childCount=2\n  b (75)\n  a (25)\n", dsr.Facets.GetTopChildren(10, "dim").ToString());
+            Assert.AreEqual("dim=field path=[] value=21 childCount=5\n  less than 10 (10)\n  less than or equal to 10 (11)\n  over 90 (9)\n  90 or above (10)\n  over 1000 (0)\n", dsr.Facets.GetTopChildren(10, "field").ToString());
+
+            // Second search, drill down on dim=b:
+            ddq = new DrillDownQuery(config);
+            ddq.Add("dim", "b");
+            dsr = ds.Search(null, ddq, 10);
+
+            Assert.AreEqual(75, dsr.Hits.TotalHits);
+            Assert.AreEqual("dim=dim path=[] value=100 childCount=2\n  b (75)\n  a (25)\n", dsr.Facets.GetTopChildren(10, "dim").ToString());
+            Assert.AreEqual("dim=field path=[] value=16 childCount=5\n  less than 10 (7)\n  less than or equal to 10 (8)\n  over 90 (7)\n  90 or above (8)\n  over 1000 (0)\n", dsr.Facets.GetTopChildren(10, "field").ToString());
+
+            // Third search, drill down on "less than or equal to 10":
+            ddq = new DrillDownQuery(config);
+            ddq.Add("field", NumericRangeQuery.NewLongRange("field", 0L, 10L, true, true));
+            dsr = ds.Search(null, ddq, 10);
+
+            Assert.AreEqual(11, dsr.Hits.TotalHits);
+            Assert.AreEqual("dim=dim path=[] value=11 childCount=2\n  b (8)\n  a (3)\n", dsr.Facets.GetTopChildren(10, "dim").ToString());
+            Assert.AreEqual("dim=field path=[] value=21 childCount=5\n  less than 10 (10)\n  less than or equal to 10 (11)\n  over 90 (9)\n  90 or above (10)\n  over 1000 (0)\n", dsr.Facets.GetTopChildren(10, "field").ToString());
+            IOUtils.Close(tw, tr, td, w, r, d);
+        }
+
+        private class DrillSidewaysAnonymousInnerClassHelper : DrillSideways
+        {
+            private readonly TestRangeFacetCounts outerInstance;
+
+            private new FacetsConfig config;
+
+            public DrillSidewaysAnonymousInnerClassHelper(TestRangeFacetCounts outerInstance, IndexSearcher s, FacetsConfig config, TaxonomyReader tr)
+                : base(s, config, tr)
+            {
+                this.outerInstance = outerInstance;
+                this.config = config;
+            }
+
+            protected override Facets BuildFacetsResult(FacetsCollector drillDowns, FacetsCollector[] drillSideways, string[] drillSidewaysDims)
+            {
+                FacetsCollector dimFC = drillDowns;
+                FacetsCollector fieldFC = drillDowns;
+                if (drillSideways != null)
+                {
+                    for (int i = 0; i < drillSideways.Length; i++)
+                    {
+                        string dim = drillSidewaysDims[i];
+                        if (dim.Equals("field"))
+                        {
+                            fieldFC = drillSideways[i];
+                        }
+                        else
+                        {
+                            dimFC = drillSideways[i];
+                        }
+                    }
+                }
+
+                IDictionary<string, Facets> byDim = new Dictionary<string, Facets>();
+                byDim["field"] = new LongRangeFacetCounts("field", fieldFC, new LongRange("less than 10", 0L, true, 10L, false), new LongRange("less than or equal to 10", 0L, true, 10L, true), new LongRange("over 90", 90L, false, 100L, false), new LongRange("90 or above", 90L, true, 100L, false), new LongRange("over 1000", 1000L, false, long.MaxValue, false));
+                byDim["dim"] = outerInstance.GetTaxonomyFacetCounts(taxoReader, config, dimFC);
+                return new MultiFacets(byDim, null);
+            }
+
+            protected override bool ScoreSubDocsAtOnce()
+            {
+                return Random().NextBoolean();
+            }
+        }
+
+        [Test]
+        public virtual void TestBasicDouble()
+        {
+            Directory d = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(Random(), d);
+            Document doc = new Document();
+            DoubleDocValuesField field = new DoubleDocValuesField("field", 0.0);
+            doc.Add(field);
+            for (long l = 0; l < 100; l++)
+            {
+                field.DoubleValue = l;
+                w.AddDocument(doc);
+            }
+
+            IndexReader r = w.Reader;
+
+            FacetsCollector fc = new FacetsCollector();
+
+            IndexSearcher s = NewSearcher(r);
+            s.Search(new MatchAllDocsQuery(), fc);
+            Facets facets = new DoubleRangeFacetCounts("field", fc, new DoubleRange("less than 10", 0.0, true, 10.0, false), new DoubleRange("less than or equal to 10", 0.0, true, 10.0, true), new DoubleRange("over 90", 90.0, false, 100.0, false), new DoubleRange("90 or above", 90.0, true, 100.0, false), new DoubleRange("over 1000", 1000.0, false, double.PositiveInfinity, false));
+
+            Assert.AreEqual("dim=field path=[] value=21 childCount=5\n  less than 10 (10)\n  less than or equal to 10 (11)\n  over 90 (9)\n  90 or above (10)\n  over 1000 (0)\n", facets.GetTopChildren(10, "field").ToString());
+
+            IOUtils.Close(w, r, d);
+        }
+
+        [Test]
+        public virtual void TestBasicFloat()
+        {
+            Directory d = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(Random(), d);
+            Document doc = new Document();
+            FloatDocValuesField field = new FloatDocValuesField("field", 0.0f);
+            doc.Add(field);
+            for (long l = 0; l < 100; l++)
+            {
+                field.FloatValue = l;
+                w.AddDocument(doc);
+            }
+
+            IndexReader r = w.Reader;
+
+            FacetsCollector fc = new FacetsCollector();
+
+            IndexSearcher s = NewSearcher(r);
+            s.Search(new MatchAllDocsQuery(), fc);
+
+            Facets facets = new DoubleRangeFacetCounts("field", new FloatFieldSource("field"), fc, new DoubleRange("less than 10", 0.0f, true, 10.0f, false), new DoubleRange("less than or equal to 10", 0.0f, true, 10.0f, true), new DoubleRange("over 90", 90.0f, false, 100.0f, false), new DoubleRange("90 or above", 90.0f, true, 100.0f, false), new DoubleRange("over 1000", 1000.0f, false, double.PositiveInfinity, false));
+
+            Assert.AreEqual("dim=field path=[] value=21 childCount=5\n  less than 10 (10)\n  less than or equal to 10 (11)\n  over 90 (9)\n  90 or above (10)\n  over 1000 (0)\n", facets.GetTopChildren(10, "field").ToString());
+
+            IOUtils.Close(w, r, d);
+        }
+
+        [Test]
+        public virtual void TestRandomLongs()
+        {
+            Directory dir = NewDirectory();
+            var w = new RandomIndexWriter(Random(), dir);
+
+            int numDocs = AtLeast(1000);
+            if (VERBOSE)
+            {
+                Console.WriteLine("TEST: numDocs=" + numDocs);
+            }
+            long[] values = new long[numDocs];
+            long minValue = long.MaxValue;
+            long maxValue = long.MinValue;
+            for (int i = 0; i < numDocs; i++)
+            {
+                Document doc = new Document();
+                long v = Random().NextLong();
+                values[i] = v;
+                doc.Add(new NumericDocValuesField("field", v));
+                doc.Add(new LongField("field", v, Field.Store.NO));
+                w.AddDocument(doc);
+                minValue = Math.Min(minValue, v);
+                maxValue = Math.Max(maxValue, v);
+            }
+            IndexReader r = w.Reader;
+
+            IndexSearcher s = NewSearcher(r);
+            FacetsConfig config = new FacetsConfig();
+
+            int numIters = AtLeast(10);
+            for (int iter = 0; iter < numIters; iter++)
+            {
+                if (VERBOSE)
+                {
+                    Console.WriteLine("TEST: iter=" + iter);
+                }
+                int numRange = TestUtil.NextInt(Random(), 1, 100);
+                LongRange[] ranges = new LongRange[numRange];
+                int[] expectedCounts = new int[numRange];
+                long minAcceptedValue = long.MaxValue;
+                long maxAcceptedValue = long.MinValue;
+                for (int rangeID = 0; rangeID < numRange; rangeID++)
+                {
+                    long min;
+                    if (rangeID > 0 && Random().Next(10) == 7)
+                    {
+                        // Use an existing boundary:
+                        LongRange prevRange = ranges[Random().Next(rangeID)];
+                        if (Random().NextBoolean())
+                        {
+                            min = prevRange.min;
+                        }
+                        else
+                        {
+                            min = prevRange.max;
+                        }
+                    }
+                    else
+                    {
+                        min = Random().NextLong();
+                    }
+                    long max;
+                    if (rangeID > 0 && Random().Next(10) == 7)
+                    {
+                        // Use an existing boundary:
+                        LongRange prevRange = ranges[Random().Next(rangeID)];
+                        if (Random().NextBoolean())
+                        {
+                            max = prevRange.min;
+                        }
+                        else
+                        {
+                            max = prevRange.max;
+                        }
+                    }
+                    else
+                    {
+                        max = Random().NextLong();
+                    }
+
+                    if (min > max)
+                    {
+                        long x = min;
+                        min = max;
+                        max = x;
+                    }
+                    bool minIncl;
+                    bool maxIncl;
+                    if (min == max)
+                    {
+                        minIncl = true;
+                        maxIncl = true;
+                    }
+                    else
+                    {
+                        minIncl = Random().NextBoolean();
+                        maxIncl = Random().NextBoolean();
+                    }
+                    ranges[rangeID] = new LongRange("r" + rangeID, min, minIncl, max, maxIncl);
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine("  range " + rangeID + ": " + ranges[rangeID]);
+                    }
+
+                    // Do "slow but hopefully correct" computation of
+                    // expected count:
+                    for (int i = 0; i < numDocs; i++)
+                    {
+                        bool accept = true;
+                        if (minIncl)
+                        {
+                            accept &= values[i] >= min;
+                        }
+                        else
+                        {
+                            accept &= values[i] > min;
+                        }
+                        if (maxIncl)
+                        {
+                            accept &= values[i] <= max;
+                        }
+                        else
+                        {
+                            accept &= values[i] < max;
+                        }
+                        if (accept)
+                        {
+                            expectedCounts[rangeID]++;
+                            minAcceptedValue = Math.Min(minAcceptedValue, values[i]);
+                            maxAcceptedValue = Math.Max(maxAcceptedValue, values[i]);
+                        }
+                    }
+                }
+
+                FacetsCollector sfc = new FacetsCollector();
+                s.Search(new MatchAllDocsQuery(), sfc);
+                Filter fastMatchFilter;
+                if (Random().NextBoolean())
+                {
+                    if (Random().NextBoolean())
+                    {
+                        fastMatchFilter = NumericRangeFilter.NewLongRange("field", minValue, maxValue, true, true);
+                    }
+                    else
+                    {
+                        fastMatchFilter = NumericRangeFilter.NewLongRange("field", minAcceptedValue, maxAcceptedValue, true, true);
+                    }
+                }
+                else
+                {
+                    fastMatchFilter = null;
+                }
+                ValueSource vs = new LongFieldSource("field");
+                Facets facets = new LongRangeFacetCounts("field", vs, sfc, fastMatchFilter, ranges);
+                FacetResult result = facets.GetTopChildren(10, "field");
+                Assert.AreEqual(numRange, result.LabelValues.Length);
+                for (int rangeID = 0; rangeID < numRange; rangeID++)
+                {
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine("  range " + rangeID + " expectedCount=" + expectedCounts[rangeID]);
+                    }
+                    LabelAndValue subNode = result.LabelValues[rangeID];
+                    Assert.AreEqual("r" + rangeID, subNode.label);
+                    Assert.AreEqual(expectedCounts[rangeID], (int)subNode.value);
+
+                    LongRange range = ranges[rangeID];
+
+                    // Test drill-down:
+                    DrillDownQuery ddq = new DrillDownQuery(config);
+                    if (Random().NextBoolean())
+                    {
+                        if (Random().NextBoolean())
+                        {
+                            ddq.Add("field", NumericRangeFilter.NewLongRange("field", range.min, range.max, range.minInclusive, range.maxInclusive));
+                        }
+                        else
+                        {
+                            ddq.Add("field", NumericRangeQuery.NewLongRange("field", range.min, range.max, range.minInclusive, range.maxInclusive));
+                        }
+                    }
+                    else
+                    {
+                        ddq.Add("field", range.GetFilter(fastMatchFilter, vs));
+                    }
+                    Assert.AreEqual(expectedCounts[rangeID], s.Search(ddq, 10).TotalHits);
+                }
+            }
+
+            IOUtils.Close(w, r, dir);
+        }
+
+        [Test]
+        public virtual void TestRandomFloats()
+        {
+            Directory dir = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(Random(), dir);
+
+            int numDocs = AtLeast(1000);
+            float[] values = new float[numDocs];
+            float minValue = float.PositiveInfinity;
+            float maxValue = float.NegativeInfinity;
+            for (int i = 0; i < numDocs; i++)
+            {
+                Document doc = new Document();
+                float v = Random().NextFloat();
+                values[i] = v;
+                doc.Add(new FloatDocValuesField("field", v));
+                doc.Add(new FloatField("field", v, Field.Store.NO));
+                w.AddDocument(doc);
+                minValue = Math.Min(minValue, v);
+                maxValue = Math.Max(maxValue, v);
+            }
+            IndexReader r = w.Reader;
+
+            IndexSearcher s = NewSearcher(r);
+            FacetsConfig config = new FacetsConfig();
+
+            int numIters = AtLeast(10);
+            for (int iter = 0; iter < numIters; iter++)
+            {
+                if (VERBOSE)
+                {
+                    Console.WriteLine("TEST: iter=" + iter);
+                }
+                int numRange = TestUtil.NextInt(Random(), 1, 5);
+                DoubleRange[] ranges = new DoubleRange[numRange];
+                int[] expectedCounts = new int[numRange];
+                float minAcceptedValue = float.PositiveInfinity;
+                float maxAcceptedValue = float.NegativeInfinity;
+                if (VERBOSE)
+                {
+                    Console.WriteLine("TEST: " + numRange + " ranges");
+                }
+                for (int rangeID = 0; rangeID < numRange; rangeID++)
+                {
+                    double min;
+                    if (rangeID > 0 && Random().Next(10) == 7)
+                    {
+                        // Use an existing boundary:
+                        DoubleRange prevRange = ranges[Random().Next(rangeID)];
+                        if (Random().NextBoolean())
+                        {
+                            min = prevRange.Min;
+                        }
+                        else
+                        {
+                            min = prevRange.Max;
+                        }
+                    }
+                    else
+                    {
+                        min = Random().NextDouble();
+                    }
+                    double max;
+                    if (rangeID > 0 && Random().Next(10) == 7)
+                    {
+                        // Use an existing boundary:
+                        DoubleRange prevRange = ranges[Random().Next(rangeID)];
+                        if (Random().NextBoolean())
+                        {
+                            max = prevRange.Min;
+                        }
+                        else
+                        {
+                            max = prevRange.Max;
+                        }
+                    }
+                    else
+                    {
+                        max = Random().NextDouble();
+                    }
+
+                    if (min > max)
+                    {
+                        double x = min;
+                        min = max;
+                        max = x;
+                    }
+
+                    // Must truncate to float precision so that the
+                    // drill-down counts (which use NRQ.newFloatRange)
+                    // are correct:
+                    min = (float)min;
+                    max = (float)max;
+
+                    bool minIncl;
+                    bool maxIncl;
+                    if (min == max)
+                    {
+                        minIncl = true;
+                        maxIncl = true;
+                    }
+                    else
+                    {
+                        minIncl = Random().NextBoolean();
+                        maxIncl = Random().NextBoolean();
+                    }
+                    ranges[rangeID] = new DoubleRange("r" + rangeID, min, minIncl, max, maxIncl);
+
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine("TEST:   range " + rangeID + ": " + ranges[rangeID]);
+                    }
+
+                    // Do "slow but hopefully correct" computation of
+                    // expected count:
+                    for (int i = 0; i < numDocs; i++)
+                    {
+                        bool accept = true;
+                        if (minIncl)
+                        {
+                            accept &= values[i] >= min;
+                        }
+                        else
+                        {
+                            accept &= values[i] > min;
+                        }
+                        if (maxIncl)
+                        {
+                            accept &= values[i] <= max;
+                        }
+                        else
+                        {
+                            accept &= values[i] < max;
+                        }
+                        if (VERBOSE)
+                        {
+                            Console.WriteLine("TEST:   check doc=" + i + " val=" + values[i] + " accept=" + accept);
+                        }
+                        if (accept)
+                        {
+                            expectedCounts[rangeID]++;
+                            minAcceptedValue = Math.Min(minAcceptedValue, values[i]);
+                            maxAcceptedValue = Math.Max(maxAcceptedValue, values[i]);
+                        }
+                    }
+                }
+
+                FacetsCollector sfc = new FacetsCollector();
+                s.Search(new MatchAllDocsQuery(), sfc);
+                Filter fastMatchFilter;
+                if (Random().NextBoolean())
+                {
+                    if (Random().NextBoolean())
+                    {
+                        fastMatchFilter = NumericRangeFilter.NewFloatRange("field", minValue, maxValue, true, true);
+                    }
+                    else
+                    {
+                        fastMatchFilter = NumericRangeFilter.NewFloatRange("field", minAcceptedValue, maxAcceptedValue, true, true);
+                    }
+                }
+                else
+                {
+                    fastMatchFilter = null;
+                }
+                ValueSource vs = new FloatFieldSource("field");
+                Facets facets = new DoubleRangeFacetCounts("field", vs, sfc, fastMatchFilter, ranges);
+                FacetResult result = facets.GetTopChildren(10, "field");
+                Assert.AreEqual(numRange, result.LabelValues.Length);
+                for (int rangeID = 0; rangeID < numRange; rangeID++)
+                {
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine("TEST: verify range " + rangeID + " expectedCount=" + expectedCounts[rangeID]);
+                    }
+                    LabelAndValue subNode = result.LabelValues[rangeID];
+                    Assert.AreEqual("r" + rangeID, subNode.label);
+                    Assert.AreEqual(expectedCounts[rangeID], (int)subNode.value);
+
+                    DoubleRange range = ranges[rangeID];
+
+                    // Test drill-down:
+                    DrillDownQuery ddq = new DrillDownQuery(config);
+                    if (Random().NextBoolean())
+                    {
+                        if (Random().NextBoolean())
+                        {
+                            ddq.Add("field", NumericRangeFilter.NewFloatRange("field", (float)range.Min, (float)range.Max, range.MinInclusive, range.MaxInclusive));
+                        }
+                        else
+                        {
+                            ddq.Add("field", NumericRangeQuery.NewFloatRange("field", (float)range.Min, (float)range.Max, range.MinInclusive, range.MaxInclusive));
+                        }
+                    }
+                    else
+                    {
+                        ddq.Add("field", range.GetFilter(fastMatchFilter, vs));
+                    }
+                    Assert.AreEqual(expectedCounts[rangeID], s.Search(ddq, 10).TotalHits);
+                }
+            }
+
+            IOUtils.Close(w, r, dir);
+        }
+
+        [Test]
+        public virtual void TestRandomDoubles()
+        {
+            Directory dir = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(Random(), dir);
+
+            int numDocs = AtLeast(1000);
+            double[] values = new double[numDocs];
+            double minValue = double.PositiveInfinity;
+            double maxValue = double.NegativeInfinity;
+            for (int i = 0; i < numDocs; i++)
+            {
+                Document doc = new Document();
+                double v = Random().NextDouble();
+                values[i] = v;
+                doc.Add(new DoubleDocValuesField("field", v));
+                doc.Add(new DoubleField("field", v, Field.Store.NO));
+                w.AddDocument(doc);
+                minValue = Math.Min(minValue, v);
+                maxValue = Math.Max(maxValue, v);
+            }
+            IndexReader r = w.Reader;
+
+            IndexSearcher s = NewSearcher(r);
+            FacetsConfig config = new FacetsConfig();
+
+            int numIters = AtLeast(10);
+            for (int iter = 0; iter < numIters; iter++)
+            {
+                if (VERBOSE)
+                {
+                    Console.WriteLine("TEST: iter=" + iter);
+                }
+                int numRange = TestUtil.NextInt(Random(), 1, 5);
+                DoubleRange[] ranges = new DoubleRange[numRange];
+                int[] expectedCounts = new int[numRange];
+                double minAcceptedValue = double.PositiveInfinity;
+                double maxAcceptedValue = double.NegativeInfinity;
+                for (int rangeID = 0; rangeID < numRange; rangeID++)
+                {
+                    double min;
+                    if (rangeID > 0 && Random().Next(10) == 7)
+                    {
+                        // Use an existing boundary:
+                        DoubleRange prevRange = ranges[Random().Next(rangeID)];
+                        if (Random().NextBoolean())
+                        {
+                            min = prevRange.Min;
+                        }
+                        else
+                        {
+                            min = prevRange.Max;
+                        }
+                    }
+                    else
+                    {
+                        min = Random().NextDouble();
+                    }
+                    double max;
+                    if (rangeID > 0 && Random().Next(10) == 7)
+                    {
+                        // Use an existing boundary:
+                        DoubleRange prevRange = ranges[Random().Next(rangeID)];
+                        if (Random().NextBoolean())
+                        {
+                            max = prevRange.Min;
+                        }
+                        else
+                        {
+                            max = prevRange.Max;
+                        }
+                    }
+                    else
+                    {
+                        max = Random().NextDouble();
+                    }
+
+                    if (min > max)
+                    {
+                        double x = min;
+                        min = max;
+                        max = x;
+                    }
+
+                    bool minIncl;
+                    bool maxIncl;
+                    if (min == max)
+                    {
+                        minIncl = true;
+                        maxIncl = true;
+                    }
+                    else
+                    {
+                        minIncl = Random().NextBoolean();
+                        maxIncl = Random().NextBoolean();
+                    }
+                    ranges[rangeID] = new DoubleRange("r" + rangeID, min, minIncl, max, maxIncl);
+
+                    // Do "slow but hopefully correct" computation of
+                    // expected count:
+                    for (int i = 0; i < numDocs; i++)
+                    {
+                        bool accept = true;
+                        if (minIncl)
+                        {
+                            accept &= values[i] >= min;
+                        }
+                        else
+                        {
+                            accept &= values[i] > min;
+                        }
+                        if (maxIncl)
+                        {
+                            accept &= values[i] <= max;
+                        }
+                        else
+                        {
+                            accept &= values[i] < max;
+                        }
+                        if (accept)
+                        {
+                            expectedCounts[rangeID]++;
+                            minAcceptedValue = Math.Min(minAcceptedValue, values[i]);
+                            maxAcceptedValue = Math.Max(maxAcceptedValue, values[i]);
+                        }
+                    }
+                }
+
+                FacetsCollector sfc = new FacetsCollector();
+                s.Search(new MatchAllDocsQuery(), sfc);
+                Filter fastMatchFilter;
+                if (Random().NextBoolean())
+                {
+                    if (Random().NextBoolean())
+                    {
+                        fastMatchFilter = NumericRangeFilter.NewDoubleRange("field", minValue, maxValue, true, true);
+                    }
+                    else
+                    {
+                        fastMatchFilter = NumericRangeFilter.NewDoubleRange("field", minAcceptedValue, maxAcceptedValue, true, true);
+                    }
+                }
+                else
+                {
+                    fastMatchFilter = null;
+                }
+                ValueSource vs = new DoubleFieldSource("field");
+                Facets facets = new DoubleRangeFacetCounts("field", vs, sfc, fastMatchFilter, ranges);
+                FacetResult result = facets.GetTopChildren(10, "field");
+                Assert.AreEqual(numRange, result.LabelValues.Length);
+                for (int rangeID = 0; rangeID < numRange; rangeID++)
+                {
+                    if (VERBOSE)
+                    {
+                        Console.WriteLine("  range " + rangeID + " expectedCount=" + expectedCounts[rangeID]);
+                    }
+                    LabelAndValue subNode = result.LabelValues[rangeID];
+                    Assert.AreEqual("r" + rangeID, subNode.label);
+                    Assert.AreEqual(expectedCounts[rangeID], (int)subNode.value);
+
+                    DoubleRange range = ranges[rangeID];
+
+                    // Test drill-down:
+                    DrillDownQuery ddq = new DrillDownQuery(config);
+                    if (Random().NextBoolean())
+                    {
+                        if (Random().NextBoolean())
+                        {
+                            ddq.Add("field", NumericRangeFilter.NewDoubleRange("field", range.Min, range.Max, range.MinInclusive, range.MaxInclusive));
+                        }
+                        else
+                        {
+                            ddq.Add("field", NumericRangeQuery.NewDoubleRange("field", range.Min, range.Max, range.MinInclusive, range.MaxInclusive));
+                        }
+                    }
+                    else
+                    {
+                        ddq.Add("field", range.GetFilter(fastMatchFilter, vs));
+                    }
+
+                    Assert.AreEqual(expectedCounts[rangeID], s.Search(ddq, 10).TotalHits);
+                }
+            }
+
+            IOUtils.Close(w, r, dir);
+        }
+
+        // LUCENE-5178
+        [Test]
+        public virtual void TestMissingValues()
+        {
+            AssumeTrue("codec does not support docsWithField", DefaultCodecSupportsDocsWithField());
+            Directory d = NewDirectory();
+            RandomIndexWriter w = new RandomIndexWriter(Random(), d);
+            Document doc = new Document();
+            NumericDocValuesField field = new NumericDocValuesField("field", 0L);
+            doc.Add(field);
+            for (long l = 0; l < 100; l++)
+            {
+                if (l % 5 == 0)
+                {
+                    // Every 5th doc is missing the value:
+                    w.AddDocument(new Document());
+                    continue;
+                }
+                field.LongValue = l;
+                w.AddDocument(doc);
+            }
+
+            IndexReader r = w.Reader;
+
+            FacetsCollector fc = new FacetsCollector();
+
+            IndexSearcher s = NewSearcher(r);
+            s.Search(new MatchAllDocsQuery(), fc);
+            Facets facets = new LongRangeFacetCounts("field", fc, new LongRange("less than 10", 0L, true, 10L, false), new LongRange("less than or equal to 10", 0L, true, 10L, true), new LongRange("over 90", 90L, false, 100L, false), new LongRange("90 or above", 90L, true, 100L, false), new LongRange("over 1000", 1000L, false, long.MaxValue, false));
+
+            Assert.AreEqual("dim=field path=[] value=16 childCount=5\n  less than 10 (8)\n  less than or equal to 10 (8)\n  over 90 (8)\n  90 or above (8)\n  over 1000 (0)\n", facets.GetTopChildren(10, "field").ToString());
+
+            IOUtils.Close(w, r, d);
+        }
+
+        [Test]
+        public virtual void TestCustomDoublesValueSource()
+        {
+            Directory dir = NewDirectory();
+            RandomIndexWriter writer = new RandomIndexWriter(Random(), dir);
+
+            Document doc = new Document();
+            writer.AddDocument(doc);
+            writer.AddDocument(doc);
+            writer.AddDocument(doc);
+
+            // Test wants 3 docs in one segment:
+            writer.ForceMerge(1);
+
+            var vs = new ValueSourceAnonymousInnerClassHelper(this, doc);
+
+            FacetsConfig config = new FacetsConfig();
+
+            FacetsCollector fc = new FacetsCollector();
+
+            IndexReader r = writer.Reader;
+            IndexSearcher s = NewSearcher(r);
+            s.Search(new MatchAllDocsQuery(), fc);
+
+            DoubleRange[] ranges = new DoubleRange[] { new DoubleRange("< 1", 0.0, true, 1.0, false), new DoubleRange("< 2", 0.0, true, 2.0, false), new DoubleRange("< 5", 0.0, true, 5.0, false), new DoubleRange("< 10", 0.0, true, 10.0, false), new DoubleRange("< 20", 0.0, true, 20.0, false), new DoubleRange("< 50", 0.0, true, 50.0, false) };
+
+            Filter fastMatchFilter;
+            AtomicBoolean filterWasUsed = new AtomicBoolean();
+            if (Random().NextBoolean())
+            {
+                // Sort of silly:
+                fastMatchFilter = new CachingWrapperFilterAnonymousInnerClassHelper(this, new QueryWrapperFilter(new MatchAllDocsQuery()), filterWasUsed);
+            }
+            else
+            {
+                fastMatchFilter = null;
+            }
+
+            if (VERBOSE)
+            {
+                Console.WriteLine("TEST: fastMatchFilter=" + fastMatchFilter);
+            }
+
+            Facets facets = new DoubleRangeFacetCounts("field", vs, fc, fastMatchFilter, ranges);
+
+            Assert.AreEqual("dim=field path=[] value=3 childCount=6\n  < 1 (0)\n  < 2 (1)\n  < 5 (3)\n  < 10 (3)\n  < 20 (3)\n  < 50 (3)\n", facets.GetTopChildren(10, "field").ToString());
+            Assert.True(fastMatchFilter == null || filterWasUsed.Get());
+
+            DrillDownQuery ddq = new DrillDownQuery(config);
+            ddq.Add("field", ranges[1].GetFilter(fastMatchFilter, vs));
+
+            // Test simple drill-down:
+            Assert.AreEqual(1, s.Search(ddq, 10).TotalHits);
+
+            // Test drill-sideways after drill-down
+            DrillSideways ds = new DrillSidewaysAnonymousInnerClassHelper2(this, s, config, (TaxonomyReader)null, vs, ranges, fastMatchFilter);
+
+
+            DrillSidewaysResult dsr = ds.Search(ddq, 10);
+            Assert.AreEqual(1, dsr.Hits.TotalHits);
+            Assert.AreEqual("dim=field path=[] value=3 childCount=6\n  < 1 (0)\n  < 2 (1)\n  < 5 (3)\n  < 10 (3)\n  < 20 (3)\n  < 50 (3)\n", dsr.Facets.GetTopChildren(10, "field").ToString());
+
+            IOUtils.Close(r, writer, dir);
+        }
+
+        private class ValueSourceAnonymousInnerClassHelper : ValueSource
+        {
+            private readonly TestRangeFacetCounts outerInstance;
+
+            private Document doc;
+
+            public ValueSourceAnonymousInnerClassHelper(TestRangeFacetCounts outerInstance, Document doc)
+            {
+                this.outerInstance = outerInstance;
+                this.doc = doc;
+            }
+
+            public override FunctionValues GetValues(IDictionary ignored, AtomicReaderContext ignored2)
+            {
+                return new DoubleDocValuesAnonymousInnerClassHelper(this);
+            }
+
+            private class DoubleDocValuesAnonymousInnerClassHelper : DoubleDocValues
+            {
+                private readonly ValueSourceAnonymousInnerClassHelper outerInstance;
+
+                public DoubleDocValuesAnonymousInnerClassHelper(ValueSourceAnonymousInnerClassHelper outerInstance)
+                    : base(null)
+                {
+                    this.outerInstance = outerInstance;
+                }
+
+                public override double DoubleVal(int doc)
+                {
+                    return doc + 1;
+                }
+            }
+
+            public override bool Equals(object o)
+            {
+                throw new System.NotSupportedException();
+            }
+
+            public override int GetHashCode()
+            {
+                throw new System.NotSupportedException();
+            }
+
+            public override string Description
+            {
+                get { throw new NotSupportedException(); }
+            }
+
+        }
+
+        private class CachingWrapperFilterAnonymousInnerClassHelper : CachingWrapperFilter
+        {
+            private readonly TestRangeFacetCounts outerInstance;
+
+            private AtomicBoolean filterWasUsed;
+
+            public CachingWrapperFilterAnonymousInnerClassHelper(TestRangeFacetCounts outerInstance, QueryWrapperFilter org, AtomicBoolean filterWasUsed)
+                : base(org)
+            {
+                this.outerInstance = outerInstance;
+                this.filterWasUsed = filterWasUsed;
+            }
+
+            protected override DocIdSet CacheImpl(DocIdSetIterator iterator, AtomicReader reader)
+            {
+                var cached = new FixedBitSet(reader.MaxDoc);
+                filterWasUsed.Set(true);
+                cached.Or(iterator);
+                return cached;
+            }
+        }
+
+        private class DrillSidewaysAnonymousInnerClassHelper2 : DrillSideways
+        {
+            private readonly TestRangeFacetCounts outerInstance;
+
+            private ValueSource vs;
+            private Lucene.Net.Facet.Range.DoubleRange[] ranges;
+            private Filter fastMatchFilter;
+
+
+            public DrillSidewaysAnonymousInnerClassHelper2(TestRangeFacetCounts testRangeFacetCounts, IndexSearcher indexSearcher, FacetsConfig facetsConfig, TaxonomyReader org, ValueSource valueSource, DoubleRange[] doubleRanges, Filter filter)
+                : base(indexSearcher, facetsConfig, org)
+            {
+                this.outerInstance = outerInstance;
+                this.vs = valueSource;
+                this.ranges = doubleRanges;
+                this.fastMatchFilter = filter;
+            }
+
+
+            protected override Facets BuildFacetsResult(FacetsCollector drillDowns, FacetsCollector[] drillSideways, string[] drillSidewaysDims)
+            {
+                Debug.Assert(drillSideways.Length == 1);
+                return new DoubleRangeFacetCounts("field", vs, drillSideways[0], fastMatchFilter, ranges);
+            }
+
+            protected override bool ScoreSubDocsAtOnce()
+            {
+                return Random().NextBoolean();
+            }
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/68aa9728/src/Lucene.Net.Tests.Facet/SlowRAMDirectory.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.Facet/SlowRAMDirectory.cs b/src/Lucene.Net.Tests.Facet/SlowRAMDirectory.cs
new file mode 100644
index 0000000..72de557
--- /dev/null
+++ b/src/Lucene.Net.Tests.Facet/SlowRAMDirectory.cs
@@ -0,0 +1,261 @@
+using System;
+using System.Threading;
+using Lucene.Net.Randomized.Generators;
+
+namespace Lucene.Net.Facet
+{
+
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+
+    using IOContext = Lucene.Net.Store.IOContext;
+    using IndexInput = Lucene.Net.Store.IndexInput;
+    using IndexOutput = Lucene.Net.Store.IndexOutput;
+    using RAMDirectory = Lucene.Net.Store.RAMDirectory;
+    using ThreadInterruptedException = Lucene.Net.Util.ThreadInterruptedException;
+
+    /// <summary>
+    /// Test utility - slow directory
+    /// </summary>
+    // TODO: move to test-framework and sometimes use in tests?
+    public class SlowRAMDirectory : RAMDirectory
+    {
+
+        private const int IO_SLEEP_THRESHOLD = 50;
+
+        internal Random random;
+        private int sleepMillis;
+
+        public virtual int SleepMillis
+        {
+            set
+            {
+                this.sleepMillis = value;
+            }
+        }
+
+        public SlowRAMDirectory(int sleepMillis, Random random)
+        {
+            this.sleepMillis = sleepMillis;
+            this.random = random;
+        }
+
+        public override IndexOutput CreateOutput(string name, IOContext context)
+        {
+            if (sleepMillis != -1)
+            {
+                return new SlowIndexOutput(this, base.CreateOutput(name, context));
+            }
+
+            return base.CreateOutput(name, context);
+        }
+
+        public override IndexInput OpenInput(string name, IOContext context)
+        {
+            if (sleepMillis != -1)
+            {
+                return new SlowIndexInput(this, base.OpenInput(name, context));
+            }
+            return base.OpenInput(name, context);
+        }
+
+        internal virtual void doSleep(Random random, int length)
+        {
+            int sTime = length < 10 ? sleepMillis : (int)(sleepMillis * Math.Log(length));
+            if (random != null)
+            {
+                sTime = random.Next(sTime);
+            }
+            try
+            {
+                Thread.Sleep(sTime);
+            }
+            catch (ThreadInterruptedException e)
+            {
+                throw new ThreadInterruptedException(e);
+            }
+        }
+
+        /// <summary>
+        /// Make a private random. </summary>
+        internal virtual Random forkRandom()
+        {
+            if (random == null)
+            {
+                return null;
+            }
+            return new Random((int)random.NextLong());
+        }
+
+        /// <summary>
+        /// Delegate class to wrap an IndexInput and delay reading bytes by some
+        /// specified time.
+        /// </summary>
+        private class SlowIndexInput : IndexInput
+        {
+            private readonly SlowRAMDirectory outerInstance;
+
+            internal IndexInput ii;
+            internal int numRead = 0;
+            internal Random rand;
+
+            public SlowIndexInput(SlowRAMDirectory outerInstance, IndexInput ii)
+                : base("SlowIndexInput(" + ii + ")")
+            {
+                this.outerInstance = outerInstance;
+                this.rand = outerInstance.forkRandom();
+                this.ii = ii;
+            }
+
+            public override byte ReadByte()
+            {
+                if (numRead >= IO_SLEEP_THRESHOLD)
+                {
+                    outerInstance.doSleep(rand, 0);
+                    numRead = 0;
+                }
+                ++numRead;
+                return ii.ReadByte();
+            }
+
+            public override void ReadBytes(byte[] b, int offset, int len)
+            {
+                if (numRead >= IO_SLEEP_THRESHOLD)
+                {
+                    outerInstance.doSleep(rand, len);
+                    numRead = 0;
+                }
+                numRead += len;
+                ii.ReadBytes(b, offset, len);
+            }
+
+
+            // TODO: is it intentional that clone doesnt wrap?
+            public override object Clone()
+            {
+                return ii.Clone();
+            }
+
+
+            public override void Dispose()
+            {
+                ii.Dispose();
+            }
+            public override bool Equals(object o)
+            {
+                return ii.Equals(o);
+            }
+            public override long FilePointer
+            {
+                get
+                {
+                    return ii.FilePointer;
+                }
+            }
+
+            public override void Seek(long pos)
+            {
+                ii.Seek(pos);
+            }
+
+
+            public override int GetHashCode()
+            {
+                return ii.GetHashCode();
+            }
+            public override long Length()
+            {
+                return ii.Length();
+            }
+
+        }
+
+        /// <summary>
+        /// Delegate class to wrap an IndexOutput and delay writing bytes by some
+        /// specified time.
+        /// </summary>
+        private class SlowIndexOutput : IndexOutput
+        {
+            private readonly SlowRAMDirectory outerInstance;
+
+
+            internal IndexOutput io;
+            internal int numWrote;
+            internal readonly Random rand;
+
+            public SlowIndexOutput(SlowRAMDirectory outerInstance, IndexOutput io)
+            {
+                this.outerInstance = outerInstance;
+                this.io = io;
+                this.rand = outerInstance.forkRandom();
+            }
+
+            public override void WriteByte(byte b)
+            {
+                if (numWrote >= IO_SLEEP_THRESHOLD)
+                {
+                    outerInstance.doSleep(rand, 0);
+                    numWrote = 0;
+                }
+                ++numWrote;
+                io.WriteByte(b);
+            }
+
+            public override void WriteBytes(byte[] b, int offset, int length)
+            {
+                if (numWrote >= IO_SLEEP_THRESHOLD)
+                {
+                    outerInstance.doSleep(rand, length);
+                    numWrote = 0;
+                }
+                numWrote += length;
+                io.WriteBytes(b, offset, length);
+            }
+
+            public override void Dispose()
+            {
+                io.Dispose();
+            }
+            public override void Flush()
+            {
+                io.Flush();
+            }
+            public override long FilePointer
+            {
+                get
+                {
+                    return io.FilePointer;
+                }
+            }
+            public override void Seek(long pos)
+            {
+                io.Seek(pos);
+            }
+
+            public override long Checksum
+            {
+                get
+                {
+                    return io.Checksum;
+                }
+            }
+        }
+
+    }
+
+}
\ No newline at end of file